| author | |
| committer | |
| log | 8297f28546b44afe49bec074733f05e03a3c0e62 |
| tree | bc0740d17e70cd749bcc94db43f45fefcb642468 |
| parent | 275652f620541919087bc92da0d2f9e97c66d3c0 |
22 files changed, 1570 insertions(+), 1280 deletions(-)
src/InternPool.zig+225-71| ... | @@ -1,5 +1,10 @@ | ... | @@ -1,5 +1,10 @@ |
| 1 | //! All interned objects have both a value and a type. | 1 | //! All interned objects have both a value and a type. |
| 2 | //! This data structure is self-contained, with the following exceptions: | ||
| 3 | //! * type_struct via Module.Struct.Index | ||
| 4 | //! * type_opaque via Module.Namespace.Index and Module.Decl.Index | ||
| 2 | 5 | ||
| 6 | /// Maps `Key` to `Index`. `Key` objects are not stored anywhere; they are | ||
| 7 | /// constructed lazily. | ||
| 3 | map: std.AutoArrayHashMapUnmanaged(void, void) = .{}, | 8 | map: std.AutoArrayHashMapUnmanaged(void, void) = .{}, |
| 4 | items: std.MultiArrayList(Item) = .{}, | 9 | items: std.MultiArrayList(Item) = .{}, |
| 5 | extra: std.ArrayListUnmanaged(u32) = .{}, | 10 | extra: std.ArrayListUnmanaged(u32) = .{}, |
| ... | @@ -9,6 +14,13 @@ extra: std.ArrayListUnmanaged(u32) = .{}, | ... | @@ -9,6 +14,13 @@ extra: std.ArrayListUnmanaged(u32) = .{}, |
| 9 | /// violate the above mechanism. | 14 | /// violate the above mechanism. |
| 10 | limbs: std.ArrayListUnmanaged(u64) = .{}, | 15 | limbs: std.ArrayListUnmanaged(u64) = .{}, |
| 11 | 16 | ||
| 17 | /// Struct objects are stored in this data structure because: | ||
| 18 | /// * They contain pointers such as the field maps. | ||
| 19 | /// * They need to be mutated after creation. | ||
| 20 | allocated_structs: std.SegmentedList(Module.Struct, 0) = .{}, | ||
| 21 | /// When a Struct object is freed from `allocated_structs`, it is pushed into this stack. | ||
| 22 | structs_free_list: std.ArrayListUnmanaged(Module.Struct.Index) = .{}, | ||
| 23 | |||
| 12 | const std = @import("std"); | 24 | const std = @import("std"); |
| 13 | const Allocator = std.mem.Allocator; | 25 | const Allocator = std.mem.Allocator; |
| 14 | const assert = std.debug.assert; | 26 | const assert = std.debug.assert; |
| ... | @@ -17,8 +29,7 @@ const BigIntMutable = std.math.big.int.Mutable; | ... | @@ -17,8 +29,7 @@ const BigIntMutable = std.math.big.int.Mutable; |
| 17 | const Limb = std.math.big.Limb; | 29 | const Limb = std.math.big.Limb; |
| 18 | 30 | ||
| 19 | const InternPool = @This(); | 31 | const InternPool = @This(); |
| 20 | const DeclIndex = @import("Module.zig").Decl.Index; | 32 | const Module = @import("Module.zig"); |
| 21 | const NamespaceIndex = @import("Module.zig").Namespace.Index; | ||
| 22 | 33 | ||
| 23 | const KeyAdapter = struct { | 34 | const KeyAdapter = struct { |
| 24 | intern_pool: *const InternPool, | 35 | intern_pool: *const InternPool, |
| ... | @@ -45,11 +56,20 @@ pub const Key = union(enum) { | ... | @@ -45,11 +56,20 @@ pub const Key = union(enum) { |
| 45 | payload_type: Index, | 56 | payload_type: Index, |
| 46 | }, | 57 | }, |
| 47 | simple_type: SimpleType, | 58 | simple_type: SimpleType, |
| 59 | /// If `empty_struct_type` is handled separately, then this value may be | ||
| 60 | /// safely assumed to never be `none`. | ||
| 61 | struct_type: StructType, | ||
| 62 | union_type: struct { | ||
| 63 | fields_len: u32, | ||
| 64 | // TODO move Module.Union data to InternPool | ||
| 65 | }, | ||
| 66 | opaque_type: OpaqueType, | ||
| 67 | |||
| 48 | simple_value: SimpleValue, | 68 | simple_value: SimpleValue, |
| 49 | extern_func: struct { | 69 | extern_func: struct { |
| 50 | ty: Index, | 70 | ty: Index, |
| 51 | /// The Decl that corresponds to the function itself. | 71 | /// The Decl that corresponds to the function itself. |
| 52 | decl: DeclIndex, | 72 | decl: Module.Decl.Index, |
| 53 | /// Library name if specified. | 73 | /// Library name if specified. |
| 54 | /// For example `extern "c" fn write(...) usize` would have 'c' as library name. | 74 | /// For example `extern "c" fn write(...) usize` would have 'c' as library name. |
| 55 | /// Index into the string table bytes. | 75 | /// Index into the string table bytes. |
| ... | @@ -62,13 +82,11 @@ pub const Key = union(enum) { | ... | @@ -62,13 +82,11 @@ pub const Key = union(enum) { |
| 62 | ty: Index, | 82 | ty: Index, |
| 63 | tag: BigIntConst, | 83 | tag: BigIntConst, |
| 64 | }, | 84 | }, |
| 65 | struct_type: StructType, | 85 | /// An instance of a struct, array, or vector. |
| 66 | opaque_type: OpaqueType, | 86 | /// Each element/field stored as an `Index`. |
| 67 | 87 | /// In the case of sentinel-terminated arrays, the sentinel value *is* stored, | |
| 68 | union_type: struct { | 88 | /// so the slice length will be one more than the type's array length. |
| 69 | fields_len: u32, | 89 | aggregate: Aggregate, |
| 70 | // TODO move Module.Union data to InternPool | ||
| 71 | }, | ||
| 72 | 90 | ||
| 73 | pub const IntType = std.builtin.Type.Int; | 91 | pub const IntType = std.builtin.Type.Int; |
| 74 | 92 | ||
| ... | @@ -113,16 +131,27 @@ pub const Key = union(enum) { | ... | @@ -113,16 +131,27 @@ pub const Key = union(enum) { |
| 113 | child: Index, | 131 | child: Index, |
| 114 | }; | 132 | }; |
| 115 | 133 | ||
| 116 | pub const StructType = struct { | ||
| 117 | fields_len: u32, | ||
| 118 | // TODO move Module.Struct data to InternPool | ||
| 119 | }; | ||
| 120 | |||
| 121 | pub const OpaqueType = struct { | 134 | pub const OpaqueType = struct { |
| 122 | /// The Decl that corresponds to the opaque itself. | 135 | /// The Decl that corresponds to the opaque itself. |
| 123 | decl: DeclIndex, | 136 | decl: Module.Decl.Index, |
| 124 | /// Represents the declarations inside this opaque. | 137 | /// Represents the declarations inside this opaque. |
| 125 | namespace: NamespaceIndex, | 138 | namespace: Module.Namespace.Index, |
| 139 | }; | ||
| 140 | |||
| 141 | /// There are three possibilities here: | ||
| 142 | /// * `@TypeOf(.{})` (untyped empty struct literal) | ||
| 143 | /// - namespace == .none, index == .none | ||
| 144 | /// * A struct which has a namepace, but no fields. | ||
| 145 | /// - index == .none | ||
| 146 | /// * A struct which has fields as well as a namepace. | ||
| 147 | pub const StructType = struct { | ||
| 148 | /// This will be `none` only in the case of `@TypeOf(.{})` | ||
| 149 | /// (`Index.empty_struct_type`). | ||
| 150 | namespace: Module.Namespace.OptionalIndex, | ||
| 151 | /// The `none` tag is used to represent two cases: | ||
| 152 | /// * `@TypeOf(.{})`, in which case `namespace` will also be `none`. | ||
| 153 | /// * A struct with no fields, in which case `namespace` will be populated. | ||
| 154 | index: Module.Struct.OptionalIndex, | ||
| 126 | }; | 155 | }; |
| 127 | 156 | ||
| 128 | pub const Int = struct { | 157 | pub const Int = struct { |
| ... | @@ -156,18 +185,24 @@ pub const Key = union(enum) { | ... | @@ -156,18 +185,24 @@ pub const Key = union(enum) { |
| 156 | addr: Addr, | 185 | addr: Addr, |
| 157 | 186 | ||
| 158 | pub const Addr = union(enum) { | 187 | pub const Addr = union(enum) { |
| 159 | decl: DeclIndex, | 188 | decl: Module.Decl.Index, |
| 160 | int: Index, | 189 | int: Index, |
| 161 | }; | 190 | }; |
| 162 | }; | 191 | }; |
| 163 | 192 | ||
| 164 | /// `null` is represented by the `val` field being `none`. | 193 | /// `null` is represented by the `val` field being `none`. |
| 165 | pub const Opt = struct { | 194 | pub const Opt = struct { |
| 195 | /// This is the optional type; not the payload type. | ||
| 166 | ty: Index, | 196 | ty: Index, |
| 167 | /// This could be `none`, indicating the optional is `null`. | 197 | /// This could be `none`, indicating the optional is `null`. |
| 168 | val: Index, | 198 | val: Index, |
| 169 | }; | 199 | }; |
| 170 | 200 | ||
| 201 | pub const Aggregate = struct { | ||
| 202 | ty: Index, | ||
| 203 | fields: []const Index, | ||
| 204 | }; | ||
| 205 | |||
| 171 | pub fn hash32(key: Key) u32 { | 206 | pub fn hash32(key: Key) u32 { |
| 172 | return @truncate(u32, key.hash64()); | 207 | return @truncate(u32, key.hash64()); |
| 173 | } | 208 | } |
| ... | @@ -193,8 +228,15 @@ pub const Key = union(enum) { | ... | @@ -193,8 +228,15 @@ pub const Key = union(enum) { |
| 193 | .simple_value, | 228 | .simple_value, |
| 194 | .extern_func, | 229 | .extern_func, |
| 195 | .opt, | 230 | .opt, |
| 231 | .struct_type, | ||
| 196 | => |info| std.hash.autoHash(hasher, info), | 232 | => |info| std.hash.autoHash(hasher, info), |
| 197 | 233 | ||
| 234 | .union_type => |union_type| { | ||
| 235 | _ = union_type; | ||
| 236 | @panic("TODO"); | ||
| 237 | }, | ||
| 238 | .opaque_type => |opaque_type| std.hash.autoHash(hasher, opaque_type.decl), | ||
| 239 | |||
| 198 | .int => |int| { | 240 | .int => |int| { |
| 199 | // Canonicalize all integers by converting them to BigIntConst. | 241 | // Canonicalize all integers by converting them to BigIntConst. |
| 200 | var buffer: Key.Int.Storage.BigIntSpace = undefined; | 242 | var buffer: Key.Int.Storage.BigIntSpace = undefined; |
| ... | @@ -221,16 +263,10 @@ pub const Key = union(enum) { | ... | @@ -221,16 +263,10 @@ pub const Key = union(enum) { |
| 221 | for (enum_tag.tag.limbs) |limb| std.hash.autoHash(hasher, limb); | 263 | for (enum_tag.tag.limbs) |limb| std.hash.autoHash(hasher, limb); |
| 222 | }, | 264 | }, |
| 223 | 265 | ||
| 224 | .struct_type => |struct_type| { | 266 | .aggregate => |aggregate| { |
| 225 | if (struct_type.fields_len != 0) { | 267 | std.hash.autoHash(hasher, aggregate.ty); |
| 226 | @panic("TODO"); | 268 | for (aggregate.fields) |field| std.hash.autoHash(hasher, field); |
| 227 | } | ||
| 228 | }, | ||
| 229 | .union_type => |union_type| { | ||
| 230 | _ = union_type; | ||
| 231 | @panic("TODO"); | ||
| 232 | }, | 269 | }, |
| 233 | .opaque_type => |opaque_type| std.hash.autoHash(hasher, opaque_type.decl), | ||
| 234 | } | 270 | } |
| 235 | } | 271 | } |
| 236 | 272 | ||
| ... | @@ -280,6 +316,10 @@ pub const Key = union(enum) { | ... | @@ -280,6 +316,10 @@ pub const Key = union(enum) { |
| 280 | const b_info = b.opt; | 316 | const b_info = b.opt; |
| 281 | return std.meta.eql(a_info, b_info); | 317 | return std.meta.eql(a_info, b_info); |
| 282 | }, | 318 | }, |
| 319 | .struct_type => |a_info| { | ||
| 320 | const b_info = b.struct_type; | ||
| 321 | return std.meta.eql(a_info, b_info); | ||
| 322 | }, | ||
| 283 | 323 | ||
| 284 | .ptr => |a_info| { | 324 | .ptr => |a_info| { |
| 285 | const b_info = b.ptr; | 325 | const b_info = b.ptr; |
| ... | @@ -331,16 +371,6 @@ pub const Key = union(enum) { | ... | @@ -331,16 +371,6 @@ pub const Key = union(enum) { |
| 331 | @panic("TODO"); | 371 | @panic("TODO"); |
| 332 | }, | 372 | }, |
| 333 | 373 | ||
| 334 | .struct_type => |a_info| { | ||
| 335 | const b_info = b.struct_type; | ||
| 336 | |||
| 337 | // TODO: remove this special case for empty_struct | ||
| 338 | if (a_info.fields_len == 0 and b_info.fields_len == 0) | ||
| 339 | return true; | ||
| 340 | |||
| 341 | @panic("TODO"); | ||
| 342 | }, | ||
| 343 | |||
| 344 | .union_type => |a_info| { | 374 | .union_type => |a_info| { |
| 345 | const b_info = b.union_type; | 375 | const b_info = b.union_type; |
| 346 | 376 | ||
| ... | @@ -353,6 +383,11 @@ pub const Key = union(enum) { | ... | @@ -353,6 +383,11 @@ pub const Key = union(enum) { |
| 353 | const b_info = b.opaque_type; | 383 | const b_info = b.opaque_type; |
| 354 | return a_info.decl == b_info.decl; | 384 | return a_info.decl == b_info.decl; |
| 355 | }, | 385 | }, |
| 386 | .aggregate => |a_info| { | ||
| 387 | const b_info = b.aggregate; | ||
| 388 | if (a_info.ty != b_info.ty) return false; | ||
| 389 | return std.mem.eql(Index, a_info.fields, b_info.fields); | ||
| 390 | }, | ||
| 356 | } | 391 | } |
| 357 | } | 392 | } |
| 358 | 393 | ||
| ... | @@ -375,6 +410,7 @@ pub const Key = union(enum) { | ... | @@ -375,6 +410,7 @@ pub const Key = union(enum) { |
| 375 | .opt, | 410 | .opt, |
| 376 | .extern_func, | 411 | .extern_func, |
| 377 | .enum_tag, | 412 | .enum_tag, |
| 413 | .aggregate, | ||
| 378 | => |x| return x.ty, | 414 | => |x| return x.ty, |
| 379 | 415 | ||
| 380 | .simple_value => |s| switch (s) { | 416 | .simple_value => |s| switch (s) { |
| ... | @@ -471,6 +507,7 @@ pub const Index = enum(u32) { | ... | @@ -471,6 +507,7 @@ pub const Index = enum(u32) { |
| 471 | anyerror_void_error_union_type, | 507 | anyerror_void_error_union_type, |
| 472 | generic_poison_type, | 508 | generic_poison_type, |
| 473 | var_args_param_type, | 509 | var_args_param_type, |
| 510 | /// `@TypeOf(.{})` | ||
| 474 | empty_struct_type, | 511 | empty_struct_type, |
| 475 | 512 | ||
| 476 | /// `undefined` (untyped) | 513 | /// `undefined` (untyped) |
| ... | @@ -691,7 +728,8 @@ pub const static_keys = [_]Key{ | ... | @@ -691,7 +728,8 @@ pub const static_keys = [_]Key{ |
| 691 | 728 | ||
| 692 | // empty_struct_type | 729 | // empty_struct_type |
| 693 | .{ .struct_type = .{ | 730 | .{ .struct_type = .{ |
| 694 | .fields_len = 0, | 731 | .namespace = .none, |
| 732 | .index = .none, | ||
| 695 | } }, | 733 | } }, |
| 696 | 734 | ||
| 697 | .{ .simple_value = .undefined }, | 735 | .{ .simple_value = .undefined }, |
| ... | @@ -792,16 +830,18 @@ pub const Tag = enum(u8) { | ... | @@ -792,16 +830,18 @@ pub const Tag = enum(u8) { |
| 792 | /// An opaque type. | 830 | /// An opaque type. |
| 793 | /// data is index of Key.OpaqueType in extra. | 831 | /// data is index of Key.OpaqueType in extra. |
| 794 | type_opaque, | 832 | type_opaque, |
| 833 | /// A struct type. | ||
| 834 | /// data is Module.Struct.OptionalIndex | ||
| 835 | /// The `none` tag is used to represent `@TypeOf(.{})`. | ||
| 836 | type_struct, | ||
| 837 | /// A struct type that has only a namespace; no fields, and there is no | ||
| 838 | /// Module.Struct object allocated for it. | ||
| 839 | /// data is Module.Namespace.Index. | ||
| 840 | type_struct_ns, | ||
| 795 | 841 | ||
| 796 | /// A value that can be represented with only an enum tag. | 842 | /// A value that can be represented with only an enum tag. |
| 797 | /// data is SimpleValue enum value. | 843 | /// data is SimpleValue enum value. |
| 798 | simple_value, | 844 | simple_value, |
| 799 | /// The SimpleType and SimpleValue enums are exposed via the InternPool API using | ||
| 800 | /// SimpleType and SimpleValue as the Key data themselves. | ||
| 801 | /// This tag is for miscellaneous types and values that can be represented with | ||
| 802 | /// only an enum tag, but will be presented via the API with a different Key. | ||
| 803 | /// data is SimpleInternal enum value. | ||
| 804 | simple_internal, | ||
| 805 | /// A pointer to an integer value. | 845 | /// A pointer to an integer value. |
| 806 | /// data is extra index of PtrInt, which contains the type and address. | 846 | /// data is extra index of PtrInt, which contains the type and address. |
| 807 | /// Only pointer types are allowed to have this encoding. Optional types must use | 847 | /// Only pointer types are allowed to have this encoding. Optional types must use |
| ... | @@ -809,6 +849,8 @@ pub const Tag = enum(u8) { | ... | @@ -809,6 +849,8 @@ pub const Tag = enum(u8) { |
| 809 | ptr_int, | 849 | ptr_int, |
| 810 | /// An optional value that is non-null. | 850 | /// An optional value that is non-null. |
| 811 | /// data is Index of the payload value. | 851 | /// data is Index of the payload value. |
| 852 | /// In order to use this encoding, one must ensure that the `InternPool` | ||
| 853 | /// already contains the optional type corresponding to this payload. | ||
| 812 | opt_payload, | 854 | opt_payload, |
| 813 | /// An optional value that is null. | 855 | /// An optional value that is null. |
| 814 | /// data is Index of the payload type. | 856 | /// data is Index of the payload type. |
| ... | @@ -859,6 +901,13 @@ pub const Tag = enum(u8) { | ... | @@ -859,6 +901,13 @@ pub const Tag = enum(u8) { |
| 859 | extern_func, | 901 | extern_func, |
| 860 | /// A regular function. | 902 | /// A regular function. |
| 861 | func, | 903 | func, |
| 904 | /// This represents the only possible value for *some* types which have | ||
| 905 | /// only one possible value. Not all only-possible-values are encoded this way; | ||
| 906 | /// for example structs which have all comptime fields are not encoded this way. | ||
| 907 | /// The set of values that are encoded this way is: | ||
| 908 | /// * A struct which has 0 fields. | ||
| 909 | /// data is Index of the type, which is known to be zero bits at runtime. | ||
| 910 | only_possible_value, | ||
| 862 | }; | 911 | }; |
| 863 | 912 | ||
| 864 | /// Having `SimpleType` and `SimpleValue` in separate enums makes it easier to | 913 | /// Having `SimpleType` and `SimpleValue` in separate enums makes it easier to |
| ... | @@ -912,9 +961,12 @@ pub const SimpleType = enum(u32) { | ... | @@ -912,9 +961,12 @@ pub const SimpleType = enum(u32) { |
| 912 | }; | 961 | }; |
| 913 | 962 | ||
| 914 | pub const SimpleValue = enum(u32) { | 963 | pub const SimpleValue = enum(u32) { |
| 964 | /// This is untyped `undefined`. | ||
| 915 | undefined, | 965 | undefined, |
| 916 | void, | 966 | void, |
| 967 | /// This is untyped `null`. | ||
| 917 | null, | 968 | null, |
| 969 | /// This is the untyped empty struct literal: `.{}` | ||
| 918 | empty_struct, | 970 | empty_struct, |
| 919 | true, | 971 | true, |
| 920 | false, | 972 | false, |
| ... | @@ -923,12 +975,6 @@ pub const SimpleValue = enum(u32) { | ... | @@ -923,12 +975,6 @@ pub const SimpleValue = enum(u32) { |
| 923 | generic_poison, | 975 | generic_poison, |
| 924 | }; | 976 | }; |
| 925 | 977 | ||
| 926 | pub const SimpleInternal = enum(u32) { | ||
| 927 | /// This is the empty struct type. Note that empty_struct value is exposed | ||
| 928 | /// via SimpleValue. | ||
| 929 | type_empty_struct, | ||
| 930 | }; | ||
| 931 | |||
| 932 | pub const Pointer = struct { | 978 | pub const Pointer = struct { |
| 933 | child: Index, | 979 | child: Index, |
| 934 | sentinel: Index, | 980 | sentinel: Index, |
| ... | @@ -1005,7 +1051,7 @@ pub const ErrorUnion = struct { | ... | @@ -1005,7 +1051,7 @@ pub const ErrorUnion = struct { |
| 1005 | /// 0. field name: null-terminated string index for each fields_len; declaration order | 1051 | /// 0. field name: null-terminated string index for each fields_len; declaration order |
| 1006 | pub const EnumSimple = struct { | 1052 | pub const EnumSimple = struct { |
| 1007 | /// The Decl that corresponds to the enum itself. | 1053 | /// The Decl that corresponds to the enum itself. |
| 1008 | decl: DeclIndex, | 1054 | decl: Module.Decl.Index, |
| 1009 | /// An integer type which is used for the numerical value of the enum. This | 1055 | /// An integer type which is used for the numerical value of the enum. This |
| 1010 | /// is inferred by Zig to be the smallest power of two unsigned int that | 1056 | /// is inferred by Zig to be the smallest power of two unsigned int that |
| 1011 | /// fits the number of fields. It is stored here to avoid unnecessary | 1057 | /// fits the number of fields. It is stored here to avoid unnecessary |
| ... | @@ -1091,6 +1137,10 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { | ... | @@ -1091,6 +1137,10 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { |
| 1091 | ip.items.deinit(gpa); | 1137 | ip.items.deinit(gpa); |
| 1092 | ip.extra.deinit(gpa); | 1138 | ip.extra.deinit(gpa); |
| 1093 | ip.limbs.deinit(gpa); | 1139 | ip.limbs.deinit(gpa); |
| 1140 | |||
| 1141 | ip.structs_free_list.deinit(gpa); | ||
| 1142 | ip.allocated_structs.deinit(gpa); | ||
| 1143 | |||
| 1094 | ip.* = undefined; | 1144 | ip.* = undefined; |
| 1095 | } | 1145 | } |
| 1096 | 1146 | ||
| ... | @@ -1167,20 +1217,38 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { | ... | @@ -1167,20 +1217,38 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { |
| 1167 | .type_enum_simple => @panic("TODO"), | 1217 | .type_enum_simple => @panic("TODO"), |
| 1168 | 1218 | ||
| 1169 | .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) }, | 1219 | .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) }, |
| 1170 | 1220 | .type_struct => { | |
| 1171 | .simple_internal => switch (@intToEnum(SimpleInternal, data)) { | 1221 | const struct_index = @intToEnum(Module.Struct.OptionalIndex, data); |
| 1172 | .type_empty_struct => .{ .struct_type = .{ | 1222 | const namespace = if (struct_index.unwrap()) |i| |
| 1173 | .fields_len = 0, | 1223 | ip.structPtrConst(i).namespace.toOptional() |
| 1174 | } }, | 1224 | else |
| 1225 | .none; | ||
| 1226 | return .{ .struct_type = .{ | ||
| 1227 | .index = struct_index, | ||
| 1228 | .namespace = namespace, | ||
| 1229 | } }; | ||
| 1175 | }, | 1230 | }, |
| 1231 | .type_struct_ns => .{ .struct_type = .{ | ||
| 1232 | .index = .none, | ||
| 1233 | .namespace = @intToEnum(Module.Namespace.Index, data).toOptional(), | ||
| 1234 | } }, | ||
| 1235 | |||
| 1176 | .opt_null => .{ .opt = .{ | 1236 | .opt_null => .{ .opt = .{ |
| 1177 | .ty = @intToEnum(Index, data), | 1237 | .ty = @intToEnum(Index, data), |
| 1178 | .val = .none, | 1238 | .val = .none, |
| 1179 | } }, | 1239 | } }, |
| 1180 | .opt_payload => .{ .opt = .{ | 1240 | .opt_payload => { |
| 1181 | .ty = indexToKey(ip, @intToEnum(Index, data)).typeOf(), | 1241 | const payload_val = @intToEnum(Index, data); |
| 1182 | .val = @intToEnum(Index, data), | 1242 | // The existence of `opt_payload` guarantees that the optional type will be |
| 1183 | } }, | 1243 | // stored in the `InternPool`. |
| 1244 | const opt_ty = ip.getAssumeExists(.{ | ||
| 1245 | .opt_type = indexToKey(ip, payload_val).typeOf(), | ||
| 1246 | }); | ||
| 1247 | return .{ .opt = .{ | ||
| 1248 | .ty = opt_ty, | ||
| 1249 | .val = payload_val, | ||
| 1250 | } }; | ||
| 1251 | }, | ||
| 1184 | .ptr_int => { | 1252 | .ptr_int => { |
| 1185 | const info = ip.extraData(PtrInt, data); | 1253 | const info = ip.extraData(PtrInt, data); |
| 1186 | return .{ .ptr = .{ | 1254 | return .{ .ptr = .{ |
| ... | @@ -1225,6 +1293,16 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { | ... | @@ -1225,6 +1293,16 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { |
| 1225 | .float_f128 => @panic("TODO"), | 1293 | .float_f128 => @panic("TODO"), |
| 1226 | .extern_func => @panic("TODO"), | 1294 | .extern_func => @panic("TODO"), |
| 1227 | .func => @panic("TODO"), | 1295 | .func => @panic("TODO"), |
| 1296 | .only_possible_value => { | ||
| 1297 | const ty = @intToEnum(Index, data); | ||
| 1298 | return switch (ip.indexToKey(ty)) { | ||
| 1299 | .struct_type => .{ .aggregate = .{ | ||
| 1300 | .ty = ty, | ||
| 1301 | .fields = &.{}, | ||
| 1302 | } }, | ||
| 1303 | else => unreachable, | ||
| 1304 | }; | ||
| 1305 | }, | ||
| 1228 | }; | 1306 | }; |
| 1229 | } | 1307 | } |
| 1230 | 1308 | ||
| ... | @@ -1359,12 +1437,15 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -1359,12 +1437,15 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 1359 | }, | 1437 | }, |
| 1360 | 1438 | ||
| 1361 | .struct_type => |struct_type| { | 1439 | .struct_type => |struct_type| { |
| 1362 | if (struct_type.fields_len != 0) { | 1440 | ip.items.appendAssumeCapacity(if (struct_type.index.unwrap()) |i| .{ |
| 1363 | @panic("TODO"); // handle structs other than empty_struct | 1441 | .tag = .type_struct, |
| 1364 | } | 1442 | .data = @enumToInt(i), |
| 1365 | ip.items.appendAssumeCapacity(.{ | 1443 | } else if (struct_type.namespace.unwrap()) |i| .{ |
| 1366 | .tag = .simple_internal, | 1444 | .tag = .type_struct_ns, |
| 1367 | .data = @enumToInt(SimpleInternal.type_empty_struct), | 1445 | .data = @enumToInt(i), |
| 1446 | } else .{ | ||
| 1447 | .tag = .type_struct, | ||
| 1448 | .data = @enumToInt(Module.Struct.OptionalIndex.none), | ||
| 1368 | }); | 1449 | }); |
| 1369 | }, | 1450 | }, |
| 1370 | 1451 | ||
| ... | @@ -1398,6 +1479,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -1398,6 +1479,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 1398 | 1479 | ||
| 1399 | .opt => |opt| { | 1480 | .opt => |opt| { |
| 1400 | assert(opt.ty != .none); | 1481 | assert(opt.ty != .none); |
| 1482 | assert(ip.isOptionalType(opt.ty)); | ||
| 1401 | ip.items.appendAssumeCapacity(if (opt.val == .none) .{ | 1483 | ip.items.appendAssumeCapacity(if (opt.val == .none) .{ |
| 1402 | .tag = .opt_null, | 1484 | .tag = .opt_null, |
| 1403 | .data = @enumToInt(opt.ty), | 1485 | .data = @enumToInt(opt.ty), |
| ... | @@ -1549,10 +1631,35 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -1549,10 +1631,35 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 1549 | const tag: Tag = if (enum_tag.tag.positive) .enum_tag_positive else .enum_tag_negative; | 1631 | const tag: Tag = if (enum_tag.tag.positive) .enum_tag_positive else .enum_tag_negative; |
| 1550 | try addInt(ip, gpa, enum_tag.ty, tag, enum_tag.tag.limbs); | 1632 | try addInt(ip, gpa, enum_tag.ty, tag, enum_tag.tag.limbs); |
| 1551 | }, | 1633 | }, |
| 1634 | |||
| 1635 | .aggregate => |aggregate| { | ||
| 1636 | if (aggregate.fields.len == 0) { | ||
| 1637 | ip.items.appendAssumeCapacity(.{ | ||
| 1638 | .tag = .only_possible_value, | ||
| 1639 | .data = @enumToInt(aggregate.ty), | ||
| 1640 | }); | ||
| 1641 | return @intToEnum(Index, ip.items.len - 1); | ||
| 1642 | } | ||
| 1643 | @panic("TODO"); | ||
| 1644 | }, | ||
| 1552 | } | 1645 | } |
| 1553 | return @intToEnum(Index, ip.items.len - 1); | 1646 | return @intToEnum(Index, ip.items.len - 1); |
| 1554 | } | 1647 | } |
| 1555 | 1648 | ||
| 1649 | pub fn getAssumeExists(ip: InternPool, key: Key) Index { | ||
| 1650 | const adapter: KeyAdapter = .{ .intern_pool = &ip }; | ||
| 1651 | const index = ip.map.getIndexAdapted(key, adapter).?; | ||
| 1652 | return @intToEnum(Index, index); | ||
| 1653 | } | ||
| 1654 | |||
| 1655 | /// This operation only happens under compile error conditions. | ||
| 1656 | /// Leak the index until the next garbage collection. | ||
| 1657 | pub fn remove(ip: *InternPool, index: Index) void { | ||
| 1658 | _ = ip; | ||
| 1659 | _ = index; | ||
| 1660 | @panic("TODO this is a bit problematic to implement, could we maybe just never support a remove() operation on InternPool?"); | ||
| 1661 | } | ||
| 1662 | |||
| 1556 | fn addInt(ip: *InternPool, gpa: Allocator, ty: Index, tag: Tag, limbs: []const Limb) !void { | 1663 | fn addInt(ip: *InternPool, gpa: Allocator, ty: Index, tag: Tag, limbs: []const Limb) !void { |
| 1557 | const limbs_len = @intCast(u32, limbs.len); | 1664 | const limbs_len = @intCast(u32, limbs.len); |
| 1558 | try ip.reserveLimbs(gpa, @typeInfo(Int).Struct.fields.len + limbs_len); | 1665 | try ip.reserveLimbs(gpa, @typeInfo(Int).Struct.fields.len + limbs_len); |
| ... | @@ -1578,8 +1685,8 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 { | ... | @@ -1578,8 +1685,8 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 { |
| 1578 | ip.extra.appendAssumeCapacity(switch (field.type) { | 1685 | ip.extra.appendAssumeCapacity(switch (field.type) { |
| 1579 | u32 => @field(extra, field.name), | 1686 | u32 => @field(extra, field.name), |
| 1580 | Index => @enumToInt(@field(extra, field.name)), | 1687 | Index => @enumToInt(@field(extra, field.name)), |
| 1581 | DeclIndex => @enumToInt(@field(extra, field.name)), | 1688 | Module.Decl.Index => @enumToInt(@field(extra, field.name)), |
| 1582 | NamespaceIndex => @enumToInt(@field(extra, field.name)), | 1689 | Module.Namespace.Index => @enumToInt(@field(extra, field.name)), |
| 1583 | i32 => @bitCast(u32, @field(extra, field.name)), | 1690 | i32 => @bitCast(u32, @field(extra, field.name)), |
| 1584 | Pointer.Flags => @bitCast(u32, @field(extra, field.name)), | 1691 | Pointer.Flags => @bitCast(u32, @field(extra, field.name)), |
| 1585 | Pointer.PackedOffset => @bitCast(u32, @field(extra, field.name)), | 1692 | Pointer.PackedOffset => @bitCast(u32, @field(extra, field.name)), |
| ... | @@ -1635,8 +1742,8 @@ fn extraData(ip: InternPool, comptime T: type, index: usize) T { | ... | @@ -1635,8 +1742,8 @@ fn extraData(ip: InternPool, comptime T: type, index: usize) T { |
| 1635 | @field(result, field.name) = switch (field.type) { | 1742 | @field(result, field.name) = switch (field.type) { |
| 1636 | u32 => int32, | 1743 | u32 => int32, |
| 1637 | Index => @intToEnum(Index, int32), | 1744 | Index => @intToEnum(Index, int32), |
| 1638 | DeclIndex => @intToEnum(DeclIndex, int32), | 1745 | Module.Decl.Index => @intToEnum(Module.Decl.Index, int32), |
| 1639 | NamespaceIndex => @intToEnum(NamespaceIndex, int32), | 1746 | Module.Namespace.Index => @intToEnum(Module.Namespace.Index, int32), |
| 1640 | i32 => @bitCast(i32, int32), | 1747 | i32 => @bitCast(i32, int32), |
| 1641 | Pointer.Flags => @bitCast(Pointer.Flags, int32), | 1748 | Pointer.Flags => @bitCast(Pointer.Flags, int32), |
| 1642 | Pointer.PackedOffset => @bitCast(Pointer.PackedOffset, int32), | 1749 | Pointer.PackedOffset => @bitCast(Pointer.PackedOffset, int32), |
| ... | @@ -1808,6 +1915,20 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al | ... | @@ -1808,6 +1915,20 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al |
| 1808 | } | 1915 | } |
| 1809 | } | 1916 | } |
| 1810 | 1917 | ||
| 1918 | pub fn indexToStruct(ip: *InternPool, val: Index) Module.Struct.OptionalIndex { | ||
| 1919 | const tags = ip.items.items(.tag); | ||
| 1920 | if (val == .none) return .none; | ||
| 1921 | if (tags[@enumToInt(val)] != .type_struct) return .none; | ||
| 1922 | const datas = ip.items.items(.data); | ||
| 1923 | return @intToEnum(Module.Struct.Index, datas[@enumToInt(val)]).toOptional(); | ||
| 1924 | } | ||
| 1925 | |||
| 1926 | pub fn isOptionalType(ip: InternPool, ty: Index) bool { | ||
| 1927 | const tags = ip.items.items(.tag); | ||
| 1928 | if (ty == .none) return false; | ||
| 1929 | return tags[@enumToInt(ty)] == .type_optional; | ||
| 1930 | } | ||
| 1931 | |||
| 1811 | pub fn dump(ip: InternPool) void { | 1932 | pub fn dump(ip: InternPool) void { |
| 1812 | dumpFallible(ip, std.heap.page_allocator) catch return; | 1933 | dumpFallible(ip, std.heap.page_allocator) catch return; |
| 1813 | } | 1934 | } |
| ... | @@ -1859,9 +1980,10 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { | ... | @@ -1859,9 +1980,10 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { |
| 1859 | .type_error_union => @sizeOf(ErrorUnion), | 1980 | .type_error_union => @sizeOf(ErrorUnion), |
| 1860 | .type_enum_simple => @sizeOf(EnumSimple), | 1981 | .type_enum_simple => @sizeOf(EnumSimple), |
| 1861 | .type_opaque => @sizeOf(Key.OpaqueType), | 1982 | .type_opaque => @sizeOf(Key.OpaqueType), |
| 1983 | .type_struct => 0, | ||
| 1984 | .type_struct_ns => 0, | ||
| 1862 | .simple_type => 0, | 1985 | .simple_type => 0, |
| 1863 | .simple_value => 0, | 1986 | .simple_value => 0, |
| 1864 | .simple_internal => 0, | ||
| 1865 | .ptr_int => @sizeOf(PtrInt), | 1987 | .ptr_int => @sizeOf(PtrInt), |
| 1866 | .opt_null => 0, | 1988 | .opt_null => 0, |
| 1867 | .opt_payload => 0, | 1989 | .opt_payload => 0, |
| ... | @@ -1887,6 +2009,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { | ... | @@ -1887,6 +2009,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { |
| 1887 | .float_f128 => @sizeOf(Float128), | 2009 | .float_f128 => @sizeOf(Float128), |
| 1888 | .extern_func => @panic("TODO"), | 2010 | .extern_func => @panic("TODO"), |
| 1889 | .func => @panic("TODO"), | 2011 | .func => @panic("TODO"), |
| 2012 | .only_possible_value => 0, | ||
| 1890 | }); | 2013 | }); |
| 1891 | } | 2014 | } |
| 1892 | const SortContext = struct { | 2015 | const SortContext = struct { |
| ... | @@ -1905,3 +2028,34 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { | ... | @@ -1905,3 +2028,34 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { |
| 1905 | }); | 2028 | }); |
| 1906 | } | 2029 | } |
| 1907 | } | 2030 | } |
| 2031 | |||
| 2032 | pub fn structPtr(ip: *InternPool, index: Module.Struct.Index) *Module.Struct { | ||
| 2033 | return ip.allocated_structs.at(@enumToInt(index)); | ||
| 2034 | } | ||
| 2035 | |||
| 2036 | pub fn structPtrConst(ip: InternPool, index: Module.Struct.Index) *const Module.Struct { | ||
| 2037 | return ip.allocated_structs.at(@enumToInt(index)); | ||
| 2038 | } | ||
| 2039 | |||
| 2040 | pub fn structPtrUnwrapConst(ip: InternPool, index: Module.Struct.OptionalIndex) ?*const Module.Struct { | ||
| 2041 | return structPtrConst(ip, index.unwrap() orelse return null); | ||
| 2042 | } | ||
| 2043 | |||
| 2044 | pub fn createStruct( | ||
| 2045 | ip: *InternPool, | ||
| 2046 | gpa: Allocator, | ||
| 2047 | initialization: Module.Struct, | ||
| 2048 | ) Allocator.Error!Module.Struct.Index { | ||
| 2049 | if (ip.structs_free_list.popOrNull()) |index| return index; | ||
| 2050 | const ptr = try ip.allocated_structs.addOne(gpa); | ||
| 2051 | ptr.* = initialization; | ||
| 2052 | return @intToEnum(Module.Struct.Index, ip.allocated_structs.len - 1); | ||
| 2053 | } | ||
| 2054 | |||
| 2055 | pub fn destroyStruct(ip: *InternPool, gpa: Allocator, index: Module.Struct.Index) void { | ||
| 2056 | ip.structPtr(index).* = undefined; | ||
| 2057 | ip.structs_free_list.append(gpa, index) catch { | ||
| 2058 | // In order to keep `destroyStruct` a non-fallible function, we ignore memory | ||
| 2059 | // allocation failures here, instead leaking the Struct until garbage collection. | ||
| 2060 | }; | ||
| 2061 | } |
src/Module.zig+117-62| ... | @@ -839,11 +839,14 @@ pub const Decl = struct { | ... | @@ -839,11 +839,14 @@ pub const Decl = struct { |
| 839 | 839 | ||
| 840 | /// If the Decl has a value and it is a struct, return it, | 840 | /// If the Decl has a value and it is a struct, return it, |
| 841 | /// otherwise null. | 841 | /// otherwise null. |
| 842 | pub fn getStruct(decl: *Decl) ?*Struct { | 842 | pub fn getStruct(decl: *Decl, mod: *Module) ?*Struct { |
| 843 | if (!decl.owns_tv) return null; | 843 | return mod.structPtrUnwrap(getStructIndex(decl, mod)); |
| 844 | const ty = (decl.val.castTag(.ty) orelse return null).data; | 844 | } |
| 845 | const struct_obj = (ty.castTag(.@"struct") orelse return null).data; | 845 | |
| 846 | return struct_obj; | 846 | pub fn getStructIndex(decl: *Decl, mod: *Module) Struct.OptionalIndex { |
| 847 | if (!decl.owns_tv) return .none; | ||
| 848 | const ty = (decl.val.castTag(.ty) orelse return .none).data; | ||
| 849 | return mod.intern_pool.indexToStruct(ty.ip_index); | ||
| 847 | } | 850 | } |
| 848 | 851 | ||
| 849 | /// If the Decl has a value and it is a union, return it, | 852 | /// If the Decl has a value and it is a union, return it, |
| ... | @@ -884,32 +887,29 @@ pub const Decl = struct { | ... | @@ -884,32 +887,29 @@ pub const Decl = struct { |
| 884 | /// Only returns it if the Decl is the owner. | 887 | /// Only returns it if the Decl is the owner. |
| 885 | pub fn getInnerNamespaceIndex(decl: *Decl, mod: *Module) Namespace.OptionalIndex { | 888 | pub fn getInnerNamespaceIndex(decl: *Decl, mod: *Module) Namespace.OptionalIndex { |
| 886 | if (!decl.owns_tv) return .none; | 889 | if (!decl.owns_tv) return .none; |
| 887 | if (decl.val.ip_index == .none) { | 890 | switch (decl.val.ip_index) { |
| 888 | const ty = (decl.val.castTag(.ty) orelse return .none).data; | 891 | .empty_struct_type => return .none, |
| 889 | switch (ty.tag()) { | 892 | .none => { |
| 890 | .@"struct" => { | 893 | const ty = (decl.val.castTag(.ty) orelse return .none).data; |
| 891 | const struct_obj = ty.castTag(.@"struct").?.data; | 894 | switch (ty.tag()) { |
| 892 | return struct_obj.namespace.toOptional(); | 895 | .enum_full, .enum_nonexhaustive => { |
| 893 | }, | 896 | const enum_obj = ty.cast(Type.Payload.EnumFull).?.data; |
| 894 | .enum_full, .enum_nonexhaustive => { | 897 | return enum_obj.namespace.toOptional(); |
| 895 | const enum_obj = ty.cast(Type.Payload.EnumFull).?.data; | 898 | }, |
| 896 | return enum_obj.namespace.toOptional(); | 899 | .@"union", .union_safety_tagged, .union_tagged => { |
| 897 | }, | 900 | const union_obj = ty.cast(Type.Payload.Union).?.data; |
| 898 | .empty_struct => { | 901 | return union_obj.namespace.toOptional(); |
| 899 | @panic("TODO"); | 902 | }, |
| 900 | }, | ||
| 901 | .@"union", .union_safety_tagged, .union_tagged => { | ||
| 902 | const union_obj = ty.cast(Type.Payload.Union).?.data; | ||
| 903 | return union_obj.namespace.toOptional(); | ||
| 904 | }, | ||
| 905 | 903 | ||
| 906 | else => return .none, | 904 | else => return .none, |
| 907 | } | 905 | } |
| 906 | }, | ||
| 907 | else => return switch (mod.intern_pool.indexToKey(decl.val.ip_index)) { | ||
| 908 | .opaque_type => |opaque_type| opaque_type.namespace.toOptional(), | ||
| 909 | .struct_type => |struct_type| struct_type.namespace, | ||
| 910 | else => .none, | ||
| 911 | }, | ||
| 908 | } | 912 | } |
| 909 | return switch (mod.intern_pool.indexToKey(decl.val.ip_index)) { | ||
| 910 | .opaque_type => |opaque_type| opaque_type.namespace.toOptional(), | ||
| 911 | else => .none, | ||
| 912 | }; | ||
| 913 | } | 913 | } |
| 914 | 914 | ||
| 915 | /// Same as `getInnerNamespaceIndex` but additionally obtains the pointer. | 915 | /// Same as `getInnerNamespaceIndex` but additionally obtains the pointer. |
| ... | @@ -1046,6 +1046,28 @@ pub const Struct = struct { | ... | @@ -1046,6 +1046,28 @@ pub const Struct = struct { |
| 1046 | is_tuple: bool, | 1046 | is_tuple: bool, |
| 1047 | assumed_runtime_bits: bool = false, | 1047 | assumed_runtime_bits: bool = false, |
| 1048 | 1048 | ||
| 1049 | pub const Index = enum(u32) { | ||
| 1050 | _, | ||
| 1051 | |||
| 1052 | pub fn toOptional(i: Index) OptionalIndex { | ||
| 1053 | return @intToEnum(OptionalIndex, @enumToInt(i)); | ||
| 1054 | } | ||
| 1055 | }; | ||
| 1056 | |||
| 1057 | pub const OptionalIndex = enum(u32) { | ||
| 1058 | none = std.math.maxInt(u32), | ||
| 1059 | _, | ||
| 1060 | |||
| 1061 | pub fn init(oi: ?Index) OptionalIndex { | ||
| 1062 | return @intToEnum(OptionalIndex, @enumToInt(oi orelse return .none)); | ||
| 1063 | } | ||
| 1064 | |||
| 1065 | pub fn unwrap(oi: OptionalIndex) ?Index { | ||
| 1066 | if (oi == .none) return null; | ||
| 1067 | return @intToEnum(Index, @enumToInt(oi)); | ||
| 1068 | } | ||
| 1069 | }; | ||
| 1070 | |||
| 1049 | pub const Fields = std.StringArrayHashMapUnmanaged(Field); | 1071 | pub const Fields = std.StringArrayHashMapUnmanaged(Field); |
| 1050 | 1072 | ||
| 1051 | /// The `Type` and `Value` memory is owned by the arena of the Struct's owner_decl. | 1073 | /// The `Type` and `Value` memory is owned by the arena of the Struct's owner_decl. |
| ... | @@ -1111,12 +1133,7 @@ pub const Struct = struct { | ... | @@ -1111,12 +1133,7 @@ pub const Struct = struct { |
| 1111 | } | 1133 | } |
| 1112 | 1134 | ||
| 1113 | pub fn srcLoc(s: Struct, mod: *Module) SrcLoc { | 1135 | pub fn srcLoc(s: Struct, mod: *Module) SrcLoc { |
| 1114 | const owner_decl = mod.declPtr(s.owner_decl); | 1136 | return mod.declPtr(s.owner_decl).srcLoc(mod); |
| 1115 | return .{ | ||
| 1116 | .file_scope = owner_decl.getFileScope(mod), | ||
| 1117 | .parent_decl_node = owner_decl.src_node, | ||
| 1118 | .lazy = LazySrcLoc.nodeOffset(0), | ||
| 1119 | }; | ||
| 1120 | } | 1137 | } |
| 1121 | 1138 | ||
| 1122 | pub fn fieldSrcLoc(s: Struct, mod: *Module, query: FieldSrcQuery) SrcLoc { | 1139 | pub fn fieldSrcLoc(s: Struct, mod: *Module, query: FieldSrcQuery) SrcLoc { |
| ... | @@ -3622,6 +3639,16 @@ pub fn namespacePtr(mod: *Module, index: Namespace.Index) *Namespace { | ... | @@ -3622,6 +3639,16 @@ pub fn namespacePtr(mod: *Module, index: Namespace.Index) *Namespace { |
| 3622 | return mod.allocated_namespaces.at(@enumToInt(index)); | 3639 | return mod.allocated_namespaces.at(@enumToInt(index)); |
| 3623 | } | 3640 | } |
| 3624 | 3641 | ||
| 3642 | pub fn structPtr(mod: *Module, index: Struct.Index) *Struct { | ||
| 3643 | return mod.intern_pool.structPtr(index); | ||
| 3644 | } | ||
| 3645 | |||
| 3646 | /// This one accepts an index from the InternPool and asserts that it is not | ||
| 3647 | /// the anonymous empty struct type. | ||
| 3648 | pub fn structPtrUnwrap(mod: *Module, index: Struct.OptionalIndex) ?*Struct { | ||
| 3649 | return structPtr(mod, index.unwrap() orelse return null); | ||
| 3650 | } | ||
| 3651 | |||
| 3625 | /// Returns true if and only if the Decl is the top level struct associated with a File. | 3652 | /// Returns true if and only if the Decl is the top level struct associated with a File. |
| 3626 | pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool { | 3653 | pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool { |
| 3627 | const decl = mod.declPtr(decl_index); | 3654 | const decl = mod.declPtr(decl_index); |
| ... | @@ -4078,7 +4105,7 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void { | ... | @@ -4078,7 +4105,7 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void { |
| 4078 | 4105 | ||
| 4079 | if (!decl.owns_tv) continue; | 4106 | if (!decl.owns_tv) continue; |
| 4080 | 4107 | ||
| 4081 | if (decl.getStruct()) |struct_obj| { | 4108 | if (decl.getStruct(mod)) |struct_obj| { |
| 4082 | struct_obj.zir_index = inst_map.get(struct_obj.zir_index) orelse { | 4109 | struct_obj.zir_index = inst_map.get(struct_obj.zir_index) orelse { |
| 4083 | try file.deleted_decls.append(gpa, decl_index); | 4110 | try file.deleted_decls.append(gpa, decl_index); |
| 4084 | continue; | 4111 | continue; |
| ... | @@ -4597,36 +4624,50 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { | ... | @@ -4597,36 +4624,50 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 4597 | errdefer new_decl_arena.deinit(); | 4624 | errdefer new_decl_arena.deinit(); |
| 4598 | const new_decl_arena_allocator = new_decl_arena.allocator(); | 4625 | const new_decl_arena_allocator = new_decl_arena.allocator(); |
| 4599 | 4626 | ||
| 4600 | const struct_obj = try new_decl_arena_allocator.create(Module.Struct); | 4627 | // Because these three things each reference each other, `undefined` |
| 4601 | const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj); | 4628 | // placeholders are used before being set after the struct type gains an |
| 4602 | const struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty); | 4629 | // InternPool index. |
| 4603 | const ty_ty = comptime Type.type; | 4630 | const new_namespace_index = try mod.createNamespace(.{ |
| 4604 | struct_obj.* = .{ | 4631 | .parent = .none, |
| 4605 | .owner_decl = undefined, // set below | 4632 | .ty = undefined, |
| 4633 | .file_scope = file, | ||
| 4634 | }); | ||
| 4635 | const new_namespace = mod.namespacePtr(new_namespace_index); | ||
| 4636 | errdefer mod.destroyNamespace(new_namespace_index); | ||
| 4637 | |||
| 4638 | const new_decl_index = try mod.allocateNewDecl(new_namespace_index, 0, null); | ||
| 4639 | const new_decl = mod.declPtr(new_decl_index); | ||
| 4640 | errdefer @panic("TODO error handling"); | ||
| 4641 | |||
| 4642 | const struct_index = try mod.createStruct(.{ | ||
| 4643 | .owner_decl = new_decl_index, | ||
| 4606 | .fields = .{}, | 4644 | .fields = .{}, |
| 4607 | .zir_index = undefined, // set below | 4645 | .zir_index = undefined, // set below |
| 4608 | .layout = .Auto, | 4646 | .layout = .Auto, |
| 4609 | .status = .none, | 4647 | .status = .none, |
| 4610 | .known_non_opv = undefined, | 4648 | .known_non_opv = undefined, |
| 4611 | .is_tuple = undefined, // set below | 4649 | .is_tuple = undefined, // set below |
| 4612 | .namespace = try mod.createNamespace(.{ | 4650 | .namespace = new_namespace_index, |
| 4613 | .parent = .none, | 4651 | }); |
| 4614 | .ty = struct_ty, | 4652 | errdefer mod.destroyStruct(struct_index); |
| 4615 | .file_scope = file, | 4653 | |
| 4616 | }), | 4654 | const struct_ty = try mod.intern_pool.get(gpa, .{ .struct_type = .{ |
| 4617 | }; | 4655 | .index = struct_index.toOptional(), |
| 4618 | const new_decl_index = try mod.allocateNewDecl(struct_obj.namespace, 0, null); | 4656 | .namespace = new_namespace_index.toOptional(), |
| 4619 | const new_decl = mod.declPtr(new_decl_index); | 4657 | } }); |
| 4658 | errdefer mod.intern_pool.remove(struct_ty); | ||
| 4659 | |||
| 4660 | new_namespace.ty = struct_ty.toType(); | ||
| 4620 | file.root_decl = new_decl_index.toOptional(); | 4661 | file.root_decl = new_decl_index.toOptional(); |
| 4621 | struct_obj.owner_decl = new_decl_index; | 4662 | |
| 4622 | new_decl.name = try file.fullyQualifiedNameZ(gpa); | 4663 | new_decl.name = try file.fullyQualifiedNameZ(gpa); |
| 4623 | new_decl.src_line = 0; | 4664 | new_decl.src_line = 0; |
| 4624 | new_decl.is_pub = true; | 4665 | new_decl.is_pub = true; |
| 4625 | new_decl.is_exported = false; | 4666 | new_decl.is_exported = false; |
| 4626 | new_decl.has_align = false; | 4667 | new_decl.has_align = false; |
| 4627 | new_decl.has_linksection_or_addrspace = false; | 4668 | new_decl.has_linksection_or_addrspace = false; |
| 4628 | new_decl.ty = ty_ty; | 4669 | new_decl.ty = Type.type; |
| 4629 | new_decl.val = struct_val; | 4670 | new_decl.val = struct_ty.toValue(); |
| 4630 | new_decl.@"align" = 0; | 4671 | new_decl.@"align" = 0; |
| 4631 | new_decl.@"linksection" = null; | 4672 | new_decl.@"linksection" = null; |
| 4632 | new_decl.has_tv = true; | 4673 | new_decl.has_tv = true; |
| ... | @@ -4639,6 +4680,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { | ... | @@ -4639,6 +4680,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 4639 | if (file.status == .success_zir) { | 4680 | if (file.status == .success_zir) { |
| 4640 | assert(file.zir_loaded); | 4681 | assert(file.zir_loaded); |
| 4641 | const main_struct_inst = Zir.main_struct_inst; | 4682 | const main_struct_inst = Zir.main_struct_inst; |
| 4683 | const struct_obj = mod.structPtr(struct_index); | ||
| 4642 | struct_obj.zir_index = main_struct_inst; | 4684 | struct_obj.zir_index = main_struct_inst; |
| 4643 | const extended = file.zir.instructions.items(.data)[main_struct_inst].extended; | 4685 | const extended = file.zir.instructions.items(.data)[main_struct_inst].extended; |
| 4644 | const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small); | 4686 | const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small); |
| ... | @@ -4665,7 +4707,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { | ... | @@ -4665,7 +4707,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 4665 | var wip_captures = try WipCaptureScope.init(gpa, new_decl_arena_allocator, null); | 4707 | var wip_captures = try WipCaptureScope.init(gpa, new_decl_arena_allocator, null); |
| 4666 | defer wip_captures.deinit(); | 4708 | defer wip_captures.deinit(); |
| 4667 | 4709 | ||
| 4668 | if (sema.analyzeStructDecl(new_decl, main_struct_inst, struct_obj)) |_| { | 4710 | if (sema.analyzeStructDecl(new_decl, main_struct_inst, struct_index)) |_| { |
| 4669 | try wip_captures.finalize(); | 4711 | try wip_captures.finalize(); |
| 4670 | new_decl.analysis = .complete; | 4712 | new_decl.analysis = .complete; |
| 4671 | } else |err| switch (err) { | 4713 | } else |err| switch (err) { |
| ... | @@ -4761,11 +4803,12 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -4761,11 +4803,12 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4761 | if (mod.declIsRoot(decl_index)) { | 4803 | if (mod.declIsRoot(decl_index)) { |
| 4762 | log.debug("semaDecl root {*} ({s})", .{ decl, decl.name }); | 4804 | log.debug("semaDecl root {*} ({s})", .{ decl, decl.name }); |
| 4763 | const main_struct_inst = Zir.main_struct_inst; | 4805 | const main_struct_inst = Zir.main_struct_inst; |
| 4764 | const struct_obj = decl.getStruct().?; | 4806 | const struct_index = decl.getStructIndex(mod).unwrap().?; |
| 4807 | const struct_obj = mod.structPtr(struct_index); | ||
| 4765 | // This might not have gotten set in `semaFile` if the first time had | 4808 | // This might not have gotten set in `semaFile` if the first time had |
| 4766 | // a ZIR failure, so we set it here in case. | 4809 | // a ZIR failure, so we set it here in case. |
| 4767 | struct_obj.zir_index = main_struct_inst; | 4810 | struct_obj.zir_index = main_struct_inst; |
| 4768 | try sema.analyzeStructDecl(decl, main_struct_inst, struct_obj); | 4811 | try sema.analyzeStructDecl(decl, main_struct_inst, struct_index); |
| 4769 | decl.analysis = .complete; | 4812 | decl.analysis = .complete; |
| 4770 | decl.generation = mod.generation; | 4813 | decl.generation = mod.generation; |
| 4771 | return false; | 4814 | return false; |
| ... | @@ -5970,6 +6013,14 @@ pub fn destroyNamespace(mod: *Module, index: Namespace.Index) void { | ... | @@ -5970,6 +6013,14 @@ pub fn destroyNamespace(mod: *Module, index: Namespace.Index) void { |
| 5970 | }; | 6013 | }; |
| 5971 | } | 6014 | } |
| 5972 | 6015 | ||
| 6016 | pub fn createStruct(mod: *Module, initialization: Struct) Allocator.Error!Struct.Index { | ||
| 6017 | return mod.intern_pool.createStruct(mod.gpa, initialization); | ||
| 6018 | } | ||
| 6019 | |||
| 6020 | pub fn destroyStruct(mod: *Module, index: Struct.Index) void { | ||
| 6021 | return mod.intern_pool.destroyStruct(mod.gpa, index); | ||
| 6022 | } | ||
| 6023 | |||
| 5973 | pub fn allocateNewDecl( | 6024 | pub fn allocateNewDecl( |
| 5974 | mod: *Module, | 6025 | mod: *Module, |
| 5975 | namespace: Namespace.Index, | 6026 | namespace: Namespace.Index, |
| ... | @@ -7202,12 +7253,7 @@ pub fn atomicPtrAlignment( | ... | @@ -7202,12 +7253,7 @@ pub fn atomicPtrAlignment( |
| 7202 | } | 7253 | } |
| 7203 | 7254 | ||
| 7204 | pub fn opaqueSrcLoc(mod: *Module, opaque_type: InternPool.Key.OpaqueType) SrcLoc { | 7255 | pub fn opaqueSrcLoc(mod: *Module, opaque_type: InternPool.Key.OpaqueType) SrcLoc { |
| 7205 | const owner_decl = mod.declPtr(opaque_type.decl); | 7256 | return mod.declPtr(opaque_type.decl).srcLoc(mod); |
| 7206 | return .{ | ||
| 7207 | .file_scope = owner_decl.getFileScope(mod), | ||
| 7208 | .parent_decl_node = owner_decl.src_node, | ||
| 7209 | .lazy = LazySrcLoc.nodeOffset(0), | ||
| 7210 | }; | ||
| 7211 | } | 7257 | } |
| 7212 | 7258 | ||
| 7213 | pub fn opaqueFullyQualifiedName(mod: *Module, opaque_type: InternPool.Key.OpaqueType) ![:0]u8 { | 7259 | pub fn opaqueFullyQualifiedName(mod: *Module, opaque_type: InternPool.Key.OpaqueType) ![:0]u8 { |
| ... | @@ -7221,3 +7267,12 @@ pub fn declFileScope(mod: *Module, decl_index: Decl.Index) *File { | ... | @@ -7221,3 +7267,12 @@ pub fn declFileScope(mod: *Module, decl_index: Decl.Index) *File { |
| 7221 | pub fn namespaceDeclIndex(mod: *Module, namespace_index: Namespace.Index) Decl.Index { | 7267 | pub fn namespaceDeclIndex(mod: *Module, namespace_index: Namespace.Index) Decl.Index { |
| 7222 | return mod.namespacePtr(namespace_index).getDeclIndex(mod); | 7268 | return mod.namespacePtr(namespace_index).getDeclIndex(mod); |
| 7223 | } | 7269 | } |
| 7270 | |||
| 7271 | /// Returns null in the following cases: | ||
| 7272 | /// * `@TypeOf(.{})` | ||
| 7273 | /// * A struct which has no fields (`struct {}`). | ||
| 7274 | /// * Not a struct. | ||
| 7275 | pub fn typeToStruct(mod: *Module, ty: Type) ?*Struct { | ||
| 7276 | const struct_index = mod.intern_pool.indexToStruct(ty.ip_index).unwrap() orelse return null; | ||
| 7277 | return mod.structPtr(struct_index); | ||
| 7278 | } |
src/Sema.zig+349-293| ... | @@ -2090,16 +2090,17 @@ fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: | ... | @@ -2090,16 +2090,17 @@ fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: |
| 2090 | } | 2090 | } |
| 2091 | 2091 | ||
| 2092 | fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazySrcLoc, container_ty: Type, field_index: usize) CompileError { | 2092 | fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazySrcLoc, container_ty: Type, field_index: usize) CompileError { |
| 2093 | const mod = sema.mod; | ||
| 2093 | const msg = msg: { | 2094 | const msg = msg: { |
| 2094 | const msg = try sema.errMsg(block, init_src, "value stored in comptime field does not match the default value of the field", .{}); | 2095 | const msg = try sema.errMsg(block, init_src, "value stored in comptime field does not match the default value of the field", .{}); |
| 2095 | errdefer msg.destroy(sema.gpa); | 2096 | errdefer msg.destroy(sema.gpa); |
| 2096 | 2097 | ||
| 2097 | const struct_ty = container_ty.castTag(.@"struct") orelse break :msg msg; | 2098 | const struct_ty = mod.typeToStruct(container_ty) orelse break :msg msg; |
| 2098 | const default_value_src = struct_ty.data.fieldSrcLoc(sema.mod, .{ | 2099 | const default_value_src = struct_ty.fieldSrcLoc(mod, .{ |
| 2099 | .index = field_index, | 2100 | .index = field_index, |
| 2100 | .range = .value, | 2101 | .range = .value, |
| 2101 | }); | 2102 | }); |
| 2102 | try sema.mod.errNoteNonLazy(default_value_src, msg, "default value set here", .{}); | 2103 | try mod.errNoteNonLazy(default_value_src, msg, "default value set here", .{}); |
| 2103 | break :msg msg; | 2104 | break :msg msg; |
| 2104 | }; | 2105 | }; |
| 2105 | return sema.failWithOwnedErrorMsg(msg); | 2106 | return sema.failWithOwnedErrorMsg(msg); |
| ... | @@ -2632,8 +2633,10 @@ pub fn analyzeStructDecl( | ... | @@ -2632,8 +2633,10 @@ pub fn analyzeStructDecl( |
| 2632 | sema: *Sema, | 2633 | sema: *Sema, |
| 2633 | new_decl: *Decl, | 2634 | new_decl: *Decl, |
| 2634 | inst: Zir.Inst.Index, | 2635 | inst: Zir.Inst.Index, |
| 2635 | struct_obj: *Module.Struct, | 2636 | struct_index: Module.Struct.Index, |
| 2636 | ) SemaError!void { | 2637 | ) SemaError!void { |
| 2638 | const mod = sema.mod; | ||
| 2639 | const struct_obj = mod.structPtr(struct_index); | ||
| 2637 | const extended = sema.code.instructions.items(.data)[inst].extended; | 2640 | const extended = sema.code.instructions.items(.data)[inst].extended; |
| 2638 | assert(extended.opcode == .struct_decl); | 2641 | assert(extended.opcode == .struct_decl); |
| 2639 | const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small); | 2642 | const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small); |
| ... | @@ -2662,7 +2665,7 @@ pub fn analyzeStructDecl( | ... | @@ -2662,7 +2665,7 @@ pub fn analyzeStructDecl( |
| 2662 | } | 2665 | } |
| 2663 | } | 2666 | } |
| 2664 | 2667 | ||
| 2665 | _ = try sema.mod.scanNamespace(struct_obj.namespace, extra_index, decls_len, new_decl); | 2668 | _ = try mod.scanNamespace(struct_obj.namespace, extra_index, decls_len, new_decl); |
| 2666 | } | 2669 | } |
| 2667 | 2670 | ||
| 2668 | fn zirStructDecl( | 2671 | fn zirStructDecl( |
| ... | @@ -2671,28 +2674,38 @@ fn zirStructDecl( | ... | @@ -2671,28 +2674,38 @@ fn zirStructDecl( |
| 2671 | extended: Zir.Inst.Extended.InstData, | 2674 | extended: Zir.Inst.Extended.InstData, |
| 2672 | inst: Zir.Inst.Index, | 2675 | inst: Zir.Inst.Index, |
| 2673 | ) CompileError!Air.Inst.Ref { | 2676 | ) CompileError!Air.Inst.Ref { |
| 2677 | const mod = sema.mod; | ||
| 2678 | const gpa = sema.gpa; | ||
| 2674 | const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small); | 2679 | const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small); |
| 2675 | const src: LazySrcLoc = if (small.has_src_node) blk: { | 2680 | const src: LazySrcLoc = if (small.has_src_node) blk: { |
| 2676 | const node_offset = @bitCast(i32, sema.code.extra[extended.operand]); | 2681 | const node_offset = @bitCast(i32, sema.code.extra[extended.operand]); |
| 2677 | break :blk LazySrcLoc.nodeOffset(node_offset); | 2682 | break :blk LazySrcLoc.nodeOffset(node_offset); |
| 2678 | } else sema.src; | 2683 | } else sema.src; |
| 2679 | 2684 | ||
| 2680 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); | 2685 | var new_decl_arena = std.heap.ArenaAllocator.init(gpa); |
| 2681 | errdefer new_decl_arena.deinit(); | 2686 | errdefer new_decl_arena.deinit(); |
| 2682 | const new_decl_arena_allocator = new_decl_arena.allocator(); | ||
| 2683 | 2687 | ||
| 2684 | const mod = sema.mod; | 2688 | // Because these three things each reference each other, `undefined` |
| 2685 | const struct_obj = try new_decl_arena_allocator.create(Module.Struct); | 2689 | // placeholders are used before being set after the struct type gains an |
| 2686 | const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj); | 2690 | // InternPool index. |
| 2687 | const struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty); | 2691 | |
| 2688 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | 2692 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ |
| 2689 | .ty = Type.type, | 2693 | .ty = Type.type, |
| 2690 | .val = struct_val, | 2694 | .val = undefined, |
| 2691 | }, small.name_strategy, "struct", inst); | 2695 | }, small.name_strategy, "struct", inst); |
| 2692 | const new_decl = mod.declPtr(new_decl_index); | 2696 | const new_decl = mod.declPtr(new_decl_index); |
| 2693 | new_decl.owns_tv = true; | 2697 | new_decl.owns_tv = true; |
| 2694 | errdefer mod.abortAnonDecl(new_decl_index); | 2698 | errdefer mod.abortAnonDecl(new_decl_index); |
| 2695 | struct_obj.* = .{ | 2699 | |
| 2700 | const new_namespace_index = try mod.createNamespace(.{ | ||
| 2701 | .parent = block.namespace.toOptional(), | ||
| 2702 | .ty = undefined, | ||
| 2703 | .file_scope = block.getFileScope(mod), | ||
| 2704 | }); | ||
| 2705 | const new_namespace = mod.namespacePtr(new_namespace_index); | ||
| 2706 | errdefer mod.destroyNamespace(new_namespace_index); | ||
| 2707 | |||
| 2708 | const struct_index = try mod.createStruct(.{ | ||
| 2696 | .owner_decl = new_decl_index, | 2709 | .owner_decl = new_decl_index, |
| 2697 | .fields = .{}, | 2710 | .fields = .{}, |
| 2698 | .zir_index = inst, | 2711 | .zir_index = inst, |
| ... | @@ -2700,13 +2713,20 @@ fn zirStructDecl( | ... | @@ -2700,13 +2713,20 @@ fn zirStructDecl( |
| 2700 | .status = .none, | 2713 | .status = .none, |
| 2701 | .known_non_opv = undefined, | 2714 | .known_non_opv = undefined, |
| 2702 | .is_tuple = small.is_tuple, | 2715 | .is_tuple = small.is_tuple, |
| 2703 | .namespace = try mod.createNamespace(.{ | 2716 | .namespace = new_namespace_index, |
| 2704 | .parent = block.namespace.toOptional(), | 2717 | }); |
| 2705 | .ty = struct_ty, | 2718 | errdefer mod.destroyStruct(struct_index); |
| 2706 | .file_scope = block.getFileScope(mod), | 2719 | |
| 2707 | }), | 2720 | const struct_ty = try mod.intern_pool.get(gpa, .{ .struct_type = .{ |
| 2708 | }; | 2721 | .index = struct_index.toOptional(), |
| 2709 | try sema.analyzeStructDecl(new_decl, inst, struct_obj); | 2722 | .namespace = new_namespace_index.toOptional(), |
| 2723 | } }); | ||
| 2724 | errdefer mod.intern_pool.remove(struct_ty); | ||
| 2725 | |||
| 2726 | new_decl.val = struct_ty.toValue(); | ||
| 2727 | new_namespace.ty = struct_ty.toType(); | ||
| 2728 | |||
| 2729 | try sema.analyzeStructDecl(new_decl, inst, struct_index); | ||
| 2710 | try new_decl.finalizeNewArena(&new_decl_arena); | 2730 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 2711 | return sema.analyzeDeclVal(block, src, new_decl_index); | 2731 | return sema.analyzeDeclVal(block, src, new_decl_index); |
| 2712 | } | 2732 | } |
| ... | @@ -2721,6 +2741,7 @@ fn createAnonymousDeclTypeNamed( | ... | @@ -2721,6 +2741,7 @@ fn createAnonymousDeclTypeNamed( |
| 2721 | inst: ?Zir.Inst.Index, | 2741 | inst: ?Zir.Inst.Index, |
| 2722 | ) !Decl.Index { | 2742 | ) !Decl.Index { |
| 2723 | const mod = sema.mod; | 2743 | const mod = sema.mod; |
| 2744 | const gpa = sema.gpa; | ||
| 2724 | const namespace = block.namespace; | 2745 | const namespace = block.namespace; |
| 2725 | const src_scope = block.wip_capture_scope; | 2746 | const src_scope = block.wip_capture_scope; |
| 2726 | const src_decl = mod.declPtr(block.src_decl); | 2747 | const src_decl = mod.declPtr(block.src_decl); |
| ... | @@ -2736,16 +2757,16 @@ fn createAnonymousDeclTypeNamed( | ... | @@ -2736,16 +2757,16 @@ fn createAnonymousDeclTypeNamed( |
| 2736 | // semantically analyzed. | 2757 | // semantically analyzed. |
| 2737 | // This name is also used as the key in the parent namespace so it cannot be | 2758 | // This name is also used as the key in the parent namespace so it cannot be |
| 2738 | // renamed. | 2759 | // renamed. |
| 2739 | const name = try std.fmt.allocPrintZ(sema.gpa, "{s}__{s}_{d}", .{ | 2760 | const name = try std.fmt.allocPrintZ(gpa, "{s}__{s}_{d}", .{ |
| 2740 | src_decl.name, anon_prefix, @enumToInt(new_decl_index), | 2761 | src_decl.name, anon_prefix, @enumToInt(new_decl_index), |
| 2741 | }); | 2762 | }); |
| 2742 | errdefer sema.gpa.free(name); | 2763 | errdefer gpa.free(name); |
| 2743 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); | 2764 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); |
| 2744 | return new_decl_index; | 2765 | return new_decl_index; |
| 2745 | }, | 2766 | }, |
| 2746 | .parent => { | 2767 | .parent => { |
| 2747 | const name = try sema.gpa.dupeZ(u8, mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0)); | 2768 | const name = try gpa.dupeZ(u8, mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0)); |
| 2748 | errdefer sema.gpa.free(name); | 2769 | errdefer gpa.free(name); |
| 2749 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); | 2770 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); |
| 2750 | return new_decl_index; | 2771 | return new_decl_index; |
| 2751 | }, | 2772 | }, |
| ... | @@ -2753,7 +2774,7 @@ fn createAnonymousDeclTypeNamed( | ... | @@ -2753,7 +2774,7 @@ fn createAnonymousDeclTypeNamed( |
| 2753 | const fn_info = sema.code.getFnInfo(sema.func.?.zir_body_inst); | 2774 | const fn_info = sema.code.getFnInfo(sema.func.?.zir_body_inst); |
| 2754 | const zir_tags = sema.code.instructions.items(.tag); | 2775 | const zir_tags = sema.code.instructions.items(.tag); |
| 2755 | 2776 | ||
| 2756 | var buf = std.ArrayList(u8).init(sema.gpa); | 2777 | var buf = std.ArrayList(u8).init(gpa); |
| 2757 | defer buf.deinit(); | 2778 | defer buf.deinit(); |
| 2758 | try buf.appendSlice(mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0)); | 2779 | try buf.appendSlice(mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0)); |
| 2759 | try buf.appendSlice("("); | 2780 | try buf.appendSlice("("); |
| ... | @@ -2781,7 +2802,7 @@ fn createAnonymousDeclTypeNamed( | ... | @@ -2781,7 +2802,7 @@ fn createAnonymousDeclTypeNamed( |
| 2781 | 2802 | ||
| 2782 | try buf.appendSlice(")"); | 2803 | try buf.appendSlice(")"); |
| 2783 | const name = try buf.toOwnedSliceSentinel(0); | 2804 | const name = try buf.toOwnedSliceSentinel(0); |
| 2784 | errdefer sema.gpa.free(name); | 2805 | errdefer gpa.free(name); |
| 2785 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); | 2806 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); |
| 2786 | return new_decl_index; | 2807 | return new_decl_index; |
| 2787 | }, | 2808 | }, |
| ... | @@ -2794,10 +2815,10 @@ fn createAnonymousDeclTypeNamed( | ... | @@ -2794,10 +2815,10 @@ fn createAnonymousDeclTypeNamed( |
| 2794 | .dbg_var_ptr, .dbg_var_val => { | 2815 | .dbg_var_ptr, .dbg_var_val => { |
| 2795 | if (zir_data[i].str_op.operand != ref) continue; | 2816 | if (zir_data[i].str_op.operand != ref) continue; |
| 2796 | 2817 | ||
| 2797 | const name = try std.fmt.allocPrintZ(sema.gpa, "{s}.{s}", .{ | 2818 | const name = try std.fmt.allocPrintZ(gpa, "{s}.{s}", .{ |
| 2798 | src_decl.name, zir_data[i].str_op.getStr(sema.code), | 2819 | src_decl.name, zir_data[i].str_op.getStr(sema.code), |
| 2799 | }); | 2820 | }); |
| 2800 | errdefer sema.gpa.free(name); | 2821 | errdefer gpa.free(name); |
| 2801 | 2822 | ||
| 2802 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); | 2823 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); |
| 2803 | return new_decl_index; | 2824 | return new_decl_index; |
| ... | @@ -3216,13 +3237,13 @@ fn zirOpaqueDecl( | ... | @@ -3216,13 +3237,13 @@ fn zirOpaqueDecl( |
| 3216 | .file_scope = block.getFileScope(mod), | 3237 | .file_scope = block.getFileScope(mod), |
| 3217 | }); | 3238 | }); |
| 3218 | const new_namespace = mod.namespacePtr(new_namespace_index); | 3239 | const new_namespace = mod.namespacePtr(new_namespace_index); |
| 3219 | errdefer @panic("TODO error handling"); | 3240 | errdefer mod.destroyNamespace(new_namespace_index); |
| 3220 | 3241 | ||
| 3221 | const opaque_ty = try mod.intern_pool.get(gpa, .{ .opaque_type = .{ | 3242 | const opaque_ty = try mod.intern_pool.get(gpa, .{ .opaque_type = .{ |
| 3222 | .decl = new_decl_index, | 3243 | .decl = new_decl_index, |
| 3223 | .namespace = new_namespace_index, | 3244 | .namespace = new_namespace_index, |
| 3224 | } }); | 3245 | } }); |
| 3225 | errdefer @panic("TODO error handling"); | 3246 | errdefer mod.intern_pool.remove(opaque_ty); |
| 3226 | 3247 | ||
| 3227 | new_decl.val = opaque_ty.toValue(); | 3248 | new_decl.val = opaque_ty.toValue(); |
| 3228 | new_namespace.ty = opaque_ty.toType(); | 3249 | new_namespace.ty = opaque_ty.toType(); |
| ... | @@ -3960,7 +3981,7 @@ fn zirArrayBasePtr( | ... | @@ -3960,7 +3981,7 @@ fn zirArrayBasePtr( |
| 3960 | const elem_ty = sema.typeOf(base_ptr).childType(mod); | 3981 | const elem_ty = sema.typeOf(base_ptr).childType(mod); |
| 3961 | switch (elem_ty.zigTypeTag(mod)) { | 3982 | switch (elem_ty.zigTypeTag(mod)) { |
| 3962 | .Array, .Vector => return base_ptr, | 3983 | .Array, .Vector => return base_ptr, |
| 3963 | .Struct => if (elem_ty.isTuple()) { | 3984 | .Struct => if (elem_ty.isTuple(mod)) { |
| 3964 | // TODO validate element count | 3985 | // TODO validate element count |
| 3965 | return base_ptr; | 3986 | return base_ptr; |
| 3966 | }, | 3987 | }, |
| ... | @@ -4150,7 +4171,7 @@ fn validateArrayInitTy( | ... | @@ -4150,7 +4171,7 @@ fn validateArrayInitTy( |
| 4150 | } | 4171 | } |
| 4151 | return; | 4172 | return; |
| 4152 | }, | 4173 | }, |
| 4153 | .Struct => if (ty.isTuple()) { | 4174 | .Struct => if (ty.isTuple(mod)) { |
| 4154 | _ = try sema.resolveTypeFields(ty); | 4175 | _ = try sema.resolveTypeFields(ty); |
| 4155 | const array_len = ty.arrayLen(mod); | 4176 | const array_len = ty.arrayLen(mod); |
| 4156 | if (extra.init_count > array_len) { | 4177 | if (extra.init_count > array_len) { |
| ... | @@ -4358,7 +4379,7 @@ fn validateStructInit( | ... | @@ -4358,7 +4379,7 @@ fn validateStructInit( |
| 4358 | const gpa = sema.gpa; | 4379 | const gpa = sema.gpa; |
| 4359 | 4380 | ||
| 4360 | // Maps field index to field_ptr index of where it was already initialized. | 4381 | // Maps field index to field_ptr index of where it was already initialized. |
| 4361 | const found_fields = try gpa.alloc(Zir.Inst.Index, struct_ty.structFieldCount()); | 4382 | const found_fields = try gpa.alloc(Zir.Inst.Index, struct_ty.structFieldCount(mod)); |
| 4362 | defer gpa.free(found_fields); | 4383 | defer gpa.free(found_fields); |
| 4363 | @memset(found_fields, 0); | 4384 | @memset(found_fields, 0); |
| 4364 | 4385 | ||
| ... | @@ -4370,7 +4391,7 @@ fn validateStructInit( | ... | @@ -4370,7 +4391,7 @@ fn validateStructInit( |
| 4370 | const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data; | 4391 | const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data; |
| 4371 | struct_ptr_zir_ref = field_ptr_extra.lhs; | 4392 | struct_ptr_zir_ref = field_ptr_extra.lhs; |
| 4372 | const field_name = sema.code.nullTerminatedString(field_ptr_extra.field_name_start); | 4393 | const field_name = sema.code.nullTerminatedString(field_ptr_extra.field_name_start); |
| 4373 | const field_index = if (struct_ty.isTuple()) | 4394 | const field_index = if (struct_ty.isTuple(mod)) |
| 4374 | try sema.tupleFieldIndex(block, struct_ty, field_name, field_src) | 4395 | try sema.tupleFieldIndex(block, struct_ty, field_name, field_src) |
| 4375 | else | 4396 | else |
| 4376 | try sema.structFieldIndex(block, struct_ty, field_name, field_src); | 4397 | try sema.structFieldIndex(block, struct_ty, field_name, field_src); |
| ... | @@ -4403,9 +4424,9 @@ fn validateStructInit( | ... | @@ -4403,9 +4424,9 @@ fn validateStructInit( |
| 4403 | for (found_fields, 0..) |field_ptr, i| { | 4424 | for (found_fields, 0..) |field_ptr, i| { |
| 4404 | if (field_ptr != 0) continue; | 4425 | if (field_ptr != 0) continue; |
| 4405 | 4426 | ||
| 4406 | const default_val = struct_ty.structFieldDefaultValue(i); | 4427 | const default_val = struct_ty.structFieldDefaultValue(i, mod); |
| 4407 | if (default_val.ip_index == .unreachable_value) { | 4428 | if (default_val.ip_index == .unreachable_value) { |
| 4408 | if (struct_ty.isTuple()) { | 4429 | if (struct_ty.isTuple(mod)) { |
| 4409 | const template = "missing tuple field with index {d}"; | 4430 | const template = "missing tuple field with index {d}"; |
| 4410 | if (root_msg) |msg| { | 4431 | if (root_msg) |msg| { |
| 4411 | try sema.errNote(block, init_src, msg, template, .{i}); | 4432 | try sema.errNote(block, init_src, msg, template, .{i}); |
| ... | @@ -4414,7 +4435,7 @@ fn validateStructInit( | ... | @@ -4414,7 +4435,7 @@ fn validateStructInit( |
| 4414 | } | 4435 | } |
| 4415 | continue; | 4436 | continue; |
| 4416 | } | 4437 | } |
| 4417 | const field_name = struct_ty.structFieldName(i); | 4438 | const field_name = struct_ty.structFieldName(i, mod); |
| 4418 | const template = "missing struct field: {s}"; | 4439 | const template = "missing struct field: {s}"; |
| 4419 | const args = .{field_name}; | 4440 | const args = .{field_name}; |
| 4420 | if (root_msg) |msg| { | 4441 | if (root_msg) |msg| { |
| ... | @@ -4426,7 +4447,7 @@ fn validateStructInit( | ... | @@ -4426,7 +4447,7 @@ fn validateStructInit( |
| 4426 | } | 4447 | } |
| 4427 | 4448 | ||
| 4428 | const field_src = init_src; // TODO better source location | 4449 | const field_src = init_src; // TODO better source location |
| 4429 | const default_field_ptr = if (struct_ty.isTuple()) | 4450 | const default_field_ptr = if (struct_ty.isTuple(mod)) |
| 4430 | try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true) | 4451 | try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true) |
| 4431 | else | 4452 | else |
| 4432 | try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true); | 4453 | try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true); |
| ... | @@ -4436,11 +4457,11 @@ fn validateStructInit( | ... | @@ -4436,11 +4457,11 @@ fn validateStructInit( |
| 4436 | } | 4457 | } |
| 4437 | 4458 | ||
| 4438 | if (root_msg) |msg| { | 4459 | if (root_msg) |msg| { |
| 4439 | if (struct_ty.castTag(.@"struct")) |struct_obj| { | 4460 | if (mod.typeToStruct(struct_ty)) |struct_obj| { |
| 4440 | const fqn = try struct_obj.data.getFullyQualifiedName(mod); | 4461 | const fqn = try struct_obj.getFullyQualifiedName(mod); |
| 4441 | defer gpa.free(fqn); | 4462 | defer gpa.free(fqn); |
| 4442 | try mod.errNoteNonLazy( | 4463 | try mod.errNoteNonLazy( |
| 4443 | struct_obj.data.srcLoc(mod), | 4464 | struct_obj.srcLoc(mod), |
| 4444 | msg, | 4465 | msg, |
| 4445 | "struct '{s}' declared here", | 4466 | "struct '{s}' declared here", |
| 4446 | .{fqn}, | 4467 | .{fqn}, |
| ... | @@ -4463,12 +4484,12 @@ fn validateStructInit( | ... | @@ -4463,12 +4484,12 @@ fn validateStructInit( |
| 4463 | 4484 | ||
| 4464 | // We collect the comptime field values in case the struct initialization | 4485 | // We collect the comptime field values in case the struct initialization |
| 4465 | // ends up being comptime-known. | 4486 | // ends up being comptime-known. |
| 4466 | const field_values = try sema.arena.alloc(Value, struct_ty.structFieldCount()); | 4487 | const field_values = try sema.arena.alloc(Value, struct_ty.structFieldCount(mod)); |
| 4467 | 4488 | ||
| 4468 | field: for (found_fields, 0..) |field_ptr, i| { | 4489 | field: for (found_fields, 0..) |field_ptr, i| { |
| 4469 | if (field_ptr != 0) { | 4490 | if (field_ptr != 0) { |
| 4470 | // Determine whether the value stored to this pointer is comptime-known. | 4491 | // Determine whether the value stored to this pointer is comptime-known. |
| 4471 | const field_ty = struct_ty.structFieldType(i); | 4492 | const field_ty = struct_ty.structFieldType(i, mod); |
| 4472 | if (try sema.typeHasOnePossibleValue(field_ty)) |opv| { | 4493 | if (try sema.typeHasOnePossibleValue(field_ty)) |opv| { |
| 4473 | field_values[i] = opv; | 4494 | field_values[i] = opv; |
| 4474 | continue; | 4495 | continue; |
| ... | @@ -4548,9 +4569,9 @@ fn validateStructInit( | ... | @@ -4548,9 +4569,9 @@ fn validateStructInit( |
| 4548 | continue :field; | 4569 | continue :field; |
| 4549 | } | 4570 | } |
| 4550 | 4571 | ||
| 4551 | const default_val = struct_ty.structFieldDefaultValue(i); | 4572 | const default_val = struct_ty.structFieldDefaultValue(i, mod); |
| 4552 | if (default_val.ip_index == .unreachable_value) { | 4573 | if (default_val.ip_index == .unreachable_value) { |
| 4553 | if (struct_ty.isTuple()) { | 4574 | if (struct_ty.isTuple(mod)) { |
| 4554 | const template = "missing tuple field with index {d}"; | 4575 | const template = "missing tuple field with index {d}"; |
| 4555 | if (root_msg) |msg| { | 4576 | if (root_msg) |msg| { |
| 4556 | try sema.errNote(block, init_src, msg, template, .{i}); | 4577 | try sema.errNote(block, init_src, msg, template, .{i}); |
| ... | @@ -4559,7 +4580,7 @@ fn validateStructInit( | ... | @@ -4559,7 +4580,7 @@ fn validateStructInit( |
| 4559 | } | 4580 | } |
| 4560 | continue; | 4581 | continue; |
| 4561 | } | 4582 | } |
| 4562 | const field_name = struct_ty.structFieldName(i); | 4583 | const field_name = struct_ty.structFieldName(i, mod); |
| 4563 | const template = "missing struct field: {s}"; | 4584 | const template = "missing struct field: {s}"; |
| 4564 | const args = .{field_name}; | 4585 | const args = .{field_name}; |
| 4565 | if (root_msg) |msg| { | 4586 | if (root_msg) |msg| { |
| ... | @@ -4573,11 +4594,11 @@ fn validateStructInit( | ... | @@ -4573,11 +4594,11 @@ fn validateStructInit( |
| 4573 | } | 4594 | } |
| 4574 | 4595 | ||
| 4575 | if (root_msg) |msg| { | 4596 | if (root_msg) |msg| { |
| 4576 | if (struct_ty.castTag(.@"struct")) |struct_obj| { | 4597 | if (mod.typeToStruct(struct_ty)) |struct_obj| { |
| 4577 | const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod); | 4598 | const fqn = try struct_obj.getFullyQualifiedName(sema.mod); |
| 4578 | defer gpa.free(fqn); | 4599 | defer gpa.free(fqn); |
| 4579 | try sema.mod.errNoteNonLazy( | 4600 | try sema.mod.errNoteNonLazy( |
| 4580 | struct_obj.data.srcLoc(sema.mod), | 4601 | struct_obj.srcLoc(sema.mod), |
| 4581 | msg, | 4602 | msg, |
| 4582 | "struct '{s}' declared here", | 4603 | "struct '{s}' declared here", |
| 4583 | .{fqn}, | 4604 | .{fqn}, |
| ... | @@ -4605,7 +4626,7 @@ fn validateStructInit( | ... | @@ -4605,7 +4626,7 @@ fn validateStructInit( |
| 4605 | if (field_ptr != 0) continue; | 4626 | if (field_ptr != 0) continue; |
| 4606 | 4627 | ||
| 4607 | const field_src = init_src; // TODO better source location | 4628 | const field_src = init_src; // TODO better source location |
| 4608 | const default_field_ptr = if (struct_ty.isTuple()) | 4629 | const default_field_ptr = if (struct_ty.isTuple(mod)) |
| 4609 | try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true) | 4630 | try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true) |
| 4610 | else | 4631 | else |
| 4611 | try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true); | 4632 | try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true); |
| ... | @@ -4638,7 +4659,7 @@ fn zirValidateArrayInit( | ... | @@ -4638,7 +4659,7 @@ fn zirValidateArrayInit( |
| 4638 | 4659 | ||
| 4639 | var i = instrs.len; | 4660 | var i = instrs.len; |
| 4640 | while (i < array_len) : (i += 1) { | 4661 | while (i < array_len) : (i += 1) { |
| 4641 | const default_val = array_ty.structFieldDefaultValue(i); | 4662 | const default_val = array_ty.structFieldDefaultValue(i, mod); |
| 4642 | if (default_val.ip_index == .unreachable_value) { | 4663 | if (default_val.ip_index == .unreachable_value) { |
| 4643 | const template = "missing tuple field with index {d}"; | 4664 | const template = "missing tuple field with index {d}"; |
| 4644 | if (root_msg) |msg| { | 4665 | if (root_msg) |msg| { |
| ... | @@ -4698,7 +4719,7 @@ fn zirValidateArrayInit( | ... | @@ -4698,7 +4719,7 @@ fn zirValidateArrayInit( |
| 4698 | outer: for (instrs, 0..) |elem_ptr, i| { | 4719 | outer: for (instrs, 0..) |elem_ptr, i| { |
| 4699 | // Determine whether the value stored to this pointer is comptime-known. | 4720 | // Determine whether the value stored to this pointer is comptime-known. |
| 4700 | 4721 | ||
| 4701 | if (array_ty.isTuple()) { | 4722 | if (array_ty.isTuple(mod)) { |
| 4702 | if (try array_ty.structFieldValueComptime(mod, i)) |opv| { | 4723 | if (try array_ty.structFieldValueComptime(mod, i)) |opv| { |
| 4703 | element_vals[i] = opv; | 4724 | element_vals[i] = opv; |
| 4704 | continue; | 4725 | continue; |
| ... | @@ -7950,7 +7971,7 @@ fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr | ... | @@ -7950,7 +7971,7 @@ fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 7950 | const indexable_ty = try sema.resolveType(block, .unneeded, bin.lhs); | 7971 | const indexable_ty = try sema.resolveType(block, .unneeded, bin.lhs); |
| 7951 | assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction | 7972 | assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction |
| 7952 | if (indexable_ty.zigTypeTag(mod) == .Struct) { | 7973 | if (indexable_ty.zigTypeTag(mod) == .Struct) { |
| 7953 | const elem_type = indexable_ty.structFieldType(@enumToInt(bin.rhs)); | 7974 | const elem_type = indexable_ty.structFieldType(@enumToInt(bin.rhs), mod); |
| 7954 | return sema.addType(elem_type); | 7975 | return sema.addType(elem_type); |
| 7955 | } else { | 7976 | } else { |
| 7956 | const elem_type = indexable_ty.elemType2(mod); | 7977 | const elem_type = indexable_ty.elemType2(mod); |
| ... | @@ -9822,7 +9843,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -9822,7 +9843,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9822 | }; | 9843 | }; |
| 9823 | return sema.failWithOwnedErrorMsg(msg); | 9844 | return sema.failWithOwnedErrorMsg(msg); |
| 9824 | }, | 9845 | }, |
| 9825 | .Struct, .Union => if (dest_ty.containerLayout() == .Auto) { | 9846 | .Struct, .Union => if (dest_ty.containerLayout(mod) == .Auto) { |
| 9826 | const container = switch (dest_ty.zigTypeTag(mod)) { | 9847 | const container = switch (dest_ty.zigTypeTag(mod)) { |
| 9827 | .Struct => "struct", | 9848 | .Struct => "struct", |
| 9828 | .Union => "union", | 9849 | .Union => "union", |
| ... | @@ -9885,7 +9906,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -9885,7 +9906,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9885 | }; | 9906 | }; |
| 9886 | return sema.failWithOwnedErrorMsg(msg); | 9907 | return sema.failWithOwnedErrorMsg(msg); |
| 9887 | }, | 9908 | }, |
| 9888 | .Struct, .Union => if (operand_ty.containerLayout() == .Auto) { | 9909 | .Struct, .Union => if (operand_ty.containerLayout(mod) == .Auto) { |
| 9889 | const container = switch (operand_ty.zigTypeTag(mod)) { | 9910 | const container = switch (operand_ty.zigTypeTag(mod)) { |
| 9890 | .Struct => "struct", | 9911 | .Struct => "struct", |
| 9891 | .Union => "union", | 9912 | .Union => "union", |
| ... | @@ -12041,12 +12062,12 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12041,12 +12062,12 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12041 | if (mem.eql(u8, name, field_name)) break true; | 12062 | if (mem.eql(u8, name, field_name)) break true; |
| 12042 | } else false; | 12063 | } else false; |
| 12043 | } | 12064 | } |
| 12044 | if (ty.isTuple()) { | 12065 | if (ty.isTuple(mod)) { |
| 12045 | const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch break :hf false; | 12066 | const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch break :hf false; |
| 12046 | break :hf field_index < ty.structFieldCount(); | 12067 | break :hf field_index < ty.structFieldCount(mod); |
| 12047 | } | 12068 | } |
| 12048 | break :hf switch (ty.zigTypeTag(mod)) { | 12069 | break :hf switch (ty.zigTypeTag(mod)) { |
| 12049 | .Struct => ty.structFields().contains(field_name), | 12070 | .Struct => ty.structFields(mod).contains(field_name), |
| 12050 | .Union => ty.unionFields().contains(field_name), | 12071 | .Union => ty.unionFields().contains(field_name), |
| 12051 | .Enum => ty.enumFields().contains(field_name), | 12072 | .Enum => ty.enumFields().contains(field_name), |
| 12052 | .Array => mem.eql(u8, field_name, "len"), | 12073 | .Array => mem.eql(u8, field_name, "len"), |
| ... | @@ -12601,14 +12622,15 @@ fn analyzeTupleCat( | ... | @@ -12601,14 +12622,15 @@ fn analyzeTupleCat( |
| 12601 | lhs: Air.Inst.Ref, | 12622 | lhs: Air.Inst.Ref, |
| 12602 | rhs: Air.Inst.Ref, | 12623 | rhs: Air.Inst.Ref, |
| 12603 | ) CompileError!Air.Inst.Ref { | 12624 | ) CompileError!Air.Inst.Ref { |
| 12625 | const mod = sema.mod; | ||
| 12604 | const lhs_ty = sema.typeOf(lhs); | 12626 | const lhs_ty = sema.typeOf(lhs); |
| 12605 | const rhs_ty = sema.typeOf(rhs); | 12627 | const rhs_ty = sema.typeOf(rhs); |
| 12606 | const src = LazySrcLoc.nodeOffset(src_node); | 12628 | const src = LazySrcLoc.nodeOffset(src_node); |
| 12607 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node }; | 12629 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node }; |
| 12608 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node }; | 12630 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node }; |
| 12609 | 12631 | ||
| 12610 | const lhs_len = lhs_ty.structFieldCount(); | 12632 | const lhs_len = lhs_ty.structFieldCount(mod); |
| 12611 | const rhs_len = rhs_ty.structFieldCount(); | 12633 | const rhs_len = rhs_ty.structFieldCount(mod); |
| 12612 | const dest_fields = lhs_len + rhs_len; | 12634 | const dest_fields = lhs_len + rhs_len; |
| 12613 | 12635 | ||
| 12614 | if (dest_fields == 0) { | 12636 | if (dest_fields == 0) { |
| ... | @@ -12629,8 +12651,8 @@ fn analyzeTupleCat( | ... | @@ -12629,8 +12651,8 @@ fn analyzeTupleCat( |
| 12629 | var runtime_src: ?LazySrcLoc = null; | 12651 | var runtime_src: ?LazySrcLoc = null; |
| 12630 | var i: u32 = 0; | 12652 | var i: u32 = 0; |
| 12631 | while (i < lhs_len) : (i += 1) { | 12653 | while (i < lhs_len) : (i += 1) { |
| 12632 | types[i] = lhs_ty.structFieldType(i); | 12654 | types[i] = lhs_ty.structFieldType(i, mod); |
| 12633 | const default_val = lhs_ty.structFieldDefaultValue(i); | 12655 | const default_val = lhs_ty.structFieldDefaultValue(i, mod); |
| 12634 | values[i] = default_val; | 12656 | values[i] = default_val; |
| 12635 | const operand_src = lhs_src; // TODO better source location | 12657 | const operand_src = lhs_src; // TODO better source location |
| 12636 | if (default_val.ip_index == .unreachable_value) { | 12658 | if (default_val.ip_index == .unreachable_value) { |
| ... | @@ -12639,8 +12661,8 @@ fn analyzeTupleCat( | ... | @@ -12639,8 +12661,8 @@ fn analyzeTupleCat( |
| 12639 | } | 12661 | } |
| 12640 | i = 0; | 12662 | i = 0; |
| 12641 | while (i < rhs_len) : (i += 1) { | 12663 | while (i < rhs_len) : (i += 1) { |
| 12642 | types[i + lhs_len] = rhs_ty.structFieldType(i); | 12664 | types[i + lhs_len] = rhs_ty.structFieldType(i, mod); |
| 12643 | const default_val = rhs_ty.structFieldDefaultValue(i); | 12665 | const default_val = rhs_ty.structFieldDefaultValue(i, mod); |
| 12644 | values[i + lhs_len] = default_val; | 12666 | values[i + lhs_len] = default_val; |
| 12645 | const operand_src = rhs_src; // TODO better source location | 12667 | const operand_src = rhs_src; // TODO better source location |
| 12646 | if (default_val.ip_index == .unreachable_value) { | 12668 | if (default_val.ip_index == .unreachable_value) { |
| ... | @@ -12691,8 +12713,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12691,8 +12713,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12691 | const rhs_ty = sema.typeOf(rhs); | 12713 | const rhs_ty = sema.typeOf(rhs); |
| 12692 | const src = inst_data.src(); | 12714 | const src = inst_data.src(); |
| 12693 | 12715 | ||
| 12694 | const lhs_is_tuple = lhs_ty.isTuple(); | 12716 | const lhs_is_tuple = lhs_ty.isTuple(mod); |
| 12695 | const rhs_is_tuple = rhs_ty.isTuple(); | 12717 | const rhs_is_tuple = rhs_ty.isTuple(mod); |
| 12696 | if (lhs_is_tuple and rhs_is_tuple) { | 12718 | if (lhs_is_tuple and rhs_is_tuple) { |
| 12697 | return sema.analyzeTupleCat(block, inst_data.src_node, lhs, rhs); | 12719 | return sema.analyzeTupleCat(block, inst_data.src_node, lhs, rhs); |
| 12698 | } | 12720 | } |
| ... | @@ -12800,8 +12822,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12800,8 +12822,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12800 | var elem_i: usize = 0; | 12822 | var elem_i: usize = 0; |
| 12801 | while (elem_i < lhs_len) : (elem_i += 1) { | 12823 | while (elem_i < lhs_len) : (elem_i += 1) { |
| 12802 | const lhs_elem_i = elem_i; | 12824 | const lhs_elem_i = elem_i; |
| 12803 | const elem_ty = if (lhs_is_tuple) lhs_ty.structFieldType(lhs_elem_i) else lhs_info.elem_type; | 12825 | const elem_ty = if (lhs_is_tuple) lhs_ty.structFieldType(lhs_elem_i, mod) else lhs_info.elem_type; |
| 12804 | const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i) else Value.@"unreachable"; | 12826 | const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, mod) else Value.@"unreachable"; |
| 12805 | const elem_val = if (elem_default_val.ip_index == .unreachable_value) try lhs_sub_val.elemValue(mod, lhs_elem_i) else elem_default_val; | 12827 | const elem_val = if (elem_default_val.ip_index == .unreachable_value) try lhs_sub_val.elemValue(mod, lhs_elem_i) else elem_default_val; |
| 12806 | const elem_val_inst = try sema.addConstant(elem_ty, elem_val); | 12828 | const elem_val_inst = try sema.addConstant(elem_ty, elem_val); |
| 12807 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded); | 12829 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded); |
| ... | @@ -12810,8 +12832,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12810,8 +12832,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12810 | } | 12832 | } |
| 12811 | while (elem_i < result_len) : (elem_i += 1) { | 12833 | while (elem_i < result_len) : (elem_i += 1) { |
| 12812 | const rhs_elem_i = elem_i - lhs_len; | 12834 | const rhs_elem_i = elem_i - lhs_len; |
| 12813 | const elem_ty = if (rhs_is_tuple) rhs_ty.structFieldType(rhs_elem_i) else rhs_info.elem_type; | 12835 | const elem_ty = if (rhs_is_tuple) rhs_ty.structFieldType(rhs_elem_i, mod) else rhs_info.elem_type; |
| 12814 | const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i) else Value.@"unreachable"; | 12836 | const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, mod) else Value.@"unreachable"; |
| 12815 | const elem_val = if (elem_default_val.ip_index == .unreachable_value) try rhs_sub_val.elemValue(mod, rhs_elem_i) else elem_default_val; | 12837 | const elem_val = if (elem_default_val.ip_index == .unreachable_value) try rhs_sub_val.elemValue(mod, rhs_elem_i) else elem_default_val; |
| 12816 | const elem_val_inst = try sema.addConstant(elem_ty, elem_val); | 12838 | const elem_val_inst = try sema.addConstant(elem_ty, elem_val); |
| 12817 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded); | 12839 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded); |
| ... | @@ -12909,8 +12931,8 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins | ... | @@ -12909,8 +12931,8 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins |
| 12909 | } | 12931 | } |
| 12910 | }, | 12932 | }, |
| 12911 | .Struct => { | 12933 | .Struct => { |
| 12912 | if (operand_ty.isTuple() and peer_ty.isIndexable(mod)) { | 12934 | if (operand_ty.isTuple(mod) and peer_ty.isIndexable(mod)) { |
| 12913 | assert(!peer_ty.isTuple()); | 12935 | assert(!peer_ty.isTuple(mod)); |
| 12914 | return .{ | 12936 | return .{ |
| 12915 | .elem_type = peer_ty.elemType2(mod), | 12937 | .elem_type = peer_ty.elemType2(mod), |
| 12916 | .sentinel = null, | 12938 | .sentinel = null, |
| ... | @@ -12930,12 +12952,13 @@ fn analyzeTupleMul( | ... | @@ -12930,12 +12952,13 @@ fn analyzeTupleMul( |
| 12930 | operand: Air.Inst.Ref, | 12952 | operand: Air.Inst.Ref, |
| 12931 | factor: u64, | 12953 | factor: u64, |
| 12932 | ) CompileError!Air.Inst.Ref { | 12954 | ) CompileError!Air.Inst.Ref { |
| 12955 | const mod = sema.mod; | ||
| 12933 | const operand_ty = sema.typeOf(operand); | 12956 | const operand_ty = sema.typeOf(operand); |
| 12934 | const src = LazySrcLoc.nodeOffset(src_node); | 12957 | const src = LazySrcLoc.nodeOffset(src_node); |
| 12935 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node }; | 12958 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node }; |
| 12936 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node }; | 12959 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node }; |
| 12937 | 12960 | ||
| 12938 | const tuple_len = operand_ty.structFieldCount(); | 12961 | const tuple_len = operand_ty.structFieldCount(mod); |
| 12939 | const final_len_u64 = std.math.mul(u64, tuple_len, factor) catch | 12962 | const final_len_u64 = std.math.mul(u64, tuple_len, factor) catch |
| 12940 | return sema.fail(block, rhs_src, "operation results in overflow", .{}); | 12963 | return sema.fail(block, rhs_src, "operation results in overflow", .{}); |
| 12941 | 12964 | ||
| ... | @@ -12951,8 +12974,8 @@ fn analyzeTupleMul( | ... | @@ -12951,8 +12974,8 @@ fn analyzeTupleMul( |
| 12951 | var runtime_src: ?LazySrcLoc = null; | 12974 | var runtime_src: ?LazySrcLoc = null; |
| 12952 | var i: u32 = 0; | 12975 | var i: u32 = 0; |
| 12953 | while (i < tuple_len) : (i += 1) { | 12976 | while (i < tuple_len) : (i += 1) { |
| 12954 | types[i] = operand_ty.structFieldType(i); | 12977 | types[i] = operand_ty.structFieldType(i, mod); |
| 12955 | values[i] = operand_ty.structFieldDefaultValue(i); | 12978 | values[i] = operand_ty.structFieldDefaultValue(i, mod); |
| 12956 | const operand_src = lhs_src; // TODO better source location | 12979 | const operand_src = lhs_src; // TODO better source location |
| 12957 | if (values[i].ip_index == .unreachable_value) { | 12980 | if (values[i].ip_index == .unreachable_value) { |
| 12958 | runtime_src = operand_src; | 12981 | runtime_src = operand_src; |
| ... | @@ -13006,7 +13029,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -13006,7 +13029,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13006 | const operator_src: LazySrcLoc = .{ .node_offset_main_token = inst_data.src_node }; | 13029 | const operator_src: LazySrcLoc = .{ .node_offset_main_token = inst_data.src_node }; |
| 13007 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; | 13030 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; |
| 13008 | 13031 | ||
| 13009 | if (lhs_ty.isTuple()) { | 13032 | if (lhs_ty.isTuple(mod)) { |
| 13010 | // In `**` rhs must be comptime-known, but lhs can be runtime-known | 13033 | // In `**` rhs must be comptime-known, but lhs can be runtime-known |
| 13011 | const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize, "array multiplication factor must be comptime-known"); | 13034 | const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize, "array multiplication factor must be comptime-known"); |
| 13012 | return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor); | 13035 | return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor); |
| ... | @@ -14502,7 +14525,7 @@ fn zirOverflowArithmetic( | ... | @@ -14502,7 +14525,7 @@ fn zirOverflowArithmetic( |
| 14502 | 14525 | ||
| 14503 | const element_refs = try sema.arena.alloc(Air.Inst.Ref, 2); | 14526 | const element_refs = try sema.arena.alloc(Air.Inst.Ref, 2); |
| 14504 | element_refs[0] = result.inst; | 14527 | element_refs[0] = result.inst; |
| 14505 | element_refs[1] = try sema.addConstant(tuple_ty.structFieldType(1), result.overflow_bit); | 14528 | element_refs[1] = try sema.addConstant(tuple_ty.structFieldType(1, mod), result.overflow_bit); |
| 14506 | return block.addAggregateInit(tuple_ty, element_refs); | 14529 | return block.addAggregateInit(tuple_ty, element_refs); |
| 14507 | } | 14530 | } |
| 14508 | 14531 | ||
| ... | @@ -16378,7 +16401,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16378,7 +16401,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16378 | 16401 | ||
| 16379 | const union_ty = try sema.resolveTypeFields(ty); | 16402 | const union_ty = try sema.resolveTypeFields(ty); |
| 16380 | try sema.resolveTypeLayout(ty); // Getting alignment requires type layout | 16403 | try sema.resolveTypeLayout(ty); // Getting alignment requires type layout |
| 16381 | const layout = union_ty.containerLayout(); | 16404 | const layout = union_ty.containerLayout(mod); |
| 16382 | 16405 | ||
| 16383 | const union_fields = union_ty.unionFields(); | 16406 | const union_fields = union_ty.unionFields(); |
| 16384 | const union_field_vals = try fields_anon_decl.arena().alloc(Value, union_fields.count()); | 16407 | const union_field_vals = try fields_anon_decl.arena().alloc(Value, union_fields.count()); |
| ... | @@ -16484,7 +16507,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16484,7 +16507,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16484 | }; | 16507 | }; |
| 16485 | const struct_ty = try sema.resolveTypeFields(ty); | 16508 | const struct_ty = try sema.resolveTypeFields(ty); |
| 16486 | try sema.resolveTypeLayout(ty); // Getting alignment requires type layout | 16509 | try sema.resolveTypeLayout(ty); // Getting alignment requires type layout |
| 16487 | const layout = struct_ty.containerLayout(); | 16510 | const layout = struct_ty.containerLayout(mod); |
| 16488 | 16511 | ||
| 16489 | const struct_field_vals = fv: { | 16512 | const struct_field_vals = fv: { |
| 16490 | if (struct_ty.isSimpleTupleOrAnonStruct()) { | 16513 | if (struct_ty.isSimpleTupleOrAnonStruct()) { |
| ... | @@ -16532,7 +16555,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16532,7 +16555,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16532 | } | 16555 | } |
| 16533 | break :fv struct_field_vals; | 16556 | break :fv struct_field_vals; |
| 16534 | } | 16557 | } |
| 16535 | const struct_fields = struct_ty.structFields(); | 16558 | const struct_fields = struct_ty.structFields(mod); |
| 16536 | const struct_field_vals = try fields_anon_decl.arena().alloc(Value, struct_fields.count()); | 16559 | const struct_field_vals = try fields_anon_decl.arena().alloc(Value, struct_fields.count()); |
| 16537 | 16560 | ||
| 16538 | for (struct_field_vals, 0..) |*field_val, i| { | 16561 | for (struct_field_vals, 0..) |*field_val, i| { |
| ... | @@ -16600,7 +16623,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16600,7 +16623,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16600 | 16623 | ||
| 16601 | const backing_integer_val = blk: { | 16624 | const backing_integer_val = blk: { |
| 16602 | if (layout == .Packed) { | 16625 | if (layout == .Packed) { |
| 16603 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | 16626 | const struct_obj = mod.typeToStruct(struct_ty).?; |
| 16604 | assert(struct_obj.haveLayout()); | 16627 | assert(struct_obj.haveLayout()); |
| 16605 | assert(struct_obj.backing_int_ty.isInt(mod)); | 16628 | assert(struct_obj.backing_int_ty.isInt(mod)); |
| 16606 | const backing_int_ty_val = try Value.Tag.ty.create(sema.arena, struct_obj.backing_int_ty); | 16629 | const backing_int_ty_val = try Value.Tag.ty.create(sema.arena, struct_obj.backing_int_ty); |
| ... | @@ -16624,7 +16647,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16624,7 +16647,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16624 | // decls: []const Declaration, | 16647 | // decls: []const Declaration, |
| 16625 | decls_val, | 16648 | decls_val, |
| 16626 | // is_tuple: bool, | 16649 | // is_tuple: bool, |
| 16627 | Value.makeBool(struct_ty.isTuple()), | 16650 | Value.makeBool(struct_ty.isTuple(mod)), |
| 16628 | }; | 16651 | }; |
| 16629 | 16652 | ||
| 16630 | return sema.addConstant( | 16653 | return sema.addConstant( |
| ... | @@ -17801,12 +17824,13 @@ fn structInitEmpty( | ... | @@ -17801,12 +17824,13 @@ fn structInitEmpty( |
| 17801 | dest_src: LazySrcLoc, | 17824 | dest_src: LazySrcLoc, |
| 17802 | init_src: LazySrcLoc, | 17825 | init_src: LazySrcLoc, |
| 17803 | ) CompileError!Air.Inst.Ref { | 17826 | ) CompileError!Air.Inst.Ref { |
| 17827 | const mod = sema.mod; | ||
| 17804 | const gpa = sema.gpa; | 17828 | const gpa = sema.gpa; |
| 17805 | // This logic must be synchronized with that in `zirStructInit`. | 17829 | // This logic must be synchronized with that in `zirStructInit`. |
| 17806 | const struct_ty = try sema.resolveTypeFields(obj_ty); | 17830 | const struct_ty = try sema.resolveTypeFields(obj_ty); |
| 17807 | 17831 | ||
| 17808 | // The init values to use for the struct instance. | 17832 | // The init values to use for the struct instance. |
| 17809 | const field_inits = try gpa.alloc(Air.Inst.Ref, struct_ty.structFieldCount()); | 17833 | const field_inits = try gpa.alloc(Air.Inst.Ref, struct_ty.structFieldCount(mod)); |
| 17810 | defer gpa.free(field_inits); | 17834 | defer gpa.free(field_inits); |
| 17811 | @memset(field_inits, .none); | 17835 | @memset(field_inits, .none); |
| 17812 | 17836 | ||
| ... | @@ -17897,18 +17921,18 @@ fn zirStructInit( | ... | @@ -17897,18 +17921,18 @@ fn zirStructInit( |
| 17897 | 17921 | ||
| 17898 | // Maps field index to field_type index of where it was already initialized. | 17922 | // Maps field index to field_type index of where it was already initialized. |
| 17899 | // For making sure all fields are accounted for and no fields are duplicated. | 17923 | // For making sure all fields are accounted for and no fields are duplicated. |
| 17900 | const found_fields = try gpa.alloc(Zir.Inst.Index, resolved_ty.structFieldCount()); | 17924 | const found_fields = try gpa.alloc(Zir.Inst.Index, resolved_ty.structFieldCount(mod)); |
| 17901 | defer gpa.free(found_fields); | 17925 | defer gpa.free(found_fields); |
| 17902 | 17926 | ||
| 17903 | // The init values to use for the struct instance. | 17927 | // The init values to use for the struct instance. |
| 17904 | const field_inits = try gpa.alloc(Air.Inst.Ref, resolved_ty.structFieldCount()); | 17928 | const field_inits = try gpa.alloc(Air.Inst.Ref, resolved_ty.structFieldCount(mod)); |
| 17905 | defer gpa.free(field_inits); | 17929 | defer gpa.free(field_inits); |
| 17906 | @memset(field_inits, .none); | 17930 | @memset(field_inits, .none); |
| 17907 | 17931 | ||
| 17908 | var field_i: u32 = 0; | 17932 | var field_i: u32 = 0; |
| 17909 | var extra_index = extra.end; | 17933 | var extra_index = extra.end; |
| 17910 | 17934 | ||
| 17911 | const is_packed = resolved_ty.containerLayout() == .Packed; | 17935 | const is_packed = resolved_ty.containerLayout(mod) == .Packed; |
| 17912 | while (field_i < extra.data.fields_len) : (field_i += 1) { | 17936 | while (field_i < extra.data.fields_len) : (field_i += 1) { |
| 17913 | const item = sema.code.extraData(Zir.Inst.StructInit.Item, extra_index); | 17937 | const item = sema.code.extraData(Zir.Inst.StructInit.Item, extra_index); |
| 17914 | extra_index = item.end; | 17938 | extra_index = item.end; |
| ... | @@ -17917,7 +17941,7 @@ fn zirStructInit( | ... | @@ -17917,7 +17941,7 @@ fn zirStructInit( |
| 17917 | const field_src: LazySrcLoc = .{ .node_offset_initializer = field_type_data.src_node }; | 17941 | const field_src: LazySrcLoc = .{ .node_offset_initializer = field_type_data.src_node }; |
| 17918 | const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data; | 17942 | const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data; |
| 17919 | const field_name = sema.code.nullTerminatedString(field_type_extra.name_start); | 17943 | const field_name = sema.code.nullTerminatedString(field_type_extra.name_start); |
| 17920 | const field_index = if (resolved_ty.isTuple()) | 17944 | const field_index = if (resolved_ty.isTuple(mod)) |
| 17921 | try sema.tupleFieldIndex(block, resolved_ty, field_name, field_src) | 17945 | try sema.tupleFieldIndex(block, resolved_ty, field_name, field_src) |
| 17922 | else | 17946 | else |
| 17923 | try sema.structFieldIndex(block, resolved_ty, field_name, field_src); | 17947 | try sema.structFieldIndex(block, resolved_ty, field_name, field_src); |
| ... | @@ -17940,7 +17964,7 @@ fn zirStructInit( | ... | @@ -17940,7 +17964,7 @@ fn zirStructInit( |
| 17940 | return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known"); | 17964 | return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known"); |
| 17941 | }; | 17965 | }; |
| 17942 | 17966 | ||
| 17943 | if (!init_val.eql(default_value, resolved_ty.structFieldType(field_index), sema.mod)) { | 17967 | if (!init_val.eql(default_value, resolved_ty.structFieldType(field_index, mod), sema.mod)) { |
| 17944 | return sema.failWithInvalidComptimeFieldStore(block, field_src, resolved_ty, field_index); | 17968 | return sema.failWithInvalidComptimeFieldStore(block, field_src, resolved_ty, field_index); |
| 17945 | } | 17969 | } |
| 17946 | }; | 17970 | }; |
| ... | @@ -18029,13 +18053,13 @@ fn finishStructInit( | ... | @@ -18029,13 +18053,13 @@ fn finishStructInit( |
| 18029 | field_inits[i] = try sema.addConstant(struct_obj.types[i], default_val); | 18053 | field_inits[i] = try sema.addConstant(struct_obj.types[i], default_val); |
| 18030 | } | 18054 | } |
| 18031 | } | 18055 | } |
| 18032 | } else if (struct_ty.isTuple()) { | 18056 | } else if (struct_ty.isTuple(mod)) { |
| 18033 | var i: u32 = 0; | 18057 | var i: u32 = 0; |
| 18034 | const len = struct_ty.structFieldCount(); | 18058 | const len = struct_ty.structFieldCount(mod); |
| 18035 | while (i < len) : (i += 1) { | 18059 | while (i < len) : (i += 1) { |
| 18036 | if (field_inits[i] != .none) continue; | 18060 | if (field_inits[i] != .none) continue; |
| 18037 | 18061 | ||
| 18038 | const default_val = struct_ty.structFieldDefaultValue(i); | 18062 | const default_val = struct_ty.structFieldDefaultValue(i, mod); |
| 18039 | if (default_val.ip_index == .unreachable_value) { | 18063 | if (default_val.ip_index == .unreachable_value) { |
| 18040 | const template = "missing tuple field with index {d}"; | 18064 | const template = "missing tuple field with index {d}"; |
| 18041 | if (root_msg) |msg| { | 18065 | if (root_msg) |msg| { |
| ... | @@ -18044,11 +18068,11 @@ fn finishStructInit( | ... | @@ -18044,11 +18068,11 @@ fn finishStructInit( |
| 18044 | root_msg = try sema.errMsg(block, init_src, template, .{i}); | 18068 | root_msg = try sema.errMsg(block, init_src, template, .{i}); |
| 18045 | } | 18069 | } |
| 18046 | } else { | 18070 | } else { |
| 18047 | field_inits[i] = try sema.addConstant(struct_ty.structFieldType(i), default_val); | 18071 | field_inits[i] = try sema.addConstant(struct_ty.structFieldType(i, mod), default_val); |
| 18048 | } | 18072 | } |
| 18049 | } | 18073 | } |
| 18050 | } else { | 18074 | } else { |
| 18051 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | 18075 | const struct_obj = mod.typeToStruct(struct_ty).?; |
| 18052 | for (struct_obj.fields.values(), 0..) |field, i| { | 18076 | for (struct_obj.fields.values(), 0..) |field, i| { |
| 18053 | if (field_inits[i] != .none) continue; | 18077 | if (field_inits[i] != .none) continue; |
| 18054 | 18078 | ||
| ... | @@ -18068,11 +18092,11 @@ fn finishStructInit( | ... | @@ -18068,11 +18092,11 @@ fn finishStructInit( |
| 18068 | } | 18092 | } |
| 18069 | 18093 | ||
| 18070 | if (root_msg) |msg| { | 18094 | if (root_msg) |msg| { |
| 18071 | if (struct_ty.castTag(.@"struct")) |struct_obj| { | 18095 | if (mod.typeToStruct(struct_ty)) |struct_obj| { |
| 18072 | const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod); | 18096 | const fqn = try struct_obj.getFullyQualifiedName(sema.mod); |
| 18073 | defer gpa.free(fqn); | 18097 | defer gpa.free(fqn); |
| 18074 | try sema.mod.errNoteNonLazy( | 18098 | try sema.mod.errNoteNonLazy( |
| 18075 | struct_obj.data.srcLoc(sema.mod), | 18099 | struct_obj.srcLoc(sema.mod), |
| 18076 | msg, | 18100 | msg, |
| 18077 | "struct '{s}' declared here", | 18101 | "struct '{s}' declared here", |
| 18078 | .{fqn}, | 18102 | .{fqn}, |
| ... | @@ -18277,7 +18301,7 @@ fn zirArrayInit( | ... | @@ -18277,7 +18301,7 @@ fn zirArrayInit( |
| 18277 | for (args[1..], 0..) |arg, i| { | 18301 | for (args[1..], 0..) |arg, i| { |
| 18278 | const resolved_arg = try sema.resolveInst(arg); | 18302 | const resolved_arg = try sema.resolveInst(arg); |
| 18279 | const elem_ty = if (array_ty.zigTypeTag(mod) == .Struct) | 18303 | const elem_ty = if (array_ty.zigTypeTag(mod) == .Struct) |
| 18280 | array_ty.structFieldType(i) | 18304 | array_ty.structFieldType(i, mod) |
| 18281 | else | 18305 | else |
| 18282 | array_ty.elemType2(mod); | 18306 | array_ty.elemType2(mod); |
| 18283 | resolved_args[i] = sema.coerce(block, elem_ty, resolved_arg, .unneeded) catch |err| switch (err) { | 18307 | resolved_args[i] = sema.coerce(block, elem_ty, resolved_arg, .unneeded) catch |err| switch (err) { |
| ... | @@ -18331,12 +18355,12 @@ fn zirArrayInit( | ... | @@ -18331,12 +18355,12 @@ fn zirArrayInit( |
| 18331 | }); | 18355 | }); |
| 18332 | const alloc = try block.addTy(.alloc, alloc_ty); | 18356 | const alloc = try block.addTy(.alloc, alloc_ty); |
| 18333 | 18357 | ||
| 18334 | if (array_ty.isTuple()) { | 18358 | if (array_ty.isTuple(mod)) { |
| 18335 | for (resolved_args, 0..) |arg, i| { | 18359 | for (resolved_args, 0..) |arg, i| { |
| 18336 | const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ | 18360 | const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ |
| 18337 | .mutable = true, | 18361 | .mutable = true, |
| 18338 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), | 18362 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 18339 | .pointee_type = array_ty.structFieldType(i), | 18363 | .pointee_type = array_ty.structFieldType(i, mod), |
| 18340 | }); | 18364 | }); |
| 18341 | const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty); | 18365 | const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty); |
| 18342 | 18366 | ||
| ... | @@ -18514,7 +18538,7 @@ fn fieldType( | ... | @@ -18514,7 +18538,7 @@ fn fieldType( |
| 18514 | const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src); | 18538 | const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src); |
| 18515 | return sema.addType(cur_ty.tupleFields().types[field_index]); | 18539 | return sema.addType(cur_ty.tupleFields().types[field_index]); |
| 18516 | } | 18540 | } |
| 18517 | const struct_obj = cur_ty.castTag(.@"struct").?.data; | 18541 | const struct_obj = mod.typeToStruct(cur_ty).?; |
| 18518 | const field = struct_obj.fields.get(field_name) orelse | 18542 | const field = struct_obj.fields.get(field_name) orelse |
| 18519 | return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name); | 18543 | return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name); |
| 18520 | return sema.addType(field.ty); | 18544 | return sema.addType(field.ty); |
| ... | @@ -19185,13 +19209,13 @@ fn zirReify( | ... | @@ -19185,13 +19209,13 @@ fn zirReify( |
| 19185 | .file_scope = block.getFileScope(mod), | 19209 | .file_scope = block.getFileScope(mod), |
| 19186 | }); | 19210 | }); |
| 19187 | const new_namespace = mod.namespacePtr(new_namespace_index); | 19211 | const new_namespace = mod.namespacePtr(new_namespace_index); |
| 19188 | errdefer @panic("TODO error handling"); | 19212 | errdefer mod.destroyNamespace(new_namespace_index); |
| 19189 | 19213 | ||
| 19190 | const opaque_ty = try mod.intern_pool.get(gpa, .{ .opaque_type = .{ | 19214 | const opaque_ty = try mod.intern_pool.get(gpa, .{ .opaque_type = .{ |
| 19191 | .decl = new_decl_index, | 19215 | .decl = new_decl_index, |
| 19192 | .namespace = new_namespace_index, | 19216 | .namespace = new_namespace_index, |
| 19193 | } }); | 19217 | } }); |
| 19194 | errdefer @panic("TODO error handling"); | 19218 | errdefer mod.intern_pool.remove(opaque_ty); |
| 19195 | 19219 | ||
| 19196 | new_decl.val = opaque_ty.toValue(); | 19220 | new_decl.val = opaque_ty.toValue(); |
| 19197 | new_namespace.ty = opaque_ty.toType(); | 19221 | new_namespace.ty = opaque_ty.toType(); |
| ... | @@ -19493,22 +19517,34 @@ fn reifyStruct( | ... | @@ -19493,22 +19517,34 @@ fn reifyStruct( |
| 19493 | name_strategy: Zir.Inst.NameStrategy, | 19517 | name_strategy: Zir.Inst.NameStrategy, |
| 19494 | is_tuple: bool, | 19518 | is_tuple: bool, |
| 19495 | ) CompileError!Air.Inst.Ref { | 19519 | ) CompileError!Air.Inst.Ref { |
| 19496 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); | 19520 | const mod = sema.mod; |
| 19521 | const gpa = sema.gpa; | ||
| 19522 | |||
| 19523 | var new_decl_arena = std.heap.ArenaAllocator.init(gpa); | ||
| 19497 | errdefer new_decl_arena.deinit(); | 19524 | errdefer new_decl_arena.deinit(); |
| 19498 | const new_decl_arena_allocator = new_decl_arena.allocator(); | 19525 | const new_decl_arena_allocator = new_decl_arena.allocator(); |
| 19499 | 19526 | ||
| 19500 | const struct_obj = try new_decl_arena_allocator.create(Module.Struct); | 19527 | // Because these three things each reference each other, `undefined` |
| 19501 | const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj); | 19528 | // placeholders are used before being set after the struct type gains an |
| 19502 | const new_struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty); | 19529 | // InternPool index. |
| 19503 | const mod = sema.mod; | 19530 | |
| 19504 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | 19531 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ |
| 19505 | .ty = Type.type, | 19532 | .ty = Type.type, |
| 19506 | .val = new_struct_val, | 19533 | .val = undefined, |
| 19507 | }, name_strategy, "struct", inst); | 19534 | }, name_strategy, "struct", inst); |
| 19508 | const new_decl = mod.declPtr(new_decl_index); | 19535 | const new_decl = mod.declPtr(new_decl_index); |
| 19509 | new_decl.owns_tv = true; | 19536 | new_decl.owns_tv = true; |
| 19510 | errdefer mod.abortAnonDecl(new_decl_index); | 19537 | errdefer mod.abortAnonDecl(new_decl_index); |
| 19511 | struct_obj.* = .{ | 19538 | |
| 19539 | const new_namespace_index = try mod.createNamespace(.{ | ||
| 19540 | .parent = block.namespace.toOptional(), | ||
| 19541 | .ty = undefined, | ||
| 19542 | .file_scope = block.getFileScope(mod), | ||
| 19543 | }); | ||
| 19544 | const new_namespace = mod.namespacePtr(new_namespace_index); | ||
| 19545 | errdefer mod.destroyNamespace(new_namespace_index); | ||
| 19546 | |||
| 19547 | const struct_index = try mod.createStruct(.{ | ||
| 19512 | .owner_decl = new_decl_index, | 19548 | .owner_decl = new_decl_index, |
| 19513 | .fields = .{}, | 19549 | .fields = .{}, |
| 19514 | .zir_index = inst, | 19550 | .zir_index = inst, |
| ... | @@ -19516,12 +19552,19 @@ fn reifyStruct( | ... | @@ -19516,12 +19552,19 @@ fn reifyStruct( |
| 19516 | .status = .have_field_types, | 19552 | .status = .have_field_types, |
| 19517 | .known_non_opv = false, | 19553 | .known_non_opv = false, |
| 19518 | .is_tuple = is_tuple, | 19554 | .is_tuple = is_tuple, |
| 19519 | .namespace = try mod.createNamespace(.{ | 19555 | .namespace = new_namespace_index, |
| 19520 | .parent = block.namespace.toOptional(), | 19556 | }); |
| 19521 | .ty = struct_ty, | 19557 | const struct_obj = mod.structPtr(struct_index); |
| 19522 | .file_scope = block.getFileScope(mod), | 19558 | errdefer mod.destroyStruct(struct_index); |
| 19523 | }), | 19559 | |
| 19524 | }; | 19560 | const struct_ty = try mod.intern_pool.get(gpa, .{ .struct_type = .{ |
| 19561 | .index = struct_index.toOptional(), | ||
| 19562 | .namespace = new_namespace_index.toOptional(), | ||
| 19563 | } }); | ||
| 19564 | errdefer mod.intern_pool.remove(struct_ty); | ||
| 19565 | |||
| 19566 | new_decl.val = struct_ty.toValue(); | ||
| 19567 | new_namespace.ty = struct_ty.toType(); | ||
| 19525 | 19568 | ||
| 19526 | // Fields | 19569 | // Fields |
| 19527 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod)); | 19570 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod)); |
| ... | @@ -19609,7 +19652,7 @@ fn reifyStruct( | ... | @@ -19609,7 +19652,7 @@ fn reifyStruct( |
| 19609 | if (field_ty.zigTypeTag(mod) == .Opaque) { | 19652 | if (field_ty.zigTypeTag(mod) == .Opaque) { |
| 19610 | const msg = msg: { | 19653 | const msg = msg: { |
| 19611 | const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); | 19654 | const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); |
| 19612 | errdefer msg.destroy(sema.gpa); | 19655 | errdefer msg.destroy(gpa); |
| 19613 | 19656 | ||
| 19614 | try sema.addDeclaredHereNote(msg, field_ty); | 19657 | try sema.addDeclaredHereNote(msg, field_ty); |
| 19615 | break :msg msg; | 19658 | break :msg msg; |
| ... | @@ -19619,7 +19662,7 @@ fn reifyStruct( | ... | @@ -19619,7 +19662,7 @@ fn reifyStruct( |
| 19619 | if (field_ty.zigTypeTag(mod) == .NoReturn) { | 19662 | if (field_ty.zigTypeTag(mod) == .NoReturn) { |
| 19620 | const msg = msg: { | 19663 | const msg = msg: { |
| 19621 | const msg = try sema.errMsg(block, src, "struct fields cannot be 'noreturn'", .{}); | 19664 | const msg = try sema.errMsg(block, src, "struct fields cannot be 'noreturn'", .{}); |
| 19622 | errdefer msg.destroy(sema.gpa); | 19665 | errdefer msg.destroy(gpa); |
| 19623 | 19666 | ||
| 19624 | try sema.addDeclaredHereNote(msg, field_ty); | 19667 | try sema.addDeclaredHereNote(msg, field_ty); |
| 19625 | break :msg msg; | 19668 | break :msg msg; |
| ... | @@ -19629,7 +19672,7 @@ fn reifyStruct( | ... | @@ -19629,7 +19672,7 @@ fn reifyStruct( |
| 19629 | if (struct_obj.layout == .Extern and !try sema.validateExternType(field_ty, .struct_field)) { | 19672 | if (struct_obj.layout == .Extern and !try sema.validateExternType(field_ty, .struct_field)) { |
| 19630 | const msg = msg: { | 19673 | const msg = msg: { |
| 19631 | const msg = try sema.errMsg(block, src, "extern structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); | 19674 | const msg = try sema.errMsg(block, src, "extern structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); |
| 19632 | errdefer msg.destroy(sema.gpa); | 19675 | errdefer msg.destroy(gpa); |
| 19633 | 19676 | ||
| 19634 | const src_decl = sema.mod.declPtr(block.src_decl); | 19677 | const src_decl = sema.mod.declPtr(block.src_decl); |
| 19635 | try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl, mod), field_ty, .struct_field); | 19678 | try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl, mod), field_ty, .struct_field); |
| ... | @@ -19641,7 +19684,7 @@ fn reifyStruct( | ... | @@ -19641,7 +19684,7 @@ fn reifyStruct( |
| 19641 | } else if (struct_obj.layout == .Packed and !(validatePackedType(field_ty, mod))) { | 19684 | } else if (struct_obj.layout == .Packed and !(validatePackedType(field_ty, mod))) { |
| 19642 | const msg = msg: { | 19685 | const msg = msg: { |
| 19643 | const msg = try sema.errMsg(block, src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); | 19686 | const msg = try sema.errMsg(block, src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); |
| 19644 | errdefer msg.destroy(sema.gpa); | 19687 | errdefer msg.destroy(gpa); |
| 19645 | 19688 | ||
| 19646 | const src_decl = sema.mod.declPtr(block.src_decl); | 19689 | const src_decl = sema.mod.declPtr(block.src_decl); |
| 19647 | try sema.explainWhyTypeIsNotPacked(msg, src.toSrcLoc(src_decl, mod), field_ty); | 19690 | try sema.explainWhyTypeIsNotPacked(msg, src.toSrcLoc(src_decl, mod), field_ty); |
| ... | @@ -19660,7 +19703,7 @@ fn reifyStruct( | ... | @@ -19660,7 +19703,7 @@ fn reifyStruct( |
| 19660 | sema.resolveTypeLayout(field.ty) catch |err| switch (err) { | 19703 | sema.resolveTypeLayout(field.ty) catch |err| switch (err) { |
| 19661 | error.AnalysisFail => { | 19704 | error.AnalysisFail => { |
| 19662 | const msg = sema.err orelse return err; | 19705 | const msg = sema.err orelse return err; |
| 19663 | try sema.addFieldErrNote(struct_ty, index, msg, "while checking this field", .{}); | 19706 | try sema.addFieldErrNote(struct_ty.toType(), index, msg, "while checking this field", .{}); |
| 19664 | return err; | 19707 | return err; |
| 19665 | }, | 19708 | }, |
| 19666 | else => return err, | 19709 | else => return err, |
| ... | @@ -20558,21 +20601,21 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 | ... | @@ -20558,21 +20601,21 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 |
| 20558 | }, | 20601 | }, |
| 20559 | } | 20602 | } |
| 20560 | 20603 | ||
| 20561 | const field_index = if (ty.isTuple()) blk: { | 20604 | const field_index = if (ty.isTuple(mod)) blk: { |
| 20562 | if (mem.eql(u8, field_name, "len")) { | 20605 | if (mem.eql(u8, field_name, "len")) { |
| 20563 | return sema.fail(block, src, "no offset available for 'len' field of tuple", .{}); | 20606 | return sema.fail(block, src, "no offset available for 'len' field of tuple", .{}); |
| 20564 | } | 20607 | } |
| 20565 | break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src); | 20608 | break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src); |
| 20566 | } else try sema.structFieldIndex(block, ty, field_name, rhs_src); | 20609 | } else try sema.structFieldIndex(block, ty, field_name, rhs_src); |
| 20567 | 20610 | ||
| 20568 | if (ty.structFieldIsComptime(field_index)) { | 20611 | if (ty.structFieldIsComptime(field_index, mod)) { |
| 20569 | return sema.fail(block, src, "no offset available for comptime field", .{}); | 20612 | return sema.fail(block, src, "no offset available for comptime field", .{}); |
| 20570 | } | 20613 | } |
| 20571 | 20614 | ||
| 20572 | switch (ty.containerLayout()) { | 20615 | switch (ty.containerLayout(mod)) { |
| 20573 | .Packed => { | 20616 | .Packed => { |
| 20574 | var bit_sum: u64 = 0; | 20617 | var bit_sum: u64 = 0; |
| 20575 | const fields = ty.structFields(); | 20618 | const fields = ty.structFields(mod); |
| 20576 | for (fields.values(), 0..) |field, i| { | 20619 | for (fields.values(), 0..) |field, i| { |
| 20577 | if (i == field_index) { | 20620 | if (i == field_index) { |
| 20578 | return bit_sum; | 20621 | return bit_sum; |
| ... | @@ -21810,6 +21853,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -21810,6 +21853,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 21810 | const tracy = trace(@src()); | 21853 | const tracy = trace(@src()); |
| 21811 | defer tracy.end(); | 21854 | defer tracy.end(); |
| 21812 | 21855 | ||
| 21856 | const mod = sema.mod; | ||
| 21813 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 21857 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 21814 | const modifier_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 21858 | const modifier_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 21815 | const func_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 21859 | const func_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| ... | @@ -21869,11 +21913,11 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -21869,11 +21913,11 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 21869 | const args = try sema.resolveInst(extra.args); | 21913 | const args = try sema.resolveInst(extra.args); |
| 21870 | 21914 | ||
| 21871 | const args_ty = sema.typeOf(args); | 21915 | const args_ty = sema.typeOf(args); |
| 21872 | if (!args_ty.isTuple() and args_ty.ip_index != .empty_struct_type) { | 21916 | if (!args_ty.isTuple(mod) and args_ty.ip_index != .empty_struct_type) { |
| 21873 | return sema.fail(block, args_src, "expected a tuple, found '{}'", .{args_ty.fmt(sema.mod)}); | 21917 | return sema.fail(block, args_src, "expected a tuple, found '{}'", .{args_ty.fmt(sema.mod)}); |
| 21874 | } | 21918 | } |
| 21875 | 21919 | ||
| 21876 | var resolved_args: []Air.Inst.Ref = try sema.arena.alloc(Air.Inst.Ref, args_ty.structFieldCount()); | 21920 | var resolved_args: []Air.Inst.Ref = try sema.arena.alloc(Air.Inst.Ref, args_ty.structFieldCount(mod)); |
| 21877 | for (resolved_args, 0..) |*resolved, i| { | 21921 | for (resolved_args, 0..) |*resolved, i| { |
| 21878 | resolved.* = try sema.tupleFieldValByIndex(block, args_src, args, @intCast(u32, i), args_ty); | 21922 | resolved.* = try sema.tupleFieldValByIndex(block, args_src, args, @intCast(u32, i), args_ty); |
| 21879 | } | 21923 | } |
| ... | @@ -21905,7 +21949,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -21905,7 +21949,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 21905 | 21949 | ||
| 21906 | const field_index = switch (parent_ty.zigTypeTag(mod)) { | 21950 | const field_index = switch (parent_ty.zigTypeTag(mod)) { |
| 21907 | .Struct => blk: { | 21951 | .Struct => blk: { |
| 21908 | if (parent_ty.isTuple()) { | 21952 | if (parent_ty.isTuple(mod)) { |
| 21909 | if (mem.eql(u8, field_name, "len")) { | 21953 | if (mem.eql(u8, field_name, "len")) { |
| 21910 | return sema.fail(block, src, "cannot get @fieldParentPtr of 'len' field of tuple", .{}); | 21954 | return sema.fail(block, src, "cannot get @fieldParentPtr of 'len' field of tuple", .{}); |
| 21911 | } | 21955 | } |
| ... | @@ -21918,7 +21962,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -21918,7 +21962,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 21918 | else => unreachable, | 21962 | else => unreachable, |
| 21919 | }; | 21963 | }; |
| 21920 | 21964 | ||
| 21921 | if (parent_ty.zigTypeTag(mod) == .Struct and parent_ty.structFieldIsComptime(field_index)) { | 21965 | if (parent_ty.zigTypeTag(mod) == .Struct and parent_ty.structFieldIsComptime(field_index, mod)) { |
| 21922 | return sema.fail(block, src, "cannot get @fieldParentPtr of a comptime field", .{}); | 21966 | return sema.fail(block, src, "cannot get @fieldParentPtr of a comptime field", .{}); |
| 21923 | } | 21967 | } |
| 21924 | 21968 | ||
| ... | @@ -21926,17 +21970,17 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -21926,17 +21970,17 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 21926 | const field_ptr_ty_info = field_ptr_ty.ptrInfo(mod); | 21970 | const field_ptr_ty_info = field_ptr_ty.ptrInfo(mod); |
| 21927 | 21971 | ||
| 21928 | var ptr_ty_data: Type.Payload.Pointer.Data = .{ | 21972 | var ptr_ty_data: Type.Payload.Pointer.Data = .{ |
| 21929 | .pointee_type = parent_ty.structFieldType(field_index), | 21973 | .pointee_type = parent_ty.structFieldType(field_index, mod), |
| 21930 | .mutable = field_ptr_ty_info.mutable, | 21974 | .mutable = field_ptr_ty_info.mutable, |
| 21931 | .@"addrspace" = field_ptr_ty_info.@"addrspace", | 21975 | .@"addrspace" = field_ptr_ty_info.@"addrspace", |
| 21932 | }; | 21976 | }; |
| 21933 | 21977 | ||
| 21934 | if (parent_ty.containerLayout() == .Packed) { | 21978 | if (parent_ty.containerLayout(mod) == .Packed) { |
| 21935 | return sema.fail(block, src, "TODO handle packed structs/unions with @fieldParentPtr", .{}); | 21979 | return sema.fail(block, src, "TODO handle packed structs/unions with @fieldParentPtr", .{}); |
| 21936 | } else { | 21980 | } else { |
| 21937 | ptr_ty_data.@"align" = blk: { | 21981 | ptr_ty_data.@"align" = blk: { |
| 21938 | if (parent_ty.castTag(.@"struct")) |struct_obj| { | 21982 | if (mod.typeToStruct(parent_ty)) |struct_obj| { |
| 21939 | break :blk struct_obj.data.fields.values()[field_index].abi_align; | 21983 | break :blk struct_obj.fields.values()[field_index].abi_align; |
| 21940 | } else if (parent_ty.cast(Type.Payload.Union)) |union_obj| { | 21984 | } else if (parent_ty.cast(Type.Payload.Union)) |union_obj| { |
| 21941 | break :blk union_obj.data.fields.values()[field_index].abi_align; | 21985 | break :blk union_obj.data.fields.values()[field_index].abi_align; |
| 21942 | } else { | 21986 | } else { |
| ... | @@ -23380,8 +23424,7 @@ fn explainWhyTypeIsComptimeInner( | ... | @@ -23380,8 +23424,7 @@ fn explainWhyTypeIsComptimeInner( |
| 23380 | .Struct => { | 23424 | .Struct => { |
| 23381 | if ((try type_set.getOrPutContext(sema.gpa, ty, .{ .mod = mod })).found_existing) return; | 23425 | if ((try type_set.getOrPutContext(sema.gpa, ty, .{ .mod = mod })).found_existing) return; |
| 23382 | 23426 | ||
| 23383 | if (ty.castTag(.@"struct")) |payload| { | 23427 | if (mod.typeToStruct(ty)) |struct_obj| { |
| 23384 | const struct_obj = payload.data; | ||
| 23385 | for (struct_obj.fields.values(), 0..) |field, i| { | 23428 | for (struct_obj.fields.values(), 0..) |field, i| { |
| 23386 | const field_src_loc = struct_obj.fieldSrcLoc(sema.mod, .{ | 23429 | const field_src_loc = struct_obj.fieldSrcLoc(sema.mod, .{ |
| 23387 | .index = i, | 23430 | .index = i, |
| ... | @@ -23472,7 +23515,7 @@ fn validateExternType( | ... | @@ -23472,7 +23515,7 @@ fn validateExternType( |
| 23472 | .Enum => { | 23515 | .Enum => { |
| 23473 | return sema.validateExternType(try ty.intTagType(mod), position); | 23516 | return sema.validateExternType(try ty.intTagType(mod), position); |
| 23474 | }, | 23517 | }, |
| 23475 | .Struct, .Union => switch (ty.containerLayout()) { | 23518 | .Struct, .Union => switch (ty.containerLayout(mod)) { |
| 23476 | .Extern => return true, | 23519 | .Extern => return true, |
| 23477 | .Packed => { | 23520 | .Packed => { |
| 23478 | const bit_size = try ty.bitSizeAdvanced(mod, sema); | 23521 | const bit_size = try ty.bitSizeAdvanced(mod, sema); |
| ... | @@ -23569,7 +23612,7 @@ fn explainWhyTypeIsNotExtern( | ... | @@ -23569,7 +23612,7 @@ fn explainWhyTypeIsNotExtern( |
| 23569 | 23612 | ||
| 23570 | /// Returns true if `ty` is allowed in packed types. | 23613 | /// Returns true if `ty` is allowed in packed types. |
| 23571 | /// Does *NOT* require `ty` to be resolved in any way. | 23614 | /// Does *NOT* require `ty` to be resolved in any way. |
| 23572 | fn validatePackedType(ty: Type, mod: *const Module) bool { | 23615 | fn validatePackedType(ty: Type, mod: *Module) bool { |
| 23573 | switch (ty.zigTypeTag(mod)) { | 23616 | switch (ty.zigTypeTag(mod)) { |
| 23574 | .Type, | 23617 | .Type, |
| 23575 | .ComptimeFloat, | 23618 | .ComptimeFloat, |
| ... | @@ -23595,7 +23638,7 @@ fn validatePackedType(ty: Type, mod: *const Module) bool { | ... | @@ -23595,7 +23638,7 @@ fn validatePackedType(ty: Type, mod: *const Module) bool { |
| 23595 | .Enum, | 23638 | .Enum, |
| 23596 | => return true, | 23639 | => return true, |
| 23597 | .Pointer => return !ty.isSlice(mod), | 23640 | .Pointer => return !ty.isSlice(mod), |
| 23598 | .Struct, .Union => return ty.containerLayout() == .Packed, | 23641 | .Struct, .Union => return ty.containerLayout(mod) == .Packed, |
| 23599 | } | 23642 | } |
| 23600 | } | 23643 | } |
| 23601 | 23644 | ||
| ... | @@ -24419,27 +24462,27 @@ fn fieldCallBind( | ... | @@ -24419,27 +24462,27 @@ fn fieldCallBind( |
| 24419 | switch (concrete_ty.zigTypeTag(mod)) { | 24462 | switch (concrete_ty.zigTypeTag(mod)) { |
| 24420 | .Struct => { | 24463 | .Struct => { |
| 24421 | const struct_ty = try sema.resolveTypeFields(concrete_ty); | 24464 | const struct_ty = try sema.resolveTypeFields(concrete_ty); |
| 24422 | if (struct_ty.castTag(.@"struct")) |struct_obj| { | 24465 | if (mod.typeToStruct(struct_ty)) |struct_obj| { |
| 24423 | const field_index_usize = struct_obj.data.fields.getIndex(field_name) orelse | 24466 | const field_index_usize = struct_obj.fields.getIndex(field_name) orelse |
| 24424 | break :find_field; | 24467 | break :find_field; |
| 24425 | const field_index = @intCast(u32, field_index_usize); | 24468 | const field_index = @intCast(u32, field_index_usize); |
| 24426 | const field = struct_obj.data.fields.values()[field_index]; | 24469 | const field = struct_obj.fields.values()[field_index]; |
| 24427 | 24470 | ||
| 24428 | return sema.finishFieldCallBind(block, src, ptr_ty, field.ty, field_index, object_ptr); | 24471 | return sema.finishFieldCallBind(block, src, ptr_ty, field.ty, field_index, object_ptr); |
| 24429 | } else if (struct_ty.isTuple()) { | 24472 | } else if (struct_ty.isTuple(mod)) { |
| 24430 | if (mem.eql(u8, field_name, "len")) { | 24473 | if (mem.eql(u8, field_name, "len")) { |
| 24431 | return .{ .direct = try sema.addIntUnsigned(Type.usize, struct_ty.structFieldCount()) }; | 24474 | return .{ .direct = try sema.addIntUnsigned(Type.usize, struct_ty.structFieldCount(mod)) }; |
| 24432 | } | 24475 | } |
| 24433 | if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| { | 24476 | if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| { |
| 24434 | if (field_index >= struct_ty.structFieldCount()) break :find_field; | 24477 | if (field_index >= struct_ty.structFieldCount(mod)) break :find_field; |
| 24435 | return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(field_index), field_index, object_ptr); | 24478 | return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(field_index, mod), field_index, object_ptr); |
| 24436 | } else |_| {} | 24479 | } else |_| {} |
| 24437 | } else { | 24480 | } else { |
| 24438 | const max = struct_ty.structFieldCount(); | 24481 | const max = struct_ty.structFieldCount(mod); |
| 24439 | var i: u32 = 0; | 24482 | var i: u32 = 0; |
| 24440 | while (i < max) : (i += 1) { | 24483 | while (i < max) : (i += 1) { |
| 24441 | if (mem.eql(u8, struct_ty.structFieldName(i), field_name)) { | 24484 | if (mem.eql(u8, struct_ty.structFieldName(i, mod), field_name)) { |
| 24442 | return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(i), i, object_ptr); | 24485 | return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(i, mod), i, object_ptr); |
| 24443 | } | 24486 | } |
| 24444 | } | 24487 | } |
| 24445 | } | 24488 | } |
| ... | @@ -24651,9 +24694,9 @@ fn structFieldPtr( | ... | @@ -24651,9 +24694,9 @@ fn structFieldPtr( |
| 24651 | const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty); | 24694 | const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty); |
| 24652 | try sema.resolveStructLayout(struct_ty); | 24695 | try sema.resolveStructLayout(struct_ty); |
| 24653 | 24696 | ||
| 24654 | if (struct_ty.isTuple()) { | 24697 | if (struct_ty.isTuple(mod)) { |
| 24655 | if (mem.eql(u8, field_name, "len")) { | 24698 | if (mem.eql(u8, field_name, "len")) { |
| 24656 | const len_inst = try sema.addIntUnsigned(Type.usize, struct_ty.structFieldCount()); | 24699 | const len_inst = try sema.addIntUnsigned(Type.usize, struct_ty.structFieldCount(mod)); |
| 24657 | return sema.analyzeRef(block, src, len_inst); | 24700 | return sema.analyzeRef(block, src, len_inst); |
| 24658 | } | 24701 | } |
| 24659 | const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src); | 24702 | const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src); |
| ... | @@ -24663,7 +24706,7 @@ fn structFieldPtr( | ... | @@ -24663,7 +24706,7 @@ fn structFieldPtr( |
| 24663 | return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing); | 24706 | return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing); |
| 24664 | } | 24707 | } |
| 24665 | 24708 | ||
| 24666 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | 24709 | const struct_obj = mod.typeToStruct(struct_ty).?; |
| 24667 | 24710 | ||
| 24668 | const field_index_big = struct_obj.fields.getIndex(field_name) orelse | 24711 | const field_index_big = struct_obj.fields.getIndex(field_name) orelse |
| 24669 | return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name); | 24712 | return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name); |
| ... | @@ -24687,7 +24730,7 @@ fn structFieldPtrByIndex( | ... | @@ -24687,7 +24730,7 @@ fn structFieldPtrByIndex( |
| 24687 | } | 24730 | } |
| 24688 | 24731 | ||
| 24689 | const mod = sema.mod; | 24732 | const mod = sema.mod; |
| 24690 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | 24733 | const struct_obj = mod.typeToStruct(struct_ty).?; |
| 24691 | const field = struct_obj.fields.values()[field_index]; | 24734 | const field = struct_obj.fields.values()[field_index]; |
| 24692 | const struct_ptr_ty = sema.typeOf(struct_ptr); | 24735 | const struct_ptr_ty = sema.typeOf(struct_ptr); |
| 24693 | const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(mod); | 24736 | const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(mod); |
| ... | @@ -24799,8 +24842,11 @@ fn structFieldVal( | ... | @@ -24799,8 +24842,11 @@ fn structFieldVal( |
| 24799 | const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src); | 24842 | const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src); |
| 24800 | return sema.tupleFieldValByIndex(block, src, struct_byval, field_index, struct_ty); | 24843 | return sema.tupleFieldValByIndex(block, src, struct_byval, field_index, struct_ty); |
| 24801 | }, | 24844 | }, |
| 24802 | .@"struct" => { | 24845 | else => unreachable, |
| 24803 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | 24846 | }, |
| 24847 | else => switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) { | ||
| 24848 | .struct_type => |struct_type| { | ||
| 24849 | const struct_obj = mod.structPtrUnwrap(struct_type.index).?; | ||
| 24804 | if (struct_obj.is_tuple) return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty); | 24850 | if (struct_obj.is_tuple) return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty); |
| 24805 | 24851 | ||
| 24806 | const field_index_usize = struct_obj.fields.getIndex(field_name) orelse | 24852 | const field_index_usize = struct_obj.fields.getIndex(field_name) orelse |
| ... | @@ -24827,7 +24873,6 @@ fn structFieldVal( | ... | @@ -24827,7 +24873,6 @@ fn structFieldVal( |
| 24827 | }, | 24873 | }, |
| 24828 | else => unreachable, | 24874 | else => unreachable, |
| 24829 | }, | 24875 | }, |
| 24830 | else => unreachable, | ||
| 24831 | } | 24876 | } |
| 24832 | } | 24877 | } |
| 24833 | 24878 | ||
| ... | @@ -24840,8 +24885,9 @@ fn tupleFieldVal( | ... | @@ -24840,8 +24885,9 @@ fn tupleFieldVal( |
| 24840 | field_name_src: LazySrcLoc, | 24885 | field_name_src: LazySrcLoc, |
| 24841 | tuple_ty: Type, | 24886 | tuple_ty: Type, |
| 24842 | ) CompileError!Air.Inst.Ref { | 24887 | ) CompileError!Air.Inst.Ref { |
| 24888 | const mod = sema.mod; | ||
| 24843 | if (mem.eql(u8, field_name, "len")) { | 24889 | if (mem.eql(u8, field_name, "len")) { |
| 24844 | return sema.addIntUnsigned(Type.usize, tuple_ty.structFieldCount()); | 24890 | return sema.addIntUnsigned(Type.usize, tuple_ty.structFieldCount(mod)); |
| 24845 | } | 24891 | } |
| 24846 | const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_name_src); | 24892 | const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_name_src); |
| 24847 | return sema.tupleFieldValByIndex(block, src, tuple_byval, field_index, tuple_ty); | 24893 | return sema.tupleFieldValByIndex(block, src, tuple_byval, field_index, tuple_ty); |
| ... | @@ -24858,7 +24904,7 @@ fn tupleFieldIndex( | ... | @@ -24858,7 +24904,7 @@ fn tupleFieldIndex( |
| 24858 | const mod = sema.mod; | 24904 | const mod = sema.mod; |
| 24859 | assert(!std.mem.eql(u8, field_name, "len")); | 24905 | assert(!std.mem.eql(u8, field_name, "len")); |
| 24860 | if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| { | 24906 | if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| { |
| 24861 | if (field_index < tuple_ty.structFieldCount()) return field_index; | 24907 | if (field_index < tuple_ty.structFieldCount(mod)) return field_index; |
| 24862 | return sema.fail(block, field_name_src, "index '{s}' out of bounds of tuple '{}'", .{ | 24908 | return sema.fail(block, field_name_src, "index '{s}' out of bounds of tuple '{}'", .{ |
| 24863 | field_name, tuple_ty.fmt(mod), | 24909 | field_name, tuple_ty.fmt(mod), |
| 24864 | }); | 24910 | }); |
| ... | @@ -24878,7 +24924,7 @@ fn tupleFieldValByIndex( | ... | @@ -24878,7 +24924,7 @@ fn tupleFieldValByIndex( |
| 24878 | tuple_ty: Type, | 24924 | tuple_ty: Type, |
| 24879 | ) CompileError!Air.Inst.Ref { | 24925 | ) CompileError!Air.Inst.Ref { |
| 24880 | const mod = sema.mod; | 24926 | const mod = sema.mod; |
| 24881 | const field_ty = tuple_ty.structFieldType(field_index); | 24927 | const field_ty = tuple_ty.structFieldType(field_index, mod); |
| 24882 | 24928 | ||
| 24883 | if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| { | 24929 | if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| { |
| 24884 | return sema.addConstant(field_ty, default_value); | 24930 | return sema.addConstant(field_ty, default_value); |
| ... | @@ -25251,7 +25297,7 @@ fn tupleFieldPtr( | ... | @@ -25251,7 +25297,7 @@ fn tupleFieldPtr( |
| 25251 | const tuple_ptr_ty = sema.typeOf(tuple_ptr); | 25297 | const tuple_ptr_ty = sema.typeOf(tuple_ptr); |
| 25252 | const tuple_ty = tuple_ptr_ty.childType(mod); | 25298 | const tuple_ty = tuple_ptr_ty.childType(mod); |
| 25253 | _ = try sema.resolveTypeFields(tuple_ty); | 25299 | _ = try sema.resolveTypeFields(tuple_ty); |
| 25254 | const field_count = tuple_ty.structFieldCount(); | 25300 | const field_count = tuple_ty.structFieldCount(mod); |
| 25255 | 25301 | ||
| 25256 | if (field_count == 0) { | 25302 | if (field_count == 0) { |
| 25257 | return sema.fail(block, tuple_ptr_src, "indexing into empty tuple is not allowed", .{}); | 25303 | return sema.fail(block, tuple_ptr_src, "indexing into empty tuple is not allowed", .{}); |
| ... | @@ -25263,7 +25309,7 @@ fn tupleFieldPtr( | ... | @@ -25263,7 +25309,7 @@ fn tupleFieldPtr( |
| 25263 | }); | 25309 | }); |
| 25264 | } | 25310 | } |
| 25265 | 25311 | ||
| 25266 | const field_ty = tuple_ty.structFieldType(field_index); | 25312 | const field_ty = tuple_ty.structFieldType(field_index, mod); |
| 25267 | const ptr_field_ty = try Type.ptr(sema.arena, mod, .{ | 25313 | const ptr_field_ty = try Type.ptr(sema.arena, mod, .{ |
| 25268 | .pointee_type = field_ty, | 25314 | .pointee_type = field_ty, |
| 25269 | .mutable = tuple_ptr_ty.ptrIsMutable(mod), | 25315 | .mutable = tuple_ptr_ty.ptrIsMutable(mod), |
| ... | @@ -25308,7 +25354,7 @@ fn tupleField( | ... | @@ -25308,7 +25354,7 @@ fn tupleField( |
| 25308 | ) CompileError!Air.Inst.Ref { | 25354 | ) CompileError!Air.Inst.Ref { |
| 25309 | const mod = sema.mod; | 25355 | const mod = sema.mod; |
| 25310 | const tuple_ty = try sema.resolveTypeFields(sema.typeOf(tuple)); | 25356 | const tuple_ty = try sema.resolveTypeFields(sema.typeOf(tuple)); |
| 25311 | const field_count = tuple_ty.structFieldCount(); | 25357 | const field_count = tuple_ty.structFieldCount(mod); |
| 25312 | 25358 | ||
| 25313 | if (field_count == 0) { | 25359 | if (field_count == 0) { |
| 25314 | return sema.fail(block, tuple_src, "indexing into empty tuple is not allowed", .{}); | 25360 | return sema.fail(block, tuple_src, "indexing into empty tuple is not allowed", .{}); |
| ... | @@ -25320,7 +25366,7 @@ fn tupleField( | ... | @@ -25320,7 +25366,7 @@ fn tupleField( |
| 25320 | }); | 25366 | }); |
| 25321 | } | 25367 | } |
| 25322 | 25368 | ||
| 25323 | const field_ty = tuple_ty.structFieldType(field_index); | 25369 | const field_ty = tuple_ty.structFieldType(field_index, mod); |
| 25324 | 25370 | ||
| 25325 | if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| { | 25371 | if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| { |
| 25326 | return sema.addConstant(field_ty, default_value); // comptime field | 25372 | return sema.addConstant(field_ty, default_value); // comptime field |
| ... | @@ -25919,7 +25965,7 @@ fn coerceExtra( | ... | @@ -25919,7 +25965,7 @@ fn coerceExtra( |
| 25919 | .Array => { | 25965 | .Array => { |
| 25920 | // pointer to tuple to pointer to array | 25966 | // pointer to tuple to pointer to array |
| 25921 | if (inst_ty.isSinglePointer(mod) and | 25967 | if (inst_ty.isSinglePointer(mod) and |
| 25922 | inst_ty.childType(mod).isTuple() and | 25968 | inst_ty.childType(mod).isTuple(mod) and |
| 25923 | sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) | 25969 | sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) |
| 25924 | { | 25970 | { |
| 25925 | return sema.coerceTupleToArrayPtrs(block, dest_ty, dest_ty_src, inst, inst_src); | 25971 | return sema.coerceTupleToArrayPtrs(block, dest_ty, dest_ty_src, inst, inst_src); |
| ... | @@ -25939,11 +25985,11 @@ fn coerceExtra( | ... | @@ -25939,11 +25985,11 @@ fn coerceExtra( |
| 25939 | 25985 | ||
| 25940 | if (!inst_ty.isSinglePointer(mod)) break :to_slice; | 25986 | if (!inst_ty.isSinglePointer(mod)) break :to_slice; |
| 25941 | const inst_child_ty = inst_ty.childType(mod); | 25987 | const inst_child_ty = inst_ty.childType(mod); |
| 25942 | if (!inst_child_ty.isTuple()) break :to_slice; | 25988 | if (!inst_child_ty.isTuple(mod)) break :to_slice; |
| 25943 | 25989 | ||
| 25944 | // empty tuple to zero-length slice | 25990 | // empty tuple to zero-length slice |
| 25945 | // note that this allows coercing to a mutable slice. | 25991 | // note that this allows coercing to a mutable slice. |
| 25946 | if (inst_child_ty.structFieldCount() == 0) { | 25992 | if (inst_child_ty.structFieldCount(mod) == 0) { |
| 25947 | // Optional slice is represented with a null pointer so | 25993 | // Optional slice is represented with a null pointer so |
| 25948 | // we use a dummy pointer value with the required alignment. | 25994 | // we use a dummy pointer value with the required alignment. |
| 25949 | const slice_val = try Value.Tag.slice.create(sema.arena, .{ | 25995 | const slice_val = try Value.Tag.slice.create(sema.arena, .{ |
| ... | @@ -26213,7 +26259,7 @@ fn coerceExtra( | ... | @@ -26213,7 +26259,7 @@ fn coerceExtra( |
| 26213 | if (inst == .empty_struct) { | 26259 | if (inst == .empty_struct) { |
| 26214 | return sema.arrayInitEmpty(block, inst_src, dest_ty); | 26260 | return sema.arrayInitEmpty(block, inst_src, dest_ty); |
| 26215 | } | 26261 | } |
| 26216 | if (inst_ty.isTuple()) { | 26262 | if (inst_ty.isTuple(mod)) { |
| 26217 | return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src); | 26263 | return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src); |
| 26218 | } | 26264 | } |
| 26219 | }, | 26265 | }, |
| ... | @@ -26225,7 +26271,7 @@ fn coerceExtra( | ... | @@ -26225,7 +26271,7 @@ fn coerceExtra( |
| 26225 | .Vector => switch (inst_ty.zigTypeTag(mod)) { | 26271 | .Vector => switch (inst_ty.zigTypeTag(mod)) { |
| 26226 | .Array, .Vector => return sema.coerceArrayLike(block, dest_ty, dest_ty_src, inst, inst_src), | 26272 | .Array, .Vector => return sema.coerceArrayLike(block, dest_ty, dest_ty_src, inst, inst_src), |
| 26227 | .Struct => { | 26273 | .Struct => { |
| 26228 | if (inst_ty.isTuple()) { | 26274 | if (inst_ty.isTuple(mod)) { |
| 26229 | return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src); | 26275 | return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src); |
| 26230 | } | 26276 | } |
| 26231 | }, | 26277 | }, |
| ... | @@ -26238,7 +26284,7 @@ fn coerceExtra( | ... | @@ -26238,7 +26284,7 @@ fn coerceExtra( |
| 26238 | if (inst == .empty_struct) { | 26284 | if (inst == .empty_struct) { |
| 26239 | return sema.structInitEmpty(block, dest_ty, dest_ty_src, inst_src); | 26285 | return sema.structInitEmpty(block, dest_ty, dest_ty_src, inst_src); |
| 26240 | } | 26286 | } |
| 26241 | if (inst_ty.isTupleOrAnonStruct()) { | 26287 | if (inst_ty.isTupleOrAnonStruct(mod)) { |
| 26242 | return sema.coerceTupleToStruct(block, dest_ty, inst, inst_src) catch |err| switch (err) { | 26288 | return sema.coerceTupleToStruct(block, dest_ty, inst, inst_src) catch |err| switch (err) { |
| 26243 | error.NotCoercible => break :blk, | 26289 | error.NotCoercible => break :blk, |
| 26244 | else => |e| return e, | 26290 | else => |e| return e, |
| ... | @@ -27304,8 +27350,8 @@ fn storePtr2( | ... | @@ -27304,8 +27350,8 @@ fn storePtr2( |
| 27304 | // this code does not handle tuple-to-struct coercion which requires dealing with missing | 27350 | // this code does not handle tuple-to-struct coercion which requires dealing with missing |
| 27305 | // fields. | 27351 | // fields. |
| 27306 | const operand_ty = sema.typeOf(uncasted_operand); | 27352 | const operand_ty = sema.typeOf(uncasted_operand); |
| 27307 | if (operand_ty.isTuple() and elem_ty.zigTypeTag(mod) == .Array) { | 27353 | if (operand_ty.isTuple(mod) and elem_ty.zigTypeTag(mod) == .Array) { |
| 27308 | const field_count = operand_ty.structFieldCount(); | 27354 | const field_count = operand_ty.structFieldCount(mod); |
| 27309 | var i: u32 = 0; | 27355 | var i: u32 = 0; |
| 27310 | while (i < field_count) : (i += 1) { | 27356 | while (i < field_count) : (i += 1) { |
| 27311 | const elem_src = operand_src; // TODO better source location | 27357 | const elem_src = operand_src; // TODO better source location |
| ... | @@ -27804,7 +27850,7 @@ fn beginComptimePtrMutation( | ... | @@ -27804,7 +27850,7 @@ fn beginComptimePtrMutation( |
| 27804 | 27850 | ||
| 27805 | switch (parent.ty.zigTypeTag(mod)) { | 27851 | switch (parent.ty.zigTypeTag(mod)) { |
| 27806 | .Struct => { | 27852 | .Struct => { |
| 27807 | const fields = try arena.alloc(Value, parent.ty.structFieldCount()); | 27853 | const fields = try arena.alloc(Value, parent.ty.structFieldCount(mod)); |
| 27808 | @memset(fields, Value.undef); | 27854 | @memset(fields, Value.undef); |
| 27809 | 27855 | ||
| 27810 | val_ptr.* = try Value.Tag.aggregate.create(arena, fields); | 27856 | val_ptr.* = try Value.Tag.aggregate.create(arena, fields); |
| ... | @@ -27813,7 +27859,7 @@ fn beginComptimePtrMutation( | ... | @@ -27813,7 +27859,7 @@ fn beginComptimePtrMutation( |
| 27813 | sema, | 27859 | sema, |
| 27814 | block, | 27860 | block, |
| 27815 | src, | 27861 | src, |
| 27816 | parent.ty.structFieldType(field_index), | 27862 | parent.ty.structFieldType(field_index, mod), |
| 27817 | &fields[field_index], | 27863 | &fields[field_index], |
| 27818 | ptr_elem_ty, | 27864 | ptr_elem_ty, |
| 27819 | parent.decl_ref_mut, | 27865 | parent.decl_ref_mut, |
| ... | @@ -27832,7 +27878,7 @@ fn beginComptimePtrMutation( | ... | @@ -27832,7 +27878,7 @@ fn beginComptimePtrMutation( |
| 27832 | sema, | 27878 | sema, |
| 27833 | block, | 27879 | block, |
| 27834 | src, | 27880 | src, |
| 27835 | parent.ty.structFieldType(field_index), | 27881 | parent.ty.structFieldType(field_index, mod), |
| 27836 | &payload.data.val, | 27882 | &payload.data.val, |
| 27837 | ptr_elem_ty, | 27883 | ptr_elem_ty, |
| 27838 | parent.decl_ref_mut, | 27884 | parent.decl_ref_mut, |
| ... | @@ -27878,7 +27924,7 @@ fn beginComptimePtrMutation( | ... | @@ -27878,7 +27924,7 @@ fn beginComptimePtrMutation( |
| 27878 | sema, | 27924 | sema, |
| 27879 | block, | 27925 | block, |
| 27880 | src, | 27926 | src, |
| 27881 | parent.ty.structFieldType(field_index), | 27927 | parent.ty.structFieldType(field_index, mod), |
| 27882 | duped, | 27928 | duped, |
| 27883 | ptr_elem_ty, | 27929 | ptr_elem_ty, |
| 27884 | parent.decl_ref_mut, | 27930 | parent.decl_ref_mut, |
| ... | @@ -27889,7 +27935,7 @@ fn beginComptimePtrMutation( | ... | @@ -27889,7 +27935,7 @@ fn beginComptimePtrMutation( |
| 27889 | sema, | 27935 | sema, |
| 27890 | block, | 27936 | block, |
| 27891 | src, | 27937 | src, |
| 27892 | parent.ty.structFieldType(field_index), | 27938 | parent.ty.structFieldType(field_index, mod), |
| 27893 | &val_ptr.castTag(.aggregate).?.data[field_index], | 27939 | &val_ptr.castTag(.aggregate).?.data[field_index], |
| 27894 | ptr_elem_ty, | 27940 | ptr_elem_ty, |
| 27895 | parent.decl_ref_mut, | 27941 | parent.decl_ref_mut, |
| ... | @@ -27907,7 +27953,7 @@ fn beginComptimePtrMutation( | ... | @@ -27907,7 +27953,7 @@ fn beginComptimePtrMutation( |
| 27907 | sema, | 27953 | sema, |
| 27908 | block, | 27954 | block, |
| 27909 | src, | 27955 | src, |
| 27910 | parent.ty.structFieldType(field_index), | 27956 | parent.ty.structFieldType(field_index, mod), |
| 27911 | &payload.val, | 27957 | &payload.val, |
| 27912 | ptr_elem_ty, | 27958 | ptr_elem_ty, |
| 27913 | parent.decl_ref_mut, | 27959 | parent.decl_ref_mut, |
| ... | @@ -28269,8 +28315,8 @@ fn beginComptimePtrLoad( | ... | @@ -28269,8 +28315,8 @@ fn beginComptimePtrLoad( |
| 28269 | var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.container_ptr, field_ptr.container_ty); | 28315 | var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.container_ptr, field_ptr.container_ty); |
| 28270 | 28316 | ||
| 28271 | if (field_ptr.container_ty.hasWellDefinedLayout(mod)) { | 28317 | if (field_ptr.container_ty.hasWellDefinedLayout(mod)) { |
| 28272 | const struct_ty = field_ptr.container_ty.castTag(.@"struct"); | 28318 | const struct_obj = mod.typeToStruct(field_ptr.container_ty); |
| 28273 | if (struct_ty != null and struct_ty.?.data.layout == .Packed) { | 28319 | if (struct_obj != null and struct_obj.?.layout == .Packed) { |
| 28274 | // packed structs are not byte addressable | 28320 | // packed structs are not byte addressable |
| 28275 | deref.parent = null; | 28321 | deref.parent = null; |
| 28276 | } else if (deref.parent) |*parent| { | 28322 | } else if (deref.parent) |*parent| { |
| ... | @@ -28310,7 +28356,7 @@ fn beginComptimePtrLoad( | ... | @@ -28310,7 +28356,7 @@ fn beginComptimePtrLoad( |
| 28310 | else => unreachable, | 28356 | else => unreachable, |
| 28311 | }; | 28357 | }; |
| 28312 | } else { | 28358 | } else { |
| 28313 | const field_ty = field_ptr.container_ty.structFieldType(field_index); | 28359 | const field_ty = field_ptr.container_ty.structFieldType(field_index, mod); |
| 28314 | deref.pointee = TypedValue{ | 28360 | deref.pointee = TypedValue{ |
| 28315 | .ty = field_ty, | 28361 | .ty = field_ty, |
| 28316 | .val = try tv.val.fieldValue(tv.ty, mod, field_index), | 28362 | .val = try tv.val.fieldValue(tv.ty, mod, field_index), |
| ... | @@ -28483,7 +28529,7 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul | ... | @@ -28483,7 +28529,7 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul |
| 28483 | const inst_info = inst_ty.ptrInfo(mod); | 28529 | const inst_info = inst_ty.ptrInfo(mod); |
| 28484 | const len0 = (inst_info.pointee_type.zigTypeTag(mod) == .Array and (inst_info.pointee_type.arrayLenIncludingSentinel(mod) == 0 or | 28530 | const len0 = (inst_info.pointee_type.zigTypeTag(mod) == .Array and (inst_info.pointee_type.arrayLenIncludingSentinel(mod) == 0 or |
| 28485 | (inst_info.pointee_type.arrayLen(mod) == 0 and dest_info.sentinel == null and dest_info.size != .C and dest_info.size != .Many))) or | 28531 | (inst_info.pointee_type.arrayLen(mod) == 0 and dest_info.sentinel == null and dest_info.size != .C and dest_info.size != .Many))) or |
| 28486 | (inst_info.pointee_type.isTuple() and inst_info.pointee_type.structFieldCount() == 0); | 28532 | (inst_info.pointee_type.isTuple(mod) and inst_info.pointee_type.structFieldCount(mod) == 0); |
| 28487 | 28533 | ||
| 28488 | const ok_cv_qualifiers = | 28534 | const ok_cv_qualifiers = |
| 28489 | ((inst_info.mutable or !dest_info.mutable) or len0) and | 28535 | ((inst_info.mutable or !dest_info.mutable) or len0) and |
| ... | @@ -28714,8 +28760,9 @@ fn coerceAnonStructToUnion( | ... | @@ -28714,8 +28760,9 @@ fn coerceAnonStructToUnion( |
| 28714 | inst: Air.Inst.Ref, | 28760 | inst: Air.Inst.Ref, |
| 28715 | inst_src: LazySrcLoc, | 28761 | inst_src: LazySrcLoc, |
| 28716 | ) !Air.Inst.Ref { | 28762 | ) !Air.Inst.Ref { |
| 28763 | const mod = sema.mod; | ||
| 28717 | const inst_ty = sema.typeOf(inst); | 28764 | const inst_ty = sema.typeOf(inst); |
| 28718 | const field_count = inst_ty.structFieldCount(); | 28765 | const field_count = inst_ty.structFieldCount(mod); |
| 28719 | if (field_count != 1) { | 28766 | if (field_count != 1) { |
| 28720 | const msg = msg: { | 28767 | const msg = msg: { |
| 28721 | const msg = if (field_count > 1) try sema.errMsg( | 28768 | const msg = if (field_count > 1) try sema.errMsg( |
| ... | @@ -28927,7 +28974,7 @@ fn coerceTupleToSlicePtrs( | ... | @@ -28927,7 +28974,7 @@ fn coerceTupleToSlicePtrs( |
| 28927 | const tuple_ty = sema.typeOf(ptr_tuple).childType(mod); | 28974 | const tuple_ty = sema.typeOf(ptr_tuple).childType(mod); |
| 28928 | const tuple = try sema.analyzeLoad(block, tuple_src, ptr_tuple, tuple_src); | 28975 | const tuple = try sema.analyzeLoad(block, tuple_src, ptr_tuple, tuple_src); |
| 28929 | const slice_info = slice_ty.ptrInfo(mod); | 28976 | const slice_info = slice_ty.ptrInfo(mod); |
| 28930 | const array_ty = try Type.array(sema.arena, tuple_ty.structFieldCount(), slice_info.sentinel, slice_info.pointee_type, sema.mod); | 28977 | const array_ty = try Type.array(sema.arena, tuple_ty.structFieldCount(mod), slice_info.sentinel, slice_info.pointee_type, sema.mod); |
| 28931 | const array_inst = try sema.coerceTupleToArray(block, array_ty, slice_ty_src, tuple, tuple_src); | 28978 | const array_inst = try sema.coerceTupleToArray(block, array_ty, slice_ty_src, tuple, tuple_src); |
| 28932 | if (slice_info.@"align" != 0) { | 28979 | if (slice_info.@"align" != 0) { |
| 28933 | return sema.fail(block, slice_ty_src, "TODO: override the alignment of the array decl we create here", .{}); | 28980 | return sema.fail(block, slice_ty_src, "TODO: override the alignment of the array decl we create here", .{}); |
| ... | @@ -28966,20 +29013,21 @@ fn coerceTupleToStruct( | ... | @@ -28966,20 +29013,21 @@ fn coerceTupleToStruct( |
| 28966 | inst: Air.Inst.Ref, | 29013 | inst: Air.Inst.Ref, |
| 28967 | inst_src: LazySrcLoc, | 29014 | inst_src: LazySrcLoc, |
| 28968 | ) !Air.Inst.Ref { | 29015 | ) !Air.Inst.Ref { |
| 29016 | const mod = sema.mod; | ||
| 28969 | const struct_ty = try sema.resolveTypeFields(dest_ty); | 29017 | const struct_ty = try sema.resolveTypeFields(dest_ty); |
| 28970 | 29018 | ||
| 28971 | if (struct_ty.isTupleOrAnonStruct()) { | 29019 | if (struct_ty.isTupleOrAnonStruct(mod)) { |
| 28972 | return sema.coerceTupleToTuple(block, struct_ty, inst, inst_src); | 29020 | return sema.coerceTupleToTuple(block, struct_ty, inst, inst_src); |
| 28973 | } | 29021 | } |
| 28974 | 29022 | ||
| 28975 | const fields = struct_ty.structFields(); | 29023 | const fields = struct_ty.structFields(mod); |
| 28976 | const field_vals = try sema.arena.alloc(Value, fields.count()); | 29024 | const field_vals = try sema.arena.alloc(Value, fields.count()); |
| 28977 | const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len); | 29025 | const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len); |
| 28978 | @memset(field_refs, .none); | 29026 | @memset(field_refs, .none); |
| 28979 | 29027 | ||
| 28980 | const inst_ty = sema.typeOf(inst); | 29028 | const inst_ty = sema.typeOf(inst); |
| 28981 | var runtime_src: ?LazySrcLoc = null; | 29029 | var runtime_src: ?LazySrcLoc = null; |
| 28982 | const field_count = inst_ty.structFieldCount(); | 29030 | const field_count = inst_ty.structFieldCount(mod); |
| 28983 | var field_i: u32 = 0; | 29031 | var field_i: u32 = 0; |
| 28984 | while (field_i < field_count) : (field_i += 1) { | 29032 | while (field_i < field_count) : (field_i += 1) { |
| 28985 | const field_src = inst_src; // TODO better source location | 29033 | const field_src = inst_src; // TODO better source location |
| ... | @@ -29061,13 +29109,14 @@ fn coerceTupleToTuple( | ... | @@ -29061,13 +29109,14 @@ fn coerceTupleToTuple( |
| 29061 | inst: Air.Inst.Ref, | 29109 | inst: Air.Inst.Ref, |
| 29062 | inst_src: LazySrcLoc, | 29110 | inst_src: LazySrcLoc, |
| 29063 | ) !Air.Inst.Ref { | 29111 | ) !Air.Inst.Ref { |
| 29064 | const dest_field_count = tuple_ty.structFieldCount(); | 29112 | const mod = sema.mod; |
| 29113 | const dest_field_count = tuple_ty.structFieldCount(mod); | ||
| 29065 | const field_vals = try sema.arena.alloc(Value, dest_field_count); | 29114 | const field_vals = try sema.arena.alloc(Value, dest_field_count); |
| 29066 | const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len); | 29115 | const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len); |
| 29067 | @memset(field_refs, .none); | 29116 | @memset(field_refs, .none); |
| 29068 | 29117 | ||
| 29069 | const inst_ty = sema.typeOf(inst); | 29118 | const inst_ty = sema.typeOf(inst); |
| 29070 | const inst_field_count = inst_ty.structFieldCount(); | 29119 | const inst_field_count = inst_ty.structFieldCount(mod); |
| 29071 | if (inst_field_count > dest_field_count) return error.NotCoercible; | 29120 | if (inst_field_count > dest_field_count) return error.NotCoercible; |
| 29072 | 29121 | ||
| 29073 | var runtime_src: ?LazySrcLoc = null; | 29122 | var runtime_src: ?LazySrcLoc = null; |
| ... | @@ -29085,8 +29134,8 @@ fn coerceTupleToTuple( | ... | @@ -29085,8 +29134,8 @@ fn coerceTupleToTuple( |
| 29085 | 29134 | ||
| 29086 | const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src); | 29135 | const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src); |
| 29087 | 29136 | ||
| 29088 | const field_ty = tuple_ty.structFieldType(field_i); | 29137 | const field_ty = tuple_ty.structFieldType(field_i, mod); |
| 29089 | const default_val = tuple_ty.structFieldDefaultValue(field_i); | 29138 | const default_val = tuple_ty.structFieldDefaultValue(field_i, mod); |
| 29090 | const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i); | 29139 | const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i); |
| 29091 | const coerced = try sema.coerce(block, field_ty, elem_ref, field_src); | 29140 | const coerced = try sema.coerce(block, field_ty, elem_ref, field_src); |
| 29092 | field_refs[field_index] = coerced; | 29141 | field_refs[field_index] = coerced; |
| ... | @@ -29115,12 +29164,12 @@ fn coerceTupleToTuple( | ... | @@ -29115,12 +29164,12 @@ fn coerceTupleToTuple( |
| 29115 | for (field_refs, 0..) |*field_ref, i| { | 29164 | for (field_refs, 0..) |*field_ref, i| { |
| 29116 | if (field_ref.* != .none) continue; | 29165 | if (field_ref.* != .none) continue; |
| 29117 | 29166 | ||
| 29118 | const default_val = tuple_ty.structFieldDefaultValue(i); | 29167 | const default_val = tuple_ty.structFieldDefaultValue(i, mod); |
| 29119 | const field_ty = tuple_ty.structFieldType(i); | 29168 | const field_ty = tuple_ty.structFieldType(i, mod); |
| 29120 | 29169 | ||
| 29121 | const field_src = inst_src; // TODO better source location | 29170 | const field_src = inst_src; // TODO better source location |
| 29122 | if (default_val.ip_index == .unreachable_value) { | 29171 | if (default_val.ip_index == .unreachable_value) { |
| 29123 | if (tuple_ty.isTuple()) { | 29172 | if (tuple_ty.isTuple(mod)) { |
| 29124 | const template = "missing tuple field: {d}"; | 29173 | const template = "missing tuple field: {d}"; |
| 29125 | if (root_msg) |msg| { | 29174 | if (root_msg) |msg| { |
| 29126 | try sema.errNote(block, field_src, msg, template, .{i}); | 29175 | try sema.errNote(block, field_src, msg, template, .{i}); |
| ... | @@ -29130,7 +29179,7 @@ fn coerceTupleToTuple( | ... | @@ -29130,7 +29179,7 @@ fn coerceTupleToTuple( |
| 29130 | continue; | 29179 | continue; |
| 29131 | } | 29180 | } |
| 29132 | const template = "missing struct field: {s}"; | 29181 | const template = "missing struct field: {s}"; |
| 29133 | const args = .{tuple_ty.structFieldName(i)}; | 29182 | const args = .{tuple_ty.structFieldName(i, mod)}; |
| 29134 | if (root_msg) |msg| { | 29183 | if (root_msg) |msg| { |
| 29135 | try sema.errNote(block, field_src, msg, template, args); | 29184 | try sema.errNote(block, field_src, msg, template, args); |
| 29136 | } else { | 29185 | } else { |
| ... | @@ -31222,17 +31271,17 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -31222,17 +31271,17 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void { |
| 31222 | } | 31271 | } |
| 31223 | 31272 | ||
| 31224 | fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { | 31273 | fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 31274 | const mod = sema.mod; | ||
| 31225 | const resolved_ty = try sema.resolveTypeFields(ty); | 31275 | const resolved_ty = try sema.resolveTypeFields(ty); |
| 31226 | if (resolved_ty.castTag(.@"struct")) |payload| { | 31276 | if (mod.typeToStruct(resolved_ty)) |struct_obj| { |
| 31227 | const struct_obj = payload.data; | ||
| 31228 | switch (struct_obj.status) { | 31277 | switch (struct_obj.status) { |
| 31229 | .none, .have_field_types => {}, | 31278 | .none, .have_field_types => {}, |
| 31230 | .field_types_wip, .layout_wip => { | 31279 | .field_types_wip, .layout_wip => { |
| 31231 | const msg = try Module.ErrorMsg.create( | 31280 | const msg = try Module.ErrorMsg.create( |
| 31232 | sema.gpa, | 31281 | sema.gpa, |
| 31233 | struct_obj.srcLoc(sema.mod), | 31282 | struct_obj.srcLoc(mod), |
| 31234 | "struct '{}' depends on itself", | 31283 | "struct '{}' depends on itself", |
| 31235 | .{ty.fmt(sema.mod)}, | 31284 | .{ty.fmt(mod)}, |
| 31236 | ); | 31285 | ); |
| 31237 | return sema.failWithOwnedErrorMsg(msg); | 31286 | return sema.failWithOwnedErrorMsg(msg); |
| 31238 | }, | 31287 | }, |
| ... | @@ -31256,7 +31305,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -31256,7 +31305,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 31256 | } | 31305 | } |
| 31257 | 31306 | ||
| 31258 | if (struct_obj.layout == .Packed) { | 31307 | if (struct_obj.layout == .Packed) { |
| 31259 | try semaBackingIntType(sema.mod, struct_obj); | 31308 | try semaBackingIntType(mod, struct_obj); |
| 31260 | } | 31309 | } |
| 31261 | 31310 | ||
| 31262 | struct_obj.status = .have_layout; | 31311 | struct_obj.status = .have_layout; |
| ... | @@ -31265,20 +31314,20 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -31265,20 +31314,20 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 31265 | if (struct_obj.assumed_runtime_bits and !(try sema.typeHasRuntimeBits(resolved_ty))) { | 31314 | if (struct_obj.assumed_runtime_bits and !(try sema.typeHasRuntimeBits(resolved_ty))) { |
| 31266 | const msg = try Module.ErrorMsg.create( | 31315 | const msg = try Module.ErrorMsg.create( |
| 31267 | sema.gpa, | 31316 | sema.gpa, |
| 31268 | struct_obj.srcLoc(sema.mod), | 31317 | struct_obj.srcLoc(mod), |
| 31269 | "struct layout depends on it having runtime bits", | 31318 | "struct layout depends on it having runtime bits", |
| 31270 | .{}, | 31319 | .{}, |
| 31271 | ); | 31320 | ); |
| 31272 | return sema.failWithOwnedErrorMsg(msg); | 31321 | return sema.failWithOwnedErrorMsg(msg); |
| 31273 | } | 31322 | } |
| 31274 | 31323 | ||
| 31275 | if (struct_obj.layout == .Auto and sema.mod.backendSupportsFeature(.field_reordering)) { | 31324 | if (struct_obj.layout == .Auto and mod.backendSupportsFeature(.field_reordering)) { |
| 31276 | const optimized_order = if (struct_obj.owner_decl == sema.owner_decl_index) | 31325 | const optimized_order = if (struct_obj.owner_decl == sema.owner_decl_index) |
| 31277 | try sema.perm_arena.alloc(u32, struct_obj.fields.count()) | 31326 | try sema.perm_arena.alloc(u32, struct_obj.fields.count()) |
| 31278 | else blk: { | 31327 | else blk: { |
| 31279 | const decl = sema.mod.declPtr(struct_obj.owner_decl); | 31328 | const decl = mod.declPtr(struct_obj.owner_decl); |
| 31280 | var decl_arena: std.heap.ArenaAllocator = undefined; | 31329 | var decl_arena: std.heap.ArenaAllocator = undefined; |
| 31281 | const decl_arena_allocator = decl.value_arena.?.acquire(sema.mod.gpa, &decl_arena); | 31330 | const decl_arena_allocator = decl.value_arena.?.acquire(mod.gpa, &decl_arena); |
| 31282 | defer decl.value_arena.?.release(&decl_arena); | 31331 | defer decl.value_arena.?.release(&decl_arena); |
| 31283 | break :blk try decl_arena_allocator.alloc(u32, struct_obj.fields.count()); | 31332 | break :blk try decl_arena_allocator.alloc(u32, struct_obj.fields.count()); |
| 31284 | }; | 31333 | }; |
| ... | @@ -31528,7 +31577,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -31528,7 +31577,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 31528 | return switch (ty.ip_index) { | 31577 | return switch (ty.ip_index) { |
| 31529 | .empty_struct_type => false, | 31578 | .empty_struct_type => false, |
| 31530 | .none => switch (ty.tag()) { | 31579 | .none => switch (ty.tag()) { |
| 31531 | .empty_struct, | ||
| 31532 | .error_set, | 31580 | .error_set, |
| 31533 | .error_set_single, | 31581 | .error_set_single, |
| 31534 | .error_set_inferred, | 31582 | .error_set_inferred, |
| ... | @@ -31569,27 +31617,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -31569,27 +31617,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 31569 | return false; | 31617 | return false; |
| 31570 | }, | 31618 | }, |
| 31571 | 31619 | ||
| 31572 | .@"struct" => { | ||
| 31573 | const struct_obj = ty.castTag(.@"struct").?.data; | ||
| 31574 | switch (struct_obj.requires_comptime) { | ||
| 31575 | .no, .wip => return false, | ||
| 31576 | .yes => return true, | ||
| 31577 | .unknown => { | ||
| 31578 | var requires_comptime = false; | ||
| 31579 | struct_obj.requires_comptime = .wip; | ||
| 31580 | for (struct_obj.fields.values()) |field| { | ||
| 31581 | if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true; | ||
| 31582 | } | ||
| 31583 | if (requires_comptime) { | ||
| 31584 | struct_obj.requires_comptime = .yes; | ||
| 31585 | } else { | ||
| 31586 | struct_obj.requires_comptime = .no; | ||
| 31587 | } | ||
| 31588 | return requires_comptime; | ||
| 31589 | }, | ||
| 31590 | } | ||
| 31591 | }, | ||
| 31592 | |||
| 31593 | .@"union", .union_safety_tagged, .union_tagged => { | 31620 | .@"union", .union_safety_tagged, .union_tagged => { |
| 31594 | const union_obj = ty.cast(Type.Payload.Union).?.data; | 31621 | const union_obj = ty.cast(Type.Payload.Union).?.data; |
| 31595 | switch (union_obj.requires_comptime) { | 31622 | switch (union_obj.requires_comptime) { |
| ... | @@ -31686,7 +31713,27 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -31686,7 +31713,27 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 31686 | .type_info, | 31713 | .type_info, |
| 31687 | => true, | 31714 | => true, |
| 31688 | }, | 31715 | }, |
| 31689 | .struct_type => @panic("TODO"), | 31716 | .struct_type => |struct_type| { |
| 31717 | const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false; | ||
| 31718 | switch (struct_obj.requires_comptime) { | ||
| 31719 | .no, .wip => return false, | ||
| 31720 | .yes => return true, | ||
| 31721 | .unknown => { | ||
| 31722 | var requires_comptime = false; | ||
| 31723 | struct_obj.requires_comptime = .wip; | ||
| 31724 | for (struct_obj.fields.values()) |field| { | ||
| 31725 | if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true; | ||
| 31726 | } | ||
| 31727 | if (requires_comptime) { | ||
| 31728 | struct_obj.requires_comptime = .yes; | ||
| 31729 | } else { | ||
| 31730 | struct_obj.requires_comptime = .no; | ||
| 31731 | } | ||
| 31732 | return requires_comptime; | ||
| 31733 | }, | ||
| 31734 | } | ||
| 31735 | }, | ||
| 31736 | |||
| 31690 | .union_type => @panic("TODO"), | 31737 | .union_type => @panic("TODO"), |
| 31691 | .opaque_type => false, | 31738 | .opaque_type => false, |
| 31692 | 31739 | ||
| ... | @@ -31697,6 +31744,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -31697,6 +31744,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 31697 | .ptr => unreachable, | 31744 | .ptr => unreachable, |
| 31698 | .opt => unreachable, | 31745 | .opt => unreachable, |
| 31699 | .enum_tag => unreachable, | 31746 | .enum_tag => unreachable, |
| 31747 | .aggregate => unreachable, | ||
| 31700 | }, | 31748 | }, |
| 31701 | }; | 31749 | }; |
| 31702 | } | 31750 | } |
| ... | @@ -31710,16 +31758,21 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -31710,16 +31758,21 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void { |
| 31710 | const child_ty = try sema.resolveTypeFields(ty.childType(mod)); | 31758 | const child_ty = try sema.resolveTypeFields(ty.childType(mod)); |
| 31711 | return sema.resolveTypeFully(child_ty); | 31759 | return sema.resolveTypeFully(child_ty); |
| 31712 | }, | 31760 | }, |
| 31713 | .Struct => switch (ty.tag()) { | 31761 | .Struct => switch (ty.ip_index) { |
| 31714 | .@"struct" => return sema.resolveStructFully(ty), | 31762 | .none => switch (ty.tag()) { |
| 31715 | .tuple, .anon_struct => { | 31763 | .tuple, .anon_struct => { |
| 31716 | const tuple = ty.tupleFields(); | 31764 | const tuple = ty.tupleFields(); |
| 31717 | 31765 | ||
| 31718 | for (tuple.types) |field_ty| { | 31766 | for (tuple.types) |field_ty| { |
| 31719 | try sema.resolveTypeFully(field_ty); | 31767 | try sema.resolveTypeFully(field_ty); |
| 31720 | } | 31768 | } |
| 31769 | }, | ||
| 31770 | else => {}, | ||
| 31771 | }, | ||
| 31772 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 31773 | .struct_type => return sema.resolveStructFully(ty), | ||
| 31774 | else => {}, | ||
| 31721 | }, | 31775 | }, |
| 31722 | else => {}, | ||
| 31723 | }, | 31776 | }, |
| 31724 | .Union => return sema.resolveUnionFully(ty), | 31777 | .Union => return sema.resolveUnionFully(ty), |
| 31725 | .Array => return sema.resolveTypeFully(ty.childType(mod)), | 31778 | .Array => return sema.resolveTypeFully(ty.childType(mod)), |
| ... | @@ -31746,9 +31799,9 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -31746,9 +31799,9 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void { |
| 31746 | fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void { | 31799 | fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void { |
| 31747 | try sema.resolveStructLayout(ty); | 31800 | try sema.resolveStructLayout(ty); |
| 31748 | 31801 | ||
| 31802 | const mod = sema.mod; | ||
| 31749 | const resolved_ty = try sema.resolveTypeFields(ty); | 31803 | const resolved_ty = try sema.resolveTypeFields(ty); |
| 31750 | const payload = resolved_ty.castTag(.@"struct").?; | 31804 | const struct_obj = mod.typeToStruct(resolved_ty).?; |
| 31751 | const struct_obj = payload.data; | ||
| 31752 | 31805 | ||
| 31753 | switch (struct_obj.status) { | 31806 | switch (struct_obj.status) { |
| 31754 | .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {}, | 31807 | .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {}, |
| ... | @@ -31806,11 +31859,6 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type { | ... | @@ -31806,11 +31859,6 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type { |
| 31806 | 31859 | ||
| 31807 | switch (ty.ip_index) { | 31860 | switch (ty.ip_index) { |
| 31808 | .none => switch (ty.tag()) { | 31861 | .none => switch (ty.tag()) { |
| 31809 | .@"struct" => { | ||
| 31810 | const struct_obj = ty.castTag(.@"struct").?.data; | ||
| 31811 | try sema.resolveTypeFieldsStruct(ty, struct_obj); | ||
| 31812 | return ty; | ||
| 31813 | }, | ||
| 31814 | .@"union", .union_safety_tagged, .union_tagged => { | 31862 | .@"union", .union_safety_tagged, .union_tagged => { |
| 31815 | const union_obj = ty.cast(Type.Payload.Union).?.data; | 31863 | const union_obj = ty.cast(Type.Payload.Union).?.data; |
| 31816 | try sema.resolveTypeFieldsUnion(ty, union_obj); | 31864 | try sema.resolveTypeFieldsUnion(ty, union_obj); |
| ... | @@ -31904,7 +31952,11 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type { | ... | @@ -31904,7 +31952,11 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type { |
| 31904 | .prefetch_options_type => return sema.getBuiltinType("PrefetchOptions"), | 31952 | .prefetch_options_type => return sema.getBuiltinType("PrefetchOptions"), |
| 31905 | 31953 | ||
| 31906 | _ => switch (mod.intern_pool.indexToKey(ty.ip_index)) { | 31954 | _ => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 31907 | .struct_type => @panic("TODO"), | 31955 | .struct_type => |struct_type| { |
| 31956 | const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return ty; | ||
| 31957 | try sema.resolveTypeFieldsStruct(ty, struct_obj); | ||
| 31958 | return ty; | ||
| 31959 | }, | ||
| 31908 | .union_type => @panic("TODO"), | 31960 | .union_type => @panic("TODO"), |
| 31909 | else => return ty, | 31961 | else => return ty, |
| 31910 | }, | 31962 | }, |
| ... | @@ -33010,28 +33062,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -33010,28 +33062,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 33010 | } | 33062 | } |
| 33011 | }, | 33063 | }, |
| 33012 | 33064 | ||
| 33013 | .@"struct" => { | ||
| 33014 | const resolved_ty = try sema.resolveTypeFields(ty); | ||
| 33015 | const s = resolved_ty.castTag(.@"struct").?.data; | ||
| 33016 | for (s.fields.values(), 0..) |field, i| { | ||
| 33017 | if (field.is_comptime) continue; | ||
| 33018 | if (field.ty.eql(resolved_ty, sema.mod)) { | ||
| 33019 | const msg = try Module.ErrorMsg.create( | ||
| 33020 | sema.gpa, | ||
| 33021 | s.srcLoc(sema.mod), | ||
| 33022 | "struct '{}' depends on itself", | ||
| 33023 | .{ty.fmt(sema.mod)}, | ||
| 33024 | ); | ||
| 33025 | try sema.addFieldErrNote(resolved_ty, i, msg, "while checking this field", .{}); | ||
| 33026 | return sema.failWithOwnedErrorMsg(msg); | ||
| 33027 | } | ||
| 33028 | if ((try sema.typeHasOnePossibleValue(field.ty)) == null) { | ||
| 33029 | return null; | ||
| 33030 | } | ||
| 33031 | } | ||
| 33032 | return Value.empty_struct; | ||
| 33033 | }, | ||
| 33034 | |||
| 33035 | .tuple, .anon_struct => { | 33065 | .tuple, .anon_struct => { |
| 33036 | const tuple = ty.tupleFields(); | 33066 | const tuple = ty.tupleFields(); |
| 33037 | for (tuple.values, 0..) |val, i| { | 33067 | for (tuple.values, 0..) |val, i| { |
| ... | @@ -33120,8 +33150,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -33120,8 +33150,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 33120 | }); | 33150 | }); |
| 33121 | }, | 33151 | }, |
| 33122 | 33152 | ||
| 33123 | .empty_struct => return Value.empty_struct, | ||
| 33124 | |||
| 33125 | .array => { | 33153 | .array => { |
| 33126 | if (ty.arrayLen(mod) == 0) | 33154 | if (ty.arrayLen(mod) == 0) |
| 33127 | return Value.initTag(.empty_array); | 33155 | return Value.initTag(.empty_array); |
| ... | @@ -33212,7 +33240,34 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -33212,7 +33240,34 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 33212 | .generic_poison => return error.GenericPoison, | 33240 | .generic_poison => return error.GenericPoison, |
| 33213 | .var_args_param => unreachable, | 33241 | .var_args_param => unreachable, |
| 33214 | }, | 33242 | }, |
| 33215 | .struct_type => @panic("TODO"), | 33243 | .struct_type => |struct_type| { |
| 33244 | const resolved_ty = try sema.resolveTypeFields(ty); | ||
| 33245 | if (mod.structPtrUnwrap(struct_type.index)) |s| { | ||
| 33246 | for (s.fields.values(), 0..) |field, i| { | ||
| 33247 | if (field.is_comptime) continue; | ||
| 33248 | if (field.ty.eql(resolved_ty, sema.mod)) { | ||
| 33249 | const msg = try Module.ErrorMsg.create( | ||
| 33250 | sema.gpa, | ||
| 33251 | s.srcLoc(sema.mod), | ||
| 33252 | "struct '{}' depends on itself", | ||
| 33253 | .{ty.fmt(sema.mod)}, | ||
| 33254 | ); | ||
| 33255 | try sema.addFieldErrNote(resolved_ty, i, msg, "while checking this field", .{}); | ||
| 33256 | return sema.failWithOwnedErrorMsg(msg); | ||
| 33257 | } | ||
| 33258 | if ((try sema.typeHasOnePossibleValue(field.ty)) == null) { | ||
| 33259 | return null; | ||
| 33260 | } | ||
| 33261 | } | ||
| 33262 | } | ||
| 33263 | // In this case the struct has no fields and therefore has one possible value. | ||
| 33264 | const empty = try mod.intern(.{ .aggregate = .{ | ||
| 33265 | .ty = ty.ip_index, | ||
| 33266 | .fields = &.{}, | ||
| 33267 | } }); | ||
| 33268 | return empty.toValue(); | ||
| 33269 | }, | ||
| 33270 | |||
| 33216 | .union_type => @panic("TODO"), | 33271 | .union_type => @panic("TODO"), |
| 33217 | .opaque_type => null, | 33272 | .opaque_type => null, |
| 33218 | 33273 | ||
| ... | @@ -33223,6 +33278,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -33223,6 +33278,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 33223 | .ptr => unreachable, | 33278 | .ptr => unreachable, |
| 33224 | .opt => unreachable, | 33279 | .opt => unreachable, |
| 33225 | .enum_tag => unreachable, | 33280 | .enum_tag => unreachable, |
| 33281 | .aggregate => unreachable, | ||
| 33226 | }, | 33282 | }, |
| 33227 | } | 33283 | } |
| 33228 | } | 33284 | } |
| ... | @@ -33614,7 +33670,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -33614,7 +33670,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 33614 | .empty_struct_type => false, | 33670 | .empty_struct_type => false, |
| 33615 | 33671 | ||
| 33616 | .none => switch (ty.tag()) { | 33672 | .none => switch (ty.tag()) { |
| 33617 | .empty_struct, | ||
| 33618 | .error_set, | 33673 | .error_set, |
| 33619 | .error_set_single, | 33674 | .error_set_single, |
| 33620 | .error_set_inferred, | 33675 | .error_set_inferred, |
| ... | @@ -33655,31 +33710,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -33655,31 +33710,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 33655 | return false; | 33710 | return false; |
| 33656 | }, | 33711 | }, |
| 33657 | 33712 | ||
| 33658 | .@"struct" => { | ||
| 33659 | const struct_obj = ty.castTag(.@"struct").?.data; | ||
| 33660 | switch (struct_obj.requires_comptime) { | ||
| 33661 | .no, .wip => return false, | ||
| 33662 | .yes => return true, | ||
| 33663 | .unknown => { | ||
| 33664 | if (struct_obj.status == .field_types_wip) | ||
| 33665 | return false; | ||
| 33666 | |||
| 33667 | try sema.resolveTypeFieldsStruct(ty, struct_obj); | ||
| 33668 | |||
| 33669 | struct_obj.requires_comptime = .wip; | ||
| 33670 | for (struct_obj.fields.values()) |field| { | ||
| 33671 | if (field.is_comptime) continue; | ||
| 33672 | if (try sema.typeRequiresComptime(field.ty)) { | ||
| 33673 | struct_obj.requires_comptime = .yes; | ||
| 33674 | return true; | ||
| 33675 | } | ||
| 33676 | } | ||
| 33677 | struct_obj.requires_comptime = .no; | ||
| 33678 | return false; | ||
| 33679 | }, | ||
| 33680 | } | ||
| 33681 | }, | ||
| 33682 | |||
| 33683 | .@"union", .union_safety_tagged, .union_tagged => { | 33713 | .@"union", .union_safety_tagged, .union_tagged => { |
| 33684 | const union_obj = ty.cast(Type.Payload.Union).?.data; | 33714 | const union_obj = ty.cast(Type.Payload.Union).?.data; |
| 33685 | switch (union_obj.requires_comptime) { | 33715 | switch (union_obj.requires_comptime) { |
| ... | @@ -33782,7 +33812,31 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -33782,7 +33812,31 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 33782 | 33812 | ||
| 33783 | .var_args_param => unreachable, | 33813 | .var_args_param => unreachable, |
| 33784 | }, | 33814 | }, |
| 33785 | .struct_type => @panic("TODO"), | 33815 | .struct_type => |struct_type| { |
| 33816 | const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false; | ||
| 33817 | switch (struct_obj.requires_comptime) { | ||
| 33818 | .no, .wip => return false, | ||
| 33819 | .yes => return true, | ||
| 33820 | .unknown => { | ||
| 33821 | if (struct_obj.status == .field_types_wip) | ||
| 33822 | return false; | ||
| 33823 | |||
| 33824 | try sema.resolveTypeFieldsStruct(ty, struct_obj); | ||
| 33825 | |||
| 33826 | struct_obj.requires_comptime = .wip; | ||
| 33827 | for (struct_obj.fields.values()) |field| { | ||
| 33828 | if (field.is_comptime) continue; | ||
| 33829 | if (try sema.typeRequiresComptime(field.ty)) { | ||
| 33830 | struct_obj.requires_comptime = .yes; | ||
| 33831 | return true; | ||
| 33832 | } | ||
| 33833 | } | ||
| 33834 | struct_obj.requires_comptime = .no; | ||
| 33835 | return false; | ||
| 33836 | }, | ||
| 33837 | } | ||
| 33838 | }, | ||
| 33839 | |||
| 33786 | .union_type => @panic("TODO"), | 33840 | .union_type => @panic("TODO"), |
| 33787 | .opaque_type => false, | 33841 | .opaque_type => false, |
| 33788 | 33842 | ||
| ... | @@ -33793,6 +33847,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -33793,6 +33847,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 33793 | .ptr => unreachable, | 33847 | .ptr => unreachable, |
| 33794 | .opt => unreachable, | 33848 | .opt => unreachable, |
| 33795 | .enum_tag => unreachable, | 33849 | .enum_tag => unreachable, |
| 33850 | .aggregate => unreachable, | ||
| 33796 | }, | 33851 | }, |
| 33797 | }; | 33852 | }; |
| 33798 | } | 33853 | } |
| ... | @@ -33864,11 +33919,12 @@ fn structFieldIndex( | ... | @@ -33864,11 +33919,12 @@ fn structFieldIndex( |
| 33864 | field_name: []const u8, | 33919 | field_name: []const u8, |
| 33865 | field_src: LazySrcLoc, | 33920 | field_src: LazySrcLoc, |
| 33866 | ) !u32 { | 33921 | ) !u32 { |
| 33922 | const mod = sema.mod; | ||
| 33867 | const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty); | 33923 | const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty); |
| 33868 | if (struct_ty.isAnonStruct()) { | 33924 | if (struct_ty.isAnonStruct()) { |
| 33869 | return sema.anonStructFieldIndex(block, struct_ty, field_name, field_src); | 33925 | return sema.anonStructFieldIndex(block, struct_ty, field_name, field_src); |
| 33870 | } else { | 33926 | } else { |
| 33871 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | 33927 | const struct_obj = mod.typeToStruct(struct_ty).?; |
| 33872 | const field_index_usize = struct_obj.fields.getIndex(field_name) orelse | 33928 | const field_index_usize = struct_obj.fields.getIndex(field_name) orelse |
| 33873 | return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name); | 33929 | return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name); |
| 33874 | return @intCast(u32, field_index_usize); | 33930 | return @intCast(u32, field_index_usize); |
src/TypedValue.zig+13-7| ... | @@ -180,7 +180,7 @@ pub fn print( | ... | @@ -180,7 +180,7 @@ pub fn print( |
| 180 | switch (field_ptr.container_ty.tag()) { | 180 | switch (field_ptr.container_ty.tag()) { |
| 181 | .tuple => return writer.print(".@\"{d}\"", .{field_ptr.field_index}), | 181 | .tuple => return writer.print(".@\"{d}\"", .{field_ptr.field_index}), |
| 182 | else => { | 182 | else => { |
| 183 | const field_name = field_ptr.container_ty.structFieldName(field_ptr.field_index); | 183 | const field_name = field_ptr.container_ty.structFieldName(field_ptr.field_index, mod); |
| 184 | return writer.print(".{s}", .{field_name}); | 184 | return writer.print(".{s}", .{field_name}); |
| 185 | }, | 185 | }, |
| 186 | } | 186 | } |
| ... | @@ -381,21 +381,27 @@ fn printAggregate( | ... | @@ -381,21 +381,27 @@ fn printAggregate( |
| 381 | } | 381 | } |
| 382 | if (ty.zigTypeTag(mod) == .Struct) { | 382 | if (ty.zigTypeTag(mod) == .Struct) { |
| 383 | try writer.writeAll(".{"); | 383 | try writer.writeAll(".{"); |
| 384 | const max_len = std.math.min(ty.structFieldCount(), max_aggregate_items); | 384 | const max_len = std.math.min(ty.structFieldCount(mod), max_aggregate_items); |
| 385 | 385 | ||
| 386 | var i: u32 = 0; | 386 | var i: u32 = 0; |
| 387 | while (i < max_len) : (i += 1) { | 387 | while (i < max_len) : (i += 1) { |
| 388 | if (i != 0) try writer.writeAll(", "); | 388 | if (i != 0) try writer.writeAll(", "); |
| 389 | switch (ty.tag()) { | 389 | switch (ty.ip_index) { |
| 390 | .anon_struct, .@"struct" => try writer.print(".{s} = ", .{ty.structFieldName(i)}), | 390 | .none => switch (ty.tag()) { |
| 391 | else => {}, | 391 | .anon_struct => try writer.print(".{s} = ", .{ty.structFieldName(i, mod)}), |
| 392 | else => {}, | ||
| 393 | }, | ||
| 394 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 395 | .struct_type => try writer.print(".{s} = ", .{ty.structFieldName(i, mod)}), | ||
| 396 | else => {}, | ||
| 397 | }, | ||
| 392 | } | 398 | } |
| 393 | try print(.{ | 399 | try print(.{ |
| 394 | .ty = ty.structFieldType(i), | 400 | .ty = ty.structFieldType(i, mod), |
| 395 | .val = try val.fieldValue(ty, mod, i), | 401 | .val = try val.fieldValue(ty, mod, i), |
| 396 | }, writer, level - 1, mod); | 402 | }, writer, level - 1, mod); |
| 397 | } | 403 | } |
| 398 | if (ty.structFieldCount() > max_aggregate_items) { | 404 | if (ty.structFieldCount(mod) > max_aggregate_items) { |
| 399 | try writer.writeAll(", ..."); | 405 | try writer.writeAll(", ..."); |
| 400 | } | 406 | } |
| 401 | return writer.writeAll("}"); | 407 | return writer.writeAll("}"); |
src/arch/aarch64/CodeGen.zig+3-3| ... | @@ -4119,7 +4119,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4119,7 +4119,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 4119 | const mod = self.bin_file.options.module.?; | 4119 | const mod = self.bin_file.options.module.?; |
| 4120 | const mcv = try self.resolveInst(operand); | 4120 | const mcv = try self.resolveInst(operand); |
| 4121 | const struct_ty = self.typeOf(operand); | 4121 | const struct_ty = self.typeOf(operand); |
| 4122 | const struct_field_ty = struct_ty.structFieldType(index); | 4122 | const struct_field_ty = struct_ty.structFieldType(index, mod); |
| 4123 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod)); | 4123 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod)); |
| 4124 | 4124 | ||
| 4125 | switch (mcv) { | 4125 | switch (mcv) { |
| ... | @@ -5466,10 +5466,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -5466,10 +5466,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 5466 | const reg_lock = self.register_manager.lockReg(rwo.reg); | 5466 | const reg_lock = self.register_manager.lockReg(rwo.reg); |
| 5467 | defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg); | 5467 | defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg); |
| 5468 | 5468 | ||
| 5469 | const wrapped_ty = ty.structFieldType(0); | 5469 | const wrapped_ty = ty.structFieldType(0, mod); |
| 5470 | try self.genSetStack(wrapped_ty, stack_offset, .{ .register = rwo.reg }); | 5470 | try self.genSetStack(wrapped_ty, stack_offset, .{ .register = rwo.reg }); |
| 5471 | 5471 | ||
| 5472 | const overflow_bit_ty = ty.structFieldType(1); | 5472 | const overflow_bit_ty = ty.structFieldType(1, mod); |
| 5473 | const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod)); | 5473 | const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod)); |
| 5474 | const raw_cond_reg = try self.register_manager.allocReg(null, gp); | 5474 | const raw_cond_reg = try self.register_manager.allocReg(null, gp); |
| 5475 | const cond_reg = self.registerAlias(raw_cond_reg, overflow_bit_ty); | 5475 | const cond_reg = self.registerAlias(raw_cond_reg, overflow_bit_ty); |
src/arch/aarch64/abi.zig+6-6| ... | @@ -21,7 +21,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class { | ... | @@ -21,7 +21,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class { |
| 21 | var maybe_float_bits: ?u16 = null; | 21 | var maybe_float_bits: ?u16 = null; |
| 22 | switch (ty.zigTypeTag(mod)) { | 22 | switch (ty.zigTypeTag(mod)) { |
| 23 | .Struct => { | 23 | .Struct => { |
| 24 | if (ty.containerLayout() == .Packed) return .byval; | 24 | if (ty.containerLayout(mod) == .Packed) return .byval; |
| 25 | const float_count = countFloats(ty, mod, &maybe_float_bits); | 25 | const float_count = countFloats(ty, mod, &maybe_float_bits); |
| 26 | if (float_count <= sret_float_count) return .{ .float_array = float_count }; | 26 | if (float_count <= sret_float_count) return .{ .float_array = float_count }; |
| 27 | 27 | ||
| ... | @@ -31,7 +31,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class { | ... | @@ -31,7 +31,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class { |
| 31 | return .integer; | 31 | return .integer; |
| 32 | }, | 32 | }, |
| 33 | .Union => { | 33 | .Union => { |
| 34 | if (ty.containerLayout() == .Packed) return .byval; | 34 | if (ty.containerLayout(mod) == .Packed) return .byval; |
| 35 | const float_count = countFloats(ty, mod, &maybe_float_bits); | 35 | const float_count = countFloats(ty, mod, &maybe_float_bits); |
| 36 | if (float_count <= sret_float_count) return .{ .float_array = float_count }; | 36 | if (float_count <= sret_float_count) return .{ .float_array = float_count }; |
| 37 | 37 | ||
| ... | @@ -90,11 +90,11 @@ fn countFloats(ty: Type, mod: *Module, maybe_float_bits: *?u16) u8 { | ... | @@ -90,11 +90,11 @@ fn countFloats(ty: Type, mod: *Module, maybe_float_bits: *?u16) u8 { |
| 90 | return max_count; | 90 | return max_count; |
| 91 | }, | 91 | }, |
| 92 | .Struct => { | 92 | .Struct => { |
| 93 | const fields_len = ty.structFieldCount(); | 93 | const fields_len = ty.structFieldCount(mod); |
| 94 | var count: u8 = 0; | 94 | var count: u8 = 0; |
| 95 | var i: u32 = 0; | 95 | var i: u32 = 0; |
| 96 | while (i < fields_len) : (i += 1) { | 96 | while (i < fields_len) : (i += 1) { |
| 97 | const field_ty = ty.structFieldType(i); | 97 | const field_ty = ty.structFieldType(i, mod); |
| 98 | const field_count = countFloats(field_ty, mod, maybe_float_bits); | 98 | const field_count = countFloats(field_ty, mod, maybe_float_bits); |
| 99 | if (field_count == invalid) return invalid; | 99 | if (field_count == invalid) return invalid; |
| 100 | count += field_count; | 100 | count += field_count; |
| ... | @@ -125,10 +125,10 @@ pub fn getFloatArrayType(ty: Type, mod: *Module) ?Type { | ... | @@ -125,10 +125,10 @@ pub fn getFloatArrayType(ty: Type, mod: *Module) ?Type { |
| 125 | return null; | 125 | return null; |
| 126 | }, | 126 | }, |
| 127 | .Struct => { | 127 | .Struct => { |
| 128 | const fields_len = ty.structFieldCount(); | 128 | const fields_len = ty.structFieldCount(mod); |
| 129 | var i: u32 = 0; | 129 | var i: u32 = 0; |
| 130 | while (i < fields_len) : (i += 1) { | 130 | while (i < fields_len) : (i += 1) { |
| 131 | const field_ty = ty.structFieldType(i); | 131 | const field_ty = ty.structFieldType(i, mod); |
| 132 | if (getFloatArrayType(field_ty, mod)) |some| return some; | 132 | if (getFloatArrayType(field_ty, mod)) |some| return some; |
| 133 | } | 133 | } |
| 134 | return null; | 134 | return null; |
src/arch/arm/CodeGen.zig+3-3| ... | @@ -2910,7 +2910,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2910,7 +2910,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2910 | const mcv = try self.resolveInst(operand); | 2910 | const mcv = try self.resolveInst(operand); |
| 2911 | const struct_ty = self.typeOf(operand); | 2911 | const struct_ty = self.typeOf(operand); |
| 2912 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod)); | 2912 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod)); |
| 2913 | const struct_field_ty = struct_ty.structFieldType(index); | 2913 | const struct_field_ty = struct_ty.structFieldType(index, mod); |
| 2914 | 2914 | ||
| 2915 | switch (mcv) { | 2915 | switch (mcv) { |
| 2916 | .dead, .unreach => unreachable, | 2916 | .dead, .unreach => unreachable, |
| ... | @@ -5404,10 +5404,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -5404,10 +5404,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 5404 | const reg_lock = self.register_manager.lockReg(reg); | 5404 | const reg_lock = self.register_manager.lockReg(reg); |
| 5405 | defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg); | 5405 | defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg); |
| 5406 | 5406 | ||
| 5407 | const wrapped_ty = ty.structFieldType(0); | 5407 | const wrapped_ty = ty.structFieldType(0, mod); |
| 5408 | try self.genSetStack(wrapped_ty, stack_offset, .{ .register = reg }); | 5408 | try self.genSetStack(wrapped_ty, stack_offset, .{ .register = reg }); |
| 5409 | 5409 | ||
| 5410 | const overflow_bit_ty = ty.structFieldType(1); | 5410 | const overflow_bit_ty = ty.structFieldType(1, mod); |
| 5411 | const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod)); | 5411 | const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod)); |
| 5412 | const cond_reg = try self.register_manager.allocReg(null, gp); | 5412 | const cond_reg = try self.register_manager.allocReg(null, gp); |
| 5413 | 5413 |
src/arch/arm/abi.zig+6-6| ... | @@ -32,7 +32,7 @@ pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class { | ... | @@ -32,7 +32,7 @@ pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class { |
| 32 | switch (ty.zigTypeTag(mod)) { | 32 | switch (ty.zigTypeTag(mod)) { |
| 33 | .Struct => { | 33 | .Struct => { |
| 34 | const bit_size = ty.bitSize(mod); | 34 | const bit_size = ty.bitSize(mod); |
| 35 | if (ty.containerLayout() == .Packed) { | 35 | if (ty.containerLayout(mod) == .Packed) { |
| 36 | if (bit_size > 64) return .memory; | 36 | if (bit_size > 64) return .memory; |
| 37 | return .byval; | 37 | return .byval; |
| 38 | } | 38 | } |
| ... | @@ -40,10 +40,10 @@ pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class { | ... | @@ -40,10 +40,10 @@ pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class { |
| 40 | const float_count = countFloats(ty, mod, &maybe_float_bits); | 40 | const float_count = countFloats(ty, mod, &maybe_float_bits); |
| 41 | if (float_count <= byval_float_count) return .byval; | 41 | if (float_count <= byval_float_count) return .byval; |
| 42 | 42 | ||
| 43 | const fields = ty.structFieldCount(); | 43 | const fields = ty.structFieldCount(mod); |
| 44 | var i: u32 = 0; | 44 | var i: u32 = 0; |
| 45 | while (i < fields) : (i += 1) { | 45 | while (i < fields) : (i += 1) { |
| 46 | const field_ty = ty.structFieldType(i); | 46 | const field_ty = ty.structFieldType(i, mod); |
| 47 | const field_alignment = ty.structFieldAlign(i, mod); | 47 | const field_alignment = ty.structFieldAlign(i, mod); |
| 48 | const field_size = field_ty.bitSize(mod); | 48 | const field_size = field_ty.bitSize(mod); |
| 49 | if (field_size > 32 or field_alignment > 32) { | 49 | if (field_size > 32 or field_alignment > 32) { |
| ... | @@ -54,7 +54,7 @@ pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class { | ... | @@ -54,7 +54,7 @@ pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class { |
| 54 | }, | 54 | }, |
| 55 | .Union => { | 55 | .Union => { |
| 56 | const bit_size = ty.bitSize(mod); | 56 | const bit_size = ty.bitSize(mod); |
| 57 | if (ty.containerLayout() == .Packed) { | 57 | if (ty.containerLayout(mod) == .Packed) { |
| 58 | if (bit_size > 64) return .memory; | 58 | if (bit_size > 64) return .memory; |
| 59 | return .byval; | 59 | return .byval; |
| 60 | } | 60 | } |
| ... | @@ -132,11 +132,11 @@ fn countFloats(ty: Type, mod: *Module, maybe_float_bits: *?u16) u32 { | ... | @@ -132,11 +132,11 @@ fn countFloats(ty: Type, mod: *Module, maybe_float_bits: *?u16) u32 { |
| 132 | return max_count; | 132 | return max_count; |
| 133 | }, | 133 | }, |
| 134 | .Struct => { | 134 | .Struct => { |
| 135 | const fields_len = ty.structFieldCount(); | 135 | const fields_len = ty.structFieldCount(mod); |
| 136 | var count: u32 = 0; | 136 | var count: u32 = 0; |
| 137 | var i: u32 = 0; | 137 | var i: u32 = 0; |
| 138 | while (i < fields_len) : (i += 1) { | 138 | while (i < fields_len) : (i += 1) { |
| 139 | const field_ty = ty.structFieldType(i); | 139 | const field_ty = ty.structFieldType(i, mod); |
| 140 | const field_count = countFloats(field_ty, mod, maybe_float_bits); | 140 | const field_count = countFloats(field_ty, mod, maybe_float_bits); |
| 141 | if (field_count == invalid) return invalid; | 141 | if (field_count == invalid) return invalid; |
| 142 | count += field_count; | 142 | count += field_count; |
src/arch/riscv64/abi.zig+2-2| ... | @@ -15,7 +15,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class { | ... | @@ -15,7 +15,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class { |
| 15 | switch (ty.zigTypeTag(mod)) { | 15 | switch (ty.zigTypeTag(mod)) { |
| 16 | .Struct => { | 16 | .Struct => { |
| 17 | const bit_size = ty.bitSize(mod); | 17 | const bit_size = ty.bitSize(mod); |
| 18 | if (ty.containerLayout() == .Packed) { | 18 | if (ty.containerLayout(mod) == .Packed) { |
| 19 | if (bit_size > max_byval_size) return .memory; | 19 | if (bit_size > max_byval_size) return .memory; |
| 20 | return .byval; | 20 | return .byval; |
| 21 | } | 21 | } |
| ... | @@ -26,7 +26,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class { | ... | @@ -26,7 +26,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class { |
| 26 | }, | 26 | }, |
| 27 | .Union => { | 27 | .Union => { |
| 28 | const bit_size = ty.bitSize(mod); | 28 | const bit_size = ty.bitSize(mod); |
| 29 | if (ty.containerLayout() == .Packed) { | 29 | if (ty.containerLayout(mod) == .Packed) { |
| 30 | if (bit_size > max_byval_size) return .memory; | 30 | if (bit_size > max_byval_size) return .memory; |
| 31 | return .byval; | 31 | return .byval; |
| 32 | } | 32 | } |
src/arch/sparc64/CodeGen.zig+2-2| ... | @@ -3993,10 +3993,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3993,10 +3993,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3993 | const reg_lock = self.register_manager.lockReg(rwo.reg); | 3993 | const reg_lock = self.register_manager.lockReg(rwo.reg); |
| 3994 | defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg); | 3994 | defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg); |
| 3995 | 3995 | ||
| 3996 | const wrapped_ty = ty.structFieldType(0); | 3996 | const wrapped_ty = ty.structFieldType(0, mod); |
| 3997 | try self.genSetStack(wrapped_ty, stack_offset, .{ .register = rwo.reg }); | 3997 | try self.genSetStack(wrapped_ty, stack_offset, .{ .register = rwo.reg }); |
| 3998 | 3998 | ||
| 3999 | const overflow_bit_ty = ty.structFieldType(1); | 3999 | const overflow_bit_ty = ty.structFieldType(1, mod); |
| 4000 | const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod)); | 4000 | const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod)); |
| 4001 | const cond_reg = try self.register_manager.allocReg(null, gp); | 4001 | const cond_reg = try self.register_manager.allocReg(null, gp); |
| 4002 | 4002 |
src/arch/wasm/CodeGen.zig+15-16| ... | @@ -1006,9 +1006,9 @@ fn typeToValtype(ty: Type, mod: *Module) wasm.Valtype { | ... | @@ -1006,9 +1006,9 @@ fn typeToValtype(ty: Type, mod: *Module) wasm.Valtype { |
| 1006 | if (info.bits > 32 and info.bits <= 128) break :blk wasm.Valtype.i64; | 1006 | if (info.bits > 32 and info.bits <= 128) break :blk wasm.Valtype.i64; |
| 1007 | break :blk wasm.Valtype.i32; // represented as pointer to stack | 1007 | break :blk wasm.Valtype.i32; // represented as pointer to stack |
| 1008 | }, | 1008 | }, |
| 1009 | .Struct => switch (ty.containerLayout()) { | 1009 | .Struct => switch (ty.containerLayout(mod)) { |
| 1010 | .Packed => { | 1010 | .Packed => { |
| 1011 | const struct_obj = ty.castTag(.@"struct").?.data; | 1011 | const struct_obj = mod.typeToStruct(ty).?; |
| 1012 | return typeToValtype(struct_obj.backing_int_ty, mod); | 1012 | return typeToValtype(struct_obj.backing_int_ty, mod); |
| 1013 | }, | 1013 | }, |
| 1014 | else => wasm.Valtype.i32, | 1014 | else => wasm.Valtype.i32, |
| ... | @@ -1017,7 +1017,7 @@ fn typeToValtype(ty: Type, mod: *Module) wasm.Valtype { | ... | @@ -1017,7 +1017,7 @@ fn typeToValtype(ty: Type, mod: *Module) wasm.Valtype { |
| 1017 | .direct => wasm.Valtype.v128, | 1017 | .direct => wasm.Valtype.v128, |
| 1018 | .unrolled => wasm.Valtype.i32, | 1018 | .unrolled => wasm.Valtype.i32, |
| 1019 | }, | 1019 | }, |
| 1020 | .Union => switch (ty.containerLayout()) { | 1020 | .Union => switch (ty.containerLayout(mod)) { |
| 1021 | .Packed => { | 1021 | .Packed => { |
| 1022 | const int_ty = mod.intType(.unsigned, @intCast(u16, ty.bitSize(mod))) catch @panic("out of memory"); | 1022 | const int_ty = mod.intType(.unsigned, @intCast(u16, ty.bitSize(mod))) catch @panic("out of memory"); |
| 1023 | return typeToValtype(int_ty, mod); | 1023 | return typeToValtype(int_ty, mod); |
| ... | @@ -1747,8 +1747,7 @@ fn isByRef(ty: Type, mod: *Module) bool { | ... | @@ -1747,8 +1747,7 @@ fn isByRef(ty: Type, mod: *Module) bool { |
| 1747 | return ty.hasRuntimeBitsIgnoreComptime(mod); | 1747 | return ty.hasRuntimeBitsIgnoreComptime(mod); |
| 1748 | }, | 1748 | }, |
| 1749 | .Struct => { | 1749 | .Struct => { |
| 1750 | if (ty.castTag(.@"struct")) |struct_ty| { | 1750 | if (mod.typeToStruct(ty)) |struct_obj| { |
| 1751 | const struct_obj = struct_ty.data; | ||
| 1752 | if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) { | 1751 | if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) { |
| 1753 | return isByRef(struct_obj.backing_int_ty, mod); | 1752 | return isByRef(struct_obj.backing_int_ty, mod); |
| 1754 | } | 1753 | } |
| ... | @@ -2954,11 +2953,11 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue | ... | @@ -2954,11 +2953,11 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue |
| 2954 | const parent_ty = field_ptr.container_ty; | 2953 | const parent_ty = field_ptr.container_ty; |
| 2955 | 2954 | ||
| 2956 | const field_offset = switch (parent_ty.zigTypeTag(mod)) { | 2955 | const field_offset = switch (parent_ty.zigTypeTag(mod)) { |
| 2957 | .Struct => switch (parent_ty.containerLayout()) { | 2956 | .Struct => switch (parent_ty.containerLayout(mod)) { |
| 2958 | .Packed => parent_ty.packedStructFieldByteOffset(field_ptr.field_index, mod), | 2957 | .Packed => parent_ty.packedStructFieldByteOffset(field_ptr.field_index, mod), |
| 2959 | else => parent_ty.structFieldOffset(field_ptr.field_index, mod), | 2958 | else => parent_ty.structFieldOffset(field_ptr.field_index, mod), |
| 2960 | }, | 2959 | }, |
| 2961 | .Union => switch (parent_ty.containerLayout()) { | 2960 | .Union => switch (parent_ty.containerLayout(mod)) { |
| 2962 | .Packed => 0, | 2961 | .Packed => 0, |
| 2963 | else => blk: { | 2962 | else => blk: { |
| 2964 | const layout: Module.Union.Layout = parent_ty.unionGetLayout(mod); | 2963 | const layout: Module.Union.Layout = parent_ty.unionGetLayout(mod); |
| ... | @@ -3158,7 +3157,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { | ... | @@ -3158,7 +3157,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { |
| 3158 | return WValue{ .imm32 = @boolToInt(is_pl) }; | 3157 | return WValue{ .imm32 = @boolToInt(is_pl) }; |
| 3159 | }, | 3158 | }, |
| 3160 | .Struct => { | 3159 | .Struct => { |
| 3161 | const struct_obj = ty.castTag(.@"struct").?.data; | 3160 | const struct_obj = mod.typeToStruct(ty).?; |
| 3162 | assert(struct_obj.layout == .Packed); | 3161 | assert(struct_obj.layout == .Packed); |
| 3163 | var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer | 3162 | var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer |
| 3164 | val.writeToPackedMemory(ty, func.bin_file.base.options.module.?, &buf, 0) catch unreachable; | 3163 | val.writeToPackedMemory(ty, func.bin_file.base.options.module.?, &buf, 0) catch unreachable; |
| ... | @@ -3225,7 +3224,7 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue { | ... | @@ -3225,7 +3224,7 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue { |
| 3225 | return WValue{ .imm32 = 0xaaaaaaaa }; | 3224 | return WValue{ .imm32 = 0xaaaaaaaa }; |
| 3226 | }, | 3225 | }, |
| 3227 | .Struct => { | 3226 | .Struct => { |
| 3228 | const struct_obj = ty.castTag(.@"struct").?.data; | 3227 | const struct_obj = mod.typeToStruct(ty).?; |
| 3229 | assert(struct_obj.layout == .Packed); | 3228 | assert(struct_obj.layout == .Packed); |
| 3230 | return func.emitUndefined(struct_obj.backing_int_ty); | 3229 | return func.emitUndefined(struct_obj.backing_int_ty); |
| 3231 | }, | 3230 | }, |
| ... | @@ -3635,7 +3634,7 @@ fn structFieldPtr( | ... | @@ -3635,7 +3634,7 @@ fn structFieldPtr( |
| 3635 | ) InnerError!WValue { | 3634 | ) InnerError!WValue { |
| 3636 | const mod = func.bin_file.base.options.module.?; | 3635 | const mod = func.bin_file.base.options.module.?; |
| 3637 | const result_ty = func.typeOfIndex(inst); | 3636 | const result_ty = func.typeOfIndex(inst); |
| 3638 | const offset = switch (struct_ty.containerLayout()) { | 3637 | const offset = switch (struct_ty.containerLayout(mod)) { |
| 3639 | .Packed => switch (struct_ty.zigTypeTag(mod)) { | 3638 | .Packed => switch (struct_ty.zigTypeTag(mod)) { |
| 3640 | .Struct => offset: { | 3639 | .Struct => offset: { |
| 3641 | if (result_ty.ptrInfo(mod).host_size != 0) { | 3640 | if (result_ty.ptrInfo(mod).host_size != 0) { |
| ... | @@ -3668,13 +3667,13 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3668,13 +3667,13 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3668 | const struct_ty = func.typeOf(struct_field.struct_operand); | 3667 | const struct_ty = func.typeOf(struct_field.struct_operand); |
| 3669 | const operand = try func.resolveInst(struct_field.struct_operand); | 3668 | const operand = try func.resolveInst(struct_field.struct_operand); |
| 3670 | const field_index = struct_field.field_index; | 3669 | const field_index = struct_field.field_index; |
| 3671 | const field_ty = struct_ty.structFieldType(field_index); | 3670 | const field_ty = struct_ty.structFieldType(field_index, mod); |
| 3672 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) return func.finishAir(inst, .none, &.{struct_field.struct_operand}); | 3671 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) return func.finishAir(inst, .none, &.{struct_field.struct_operand}); |
| 3673 | 3672 | ||
| 3674 | const result = switch (struct_ty.containerLayout()) { | 3673 | const result = switch (struct_ty.containerLayout(mod)) { |
| 3675 | .Packed => switch (struct_ty.zigTypeTag(mod)) { | 3674 | .Packed => switch (struct_ty.zigTypeTag(mod)) { |
| 3676 | .Struct => result: { | 3675 | .Struct => result: { |
| 3677 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | 3676 | const struct_obj = mod.typeToStruct(struct_ty).?; |
| 3678 | const offset = struct_obj.packedFieldBitOffset(mod, field_index); | 3677 | const offset = struct_obj.packedFieldBitOffset(mod, field_index); |
| 3679 | const backing_ty = struct_obj.backing_int_ty; | 3678 | const backing_ty = struct_obj.backing_int_ty; |
| 3680 | const wasm_bits = toWasmBits(backing_ty.intInfo(mod).bits) orelse { | 3679 | const wasm_bits = toWasmBits(backing_ty.intInfo(mod).bits) orelse { |
| ... | @@ -4998,12 +4997,12 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4998,12 +4997,12 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4998 | } | 4997 | } |
| 4999 | break :result_value result; | 4998 | break :result_value result; |
| 5000 | }, | 4999 | }, |
| 5001 | .Struct => switch (result_ty.containerLayout()) { | 5000 | .Struct => switch (result_ty.containerLayout(mod)) { |
| 5002 | .Packed => { | 5001 | .Packed => { |
| 5003 | if (isByRef(result_ty, mod)) { | 5002 | if (isByRef(result_ty, mod)) { |
| 5004 | return func.fail("TODO: airAggregateInit for packed structs larger than 64 bits", .{}); | 5003 | return func.fail("TODO: airAggregateInit for packed structs larger than 64 bits", .{}); |
| 5005 | } | 5004 | } |
| 5006 | const struct_obj = result_ty.castTag(.@"struct").?.data; | 5005 | const struct_obj = mod.typeToStruct(result_ty).?; |
| 5007 | const fields = struct_obj.fields.values(); | 5006 | const fields = struct_obj.fields.values(); |
| 5008 | const backing_type = struct_obj.backing_int_ty; | 5007 | const backing_type = struct_obj.backing_int_ty; |
| 5009 | 5008 | ||
| ... | @@ -5051,7 +5050,7 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5051,7 +5050,7 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5051 | for (elements, 0..) |elem, elem_index| { | 5050 | for (elements, 0..) |elem, elem_index| { |
| 5052 | if ((try result_ty.structFieldValueComptime(mod, elem_index)) != null) continue; | 5051 | if ((try result_ty.structFieldValueComptime(mod, elem_index)) != null) continue; |
| 5053 | 5052 | ||
| 5054 | const elem_ty = result_ty.structFieldType(elem_index); | 5053 | const elem_ty = result_ty.structFieldType(elem_index, mod); |
| 5055 | const elem_size = @intCast(u32, elem_ty.abiSize(mod)); | 5054 | const elem_size = @intCast(u32, elem_ty.abiSize(mod)); |
| 5056 | const value = try func.resolveInst(elem); | 5055 | const value = try func.resolveInst(elem); |
| 5057 | try func.store(offset, value, elem_ty, 0); | 5056 | try func.store(offset, value, elem_ty, 0); |
src/arch/wasm/abi.zig+9-9| ... | @@ -26,14 +26,14 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class { | ... | @@ -26,14 +26,14 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class { |
| 26 | if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return none; | 26 | if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return none; |
| 27 | switch (ty.zigTypeTag(mod)) { | 27 | switch (ty.zigTypeTag(mod)) { |
| 28 | .Struct => { | 28 | .Struct => { |
| 29 | if (ty.containerLayout() == .Packed) { | 29 | if (ty.containerLayout(mod) == .Packed) { |
| 30 | if (ty.bitSize(mod) <= 64) return direct; | 30 | if (ty.bitSize(mod) <= 64) return direct; |
| 31 | return .{ .direct, .direct }; | 31 | return .{ .direct, .direct }; |
| 32 | } | 32 | } |
| 33 | // When the struct type is non-scalar | 33 | // When the struct type is non-scalar |
| 34 | if (ty.structFieldCount() > 1) return memory; | 34 | if (ty.structFieldCount(mod) > 1) return memory; |
| 35 | // When the struct's alignment is non-natural | 35 | // When the struct's alignment is non-natural |
| 36 | const field = ty.structFields().values()[0]; | 36 | const field = ty.structFields(mod).values()[0]; |
| 37 | if (field.abi_align != 0) { | 37 | if (field.abi_align != 0) { |
| 38 | if (field.abi_align > field.ty.abiAlignment(mod)) { | 38 | if (field.abi_align > field.ty.abiAlignment(mod)) { |
| 39 | return memory; | 39 | return memory; |
| ... | @@ -64,7 +64,7 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class { | ... | @@ -64,7 +64,7 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class { |
| 64 | return direct; | 64 | return direct; |
| 65 | }, | 65 | }, |
| 66 | .Union => { | 66 | .Union => { |
| 67 | if (ty.containerLayout() == .Packed) { | 67 | if (ty.containerLayout(mod) == .Packed) { |
| 68 | if (ty.bitSize(mod) <= 64) return direct; | 68 | if (ty.bitSize(mod) <= 64) return direct; |
| 69 | return .{ .direct, .direct }; | 69 | return .{ .direct, .direct }; |
| 70 | } | 70 | } |
| ... | @@ -96,19 +96,19 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class { | ... | @@ -96,19 +96,19 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class { |
| 96 | pub fn scalarType(ty: Type, mod: *Module) Type { | 96 | pub fn scalarType(ty: Type, mod: *Module) Type { |
| 97 | switch (ty.zigTypeTag(mod)) { | 97 | switch (ty.zigTypeTag(mod)) { |
| 98 | .Struct => { | 98 | .Struct => { |
| 99 | switch (ty.containerLayout()) { | 99 | switch (ty.containerLayout(mod)) { |
| 100 | .Packed => { | 100 | .Packed => { |
| 101 | const struct_obj = ty.castTag(.@"struct").?.data; | 101 | const struct_obj = mod.typeToStruct(ty).?; |
| 102 | return scalarType(struct_obj.backing_int_ty, mod); | 102 | return scalarType(struct_obj.backing_int_ty, mod); |
| 103 | }, | 103 | }, |
| 104 | else => { | 104 | else => { |
| 105 | std.debug.assert(ty.structFieldCount() == 1); | 105 | std.debug.assert(ty.structFieldCount(mod) == 1); |
| 106 | return scalarType(ty.structFieldType(0), mod); | 106 | return scalarType(ty.structFieldType(0, mod), mod); |
| 107 | }, | 107 | }, |
| 108 | } | 108 | } |
| 109 | }, | 109 | }, |
| 110 | .Union => { | 110 | .Union => { |
| 111 | if (ty.containerLayout() != .Packed) { | 111 | if (ty.containerLayout(mod) != .Packed) { |
| 112 | const layout = ty.unionGetLayout(mod); | 112 | const layout = ty.unionGetLayout(mod); |
| 113 | if (layout.payload_size == 0 and layout.tag_size != 0) { | 113 | if (layout.payload_size == 0 and layout.tag_size != 0) { |
| 114 | return scalarType(ty.unionTagTypeSafety().?, mod); | 114 | return scalarType(ty.unionTagTypeSafety().?, mod); |
src/arch/x86_64/CodeGen.zig+17-17| ... | @@ -3252,13 +3252,13 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3252,13 +3252,13 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3252 | try self.genSetMem( | 3252 | try self.genSetMem( |
| 3253 | .{ .frame = frame_index }, | 3253 | .{ .frame = frame_index }, |
| 3254 | @intCast(i32, tuple_ty.structFieldOffset(1, mod)), | 3254 | @intCast(i32, tuple_ty.structFieldOffset(1, mod)), |
| 3255 | tuple_ty.structFieldType(1), | 3255 | tuple_ty.structFieldType(1, mod), |
| 3256 | .{ .eflags = cc }, | 3256 | .{ .eflags = cc }, |
| 3257 | ); | 3257 | ); |
| 3258 | try self.genSetMem( | 3258 | try self.genSetMem( |
| 3259 | .{ .frame = frame_index }, | 3259 | .{ .frame = frame_index }, |
| 3260 | @intCast(i32, tuple_ty.structFieldOffset(0, mod)), | 3260 | @intCast(i32, tuple_ty.structFieldOffset(0, mod)), |
| 3261 | tuple_ty.structFieldType(0), | 3261 | tuple_ty.structFieldType(0, mod), |
| 3262 | partial_mcv, | 3262 | partial_mcv, |
| 3263 | ); | 3263 | ); |
| 3264 | break :result .{ .load_frame = .{ .index = frame_index } }; | 3264 | break :result .{ .load_frame = .{ .index = frame_index } }; |
| ... | @@ -3289,7 +3289,7 @@ fn genSetFrameTruncatedOverflowCompare( | ... | @@ -3289,7 +3289,7 @@ fn genSetFrameTruncatedOverflowCompare( |
| 3289 | }; | 3289 | }; |
| 3290 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); | 3290 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 3291 | 3291 | ||
| 3292 | const ty = tuple_ty.structFieldType(0); | 3292 | const ty = tuple_ty.structFieldType(0, mod); |
| 3293 | const int_info = ty.intInfo(mod); | 3293 | const int_info = ty.intInfo(mod); |
| 3294 | 3294 | ||
| 3295 | const hi_limb_bits = (int_info.bits - 1) % 64 + 1; | 3295 | const hi_limb_bits = (int_info.bits - 1) % 64 + 1; |
| ... | @@ -3336,7 +3336,7 @@ fn genSetFrameTruncatedOverflowCompare( | ... | @@ -3336,7 +3336,7 @@ fn genSetFrameTruncatedOverflowCompare( |
| 3336 | try self.genSetMem( | 3336 | try self.genSetMem( |
| 3337 | .{ .frame = frame_index }, | 3337 | .{ .frame = frame_index }, |
| 3338 | @intCast(i32, tuple_ty.structFieldOffset(1, mod)), | 3338 | @intCast(i32, tuple_ty.structFieldOffset(1, mod)), |
| 3339 | tuple_ty.structFieldType(1), | 3339 | tuple_ty.structFieldType(1, mod), |
| 3340 | if (overflow_cc) |_| .{ .register = overflow_reg.to8() } else .{ .eflags = .ne }, | 3340 | if (overflow_cc) |_| .{ .register = overflow_reg.to8() } else .{ .eflags = .ne }, |
| 3341 | ); | 3341 | ); |
| 3342 | } | 3342 | } |
| ... | @@ -3393,13 +3393,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3393,13 +3393,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3393 | try self.genSetMem( | 3393 | try self.genSetMem( |
| 3394 | .{ .frame = frame_index }, | 3394 | .{ .frame = frame_index }, |
| 3395 | @intCast(i32, tuple_ty.structFieldOffset(0, mod)), | 3395 | @intCast(i32, tuple_ty.structFieldOffset(0, mod)), |
| 3396 | tuple_ty.structFieldType(0), | 3396 | tuple_ty.structFieldType(0, mod), |
| 3397 | partial_mcv, | 3397 | partial_mcv, |
| 3398 | ); | 3398 | ); |
| 3399 | try self.genSetMem( | 3399 | try self.genSetMem( |
| 3400 | .{ .frame = frame_index }, | 3400 | .{ .frame = frame_index }, |
| 3401 | @intCast(i32, tuple_ty.structFieldOffset(1, mod)), | 3401 | @intCast(i32, tuple_ty.structFieldOffset(1, mod)), |
| 3402 | tuple_ty.structFieldType(1), | 3402 | tuple_ty.structFieldType(1, mod), |
| 3403 | .{ .immediate = 0 }, // cc being set is impossible | 3403 | .{ .immediate = 0 }, // cc being set is impossible |
| 3404 | ); | 3404 | ); |
| 3405 | } else try self.genSetFrameTruncatedOverflowCompare( | 3405 | } else try self.genSetFrameTruncatedOverflowCompare( |
| ... | @@ -5563,7 +5563,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32 | ... | @@ -5563,7 +5563,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32 |
| 5563 | const ptr_field_ty = self.typeOfIndex(inst); | 5563 | const ptr_field_ty = self.typeOfIndex(inst); |
| 5564 | const ptr_container_ty = self.typeOf(operand); | 5564 | const ptr_container_ty = self.typeOf(operand); |
| 5565 | const container_ty = ptr_container_ty.childType(mod); | 5565 | const container_ty = ptr_container_ty.childType(mod); |
| 5566 | const field_offset = @intCast(i32, switch (container_ty.containerLayout()) { | 5566 | const field_offset = @intCast(i32, switch (container_ty.containerLayout(mod)) { |
| 5567 | .Auto, .Extern => container_ty.structFieldOffset(index, mod), | 5567 | .Auto, .Extern => container_ty.structFieldOffset(index, mod), |
| 5568 | .Packed => if (container_ty.zigTypeTag(mod) == .Struct and | 5568 | .Packed => if (container_ty.zigTypeTag(mod) == .Struct and |
| 5569 | ptr_field_ty.ptrInfo(mod).host_size == 0) | 5569 | ptr_field_ty.ptrInfo(mod).host_size == 0) |
| ... | @@ -5591,16 +5591,16 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5591,16 +5591,16 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5591 | 5591 | ||
| 5592 | const container_ty = self.typeOf(operand); | 5592 | const container_ty = self.typeOf(operand); |
| 5593 | const container_rc = regClassForType(container_ty, mod); | 5593 | const container_rc = regClassForType(container_ty, mod); |
| 5594 | const field_ty = container_ty.structFieldType(index); | 5594 | const field_ty = container_ty.structFieldType(index, mod); |
| 5595 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none; | 5595 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none; |
| 5596 | const field_rc = regClassForType(field_ty, mod); | 5596 | const field_rc = regClassForType(field_ty, mod); |
| 5597 | const field_is_gp = field_rc.supersetOf(gp); | 5597 | const field_is_gp = field_rc.supersetOf(gp); |
| 5598 | 5598 | ||
| 5599 | const src_mcv = try self.resolveInst(operand); | 5599 | const src_mcv = try self.resolveInst(operand); |
| 5600 | const field_off = switch (container_ty.containerLayout()) { | 5600 | const field_off = switch (container_ty.containerLayout(mod)) { |
| 5601 | .Auto, .Extern => @intCast(u32, container_ty.structFieldOffset(index, mod) * 8), | 5601 | .Auto, .Extern => @intCast(u32, container_ty.structFieldOffset(index, mod) * 8), |
| 5602 | .Packed => if (container_ty.castTag(.@"struct")) |struct_obj| | 5602 | .Packed => if (mod.typeToStruct(container_ty)) |struct_obj| |
| 5603 | struct_obj.data.packedFieldBitOffset(mod, index) | 5603 | struct_obj.packedFieldBitOffset(mod, index) |
| 5604 | else | 5604 | else |
| 5605 | 0, | 5605 | 0, |
| 5606 | }; | 5606 | }; |
| ... | @@ -10036,13 +10036,13 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal | ... | @@ -10036,13 +10036,13 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal |
| 10036 | try self.genSetMem( | 10036 | try self.genSetMem( |
| 10037 | base, | 10037 | base, |
| 10038 | disp + @intCast(i32, ty.structFieldOffset(0, mod)), | 10038 | disp + @intCast(i32, ty.structFieldOffset(0, mod)), |
| 10039 | ty.structFieldType(0), | 10039 | ty.structFieldType(0, mod), |
| 10040 | .{ .register = ro.reg }, | 10040 | .{ .register = ro.reg }, |
| 10041 | ); | 10041 | ); |
| 10042 | try self.genSetMem( | 10042 | try self.genSetMem( |
| 10043 | base, | 10043 | base, |
| 10044 | disp + @intCast(i32, ty.structFieldOffset(1, mod)), | 10044 | disp + @intCast(i32, ty.structFieldOffset(1, mod)), |
| 10045 | ty.structFieldType(1), | 10045 | ty.structFieldType(1, mod), |
| 10046 | .{ .eflags = ro.eflags }, | 10046 | .{ .eflags = ro.eflags }, |
| 10047 | ); | 10047 | ); |
| 10048 | }, | 10048 | }, |
| ... | @@ -11259,8 +11259,8 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11259,8 +11259,8 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 11259 | .Struct => { | 11259 | .Struct => { |
| 11260 | const frame_index = | 11260 | const frame_index = |
| 11261 | try self.allocFrameIndex(FrameAlloc.initType(result_ty, mod)); | 11261 | try self.allocFrameIndex(FrameAlloc.initType(result_ty, mod)); |
| 11262 | if (result_ty.containerLayout() == .Packed) { | 11262 | if (result_ty.containerLayout(mod) == .Packed) { |
| 11263 | const struct_obj = result_ty.castTag(.@"struct").?.data; | 11263 | const struct_obj = mod.typeToStruct(result_ty).?; |
| 11264 | try self.genInlineMemset( | 11264 | try self.genInlineMemset( |
| 11265 | .{ .lea_frame = .{ .index = frame_index } }, | 11265 | .{ .lea_frame = .{ .index = frame_index } }, |
| 11266 | .{ .immediate = 0 }, | 11266 | .{ .immediate = 0 }, |
| ... | @@ -11269,7 +11269,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11269,7 +11269,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 11269 | for (elements, 0..) |elem, elem_i| { | 11269 | for (elements, 0..) |elem, elem_i| { |
| 11270 | if ((try result_ty.structFieldValueComptime(mod, elem_i)) != null) continue; | 11270 | if ((try result_ty.structFieldValueComptime(mod, elem_i)) != null) continue; |
| 11271 | 11271 | ||
| 11272 | const elem_ty = result_ty.structFieldType(elem_i); | 11272 | const elem_ty = result_ty.structFieldType(elem_i, mod); |
| 11273 | const elem_bit_size = @intCast(u32, elem_ty.bitSize(mod)); | 11273 | const elem_bit_size = @intCast(u32, elem_ty.bitSize(mod)); |
| 11274 | if (elem_bit_size > 64) { | 11274 | if (elem_bit_size > 64) { |
| 11275 | return self.fail( | 11275 | return self.fail( |
| ... | @@ -11341,7 +11341,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11341,7 +11341,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 11341 | } else for (elements, 0..) |elem, elem_i| { | 11341 | } else for (elements, 0..) |elem, elem_i| { |
| 11342 | if ((try result_ty.structFieldValueComptime(mod, elem_i)) != null) continue; | 11342 | if ((try result_ty.structFieldValueComptime(mod, elem_i)) != null) continue; |
| 11343 | 11343 | ||
| 11344 | const elem_ty = result_ty.structFieldType(elem_i); | 11344 | const elem_ty = result_ty.structFieldType(elem_i, mod); |
| 11345 | const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, mod)); | 11345 | const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, mod)); |
| 11346 | const elem_mcv = try self.resolveInst(elem); | 11346 | const elem_mcv = try self.resolveInst(elem); |
| 11347 | const mat_elem_mcv = switch (elem_mcv) { | 11347 | const mat_elem_mcv = switch (elem_mcv) { |
src/arch/x86_64/abi.zig+4-4| ... | @@ -41,7 +41,7 @@ pub fn classifyWindows(ty: Type, mod: *Module) Class { | ... | @@ -41,7 +41,7 @@ pub fn classifyWindows(ty: Type, mod: *Module) Class { |
| 41 | 1, 2, 4, 8 => return .integer, | 41 | 1, 2, 4, 8 => return .integer, |
| 42 | else => switch (ty.zigTypeTag(mod)) { | 42 | else => switch (ty.zigTypeTag(mod)) { |
| 43 | .Int => return .win_i128, | 43 | .Int => return .win_i128, |
| 44 | .Struct, .Union => if (ty.containerLayout() == .Packed) { | 44 | .Struct, .Union => if (ty.containerLayout(mod) == .Packed) { |
| 45 | return .win_i128; | 45 | return .win_i128; |
| 46 | } else { | 46 | } else { |
| 47 | return .memory; | 47 | return .memory; |
| ... | @@ -210,7 +210,7 @@ pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class { | ... | @@ -210,7 +210,7 @@ pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class { |
| 210 | // "If the size of the aggregate exceeds a single eightbyte, each is classified | 210 | // "If the size of the aggregate exceeds a single eightbyte, each is classified |
| 211 | // separately.". | 211 | // separately.". |
| 212 | const ty_size = ty.abiSize(mod); | 212 | const ty_size = ty.abiSize(mod); |
| 213 | if (ty.containerLayout() == .Packed) { | 213 | if (ty.containerLayout(mod) == .Packed) { |
| 214 | assert(ty_size <= 128); | 214 | assert(ty_size <= 128); |
| 215 | result[0] = .integer; | 215 | result[0] = .integer; |
| 216 | if (ty_size > 64) result[1] = .integer; | 216 | if (ty_size > 64) result[1] = .integer; |
| ... | @@ -221,7 +221,7 @@ pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class { | ... | @@ -221,7 +221,7 @@ pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class { |
| 221 | 221 | ||
| 222 | var result_i: usize = 0; // out of 8 | 222 | var result_i: usize = 0; // out of 8 |
| 223 | var byte_i: usize = 0; // out of 8 | 223 | var byte_i: usize = 0; // out of 8 |
| 224 | const fields = ty.structFields(); | 224 | const fields = ty.structFields(mod); |
| 225 | for (fields.values()) |field| { | 225 | for (fields.values()) |field| { |
| 226 | if (field.abi_align != 0) { | 226 | if (field.abi_align != 0) { |
| 227 | if (field.abi_align < field.ty.abiAlignment(mod)) { | 227 | if (field.abi_align < field.ty.abiAlignment(mod)) { |
| ... | @@ -329,7 +329,7 @@ pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class { | ... | @@ -329,7 +329,7 @@ pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class { |
| 329 | // "If the size of the aggregate exceeds a single eightbyte, each is classified | 329 | // "If the size of the aggregate exceeds a single eightbyte, each is classified |
| 330 | // separately.". | 330 | // separately.". |
| 331 | const ty_size = ty.abiSize(mod); | 331 | const ty_size = ty.abiSize(mod); |
| 332 | if (ty.containerLayout() == .Packed) { | 332 | if (ty.containerLayout(mod) == .Packed) { |
| 333 | assert(ty_size <= 128); | 333 | assert(ty_size <= 128); |
| 334 | result[0] = .integer; | 334 | result[0] = .integer; |
| 335 | if (ty_size > 64) result[1] = .integer; | 335 | if (ty_size > 64) result[1] = .integer; |
src/codegen.zig+3-3| ... | @@ -503,8 +503,8 @@ pub fn generateSymbol( | ... | @@ -503,8 +503,8 @@ pub fn generateSymbol( |
| 503 | return Result.ok; | 503 | return Result.ok; |
| 504 | }, | 504 | }, |
| 505 | .Struct => { | 505 | .Struct => { |
| 506 | if (typed_value.ty.containerLayout() == .Packed) { | 506 | if (typed_value.ty.containerLayout(mod) == .Packed) { |
| 507 | const struct_obj = typed_value.ty.castTag(.@"struct").?.data; | 507 | const struct_obj = mod.typeToStruct(typed_value.ty).?; |
| 508 | const fields = struct_obj.fields.values(); | 508 | const fields = struct_obj.fields.values(); |
| 509 | const field_vals = typed_value.val.castTag(.aggregate).?.data; | 509 | const field_vals = typed_value.val.castTag(.aggregate).?.data; |
| 510 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow; | 510 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow; |
| ... | @@ -539,7 +539,7 @@ pub fn generateSymbol( | ... | @@ -539,7 +539,7 @@ pub fn generateSymbol( |
| 539 | const struct_begin = code.items.len; | 539 | const struct_begin = code.items.len; |
| 540 | const field_vals = typed_value.val.castTag(.aggregate).?.data; | 540 | const field_vals = typed_value.val.castTag(.aggregate).?.data; |
| 541 | for (field_vals, 0..) |field_val, index| { | 541 | for (field_vals, 0..) |field_val, index| { |
| 542 | const field_ty = typed_value.ty.structFieldType(index); | 542 | const field_ty = typed_value.ty.structFieldType(index, mod); |
| 543 | if (!field_ty.hasRuntimeBits(mod)) continue; | 543 | if (!field_ty.hasRuntimeBits(mod)) continue; |
| 544 | 544 | ||
| 545 | switch (try generateSymbol(bin_file, src_loc, .{ | 545 | switch (try generateSymbol(bin_file, src_loc, .{ |
src/codegen/c.zig+119-109| ... | @@ -820,7 +820,7 @@ pub const DeclGen = struct { | ... | @@ -820,7 +820,7 @@ pub const DeclGen = struct { |
| 820 | try dg.renderValue(writer, Type.bool, val, initializer_type); | 820 | try dg.renderValue(writer, Type.bool, val, initializer_type); |
| 821 | return writer.writeAll(" }"); | 821 | return writer.writeAll(" }"); |
| 822 | }, | 822 | }, |
| 823 | .Struct => switch (ty.containerLayout()) { | 823 | .Struct => switch (ty.containerLayout(mod)) { |
| 824 | .Auto, .Extern => { | 824 | .Auto, .Extern => { |
| 825 | if (!location.isInitializer()) { | 825 | if (!location.isInitializer()) { |
| 826 | try writer.writeByte('('); | 826 | try writer.writeByte('('); |
| ... | @@ -830,9 +830,9 @@ pub const DeclGen = struct { | ... | @@ -830,9 +830,9 @@ pub const DeclGen = struct { |
| 830 | 830 | ||
| 831 | try writer.writeByte('{'); | 831 | try writer.writeByte('{'); |
| 832 | var empty = true; | 832 | var empty = true; |
| 833 | for (0..ty.structFieldCount()) |field_i| { | 833 | for (0..ty.structFieldCount(mod)) |field_i| { |
| 834 | if (ty.structFieldIsComptime(field_i)) continue; | 834 | if (ty.structFieldIsComptime(field_i, mod)) continue; |
| 835 | const field_ty = ty.structFieldType(field_i); | 835 | const field_ty = ty.structFieldType(field_i, mod); |
| 836 | if (!field_ty.hasRuntimeBits(mod)) continue; | 836 | if (!field_ty.hasRuntimeBits(mod)) continue; |
| 837 | 837 | ||
| 838 | if (!empty) try writer.writeByte(','); | 838 | if (!empty) try writer.writeByte(','); |
| ... | @@ -1328,7 +1328,7 @@ pub const DeclGen = struct { | ... | @@ -1328,7 +1328,7 @@ pub const DeclGen = struct { |
| 1328 | }, | 1328 | }, |
| 1329 | else => unreachable, | 1329 | else => unreachable, |
| 1330 | }, | 1330 | }, |
| 1331 | .Struct => switch (ty.containerLayout()) { | 1331 | .Struct => switch (ty.containerLayout(mod)) { |
| 1332 | .Auto, .Extern => { | 1332 | .Auto, .Extern => { |
| 1333 | const field_vals = val.castTag(.aggregate).?.data; | 1333 | const field_vals = val.castTag(.aggregate).?.data; |
| 1334 | 1334 | ||
| ... | @@ -1341,8 +1341,8 @@ pub const DeclGen = struct { | ... | @@ -1341,8 +1341,8 @@ pub const DeclGen = struct { |
| 1341 | try writer.writeByte('{'); | 1341 | try writer.writeByte('{'); |
| 1342 | var empty = true; | 1342 | var empty = true; |
| 1343 | for (field_vals, 0..) |field_val, field_i| { | 1343 | for (field_vals, 0..) |field_val, field_i| { |
| 1344 | if (ty.structFieldIsComptime(field_i)) continue; | 1344 | if (ty.structFieldIsComptime(field_i, mod)) continue; |
| 1345 | const field_ty = ty.structFieldType(field_i); | 1345 | const field_ty = ty.structFieldType(field_i, mod); |
| 1346 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 1346 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1347 | 1347 | ||
| 1348 | if (!empty) try writer.writeByte(','); | 1348 | if (!empty) try writer.writeByte(','); |
| ... | @@ -1363,8 +1363,8 @@ pub const DeclGen = struct { | ... | @@ -1363,8 +1363,8 @@ pub const DeclGen = struct { |
| 1363 | 1363 | ||
| 1364 | var eff_num_fields: usize = 0; | 1364 | var eff_num_fields: usize = 0; |
| 1365 | for (0..field_vals.len) |field_i| { | 1365 | for (0..field_vals.len) |field_i| { |
| 1366 | if (ty.structFieldIsComptime(field_i)) continue; | 1366 | if (ty.structFieldIsComptime(field_i, mod)) continue; |
| 1367 | const field_ty = ty.structFieldType(field_i); | 1367 | const field_ty = ty.structFieldType(field_i, mod); |
| 1368 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 1368 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1369 | 1369 | ||
| 1370 | eff_num_fields += 1; | 1370 | eff_num_fields += 1; |
| ... | @@ -1386,8 +1386,8 @@ pub const DeclGen = struct { | ... | @@ -1386,8 +1386,8 @@ pub const DeclGen = struct { |
| 1386 | var eff_index: usize = 0; | 1386 | var eff_index: usize = 0; |
| 1387 | var needs_closing_paren = false; | 1387 | var needs_closing_paren = false; |
| 1388 | for (field_vals, 0..) |field_val, field_i| { | 1388 | for (field_vals, 0..) |field_val, field_i| { |
| 1389 | if (ty.structFieldIsComptime(field_i)) continue; | 1389 | if (ty.structFieldIsComptime(field_i, mod)) continue; |
| 1390 | const field_ty = ty.structFieldType(field_i); | 1390 | const field_ty = ty.structFieldType(field_i, mod); |
| 1391 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 1391 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1392 | 1392 | ||
| 1393 | const cast_context = IntCastContext{ .value = .{ .value = field_val } }; | 1393 | const cast_context = IntCastContext{ .value = .{ .value = field_val } }; |
| ... | @@ -1416,8 +1416,8 @@ pub const DeclGen = struct { | ... | @@ -1416,8 +1416,8 @@ pub const DeclGen = struct { |
| 1416 | // a << a_off | b << b_off | c << c_off | 1416 | // a << a_off | b << b_off | c << c_off |
| 1417 | var empty = true; | 1417 | var empty = true; |
| 1418 | for (field_vals, 0..) |field_val, field_i| { | 1418 | for (field_vals, 0..) |field_val, field_i| { |
| 1419 | if (ty.structFieldIsComptime(field_i)) continue; | 1419 | if (ty.structFieldIsComptime(field_i, mod)) continue; |
| 1420 | const field_ty = ty.structFieldType(field_i); | 1420 | const field_ty = ty.structFieldType(field_i, mod); |
| 1421 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 1421 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1422 | 1422 | ||
| 1423 | if (!empty) try writer.writeAll(" | "); | 1423 | if (!empty) try writer.writeAll(" | "); |
| ... | @@ -1453,7 +1453,7 @@ pub const DeclGen = struct { | ... | @@ -1453,7 +1453,7 @@ pub const DeclGen = struct { |
| 1453 | const field_i = ty.unionTagFieldIndex(union_obj.tag, mod).?; | 1453 | const field_i = ty.unionTagFieldIndex(union_obj.tag, mod).?; |
| 1454 | const field_ty = ty.unionFields().values()[field_i].ty; | 1454 | const field_ty = ty.unionFields().values()[field_i].ty; |
| 1455 | const field_name = ty.unionFields().keys()[field_i]; | 1455 | const field_name = ty.unionFields().keys()[field_i]; |
| 1456 | if (ty.containerLayout() == .Packed) { | 1456 | if (ty.containerLayout(mod) == .Packed) { |
| 1457 | if (field_ty.hasRuntimeBits(mod)) { | 1457 | if (field_ty.hasRuntimeBits(mod)) { |
| 1458 | if (field_ty.isPtrAtRuntime(mod)) { | 1458 | if (field_ty.isPtrAtRuntime(mod)) { |
| 1459 | try writer.writeByte('('); | 1459 | try writer.writeByte('('); |
| ... | @@ -5218,25 +5218,25 @@ fn fieldLocation( | ... | @@ -5218,25 +5218,25 @@ fn fieldLocation( |
| 5218 | end: void, | 5218 | end: void, |
| 5219 | } { | 5219 | } { |
| 5220 | return switch (container_ty.zigTypeTag(mod)) { | 5220 | return switch (container_ty.zigTypeTag(mod)) { |
| 5221 | .Struct => switch (container_ty.containerLayout()) { | 5221 | .Struct => switch (container_ty.containerLayout(mod)) { |
| 5222 | .Auto, .Extern => for (field_index..container_ty.structFieldCount()) |next_field_index| { | 5222 | .Auto, .Extern => for (field_index..container_ty.structFieldCount(mod)) |next_field_index| { |
| 5223 | if (container_ty.structFieldIsComptime(next_field_index)) continue; | 5223 | if (container_ty.structFieldIsComptime(next_field_index, mod)) continue; |
| 5224 | const field_ty = container_ty.structFieldType(next_field_index); | 5224 | const field_ty = container_ty.structFieldType(next_field_index, mod); |
| 5225 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 5225 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 5226 | 5226 | ||
| 5227 | break .{ .field = if (container_ty.isSimpleTuple()) | 5227 | break .{ .field = if (container_ty.isSimpleTuple()) |
| 5228 | .{ .field = next_field_index } | 5228 | .{ .field = next_field_index } |
| 5229 | else | 5229 | else |
| 5230 | .{ .identifier = container_ty.structFieldName(next_field_index) } }; | 5230 | .{ .identifier = container_ty.structFieldName(next_field_index, mod) } }; |
| 5231 | } else if (container_ty.hasRuntimeBitsIgnoreComptime(mod)) .end else .begin, | 5231 | } else if (container_ty.hasRuntimeBitsIgnoreComptime(mod)) .end else .begin, |
| 5232 | .Packed => if (field_ptr_ty.ptrInfo(mod).host_size == 0) | 5232 | .Packed => if (field_ptr_ty.ptrInfo(mod).host_size == 0) |
| 5233 | .{ .byte_offset = container_ty.packedStructFieldByteOffset(field_index, mod) } | 5233 | .{ .byte_offset = container_ty.packedStructFieldByteOffset(field_index, mod) } |
| 5234 | else | 5234 | else |
| 5235 | .begin, | 5235 | .begin, |
| 5236 | }, | 5236 | }, |
| 5237 | .Union => switch (container_ty.containerLayout()) { | 5237 | .Union => switch (container_ty.containerLayout(mod)) { |
| 5238 | .Auto, .Extern => { | 5238 | .Auto, .Extern => { |
| 5239 | const field_ty = container_ty.structFieldType(field_index); | 5239 | const field_ty = container_ty.structFieldType(field_index, mod); |
| 5240 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) | 5240 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) |
| 5241 | return if (container_ty.unionTagTypeSafety() != null and | 5241 | return if (container_ty.unionTagTypeSafety() != null and |
| 5242 | !container_ty.unionHasAllZeroBitFieldTypes(mod)) | 5242 | !container_ty.unionHasAllZeroBitFieldTypes(mod)) |
| ... | @@ -5417,101 +5417,111 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5417,101 +5417,111 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5417 | // Ensure complete type definition is visible before accessing fields. | 5417 | // Ensure complete type definition is visible before accessing fields. |
| 5418 | _ = try f.typeToIndex(struct_ty, .complete); | 5418 | _ = try f.typeToIndex(struct_ty, .complete); |
| 5419 | 5419 | ||
| 5420 | const field_name: CValue = switch (struct_ty.tag()) { | 5420 | const field_name: CValue = switch (struct_ty.ip_index) { |
| 5421 | .tuple, .anon_struct, .@"struct" => switch (struct_ty.containerLayout()) { | 5421 | .none => switch (struct_ty.tag()) { |
| 5422 | .Auto, .Extern => if (struct_ty.isSimpleTuple()) | 5422 | .tuple, .anon_struct => if (struct_ty.isSimpleTuple()) |
| 5423 | .{ .field = extra.field_index } | 5423 | .{ .field = extra.field_index } |
| 5424 | else | 5424 | else |
| 5425 | .{ .identifier = struct_ty.structFieldName(extra.field_index) }, | 5425 | .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) }, |
| 5426 | .Packed => { | ||
| 5427 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | ||
| 5428 | const int_info = struct_ty.intInfo(mod); | ||
| 5429 | |||
| 5430 | const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1)); | ||
| 5431 | |||
| 5432 | const bit_offset = struct_obj.packedFieldBitOffset(mod, extra.field_index); | ||
| 5433 | const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset); | ||
| 5434 | 5426 | ||
| 5435 | const field_int_signedness = if (inst_ty.isAbiInt(mod)) | 5427 | .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout(mod) == .Packed) { |
| 5436 | inst_ty.intInfo(mod).signedness | 5428 | const operand_lval = if (struct_byval == .constant) blk: { |
| 5437 | else | 5429 | const operand_local = try f.allocLocal(inst, struct_ty); |
| 5438 | .unsigned; | 5430 | try f.writeCValue(writer, operand_local, .Other); |
| 5439 | const field_int_ty = try mod.intType(field_int_signedness, @intCast(u16, inst_ty.bitSize(mod))); | 5431 | try writer.writeAll(" = "); |
| 5440 | 5432 | try f.writeCValue(writer, struct_byval, .Initializer); | |
| 5441 | const temp_local = try f.allocLocal(inst, field_int_ty); | 5433 | try writer.writeAll(";\n"); |
| 5442 | try f.writeCValue(writer, temp_local, .Other); | 5434 | break :blk operand_local; |
| 5443 | try writer.writeAll(" = zig_wrap_"); | 5435 | } else struct_byval; |
| 5444 | try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty); | ||
| 5445 | try writer.writeAll("(("); | ||
| 5446 | try f.renderType(writer, field_int_ty); | ||
| 5447 | try writer.writeByte(')'); | ||
| 5448 | const cant_cast = int_info.bits > 64; | ||
| 5449 | if (cant_cast) { | ||
| 5450 | if (field_int_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); | ||
| 5451 | try writer.writeAll("zig_lo_"); | ||
| 5452 | try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty); | ||
| 5453 | try writer.writeByte('('); | ||
| 5454 | } | ||
| 5455 | if (bit_offset > 0) { | ||
| 5456 | try writer.writeAll("zig_shr_"); | ||
| 5457 | try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty); | ||
| 5458 | try writer.writeByte('('); | ||
| 5459 | } | ||
| 5460 | try f.writeCValue(writer, struct_byval, .Other); | ||
| 5461 | if (bit_offset > 0) { | ||
| 5462 | try writer.writeAll(", "); | ||
| 5463 | try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); | ||
| 5464 | try writer.writeByte(')'); | ||
| 5465 | } | ||
| 5466 | if (cant_cast) try writer.writeByte(')'); | ||
| 5467 | try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits); | ||
| 5468 | try writer.writeAll(");\n"); | ||
| 5469 | if (inst_ty.eql(field_int_ty, f.object.dg.module)) return temp_local; | ||
| 5470 | 5436 | ||
| 5471 | const local = try f.allocLocal(inst, inst_ty); | 5437 | const local = try f.allocLocal(inst, inst_ty); |
| 5472 | try writer.writeAll("memcpy("); | 5438 | try writer.writeAll("memcpy(&"); |
| 5473 | try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument); | 5439 | try f.writeCValue(writer, local, .Other); |
| 5474 | try writer.writeAll(", "); | 5440 | try writer.writeAll(", &"); |
| 5475 | try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument); | 5441 | try f.writeCValue(writer, operand_lval, .Other); |
| 5476 | try writer.writeAll(", sizeof("); | 5442 | try writer.writeAll(", sizeof("); |
| 5477 | try f.renderType(writer, inst_ty); | 5443 | try f.renderType(writer, inst_ty); |
| 5478 | try writer.writeAll("));\n"); | 5444 | try writer.writeAll("));\n"); |
| 5479 | try freeLocal(f, inst, temp_local.new_local, 0); | 5445 | |
| 5446 | if (struct_byval == .constant) { | ||
| 5447 | try freeLocal(f, inst, operand_lval.new_local, 0); | ||
| 5448 | } | ||
| 5449 | |||
| 5480 | return local; | 5450 | return local; |
| 5451 | } else field_name: { | ||
| 5452 | const name = struct_ty.unionFields().keys()[extra.field_index]; | ||
| 5453 | break :field_name if (struct_ty.unionTagTypeSafety()) |_| | ||
| 5454 | .{ .payload_identifier = name } | ||
| 5455 | else | ||
| 5456 | .{ .identifier = name }; | ||
| 5481 | }, | 5457 | }, |
| 5458 | else => unreachable, | ||
| 5482 | }, | 5459 | }, |
| 5483 | .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) { | 5460 | else => switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) { |
| 5484 | const operand_lval = if (struct_byval == .constant) blk: { | 5461 | .struct_type => switch (struct_ty.containerLayout(mod)) { |
| 5485 | const operand_local = try f.allocLocal(inst, struct_ty); | 5462 | .Auto, .Extern => if (struct_ty.isSimpleTuple()) |
| 5486 | try f.writeCValue(writer, operand_local, .Other); | 5463 | .{ .field = extra.field_index } |
| 5487 | try writer.writeAll(" = "); | 5464 | else |
| 5488 | try f.writeCValue(writer, struct_byval, .Initializer); | 5465 | .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) }, |
| 5489 | try writer.writeAll(";\n"); | 5466 | .Packed => { |
| 5490 | break :blk operand_local; | 5467 | const struct_obj = mod.typeToStruct(struct_ty).?; |
| 5491 | } else struct_byval; | 5468 | const int_info = struct_ty.intInfo(mod); |
| 5492 | 5469 | ||
| 5493 | const local = try f.allocLocal(inst, inst_ty); | 5470 | const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1)); |
| 5494 | try writer.writeAll("memcpy(&"); | ||
| 5495 | try f.writeCValue(writer, local, .Other); | ||
| 5496 | try writer.writeAll(", &"); | ||
| 5497 | try f.writeCValue(writer, operand_lval, .Other); | ||
| 5498 | try writer.writeAll(", sizeof("); | ||
| 5499 | try f.renderType(writer, inst_ty); | ||
| 5500 | try writer.writeAll("));\n"); | ||
| 5501 | 5471 | ||
| 5502 | if (struct_byval == .constant) { | 5472 | const bit_offset = struct_obj.packedFieldBitOffset(mod, extra.field_index); |
| 5503 | try freeLocal(f, inst, operand_lval.new_local, 0); | 5473 | const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset); |
| 5504 | } | ||
| 5505 | 5474 | ||
| 5506 | return local; | 5475 | const field_int_signedness = if (inst_ty.isAbiInt(mod)) |
| 5507 | } else field_name: { | 5476 | inst_ty.intInfo(mod).signedness |
| 5508 | const name = struct_ty.unionFields().keys()[extra.field_index]; | 5477 | else |
| 5509 | break :field_name if (struct_ty.unionTagTypeSafety()) |_| | 5478 | .unsigned; |
| 5510 | .{ .payload_identifier = name } | 5479 | const field_int_ty = try mod.intType(field_int_signedness, @intCast(u16, inst_ty.bitSize(mod))); |
| 5511 | else | 5480 | |
| 5512 | .{ .identifier = name }; | 5481 | const temp_local = try f.allocLocal(inst, field_int_ty); |
| 5482 | try f.writeCValue(writer, temp_local, .Other); | ||
| 5483 | try writer.writeAll(" = zig_wrap_"); | ||
| 5484 | try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty); | ||
| 5485 | try writer.writeAll("(("); | ||
| 5486 | try f.renderType(writer, field_int_ty); | ||
| 5487 | try writer.writeByte(')'); | ||
| 5488 | const cant_cast = int_info.bits > 64; | ||
| 5489 | if (cant_cast) { | ||
| 5490 | if (field_int_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); | ||
| 5491 | try writer.writeAll("zig_lo_"); | ||
| 5492 | try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty); | ||
| 5493 | try writer.writeByte('('); | ||
| 5494 | } | ||
| 5495 | if (bit_offset > 0) { | ||
| 5496 | try writer.writeAll("zig_shr_"); | ||
| 5497 | try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty); | ||
| 5498 | try writer.writeByte('('); | ||
| 5499 | } | ||
| 5500 | try f.writeCValue(writer, struct_byval, .Other); | ||
| 5501 | if (bit_offset > 0) { | ||
| 5502 | try writer.writeAll(", "); | ||
| 5503 | try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); | ||
| 5504 | try writer.writeByte(')'); | ||
| 5505 | } | ||
| 5506 | if (cant_cast) try writer.writeByte(')'); | ||
| 5507 | try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits); | ||
| 5508 | try writer.writeAll(");\n"); | ||
| 5509 | if (inst_ty.eql(field_int_ty, f.object.dg.module)) return temp_local; | ||
| 5510 | |||
| 5511 | const local = try f.allocLocal(inst, inst_ty); | ||
| 5512 | try writer.writeAll("memcpy("); | ||
| 5513 | try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument); | ||
| 5514 | try writer.writeAll(", "); | ||
| 5515 | try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument); | ||
| 5516 | try writer.writeAll(", sizeof("); | ||
| 5517 | try f.renderType(writer, inst_ty); | ||
| 5518 | try writer.writeAll("));\n"); | ||
| 5519 | try freeLocal(f, inst, temp_local.new_local, 0); | ||
| 5520 | return local; | ||
| 5521 | }, | ||
| 5522 | }, | ||
| 5523 | else => unreachable, | ||
| 5513 | }, | 5524 | }, |
| 5514 | else => unreachable, | ||
| 5515 | }; | 5525 | }; |
| 5516 | 5526 | ||
| 5517 | const local = try f.allocLocal(inst, inst_ty); | 5527 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -6805,17 +6815,17 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6805,17 +6815,17 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6805 | try a.end(f, writer); | 6815 | try a.end(f, writer); |
| 6806 | } | 6816 | } |
| 6807 | }, | 6817 | }, |
| 6808 | .Struct => switch (inst_ty.containerLayout()) { | 6818 | .Struct => switch (inst_ty.containerLayout(mod)) { |
| 6809 | .Auto, .Extern => for (resolved_elements, 0..) |element, field_i| { | 6819 | .Auto, .Extern => for (resolved_elements, 0..) |element, field_i| { |
| 6810 | if (inst_ty.structFieldIsComptime(field_i)) continue; | 6820 | if (inst_ty.structFieldIsComptime(field_i, mod)) continue; |
| 6811 | const field_ty = inst_ty.structFieldType(field_i); | 6821 | const field_ty = inst_ty.structFieldType(field_i, mod); |
| 6812 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 6822 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 6813 | 6823 | ||
| 6814 | const a = try Assignment.start(f, writer, field_ty); | 6824 | const a = try Assignment.start(f, writer, field_ty); |
| 6815 | try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple()) | 6825 | try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple()) |
| 6816 | .{ .field = field_i } | 6826 | .{ .field = field_i } |
| 6817 | else | 6827 | else |
| 6818 | .{ .identifier = inst_ty.structFieldName(field_i) }); | 6828 | .{ .identifier = inst_ty.structFieldName(field_i, mod) }); |
| 6819 | try a.assign(f, writer); | 6829 | try a.assign(f, writer); |
| 6820 | try f.writeCValue(writer, element, .Other); | 6830 | try f.writeCValue(writer, element, .Other); |
| 6821 | try a.end(f, writer); | 6831 | try a.end(f, writer); |
| ... | @@ -6831,8 +6841,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6831,8 +6841,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6831 | 6841 | ||
| 6832 | var empty = true; | 6842 | var empty = true; |
| 6833 | for (0..elements.len) |field_i| { | 6843 | for (0..elements.len) |field_i| { |
| 6834 | if (inst_ty.structFieldIsComptime(field_i)) continue; | 6844 | if (inst_ty.structFieldIsComptime(field_i, mod)) continue; |
| 6835 | const field_ty = inst_ty.structFieldType(field_i); | 6845 | const field_ty = inst_ty.structFieldType(field_i, mod); |
| 6836 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 6846 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 6837 | 6847 | ||
| 6838 | if (!empty) { | 6848 | if (!empty) { |
| ... | @@ -6844,8 +6854,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6844,8 +6854,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6844 | } | 6854 | } |
| 6845 | empty = true; | 6855 | empty = true; |
| 6846 | for (resolved_elements, 0..) |element, field_i| { | 6856 | for (resolved_elements, 0..) |element, field_i| { |
| 6847 | if (inst_ty.structFieldIsComptime(field_i)) continue; | 6857 | if (inst_ty.structFieldIsComptime(field_i, mod)) continue; |
| 6848 | const field_ty = inst_ty.structFieldType(field_i); | 6858 | const field_ty = inst_ty.structFieldType(field_i, mod); |
| 6849 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 6859 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 6850 | 6860 | ||
| 6851 | if (!empty) try writer.writeAll(", "); | 6861 | if (!empty) try writer.writeAll(", "); |
src/codegen/c/type.zig+25-25| ... | @@ -299,7 +299,7 @@ pub const CType = extern union { | ... | @@ -299,7 +299,7 @@ pub const CType = extern union { |
| 299 | pub fn fieldAlign(struct_ty: Type, field_i: usize, mod: *Module) AlignAs { | 299 | pub fn fieldAlign(struct_ty: Type, field_i: usize, mod: *Module) AlignAs { |
| 300 | return init( | 300 | return init( |
| 301 | struct_ty.structFieldAlign(field_i, mod), | 301 | struct_ty.structFieldAlign(field_i, mod), |
| 302 | struct_ty.structFieldType(field_i).abiAlignment(mod), | 302 | struct_ty.structFieldType(field_i, mod).abiAlignment(mod), |
| 303 | ); | 303 | ); |
| 304 | } | 304 | } |
| 305 | pub fn unionPayloadAlign(union_ty: Type, mod: *Module) AlignAs { | 305 | pub fn unionPayloadAlign(union_ty: Type, mod: *Module) AlignAs { |
| ... | @@ -1486,23 +1486,23 @@ pub const CType = extern union { | ... | @@ -1486,23 +1486,23 @@ pub const CType = extern union { |
| 1486 | } | 1486 | } |
| 1487 | }, | 1487 | }, |
| 1488 | 1488 | ||
| 1489 | .Struct, .Union => |zig_ty_tag| if (ty.containerLayout() == .Packed) { | 1489 | .Struct, .Union => |zig_ty_tag| if (ty.containerLayout(mod) == .Packed) { |
| 1490 | if (ty.castTag(.@"struct")) |struct_obj| { | 1490 | if (mod.typeToStruct(ty)) |struct_obj| { |
| 1491 | try self.initType(struct_obj.data.backing_int_ty, kind, lookup); | 1491 | try self.initType(struct_obj.backing_int_ty, kind, lookup); |
| 1492 | } else { | 1492 | } else { |
| 1493 | const bits = @intCast(u16, ty.bitSize(mod)); | 1493 | const bits = @intCast(u16, ty.bitSize(mod)); |
| 1494 | const int_ty = try mod.intType(.unsigned, bits); | 1494 | const int_ty = try mod.intType(.unsigned, bits); |
| 1495 | try self.initType(int_ty, kind, lookup); | 1495 | try self.initType(int_ty, kind, lookup); |
| 1496 | } | 1496 | } |
| 1497 | } else if (ty.isTupleOrAnonStruct()) { | 1497 | } else if (ty.isTupleOrAnonStruct(mod)) { |
| 1498 | if (lookup.isMutable()) { | 1498 | if (lookup.isMutable()) { |
| 1499 | for (0..switch (zig_ty_tag) { | 1499 | for (0..switch (zig_ty_tag) { |
| 1500 | .Struct => ty.structFieldCount(), | 1500 | .Struct => ty.structFieldCount(mod), |
| 1501 | .Union => ty.unionFields().count(), | 1501 | .Union => ty.unionFields().count(), |
| 1502 | else => unreachable, | 1502 | else => unreachable, |
| 1503 | }) |field_i| { | 1503 | }) |field_i| { |
| 1504 | const field_ty = ty.structFieldType(field_i); | 1504 | const field_ty = ty.structFieldType(field_i, mod); |
| 1505 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or | 1505 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or |
| 1506 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 1506 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1507 | _ = try lookup.typeToIndex(field_ty, switch (kind) { | 1507 | _ = try lookup.typeToIndex(field_ty, switch (kind) { |
| 1508 | .forward, .forward_parameter => .forward, | 1508 | .forward, .forward_parameter => .forward, |
| ... | @@ -1579,11 +1579,11 @@ pub const CType = extern union { | ... | @@ -1579,11 +1579,11 @@ pub const CType = extern union { |
| 1579 | } else { | 1579 | } else { |
| 1580 | var is_packed = false; | 1580 | var is_packed = false; |
| 1581 | for (0..switch (zig_ty_tag) { | 1581 | for (0..switch (zig_ty_tag) { |
| 1582 | .Struct => ty.structFieldCount(), | 1582 | .Struct => ty.structFieldCount(mod), |
| 1583 | .Union => ty.unionFields().count(), | 1583 | .Union => ty.unionFields().count(), |
| 1584 | else => unreachable, | 1584 | else => unreachable, |
| 1585 | }) |field_i| { | 1585 | }) |field_i| { |
| 1586 | const field_ty = ty.structFieldType(field_i); | 1586 | const field_ty = ty.structFieldType(field_i, mod); |
| 1587 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 1587 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1588 | 1588 | ||
| 1589 | const field_align = AlignAs.fieldAlign(ty, field_i, mod); | 1589 | const field_align = AlignAs.fieldAlign(ty, field_i, mod); |
| ... | @@ -1929,15 +1929,15 @@ pub const CType = extern union { | ... | @@ -1929,15 +1929,15 @@ pub const CType = extern union { |
| 1929 | => { | 1929 | => { |
| 1930 | const zig_ty_tag = ty.zigTypeTag(mod); | 1930 | const zig_ty_tag = ty.zigTypeTag(mod); |
| 1931 | const fields_len = switch (zig_ty_tag) { | 1931 | const fields_len = switch (zig_ty_tag) { |
| 1932 | .Struct => ty.structFieldCount(), | 1932 | .Struct => ty.structFieldCount(mod), |
| 1933 | .Union => ty.unionFields().count(), | 1933 | .Union => ty.unionFields().count(), |
| 1934 | else => unreachable, | 1934 | else => unreachable, |
| 1935 | }; | 1935 | }; |
| 1936 | 1936 | ||
| 1937 | var c_fields_len: usize = 0; | 1937 | var c_fields_len: usize = 0; |
| 1938 | for (0..fields_len) |field_i| { | 1938 | for (0..fields_len) |field_i| { |
| 1939 | const field_ty = ty.structFieldType(field_i); | 1939 | const field_ty = ty.structFieldType(field_i, mod); |
| 1940 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or | 1940 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or |
| 1941 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 1941 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1942 | c_fields_len += 1; | 1942 | c_fields_len += 1; |
| 1943 | } | 1943 | } |
| ... | @@ -1945,8 +1945,8 @@ pub const CType = extern union { | ... | @@ -1945,8 +1945,8 @@ pub const CType = extern union { |
| 1945 | const fields_pl = try arena.alloc(Payload.Fields.Field, c_fields_len); | 1945 | const fields_pl = try arena.alloc(Payload.Fields.Field, c_fields_len); |
| 1946 | var c_field_i: usize = 0; | 1946 | var c_field_i: usize = 0; |
| 1947 | for (0..fields_len) |field_i| { | 1947 | for (0..fields_len) |field_i| { |
| 1948 | const field_ty = ty.structFieldType(field_i); | 1948 | const field_ty = ty.structFieldType(field_i, mod); |
| 1949 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or | 1949 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or |
| 1950 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 1950 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1951 | 1951 | ||
| 1952 | defer c_field_i += 1; | 1952 | defer c_field_i += 1; |
| ... | @@ -1955,7 +1955,7 @@ pub const CType = extern union { | ... | @@ -1955,7 +1955,7 @@ pub const CType = extern union { |
| 1955 | std.fmt.allocPrintZ(arena, "f{}", .{field_i}) | 1955 | std.fmt.allocPrintZ(arena, "f{}", .{field_i}) |
| 1956 | else | 1956 | else |
| 1957 | arena.dupeZ(u8, switch (zig_ty_tag) { | 1957 | arena.dupeZ(u8, switch (zig_ty_tag) { |
| 1958 | .Struct => ty.structFieldName(field_i), | 1958 | .Struct => ty.structFieldName(field_i, mod), |
| 1959 | .Union => ty.unionFields().keys()[field_i], | 1959 | .Union => ty.unionFields().keys()[field_i], |
| 1960 | else => unreachable, | 1960 | else => unreachable, |
| 1961 | }), | 1961 | }), |
| ... | @@ -2074,7 +2074,7 @@ pub const CType = extern union { | ... | @@ -2074,7 +2074,7 @@ pub const CType = extern union { |
| 2074 | .fwd_anon_struct, | 2074 | .fwd_anon_struct, |
| 2075 | .fwd_anon_union, | 2075 | .fwd_anon_union, |
| 2076 | => { | 2076 | => { |
| 2077 | if (!ty.isTupleOrAnonStruct()) return false; | 2077 | if (!ty.isTupleOrAnonStruct(mod)) return false; |
| 2078 | 2078 | ||
| 2079 | var name_buf: [ | 2079 | var name_buf: [ |
| 2080 | std.fmt.count("f{}", .{std.math.maxInt(usize)}) | 2080 | std.fmt.count("f{}", .{std.math.maxInt(usize)}) |
| ... | @@ -2084,12 +2084,12 @@ pub const CType = extern union { | ... | @@ -2084,12 +2084,12 @@ pub const CType = extern union { |
| 2084 | const zig_ty_tag = ty.zigTypeTag(mod); | 2084 | const zig_ty_tag = ty.zigTypeTag(mod); |
| 2085 | var c_field_i: usize = 0; | 2085 | var c_field_i: usize = 0; |
| 2086 | for (0..switch (zig_ty_tag) { | 2086 | for (0..switch (zig_ty_tag) { |
| 2087 | .Struct => ty.structFieldCount(), | 2087 | .Struct => ty.structFieldCount(mod), |
| 2088 | .Union => ty.unionFields().count(), | 2088 | .Union => ty.unionFields().count(), |
| 2089 | else => unreachable, | 2089 | else => unreachable, |
| 2090 | }) |field_i| { | 2090 | }) |field_i| { |
| 2091 | const field_ty = ty.structFieldType(field_i); | 2091 | const field_ty = ty.structFieldType(field_i, mod); |
| 2092 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or | 2092 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or |
| 2093 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 2093 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2094 | 2094 | ||
| 2095 | defer c_field_i += 1; | 2095 | defer c_field_i += 1; |
| ... | @@ -2105,7 +2105,7 @@ pub const CType = extern union { | ... | @@ -2105,7 +2105,7 @@ pub const CType = extern union { |
| 2105 | if (ty.isSimpleTuple()) | 2105 | if (ty.isSimpleTuple()) |
| 2106 | std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable | 2106 | std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable |
| 2107 | else switch (zig_ty_tag) { | 2107 | else switch (zig_ty_tag) { |
| 2108 | .Struct => ty.structFieldName(field_i), | 2108 | .Struct => ty.structFieldName(field_i, mod), |
| 2109 | .Union => ty.unionFields().keys()[field_i], | 2109 | .Union => ty.unionFields().keys()[field_i], |
| 2110 | else => unreachable, | 2110 | else => unreachable, |
| 2111 | }, | 2111 | }, |
| ... | @@ -2210,12 +2210,12 @@ pub const CType = extern union { | ... | @@ -2210,12 +2210,12 @@ pub const CType = extern union { |
| 2210 | 2210 | ||
| 2211 | const zig_ty_tag = ty.zigTypeTag(mod); | 2211 | const zig_ty_tag = ty.zigTypeTag(mod); |
| 2212 | for (0..switch (ty.zigTypeTag(mod)) { | 2212 | for (0..switch (ty.zigTypeTag(mod)) { |
| 2213 | .Struct => ty.structFieldCount(), | 2213 | .Struct => ty.structFieldCount(mod), |
| 2214 | .Union => ty.unionFields().count(), | 2214 | .Union => ty.unionFields().count(), |
| 2215 | else => unreachable, | 2215 | else => unreachable, |
| 2216 | }) |field_i| { | 2216 | }) |field_i| { |
| 2217 | const field_ty = ty.structFieldType(field_i); | 2217 | const field_ty = ty.structFieldType(field_i, mod); |
| 2218 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or | 2218 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or |
| 2219 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 2219 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2220 | 2220 | ||
| 2221 | self.updateHasherRecurse(hasher, field_ty, switch (self.kind) { | 2221 | self.updateHasherRecurse(hasher, field_ty, switch (self.kind) { |
| ... | @@ -2227,7 +2227,7 @@ pub const CType = extern union { | ... | @@ -2227,7 +2227,7 @@ pub const CType = extern union { |
| 2227 | hasher.update(if (ty.isSimpleTuple()) | 2227 | hasher.update(if (ty.isSimpleTuple()) |
| 2228 | std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable | 2228 | std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable |
| 2229 | else switch (zig_ty_tag) { | 2229 | else switch (zig_ty_tag) { |
| 2230 | .Struct => ty.structFieldName(field_i), | 2230 | .Struct => ty.structFieldName(field_i, mod), |
| 2231 | .Union => ty.unionFields().keys()[field_i], | 2231 | .Union => ty.unionFields().keys()[field_i], |
| 2232 | else => unreachable, | 2232 | else => unreachable, |
| 2233 | }); | 2233 | }); |
src/codegen/llvm.zig+26-28| ... | @@ -1986,8 +1986,7 @@ pub const Object = struct { | ... | @@ -1986,8 +1986,7 @@ pub const Object = struct { |
| 1986 | const name = try ty.nameAlloc(gpa, o.module); | 1986 | const name = try ty.nameAlloc(gpa, o.module); |
| 1987 | defer gpa.free(name); | 1987 | defer gpa.free(name); |
| 1988 | 1988 | ||
| 1989 | if (ty.castTag(.@"struct")) |payload| { | 1989 | if (mod.typeToStruct(ty)) |struct_obj| { |
| 1990 | const struct_obj = payload.data; | ||
| 1991 | if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) { | 1990 | if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) { |
| 1992 | assert(struct_obj.haveLayout()); | 1991 | assert(struct_obj.haveLayout()); |
| 1993 | const info = struct_obj.backing_int_ty.intInfo(mod); | 1992 | const info = struct_obj.backing_int_ty.intInfo(mod); |
| ... | @@ -2075,8 +2074,7 @@ pub const Object = struct { | ... | @@ -2075,8 +2074,7 @@ pub const Object = struct { |
| 2075 | return full_di_ty; | 2074 | return full_di_ty; |
| 2076 | } | 2075 | } |
| 2077 | 2076 | ||
| 2078 | if (ty.castTag(.@"struct")) |payload| { | 2077 | if (mod.typeToStruct(ty)) |struct_obj| { |
| 2079 | const struct_obj = payload.data; | ||
| 2080 | if (!struct_obj.haveFieldTypes()) { | 2078 | if (!struct_obj.haveFieldTypes()) { |
| 2081 | // This can happen if a struct type makes it all the way to | 2079 | // This can happen if a struct type makes it all the way to |
| 2082 | // flush() without ever being instantiated or referenced (even | 2080 | // flush() without ever being instantiated or referenced (even |
| ... | @@ -2105,8 +2103,8 @@ pub const Object = struct { | ... | @@ -2105,8 +2103,8 @@ pub const Object = struct { |
| 2105 | return struct_di_ty; | 2103 | return struct_di_ty; |
| 2106 | } | 2104 | } |
| 2107 | 2105 | ||
| 2108 | const fields = ty.structFields(); | 2106 | const fields = ty.structFields(mod); |
| 2109 | const layout = ty.containerLayout(); | 2107 | const layout = ty.containerLayout(mod); |
| 2110 | 2108 | ||
| 2111 | var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{}; | 2109 | var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{}; |
| 2112 | defer di_fields.deinit(gpa); | 2110 | defer di_fields.deinit(gpa); |
| ... | @@ -2116,7 +2114,7 @@ pub const Object = struct { | ... | @@ -2116,7 +2114,7 @@ pub const Object = struct { |
| 2116 | comptime assert(struct_layout_version == 2); | 2114 | comptime assert(struct_layout_version == 2); |
| 2117 | var offset: u64 = 0; | 2115 | var offset: u64 = 0; |
| 2118 | 2116 | ||
| 2119 | var it = ty.castTag(.@"struct").?.data.runtimeFieldIterator(mod); | 2117 | var it = mod.typeToStruct(ty).?.runtimeFieldIterator(mod); |
| 2120 | while (it.next()) |field_and_index| { | 2118 | while (it.next()) |field_and_index| { |
| 2121 | const field = field_and_index.field; | 2119 | const field = field_and_index.field; |
| 2122 | const field_size = field.ty.abiSize(mod); | 2120 | const field_size = field.ty.abiSize(mod); |
| ... | @@ -2990,7 +2988,7 @@ pub const DeclGen = struct { | ... | @@ -2990,7 +2988,7 @@ pub const DeclGen = struct { |
| 2990 | return llvm_struct_ty; | 2988 | return llvm_struct_ty; |
| 2991 | } | 2989 | } |
| 2992 | 2990 | ||
| 2993 | const struct_obj = t.castTag(.@"struct").?.data; | 2991 | const struct_obj = mod.typeToStruct(t).?; |
| 2994 | 2992 | ||
| 2995 | if (struct_obj.layout == .Packed) { | 2993 | if (struct_obj.layout == .Packed) { |
| 2996 | assert(struct_obj.haveLayout()); | 2994 | assert(struct_obj.haveLayout()); |
| ... | @@ -3696,7 +3694,7 @@ pub const DeclGen = struct { | ... | @@ -3696,7 +3694,7 @@ pub const DeclGen = struct { |
| 3696 | } | 3694 | } |
| 3697 | } | 3695 | } |
| 3698 | 3696 | ||
| 3699 | const struct_obj = tv.ty.castTag(.@"struct").?.data; | 3697 | const struct_obj = mod.typeToStruct(tv.ty).?; |
| 3700 | 3698 | ||
| 3701 | if (struct_obj.layout == .Packed) { | 3699 | if (struct_obj.layout == .Packed) { |
| 3702 | assert(struct_obj.haveLayout()); | 3700 | assert(struct_obj.haveLayout()); |
| ... | @@ -4043,7 +4041,7 @@ pub const DeclGen = struct { | ... | @@ -4043,7 +4041,7 @@ pub const DeclGen = struct { |
| 4043 | const llvm_u32 = dg.context.intType(32); | 4041 | const llvm_u32 = dg.context.intType(32); |
| 4044 | switch (parent_ty.zigTypeTag(mod)) { | 4042 | switch (parent_ty.zigTypeTag(mod)) { |
| 4045 | .Union => { | 4043 | .Union => { |
| 4046 | if (parent_ty.containerLayout() == .Packed) { | 4044 | if (parent_ty.containerLayout(mod) == .Packed) { |
| 4047 | return parent_llvm_ptr; | 4045 | return parent_llvm_ptr; |
| 4048 | } | 4046 | } |
| 4049 | 4047 | ||
| ... | @@ -4065,14 +4063,14 @@ pub const DeclGen = struct { | ... | @@ -4065,14 +4063,14 @@ pub const DeclGen = struct { |
| 4065 | return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); | 4063 | return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 4066 | }, | 4064 | }, |
| 4067 | .Struct => { | 4065 | .Struct => { |
| 4068 | if (parent_ty.containerLayout() == .Packed) { | 4066 | if (parent_ty.containerLayout(mod) == .Packed) { |
| 4069 | if (!byte_aligned) return parent_llvm_ptr; | 4067 | if (!byte_aligned) return parent_llvm_ptr; |
| 4070 | const llvm_usize = dg.context.intType(target.ptrBitWidth()); | 4068 | const llvm_usize = dg.context.intType(target.ptrBitWidth()); |
| 4071 | const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize); | 4069 | const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize); |
| 4072 | // count bits of fields before this one | 4070 | // count bits of fields before this one |
| 4073 | const prev_bits = b: { | 4071 | const prev_bits = b: { |
| 4074 | var b: usize = 0; | 4072 | var b: usize = 0; |
| 4075 | for (parent_ty.structFields().values()[0..field_index]) |field| { | 4073 | for (parent_ty.structFields(mod).values()[0..field_index]) |field| { |
| 4076 | if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 4074 | if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 4077 | b += @intCast(usize, field.ty.bitSize(mod)); | 4075 | b += @intCast(usize, field.ty.bitSize(mod)); |
| 4078 | } | 4076 | } |
| ... | @@ -5983,7 +5981,7 @@ pub const FuncGen = struct { | ... | @@ -5983,7 +5981,7 @@ pub const FuncGen = struct { |
| 5983 | const struct_ty = self.typeOf(struct_field.struct_operand); | 5981 | const struct_ty = self.typeOf(struct_field.struct_operand); |
| 5984 | const struct_llvm_val = try self.resolveInst(struct_field.struct_operand); | 5982 | const struct_llvm_val = try self.resolveInst(struct_field.struct_operand); |
| 5985 | const field_index = struct_field.field_index; | 5983 | const field_index = struct_field.field_index; |
| 5986 | const field_ty = struct_ty.structFieldType(field_index); | 5984 | const field_ty = struct_ty.structFieldType(field_index, mod); |
| 5987 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) { | 5985 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 5988 | return null; | 5986 | return null; |
| 5989 | } | 5987 | } |
| ... | @@ -5991,9 +5989,9 @@ pub const FuncGen = struct { | ... | @@ -5991,9 +5989,9 @@ pub const FuncGen = struct { |
| 5991 | if (!isByRef(struct_ty, mod)) { | 5989 | if (!isByRef(struct_ty, mod)) { |
| 5992 | assert(!isByRef(field_ty, mod)); | 5990 | assert(!isByRef(field_ty, mod)); |
| 5993 | switch (struct_ty.zigTypeTag(mod)) { | 5991 | switch (struct_ty.zigTypeTag(mod)) { |
| 5994 | .Struct => switch (struct_ty.containerLayout()) { | 5992 | .Struct => switch (struct_ty.containerLayout(mod)) { |
| 5995 | .Packed => { | 5993 | .Packed => { |
| 5996 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | 5994 | const struct_obj = mod.typeToStruct(struct_ty).?; |
| 5997 | const bit_offset = struct_obj.packedFieldBitOffset(mod, field_index); | 5995 | const bit_offset = struct_obj.packedFieldBitOffset(mod, field_index); |
| 5998 | const containing_int = struct_llvm_val; | 5996 | const containing_int = struct_llvm_val; |
| 5999 | const shift_amt = containing_int.typeOf().constInt(bit_offset, .False); | 5997 | const shift_amt = containing_int.typeOf().constInt(bit_offset, .False); |
| ... | @@ -6019,7 +6017,7 @@ pub const FuncGen = struct { | ... | @@ -6019,7 +6017,7 @@ pub const FuncGen = struct { |
| 6019 | }, | 6017 | }, |
| 6020 | }, | 6018 | }, |
| 6021 | .Union => { | 6019 | .Union => { |
| 6022 | assert(struct_ty.containerLayout() == .Packed); | 6020 | assert(struct_ty.containerLayout(mod) == .Packed); |
| 6023 | const containing_int = struct_llvm_val; | 6021 | const containing_int = struct_llvm_val; |
| 6024 | const elem_llvm_ty = try self.dg.lowerType(field_ty); | 6022 | const elem_llvm_ty = try self.dg.lowerType(field_ty); |
| 6025 | if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) { | 6023 | if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) { |
| ... | @@ -6041,7 +6039,7 @@ pub const FuncGen = struct { | ... | @@ -6041,7 +6039,7 @@ pub const FuncGen = struct { |
| 6041 | 6039 | ||
| 6042 | switch (struct_ty.zigTypeTag(mod)) { | 6040 | switch (struct_ty.zigTypeTag(mod)) { |
| 6043 | .Struct => { | 6041 | .Struct => { |
| 6044 | assert(struct_ty.containerLayout() != .Packed); | 6042 | assert(struct_ty.containerLayout(mod) != .Packed); |
| 6045 | var ptr_ty_buf: Type.Payload.Pointer = undefined; | 6043 | var ptr_ty_buf: Type.Payload.Pointer = undefined; |
| 6046 | const llvm_field_index = llvmFieldIndex(struct_ty, field_index, mod, &ptr_ty_buf).?; | 6044 | const llvm_field_index = llvmFieldIndex(struct_ty, field_index, mod, &ptr_ty_buf).?; |
| 6047 | const struct_llvm_ty = try self.dg.lowerType(struct_ty); | 6045 | const struct_llvm_ty = try self.dg.lowerType(struct_ty); |
| ... | @@ -9289,8 +9287,8 @@ pub const FuncGen = struct { | ... | @@ -9289,8 +9287,8 @@ pub const FuncGen = struct { |
| 9289 | return vector; | 9287 | return vector; |
| 9290 | }, | 9288 | }, |
| 9291 | .Struct => { | 9289 | .Struct => { |
| 9292 | if (result_ty.containerLayout() == .Packed) { | 9290 | if (result_ty.containerLayout(mod) == .Packed) { |
| 9293 | const struct_obj = result_ty.castTag(.@"struct").?.data; | 9291 | const struct_obj = mod.typeToStruct(result_ty).?; |
| 9294 | assert(struct_obj.haveLayout()); | 9292 | assert(struct_obj.haveLayout()); |
| 9295 | const big_bits = struct_obj.backing_int_ty.bitSize(mod); | 9293 | const big_bits = struct_obj.backing_int_ty.bitSize(mod); |
| 9296 | const int_llvm_ty = self.context.intType(@intCast(c_uint, big_bits)); | 9294 | const int_llvm_ty = self.context.intType(@intCast(c_uint, big_bits)); |
| ... | @@ -9795,7 +9793,7 @@ pub const FuncGen = struct { | ... | @@ -9795,7 +9793,7 @@ pub const FuncGen = struct { |
| 9795 | const mod = self.dg.module; | 9793 | const mod = self.dg.module; |
| 9796 | const struct_ty = struct_ptr_ty.childType(mod); | 9794 | const struct_ty = struct_ptr_ty.childType(mod); |
| 9797 | switch (struct_ty.zigTypeTag(mod)) { | 9795 | switch (struct_ty.zigTypeTag(mod)) { |
| 9798 | .Struct => switch (struct_ty.containerLayout()) { | 9796 | .Struct => switch (struct_ty.containerLayout(mod)) { |
| 9799 | .Packed => { | 9797 | .Packed => { |
| 9800 | const result_ty = self.typeOfIndex(inst); | 9798 | const result_ty = self.typeOfIndex(inst); |
| 9801 | const result_ty_info = result_ty.ptrInfo(mod); | 9799 | const result_ty_info = result_ty.ptrInfo(mod); |
| ... | @@ -9838,7 +9836,7 @@ pub const FuncGen = struct { | ... | @@ -9838,7 +9836,7 @@ pub const FuncGen = struct { |
| 9838 | }, | 9836 | }, |
| 9839 | .Union => { | 9837 | .Union => { |
| 9840 | const layout = struct_ty.unionGetLayout(mod); | 9838 | const layout = struct_ty.unionGetLayout(mod); |
| 9841 | if (layout.payload_size == 0 or struct_ty.containerLayout() == .Packed) return struct_ptr; | 9839 | if (layout.payload_size == 0 or struct_ty.containerLayout(mod) == .Packed) return struct_ptr; |
| 9842 | const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); | 9840 | const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); |
| 9843 | const union_llvm_ty = try self.dg.lowerType(struct_ty); | 9841 | const union_llvm_ty = try self.dg.lowerType(struct_ty); |
| 9844 | const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_ptr, payload_index, ""); | 9842 | const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_ptr, payload_index, ""); |
| ... | @@ -10530,11 +10528,11 @@ fn llvmFieldIndex( | ... | @@ -10530,11 +10528,11 @@ fn llvmFieldIndex( |
| 10530 | } | 10528 | } |
| 10531 | return null; | 10529 | return null; |
| 10532 | } | 10530 | } |
| 10533 | const layout = ty.containerLayout(); | 10531 | const layout = ty.containerLayout(mod); |
| 10534 | assert(layout != .Packed); | 10532 | assert(layout != .Packed); |
| 10535 | 10533 | ||
| 10536 | var llvm_field_index: c_uint = 0; | 10534 | var llvm_field_index: c_uint = 0; |
| 10537 | var it = ty.castTag(.@"struct").?.data.runtimeFieldIterator(mod); | 10535 | var it = mod.typeToStruct(ty).?.runtimeFieldIterator(mod); |
| 10538 | while (it.next()) |field_and_index| { | 10536 | while (it.next()) |field_and_index| { |
| 10539 | const field = field_and_index.field; | 10537 | const field = field_and_index.field; |
| 10540 | const field_align = field.alignment(mod, layout); | 10538 | const field_align = field.alignment(mod, layout); |
| ... | @@ -11113,7 +11111,7 @@ fn isByRef(ty: Type, mod: *Module) bool { | ... | @@ -11113,7 +11111,7 @@ fn isByRef(ty: Type, mod: *Module) bool { |
| 11113 | .Array, .Frame => return ty.hasRuntimeBits(mod), | 11111 | .Array, .Frame => return ty.hasRuntimeBits(mod), |
| 11114 | .Struct => { | 11112 | .Struct => { |
| 11115 | // Packed structs are represented to LLVM as integers. | 11113 | // Packed structs are represented to LLVM as integers. |
| 11116 | if (ty.containerLayout() == .Packed) return false; | 11114 | if (ty.containerLayout(mod) == .Packed) return false; |
| 11117 | if (ty.isSimpleTupleOrAnonStruct()) { | 11115 | if (ty.isSimpleTupleOrAnonStruct()) { |
| 11118 | const tuple = ty.tupleFields(); | 11116 | const tuple = ty.tupleFields(); |
| 11119 | var count: usize = 0; | 11117 | var count: usize = 0; |
| ... | @@ -11127,7 +11125,7 @@ fn isByRef(ty: Type, mod: *Module) bool { | ... | @@ -11127,7 +11125,7 @@ fn isByRef(ty: Type, mod: *Module) bool { |
| 11127 | return false; | 11125 | return false; |
| 11128 | } | 11126 | } |
| 11129 | var count: usize = 0; | 11127 | var count: usize = 0; |
| 11130 | const fields = ty.structFields(); | 11128 | const fields = ty.structFields(mod); |
| 11131 | for (fields.values()) |field| { | 11129 | for (fields.values()) |field| { |
| 11132 | if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue; | 11130 | if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue; |
| 11133 | 11131 | ||
| ... | @@ -11137,7 +11135,7 @@ fn isByRef(ty: Type, mod: *Module) bool { | ... | @@ -11137,7 +11135,7 @@ fn isByRef(ty: Type, mod: *Module) bool { |
| 11137 | } | 11135 | } |
| 11138 | return false; | 11136 | return false; |
| 11139 | }, | 11137 | }, |
| 11140 | .Union => switch (ty.containerLayout()) { | 11138 | .Union => switch (ty.containerLayout(mod)) { |
| 11141 | .Packed => return false, | 11139 | .Packed => return false, |
| 11142 | else => return ty.hasRuntimeBits(mod), | 11140 | else => return ty.hasRuntimeBits(mod), |
| 11143 | }, | 11141 | }, |
| ... | @@ -11176,8 +11174,8 @@ fn isScalar(mod: *Module, ty: Type) bool { | ... | @@ -11176,8 +11174,8 @@ fn isScalar(mod: *Module, ty: Type) bool { |
| 11176 | .Vector, | 11174 | .Vector, |
| 11177 | => true, | 11175 | => true, |
| 11178 | 11176 | ||
| 11179 | .Struct => ty.containerLayout() == .Packed, | 11177 | .Struct => ty.containerLayout(mod) == .Packed, |
| 11180 | .Union => ty.containerLayout() == .Packed, | 11178 | .Union => ty.containerLayout(mod) == .Packed, |
| 11181 | else => false, | 11179 | else => false, |
| 11182 | }; | 11180 | }; |
| 11183 | } | 11181 | } |
src/codegen/spirv.zig+4-4| ... | @@ -685,7 +685,7 @@ pub const DeclGen = struct { | ... | @@ -685,7 +685,7 @@ pub const DeclGen = struct { |
| 685 | if (ty.isSimpleTupleOrAnonStruct()) { | 685 | if (ty.isSimpleTupleOrAnonStruct()) { |
| 686 | unreachable; // TODO | 686 | unreachable; // TODO |
| 687 | } else { | 687 | } else { |
| 688 | const struct_ty = ty.castTag(.@"struct").?.data; | 688 | const struct_ty = mod.typeToStruct(ty).?; |
| 689 | 689 | ||
| 690 | if (struct_ty.layout == .Packed) { | 690 | if (struct_ty.layout == .Packed) { |
| 691 | return dg.todo("packed struct constants", .{}); | 691 | return dg.todo("packed struct constants", .{}); |
| ... | @@ -1306,7 +1306,7 @@ pub const DeclGen = struct { | ... | @@ -1306,7 +1306,7 @@ pub const DeclGen = struct { |
| 1306 | } }); | 1306 | } }); |
| 1307 | } | 1307 | } |
| 1308 | 1308 | ||
| 1309 | const struct_ty = ty.castTag(.@"struct").?.data; | 1309 | const struct_ty = mod.typeToStruct(ty).?; |
| 1310 | 1310 | ||
| 1311 | if (struct_ty.layout == .Packed) { | 1311 | if (struct_ty.layout == .Packed) { |
| 1312 | return try self.resolveType(struct_ty.backing_int_ty, .direct); | 1312 | return try self.resolveType(struct_ty.backing_int_ty, .direct); |
| ... | @@ -2576,7 +2576,7 @@ pub const DeclGen = struct { | ... | @@ -2576,7 +2576,7 @@ pub const DeclGen = struct { |
| 2576 | const struct_ty = self.typeOf(struct_field.struct_operand); | 2576 | const struct_ty = self.typeOf(struct_field.struct_operand); |
| 2577 | const object_id = try self.resolve(struct_field.struct_operand); | 2577 | const object_id = try self.resolve(struct_field.struct_operand); |
| 2578 | const field_index = struct_field.field_index; | 2578 | const field_index = struct_field.field_index; |
| 2579 | const field_ty = struct_ty.structFieldType(field_index); | 2579 | const field_ty = struct_ty.structFieldType(field_index, mod); |
| 2580 | 2580 | ||
| 2581 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) return null; | 2581 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) return null; |
| 2582 | 2582 | ||
| ... | @@ -2595,7 +2595,7 @@ pub const DeclGen = struct { | ... | @@ -2595,7 +2595,7 @@ pub const DeclGen = struct { |
| 2595 | const mod = self.module; | 2595 | const mod = self.module; |
| 2596 | const object_ty = object_ptr_ty.childType(mod); | 2596 | const object_ty = object_ptr_ty.childType(mod); |
| 2597 | switch (object_ty.zigTypeTag(mod)) { | 2597 | switch (object_ty.zigTypeTag(mod)) { |
| 2598 | .Struct => switch (object_ty.containerLayout()) { | 2598 | .Struct => switch (object_ty.containerLayout(mod)) { |
| 2599 | .Packed => unreachable, // TODO | 2599 | .Packed => unreachable, // TODO |
| 2600 | else => { | 2600 | else => { |
| 2601 | const field_index_ty_ref = try self.intType(.unsigned, 32); | 2601 | const field_index_ty_ref = try self.intType(.unsigned, 32); |
src/link/Dwarf.zig+2-2| ... | @@ -360,13 +360,13 @@ pub const DeclState = struct { | ... | @@ -360,13 +360,13 @@ pub const DeclState = struct { |
| 360 | dbg_info_buffer.appendSliceAssumeCapacity(struct_name); | 360 | dbg_info_buffer.appendSliceAssumeCapacity(struct_name); |
| 361 | dbg_info_buffer.appendAssumeCapacity(0); | 361 | dbg_info_buffer.appendAssumeCapacity(0); |
| 362 | 362 | ||
| 363 | const struct_obj = ty.castTag(.@"struct").?.data; | 363 | const struct_obj = mod.typeToStruct(ty).?; |
| 364 | if (struct_obj.layout == .Packed) { | 364 | if (struct_obj.layout == .Packed) { |
| 365 | log.debug("TODO implement .debug_info for packed structs", .{}); | 365 | log.debug("TODO implement .debug_info for packed structs", .{}); |
| 366 | break :blk; | 366 | break :blk; |
| 367 | } | 367 | } |
| 368 | 368 | ||
| 369 | const fields = ty.structFields(); | 369 | const fields = ty.structFields(mod); |
| 370 | for (fields.keys(), 0..) |field_name, field_index| { | 370 | for (fields.keys(), 0..) |field_name, field_index| { |
| 371 | const field = fields.get(field_name).?; | 371 | const field = fields.get(field_name).?; |
| 372 | if (!field.ty.hasRuntimeBits(mod)) continue; | 372 | if (!field.ty.hasRuntimeBits(mod)) continue; |
src/type.zig+601-582| ... | @@ -59,8 +59,6 @@ pub const Type = struct { | ... | @@ -59,8 +59,6 @@ pub const Type = struct { |
| 59 | 59 | ||
| 60 | .anyframe_T => return .AnyFrame, | 60 | .anyframe_T => return .AnyFrame, |
| 61 | 61 | ||
| 62 | .empty_struct, | ||
| 63 | .@"struct", | ||
| 64 | .tuple, | 62 | .tuple, |
| 65 | .anon_struct, | 63 | .anon_struct, |
| 66 | => return .Struct, | 64 | => return .Struct, |
| ... | @@ -148,6 +146,7 @@ pub const Type = struct { | ... | @@ -148,6 +146,7 @@ pub const Type = struct { |
| 148 | .opt => unreachable, | 146 | .opt => unreachable, |
| 149 | .enum_tag => unreachable, | 147 | .enum_tag => unreachable, |
| 150 | .simple_value => unreachable, | 148 | .simple_value => unreachable, |
| 149 | .aggregate => unreachable, | ||
| 151 | }, | 150 | }, |
| 152 | } | 151 | } |
| 153 | } | 152 | } |
| ... | @@ -501,16 +500,6 @@ pub const Type = struct { | ... | @@ -501,16 +500,6 @@ pub const Type = struct { |
| 501 | return a.elemType2(mod).eql(b.elemType2(mod), mod); | 500 | return a.elemType2(mod).eql(b.elemType2(mod), mod); |
| 502 | }, | 501 | }, |
| 503 | 502 | ||
| 504 | .empty_struct => { | ||
| 505 | const a_namespace = a.castTag(.empty_struct).?.data; | ||
| 506 | const b_namespace = (b.castTag(.empty_struct) orelse return false).data; | ||
| 507 | return a_namespace == b_namespace; | ||
| 508 | }, | ||
| 509 | .@"struct" => { | ||
| 510 | const a_struct_obj = a.castTag(.@"struct").?.data; | ||
| 511 | const b_struct_obj = (b.castTag(.@"struct") orelse return false).data; | ||
| 512 | return a_struct_obj == b_struct_obj; | ||
| 513 | }, | ||
| 514 | .tuple => { | 503 | .tuple => { |
| 515 | if (!b.isSimpleTuple()) return false; | 504 | if (!b.isSimpleTuple()) return false; |
| 516 | 505 | ||
| ... | @@ -720,15 +709,6 @@ pub const Type = struct { | ... | @@ -720,15 +709,6 @@ pub const Type = struct { |
| 720 | hashWithHasher(ty.childType(mod), hasher, mod); | 709 | hashWithHasher(ty.childType(mod), hasher, mod); |
| 721 | }, | 710 | }, |
| 722 | 711 | ||
| 723 | .empty_struct => { | ||
| 724 | std.hash.autoHash(hasher, std.builtin.TypeId.Struct); | ||
| 725 | const namespace: *const Module.Namespace = ty.castTag(.empty_struct).?.data; | ||
| 726 | std.hash.autoHash(hasher, namespace); | ||
| 727 | }, | ||
| 728 | .@"struct" => { | ||
| 729 | const struct_obj: *const Module.Struct = ty.castTag(.@"struct").?.data; | ||
| 730 | std.hash.autoHash(hasher, struct_obj); | ||
| 731 | }, | ||
| 732 | .tuple => { | 712 | .tuple => { |
| 733 | std.hash.autoHash(hasher, std.builtin.TypeId.Struct); | 713 | std.hash.autoHash(hasher, std.builtin.TypeId.Struct); |
| 734 | 714 | ||
| ... | @@ -955,8 +935,6 @@ pub const Type = struct { | ... | @@ -955,8 +935,6 @@ pub const Type = struct { |
| 955 | .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet), | 935 | .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet), |
| 956 | .error_set_inferred => return self.copyPayloadShallow(allocator, Payload.ErrorSetInferred), | 936 | .error_set_inferred => return self.copyPayloadShallow(allocator, Payload.ErrorSetInferred), |
| 957 | .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name), | 937 | .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name), |
| 958 | .empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope), | ||
| 959 | .@"struct" => return self.copyPayloadShallow(allocator, Payload.Struct), | ||
| 960 | .@"union", .union_safety_tagged, .union_tagged => return self.copyPayloadShallow(allocator, Payload.Union), | 938 | .@"union", .union_safety_tagged, .union_tagged => return self.copyPayloadShallow(allocator, Payload.Union), |
| 961 | .enum_simple => return self.copyPayloadShallow(allocator, Payload.EnumSimple), | 939 | .enum_simple => return self.copyPayloadShallow(allocator, Payload.EnumSimple), |
| 962 | .enum_numbered => return self.copyPayloadShallow(allocator, Payload.EnumNumbered), | 940 | .enum_numbered => return self.copyPayloadShallow(allocator, Payload.EnumNumbered), |
| ... | @@ -1033,14 +1011,6 @@ pub const Type = struct { | ... | @@ -1033,14 +1011,6 @@ pub const Type = struct { |
| 1033 | while (true) { | 1011 | while (true) { |
| 1034 | const t = ty.tag(); | 1012 | const t = ty.tag(); |
| 1035 | switch (t) { | 1013 | switch (t) { |
| 1036 | .empty_struct => return writer.writeAll("struct {}"), | ||
| 1037 | |||
| 1038 | .@"struct" => { | ||
| 1039 | const struct_obj = ty.castTag(.@"struct").?.data; | ||
| 1040 | return writer.print("({s} decl={d})", .{ | ||
| 1041 | @tagName(t), struct_obj.owner_decl, | ||
| 1042 | }); | ||
| 1043 | }, | ||
| 1044 | .@"union", .union_safety_tagged, .union_tagged => { | 1014 | .@"union", .union_safety_tagged, .union_tagged => { |
| 1045 | const union_obj = ty.cast(Payload.Union).?.data; | 1015 | const union_obj = ty.cast(Payload.Union).?.data; |
| 1046 | return writer.print("({s} decl={d})", .{ | 1016 | return writer.print("({s} decl={d})", .{ |
| ... | @@ -1247,22 +1217,10 @@ pub const Type = struct { | ... | @@ -1247,22 +1217,10 @@ pub const Type = struct { |
| 1247 | /// Prints a name suitable for `@typeName`. | 1217 | /// Prints a name suitable for `@typeName`. |
| 1248 | pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void { | 1218 | pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void { |
| 1249 | switch (ty.ip_index) { | 1219 | switch (ty.ip_index) { |
| 1250 | .empty_struct_type => try writer.writeAll("@TypeOf(.{})"), | ||
| 1251 | |||
| 1252 | .none => switch (ty.tag()) { | 1220 | .none => switch (ty.tag()) { |
| 1253 | .inferred_alloc_const => unreachable, | 1221 | .inferred_alloc_const => unreachable, |
| 1254 | .inferred_alloc_mut => unreachable, | 1222 | .inferred_alloc_mut => unreachable, |
| 1255 | 1223 | ||
| 1256 | .empty_struct => { | ||
| 1257 | const namespace = ty.castTag(.empty_struct).?.data; | ||
| 1258 | try namespace.renderFullyQualifiedName(mod, "", writer); | ||
| 1259 | }, | ||
| 1260 | |||
| 1261 | .@"struct" => { | ||
| 1262 | const struct_obj = ty.castTag(.@"struct").?.data; | ||
| 1263 | const decl = mod.declPtr(struct_obj.owner_decl); | ||
| 1264 | try decl.renderFullyQualifiedName(mod, writer); | ||
| 1265 | }, | ||
| 1266 | .@"union", .union_safety_tagged, .union_tagged => { | 1224 | .@"union", .union_safety_tagged, .union_tagged => { |
| 1267 | const union_obj = ty.cast(Payload.Union).?.data; | 1225 | const union_obj = ty.cast(Payload.Union).?.data; |
| 1268 | const decl = mod.declPtr(union_obj.owner_decl); | 1226 | const decl = mod.declPtr(union_obj.owner_decl); |
| ... | @@ -1548,7 +1506,18 @@ pub const Type = struct { | ... | @@ -1548,7 +1506,18 @@ pub const Type = struct { |
| 1548 | return; | 1506 | return; |
| 1549 | }, | 1507 | }, |
| 1550 | .simple_type => |s| return writer.writeAll(@tagName(s)), | 1508 | .simple_type => |s| return writer.writeAll(@tagName(s)), |
| 1551 | .struct_type => @panic("TODO"), | 1509 | .struct_type => |struct_type| { |
| 1510 | if (mod.structPtrUnwrap(struct_type.index)) |struct_obj| { | ||
| 1511 | const decl = mod.declPtr(struct_obj.owner_decl); | ||
| 1512 | try decl.renderFullyQualifiedName(mod, writer); | ||
| 1513 | } else if (struct_type.namespace.unwrap()) |namespace_index| { | ||
| 1514 | const namespace = mod.namespacePtr(namespace_index); | ||
| 1515 | try namespace.renderFullyQualifiedName(mod, "", writer); | ||
| 1516 | } else { | ||
| 1517 | try writer.writeAll("@TypeOf(.{})"); | ||
| 1518 | } | ||
| 1519 | }, | ||
| 1520 | |||
| 1552 | .union_type => @panic("TODO"), | 1521 | .union_type => @panic("TODO"), |
| 1553 | .opaque_type => |opaque_type| { | 1522 | .opaque_type => |opaque_type| { |
| 1554 | const decl = mod.declPtr(opaque_type.decl); | 1523 | const decl = mod.declPtr(opaque_type.decl); |
| ... | @@ -1562,6 +1531,7 @@ pub const Type = struct { | ... | @@ -1562,6 +1531,7 @@ pub const Type = struct { |
| 1562 | .ptr => unreachable, | 1531 | .ptr => unreachable, |
| 1563 | .opt => unreachable, | 1532 | .opt => unreachable, |
| 1564 | .enum_tag => unreachable, | 1533 | .enum_tag => unreachable, |
| 1534 | .aggregate => unreachable, | ||
| 1565 | }, | 1535 | }, |
| 1566 | } | 1536 | } |
| 1567 | } | 1537 | } |
| ... | @@ -1624,12 +1594,10 @@ pub const Type = struct { | ... | @@ -1624,12 +1594,10 @@ pub const Type = struct { |
| 1624 | }, | 1594 | }, |
| 1625 | 1595 | ||
| 1626 | // These are false because they are comptime-only types. | 1596 | // These are false because they are comptime-only types. |
| 1627 | .empty_struct, | ||
| 1628 | // These are function *bodies*, not pointers. | 1597 | // These are function *bodies*, not pointers. |
| 1629 | // Special exceptions have to be made when emitting functions due to | 1598 | // Special exceptions have to be made when emitting functions due to |
| 1630 | // this returning false. | 1599 | // this returning false. |
| 1631 | .function, | 1600 | .function => return false, |
| 1632 | => return false, | ||
| 1633 | 1601 | ||
| 1634 | .optional => { | 1602 | .optional => { |
| 1635 | const child_ty = ty.optionalChild(mod); | 1603 | const child_ty = ty.optionalChild(mod); |
| ... | @@ -1646,28 +1614,6 @@ pub const Type = struct { | ... | @@ -1646,28 +1614,6 @@ pub const Type = struct { |
| 1646 | } | 1614 | } |
| 1647 | }, | 1615 | }, |
| 1648 | 1616 | ||
| 1649 | .@"struct" => { | ||
| 1650 | const struct_obj = ty.castTag(.@"struct").?.data; | ||
| 1651 | if (struct_obj.status == .field_types_wip) { | ||
| 1652 | // In this case, we guess that hasRuntimeBits() for this type is true, | ||
| 1653 | // and then later if our guess was incorrect, we emit a compile error. | ||
| 1654 | struct_obj.assumed_runtime_bits = true; | ||
| 1655 | return true; | ||
| 1656 | } | ||
| 1657 | switch (strat) { | ||
| 1658 | .sema => |sema| _ = try sema.resolveTypeFields(ty), | ||
| 1659 | .eager => assert(struct_obj.haveFieldTypes()), | ||
| 1660 | .lazy => if (!struct_obj.haveFieldTypes()) return error.NeedLazy, | ||
| 1661 | } | ||
| 1662 | for (struct_obj.fields.values()) |field| { | ||
| 1663 | if (field.is_comptime) continue; | ||
| 1664 | if (try field.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) | ||
| 1665 | return true; | ||
| 1666 | } else { | ||
| 1667 | return false; | ||
| 1668 | } | ||
| 1669 | }, | ||
| 1670 | |||
| 1671 | .enum_full => { | 1617 | .enum_full => { |
| 1672 | const enum_full = ty.castTag(.enum_full).?.data; | 1618 | const enum_full = ty.castTag(.enum_full).?.data; |
| 1673 | return enum_full.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); | 1619 | return enum_full.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); |
| ... | @@ -1824,7 +1770,31 @@ pub const Type = struct { | ... | @@ -1824,7 +1770,31 @@ pub const Type = struct { |
| 1824 | .generic_poison => unreachable, | 1770 | .generic_poison => unreachable, |
| 1825 | .var_args_param => unreachable, | 1771 | .var_args_param => unreachable, |
| 1826 | }, | 1772 | }, |
| 1827 | .struct_type => @panic("TODO"), | 1773 | .struct_type => |struct_type| { |
| 1774 | const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse { | ||
| 1775 | // This struct has no fields. | ||
| 1776 | return false; | ||
| 1777 | }; | ||
| 1778 | if (struct_obj.status == .field_types_wip) { | ||
| 1779 | // In this case, we guess that hasRuntimeBits() for this type is true, | ||
| 1780 | // and then later if our guess was incorrect, we emit a compile error. | ||
| 1781 | struct_obj.assumed_runtime_bits = true; | ||
| 1782 | return true; | ||
| 1783 | } | ||
| 1784 | switch (strat) { | ||
| 1785 | .sema => |sema| _ = try sema.resolveTypeFields(ty), | ||
| 1786 | .eager => assert(struct_obj.haveFieldTypes()), | ||
| 1787 | .lazy => if (!struct_obj.haveFieldTypes()) return error.NeedLazy, | ||
| 1788 | } | ||
| 1789 | for (struct_obj.fields.values()) |field| { | ||
| 1790 | if (field.is_comptime) continue; | ||
| 1791 | if (try field.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) | ||
| 1792 | return true; | ||
| 1793 | } else { | ||
| 1794 | return false; | ||
| 1795 | } | ||
| 1796 | }, | ||
| 1797 | |||
| 1828 | .union_type => @panic("TODO"), | 1798 | .union_type => @panic("TODO"), |
| 1829 | .opaque_type => true, | 1799 | .opaque_type => true, |
| 1830 | 1800 | ||
| ... | @@ -1835,6 +1805,7 @@ pub const Type = struct { | ... | @@ -1835,6 +1805,7 @@ pub const Type = struct { |
| 1835 | .ptr => unreachable, | 1805 | .ptr => unreachable, |
| 1836 | .opt => unreachable, | 1806 | .opt => unreachable, |
| 1837 | .enum_tag => unreachable, | 1807 | .enum_tag => unreachable, |
| 1808 | .aggregate => unreachable, | ||
| 1838 | }, | 1809 | }, |
| 1839 | } | 1810 | } |
| 1840 | } | 1811 | } |
| ... | @@ -1862,7 +1833,6 @@ pub const Type = struct { | ... | @@ -1862,7 +1833,6 @@ pub const Type = struct { |
| 1862 | .anyframe_T, | 1833 | .anyframe_T, |
| 1863 | .tuple, | 1834 | .tuple, |
| 1864 | .anon_struct, | 1835 | .anon_struct, |
| 1865 | .empty_struct, | ||
| 1866 | => false, | 1836 | => false, |
| 1867 | 1837 | ||
| 1868 | .enum_full, | 1838 | .enum_full, |
| ... | @@ -1877,7 +1847,6 @@ pub const Type = struct { | ... | @@ -1877,7 +1847,6 @@ pub const Type = struct { |
| 1877 | => ty.childType(mod).hasWellDefinedLayout(mod), | 1847 | => ty.childType(mod).hasWellDefinedLayout(mod), |
| 1878 | 1848 | ||
| 1879 | .optional => ty.isPtrLikeOptional(mod), | 1849 | .optional => ty.isPtrLikeOptional(mod), |
| 1880 | .@"struct" => ty.castTag(.@"struct").?.data.layout != .Auto, | ||
| 1881 | .@"union", .union_safety_tagged => ty.cast(Payload.Union).?.data.layout != .Auto, | 1850 | .@"union", .union_safety_tagged => ty.cast(Payload.Union).?.data.layout != .Auto, |
| 1882 | .union_tagged => false, | 1851 | .union_tagged => false, |
| 1883 | }, | 1852 | }, |
| ... | @@ -1936,7 +1905,13 @@ pub const Type = struct { | ... | @@ -1936,7 +1905,13 @@ pub const Type = struct { |
| 1936 | 1905 | ||
| 1937 | .var_args_param => unreachable, | 1906 | .var_args_param => unreachable, |
| 1938 | }, | 1907 | }, |
| 1939 | .struct_type => @panic("TODO"), | 1908 | .struct_type => |struct_type| { |
| 1909 | const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse { | ||
| 1910 | // Struct with no fields has a well-defined layout of no bits. | ||
| 1911 | return true; | ||
| 1912 | }; | ||
| 1913 | return struct_obj.layout != .Auto; | ||
| 1914 | }, | ||
| 1940 | .union_type => @panic("TODO"), | 1915 | .union_type => @panic("TODO"), |
| 1941 | .opaque_type => false, | 1916 | .opaque_type => false, |
| 1942 | 1917 | ||
| ... | @@ -1947,6 +1922,7 @@ pub const Type = struct { | ... | @@ -1947,6 +1922,7 @@ pub const Type = struct { |
| 1947 | .ptr => unreachable, | 1922 | .ptr => unreachable, |
| 1948 | .opt => unreachable, | 1923 | .opt => unreachable, |
| 1949 | .enum_tag => unreachable, | 1924 | .enum_tag => unreachable, |
| 1925 | .aggregate => unreachable, | ||
| 1950 | }, | 1926 | }, |
| 1951 | }; | 1927 | }; |
| 1952 | } | 1928 | } |
| ... | @@ -2146,68 +2122,6 @@ pub const Type = struct { | ... | @@ -2146,68 +2122,6 @@ pub const Type = struct { |
| 2146 | .optional => return abiAlignmentAdvancedOptional(ty, mod, strat), | 2122 | .optional => return abiAlignmentAdvancedOptional(ty, mod, strat), |
| 2147 | .error_union => return abiAlignmentAdvancedErrorUnion(ty, mod, strat), | 2123 | .error_union => return abiAlignmentAdvancedErrorUnion(ty, mod, strat), |
| 2148 | 2124 | ||
| 2149 | .@"struct" => { | ||
| 2150 | const struct_obj = ty.castTag(.@"struct").?.data; | ||
| 2151 | if (opt_sema) |sema| { | ||
| 2152 | if (struct_obj.status == .field_types_wip) { | ||
| 2153 | // We'll guess "pointer-aligned", if the struct has an | ||
| 2154 | // underaligned pointer field then some allocations | ||
| 2155 | // might require explicit alignment. | ||
| 2156 | return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }; | ||
| 2157 | } | ||
| 2158 | _ = try sema.resolveTypeFields(ty); | ||
| 2159 | } | ||
| 2160 | if (!struct_obj.haveFieldTypes()) switch (strat) { | ||
| 2161 | .eager => unreachable, // struct layout not resolved | ||
| 2162 | .sema => unreachable, // handled above | ||
| 2163 | .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) }, | ||
| 2164 | }; | ||
| 2165 | if (struct_obj.layout == .Packed) { | ||
| 2166 | switch (strat) { | ||
| 2167 | .sema => |sema| try sema.resolveTypeLayout(ty), | ||
| 2168 | .lazy => |arena| { | ||
| 2169 | if (!struct_obj.haveLayout()) { | ||
| 2170 | return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) }; | ||
| 2171 | } | ||
| 2172 | }, | ||
| 2173 | .eager => {}, | ||
| 2174 | } | ||
| 2175 | assert(struct_obj.haveLayout()); | ||
| 2176 | return AbiAlignmentAdvanced{ .scalar = struct_obj.backing_int_ty.abiAlignment(mod) }; | ||
| 2177 | } | ||
| 2178 | |||
| 2179 | const fields = ty.structFields(); | ||
| 2180 | var big_align: u32 = 0; | ||
| 2181 | for (fields.values()) |field| { | ||
| 2182 | if (!(field.ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { | ||
| 2183 | error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) }, | ||
| 2184 | else => |e| return e, | ||
| 2185 | })) continue; | ||
| 2186 | |||
| 2187 | const field_align = if (field.abi_align != 0) | ||
| 2188 | field.abi_align | ||
| 2189 | else switch (try field.ty.abiAlignmentAdvanced(mod, strat)) { | ||
| 2190 | .scalar => |a| a, | ||
| 2191 | .val => switch (strat) { | ||
| 2192 | .eager => unreachable, // struct layout not resolved | ||
| 2193 | .sema => unreachable, // handled above | ||
| 2194 | .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) }, | ||
| 2195 | }, | ||
| 2196 | }; | ||
| 2197 | big_align = @max(big_align, field_align); | ||
| 2198 | |||
| 2199 | // This logic is duplicated in Module.Struct.Field.alignment. | ||
| 2200 | if (struct_obj.layout == .Extern or target.ofmt == .c) { | ||
| 2201 | if (field.ty.isAbiInt(mod) and field.ty.intInfo(mod).bits >= 128) { | ||
| 2202 | // The C ABI requires 128 bit integer fields of structs | ||
| 2203 | // to be 16-bytes aligned. | ||
| 2204 | big_align = @max(big_align, 16); | ||
| 2205 | } | ||
| 2206 | } | ||
| 2207 | } | ||
| 2208 | return AbiAlignmentAdvanced{ .scalar = big_align }; | ||
| 2209 | }, | ||
| 2210 | |||
| 2211 | .tuple, .anon_struct => { | 2125 | .tuple, .anon_struct => { |
| 2212 | const tuple = ty.tupleFields(); | 2126 | const tuple = ty.tupleFields(); |
| 2213 | var big_align: u32 = 0; | 2127 | var big_align: u32 = 0; |
| ... | @@ -2241,8 +2155,6 @@ pub const Type = struct { | ... | @@ -2241,8 +2155,6 @@ pub const Type = struct { |
| 2241 | return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, true); | 2155 | return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, true); |
| 2242 | }, | 2156 | }, |
| 2243 | 2157 | ||
| 2244 | .empty_struct => return AbiAlignmentAdvanced{ .scalar = 0 }, | ||
| 2245 | |||
| 2246 | .inferred_alloc_const, | 2158 | .inferred_alloc_const, |
| 2247 | .inferred_alloc_mut, | 2159 | .inferred_alloc_mut, |
| 2248 | => unreachable, | 2160 | => unreachable, |
| ... | @@ -2337,7 +2249,69 @@ pub const Type = struct { | ... | @@ -2337,7 +2249,69 @@ pub const Type = struct { |
| 2337 | .generic_poison => unreachable, | 2249 | .generic_poison => unreachable, |
| 2338 | .var_args_param => unreachable, | 2250 | .var_args_param => unreachable, |
| 2339 | }, | 2251 | }, |
| 2340 | .struct_type => @panic("TODO"), | 2252 | .struct_type => |struct_type| { |
| 2253 | const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse | ||
| 2254 | return AbiAlignmentAdvanced{ .scalar = 0 }; | ||
| 2255 | |||
| 2256 | if (opt_sema) |sema| { | ||
| 2257 | if (struct_obj.status == .field_types_wip) { | ||
| 2258 | // We'll guess "pointer-aligned", if the struct has an | ||
| 2259 | // underaligned pointer field then some allocations | ||
| 2260 | // might require explicit alignment. | ||
| 2261 | return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }; | ||
| 2262 | } | ||
| 2263 | _ = try sema.resolveTypeFields(ty); | ||
| 2264 | } | ||
| 2265 | if (!struct_obj.haveFieldTypes()) switch (strat) { | ||
| 2266 | .eager => unreachable, // struct layout not resolved | ||
| 2267 | .sema => unreachable, // handled above | ||
| 2268 | .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) }, | ||
| 2269 | }; | ||
| 2270 | if (struct_obj.layout == .Packed) { | ||
| 2271 | switch (strat) { | ||
| 2272 | .sema => |sema| try sema.resolveTypeLayout(ty), | ||
| 2273 | .lazy => |arena| { | ||
| 2274 | if (!struct_obj.haveLayout()) { | ||
| 2275 | return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) }; | ||
| 2276 | } | ||
| 2277 | }, | ||
| 2278 | .eager => {}, | ||
| 2279 | } | ||
| 2280 | assert(struct_obj.haveLayout()); | ||
| 2281 | return AbiAlignmentAdvanced{ .scalar = struct_obj.backing_int_ty.abiAlignment(mod) }; | ||
| 2282 | } | ||
| 2283 | |||
| 2284 | const fields = ty.structFields(mod); | ||
| 2285 | var big_align: u32 = 0; | ||
| 2286 | for (fields.values()) |field| { | ||
| 2287 | if (!(field.ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { | ||
| 2288 | error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) }, | ||
| 2289 | else => |e| return e, | ||
| 2290 | })) continue; | ||
| 2291 | |||
| 2292 | const field_align = if (field.abi_align != 0) | ||
| 2293 | field.abi_align | ||
| 2294 | else switch (try field.ty.abiAlignmentAdvanced(mod, strat)) { | ||
| 2295 | .scalar => |a| a, | ||
| 2296 | .val => switch (strat) { | ||
| 2297 | .eager => unreachable, // struct layout not resolved | ||
| 2298 | .sema => unreachable, // handled above | ||
| 2299 | .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) }, | ||
| 2300 | }, | ||
| 2301 | }; | ||
| 2302 | big_align = @max(big_align, field_align); | ||
| 2303 | |||
| 2304 | // This logic is duplicated in Module.Struct.Field.alignment. | ||
| 2305 | if (struct_obj.layout == .Extern or target.ofmt == .c) { | ||
| 2306 | if (field.ty.isAbiInt(mod) and field.ty.intInfo(mod).bits >= 128) { | ||
| 2307 | // The C ABI requires 128 bit integer fields of structs | ||
| 2308 | // to be 16-bytes aligned. | ||
| 2309 | big_align = @max(big_align, 16); | ||
| 2310 | } | ||
| 2311 | } | ||
| 2312 | } | ||
| 2313 | return AbiAlignmentAdvanced{ .scalar = big_align }; | ||
| 2314 | }, | ||
| 2341 | .union_type => @panic("TODO"), | 2315 | .union_type => @panic("TODO"), |
| 2342 | .opaque_type => return AbiAlignmentAdvanced{ .scalar = 1 }, | 2316 | .opaque_type => return AbiAlignmentAdvanced{ .scalar = 1 }, |
| 2343 | 2317 | ||
| ... | @@ -2348,6 +2322,7 @@ pub const Type = struct { | ... | @@ -2348,6 +2322,7 @@ pub const Type = struct { |
| 2348 | .ptr => unreachable, | 2322 | .ptr => unreachable, |
| 2349 | .opt => unreachable, | 2323 | .opt => unreachable, |
| 2350 | .enum_tag => unreachable, | 2324 | .enum_tag => unreachable, |
| 2325 | .aggregate => unreachable, | ||
| 2351 | }, | 2326 | }, |
| 2352 | } | 2327 | } |
| 2353 | } | 2328 | } |
| ... | @@ -2517,42 +2492,16 @@ pub const Type = struct { | ... | @@ -2517,42 +2492,16 @@ pub const Type = struct { |
| 2517 | .inferred_alloc_const => unreachable, | 2492 | .inferred_alloc_const => unreachable, |
| 2518 | .inferred_alloc_mut => unreachable, | 2493 | .inferred_alloc_mut => unreachable, |
| 2519 | 2494 | ||
| 2520 | .empty_struct => return AbiSizeAdvanced{ .scalar = 0 }, | 2495 | .tuple, .anon_struct => { |
| 2521 | 2496 | switch (strat) { | |
| 2522 | .@"struct", .tuple, .anon_struct => switch (ty.containerLayout()) { | 2497 | .sema => |sema| try sema.resolveTypeLayout(ty), |
| 2523 | .Packed => { | 2498 | .lazy, .eager => {}, |
| 2524 | const struct_obj = ty.castTag(.@"struct").?.data; | 2499 | } |
| 2525 | switch (strat) { | 2500 | const field_count = ty.structFieldCount(mod); |
| 2526 | .sema => |sema| try sema.resolveTypeLayout(ty), | 2501 | if (field_count == 0) { |
| 2527 | .lazy => |arena| { | 2502 | return AbiSizeAdvanced{ .scalar = 0 }; |
| 2528 | if (!struct_obj.haveLayout()) { | 2503 | } |
| 2529 | return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) }; | 2504 | return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) }; |
| 2530 | } | ||
| 2531 | }, | ||
| 2532 | .eager => {}, | ||
| 2533 | } | ||
| 2534 | assert(struct_obj.haveLayout()); | ||
| 2535 | return AbiSizeAdvanced{ .scalar = struct_obj.backing_int_ty.abiSize(mod) }; | ||
| 2536 | }, | ||
| 2537 | else => { | ||
| 2538 | switch (strat) { | ||
| 2539 | .sema => |sema| try sema.resolveTypeLayout(ty), | ||
| 2540 | .lazy => |arena| { | ||
| 2541 | if (ty.castTag(.@"struct")) |payload| { | ||
| 2542 | const struct_obj = payload.data; | ||
| 2543 | if (!struct_obj.haveLayout()) { | ||
| 2544 | return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) }; | ||
| 2545 | } | ||
| 2546 | } | ||
| 2547 | }, | ||
| 2548 | .eager => {}, | ||
| 2549 | } | ||
| 2550 | const field_count = ty.structFieldCount(); | ||
| 2551 | if (field_count == 0) { | ||
| 2552 | return AbiSizeAdvanced{ .scalar = 0 }; | ||
| 2553 | } | ||
| 2554 | return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) }; | ||
| 2555 | }, | ||
| 2556 | }, | 2505 | }, |
| 2557 | 2506 | ||
| 2558 | .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => { | 2507 | .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => { |
| ... | @@ -2752,7 +2701,42 @@ pub const Type = struct { | ... | @@ -2752,7 +2701,42 @@ pub const Type = struct { |
| 2752 | .generic_poison => unreachable, | 2701 | .generic_poison => unreachable, |
| 2753 | .var_args_param => unreachable, | 2702 | .var_args_param => unreachable, |
| 2754 | }, | 2703 | }, |
| 2755 | .struct_type => @panic("TODO"), | 2704 | .struct_type => |struct_type| switch (ty.containerLayout(mod)) { |
| 2705 | .Packed => { | ||
| 2706 | const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse | ||
| 2707 | return AbiSizeAdvanced{ .scalar = 0 }; | ||
| 2708 | |||
| 2709 | switch (strat) { | ||
| 2710 | .sema => |sema| try sema.resolveTypeLayout(ty), | ||
| 2711 | .lazy => |arena| { | ||
| 2712 | if (!struct_obj.haveLayout()) { | ||
| 2713 | return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) }; | ||
| 2714 | } | ||
| 2715 | }, | ||
| 2716 | .eager => {}, | ||
| 2717 | } | ||
| 2718 | assert(struct_obj.haveLayout()); | ||
| 2719 | return AbiSizeAdvanced{ .scalar = struct_obj.backing_int_ty.abiSize(mod) }; | ||
| 2720 | }, | ||
| 2721 | else => { | ||
| 2722 | switch (strat) { | ||
| 2723 | .sema => |sema| try sema.resolveTypeLayout(ty), | ||
| 2724 | .lazy => |arena| { | ||
| 2725 | const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse | ||
| 2726 | return AbiSizeAdvanced{ .scalar = 0 }; | ||
| 2727 | if (!struct_obj.haveLayout()) { | ||
| 2728 | return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) }; | ||
| 2729 | } | ||
| 2730 | }, | ||
| 2731 | .eager => {}, | ||
| 2732 | } | ||
| 2733 | const field_count = ty.structFieldCount(mod); | ||
| 2734 | if (field_count == 0) { | ||
| 2735 | return AbiSizeAdvanced{ .scalar = 0 }; | ||
| 2736 | } | ||
| 2737 | return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) }; | ||
| 2738 | }, | ||
| 2739 | }, | ||
| 2756 | .union_type => @panic("TODO"), | 2740 | .union_type => @panic("TODO"), |
| 2757 | .opaque_type => unreachable, // no size available | 2741 | .opaque_type => unreachable, // no size available |
| 2758 | 2742 | ||
| ... | @@ -2763,6 +2747,7 @@ pub const Type = struct { | ... | @@ -2763,6 +2747,7 @@ pub const Type = struct { |
| 2763 | .ptr => unreachable, | 2747 | .ptr => unreachable, |
| 2764 | .opt => unreachable, | 2748 | .opt => unreachable, |
| 2765 | .enum_tag => unreachable, | 2749 | .enum_tag => unreachable, |
| 2750 | .aggregate => unreachable, | ||
| 2766 | }, | 2751 | }, |
| 2767 | } | 2752 | } |
| 2768 | } | 2753 | } |
| ... | @@ -2850,189 +2835,189 @@ pub const Type = struct { | ... | @@ -2850,189 +2835,189 @@ pub const Type = struct { |
| 2850 | ) Module.CompileError!u64 { | 2835 | ) Module.CompileError!u64 { |
| 2851 | const target = mod.getTarget(); | 2836 | const target = mod.getTarget(); |
| 2852 | 2837 | ||
| 2853 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 2854 | .int_type => |int_type| return int_type.bits, | ||
| 2855 | .ptr_type => |ptr_type| switch (ptr_type.size) { | ||
| 2856 | .Slice => return target.ptrBitWidth() * 2, | ||
| 2857 | else => return target.ptrBitWidth() * 2, | ||
| 2858 | }, | ||
| 2859 | .array_type => |array_type| { | ||
| 2860 | const len = array_type.len + @boolToInt(array_type.sentinel != .none); | ||
| 2861 | if (len == 0) return 0; | ||
| 2862 | const elem_ty = array_type.child.toType(); | ||
| 2863 | const elem_size = std.math.max(elem_ty.abiAlignment(mod), elem_ty.abiSize(mod)); | ||
| 2864 | if (elem_size == 0) return 0; | ||
| 2865 | const elem_bit_size = try bitSizeAdvanced(elem_ty, mod, opt_sema); | ||
| 2866 | return (len - 1) * 8 * elem_size + elem_bit_size; | ||
| 2867 | }, | ||
| 2868 | .vector_type => |vector_type| { | ||
| 2869 | const child_ty = vector_type.child.toType(); | ||
| 2870 | const elem_bit_size = try bitSizeAdvanced(child_ty, mod, opt_sema); | ||
| 2871 | return elem_bit_size * vector_type.len; | ||
| 2872 | }, | ||
| 2873 | .opt_type => @panic("TODO"), | ||
| 2874 | .error_union_type => @panic("TODO"), | ||
| 2875 | .simple_type => |t| switch (t) { | ||
| 2876 | .f16 => return 16, | ||
| 2877 | .f32 => return 32, | ||
| 2878 | .f64 => return 64, | ||
| 2879 | .f80 => return 80, | ||
| 2880 | .f128 => return 128, | ||
| 2881 | |||
| 2882 | .usize, | ||
| 2883 | .isize, | ||
| 2884 | .@"anyframe", | ||
| 2885 | => return target.ptrBitWidth(), | ||
| 2886 | |||
| 2887 | .c_char => return target.c_type_bit_size(.char), | ||
| 2888 | .c_short => return target.c_type_bit_size(.short), | ||
| 2889 | .c_ushort => return target.c_type_bit_size(.ushort), | ||
| 2890 | .c_int => return target.c_type_bit_size(.int), | ||
| 2891 | .c_uint => return target.c_type_bit_size(.uint), | ||
| 2892 | .c_long => return target.c_type_bit_size(.long), | ||
| 2893 | .c_ulong => return target.c_type_bit_size(.ulong), | ||
| 2894 | .c_longlong => return target.c_type_bit_size(.longlong), | ||
| 2895 | .c_ulonglong => return target.c_type_bit_size(.ulonglong), | ||
| 2896 | .c_longdouble => return target.c_type_bit_size(.longdouble), | ||
| 2897 | |||
| 2898 | .bool => return 1, | ||
| 2899 | .void => return 0, | ||
| 2900 | |||
| 2901 | // TODO revisit this when we have the concept of the error tag type | ||
| 2902 | .anyerror => return 16, | ||
| 2903 | |||
| 2904 | .anyopaque => unreachable, | ||
| 2905 | .type => unreachable, | ||
| 2906 | .comptime_int => unreachable, | ||
| 2907 | .comptime_float => unreachable, | ||
| 2908 | .noreturn => unreachable, | ||
| 2909 | .null => unreachable, | ||
| 2910 | .undefined => unreachable, | ||
| 2911 | .enum_literal => unreachable, | ||
| 2912 | .generic_poison => unreachable, | ||
| 2913 | .var_args_param => unreachable, | ||
| 2914 | |||
| 2915 | .atomic_order => unreachable, // missing call to resolveTypeFields | ||
| 2916 | .atomic_rmw_op => unreachable, // missing call to resolveTypeFields | ||
| 2917 | .calling_convention => unreachable, // missing call to resolveTypeFields | ||
| 2918 | .address_space => unreachable, // missing call to resolveTypeFields | ||
| 2919 | .float_mode => unreachable, // missing call to resolveTypeFields | ||
| 2920 | .reduce_op => unreachable, // missing call to resolveTypeFields | ||
| 2921 | .call_modifier => unreachable, // missing call to resolveTypeFields | ||
| 2922 | .prefetch_options => unreachable, // missing call to resolveTypeFields | ||
| 2923 | .export_options => unreachable, // missing call to resolveTypeFields | ||
| 2924 | .extern_options => unreachable, // missing call to resolveTypeFields | ||
| 2925 | .type_info => unreachable, // missing call to resolveTypeFields | ||
| 2926 | }, | ||
| 2927 | .struct_type => @panic("TODO"), | ||
| 2928 | .union_type => @panic("TODO"), | ||
| 2929 | .opaque_type => unreachable, | ||
| 2930 | |||
| 2931 | // values, not types | ||
| 2932 | .simple_value => unreachable, | ||
| 2933 | .extern_func => unreachable, | ||
| 2934 | .int => unreachable, | ||
| 2935 | .ptr => unreachable, | ||
| 2936 | .opt => unreachable, | ||
| 2937 | .enum_tag => unreachable, | ||
| 2938 | }; | ||
| 2939 | |||
| 2940 | const strat: AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager; | 2838 | const strat: AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager; |
| 2941 | 2839 | ||
| 2942 | switch (ty.tag()) { | 2840 | switch (ty.ip_index) { |
| 2943 | .function => unreachable, // represents machine code; not a pointer | 2841 | .none => switch (ty.tag()) { |
| 2944 | .empty_struct => unreachable, | 2842 | .function => unreachable, // represents machine code; not a pointer |
| 2945 | .inferred_alloc_const => unreachable, | 2843 | .inferred_alloc_const => unreachable, |
| 2946 | .inferred_alloc_mut => unreachable, | 2844 | .inferred_alloc_mut => unreachable, |
| 2947 | |||
| 2948 | .@"struct" => { | ||
| 2949 | const struct_obj = ty.castTag(.@"struct").?.data; | ||
| 2950 | if (struct_obj.layout != .Packed) { | ||
| 2951 | return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8; | ||
| 2952 | } | ||
| 2953 | if (opt_sema) |sema| _ = try sema.resolveTypeLayout(ty); | ||
| 2954 | assert(struct_obj.haveLayout()); | ||
| 2955 | return try struct_obj.backing_int_ty.bitSizeAdvanced(mod, opt_sema); | ||
| 2956 | }, | ||
| 2957 | |||
| 2958 | .tuple, .anon_struct => { | ||
| 2959 | if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty); | ||
| 2960 | if (ty.containerLayout() != .Packed) { | ||
| 2961 | return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8; | ||
| 2962 | } | ||
| 2963 | var total: u64 = 0; | ||
| 2964 | for (ty.tupleFields().types) |field_ty| { | ||
| 2965 | total += try bitSizeAdvanced(field_ty, mod, opt_sema); | ||
| 2966 | } | ||
| 2967 | return total; | ||
| 2968 | }, | ||
| 2969 | 2845 | ||
| 2970 | .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => { | 2846 | .tuple, .anon_struct => { |
| 2971 | const int_tag_ty = try ty.intTagType(mod); | 2847 | if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty); |
| 2972 | return try bitSizeAdvanced(int_tag_ty, mod, opt_sema); | 2848 | if (ty.containerLayout(mod) != .Packed) { |
| 2973 | }, | 2849 | return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8; |
| 2850 | } | ||
| 2851 | var total: u64 = 0; | ||
| 2852 | for (ty.tupleFields().types) |field_ty| { | ||
| 2853 | total += try bitSizeAdvanced(field_ty, mod, opt_sema); | ||
| 2854 | } | ||
| 2855 | return total; | ||
| 2856 | }, | ||
| 2974 | 2857 | ||
| 2975 | .@"union", .union_safety_tagged, .union_tagged => { | 2858 | .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => { |
| 2976 | if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty); | 2859 | const int_tag_ty = try ty.intTagType(mod); |
| 2977 | if (ty.containerLayout() != .Packed) { | 2860 | return try bitSizeAdvanced(int_tag_ty, mod, opt_sema); |
| 2978 | return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8; | 2861 | }, |
| 2979 | } | ||
| 2980 | const union_obj = ty.cast(Payload.Union).?.data; | ||
| 2981 | assert(union_obj.haveFieldTypes()); | ||
| 2982 | 2862 | ||
| 2983 | var size: u64 = 0; | 2863 | .@"union", .union_safety_tagged, .union_tagged => { |
| 2984 | for (union_obj.fields.values()) |field| { | 2864 | if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty); |
| 2985 | size = @max(size, try bitSizeAdvanced(field.ty, mod, opt_sema)); | 2865 | if (ty.containerLayout(mod) != .Packed) { |
| 2986 | } | 2866 | return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8; |
| 2987 | return size; | 2867 | } |
| 2988 | }, | 2868 | const union_obj = ty.cast(Payload.Union).?.data; |
| 2869 | assert(union_obj.haveFieldTypes()); | ||
| 2989 | 2870 | ||
| 2990 | .array => { | 2871 | var size: u64 = 0; |
| 2991 | const payload = ty.castTag(.array).?.data; | 2872 | for (union_obj.fields.values()) |field| { |
| 2992 | const elem_size = std.math.max(payload.elem_type.abiAlignment(mod), payload.elem_type.abiSize(mod)); | 2873 | size = @max(size, try bitSizeAdvanced(field.ty, mod, opt_sema)); |
| 2993 | if (elem_size == 0 or payload.len == 0) | 2874 | } |
| 2994 | return @as(u64, 0); | 2875 | return size; |
| 2995 | const elem_bit_size = try bitSizeAdvanced(payload.elem_type, mod, opt_sema); | 2876 | }, |
| 2996 | return (payload.len - 1) * 8 * elem_size + elem_bit_size; | 2877 | |
| 2997 | }, | 2878 | .array => { |
| 2998 | .array_sentinel => { | 2879 | const payload = ty.castTag(.array).?.data; |
| 2999 | const payload = ty.castTag(.array_sentinel).?.data; | 2880 | const elem_size = std.math.max(payload.elem_type.abiAlignment(mod), payload.elem_type.abiSize(mod)); |
| 3000 | const elem_size = std.math.max( | 2881 | if (elem_size == 0 or payload.len == 0) |
| 3001 | payload.elem_type.abiAlignment(mod), | 2882 | return @as(u64, 0); |
| 3002 | payload.elem_type.abiSize(mod), | 2883 | const elem_bit_size = try bitSizeAdvanced(payload.elem_type, mod, opt_sema); |
| 3003 | ); | 2884 | return (payload.len - 1) * 8 * elem_size + elem_bit_size; |
| 3004 | const elem_bit_size = try bitSizeAdvanced(payload.elem_type, mod, opt_sema); | 2885 | }, |
| 3005 | return payload.len * 8 * elem_size + elem_bit_size; | 2886 | .array_sentinel => { |
| 3006 | }, | 2887 | const payload = ty.castTag(.array_sentinel).?.data; |
| 2888 | const elem_size = std.math.max( | ||
| 2889 | payload.elem_type.abiAlignment(mod), | ||
| 2890 | payload.elem_type.abiSize(mod), | ||
| 2891 | ); | ||
| 2892 | const elem_bit_size = try bitSizeAdvanced(payload.elem_type, mod, opt_sema); | ||
| 2893 | return payload.len * 8 * elem_size + elem_bit_size; | ||
| 2894 | }, | ||
| 3007 | 2895 | ||
| 3008 | .anyframe_T => return target.ptrBitWidth(), | 2896 | .anyframe_T => return target.ptrBitWidth(), |
| 3009 | 2897 | ||
| 3010 | .pointer => switch (ty.castTag(.pointer).?.data.size) { | 2898 | .pointer => switch (ty.castTag(.pointer).?.data.size) { |
| 3011 | .Slice => return target.ptrBitWidth() * 2, | 2899 | .Slice => return target.ptrBitWidth() * 2, |
| 3012 | else => return target.ptrBitWidth(), | 2900 | else => return target.ptrBitWidth(), |
| 2901 | }, | ||
| 2902 | |||
| 2903 | .error_set, | ||
| 2904 | .error_set_single, | ||
| 2905 | .error_set_inferred, | ||
| 2906 | .error_set_merged, | ||
| 2907 | => return 16, // TODO revisit this when we have the concept of the error tag type | ||
| 2908 | |||
| 2909 | .optional, .error_union => { | ||
| 2910 | // Optionals and error unions are not packed so their bitsize | ||
| 2911 | // includes padding bits. | ||
| 2912 | return (try abiSizeAdvanced(ty, mod, strat)).scalar * 8; | ||
| 2913 | }, | ||
| 3013 | }, | 2914 | }, |
| 2915 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 2916 | .int_type => |int_type| return int_type.bits, | ||
| 2917 | .ptr_type => |ptr_type| switch (ptr_type.size) { | ||
| 2918 | .Slice => return target.ptrBitWidth() * 2, | ||
| 2919 | else => return target.ptrBitWidth() * 2, | ||
| 2920 | }, | ||
| 2921 | .array_type => |array_type| { | ||
| 2922 | const len = array_type.len + @boolToInt(array_type.sentinel != .none); | ||
| 2923 | if (len == 0) return 0; | ||
| 2924 | const elem_ty = array_type.child.toType(); | ||
| 2925 | const elem_size = std.math.max(elem_ty.abiAlignment(mod), elem_ty.abiSize(mod)); | ||
| 2926 | if (elem_size == 0) return 0; | ||
| 2927 | const elem_bit_size = try bitSizeAdvanced(elem_ty, mod, opt_sema); | ||
| 2928 | return (len - 1) * 8 * elem_size + elem_bit_size; | ||
| 2929 | }, | ||
| 2930 | .vector_type => |vector_type| { | ||
| 2931 | const child_ty = vector_type.child.toType(); | ||
| 2932 | const elem_bit_size = try bitSizeAdvanced(child_ty, mod, opt_sema); | ||
| 2933 | return elem_bit_size * vector_type.len; | ||
| 2934 | }, | ||
| 2935 | .opt_type => @panic("TODO"), | ||
| 2936 | .error_union_type => @panic("TODO"), | ||
| 2937 | .simple_type => |t| switch (t) { | ||
| 2938 | .f16 => return 16, | ||
| 2939 | .f32 => return 32, | ||
| 2940 | .f64 => return 64, | ||
| 2941 | .f80 => return 80, | ||
| 2942 | .f128 => return 128, | ||
| 3014 | 2943 | ||
| 3015 | .error_set, | 2944 | .usize, |
| 3016 | .error_set_single, | 2945 | .isize, |
| 3017 | .error_set_inferred, | 2946 | .@"anyframe", |
| 3018 | .error_set_merged, | 2947 | => return target.ptrBitWidth(), |
| 3019 | => return 16, // TODO revisit this when we have the concept of the error tag type | 2948 | |
| 2949 | .c_char => return target.c_type_bit_size(.char), | ||
| 2950 | .c_short => return target.c_type_bit_size(.short), | ||
| 2951 | .c_ushort => return target.c_type_bit_size(.ushort), | ||
| 2952 | .c_int => return target.c_type_bit_size(.int), | ||
| 2953 | .c_uint => return target.c_type_bit_size(.uint), | ||
| 2954 | .c_long => return target.c_type_bit_size(.long), | ||
| 2955 | .c_ulong => return target.c_type_bit_size(.ulong), | ||
| 2956 | .c_longlong => return target.c_type_bit_size(.longlong), | ||
| 2957 | .c_ulonglong => return target.c_type_bit_size(.ulonglong), | ||
| 2958 | .c_longdouble => return target.c_type_bit_size(.longdouble), | ||
| 2959 | |||
| 2960 | .bool => return 1, | ||
| 2961 | .void => return 0, | ||
| 2962 | |||
| 2963 | // TODO revisit this when we have the concept of the error tag type | ||
| 2964 | .anyerror => return 16, | ||
| 2965 | |||
| 2966 | .anyopaque => unreachable, | ||
| 2967 | .type => unreachable, | ||
| 2968 | .comptime_int => unreachable, | ||
| 2969 | .comptime_float => unreachable, | ||
| 2970 | .noreturn => unreachable, | ||
| 2971 | .null => unreachable, | ||
| 2972 | .undefined => unreachable, | ||
| 2973 | .enum_literal => unreachable, | ||
| 2974 | .generic_poison => unreachable, | ||
| 2975 | .var_args_param => unreachable, | ||
| 2976 | |||
| 2977 | .atomic_order => unreachable, // missing call to resolveTypeFields | ||
| 2978 | .atomic_rmw_op => unreachable, // missing call to resolveTypeFields | ||
| 2979 | .calling_convention => unreachable, // missing call to resolveTypeFields | ||
| 2980 | .address_space => unreachable, // missing call to resolveTypeFields | ||
| 2981 | .float_mode => unreachable, // missing call to resolveTypeFields | ||
| 2982 | .reduce_op => unreachable, // missing call to resolveTypeFields | ||
| 2983 | .call_modifier => unreachable, // missing call to resolveTypeFields | ||
| 2984 | .prefetch_options => unreachable, // missing call to resolveTypeFields | ||
| 2985 | .export_options => unreachable, // missing call to resolveTypeFields | ||
| 2986 | .extern_options => unreachable, // missing call to resolveTypeFields | ||
| 2987 | .type_info => unreachable, // missing call to resolveTypeFields | ||
| 2988 | }, | ||
| 2989 | .struct_type => |struct_type| { | ||
| 2990 | const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return 0; | ||
| 2991 | if (struct_obj.layout != .Packed) { | ||
| 2992 | return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8; | ||
| 2993 | } | ||
| 2994 | if (opt_sema) |sema| _ = try sema.resolveTypeLayout(ty); | ||
| 2995 | assert(struct_obj.haveLayout()); | ||
| 2996 | return try struct_obj.backing_int_ty.bitSizeAdvanced(mod, opt_sema); | ||
| 2997 | }, | ||
| 2998 | |||
| 2999 | .union_type => @panic("TODO"), | ||
| 3000 | .opaque_type => unreachable, | ||
| 3020 | 3001 | ||
| 3021 | .optional, .error_union => { | 3002 | // values, not types |
| 3022 | // Optionals and error unions are not packed so their bitsize | 3003 | .simple_value => unreachable, |
| 3023 | // includes padding bits. | 3004 | .extern_func => unreachable, |
| 3024 | return (try abiSizeAdvanced(ty, mod, strat)).scalar * 8; | 3005 | .int => unreachable, |
| 3006 | .ptr => unreachable, | ||
| 3007 | .opt => unreachable, | ||
| 3008 | .enum_tag => unreachable, | ||
| 3009 | .aggregate => unreachable, | ||
| 3025 | }, | 3010 | }, |
| 3026 | } | 3011 | } |
| 3027 | } | 3012 | } |
| 3028 | 3013 | ||
| 3029 | /// Returns true if the type's layout is already resolved and it is safe | 3014 | /// Returns true if the type's layout is already resolved and it is safe |
| 3030 | /// to use `abiSize`, `abiAlignment` and `bitSize` on it. | 3015 | /// to use `abiSize`, `abiAlignment` and `bitSize` on it. |
| 3031 | pub fn layoutIsResolved(ty: Type, mod: *const Module) bool { | 3016 | pub fn layoutIsResolved(ty: Type, mod: *Module) bool { |
| 3032 | switch (ty.zigTypeTag(mod)) { | 3017 | switch (ty.zigTypeTag(mod)) { |
| 3033 | .Struct => { | 3018 | .Struct => { |
| 3034 | if (ty.castTag(.@"struct")) |struct_ty| { | 3019 | if (mod.typeToStruct(ty)) |struct_obj| { |
| 3035 | return struct_ty.data.haveLayout(); | 3020 | return struct_obj.haveLayout(); |
| 3036 | } | 3021 | } |
| 3037 | return true; | 3022 | return true; |
| 3038 | }, | 3023 | }, |
| ... | @@ -3500,18 +3485,23 @@ pub const Type = struct { | ... | @@ -3500,18 +3485,23 @@ pub const Type = struct { |
| 3500 | } | 3485 | } |
| 3501 | } | 3486 | } |
| 3502 | 3487 | ||
| 3503 | pub fn containerLayout(ty: Type) std.builtin.Type.ContainerLayout { | 3488 | pub fn containerLayout(ty: Type, mod: *Module) std.builtin.Type.ContainerLayout { |
| 3504 | return switch (ty.ip_index) { | 3489 | return switch (ty.ip_index) { |
| 3505 | .empty_struct_type => .Auto, | 3490 | .empty_struct_type => .Auto, |
| 3506 | .none => switch (ty.tag()) { | 3491 | .none => switch (ty.tag()) { |
| 3507 | .tuple, .anon_struct => .Auto, | 3492 | .tuple, .anon_struct => .Auto, |
| 3508 | .@"struct" => ty.castTag(.@"struct").?.data.layout, | ||
| 3509 | .@"union" => ty.castTag(.@"union").?.data.layout, | 3493 | .@"union" => ty.castTag(.@"union").?.data.layout, |
| 3510 | .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.layout, | 3494 | .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.layout, |
| 3511 | .union_tagged => ty.castTag(.union_tagged).?.data.layout, | 3495 | .union_tagged => ty.castTag(.union_tagged).?.data.layout, |
| 3512 | else => unreachable, | 3496 | else => unreachable, |
| 3513 | }, | 3497 | }, |
| 3514 | else => unreachable, | 3498 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 3499 | .struct_type => |struct_type| { | ||
| 3500 | const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return .Auto; | ||
| 3501 | return struct_obj.layout; | ||
| 3502 | }, | ||
| 3503 | else => unreachable, | ||
| 3504 | }, | ||
| 3515 | }; | 3505 | }; |
| 3516 | } | 3506 | } |
| 3517 | 3507 | ||
| ... | @@ -3631,14 +3621,16 @@ pub const Type = struct { | ... | @@ -3631,14 +3621,16 @@ pub const Type = struct { |
| 3631 | .array_sentinel => ty.castTag(.array_sentinel).?.data.len, | 3621 | .array_sentinel => ty.castTag(.array_sentinel).?.data.len, |
| 3632 | .tuple => ty.castTag(.tuple).?.data.types.len, | 3622 | .tuple => ty.castTag(.tuple).?.data.types.len, |
| 3633 | .anon_struct => ty.castTag(.anon_struct).?.data.types.len, | 3623 | .anon_struct => ty.castTag(.anon_struct).?.data.types.len, |
| 3634 | .@"struct" => ty.castTag(.@"struct").?.data.fields.count(), | ||
| 3635 | .empty_struct => 0, | ||
| 3636 | 3624 | ||
| 3637 | else => unreachable, | 3625 | else => unreachable, |
| 3638 | }, | 3626 | }, |
| 3639 | else => switch (ip.indexToKey(ty.ip_index)) { | 3627 | else => switch (ip.indexToKey(ty.ip_index)) { |
| 3640 | .vector_type => |vector_type| vector_type.len, | 3628 | .vector_type => |vector_type| vector_type.len, |
| 3641 | .array_type => |array_type| array_type.len, | 3629 | .array_type => |array_type| array_type.len, |
| 3630 | .struct_type => |struct_type| { | ||
| 3631 | const struct_obj = ip.structPtrUnwrapConst(struct_type.index) orelse return 0; | ||
| 3632 | return struct_obj.fields.count(); | ||
| 3633 | }, | ||
| 3642 | else => unreachable, | 3634 | else => unreachable, |
| 3643 | }, | 3635 | }, |
| 3644 | }; | 3636 | }; |
| ... | @@ -3665,11 +3657,9 @@ pub const Type = struct { | ... | @@ -3665,11 +3657,9 @@ pub const Type = struct { |
| 3665 | /// Asserts the type is an array, pointer or vector. | 3657 | /// Asserts the type is an array, pointer or vector. |
| 3666 | pub fn sentinel(ty: Type, mod: *const Module) ?Value { | 3658 | pub fn sentinel(ty: Type, mod: *const Module) ?Value { |
| 3667 | return switch (ty.ip_index) { | 3659 | return switch (ty.ip_index) { |
| 3668 | .empty_struct_type => null, | ||
| 3669 | .none => switch (ty.tag()) { | 3660 | .none => switch (ty.tag()) { |
| 3670 | .array, | 3661 | .array, |
| 3671 | .tuple, | 3662 | .tuple, |
| 3672 | .@"struct", | ||
| 3673 | => null, | 3663 | => null, |
| 3674 | 3664 | ||
| 3675 | .pointer => ty.castTag(.pointer).?.data.sentinel, | 3665 | .pointer => ty.castTag(.pointer).?.data.sentinel, |
| ... | @@ -3721,16 +3711,16 @@ pub const Type = struct { | ... | @@ -3721,16 +3711,16 @@ pub const Type = struct { |
| 3721 | 3711 | ||
| 3722 | /// Returns true for integers, enums, error sets, and packed structs. | 3712 | /// Returns true for integers, enums, error sets, and packed structs. |
| 3723 | /// If this function returns true, then intInfo() can be called on the type. | 3713 | /// If this function returns true, then intInfo() can be called on the type. |
| 3724 | pub fn isAbiInt(ty: Type, mod: *const Module) bool { | 3714 | pub fn isAbiInt(ty: Type, mod: *Module) bool { |
| 3725 | return switch (ty.zigTypeTag(mod)) { | 3715 | return switch (ty.zigTypeTag(mod)) { |
| 3726 | .Int, .Enum, .ErrorSet => true, | 3716 | .Int, .Enum, .ErrorSet => true, |
| 3727 | .Struct => ty.containerLayout() == .Packed, | 3717 | .Struct => ty.containerLayout(mod) == .Packed, |
| 3728 | else => false, | 3718 | else => false, |
| 3729 | }; | 3719 | }; |
| 3730 | } | 3720 | } |
| 3731 | 3721 | ||
| 3732 | /// Asserts the type is an integer, enum, error set, or vector of one of them. | 3722 | /// Asserts the type is an integer, enum, error set, or vector of one of them. |
| 3733 | pub fn intInfo(starting_ty: Type, mod: *const Module) InternPool.Key.IntType { | 3723 | pub fn intInfo(starting_ty: Type, mod: *Module) InternPool.Key.IntType { |
| 3734 | const target = mod.getTarget(); | 3724 | const target = mod.getTarget(); |
| 3735 | var ty = starting_ty; | 3725 | var ty = starting_ty; |
| 3736 | 3726 | ||
| ... | @@ -3750,12 +3740,6 @@ pub const Type = struct { | ... | @@ -3750,12 +3740,6 @@ pub const Type = struct { |
| 3750 | return .{ .signedness = .unsigned, .bits = 16 }; | 3740 | return .{ .signedness = .unsigned, .bits = 16 }; |
| 3751 | }, | 3741 | }, |
| 3752 | 3742 | ||
| 3753 | .@"struct" => { | ||
| 3754 | const struct_obj = ty.castTag(.@"struct").?.data; | ||
| 3755 | assert(struct_obj.layout == .Packed); | ||
| 3756 | ty = struct_obj.backing_int_ty; | ||
| 3757 | }, | ||
| 3758 | |||
| 3759 | else => unreachable, | 3743 | else => unreachable, |
| 3760 | }, | 3744 | }, |
| 3761 | .anyerror_type => { | 3745 | .anyerror_type => { |
| ... | @@ -3775,6 +3759,12 @@ pub const Type = struct { | ... | @@ -3775,6 +3759,12 @@ pub const Type = struct { |
| 3775 | .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulonglong) }, | 3759 | .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulonglong) }, |
| 3776 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { | 3760 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 3777 | .int_type => |int_type| return int_type, | 3761 | .int_type => |int_type| return int_type, |
| 3762 | .struct_type => |struct_type| { | ||
| 3763 | const struct_obj = mod.structPtrUnwrap(struct_type.index).?; | ||
| 3764 | assert(struct_obj.layout == .Packed); | ||
| 3765 | ty = struct_obj.backing_int_ty; | ||
| 3766 | }, | ||
| 3767 | |||
| 3778 | .ptr_type => unreachable, | 3768 | .ptr_type => unreachable, |
| 3779 | .array_type => unreachable, | 3769 | .array_type => unreachable, |
| 3780 | .vector_type => |vector_type| ty = vector_type.child.toType(), | 3770 | .vector_type => |vector_type| ty = vector_type.child.toType(), |
| ... | @@ -3782,7 +3772,7 @@ pub const Type = struct { | ... | @@ -3782,7 +3772,7 @@ pub const Type = struct { |
| 3782 | .opt_type => unreachable, | 3772 | .opt_type => unreachable, |
| 3783 | .error_union_type => unreachable, | 3773 | .error_union_type => unreachable, |
| 3784 | .simple_type => unreachable, // handled via Index enum tag above | 3774 | .simple_type => unreachable, // handled via Index enum tag above |
| 3785 | .struct_type => @panic("TODO"), | 3775 | |
| 3786 | .union_type => unreachable, | 3776 | .union_type => unreachable, |
| 3787 | .opaque_type => unreachable, | 3777 | .opaque_type => unreachable, |
| 3788 | 3778 | ||
| ... | @@ -3793,6 +3783,7 @@ pub const Type = struct { | ... | @@ -3793,6 +3783,7 @@ pub const Type = struct { |
| 3793 | .ptr => unreachable, | 3783 | .ptr => unreachable, |
| 3794 | .opt => unreachable, | 3784 | .opt => unreachable, |
| 3795 | .enum_tag => unreachable, | 3785 | .enum_tag => unreachable, |
| 3786 | .aggregate => unreachable, | ||
| 3796 | }, | 3787 | }, |
| 3797 | }; | 3788 | }; |
| 3798 | } | 3789 | } |
| ... | @@ -3996,17 +3987,6 @@ pub const Type = struct { | ... | @@ -3996,17 +3987,6 @@ pub const Type = struct { |
| 3996 | } | 3987 | } |
| 3997 | }, | 3988 | }, |
| 3998 | 3989 | ||
| 3999 | .@"struct" => { | ||
| 4000 | const s = ty.castTag(.@"struct").?.data; | ||
| 4001 | assert(s.haveFieldTypes()); | ||
| 4002 | for (s.fields.values()) |field| { | ||
| 4003 | if (field.is_comptime) continue; | ||
| 4004 | if ((try field.ty.onePossibleValue(mod)) != null) continue; | ||
| 4005 | return null; | ||
| 4006 | } | ||
| 4007 | return Value.empty_struct; | ||
| 4008 | }, | ||
| 4009 | |||
| 4010 | .tuple, .anon_struct => { | 3990 | .tuple, .anon_struct => { |
| 4011 | const tuple = ty.tupleFields(); | 3991 | const tuple = ty.tupleFields(); |
| 4012 | for (tuple.values, 0..) |val, i| { | 3992 | for (tuple.values, 0..) |val, i| { |
| ... | @@ -4069,8 +4049,6 @@ pub const Type = struct { | ... | @@ -4069,8 +4049,6 @@ pub const Type = struct { |
| 4069 | return Value.empty_struct; | 4049 | return Value.empty_struct; |
| 4070 | }, | 4050 | }, |
| 4071 | 4051 | ||
| 4072 | .empty_struct => return Value.empty_struct, | ||
| 4073 | |||
| 4074 | .array => { | 4052 | .array => { |
| 4075 | if (ty.arrayLen(mod) == 0) | 4053 | if (ty.arrayLen(mod) == 0) |
| 4076 | return Value.initTag(.empty_array); | 4054 | return Value.initTag(.empty_array); |
| ... | @@ -4158,7 +4136,23 @@ pub const Type = struct { | ... | @@ -4158,7 +4136,23 @@ pub const Type = struct { |
| 4158 | .generic_poison => unreachable, | 4136 | .generic_poison => unreachable, |
| 4159 | .var_args_param => unreachable, | 4137 | .var_args_param => unreachable, |
| 4160 | }, | 4138 | }, |
| 4161 | .struct_type => @panic("TODO"), | 4139 | .struct_type => |struct_type| { |
| 4140 | if (mod.structPtrUnwrap(struct_type.index)) |s| { | ||
| 4141 | assert(s.haveFieldTypes()); | ||
| 4142 | for (s.fields.values()) |field| { | ||
| 4143 | if (field.is_comptime) continue; | ||
| 4144 | if ((try field.ty.onePossibleValue(mod)) != null) continue; | ||
| 4145 | return null; | ||
| 4146 | } | ||
| 4147 | } | ||
| 4148 | // In this case the struct has no fields and therefore has one possible value. | ||
| 4149 | const empty = try mod.intern(.{ .aggregate = .{ | ||
| 4150 | .ty = ty.ip_index, | ||
| 4151 | .fields = &.{}, | ||
| 4152 | } }); | ||
| 4153 | return empty.toValue(); | ||
| 4154 | }, | ||
| 4155 | |||
| 4162 | .union_type => @panic("TODO"), | 4156 | .union_type => @panic("TODO"), |
| 4163 | .opaque_type => return null, | 4157 | .opaque_type => return null, |
| 4164 | 4158 | ||
| ... | @@ -4169,6 +4163,7 @@ pub const Type = struct { | ... | @@ -4169,6 +4163,7 @@ pub const Type = struct { |
| 4169 | .ptr => unreachable, | 4163 | .ptr => unreachable, |
| 4170 | .opt => unreachable, | 4164 | .opt => unreachable, |
| 4171 | .enum_tag => unreachable, | 4165 | .enum_tag => unreachable, |
| 4166 | .aggregate => unreachable, | ||
| 4172 | }, | 4167 | }, |
| 4173 | }; | 4168 | }; |
| 4174 | } | 4169 | } |
| ... | @@ -4177,12 +4172,11 @@ pub const Type = struct { | ... | @@ -4177,12 +4172,11 @@ pub const Type = struct { |
| 4177 | /// resolves field types rather than asserting they are already resolved. | 4172 | /// resolves field types rather than asserting they are already resolved. |
| 4178 | /// TODO merge these implementations together with the "advanced" pattern seen | 4173 | /// TODO merge these implementations together with the "advanced" pattern seen |
| 4179 | /// elsewhere in this file. | 4174 | /// elsewhere in this file. |
| 4180 | pub fn comptimeOnly(ty: Type, mod: *const Module) bool { | 4175 | pub fn comptimeOnly(ty: Type, mod: *Module) bool { |
| 4181 | return switch (ty.ip_index) { | 4176 | return switch (ty.ip_index) { |
| 4182 | .empty_struct_type => false, | 4177 | .empty_struct_type => false, |
| 4183 | 4178 | ||
| 4184 | .none => switch (ty.tag()) { | 4179 | .none => switch (ty.tag()) { |
| 4185 | .empty_struct, | ||
| 4186 | .error_set, | 4180 | .error_set, |
| 4187 | .error_set_single, | 4181 | .error_set_single, |
| 4188 | .error_set_inferred, | 4182 | .error_set_inferred, |
| ... | @@ -4222,20 +4216,6 @@ pub const Type = struct { | ... | @@ -4222,20 +4216,6 @@ pub const Type = struct { |
| 4222 | return false; | 4216 | return false; |
| 4223 | }, | 4217 | }, |
| 4224 | 4218 | ||
| 4225 | .@"struct" => { | ||
| 4226 | const struct_obj = ty.castTag(.@"struct").?.data; | ||
| 4227 | switch (struct_obj.requires_comptime) { | ||
| 4228 | .wip, .unknown => { | ||
| 4229 | // Return false to avoid incorrect dependency loops. | ||
| 4230 | // This will be handled correctly once merged with | ||
| 4231 | // `Sema.typeRequiresComptime`. | ||
| 4232 | return false; | ||
| 4233 | }, | ||
| 4234 | .no => return false, | ||
| 4235 | .yes => return true, | ||
| 4236 | } | ||
| 4237 | }, | ||
| 4238 | |||
| 4239 | .@"union", .union_safety_tagged, .union_tagged => { | 4219 | .@"union", .union_safety_tagged, .union_tagged => { |
| 4240 | const union_obj = ty.cast(Type.Payload.Union).?.data; | 4220 | const union_obj = ty.cast(Type.Payload.Union).?.data; |
| 4241 | switch (union_obj.requires_comptime) { | 4221 | switch (union_obj.requires_comptime) { |
| ... | @@ -4326,7 +4306,21 @@ pub const Type = struct { | ... | @@ -4326,7 +4306,21 @@ pub const Type = struct { |
| 4326 | 4306 | ||
| 4327 | .var_args_param => unreachable, | 4307 | .var_args_param => unreachable, |
| 4328 | }, | 4308 | }, |
| 4329 | .struct_type => @panic("TODO"), | 4309 | .struct_type => |struct_type| { |
| 4310 | // A struct with no fields is not comptime-only. | ||
| 4311 | const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false; | ||
| 4312 | switch (struct_obj.requires_comptime) { | ||
| 4313 | .wip, .unknown => { | ||
| 4314 | // Return false to avoid incorrect dependency loops. | ||
| 4315 | // This will be handled correctly once merged with | ||
| 4316 | // `Sema.typeRequiresComptime`. | ||
| 4317 | return false; | ||
| 4318 | }, | ||
| 4319 | .no => return false, | ||
| 4320 | .yes => return true, | ||
| 4321 | } | ||
| 4322 | }, | ||
| 4323 | |||
| 4330 | .union_type => @panic("TODO"), | 4324 | .union_type => @panic("TODO"), |
| 4331 | .opaque_type => false, | 4325 | .opaque_type => false, |
| 4332 | 4326 | ||
| ... | @@ -4337,6 +4331,7 @@ pub const Type = struct { | ... | @@ -4337,6 +4331,7 @@ pub const Type = struct { |
| 4337 | .ptr => unreachable, | 4331 | .ptr => unreachable, |
| 4338 | .opt => unreachable, | 4332 | .opt => unreachable, |
| 4339 | .enum_tag => unreachable, | 4333 | .enum_tag => unreachable, |
| 4334 | .aggregate => unreachable, | ||
| 4340 | }, | 4335 | }, |
| 4341 | }; | 4336 | }; |
| 4342 | } | 4337 | } |
| ... | @@ -4352,19 +4347,19 @@ pub const Type = struct { | ... | @@ -4352,19 +4347,19 @@ pub const Type = struct { |
| 4352 | }; | 4347 | }; |
| 4353 | } | 4348 | } |
| 4354 | 4349 | ||
| 4355 | pub fn isIndexable(ty: Type, mod: *const Module) bool { | 4350 | pub fn isIndexable(ty: Type, mod: *Module) bool { |
| 4356 | return switch (ty.zigTypeTag(mod)) { | 4351 | return switch (ty.zigTypeTag(mod)) { |
| 4357 | .Array, .Vector => true, | 4352 | .Array, .Vector => true, |
| 4358 | .Pointer => switch (ty.ptrSize(mod)) { | 4353 | .Pointer => switch (ty.ptrSize(mod)) { |
| 4359 | .Slice, .Many, .C => true, | 4354 | .Slice, .Many, .C => true, |
| 4360 | .One => ty.childType(mod).zigTypeTag(mod) == .Array, | 4355 | .One => ty.childType(mod).zigTypeTag(mod) == .Array, |
| 4361 | }, | 4356 | }, |
| 4362 | .Struct => ty.isTuple(), | 4357 | .Struct => ty.isTuple(mod), |
| 4363 | else => false, | 4358 | else => false, |
| 4364 | }; | 4359 | }; |
| 4365 | } | 4360 | } |
| 4366 | 4361 | ||
| 4367 | pub fn indexableHasLen(ty: Type, mod: *const Module) bool { | 4362 | pub fn indexableHasLen(ty: Type, mod: *Module) bool { |
| 4368 | return switch (ty.zigTypeTag(mod)) { | 4363 | return switch (ty.zigTypeTag(mod)) { |
| 4369 | .Array, .Vector => true, | 4364 | .Array, .Vector => true, |
| 4370 | .Pointer => switch (ty.ptrSize(mod)) { | 4365 | .Pointer => switch (ty.ptrSize(mod)) { |
| ... | @@ -4372,7 +4367,7 @@ pub const Type = struct { | ... | @@ -4372,7 +4367,7 @@ pub const Type = struct { |
| 4372 | .Slice => true, | 4367 | .Slice => true, |
| 4373 | .One => ty.childType(mod).zigTypeTag(mod) == .Array, | 4368 | .One => ty.childType(mod).zigTypeTag(mod) == .Array, |
| 4374 | }, | 4369 | }, |
| 4375 | .Struct => ty.isTuple(), | 4370 | .Struct => ty.isTuple(mod), |
| 4376 | else => false, | 4371 | else => false, |
| 4377 | }; | 4372 | }; |
| 4378 | } | 4373 | } |
| ... | @@ -4381,10 +4376,8 @@ pub const Type = struct { | ... | @@ -4381,10 +4376,8 @@ pub const Type = struct { |
| 4381 | pub fn getNamespaceIndex(ty: Type, mod: *Module) Module.Namespace.OptionalIndex { | 4376 | pub fn getNamespaceIndex(ty: Type, mod: *Module) Module.Namespace.OptionalIndex { |
| 4382 | return switch (ty.ip_index) { | 4377 | return switch (ty.ip_index) { |
| 4383 | .none => switch (ty.tag()) { | 4378 | .none => switch (ty.tag()) { |
| 4384 | .@"struct" => ty.castTag(.@"struct").?.data.namespace.toOptional(), | ||
| 4385 | .enum_full => ty.castTag(.enum_full).?.data.namespace.toOptional(), | 4379 | .enum_full => ty.castTag(.enum_full).?.data.namespace.toOptional(), |
| 4386 | .enum_nonexhaustive => ty.castTag(.enum_nonexhaustive).?.data.namespace.toOptional(), | 4380 | .enum_nonexhaustive => ty.castTag(.enum_nonexhaustive).?.data.namespace.toOptional(), |
| 4387 | .empty_struct => @panic("TODO"), | ||
| 4388 | .@"union" => ty.castTag(.@"union").?.data.namespace.toOptional(), | 4381 | .@"union" => ty.castTag(.@"union").?.data.namespace.toOptional(), |
| 4389 | .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.namespace.toOptional(), | 4382 | .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.namespace.toOptional(), |
| 4390 | .union_tagged => ty.castTag(.union_tagged).?.data.namespace.toOptional(), | 4383 | .union_tagged => ty.castTag(.union_tagged).?.data.namespace.toOptional(), |
| ... | @@ -4393,6 +4386,7 @@ pub const Type = struct { | ... | @@ -4393,6 +4386,7 @@ pub const Type = struct { |
| 4393 | }, | 4386 | }, |
| 4394 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { | 4387 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 4395 | .opaque_type => |opaque_type| opaque_type.namespace.toOptional(), | 4388 | .opaque_type => |opaque_type| opaque_type.namespace.toOptional(), |
| 4389 | .struct_type => |struct_type| struct_type.namespace, | ||
| 4396 | else => .none, | 4390 | else => .none, |
| 4397 | }, | 4391 | }, |
| 4398 | }; | 4392 | }; |
| ... | @@ -4618,161 +4612,188 @@ pub const Type = struct { | ... | @@ -4618,161 +4612,188 @@ pub const Type = struct { |
| 4618 | } | 4612 | } |
| 4619 | } | 4613 | } |
| 4620 | 4614 | ||
| 4621 | pub fn structFields(ty: Type) Module.Struct.Fields { | 4615 | pub fn structFields(ty: Type, mod: *Module) Module.Struct.Fields { |
| 4622 | return switch (ty.ip_index) { | 4616 | switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 4623 | .empty_struct_type => .{}, | 4617 | .struct_type => |struct_type| { |
| 4624 | .none => switch (ty.tag()) { | 4618 | const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return .{}; |
| 4625 | .empty_struct => .{}, | 4619 | assert(struct_obj.haveFieldTypes()); |
| 4626 | .@"struct" => { | 4620 | return struct_obj.fields; |
| 4627 | const struct_obj = ty.castTag(.@"struct").?.data; | ||
| 4628 | assert(struct_obj.haveFieldTypes()); | ||
| 4629 | return struct_obj.fields; | ||
| 4630 | }, | ||
| 4631 | else => unreachable, | ||
| 4632 | }, | 4621 | }, |
| 4633 | else => unreachable, | 4622 | else => unreachable, |
| 4634 | }; | 4623 | } |
| 4635 | } | 4624 | } |
| 4636 | 4625 | ||
| 4637 | pub fn structFieldName(ty: Type, field_index: usize) []const u8 { | 4626 | pub fn structFieldName(ty: Type, field_index: usize, mod: *Module) []const u8 { |
| 4638 | switch (ty.tag()) { | 4627 | switch (ty.ip_index) { |
| 4639 | .@"struct" => { | 4628 | .none => switch (ty.tag()) { |
| 4640 | const struct_obj = ty.castTag(.@"struct").?.data; | 4629 | .anon_struct => return ty.castTag(.anon_struct).?.data.names[field_index], |
| 4641 | assert(struct_obj.haveFieldTypes()); | 4630 | else => unreachable, |
| 4642 | return struct_obj.fields.keys()[field_index]; | 4631 | }, |
| 4632 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 4633 | .struct_type => |struct_type| { | ||
| 4634 | const struct_obj = mod.structPtrUnwrap(struct_type.index).?; | ||
| 4635 | assert(struct_obj.haveFieldTypes()); | ||
| 4636 | return struct_obj.fields.keys()[field_index]; | ||
| 4637 | }, | ||
| 4638 | else => unreachable, | ||
| 4643 | }, | 4639 | }, |
| 4644 | .anon_struct => return ty.castTag(.anon_struct).?.data.names[field_index], | ||
| 4645 | else => unreachable, | ||
| 4646 | } | 4640 | } |
| 4647 | } | 4641 | } |
| 4648 | 4642 | ||
| 4649 | pub fn structFieldCount(ty: Type) usize { | 4643 | pub fn structFieldCount(ty: Type, mod: *Module) usize { |
| 4650 | return switch (ty.ip_index) { | 4644 | return switch (ty.ip_index) { |
| 4651 | .empty_struct_type => 0, | 4645 | .empty_struct_type => 0, |
| 4652 | .none => switch (ty.tag()) { | 4646 | .none => switch (ty.tag()) { |
| 4653 | .@"struct" => { | 4647 | .tuple => ty.castTag(.tuple).?.data.types.len, |
| 4654 | const struct_obj = ty.castTag(.@"struct").?.data; | 4648 | .anon_struct => ty.castTag(.anon_struct).?.data.types.len, |
| 4649 | else => unreachable, | ||
| 4650 | }, | ||
| 4651 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 4652 | .struct_type => |struct_type| { | ||
| 4653 | const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return 0; | ||
| 4655 | assert(struct_obj.haveFieldTypes()); | 4654 | assert(struct_obj.haveFieldTypes()); |
| 4656 | return struct_obj.fields.count(); | 4655 | return struct_obj.fields.count(); |
| 4657 | }, | 4656 | }, |
| 4658 | .empty_struct => 0, | ||
| 4659 | .tuple => ty.castTag(.tuple).?.data.types.len, | ||
| 4660 | .anon_struct => ty.castTag(.anon_struct).?.data.types.len, | ||
| 4661 | else => unreachable, | 4657 | else => unreachable, |
| 4662 | }, | 4658 | }, |
| 4663 | else => unreachable, | ||
| 4664 | }; | 4659 | }; |
| 4665 | } | 4660 | } |
| 4666 | 4661 | ||
| 4667 | /// Supports structs and unions. | 4662 | /// Supports structs and unions. |
| 4668 | pub fn structFieldType(ty: Type, index: usize) Type { | 4663 | pub fn structFieldType(ty: Type, index: usize, mod: *Module) Type { |
| 4669 | switch (ty.tag()) { | 4664 | return switch (ty.ip_index) { |
| 4670 | .@"struct" => { | 4665 | .none => switch (ty.tag()) { |
| 4671 | const struct_obj = ty.castTag(.@"struct").?.data; | 4666 | .@"union", .union_safety_tagged, .union_tagged => { |
| 4672 | return struct_obj.fields.values()[index].ty; | 4667 | const union_obj = ty.cast(Payload.Union).?.data; |
| 4668 | return union_obj.fields.values()[index].ty; | ||
| 4669 | }, | ||
| 4670 | .tuple => return ty.castTag(.tuple).?.data.types[index], | ||
| 4671 | .anon_struct => return ty.castTag(.anon_struct).?.data.types[index], | ||
| 4672 | else => unreachable, | ||
| 4673 | }, | 4673 | }, |
| 4674 | .@"union", .union_safety_tagged, .union_tagged => { | 4674 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 4675 | const union_obj = ty.cast(Payload.Union).?.data; | 4675 | .struct_type => |struct_type| { |
| 4676 | return union_obj.fields.values()[index].ty; | 4676 | const struct_obj = mod.structPtrUnwrap(struct_type.index).?; |
| 4677 | return struct_obj.fields.values()[index].ty; | ||
| 4678 | }, | ||
| 4679 | else => unreachable, | ||
| 4677 | }, | 4680 | }, |
| 4678 | .tuple => return ty.castTag(.tuple).?.data.types[index], | 4681 | }; |
| 4679 | .anon_struct => return ty.castTag(.anon_struct).?.data.types[index], | ||
| 4680 | else => unreachable, | ||
| 4681 | } | ||
| 4682 | } | 4682 | } |
| 4683 | 4683 | ||
| 4684 | pub fn structFieldAlign(ty: Type, index: usize, mod: *Module) u32 { | 4684 | pub fn structFieldAlign(ty: Type, index: usize, mod: *Module) u32 { |
| 4685 | switch (ty.tag()) { | 4685 | switch (ty.ip_index) { |
| 4686 | .@"struct" => { | 4686 | .none => switch (ty.tag()) { |
| 4687 | const struct_obj = ty.castTag(.@"struct").?.data; | 4687 | .@"union", .union_safety_tagged, .union_tagged => { |
| 4688 | assert(struct_obj.layout != .Packed); | 4688 | const union_obj = ty.cast(Payload.Union).?.data; |
| 4689 | return struct_obj.fields.values()[index].alignment(mod, struct_obj.layout); | 4689 | return union_obj.fields.values()[index].normalAlignment(mod); |
| 4690 | }, | ||
| 4691 | .tuple => return ty.castTag(.tuple).?.data.types[index].abiAlignment(mod), | ||
| 4692 | .anon_struct => return ty.castTag(.anon_struct).?.data.types[index].abiAlignment(mod), | ||
| 4693 | else => unreachable, | ||
| 4690 | }, | 4694 | }, |
| 4691 | .@"union", .union_safety_tagged, .union_tagged => { | 4695 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 4692 | const union_obj = ty.cast(Payload.Union).?.data; | 4696 | .struct_type => |struct_type| { |
| 4693 | return union_obj.fields.values()[index].normalAlignment(mod); | 4697 | const struct_obj = mod.structPtrUnwrap(struct_type.index).?; |
| 4698 | assert(struct_obj.layout != .Packed); | ||
| 4699 | return struct_obj.fields.values()[index].alignment(mod, struct_obj.layout); | ||
| 4700 | }, | ||
| 4701 | else => unreachable, | ||
| 4694 | }, | 4702 | }, |
| 4695 | .tuple => return ty.castTag(.tuple).?.data.types[index].abiAlignment(mod), | ||
| 4696 | .anon_struct => return ty.castTag(.anon_struct).?.data.types[index].abiAlignment(mod), | ||
| 4697 | else => unreachable, | ||
| 4698 | } | 4703 | } |
| 4699 | } | 4704 | } |
| 4700 | 4705 | ||
| 4701 | pub fn structFieldDefaultValue(ty: Type, index: usize) Value { | 4706 | pub fn structFieldDefaultValue(ty: Type, index: usize, mod: *Module) Value { |
| 4702 | switch (ty.tag()) { | 4707 | switch (ty.ip_index) { |
| 4703 | .@"struct" => { | 4708 | .none => switch (ty.tag()) { |
| 4704 | const struct_obj = ty.castTag(.@"struct").?.data; | 4709 | .tuple => { |
| 4705 | return struct_obj.fields.values()[index].default_val; | 4710 | const tuple = ty.castTag(.tuple).?.data; |
| 4706 | }, | 4711 | return tuple.values[index]; |
| 4707 | .tuple => { | 4712 | }, |
| 4708 | const tuple = ty.castTag(.tuple).?.data; | 4713 | .anon_struct => { |
| 4709 | return tuple.values[index]; | 4714 | const struct_obj = ty.castTag(.anon_struct).?.data; |
| 4715 | return struct_obj.values[index]; | ||
| 4716 | }, | ||
| 4717 | else => unreachable, | ||
| 4710 | }, | 4718 | }, |
| 4711 | .anon_struct => { | 4719 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 4712 | const struct_obj = ty.castTag(.anon_struct).?.data; | 4720 | .struct_type => |struct_type| { |
| 4713 | return struct_obj.values[index]; | 4721 | const struct_obj = mod.structPtrUnwrap(struct_type.index).?; |
| 4722 | return struct_obj.fields.values()[index].default_val; | ||
| 4723 | }, | ||
| 4724 | else => unreachable, | ||
| 4714 | }, | 4725 | }, |
| 4715 | else => unreachable, | ||
| 4716 | } | 4726 | } |
| 4717 | } | 4727 | } |
| 4718 | 4728 | ||
| 4719 | pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value { | 4729 | pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value { |
| 4720 | switch (ty.tag()) { | 4730 | switch (ty.ip_index) { |
| 4721 | .@"struct" => { | 4731 | .none => switch (ty.tag()) { |
| 4722 | const struct_obj = ty.castTag(.@"struct").?.data; | 4732 | .tuple => { |
| 4723 | const field = struct_obj.fields.values()[index]; | 4733 | const tuple = ty.castTag(.tuple).?.data; |
| 4724 | if (field.is_comptime) { | 4734 | const val = tuple.values[index]; |
| 4725 | return field.default_val; | 4735 | if (val.ip_index == .unreachable_value) { |
| 4726 | } else { | 4736 | return tuple.types[index].onePossibleValue(mod); |
| 4727 | return field.ty.onePossibleValue(mod); | 4737 | } else { |
| 4728 | } | 4738 | return val; |
| 4729 | }, | 4739 | } |
| 4730 | .tuple => { | 4740 | }, |
| 4731 | const tuple = ty.castTag(.tuple).?.data; | 4741 | .anon_struct => { |
| 4732 | const val = tuple.values[index]; | 4742 | const anon_struct = ty.castTag(.anon_struct).?.data; |
| 4733 | if (val.ip_index == .unreachable_value) { | 4743 | const val = anon_struct.values[index]; |
| 4734 | return tuple.types[index].onePossibleValue(mod); | 4744 | if (val.ip_index == .unreachable_value) { |
| 4735 | } else { | 4745 | return anon_struct.types[index].onePossibleValue(mod); |
| 4736 | return val; | 4746 | } else { |
| 4737 | } | 4747 | return val; |
| 4748 | } | ||
| 4749 | }, | ||
| 4750 | else => unreachable, | ||
| 4738 | }, | 4751 | }, |
| 4739 | .anon_struct => { | 4752 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 4740 | const anon_struct = ty.castTag(.anon_struct).?.data; | 4753 | .struct_type => |struct_type| { |
| 4741 | const val = anon_struct.values[index]; | 4754 | const struct_obj = mod.structPtrUnwrap(struct_type.index).?; |
| 4742 | if (val.ip_index == .unreachable_value) { | 4755 | const field = struct_obj.fields.values()[index]; |
| 4743 | return anon_struct.types[index].onePossibleValue(mod); | 4756 | if (field.is_comptime) { |
| 4744 | } else { | 4757 | return field.default_val; |
| 4745 | return val; | 4758 | } else { |
| 4746 | } | 4759 | return field.ty.onePossibleValue(mod); |
| 4760 | } | ||
| 4761 | }, | ||
| 4762 | else => unreachable, | ||
| 4747 | }, | 4763 | }, |
| 4748 | else => unreachable, | ||
| 4749 | } | 4764 | } |
| 4750 | } | 4765 | } |
| 4751 | 4766 | ||
| 4752 | pub fn structFieldIsComptime(ty: Type, index: usize) bool { | 4767 | pub fn structFieldIsComptime(ty: Type, index: usize, mod: *Module) bool { |
| 4753 | switch (ty.tag()) { | 4768 | switch (ty.ip_index) { |
| 4754 | .@"struct" => { | 4769 | .none => switch (ty.tag()) { |
| 4755 | const struct_obj = ty.castTag(.@"struct").?.data; | 4770 | .tuple => { |
| 4756 | if (struct_obj.layout == .Packed) return false; | 4771 | const tuple = ty.castTag(.tuple).?.data; |
| 4757 | const field = struct_obj.fields.values()[index]; | 4772 | const val = tuple.values[index]; |
| 4758 | return field.is_comptime; | 4773 | return val.ip_index != .unreachable_value; |
| 4759 | }, | 4774 | }, |
| 4760 | .tuple => { | 4775 | .anon_struct => { |
| 4761 | const tuple = ty.castTag(.tuple).?.data; | 4776 | const anon_struct = ty.castTag(.anon_struct).?.data; |
| 4762 | const val = tuple.values[index]; | 4777 | const val = anon_struct.values[index]; |
| 4763 | return val.ip_index != .unreachable_value; | 4778 | return val.ip_index != .unreachable_value; |
| 4779 | }, | ||
| 4780 | else => unreachable, | ||
| 4764 | }, | 4781 | }, |
| 4765 | .anon_struct => { | 4782 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 4766 | const anon_struct = ty.castTag(.anon_struct).?.data; | 4783 | .struct_type => |struct_type| { |
| 4767 | const val = anon_struct.values[index]; | 4784 | const struct_obj = mod.structPtrUnwrap(struct_type.index).?; |
| 4768 | return val.ip_index != .unreachable_value; | 4785 | if (struct_obj.layout == .Packed) return false; |
| 4786 | const field = struct_obj.fields.values()[index]; | ||
| 4787 | return field.is_comptime; | ||
| 4788 | }, | ||
| 4789 | else => unreachable, | ||
| 4769 | }, | 4790 | }, |
| 4770 | else => unreachable, | ||
| 4771 | } | 4791 | } |
| 4772 | } | 4792 | } |
| 4773 | 4793 | ||
| 4774 | pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, mod: *Module) u32 { | 4794 | pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, mod: *Module) u32 { |
| 4775 | const struct_obj = ty.castTag(.@"struct").?.data; | 4795 | const struct_type = mod.intern_pool.indexToKey(ty.ip_index).struct_type; |
| 4796 | const struct_obj = mod.structPtrUnwrap(struct_type.index).?; | ||
| 4776 | assert(struct_obj.layout == .Packed); | 4797 | assert(struct_obj.layout == .Packed); |
| 4777 | comptime assert(Type.packed_struct_layout_version == 2); | 4798 | comptime assert(Type.packed_struct_layout_version == 2); |
| 4778 | 4799 | ||
| ... | @@ -4833,7 +4854,8 @@ pub const Type = struct { | ... | @@ -4833,7 +4854,8 @@ pub const Type = struct { |
| 4833 | /// Get an iterator that iterates over all the struct field, returning the field and | 4854 | /// Get an iterator that iterates over all the struct field, returning the field and |
| 4834 | /// offset of that field. Asserts that the type is a non-packed struct. | 4855 | /// offset of that field. Asserts that the type is a non-packed struct. |
| 4835 | pub fn iterateStructOffsets(ty: Type, mod: *Module) StructOffsetIterator { | 4856 | pub fn iterateStructOffsets(ty: Type, mod: *Module) StructOffsetIterator { |
| 4836 | const struct_obj = ty.castTag(.@"struct").?.data; | 4857 | const struct_type = mod.intern_pool.indexToKey(ty.ip_index).struct_type; |
| 4858 | const struct_obj = mod.structPtrUnwrap(struct_type.index).?; | ||
| 4837 | assert(struct_obj.haveLayout()); | 4859 | assert(struct_obj.haveLayout()); |
| 4838 | assert(struct_obj.layout != .Packed); | 4860 | assert(struct_obj.layout != .Packed); |
| 4839 | return .{ .struct_obj = struct_obj, .module = mod }; | 4861 | return .{ .struct_obj = struct_obj, .module = mod }; |
| ... | @@ -4841,57 +4863,62 @@ pub const Type = struct { | ... | @@ -4841,57 +4863,62 @@ pub const Type = struct { |
| 4841 | 4863 | ||
| 4842 | /// Supports structs and unions. | 4864 | /// Supports structs and unions. |
| 4843 | pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 { | 4865 | pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 { |
| 4844 | switch (ty.tag()) { | 4866 | switch (ty.ip_index) { |
| 4845 | .@"struct" => { | 4867 | .none => switch (ty.tag()) { |
| 4846 | const struct_obj = ty.castTag(.@"struct").?.data; | 4868 | .tuple, .anon_struct => { |
| 4847 | assert(struct_obj.haveLayout()); | 4869 | const tuple = ty.tupleFields(); |
| 4848 | assert(struct_obj.layout != .Packed); | ||
| 4849 | var it = ty.iterateStructOffsets(mod); | ||
| 4850 | while (it.next()) |field_offset| { | ||
| 4851 | if (index == field_offset.field) | ||
| 4852 | return field_offset.offset; | ||
| 4853 | } | ||
| 4854 | |||
| 4855 | return std.mem.alignForwardGeneric(u64, it.offset, @max(it.big_align, 1)); | ||
| 4856 | }, | ||
| 4857 | 4870 | ||
| 4858 | .tuple, .anon_struct => { | 4871 | var offset: u64 = 0; |
| 4859 | const tuple = ty.tupleFields(); | 4872 | var big_align: u32 = 0; |
| 4860 | 4873 | ||
| 4861 | var offset: u64 = 0; | 4874 | for (tuple.types, 0..) |field_ty, i| { |
| 4862 | var big_align: u32 = 0; | 4875 | const field_val = tuple.values[i]; |
| 4876 | if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) { | ||
| 4877 | // comptime field | ||
| 4878 | if (i == index) return offset; | ||
| 4879 | continue; | ||
| 4880 | } | ||
| 4863 | 4881 | ||
| 4864 | for (tuple.types, 0..) |field_ty, i| { | 4882 | const field_align = field_ty.abiAlignment(mod); |
| 4865 | const field_val = tuple.values[i]; | 4883 | big_align = @max(big_align, field_align); |
| 4866 | if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) { | 4884 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); |
| 4867 | // comptime field | ||
| 4868 | if (i == index) return offset; | 4885 | if (i == index) return offset; |
| 4869 | continue; | 4886 | offset += field_ty.abiSize(mod); |
| 4870 | } | 4887 | } |
| 4888 | offset = std.mem.alignForwardGeneric(u64, offset, @max(big_align, 1)); | ||
| 4889 | return offset; | ||
| 4890 | }, | ||
| 4871 | 4891 | ||
| 4872 | const field_align = field_ty.abiAlignment(mod); | 4892 | .@"union" => return 0, |
| 4873 | big_align = @max(big_align, field_align); | 4893 | .union_safety_tagged, .union_tagged => { |
| 4874 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); | 4894 | const union_obj = ty.cast(Payload.Union).?.data; |
| 4875 | if (i == index) return offset; | 4895 | const layout = union_obj.getLayout(mod, true); |
| 4876 | offset += field_ty.abiSize(mod); | 4896 | if (layout.tag_align >= layout.payload_align) { |
| 4877 | } | 4897 | // {Tag, Payload} |
| 4878 | offset = std.mem.alignForwardGeneric(u64, offset, @max(big_align, 1)); | 4898 | return std.mem.alignForwardGeneric(u64, layout.tag_size, layout.payload_align); |
| 4879 | return offset; | 4899 | } else { |
| 4900 | // {Payload, Tag} | ||
| 4901 | return 0; | ||
| 4902 | } | ||
| 4903 | }, | ||
| 4904 | else => unreachable, | ||
| 4880 | }, | 4905 | }, |
| 4906 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 4907 | .struct_type => |struct_type| { | ||
| 4908 | const struct_obj = mod.structPtrUnwrap(struct_type.index).?; | ||
| 4909 | assert(struct_obj.haveLayout()); | ||
| 4910 | assert(struct_obj.layout != .Packed); | ||
| 4911 | var it = ty.iterateStructOffsets(mod); | ||
| 4912 | while (it.next()) |field_offset| { | ||
| 4913 | if (index == field_offset.field) | ||
| 4914 | return field_offset.offset; | ||
| 4915 | } | ||
| 4881 | 4916 | ||
| 4882 | .@"union" => return 0, | 4917 | return std.mem.alignForwardGeneric(u64, it.offset, @max(it.big_align, 1)); |
| 4883 | .union_safety_tagged, .union_tagged => { | 4918 | }, |
| 4884 | const union_obj = ty.cast(Payload.Union).?.data; | 4919 | |
| 4885 | const layout = union_obj.getLayout(mod, true); | 4920 | else => unreachable, |
| 4886 | if (layout.tag_align >= layout.payload_align) { | ||
| 4887 | // {Tag, Payload} | ||
| 4888 | return std.mem.alignForwardGeneric(u64, layout.tag_size, layout.payload_align); | ||
| 4889 | } else { | ||
| 4890 | // {Payload, Tag} | ||
| 4891 | return 0; | ||
| 4892 | } | ||
| 4893 | }, | 4921 | }, |
| 4894 | else => unreachable, | ||
| 4895 | } | 4922 | } |
| 4896 | } | 4923 | } |
| 4897 | 4924 | ||
| ... | @@ -4901,6 +4928,7 @@ pub const Type = struct { | ... | @@ -4901,6 +4928,7 @@ pub const Type = struct { |
| 4901 | 4928 | ||
| 4902 | pub fn declSrcLocOrNull(ty: Type, mod: *Module) ?Module.SrcLoc { | 4929 | pub fn declSrcLocOrNull(ty: Type, mod: *Module) ?Module.SrcLoc { |
| 4903 | switch (ty.ip_index) { | 4930 | switch (ty.ip_index) { |
| 4931 | .empty_struct_type => return null, | ||
| 4904 | .none => switch (ty.tag()) { | 4932 | .none => switch (ty.tag()) { |
| 4905 | .enum_full, .enum_nonexhaustive => { | 4933 | .enum_full, .enum_nonexhaustive => { |
| 4906 | const enum_full = ty.cast(Payload.EnumFull).?.data; | 4934 | const enum_full = ty.cast(Payload.EnumFull).?.data; |
| ... | @@ -4914,10 +4942,6 @@ pub const Type = struct { | ... | @@ -4914,10 +4942,6 @@ pub const Type = struct { |
| 4914 | const enum_simple = ty.castTag(.enum_simple).?.data; | 4942 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| 4915 | return enum_simple.srcLoc(mod); | 4943 | return enum_simple.srcLoc(mod); |
| 4916 | }, | 4944 | }, |
| 4917 | .@"struct" => { | ||
| 4918 | const struct_obj = ty.castTag(.@"struct").?.data; | ||
| 4919 | return struct_obj.srcLoc(mod); | ||
| 4920 | }, | ||
| 4921 | .error_set => { | 4945 | .error_set => { |
| 4922 | const error_set = ty.castTag(.error_set).?.data; | 4946 | const error_set = ty.castTag(.error_set).?.data; |
| 4923 | return error_set.srcLoc(mod); | 4947 | return error_set.srcLoc(mod); |
| ... | @@ -4930,7 +4954,10 @@ pub const Type = struct { | ... | @@ -4930,7 +4954,10 @@ pub const Type = struct { |
| 4930 | else => return null, | 4954 | else => return null, |
| 4931 | }, | 4955 | }, |
| 4932 | else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) { | 4956 | else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 4933 | .struct_type => @panic("TODO"), | 4957 | .struct_type => |struct_type| { |
| 4958 | const struct_obj = mod.structPtrUnwrap(struct_type.index).?; | ||
| 4959 | return struct_obj.srcLoc(mod); | ||
| 4960 | }, | ||
| 4934 | .union_type => @panic("TODO"), | 4961 | .union_type => @panic("TODO"), |
| 4935 | .opaque_type => |opaque_type| mod.opaqueSrcLoc(opaque_type), | 4962 | .opaque_type => |opaque_type| mod.opaqueSrcLoc(opaque_type), |
| 4936 | else => null, | 4963 | else => null, |
| ... | @@ -4954,10 +4981,6 @@ pub const Type = struct { | ... | @@ -4954,10 +4981,6 @@ pub const Type = struct { |
| 4954 | const enum_simple = ty.castTag(.enum_simple).?.data; | 4981 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| 4955 | return enum_simple.owner_decl; | 4982 | return enum_simple.owner_decl; |
| 4956 | }, | 4983 | }, |
| 4957 | .@"struct" => { | ||
| 4958 | const struct_obj = ty.castTag(.@"struct").?.data; | ||
| 4959 | return struct_obj.owner_decl; | ||
| 4960 | }, | ||
| 4961 | .error_set => { | 4984 | .error_set => { |
| 4962 | const error_set = ty.castTag(.error_set).?.data; | 4985 | const error_set = ty.castTag(.error_set).?.data; |
| 4963 | return error_set.owner_decl; | 4986 | return error_set.owner_decl; |
| ... | @@ -4970,7 +4993,10 @@ pub const Type = struct { | ... | @@ -4970,7 +4993,10 @@ pub const Type = struct { |
| 4970 | else => return null, | 4993 | else => return null, |
| 4971 | }, | 4994 | }, |
| 4972 | else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) { | 4995 | else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 4973 | .struct_type => @panic("TODO"), | 4996 | .struct_type => |struct_type| { |
| 4997 | const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return null; | ||
| 4998 | return struct_obj.owner_decl; | ||
| 4999 | }, | ||
| 4974 | .union_type => @panic("TODO"), | 5000 | .union_type => @panic("TODO"), |
| 4975 | .opaque_type => |opaque_type| opaque_type.decl, | 5001 | .opaque_type => |opaque_type| opaque_type.decl, |
| 4976 | else => null, | 5002 | else => null, |
| ... | @@ -5013,8 +5039,6 @@ pub const Type = struct { | ... | @@ -5013,8 +5039,6 @@ pub const Type = struct { |
| 5013 | /// The type is the inferred error set of a specific function. | 5039 | /// The type is the inferred error set of a specific function. |
| 5014 | error_set_inferred, | 5040 | error_set_inferred, |
| 5015 | error_set_merged, | 5041 | error_set_merged, |
| 5016 | empty_struct, | ||
| 5017 | @"struct", | ||
| 5018 | @"union", | 5042 | @"union", |
| 5019 | union_safety_tagged, | 5043 | union_safety_tagged, |
| 5020 | union_tagged, | 5044 | union_tagged, |
| ... | @@ -5046,12 +5070,10 @@ pub const Type = struct { | ... | @@ -5046,12 +5070,10 @@ pub const Type = struct { |
| 5046 | .function => Payload.Function, | 5070 | .function => Payload.Function, |
| 5047 | .error_union => Payload.ErrorUnion, | 5071 | .error_union => Payload.ErrorUnion, |
| 5048 | .error_set_single => Payload.Name, | 5072 | .error_set_single => Payload.Name, |
| 5049 | .@"struct" => Payload.Struct, | ||
| 5050 | .@"union", .union_safety_tagged, .union_tagged => Payload.Union, | 5073 | .@"union", .union_safety_tagged, .union_tagged => Payload.Union, |
| 5051 | .enum_full, .enum_nonexhaustive => Payload.EnumFull, | 5074 | .enum_full, .enum_nonexhaustive => Payload.EnumFull, |
| 5052 | .enum_simple => Payload.EnumSimple, | 5075 | .enum_simple => Payload.EnumSimple, |
| 5053 | .enum_numbered => Payload.EnumNumbered, | 5076 | .enum_numbered => Payload.EnumNumbered, |
| 5054 | .empty_struct => Payload.ContainerScope, | ||
| 5055 | .tuple => Payload.Tuple, | 5077 | .tuple => Payload.Tuple, |
| 5056 | .anon_struct => Payload.AnonStruct, | 5078 | .anon_struct => Payload.AnonStruct, |
| 5057 | }; | 5079 | }; |
| ... | @@ -5082,15 +5104,19 @@ pub const Type = struct { | ... | @@ -5082,15 +5104,19 @@ pub const Type = struct { |
| 5082 | } | 5104 | } |
| 5083 | }; | 5105 | }; |
| 5084 | 5106 | ||
| 5085 | pub fn isTuple(ty: Type) bool { | 5107 | pub fn isTuple(ty: Type, mod: *Module) bool { |
| 5086 | return switch (ty.ip_index) { | 5108 | return switch (ty.ip_index) { |
| 5087 | .empty_struct_type => true, | ||
| 5088 | .none => switch (ty.tag()) { | 5109 | .none => switch (ty.tag()) { |
| 5089 | .tuple => true, | 5110 | .tuple => true, |
| 5090 | .@"struct" => ty.castTag(.@"struct").?.data.is_tuple, | ||
| 5091 | else => false, | 5111 | else => false, |
| 5092 | }, | 5112 | }, |
| 5093 | else => false, // TODO struct | 5113 | else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 5114 | .struct_type => |struct_type| { | ||
| 5115 | const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false; | ||
| 5116 | return struct_obj.is_tuple; | ||
| 5117 | }, | ||
| 5118 | else => false, | ||
| 5119 | }, | ||
| 5094 | }; | 5120 | }; |
| 5095 | } | 5121 | } |
| 5096 | 5122 | ||
| ... | @@ -5101,36 +5127,41 @@ pub const Type = struct { | ... | @@ -5101,36 +5127,41 @@ pub const Type = struct { |
| 5101 | .anon_struct => true, | 5127 | .anon_struct => true, |
| 5102 | else => false, | 5128 | else => false, |
| 5103 | }, | 5129 | }, |
| 5104 | else => false, // TODO struct | 5130 | else => false, |
| 5105 | }; | 5131 | }; |
| 5106 | } | 5132 | } |
| 5107 | 5133 | ||
| 5108 | pub fn isTupleOrAnonStruct(ty: Type) bool { | 5134 | pub fn isTupleOrAnonStruct(ty: Type, mod: *Module) bool { |
| 5109 | return switch (ty.ip_index) { | 5135 | return switch (ty.ip_index) { |
| 5110 | .empty_struct_type => true, | 5136 | .empty_struct_type => true, |
| 5111 | .none => switch (ty.tag()) { | 5137 | .none => switch (ty.tag()) { |
| 5112 | .tuple, .anon_struct => true, | 5138 | .tuple, .anon_struct => true, |
| 5113 | .@"struct" => ty.castTag(.@"struct").?.data.is_tuple, | ||
| 5114 | else => false, | 5139 | else => false, |
| 5115 | }, | 5140 | }, |
| 5116 | else => false, // TODO struct | 5141 | else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 5142 | .struct_type => |struct_type| { | ||
| 5143 | const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false; | ||
| 5144 | return struct_obj.is_tuple; | ||
| 5145 | }, | ||
| 5146 | else => false, | ||
| 5147 | }, | ||
| 5117 | }; | 5148 | }; |
| 5118 | } | 5149 | } |
| 5119 | 5150 | ||
| 5120 | pub fn isSimpleTuple(ty: Type) bool { | 5151 | pub fn isSimpleTuple(ty: Type) bool { |
| 5121 | return switch (ty.ip_index) { | 5152 | return switch (ty.ip_index) { |
| 5122 | .empty_struct => true, | 5153 | .empty_struct_type => true, |
| 5123 | .none => switch (ty.tag()) { | 5154 | .none => switch (ty.tag()) { |
| 5124 | .tuple => true, | 5155 | .tuple => true, |
| 5125 | else => false, | 5156 | else => false, |
| 5126 | }, | 5157 | }, |
| 5127 | else => false, // TODO | 5158 | else => false, |
| 5128 | }; | 5159 | }; |
| 5129 | } | 5160 | } |
| 5130 | 5161 | ||
| 5131 | pub fn isSimpleTupleOrAnonStruct(ty: Type) bool { | 5162 | pub fn isSimpleTupleOrAnonStruct(ty: Type) bool { |
| 5132 | return switch (ty.ip_index) { | 5163 | return switch (ty.ip_index) { |
| 5133 | .empty_struct => true, | 5164 | .empty_struct_type => true, |
| 5134 | .none => switch (ty.tag()) { | 5165 | .none => switch (ty.tag()) { |
| 5135 | .tuple, .anon_struct => true, | 5166 | .tuple, .anon_struct => true, |
| 5136 | else => false, | 5167 | else => false, |
| ... | @@ -5142,7 +5173,7 @@ pub const Type = struct { | ... | @@ -5142,7 +5173,7 @@ pub const Type = struct { |
| 5142 | // Only allowed for simple tuple types | 5173 | // Only allowed for simple tuple types |
| 5143 | pub fn tupleFields(ty: Type) Payload.Tuple.Data { | 5174 | pub fn tupleFields(ty: Type) Payload.Tuple.Data { |
| 5144 | return switch (ty.ip_index) { | 5175 | return switch (ty.ip_index) { |
| 5145 | .empty_struct => .{ .types = &.{}, .values = &.{} }, | 5176 | .empty_struct_type => .{ .types = &.{}, .values = &.{} }, |
| 5146 | .none => switch (ty.tag()) { | 5177 | .none => switch (ty.tag()) { |
| 5147 | .tuple => ty.castTag(.tuple).?.data, | 5178 | .tuple => ty.castTag(.tuple).?.data, |
| 5148 | .anon_struct => .{ | 5179 | .anon_struct => .{ |
| ... | @@ -5319,18 +5350,6 @@ pub const Type = struct { | ... | @@ -5319,18 +5350,6 @@ pub const Type = struct { |
| 5319 | data: []const u8, | 5350 | data: []const u8, |
| 5320 | }; | 5351 | }; |
| 5321 | 5352 | ||
| 5322 | /// Mostly used for namespace like structs with zero fields. | ||
| 5323 | /// Most commonly used for files. | ||
| 5324 | pub const ContainerScope = struct { | ||
| 5325 | base: Payload, | ||
| 5326 | data: *Module.Namespace, | ||
| 5327 | }; | ||
| 5328 | |||
| 5329 | pub const Struct = struct { | ||
| 5330 | base: Payload = .{ .tag = .@"struct" }, | ||
| 5331 | data: *Module.Struct, | ||
| 5332 | }; | ||
| 5333 | |||
| 5334 | pub const Tuple = struct { | 5353 | pub const Tuple = struct { |
| 5335 | base: Payload = .{ .tag = .tuple }, | 5354 | base: Payload = .{ .tag = .tuple }, |
| 5336 | data: Data, | 5355 | data: Data, |
src/value.zig+19-26| ... | @@ -996,10 +996,10 @@ pub const Value = struct { | ... | @@ -996,10 +996,10 @@ pub const Value = struct { |
| 996 | const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8; | 996 | const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8; |
| 997 | return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0); | 997 | return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0); |
| 998 | }, | 998 | }, |
| 999 | .Struct => switch (ty.containerLayout()) { | 999 | .Struct => switch (ty.containerLayout(mod)) { |
| 1000 | .Auto => return error.IllDefinedMemoryLayout, | 1000 | .Auto => return error.IllDefinedMemoryLayout, |
| 1001 | .Extern => { | 1001 | .Extern => { |
| 1002 | const fields = ty.structFields().values(); | 1002 | const fields = ty.structFields(mod).values(); |
| 1003 | const field_vals = val.castTag(.aggregate).?.data; | 1003 | const field_vals = val.castTag(.aggregate).?.data; |
| 1004 | for (fields, 0..) |field, i| { | 1004 | for (fields, 0..) |field, i| { |
| 1005 | const off = @intCast(usize, ty.structFieldOffset(i, mod)); | 1005 | const off = @intCast(usize, ty.structFieldOffset(i, mod)); |
| ... | @@ -1017,7 +1017,7 @@ pub const Value = struct { | ... | @@ -1017,7 +1017,7 @@ pub const Value = struct { |
| 1017 | const int = mod.global_error_set.get(val.castTag(.@"error").?.data.name).?; | 1017 | const int = mod.global_error_set.get(val.castTag(.@"error").?.data.name).?; |
| 1018 | std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @intCast(Int, int), endian); | 1018 | std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @intCast(Int, int), endian); |
| 1019 | }, | 1019 | }, |
| 1020 | .Union => switch (ty.containerLayout()) { | 1020 | .Union => switch (ty.containerLayout(mod)) { |
| 1021 | .Auto => return error.IllDefinedMemoryLayout, | 1021 | .Auto => return error.IllDefinedMemoryLayout, |
| 1022 | .Extern => return error.Unimplemented, | 1022 | .Extern => return error.Unimplemented, |
| 1023 | .Packed => { | 1023 | .Packed => { |
| ... | @@ -1119,12 +1119,12 @@ pub const Value = struct { | ... | @@ -1119,12 +1119,12 @@ pub const Value = struct { |
| 1119 | bits += elem_bit_size; | 1119 | bits += elem_bit_size; |
| 1120 | } | 1120 | } |
| 1121 | }, | 1121 | }, |
| 1122 | .Struct => switch (ty.containerLayout()) { | 1122 | .Struct => switch (ty.containerLayout(mod)) { |
| 1123 | .Auto => unreachable, // Sema is supposed to have emitted a compile error already | 1123 | .Auto => unreachable, // Sema is supposed to have emitted a compile error already |
| 1124 | .Extern => unreachable, // Handled in non-packed writeToMemory | 1124 | .Extern => unreachable, // Handled in non-packed writeToMemory |
| 1125 | .Packed => { | 1125 | .Packed => { |
| 1126 | var bits: u16 = 0; | 1126 | var bits: u16 = 0; |
| 1127 | const fields = ty.structFields().values(); | 1127 | const fields = ty.structFields(mod).values(); |
| 1128 | const field_vals = val.castTag(.aggregate).?.data; | 1128 | const field_vals = val.castTag(.aggregate).?.data; |
| 1129 | for (fields, 0..) |field, i| { | 1129 | for (fields, 0..) |field, i| { |
| 1130 | const field_bits = @intCast(u16, field.ty.bitSize(mod)); | 1130 | const field_bits = @intCast(u16, field.ty.bitSize(mod)); |
| ... | @@ -1133,7 +1133,7 @@ pub const Value = struct { | ... | @@ -1133,7 +1133,7 @@ pub const Value = struct { |
| 1133 | } | 1133 | } |
| 1134 | }, | 1134 | }, |
| 1135 | }, | 1135 | }, |
| 1136 | .Union => switch (ty.containerLayout()) { | 1136 | .Union => switch (ty.containerLayout(mod)) { |
| 1137 | .Auto => unreachable, // Sema is supposed to have emitted a compile error already | 1137 | .Auto => unreachable, // Sema is supposed to have emitted a compile error already |
| 1138 | .Extern => unreachable, // Handled in non-packed writeToMemory | 1138 | .Extern => unreachable, // Handled in non-packed writeToMemory |
| 1139 | .Packed => { | 1139 | .Packed => { |
| ... | @@ -1236,14 +1236,14 @@ pub const Value = struct { | ... | @@ -1236,14 +1236,14 @@ pub const Value = struct { |
| 1236 | const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8; | 1236 | const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8; |
| 1237 | return readFromPackedMemory(ty, mod, buffer[0..byte_count], 0, arena); | 1237 | return readFromPackedMemory(ty, mod, buffer[0..byte_count], 0, arena); |
| 1238 | }, | 1238 | }, |
| 1239 | .Struct => switch (ty.containerLayout()) { | 1239 | .Struct => switch (ty.containerLayout(mod)) { |
| 1240 | .Auto => unreachable, // Sema is supposed to have emitted a compile error already | 1240 | .Auto => unreachable, // Sema is supposed to have emitted a compile error already |
| 1241 | .Extern => { | 1241 | .Extern => { |
| 1242 | const fields = ty.structFields().values(); | 1242 | const fields = ty.structFields(mod).values(); |
| 1243 | const field_vals = try arena.alloc(Value, fields.len); | 1243 | const field_vals = try arena.alloc(Value, fields.len); |
| 1244 | for (fields, 0..) |field, i| { | 1244 | for (fields, 0..) |field, i| { |
| 1245 | const off = @intCast(usize, ty.structFieldOffset(i, mod)); | 1245 | const off = @intCast(usize, ty.structFieldOffset(i, mod)); |
| 1246 | const sz = @intCast(usize, ty.structFieldType(i).abiSize(mod)); | 1246 | const sz = @intCast(usize, ty.structFieldType(i, mod).abiSize(mod)); |
| 1247 | field_vals[i] = try readFromMemory(field.ty, mod, buffer[off..(off + sz)], arena); | 1247 | field_vals[i] = try readFromMemory(field.ty, mod, buffer[off..(off + sz)], arena); |
| 1248 | } | 1248 | } |
| 1249 | return Tag.aggregate.create(arena, field_vals); | 1249 | return Tag.aggregate.create(arena, field_vals); |
| ... | @@ -1346,12 +1346,12 @@ pub const Value = struct { | ... | @@ -1346,12 +1346,12 @@ pub const Value = struct { |
| 1346 | } | 1346 | } |
| 1347 | return Tag.aggregate.create(arena, elems); | 1347 | return Tag.aggregate.create(arena, elems); |
| 1348 | }, | 1348 | }, |
| 1349 | .Struct => switch (ty.containerLayout()) { | 1349 | .Struct => switch (ty.containerLayout(mod)) { |
| 1350 | .Auto => unreachable, // Sema is supposed to have emitted a compile error already | 1350 | .Auto => unreachable, // Sema is supposed to have emitted a compile error already |
| 1351 | .Extern => unreachable, // Handled by non-packed readFromMemory | 1351 | .Extern => unreachable, // Handled by non-packed readFromMemory |
| 1352 | .Packed => { | 1352 | .Packed => { |
| 1353 | var bits: u16 = 0; | 1353 | var bits: u16 = 0; |
| 1354 | const fields = ty.structFields().values(); | 1354 | const fields = ty.structFields(mod).values(); |
| 1355 | const field_vals = try arena.alloc(Value, fields.len); | 1355 | const field_vals = try arena.alloc(Value, fields.len); |
| 1356 | for (fields, 0..) |field, i| { | 1356 | for (fields, 0..) |field, i| { |
| 1357 | const field_bits = @intCast(u16, field.ty.bitSize(mod)); | 1357 | const field_bits = @intCast(u16, field.ty.bitSize(mod)); |
| ... | @@ -1996,7 +1996,7 @@ pub const Value = struct { | ... | @@ -1996,7 +1996,7 @@ pub const Value = struct { |
| 1996 | } | 1996 | } |
| 1997 | 1997 | ||
| 1998 | if (ty.zigTypeTag(mod) == .Struct) { | 1998 | if (ty.zigTypeTag(mod) == .Struct) { |
| 1999 | const fields = ty.structFields().values(); | 1999 | const fields = ty.structFields(mod).values(); |
| 2000 | assert(fields.len == a_field_vals.len); | 2000 | assert(fields.len == a_field_vals.len); |
| 2001 | for (fields, 0..) |field, i| { | 2001 | for (fields, 0..) |field, i| { |
| 2002 | if (!(try eqlAdvanced(a_field_vals[i], field.ty, b_field_vals[i], field.ty, mod, opt_sema))) { | 2002 | if (!(try eqlAdvanced(a_field_vals[i], field.ty, b_field_vals[i], field.ty, mod, opt_sema))) { |
| ... | @@ -2019,7 +2019,7 @@ pub const Value = struct { | ... | @@ -2019,7 +2019,7 @@ pub const Value = struct { |
| 2019 | .@"union" => { | 2019 | .@"union" => { |
| 2020 | const a_union = a.castTag(.@"union").?.data; | 2020 | const a_union = a.castTag(.@"union").?.data; |
| 2021 | const b_union = b.castTag(.@"union").?.data; | 2021 | const b_union = b.castTag(.@"union").?.data; |
| 2022 | switch (ty.containerLayout()) { | 2022 | switch (ty.containerLayout(mod)) { |
| 2023 | .Packed, .Extern => { | 2023 | .Packed, .Extern => { |
| 2024 | const tag_ty = ty.unionTagTypeHypothetical(); | 2024 | const tag_ty = ty.unionTagTypeHypothetical(); |
| 2025 | if (!(try eqlAdvanced(a_union.tag, tag_ty, b_union.tag, tag_ty, mod, opt_sema))) { | 2025 | if (!(try eqlAdvanced(a_union.tag, tag_ty, b_union.tag, tag_ty, mod, opt_sema))) { |
| ... | @@ -2252,7 +2252,7 @@ pub const Value = struct { | ... | @@ -2252,7 +2252,7 @@ pub const Value = struct { |
| 2252 | .aggregate => { | 2252 | .aggregate => { |
| 2253 | const field_values = val.castTag(.aggregate).?.data; | 2253 | const field_values = val.castTag(.aggregate).?.data; |
| 2254 | for (field_values, 0..) |field_val, i| { | 2254 | for (field_values, 0..) |field_val, i| { |
| 2255 | const field_ty = ty.structFieldType(i); | 2255 | const field_ty = ty.structFieldType(i, mod); |
| 2256 | field_val.hash(field_ty, hasher, mod); | 2256 | field_val.hash(field_ty, hasher, mod); |
| 2257 | } | 2257 | } |
| 2258 | }, | 2258 | }, |
| ... | @@ -2623,7 +2623,7 @@ pub const Value = struct { | ... | @@ -2623,7 +2623,7 @@ pub const Value = struct { |
| 2623 | const data = val.castTag(.field_ptr).?.data; | 2623 | const data = val.castTag(.field_ptr).?.data; |
| 2624 | if (data.container_ptr.pointerDecl()) |decl_index| { | 2624 | if (data.container_ptr.pointerDecl()) |decl_index| { |
| 2625 | const container_decl = mod.declPtr(decl_index); | 2625 | const container_decl = mod.declPtr(decl_index); |
| 2626 | const field_type = data.container_ty.structFieldType(data.field_index); | 2626 | const field_type = data.container_ty.structFieldType(data.field_index, mod); |
| 2627 | const field_val = try container_decl.val.fieldValue(field_type, mod, data.field_index); | 2627 | const field_val = try container_decl.val.fieldValue(field_type, mod, data.field_index); |
| 2628 | return field_val.elemValue(mod, index); | 2628 | return field_val.elemValue(mod, index); |
| 2629 | } else unreachable; | 2629 | } else unreachable; |
| ... | @@ -2758,16 +2758,6 @@ pub const Value = struct { | ... | @@ -2758,16 +2758,6 @@ pub const Value = struct { |
| 2758 | pub fn fieldValue(val: Value, ty: Type, mod: *Module, index: usize) !Value { | 2758 | pub fn fieldValue(val: Value, ty: Type, mod: *Module, index: usize) !Value { |
| 2759 | switch (val.ip_index) { | 2759 | switch (val.ip_index) { |
| 2760 | .undef => return Value.undef, | 2760 | .undef => return Value.undef, |
| 2761 | .empty_struct => { | ||
| 2762 | if (ty.isSimpleTupleOrAnonStruct()) { | ||
| 2763 | const tuple = ty.tupleFields(); | ||
| 2764 | return tuple.values[index]; | ||
| 2765 | } | ||
| 2766 | if (try ty.structFieldValueComptime(mod, index)) |some| { | ||
| 2767 | return some; | ||
| 2768 | } | ||
| 2769 | unreachable; | ||
| 2770 | }, | ||
| 2771 | 2761 | ||
| 2772 | .none => switch (val.tag()) { | 2762 | .none => switch (val.tag()) { |
| 2773 | .aggregate => { | 2763 | .aggregate => { |
| ... | @@ -2784,7 +2774,10 @@ pub const Value = struct { | ... | @@ -2784,7 +2774,10 @@ pub const Value = struct { |
| 2784 | 2774 | ||
| 2785 | else => unreachable, | 2775 | else => unreachable, |
| 2786 | }, | 2776 | }, |
| 2787 | else => unreachable, | 2777 | else => return switch (mod.intern_pool.indexToKey(val.ip_index)) { |
| 2778 | .aggregate => |aggregate| aggregate.fields[index].toValue(), | ||
| 2779 | else => unreachable, | ||
| 2780 | }, | ||
| 2788 | } | 2781 | } |
| 2789 | } | 2782 | } |
| 2790 | 2783 |