| 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 | 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 | 8 | map: std.AutoArrayHashMapUnmanaged(void, void) = .{}, |
| 4 | 9 | items: std.MultiArrayList(Item) = .{}, |
| 5 | 10 | extra: std.ArrayListUnmanaged(u32) = .{}, |
| ... | ... | @@ -9,6 +14,13 @@ extra: std.ArrayListUnmanaged(u32) = .{}, |
| 9 | 14 | /// violate the above mechanism. |
| 10 | 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 | 24 | const std = @import("std"); |
| 13 | 25 | const Allocator = std.mem.Allocator; |
| 14 | 26 | const assert = std.debug.assert; |
| ... | ... | @@ -17,8 +29,7 @@ const BigIntMutable = std.math.big.int.Mutable; |
| 17 | 29 | const Limb = std.math.big.Limb; |
| 18 | 30 | |
| 19 | 31 | const InternPool = @This(); |
| 20 | const DeclIndex = @import("Module.zig").Decl.Index; | |
| 21 | const NamespaceIndex = @import("Module.zig").Namespace.Index; | |
| 32 | const Module = @import("Module.zig"); | |
| 22 | 33 | |
| 23 | 34 | const KeyAdapter = struct { |
| 24 | 35 | intern_pool: *const InternPool, |
| ... | ... | @@ -45,11 +56,20 @@ pub const Key = union(enum) { |
| 45 | 56 | payload_type: Index, |
| 46 | 57 | }, |
| 47 | 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 | 68 | simple_value: SimpleValue, |
| 49 | 69 | extern_func: struct { |
| 50 | 70 | ty: Index, |
| 51 | 71 | /// The Decl that corresponds to the function itself. |
| 52 | decl: DeclIndex, | |
| 72 | decl: Module.Decl.Index, | |
| 53 | 73 | /// Library name if specified. |
| 54 | 74 | /// For example `extern "c" fn write(...) usize` would have 'c' as library name. |
| 55 | 75 | /// Index into the string table bytes. |
| ... | ... | @@ -62,13 +82,11 @@ pub const Key = union(enum) { |
| 62 | 82 | ty: Index, |
| 63 | 83 | tag: BigIntConst, |
| 64 | 84 | }, |
| 65 | struct_type: StructType, | |
| 66 | opaque_type: OpaqueType, | |
| 67 | ||
| 68 | union_type: struct { | |
| 69 | fields_len: u32, | |
| 70 | // TODO move Module.Union data to InternPool | |
| 71 | }, | |
| 85 | /// An instance of a struct, array, or vector. | |
| 86 | /// Each element/field stored as an `Index`. | |
| 87 | /// In the case of sentinel-terminated arrays, the sentinel value *is* stored, | |
| 88 | /// so the slice length will be one more than the type's array length. | |
| 89 | aggregate: Aggregate, | |
| 72 | 90 | |
| 73 | 91 | pub const IntType = std.builtin.Type.Int; |
| 74 | 92 | |
| ... | ... | @@ -113,16 +131,27 @@ pub const Key = union(enum) { |
| 113 | 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 | 134 | pub const OpaqueType = struct { |
| 122 | 135 | /// The Decl that corresponds to the opaque itself. |
| 123 | decl: DeclIndex, | |
| 136 | decl: Module.Decl.Index, | |
| 124 | 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 | 157 | pub const Int = struct { |
| ... | ... | @@ -156,18 +185,24 @@ pub const Key = union(enum) { |
| 156 | 185 | addr: Addr, |
| 157 | 186 | |
| 158 | 187 | pub const Addr = union(enum) { |
| 159 | decl: DeclIndex, | |
| 188 | decl: Module.Decl.Index, | |
| 160 | 189 | int: Index, |
| 161 | 190 | }; |
| 162 | 191 | }; |
| 163 | 192 | |
| 164 | 193 | /// `null` is represented by the `val` field being `none`. |
| 165 | 194 | pub const Opt = struct { |
| 195 | /// This is the optional type; not the payload type. | |
| 166 | 196 | ty: Index, |
| 167 | 197 | /// This could be `none`, indicating the optional is `null`. |
| 168 | 198 | val: Index, |
| 169 | 199 | }; |
| 170 | 200 | |
| 201 | pub const Aggregate = struct { | |
| 202 | ty: Index, | |
| 203 | fields: []const Index, | |
| 204 | }; | |
| 205 | ||
| 171 | 206 | pub fn hash32(key: Key) u32 { |
| 172 | 207 | return @truncate(u32, key.hash64()); |
| 173 | 208 | } |
| ... | ... | @@ -193,8 +228,15 @@ pub const Key = union(enum) { |
| 193 | 228 | .simple_value, |
| 194 | 229 | .extern_func, |
| 195 | 230 | .opt, |
| 231 | .struct_type, | |
| 196 | 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 | 240 | .int => |int| { |
| 199 | 241 | // Canonicalize all integers by converting them to BigIntConst. |
| 200 | 242 | var buffer: Key.Int.Storage.BigIntSpace = undefined; |
| ... | ... | @@ -221,16 +263,10 @@ pub const Key = union(enum) { |
| 221 | 263 | for (enum_tag.tag.limbs) |limb| std.hash.autoHash(hasher, limb); |
| 222 | 264 | }, |
| 223 | 265 | |
| 224 | .struct_type => |struct_type| { | |
| 225 | if (struct_type.fields_len != 0) { | |
| 226 | @panic("TODO"); | |
| 227 | } | |
| 228 | }, | |
| 229 | .union_type => |union_type| { | |
| 230 | _ = union_type; | |
| 231 | @panic("TODO"); | |
| 266 | .aggregate => |aggregate| { | |
| 267 | std.hash.autoHash(hasher, aggregate.ty); | |
| 268 | for (aggregate.fields) |field| std.hash.autoHash(hasher, field); | |
| 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 | 316 | const b_info = b.opt; |
| 281 | 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 | 324 | .ptr => |a_info| { |
| 285 | 325 | const b_info = b.ptr; |
| ... | ... | @@ -331,16 +371,6 @@ pub const Key = union(enum) { |
| 331 | 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 | 374 | .union_type => |a_info| { |
| 345 | 375 | const b_info = b.union_type; |
| 346 | 376 | |
| ... | ... | @@ -353,6 +383,11 @@ pub const Key = union(enum) { |
| 353 | 383 | const b_info = b.opaque_type; |
| 354 | 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 | 410 | .opt, |
| 376 | 411 | .extern_func, |
| 377 | 412 | .enum_tag, |
| 413 | .aggregate, | |
| 378 | 414 | => |x| return x.ty, |
| 379 | 415 | |
| 380 | 416 | .simple_value => |s| switch (s) { |
| ... | ... | @@ -471,6 +507,7 @@ pub const Index = enum(u32) { |
| 471 | 507 | anyerror_void_error_union_type, |
| 472 | 508 | generic_poison_type, |
| 473 | 509 | var_args_param_type, |
| 510 | /// `@TypeOf(.{})` | |
| 474 | 511 | empty_struct_type, |
| 475 | 512 | |
| 476 | 513 | /// `undefined` (untyped) |
| ... | ... | @@ -691,7 +728,8 @@ pub const static_keys = [_]Key{ |
| 691 | 728 | |
| 692 | 729 | // empty_struct_type |
| 693 | 730 | .{ .struct_type = .{ |
| 694 | .fields_len = 0, | |
| 731 | .namespace = .none, | |
| 732 | .index = .none, | |
| 695 | 733 | } }, |
| 696 | 734 | |
| 697 | 735 | .{ .simple_value = .undefined }, |
| ... | ... | @@ -792,16 +830,18 @@ pub const Tag = enum(u8) { |
| 792 | 830 | /// An opaque type. |
| 793 | 831 | /// data is index of Key.OpaqueType in extra. |
| 794 | 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 | 842 | /// A value that can be represented with only an enum tag. |
| 797 | 843 | /// data is SimpleValue enum value. |
| 798 | 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 | 845 | /// A pointer to an integer value. |
| 806 | 846 | /// data is extra index of PtrInt, which contains the type and address. |
| 807 | 847 | /// Only pointer types are allowed to have this encoding. Optional types must use |
| ... | ... | @@ -809,6 +849,8 @@ pub const Tag = enum(u8) { |
| 809 | 849 | ptr_int, |
| 810 | 850 | /// An optional value that is non-null. |
| 811 | 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 | 854 | opt_payload, |
| 813 | 855 | /// An optional value that is null. |
| 814 | 856 | /// data is Index of the payload type. |
| ... | ... | @@ -859,6 +901,13 @@ pub const Tag = enum(u8) { |
| 859 | 901 | extern_func, |
| 860 | 902 | /// A regular function. |
| 861 | 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 | 913 | /// Having `SimpleType` and `SimpleValue` in separate enums makes it easier to |
| ... | ... | @@ -912,9 +961,12 @@ pub const SimpleType = enum(u32) { |
| 912 | 961 | }; |
| 913 | 962 | |
| 914 | 963 | pub const SimpleValue = enum(u32) { |
| 964 | /// This is untyped `undefined`. | |
| 915 | 965 | undefined, |
| 916 | 966 | void, |
| 967 | /// This is untyped `null`. | |
| 917 | 968 | null, |
| 969 | /// This is the untyped empty struct literal: `.{}` | |
| 918 | 970 | empty_struct, |
| 919 | 971 | true, |
| 920 | 972 | false, |
| ... | ... | @@ -923,12 +975,6 @@ pub const SimpleValue = enum(u32) { |
| 923 | 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 | 978 | pub const Pointer = struct { |
| 933 | 979 | child: Index, |
| 934 | 980 | sentinel: Index, |
| ... | ... | @@ -1005,7 +1051,7 @@ pub const ErrorUnion = struct { |
| 1005 | 1051 | /// 0. field name: null-terminated string index for each fields_len; declaration order |
| 1006 | 1052 | pub const EnumSimple = struct { |
| 1007 | 1053 | /// The Decl that corresponds to the enum itself. |
| 1008 | decl: DeclIndex, | |
| 1054 | decl: Module.Decl.Index, | |
| 1009 | 1055 | /// An integer type which is used for the numerical value of the enum. This |
| 1010 | 1056 | /// is inferred by Zig to be the smallest power of two unsigned int that |
| 1011 | 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 | 1137 | ip.items.deinit(gpa); |
| 1092 | 1138 | ip.extra.deinit(gpa); |
| 1093 | 1139 | ip.limbs.deinit(gpa); |
| 1140 | ||
| 1141 | ip.structs_free_list.deinit(gpa); | |
| 1142 | ip.allocated_structs.deinit(gpa); | |
| 1143 | ||
| 1094 | 1144 | ip.* = undefined; |
| 1095 | 1145 | } |
| 1096 | 1146 | |
| ... | ... | @@ -1167,20 +1217,38 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { |
| 1167 | 1217 | .type_enum_simple => @panic("TODO"), |
| 1168 | 1218 | |
| 1169 | 1219 | .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) }, |
| 1170 | ||
| 1171 | .simple_internal => switch (@intToEnum(SimpleInternal, data)) { | |
| 1172 | .type_empty_struct => .{ .struct_type = .{ | |
| 1173 | .fields_len = 0, | |
| 1174 | } }, | |
| 1220 | .type_struct => { | |
| 1221 | const struct_index = @intToEnum(Module.Struct.OptionalIndex, data); | |
| 1222 | const namespace = if (struct_index.unwrap()) |i| | |
| 1223 | ip.structPtrConst(i).namespace.toOptional() | |
| 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 | 1236 | .opt_null => .{ .opt = .{ |
| 1177 | 1237 | .ty = @intToEnum(Index, data), |
| 1178 | 1238 | .val = .none, |
| 1179 | 1239 | } }, |
| 1180 | .opt_payload => .{ .opt = .{ | |
| 1181 | .ty = indexToKey(ip, @intToEnum(Index, data)).typeOf(), | |
| 1182 | .val = @intToEnum(Index, data), | |
| 1183 | } }, | |
| 1240 | .opt_payload => { | |
| 1241 | const payload_val = @intToEnum(Index, data); | |
| 1242 | // The existence of `opt_payload` guarantees that the optional type will be | |
| 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 | 1252 | .ptr_int => { |
| 1185 | 1253 | const info = ip.extraData(PtrInt, data); |
| 1186 | 1254 | return .{ .ptr = .{ |
| ... | ... | @@ -1225,6 +1293,16 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { |
| 1225 | 1293 | .float_f128 => @panic("TODO"), |
| 1226 | 1294 | .extern_func => @panic("TODO"), |
| 1227 | 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 | 1437 | }, |
| 1360 | 1438 | |
| 1361 | 1439 | .struct_type => |struct_type| { |
| 1362 | if (struct_type.fields_len != 0) { | |
| 1363 | @panic("TODO"); // handle structs other than empty_struct | |
| 1364 | } | |
| 1365 | ip.items.appendAssumeCapacity(.{ | |
| 1366 | .tag = .simple_internal, | |
| 1367 | .data = @enumToInt(SimpleInternal.type_empty_struct), | |
| 1440 | ip.items.appendAssumeCapacity(if (struct_type.index.unwrap()) |i| .{ | |
| 1441 | .tag = .type_struct, | |
| 1442 | .data = @enumToInt(i), | |
| 1443 | } else if (struct_type.namespace.unwrap()) |i| .{ | |
| 1444 | .tag = .type_struct_ns, | |
| 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 | 1479 | |
| 1399 | 1480 | .opt => |opt| { |
| 1400 | 1481 | assert(opt.ty != .none); |
| 1482 | assert(ip.isOptionalType(opt.ty)); | |
| 1401 | 1483 | ip.items.appendAssumeCapacity(if (opt.val == .none) .{ |
| 1402 | 1484 | .tag = .opt_null, |
| 1403 | 1485 | .data = @enumToInt(opt.ty), |
| ... | ... | @@ -1549,10 +1631,35 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 1549 | 1631 | const tag: Tag = if (enum_tag.tag.positive) .enum_tag_positive else .enum_tag_negative; |
| 1550 | 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 | 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 | 1663 | fn addInt(ip: *InternPool, gpa: Allocator, ty: Index, tag: Tag, limbs: []const Limb) !void { |
| 1557 | 1664 | const limbs_len = @intCast(u32, limbs.len); |
| 1558 | 1665 | try ip.reserveLimbs(gpa, @typeInfo(Int).Struct.fields.len + limbs_len); |
| ... | ... | @@ -1578,8 +1685,8 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 { |
| 1578 | 1685 | ip.extra.appendAssumeCapacity(switch (field.type) { |
| 1579 | 1686 | u32 => @field(extra, field.name), |
| 1580 | 1687 | Index => @enumToInt(@field(extra, field.name)), |
| 1581 | DeclIndex => @enumToInt(@field(extra, field.name)), | |
| 1582 | NamespaceIndex => @enumToInt(@field(extra, field.name)), | |
| 1688 | Module.Decl.Index => @enumToInt(@field(extra, field.name)), | |
| 1689 | Module.Namespace.Index => @enumToInt(@field(extra, field.name)), | |
| 1583 | 1690 | i32 => @bitCast(u32, @field(extra, field.name)), |
| 1584 | 1691 | Pointer.Flags => @bitCast(u32, @field(extra, field.name)), |
| 1585 | 1692 | Pointer.PackedOffset => @bitCast(u32, @field(extra, field.name)), |
| ... | ... | @@ -1635,8 +1742,8 @@ fn extraData(ip: InternPool, comptime T: type, index: usize) T { |
| 1635 | 1742 | @field(result, field.name) = switch (field.type) { |
| 1636 | 1743 | u32 => int32, |
| 1637 | 1744 | Index => @intToEnum(Index, int32), |
| 1638 | DeclIndex => @intToEnum(DeclIndex, int32), | |
| 1639 | NamespaceIndex => @intToEnum(NamespaceIndex, int32), | |
| 1745 | Module.Decl.Index => @intToEnum(Module.Decl.Index, int32), | |
| 1746 | Module.Namespace.Index => @intToEnum(Module.Namespace.Index, int32), | |
| 1640 | 1747 | i32 => @bitCast(i32, int32), |
| 1641 | 1748 | Pointer.Flags => @bitCast(Pointer.Flags, int32), |
| 1642 | 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 | 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 | 1932 | pub fn dump(ip: InternPool) void { |
| 1812 | 1933 | dumpFallible(ip, std.heap.page_allocator) catch return; |
| 1813 | 1934 | } |
| ... | ... | @@ -1859,9 +1980,10 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { |
| 1859 | 1980 | .type_error_union => @sizeOf(ErrorUnion), |
| 1860 | 1981 | .type_enum_simple => @sizeOf(EnumSimple), |
| 1861 | 1982 | .type_opaque => @sizeOf(Key.OpaqueType), |
| 1983 | .type_struct => 0, | |
| 1984 | .type_struct_ns => 0, | |
| 1862 | 1985 | .simple_type => 0, |
| 1863 | 1986 | .simple_value => 0, |
| 1864 | .simple_internal => 0, | |
| 1865 | 1987 | .ptr_int => @sizeOf(PtrInt), |
| 1866 | 1988 | .opt_null => 0, |
| 1867 | 1989 | .opt_payload => 0, |
| ... | ... | @@ -1887,6 +2009,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { |
| 1887 | 2009 | .float_f128 => @sizeOf(Float128), |
| 1888 | 2010 | .extern_func => @panic("TODO"), |
| 1889 | 2011 | .func => @panic("TODO"), |
| 2012 | .only_possible_value => 0, | |
| 1890 | 2013 | }); |
| 1891 | 2014 | } |
| 1892 | 2015 | const SortContext = struct { |
| ... | ... | @@ -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 | 839 | |
| 840 | 840 | /// If the Decl has a value and it is a struct, return it, |
| 841 | 841 | /// otherwise null. |
| 842 | pub fn getStruct(decl: *Decl) ?*Struct { | |
| 843 | if (!decl.owns_tv) return null; | |
| 844 | const ty = (decl.val.castTag(.ty) orelse return null).data; | |
| 845 | const struct_obj = (ty.castTag(.@"struct") orelse return null).data; | |
| 846 | return struct_obj; | |
| 842 | pub fn getStruct(decl: *Decl, mod: *Module) ?*Struct { | |
| 843 | return mod.structPtrUnwrap(getStructIndex(decl, mod)); | |
| 844 | } | |
| 845 | ||
| 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 | 852 | /// If the Decl has a value and it is a union, return it, |
| ... | ... | @@ -884,32 +887,29 @@ pub const Decl = struct { |
| 884 | 887 | /// Only returns it if the Decl is the owner. |
| 885 | 888 | pub fn getInnerNamespaceIndex(decl: *Decl, mod: *Module) Namespace.OptionalIndex { |
| 886 | 889 | if (!decl.owns_tv) return .none; |
| 887 | if (decl.val.ip_index == .none) { | |
| 888 | const ty = (decl.val.castTag(.ty) orelse return .none).data; | |
| 889 | switch (ty.tag()) { | |
| 890 | .@"struct" => { | |
| 891 | const struct_obj = ty.castTag(.@"struct").?.data; | |
| 892 | return struct_obj.namespace.toOptional(); | |
| 893 | }, | |
| 894 | .enum_full, .enum_nonexhaustive => { | |
| 895 | const enum_obj = ty.cast(Type.Payload.EnumFull).?.data; | |
| 896 | return enum_obj.namespace.toOptional(); | |
| 897 | }, | |
| 898 | .empty_struct => { | |
| 899 | @panic("TODO"); | |
| 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 | }, | |
| 890 | switch (decl.val.ip_index) { | |
| 891 | .empty_struct_type => return .none, | |
| 892 | .none => { | |
| 893 | const ty = (decl.val.castTag(.ty) orelse return .none).data; | |
| 894 | switch (ty.tag()) { | |
| 895 | .enum_full, .enum_nonexhaustive => { | |
| 896 | const enum_obj = ty.cast(Type.Payload.EnumFull).?.data; | |
| 897 | return enum_obj.namespace.toOptional(); | |
| 898 | }, | |
| 899 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 900 | const union_obj = ty.cast(Type.Payload.Union).?.data; | |
| 901 | return union_obj.namespace.toOptional(); | |
| 902 | }, | |
| 905 | 903 | |
| 906 | else => return .none, | |
| 907 | } | |
| 904 | else => return .none, | |
| 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 | 915 | /// Same as `getInnerNamespaceIndex` but additionally obtains the pointer. |
| ... | ... | @@ -1046,6 +1046,28 @@ pub const Struct = struct { |
| 1046 | 1046 | is_tuple: bool, |
| 1047 | 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 | 1071 | pub const Fields = std.StringArrayHashMapUnmanaged(Field); |
| 1050 | 1072 | |
| 1051 | 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 | 1133 | } |
| 1112 | 1134 | |
| 1113 | 1135 | pub fn srcLoc(s: Struct, mod: *Module) SrcLoc { |
| 1114 | const owner_decl = mod.declPtr(s.owner_decl); | |
| 1115 | return .{ | |
| 1116 | .file_scope = owner_decl.getFileScope(mod), | |
| 1117 | .parent_decl_node = owner_decl.src_node, | |
| 1118 | .lazy = LazySrcLoc.nodeOffset(0), | |
| 1119 | }; | |
| 1136 | return mod.declPtr(s.owner_decl).srcLoc(mod); | |
| 1120 | 1137 | } |
| 1121 | 1138 | |
| 1122 | 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 | 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 | 3652 | /// Returns true if and only if the Decl is the top level struct associated with a File. |
| 3626 | 3653 | pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool { |
| 3627 | 3654 | const decl = mod.declPtr(decl_index); |
| ... | ... | @@ -4078,7 +4105,7 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void { |
| 4078 | 4105 | |
| 4079 | 4106 | if (!decl.owns_tv) continue; |
| 4080 | 4107 | |
| 4081 | if (decl.getStruct()) |struct_obj| { | |
| 4108 | if (decl.getStruct(mod)) |struct_obj| { | |
| 4082 | 4109 | struct_obj.zir_index = inst_map.get(struct_obj.zir_index) orelse { |
| 4083 | 4110 | try file.deleted_decls.append(gpa, decl_index); |
| 4084 | 4111 | continue; |
| ... | ... | @@ -4597,36 +4624,50 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 4597 | 4624 | errdefer new_decl_arena.deinit(); |
| 4598 | 4625 | const new_decl_arena_allocator = new_decl_arena.allocator(); |
| 4599 | 4626 | |
| 4600 | const struct_obj = try new_decl_arena_allocator.create(Module.Struct); | |
| 4601 | const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj); | |
| 4602 | const struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty); | |
| 4603 | const ty_ty = comptime Type.type; | |
| 4604 | struct_obj.* = .{ | |
| 4605 | .owner_decl = undefined, // set below | |
| 4627 | // Because these three things each reference each other, `undefined` | |
| 4628 | // placeholders are used before being set after the struct type gains an | |
| 4629 | // InternPool index. | |
| 4630 | const new_namespace_index = try mod.createNamespace(.{ | |
| 4631 | .parent = .none, | |
| 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 | 4644 | .fields = .{}, |
| 4607 | 4645 | .zir_index = undefined, // set below |
| 4608 | 4646 | .layout = .Auto, |
| 4609 | 4647 | .status = .none, |
| 4610 | 4648 | .known_non_opv = undefined, |
| 4611 | 4649 | .is_tuple = undefined, // set below |
| 4612 | .namespace = try mod.createNamespace(.{ | |
| 4613 | .parent = .none, | |
| 4614 | .ty = struct_ty, | |
| 4615 | .file_scope = file, | |
| 4616 | }), | |
| 4617 | }; | |
| 4618 | const new_decl_index = try mod.allocateNewDecl(struct_obj.namespace, 0, null); | |
| 4619 | const new_decl = mod.declPtr(new_decl_index); | |
| 4650 | .namespace = new_namespace_index, | |
| 4651 | }); | |
| 4652 | errdefer mod.destroyStruct(struct_index); | |
| 4653 | ||
| 4654 | const struct_ty = try mod.intern_pool.get(gpa, .{ .struct_type = .{ | |
| 4655 | .index = struct_index.toOptional(), | |
| 4656 | .namespace = new_namespace_index.toOptional(), | |
| 4657 | } }); | |
| 4658 | errdefer mod.intern_pool.remove(struct_ty); | |
| 4659 | ||
| 4660 | new_namespace.ty = struct_ty.toType(); | |
| 4620 | 4661 | file.root_decl = new_decl_index.toOptional(); |
| 4621 | struct_obj.owner_decl = new_decl_index; | |
| 4662 | ||
| 4622 | 4663 | new_decl.name = try file.fullyQualifiedNameZ(gpa); |
| 4623 | 4664 | new_decl.src_line = 0; |
| 4624 | 4665 | new_decl.is_pub = true; |
| 4625 | 4666 | new_decl.is_exported = false; |
| 4626 | 4667 | new_decl.has_align = false; |
| 4627 | 4668 | new_decl.has_linksection_or_addrspace = false; |
| 4628 | new_decl.ty = ty_ty; | |
| 4629 | new_decl.val = struct_val; | |
| 4669 | new_decl.ty = Type.type; | |
| 4670 | new_decl.val = struct_ty.toValue(); | |
| 4630 | 4671 | new_decl.@"align" = 0; |
| 4631 | 4672 | new_decl.@"linksection" = null; |
| 4632 | 4673 | new_decl.has_tv = true; |
| ... | ... | @@ -4639,6 +4680,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 4639 | 4680 | if (file.status == .success_zir) { |
| 4640 | 4681 | assert(file.zir_loaded); |
| 4641 | 4682 | const main_struct_inst = Zir.main_struct_inst; |
| 4683 | const struct_obj = mod.structPtr(struct_index); | |
| 4642 | 4684 | struct_obj.zir_index = main_struct_inst; |
| 4643 | 4685 | const extended = file.zir.instructions.items(.data)[main_struct_inst].extended; |
| 4644 | 4686 | const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small); |
| ... | ... | @@ -4665,7 +4707,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 4665 | 4707 | var wip_captures = try WipCaptureScope.init(gpa, new_decl_arena_allocator, null); |
| 4666 | 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 | 4711 | try wip_captures.finalize(); |
| 4670 | 4712 | new_decl.analysis = .complete; |
| 4671 | 4713 | } else |err| switch (err) { |
| ... | ... | @@ -4761,11 +4803,12 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4761 | 4803 | if (mod.declIsRoot(decl_index)) { |
| 4762 | 4804 | log.debug("semaDecl root {*} ({s})", .{ decl, decl.name }); |
| 4763 | 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 | 4808 | // This might not have gotten set in `semaFile` if the first time had |
| 4766 | 4809 | // a ZIR failure, so we set it here in case. |
| 4767 | 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 | 4812 | decl.analysis = .complete; |
| 4770 | 4813 | decl.generation = mod.generation; |
| 4771 | 4814 | return false; |
| ... | ... | @@ -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 | 6024 | pub fn allocateNewDecl( |
| 5974 | 6025 | mod: *Module, |
| 5975 | 6026 | namespace: Namespace.Index, |
| ... | ... | @@ -7202,12 +7253,7 @@ pub fn atomicPtrAlignment( |
| 7202 | 7253 | } |
| 7203 | 7254 | |
| 7204 | 7255 | pub fn opaqueSrcLoc(mod: *Module, opaque_type: InternPool.Key.OpaqueType) SrcLoc { |
| 7205 | const owner_decl = mod.declPtr(opaque_type.decl); | |
| 7206 | return .{ | |
| 7207 | .file_scope = owner_decl.getFileScope(mod), | |
| 7208 | .parent_decl_node = owner_decl.src_node, | |
| 7209 | .lazy = LazySrcLoc.nodeOffset(0), | |
| 7210 | }; | |
| 7256 | return mod.declPtr(opaque_type.decl).srcLoc(mod); | |
| 7211 | 7257 | } |
| 7212 | 7258 | |
| 7213 | 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 | 7267 | pub fn namespaceDeclIndex(mod: *Module, namespace_index: Namespace.Index) Decl.Index { |
| 7222 | 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 | 2090 | } |
| 2091 | 2091 | |
| 2092 | 2092 | fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazySrcLoc, container_ty: Type, field_index: usize) CompileError { |
| 2093 | const mod = sema.mod; | |
| 2093 | 2094 | const msg = msg: { |
| 2094 | 2095 | const msg = try sema.errMsg(block, init_src, "value stored in comptime field does not match the default value of the field", .{}); |
| 2095 | 2096 | errdefer msg.destroy(sema.gpa); |
| 2096 | 2097 | |
| 2097 | const struct_ty = container_ty.castTag(.@"struct") orelse break :msg msg; | |
| 2098 | const default_value_src = struct_ty.data.fieldSrcLoc(sema.mod, .{ | |
| 2098 | const struct_ty = mod.typeToStruct(container_ty) orelse break :msg msg; | |
| 2099 | const default_value_src = struct_ty.fieldSrcLoc(mod, .{ | |
| 2099 | 2100 | .index = field_index, |
| 2100 | 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 | 2104 | break :msg msg; |
| 2104 | 2105 | }; |
| 2105 | 2106 | return sema.failWithOwnedErrorMsg(msg); |
| ... | ... | @@ -2632,8 +2633,10 @@ pub fn analyzeStructDecl( |
| 2632 | 2633 | sema: *Sema, |
| 2633 | 2634 | new_decl: *Decl, |
| 2634 | 2635 | inst: Zir.Inst.Index, |
| 2635 | struct_obj: *Module.Struct, | |
| 2636 | struct_index: Module.Struct.Index, | |
| 2636 | 2637 | ) SemaError!void { |
| 2638 | const mod = sema.mod; | |
| 2639 | const struct_obj = mod.structPtr(struct_index); | |
| 2637 | 2640 | const extended = sema.code.instructions.items(.data)[inst].extended; |
| 2638 | 2641 | assert(extended.opcode == .struct_decl); |
| 2639 | 2642 | const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small); |
| ... | ... | @@ -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 | 2671 | fn zirStructDecl( |
| ... | ... | @@ -2671,28 +2674,38 @@ fn zirStructDecl( |
| 2671 | 2674 | extended: Zir.Inst.Extended.InstData, |
| 2672 | 2675 | inst: Zir.Inst.Index, |
| 2673 | 2676 | ) CompileError!Air.Inst.Ref { |
| 2677 | const mod = sema.mod; | |
| 2678 | const gpa = sema.gpa; | |
| 2674 | 2679 | const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small); |
| 2675 | 2680 | const src: LazySrcLoc = if (small.has_src_node) blk: { |
| 2676 | 2681 | const node_offset = @bitCast(i32, sema.code.extra[extended.operand]); |
| 2677 | 2682 | break :blk LazySrcLoc.nodeOffset(node_offset); |
| 2678 | 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 | 2686 | errdefer new_decl_arena.deinit(); |
| 2682 | const new_decl_arena_allocator = new_decl_arena.allocator(); | |
| 2683 | 2687 | |
| 2684 | const mod = sema.mod; | |
| 2685 | const struct_obj = try new_decl_arena_allocator.create(Module.Struct); | |
| 2686 | const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj); | |
| 2687 | const struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty); | |
| 2688 | // Because these three things each reference each other, `undefined` | |
| 2689 | // placeholders are used before being set after the struct type gains an | |
| 2690 | // InternPool index. | |
| 2691 | ||
| 2688 | 2692 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ |
| 2689 | 2693 | .ty = Type.type, |
| 2690 | .val = struct_val, | |
| 2694 | .val = undefined, | |
| 2691 | 2695 | }, small.name_strategy, "struct", inst); |
| 2692 | 2696 | const new_decl = mod.declPtr(new_decl_index); |
| 2693 | 2697 | new_decl.owns_tv = true; |
| 2694 | 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 | 2709 | .owner_decl = new_decl_index, |
| 2697 | 2710 | .fields = .{}, |
| 2698 | 2711 | .zir_index = inst, |
| ... | ... | @@ -2700,13 +2713,20 @@ fn zirStructDecl( |
| 2700 | 2713 | .status = .none, |
| 2701 | 2714 | .known_non_opv = undefined, |
| 2702 | 2715 | .is_tuple = small.is_tuple, |
| 2703 | .namespace = try mod.createNamespace(.{ | |
| 2704 | .parent = block.namespace.toOptional(), | |
| 2705 | .ty = struct_ty, | |
| 2706 | .file_scope = block.getFileScope(mod), | |
| 2707 | }), | |
| 2708 | }; | |
| 2709 | try sema.analyzeStructDecl(new_decl, inst, struct_obj); | |
| 2716 | .namespace = new_namespace_index, | |
| 2717 | }); | |
| 2718 | errdefer mod.destroyStruct(struct_index); | |
| 2719 | ||
| 2720 | const struct_ty = try mod.intern_pool.get(gpa, .{ .struct_type = .{ | |
| 2721 | .index = struct_index.toOptional(), | |
| 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 | 2730 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 2711 | 2731 | return sema.analyzeDeclVal(block, src, new_decl_index); |
| 2712 | 2732 | } |
| ... | ... | @@ -2721,6 +2741,7 @@ fn createAnonymousDeclTypeNamed( |
| 2721 | 2741 | inst: ?Zir.Inst.Index, |
| 2722 | 2742 | ) !Decl.Index { |
| 2723 | 2743 | const mod = sema.mod; |
| 2744 | const gpa = sema.gpa; | |
| 2724 | 2745 | const namespace = block.namespace; |
| 2725 | 2746 | const src_scope = block.wip_capture_scope; |
| 2726 | 2747 | const src_decl = mod.declPtr(block.src_decl); |
| ... | ... | @@ -2736,16 +2757,16 @@ fn createAnonymousDeclTypeNamed( |
| 2736 | 2757 | // semantically analyzed. |
| 2737 | 2758 | // This name is also used as the key in the parent namespace so it cannot be |
| 2738 | 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 | 2761 | src_decl.name, anon_prefix, @enumToInt(new_decl_index), |
| 2741 | 2762 | }); |
| 2742 | errdefer sema.gpa.free(name); | |
| 2763 | errdefer gpa.free(name); | |
| 2743 | 2764 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); |
| 2744 | 2765 | return new_decl_index; |
| 2745 | 2766 | }, |
| 2746 | 2767 | .parent => { |
| 2747 | const name = try sema.gpa.dupeZ(u8, mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0)); | |
| 2748 | errdefer sema.gpa.free(name); | |
| 2768 | const name = try gpa.dupeZ(u8, mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0)); | |
| 2769 | errdefer gpa.free(name); | |
| 2749 | 2770 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); |
| 2750 | 2771 | return new_decl_index; |
| 2751 | 2772 | }, |
| ... | ... | @@ -2753,7 +2774,7 @@ fn createAnonymousDeclTypeNamed( |
| 2753 | 2774 | const fn_info = sema.code.getFnInfo(sema.func.?.zir_body_inst); |
| 2754 | 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 | 2778 | defer buf.deinit(); |
| 2758 | 2779 | try buf.appendSlice(mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0)); |
| 2759 | 2780 | try buf.appendSlice("("); |
| ... | ... | @@ -2781,7 +2802,7 @@ fn createAnonymousDeclTypeNamed( |
| 2781 | 2802 | |
| 2782 | 2803 | try buf.appendSlice(")"); |
| 2783 | 2804 | const name = try buf.toOwnedSliceSentinel(0); |
| 2784 | errdefer sema.gpa.free(name); | |
| 2805 | errdefer gpa.free(name); | |
| 2785 | 2806 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); |
| 2786 | 2807 | return new_decl_index; |
| 2787 | 2808 | }, |
| ... | ... | @@ -2794,10 +2815,10 @@ fn createAnonymousDeclTypeNamed( |
| 2794 | 2815 | .dbg_var_ptr, .dbg_var_val => { |
| 2795 | 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 | 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 | 2823 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); |
| 2803 | 2824 | return new_decl_index; |
| ... | ... | @@ -3216,13 +3237,13 @@ fn zirOpaqueDecl( |
| 3216 | 3237 | .file_scope = block.getFileScope(mod), |
| 3217 | 3238 | }); |
| 3218 | 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 | 3242 | const opaque_ty = try mod.intern_pool.get(gpa, .{ .opaque_type = .{ |
| 3222 | 3243 | .decl = new_decl_index, |
| 3223 | 3244 | .namespace = new_namespace_index, |
| 3224 | 3245 | } }); |
| 3225 | errdefer @panic("TODO error handling"); | |
| 3246 | errdefer mod.intern_pool.remove(opaque_ty); | |
| 3226 | 3247 | |
| 3227 | 3248 | new_decl.val = opaque_ty.toValue(); |
| 3228 | 3249 | new_namespace.ty = opaque_ty.toType(); |
| ... | ... | @@ -3960,7 +3981,7 @@ fn zirArrayBasePtr( |
| 3960 | 3981 | const elem_ty = sema.typeOf(base_ptr).childType(mod); |
| 3961 | 3982 | switch (elem_ty.zigTypeTag(mod)) { |
| 3962 | 3983 | .Array, .Vector => return base_ptr, |
| 3963 | .Struct => if (elem_ty.isTuple()) { | |
| 3984 | .Struct => if (elem_ty.isTuple(mod)) { | |
| 3964 | 3985 | // TODO validate element count |
| 3965 | 3986 | return base_ptr; |
| 3966 | 3987 | }, |
| ... | ... | @@ -4150,7 +4171,7 @@ fn validateArrayInitTy( |
| 4150 | 4171 | } |
| 4151 | 4172 | return; |
| 4152 | 4173 | }, |
| 4153 | .Struct => if (ty.isTuple()) { | |
| 4174 | .Struct => if (ty.isTuple(mod)) { | |
| 4154 | 4175 | _ = try sema.resolveTypeFields(ty); |
| 4155 | 4176 | const array_len = ty.arrayLen(mod); |
| 4156 | 4177 | if (extra.init_count > array_len) { |
| ... | ... | @@ -4358,7 +4379,7 @@ fn validateStructInit( |
| 4358 | 4379 | const gpa = sema.gpa; |
| 4359 | 4380 | |
| 4360 | 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 | 4383 | defer gpa.free(found_fields); |
| 4363 | 4384 | @memset(found_fields, 0); |
| 4364 | 4385 | |
| ... | ... | @@ -4370,7 +4391,7 @@ fn validateStructInit( |
| 4370 | 4391 | const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data; |
| 4371 | 4392 | struct_ptr_zir_ref = field_ptr_extra.lhs; |
| 4372 | 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 | 4395 | try sema.tupleFieldIndex(block, struct_ty, field_name, field_src) |
| 4375 | 4396 | else |
| 4376 | 4397 | try sema.structFieldIndex(block, struct_ty, field_name, field_src); |
| ... | ... | @@ -4403,9 +4424,9 @@ fn validateStructInit( |
| 4403 | 4424 | for (found_fields, 0..) |field_ptr, i| { |
| 4404 | 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 | 4428 | if (default_val.ip_index == .unreachable_value) { |
| 4408 | if (struct_ty.isTuple()) { | |
| 4429 | if (struct_ty.isTuple(mod)) { | |
| 4409 | 4430 | const template = "missing tuple field with index {d}"; |
| 4410 | 4431 | if (root_msg) |msg| { |
| 4411 | 4432 | try sema.errNote(block, init_src, msg, template, .{i}); |
| ... | ... | @@ -4414,7 +4435,7 @@ fn validateStructInit( |
| 4414 | 4435 | } |
| 4415 | 4436 | continue; |
| 4416 | 4437 | } |
| 4417 | const field_name = struct_ty.structFieldName(i); | |
| 4438 | const field_name = struct_ty.structFieldName(i, mod); | |
| 4418 | 4439 | const template = "missing struct field: {s}"; |
| 4419 | 4440 | const args = .{field_name}; |
| 4420 | 4441 | if (root_msg) |msg| { |
| ... | ... | @@ -4426,7 +4447,7 @@ fn validateStructInit( |
| 4426 | 4447 | } |
| 4427 | 4448 | |
| 4428 | 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 | 4451 | try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true) |
| 4431 | 4452 | else |
| 4432 | 4453 | try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true); |
| ... | ... | @@ -4436,11 +4457,11 @@ fn validateStructInit( |
| 4436 | 4457 | } |
| 4437 | 4458 | |
| 4438 | 4459 | if (root_msg) |msg| { |
| 4439 | if (struct_ty.castTag(.@"struct")) |struct_obj| { | |
| 4440 | const fqn = try struct_obj.data.getFullyQualifiedName(mod); | |
| 4460 | if (mod.typeToStruct(struct_ty)) |struct_obj| { | |
| 4461 | const fqn = try struct_obj.getFullyQualifiedName(mod); | |
| 4441 | 4462 | defer gpa.free(fqn); |
| 4442 | 4463 | try mod.errNoteNonLazy( |
| 4443 | struct_obj.data.srcLoc(mod), | |
| 4464 | struct_obj.srcLoc(mod), | |
| 4444 | 4465 | msg, |
| 4445 | 4466 | "struct '{s}' declared here", |
| 4446 | 4467 | .{fqn}, |
| ... | ... | @@ -4463,12 +4484,12 @@ fn validateStructInit( |
| 4463 | 4484 | |
| 4464 | 4485 | // We collect the comptime field values in case the struct initialization |
| 4465 | 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 | 4489 | field: for (found_fields, 0..) |field_ptr, i| { |
| 4469 | 4490 | if (field_ptr != 0) { |
| 4470 | 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 | 4493 | if (try sema.typeHasOnePossibleValue(field_ty)) |opv| { |
| 4473 | 4494 | field_values[i] = opv; |
| 4474 | 4495 | continue; |
| ... | ... | @@ -4548,9 +4569,9 @@ fn validateStructInit( |
| 4548 | 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 | 4573 | if (default_val.ip_index == .unreachable_value) { |
| 4553 | if (struct_ty.isTuple()) { | |
| 4574 | if (struct_ty.isTuple(mod)) { | |
| 4554 | 4575 | const template = "missing tuple field with index {d}"; |
| 4555 | 4576 | if (root_msg) |msg| { |
| 4556 | 4577 | try sema.errNote(block, init_src, msg, template, .{i}); |
| ... | ... | @@ -4559,7 +4580,7 @@ fn validateStructInit( |
| 4559 | 4580 | } |
| 4560 | 4581 | continue; |
| 4561 | 4582 | } |
| 4562 | const field_name = struct_ty.structFieldName(i); | |
| 4583 | const field_name = struct_ty.structFieldName(i, mod); | |
| 4563 | 4584 | const template = "missing struct field: {s}"; |
| 4564 | 4585 | const args = .{field_name}; |
| 4565 | 4586 | if (root_msg) |msg| { |
| ... | ... | @@ -4573,11 +4594,11 @@ fn validateStructInit( |
| 4573 | 4594 | } |
| 4574 | 4595 | |
| 4575 | 4596 | if (root_msg) |msg| { |
| 4576 | if (struct_ty.castTag(.@"struct")) |struct_obj| { | |
| 4577 | const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod); | |
| 4597 | if (mod.typeToStruct(struct_ty)) |struct_obj| { | |
| 4598 | const fqn = try struct_obj.getFullyQualifiedName(sema.mod); | |
| 4578 | 4599 | defer gpa.free(fqn); |
| 4579 | 4600 | try sema.mod.errNoteNonLazy( |
| 4580 | struct_obj.data.srcLoc(sema.mod), | |
| 4601 | struct_obj.srcLoc(sema.mod), | |
| 4581 | 4602 | msg, |
| 4582 | 4603 | "struct '{s}' declared here", |
| 4583 | 4604 | .{fqn}, |
| ... | ... | @@ -4605,7 +4626,7 @@ fn validateStructInit( |
| 4605 | 4626 | if (field_ptr != 0) continue; |
| 4606 | 4627 | |
| 4607 | 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 | 4630 | try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true) |
| 4610 | 4631 | else |
| 4611 | 4632 | try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true); |
| ... | ... | @@ -4638,7 +4659,7 @@ fn zirValidateArrayInit( |
| 4638 | 4659 | |
| 4639 | 4660 | var i = instrs.len; |
| 4640 | 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 | 4663 | if (default_val.ip_index == .unreachable_value) { |
| 4643 | 4664 | const template = "missing tuple field with index {d}"; |
| 4644 | 4665 | if (root_msg) |msg| { |
| ... | ... | @@ -4698,7 +4719,7 @@ fn zirValidateArrayInit( |
| 4698 | 4719 | outer: for (instrs, 0..) |elem_ptr, i| { |
| 4699 | 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 | 4723 | if (try array_ty.structFieldValueComptime(mod, i)) |opv| { |
| 4703 | 4724 | element_vals[i] = opv; |
| 4704 | 4725 | continue; |
| ... | ... | @@ -7950,7 +7971,7 @@ fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 7950 | 7971 | const indexable_ty = try sema.resolveType(block, .unneeded, bin.lhs); |
| 7951 | 7972 | assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction |
| 7952 | 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 | 7975 | return sema.addType(elem_type); |
| 7955 | 7976 | } else { |
| 7956 | 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 | 9843 | }; |
| 9823 | 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 | 9847 | const container = switch (dest_ty.zigTypeTag(mod)) { |
| 9827 | 9848 | .Struct => "struct", |
| 9828 | 9849 | .Union => "union", |
| ... | ... | @@ -9885,7 +9906,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9885 | 9906 | }; |
| 9886 | 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 | 9910 | const container = switch (operand_ty.zigTypeTag(mod)) { |
| 9890 | 9911 | .Struct => "struct", |
| 9891 | 9912 | .Union => "union", |
| ... | ... | @@ -12041,12 +12062,12 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12041 | 12062 | if (mem.eql(u8, name, field_name)) break true; |
| 12042 | 12063 | } else false; |
| 12043 | 12064 | } |
| 12044 | if (ty.isTuple()) { | |
| 12065 | if (ty.isTuple(mod)) { | |
| 12045 | 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 | 12069 | break :hf switch (ty.zigTypeTag(mod)) { |
| 12049 | .Struct => ty.structFields().contains(field_name), | |
| 12070 | .Struct => ty.structFields(mod).contains(field_name), | |
| 12050 | 12071 | .Union => ty.unionFields().contains(field_name), |
| 12051 | 12072 | .Enum => ty.enumFields().contains(field_name), |
| 12052 | 12073 | .Array => mem.eql(u8, field_name, "len"), |
| ... | ... | @@ -12601,14 +12622,15 @@ fn analyzeTupleCat( |
| 12601 | 12622 | lhs: Air.Inst.Ref, |
| 12602 | 12623 | rhs: Air.Inst.Ref, |
| 12603 | 12624 | ) CompileError!Air.Inst.Ref { |
| 12625 | const mod = sema.mod; | |
| 12604 | 12626 | const lhs_ty = sema.typeOf(lhs); |
| 12605 | 12627 | const rhs_ty = sema.typeOf(rhs); |
| 12606 | 12628 | const src = LazySrcLoc.nodeOffset(src_node); |
| 12607 | 12629 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node }; |
| 12608 | 12630 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node }; |
| 12609 | 12631 | |
| 12610 | const lhs_len = lhs_ty.structFieldCount(); | |
| 12611 | const rhs_len = rhs_ty.structFieldCount(); | |
| 12632 | const lhs_len = lhs_ty.structFieldCount(mod); | |
| 12633 | const rhs_len = rhs_ty.structFieldCount(mod); | |
| 12612 | 12634 | const dest_fields = lhs_len + rhs_len; |
| 12613 | 12635 | |
| 12614 | 12636 | if (dest_fields == 0) { |
| ... | ... | @@ -12629,8 +12651,8 @@ fn analyzeTupleCat( |
| 12629 | 12651 | var runtime_src: ?LazySrcLoc = null; |
| 12630 | 12652 | var i: u32 = 0; |
| 12631 | 12653 | while (i < lhs_len) : (i += 1) { |
| 12632 | types[i] = lhs_ty.structFieldType(i); | |
| 12633 | const default_val = lhs_ty.structFieldDefaultValue(i); | |
| 12654 | types[i] = lhs_ty.structFieldType(i, mod); | |
| 12655 | const default_val = lhs_ty.structFieldDefaultValue(i, mod); | |
| 12634 | 12656 | values[i] = default_val; |
| 12635 | 12657 | const operand_src = lhs_src; // TODO better source location |
| 12636 | 12658 | if (default_val.ip_index == .unreachable_value) { |
| ... | ... | @@ -12639,8 +12661,8 @@ fn analyzeTupleCat( |
| 12639 | 12661 | } |
| 12640 | 12662 | i = 0; |
| 12641 | 12663 | while (i < rhs_len) : (i += 1) { |
| 12642 | types[i + lhs_len] = rhs_ty.structFieldType(i); | |
| 12643 | const default_val = rhs_ty.structFieldDefaultValue(i); | |
| 12664 | types[i + lhs_len] = rhs_ty.structFieldType(i, mod); | |
| 12665 | const default_val = rhs_ty.structFieldDefaultValue(i, mod); | |
| 12644 | 12666 | values[i + lhs_len] = default_val; |
| 12645 | 12667 | const operand_src = rhs_src; // TODO better source location |
| 12646 | 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 | 12713 | const rhs_ty = sema.typeOf(rhs); |
| 12692 | 12714 | const src = inst_data.src(); |
| 12693 | 12715 | |
| 12694 | const lhs_is_tuple = lhs_ty.isTuple(); | |
| 12695 | const rhs_is_tuple = rhs_ty.isTuple(); | |
| 12716 | const lhs_is_tuple = lhs_ty.isTuple(mod); | |
| 12717 | const rhs_is_tuple = rhs_ty.isTuple(mod); | |
| 12696 | 12718 | if (lhs_is_tuple and rhs_is_tuple) { |
| 12697 | 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 | 12822 | var elem_i: usize = 0; |
| 12801 | 12823 | while (elem_i < lhs_len) : (elem_i += 1) { |
| 12802 | 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; | |
| 12804 | const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i) else Value.@"unreachable"; | |
| 12825 | const elem_ty = if (lhs_is_tuple) lhs_ty.structFieldType(lhs_elem_i, mod) else lhs_info.elem_type; | |
| 12826 | const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, mod) else Value.@"unreachable"; | |
| 12805 | 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 | 12828 | const elem_val_inst = try sema.addConstant(elem_ty, elem_val); |
| 12807 | 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 | 12832 | } |
| 12811 | 12833 | while (elem_i < result_len) : (elem_i += 1) { |
| 12812 | 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; | |
| 12814 | const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i) else Value.@"unreachable"; | |
| 12835 | const elem_ty = if (rhs_is_tuple) rhs_ty.structFieldType(rhs_elem_i, mod) else rhs_info.elem_type; | |
| 12836 | const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, mod) else Value.@"unreachable"; | |
| 12815 | 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 | 12838 | const elem_val_inst = try sema.addConstant(elem_ty, elem_val); |
| 12817 | 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 | 12931 | } |
| 12910 | 12932 | }, |
| 12911 | 12933 | .Struct => { |
| 12912 | if (operand_ty.isTuple() and peer_ty.isIndexable(mod)) { | |
| 12913 | assert(!peer_ty.isTuple()); | |
| 12934 | if (operand_ty.isTuple(mod) and peer_ty.isIndexable(mod)) { | |
| 12935 | assert(!peer_ty.isTuple(mod)); | |
| 12914 | 12936 | return .{ |
| 12915 | 12937 | .elem_type = peer_ty.elemType2(mod), |
| 12916 | 12938 | .sentinel = null, |
| ... | ... | @@ -12930,12 +12952,13 @@ fn analyzeTupleMul( |
| 12930 | 12952 | operand: Air.Inst.Ref, |
| 12931 | 12953 | factor: u64, |
| 12932 | 12954 | ) CompileError!Air.Inst.Ref { |
| 12955 | const mod = sema.mod; | |
| 12933 | 12956 | const operand_ty = sema.typeOf(operand); |
| 12934 | 12957 | const src = LazySrcLoc.nodeOffset(src_node); |
| 12935 | 12958 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node }; |
| 12936 | 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 | 12962 | const final_len_u64 = std.math.mul(u64, tuple_len, factor) catch |
| 12940 | 12963 | return sema.fail(block, rhs_src, "operation results in overflow", .{}); |
| 12941 | 12964 | |
| ... | ... | @@ -12951,8 +12974,8 @@ fn analyzeTupleMul( |
| 12951 | 12974 | var runtime_src: ?LazySrcLoc = null; |
| 12952 | 12975 | var i: u32 = 0; |
| 12953 | 12976 | while (i < tuple_len) : (i += 1) { |
| 12954 | types[i] = operand_ty.structFieldType(i); | |
| 12955 | values[i] = operand_ty.structFieldDefaultValue(i); | |
| 12977 | types[i] = operand_ty.structFieldType(i, mod); | |
| 12978 | values[i] = operand_ty.structFieldDefaultValue(i, mod); | |
| 12956 | 12979 | const operand_src = lhs_src; // TODO better source location |
| 12957 | 12980 | if (values[i].ip_index == .unreachable_value) { |
| 12958 | 12981 | runtime_src = operand_src; |
| ... | ... | @@ -13006,7 +13029,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13006 | 13029 | const operator_src: LazySrcLoc = .{ .node_offset_main_token = inst_data.src_node }; |
| 13007 | 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 | 13033 | // In `**` rhs must be comptime-known, but lhs can be runtime-known |
| 13011 | 13034 | const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize, "array multiplication factor must be comptime-known"); |
| 13012 | 13035 | return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor); |
| ... | ... | @@ -14502,7 +14525,7 @@ fn zirOverflowArithmetic( |
| 14502 | 14525 | |
| 14503 | 14526 | const element_refs = try sema.arena.alloc(Air.Inst.Ref, 2); |
| 14504 | 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 | 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 | 16401 | |
| 16379 | 16402 | const union_ty = try sema.resolveTypeFields(ty); |
| 16380 | 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 | 16406 | const union_fields = union_ty.unionFields(); |
| 16384 | 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 | 16507 | }; |
| 16485 | 16508 | const struct_ty = try sema.resolveTypeFields(ty); |
| 16486 | 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 | 16512 | const struct_field_vals = fv: { |
| 16490 | 16513 | if (struct_ty.isSimpleTupleOrAnonStruct()) { |
| ... | ... | @@ -16532,7 +16555,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16532 | 16555 | } |
| 16533 | 16556 | break :fv struct_field_vals; |
| 16534 | 16557 | } |
| 16535 | const struct_fields = struct_ty.structFields(); | |
| 16558 | const struct_fields = struct_ty.structFields(mod); | |
| 16536 | 16559 | const struct_field_vals = try fields_anon_decl.arena().alloc(Value, struct_fields.count()); |
| 16537 | 16560 | |
| 16538 | 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 | 16623 | |
| 16601 | 16624 | const backing_integer_val = blk: { |
| 16602 | 16625 | if (layout == .Packed) { |
| 16603 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | |
| 16626 | const struct_obj = mod.typeToStruct(struct_ty).?; | |
| 16604 | 16627 | assert(struct_obj.haveLayout()); |
| 16605 | 16628 | assert(struct_obj.backing_int_ty.isInt(mod)); |
| 16606 | 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 | 16647 | // decls: []const Declaration, |
| 16625 | 16648 | decls_val, |
| 16626 | 16649 | // is_tuple: bool, |
| 16627 | Value.makeBool(struct_ty.isTuple()), | |
| 16650 | Value.makeBool(struct_ty.isTuple(mod)), | |
| 16628 | 16651 | }; |
| 16629 | 16652 | |
| 16630 | 16653 | return sema.addConstant( |
| ... | ... | @@ -17801,12 +17824,13 @@ fn structInitEmpty( |
| 17801 | 17824 | dest_src: LazySrcLoc, |
| 17802 | 17825 | init_src: LazySrcLoc, |
| 17803 | 17826 | ) CompileError!Air.Inst.Ref { |
| 17827 | const mod = sema.mod; | |
| 17804 | 17828 | const gpa = sema.gpa; |
| 17805 | 17829 | // This logic must be synchronized with that in `zirStructInit`. |
| 17806 | 17830 | const struct_ty = try sema.resolveTypeFields(obj_ty); |
| 17807 | 17831 | |
| 17808 | 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 | 17834 | defer gpa.free(field_inits); |
| 17811 | 17835 | @memset(field_inits, .none); |
| 17812 | 17836 | |
| ... | ... | @@ -17897,18 +17921,18 @@ fn zirStructInit( |
| 17897 | 17921 | |
| 17898 | 17922 | // Maps field index to field_type index of where it was already initialized. |
| 17899 | 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 | 17925 | defer gpa.free(found_fields); |
| 17902 | 17926 | |
| 17903 | 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 | 17929 | defer gpa.free(field_inits); |
| 17906 | 17930 | @memset(field_inits, .none); |
| 17907 | 17931 | |
| 17908 | 17932 | var field_i: u32 = 0; |
| 17909 | 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 | 17936 | while (field_i < extra.data.fields_len) : (field_i += 1) { |
| 17913 | 17937 | const item = sema.code.extraData(Zir.Inst.StructInit.Item, extra_index); |
| 17914 | 17938 | extra_index = item.end; |
| ... | ... | @@ -17917,7 +17941,7 @@ fn zirStructInit( |
| 17917 | 17941 | const field_src: LazySrcLoc = .{ .node_offset_initializer = field_type_data.src_node }; |
| 17918 | 17942 | const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data; |
| 17919 | 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 | 17945 | try sema.tupleFieldIndex(block, resolved_ty, field_name, field_src) |
| 17922 | 17946 | else |
| 17923 | 17947 | try sema.structFieldIndex(block, resolved_ty, field_name, field_src); |
| ... | ... | @@ -17940,7 +17964,7 @@ fn zirStructInit( |
| 17940 | 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 | 17968 | return sema.failWithInvalidComptimeFieldStore(block, field_src, resolved_ty, field_index); |
| 17945 | 17969 | } |
| 17946 | 17970 | }; |
| ... | ... | @@ -18029,13 +18053,13 @@ fn finishStructInit( |
| 18029 | 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 | 18057 | var i: u32 = 0; |
| 18034 | const len = struct_ty.structFieldCount(); | |
| 18058 | const len = struct_ty.structFieldCount(mod); | |
| 18035 | 18059 | while (i < len) : (i += 1) { |
| 18036 | 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 | 18063 | if (default_val.ip_index == .unreachable_value) { |
| 18040 | 18064 | const template = "missing tuple field with index {d}"; |
| 18041 | 18065 | if (root_msg) |msg| { |
| ... | ... | @@ -18044,11 +18068,11 @@ fn finishStructInit( |
| 18044 | 18068 | root_msg = try sema.errMsg(block, init_src, template, .{i}); |
| 18045 | 18069 | } |
| 18046 | 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 | 18074 | } else { |
| 18051 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | |
| 18075 | const struct_obj = mod.typeToStruct(struct_ty).?; | |
| 18052 | 18076 | for (struct_obj.fields.values(), 0..) |field, i| { |
| 18053 | 18077 | if (field_inits[i] != .none) continue; |
| 18054 | 18078 | |
| ... | ... | @@ -18068,11 +18092,11 @@ fn finishStructInit( |
| 18068 | 18092 | } |
| 18069 | 18093 | |
| 18070 | 18094 | if (root_msg) |msg| { |
| 18071 | if (struct_ty.castTag(.@"struct")) |struct_obj| { | |
| 18072 | const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod); | |
| 18095 | if (mod.typeToStruct(struct_ty)) |struct_obj| { | |
| 18096 | const fqn = try struct_obj.getFullyQualifiedName(sema.mod); | |
| 18073 | 18097 | defer gpa.free(fqn); |
| 18074 | 18098 | try sema.mod.errNoteNonLazy( |
| 18075 | struct_obj.data.srcLoc(sema.mod), | |
| 18099 | struct_obj.srcLoc(sema.mod), | |
| 18076 | 18100 | msg, |
| 18077 | 18101 | "struct '{s}' declared here", |
| 18078 | 18102 | .{fqn}, |
| ... | ... | @@ -18277,7 +18301,7 @@ fn zirArrayInit( |
| 18277 | 18301 | for (args[1..], 0..) |arg, i| { |
| 18278 | 18302 | const resolved_arg = try sema.resolveInst(arg); |
| 18279 | 18303 | const elem_ty = if (array_ty.zigTypeTag(mod) == .Struct) |
| 18280 | array_ty.structFieldType(i) | |
| 18304 | array_ty.structFieldType(i, mod) | |
| 18281 | 18305 | else |
| 18282 | 18306 | array_ty.elemType2(mod); |
| 18283 | 18307 | resolved_args[i] = sema.coerce(block, elem_ty, resolved_arg, .unneeded) catch |err| switch (err) { |
| ... | ... | @@ -18331,12 +18355,12 @@ fn zirArrayInit( |
| 18331 | 18355 | }); |
| 18332 | 18356 | const alloc = try block.addTy(.alloc, alloc_ty); |
| 18333 | 18357 | |
| 18334 | if (array_ty.isTuple()) { | |
| 18358 | if (array_ty.isTuple(mod)) { | |
| 18335 | 18359 | for (resolved_args, 0..) |arg, i| { |
| 18336 | 18360 | const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ |
| 18337 | 18361 | .mutable = true, |
| 18338 | 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 | 18365 | const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty); |
| 18342 | 18366 | |
| ... | ... | @@ -18514,7 +18538,7 @@ fn fieldType( |
| 18514 | 18538 | const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src); |
| 18515 | 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 | 18542 | const field = struct_obj.fields.get(field_name) orelse |
| 18519 | 18543 | return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name); |
| 18520 | 18544 | return sema.addType(field.ty); |
| ... | ... | @@ -19185,13 +19209,13 @@ fn zirReify( |
| 19185 | 19209 | .file_scope = block.getFileScope(mod), |
| 19186 | 19210 | }); |
| 19187 | 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 | 19214 | const opaque_ty = try mod.intern_pool.get(gpa, .{ .opaque_type = .{ |
| 19191 | 19215 | .decl = new_decl_index, |
| 19192 | 19216 | .namespace = new_namespace_index, |
| 19193 | 19217 | } }); |
| 19194 | errdefer @panic("TODO error handling"); | |
| 19218 | errdefer mod.intern_pool.remove(opaque_ty); | |
| 19195 | 19219 | |
| 19196 | 19220 | new_decl.val = opaque_ty.toValue(); |
| 19197 | 19221 | new_namespace.ty = opaque_ty.toType(); |
| ... | ... | @@ -19493,22 +19517,34 @@ fn reifyStruct( |
| 19493 | 19517 | name_strategy: Zir.Inst.NameStrategy, |
| 19494 | 19518 | is_tuple: bool, |
| 19495 | 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 | 19524 | errdefer new_decl_arena.deinit(); |
| 19498 | 19525 | const new_decl_arena_allocator = new_decl_arena.allocator(); |
| 19499 | 19526 | |
| 19500 | const struct_obj = try new_decl_arena_allocator.create(Module.Struct); | |
| 19501 | const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj); | |
| 19502 | const new_struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty); | |
| 19503 | const mod = sema.mod; | |
| 19527 | // Because these three things each reference each other, `undefined` | |
| 19528 | // placeholders are used before being set after the struct type gains an | |
| 19529 | // InternPool index. | |
| 19530 | ||
| 19504 | 19531 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ |
| 19505 | 19532 | .ty = Type.type, |
| 19506 | .val = new_struct_val, | |
| 19533 | .val = undefined, | |
| 19507 | 19534 | }, name_strategy, "struct", inst); |
| 19508 | 19535 | const new_decl = mod.declPtr(new_decl_index); |
| 19509 | 19536 | new_decl.owns_tv = true; |
| 19510 | 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 | 19548 | .owner_decl = new_decl_index, |
| 19513 | 19549 | .fields = .{}, |
| 19514 | 19550 | .zir_index = inst, |
| ... | ... | @@ -19516,12 +19552,19 @@ fn reifyStruct( |
| 19516 | 19552 | .status = .have_field_types, |
| 19517 | 19553 | .known_non_opv = false, |
| 19518 | 19554 | .is_tuple = is_tuple, |
| 19519 | .namespace = try mod.createNamespace(.{ | |
| 19520 | .parent = block.namespace.toOptional(), | |
| 19521 | .ty = struct_ty, | |
| 19522 | .file_scope = block.getFileScope(mod), | |
| 19523 | }), | |
| 19524 | }; | |
| 19555 | .namespace = new_namespace_index, | |
| 19556 | }); | |
| 19557 | const struct_obj = mod.structPtr(struct_index); | |
| 19558 | errdefer mod.destroyStruct(struct_index); | |
| 19559 | ||
| 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 | 19569 | // Fields |
| 19527 | 19570 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod)); |
| ... | ... | @@ -19609,7 +19652,7 @@ fn reifyStruct( |
| 19609 | 19652 | if (field_ty.zigTypeTag(mod) == .Opaque) { |
| 19610 | 19653 | const msg = msg: { |
| 19611 | 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 | 19657 | try sema.addDeclaredHereNote(msg, field_ty); |
| 19615 | 19658 | break :msg msg; |
| ... | ... | @@ -19619,7 +19662,7 @@ fn reifyStruct( |
| 19619 | 19662 | if (field_ty.zigTypeTag(mod) == .NoReturn) { |
| 19620 | 19663 | const msg = msg: { |
| 19621 | 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 | 19667 | try sema.addDeclaredHereNote(msg, field_ty); |
| 19625 | 19668 | break :msg msg; |
| ... | ... | @@ -19629,7 +19672,7 @@ fn reifyStruct( |
| 19629 | 19672 | if (struct_obj.layout == .Extern and !try sema.validateExternType(field_ty, .struct_field)) { |
| 19630 | 19673 | const msg = msg: { |
| 19631 | 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 | 19677 | const src_decl = sema.mod.declPtr(block.src_decl); |
| 19635 | 19678 | try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl, mod), field_ty, .struct_field); |
| ... | ... | @@ -19641,7 +19684,7 @@ fn reifyStruct( |
| 19641 | 19684 | } else if (struct_obj.layout == .Packed and !(validatePackedType(field_ty, mod))) { |
| 19642 | 19685 | const msg = msg: { |
| 19643 | 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 | 19689 | const src_decl = sema.mod.declPtr(block.src_decl); |
| 19647 | 19690 | try sema.explainWhyTypeIsNotPacked(msg, src.toSrcLoc(src_decl, mod), field_ty); |
| ... | ... | @@ -19660,7 +19703,7 @@ fn reifyStruct( |
| 19660 | 19703 | sema.resolveTypeLayout(field.ty) catch |err| switch (err) { |
| 19661 | 19704 | error.AnalysisFail => { |
| 19662 | 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 | 19707 | return err; |
| 19665 | 19708 | }, |
| 19666 | 19709 | else => return err, |
| ... | ... | @@ -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 | 20605 | if (mem.eql(u8, field_name, "len")) { |
| 20563 | 20606 | return sema.fail(block, src, "no offset available for 'len' field of tuple", .{}); |
| 20564 | 20607 | } |
| 20565 | 20608 | break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src); |
| 20566 | 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 | 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 | 20616 | .Packed => { |
| 20574 | 20617 | var bit_sum: u64 = 0; |
| 20575 | const fields = ty.structFields(); | |
| 20618 | const fields = ty.structFields(mod); | |
| 20576 | 20619 | for (fields.values(), 0..) |field, i| { |
| 20577 | 20620 | if (i == field_index) { |
| 20578 | 20621 | return bit_sum; |
| ... | ... | @@ -21810,6 +21853,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 21810 | 21853 | const tracy = trace(@src()); |
| 21811 | 21854 | defer tracy.end(); |
| 21812 | 21855 | |
| 21856 | const mod = sema.mod; | |
| 21813 | 21857 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 21814 | 21858 | const modifier_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 21815 | 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 | 21913 | const args = try sema.resolveInst(extra.args); |
| 21870 | 21914 | |
| 21871 | 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 | 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 | 21921 | for (resolved_args, 0..) |*resolved, i| { |
| 21878 | 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 | 21949 | |
| 21906 | 21950 | const field_index = switch (parent_ty.zigTypeTag(mod)) { |
| 21907 | 21951 | .Struct => blk: { |
| 21908 | if (parent_ty.isTuple()) { | |
| 21952 | if (parent_ty.isTuple(mod)) { | |
| 21909 | 21953 | if (mem.eql(u8, field_name, "len")) { |
| 21910 | 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 | 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 | 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 | 21970 | const field_ptr_ty_info = field_ptr_ty.ptrInfo(mod); |
| 21927 | 21971 | |
| 21928 | 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 | 21974 | .mutable = field_ptr_ty_info.mutable, |
| 21931 | 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 | 21979 | return sema.fail(block, src, "TODO handle packed structs/unions with @fieldParentPtr", .{}); |
| 21936 | 21980 | } else { |
| 21937 | 21981 | ptr_ty_data.@"align" = blk: { |
| 21938 | if (parent_ty.castTag(.@"struct")) |struct_obj| { | |
| 21939 | break :blk struct_obj.data.fields.values()[field_index].abi_align; | |
| 21982 | if (mod.typeToStruct(parent_ty)) |struct_obj| { | |
| 21983 | break :blk struct_obj.fields.values()[field_index].abi_align; | |
| 21940 | 21984 | } else if (parent_ty.cast(Type.Payload.Union)) |union_obj| { |
| 21941 | 21985 | break :blk union_obj.data.fields.values()[field_index].abi_align; |
| 21942 | 21986 | } else { |
| ... | ... | @@ -23380,8 +23424,7 @@ fn explainWhyTypeIsComptimeInner( |
| 23380 | 23424 | .Struct => { |
| 23381 | 23425 | if ((try type_set.getOrPutContext(sema.gpa, ty, .{ .mod = mod })).found_existing) return; |
| 23382 | 23426 | |
| 23383 | if (ty.castTag(.@"struct")) |payload| { | |
| 23384 | const struct_obj = payload.data; | |
| 23427 | if (mod.typeToStruct(ty)) |struct_obj| { | |
| 23385 | 23428 | for (struct_obj.fields.values(), 0..) |field, i| { |
| 23386 | 23429 | const field_src_loc = struct_obj.fieldSrcLoc(sema.mod, .{ |
| 23387 | 23430 | .index = i, |
| ... | ... | @@ -23472,7 +23515,7 @@ fn validateExternType( |
| 23472 | 23515 | .Enum => { |
| 23473 | 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 | 23519 | .Extern => return true, |
| 23477 | 23520 | .Packed => { |
| 23478 | 23521 | const bit_size = try ty.bitSizeAdvanced(mod, sema); |
| ... | ... | @@ -23569,7 +23612,7 @@ fn explainWhyTypeIsNotExtern( |
| 23569 | 23612 | |
| 23570 | 23613 | /// Returns true if `ty` is allowed in packed types. |
| 23571 | 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 | 23616 | switch (ty.zigTypeTag(mod)) { |
| 23574 | 23617 | .Type, |
| 23575 | 23618 | .ComptimeFloat, |
| ... | ... | @@ -23595,7 +23638,7 @@ fn validatePackedType(ty: Type, mod: *const Module) bool { |
| 23595 | 23638 | .Enum, |
| 23596 | 23639 | => return true, |
| 23597 | 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 | 24462 | switch (concrete_ty.zigTypeTag(mod)) { |
| 24420 | 24463 | .Struct => { |
| 24421 | 24464 | const struct_ty = try sema.resolveTypeFields(concrete_ty); |
| 24422 | if (struct_ty.castTag(.@"struct")) |struct_obj| { | |
| 24423 | const field_index_usize = struct_obj.data.fields.getIndex(field_name) orelse | |
| 24465 | if (mod.typeToStruct(struct_ty)) |struct_obj| { | |
| 24466 | const field_index_usize = struct_obj.fields.getIndex(field_name) orelse | |
| 24424 | 24467 | break :find_field; |
| 24425 | 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 | 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 | 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 | 24476 | if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| { |
| 24434 | if (field_index >= struct_ty.structFieldCount()) break :find_field; | |
| 24435 | return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(field_index), field_index, object_ptr); | |
| 24477 | if (field_index >= struct_ty.structFieldCount(mod)) break :find_field; | |
| 24478 | return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(field_index, mod), field_index, object_ptr); | |
| 24436 | 24479 | } else |_| {} |
| 24437 | 24480 | } else { |
| 24438 | const max = struct_ty.structFieldCount(); | |
| 24481 | const max = struct_ty.structFieldCount(mod); | |
| 24439 | 24482 | var i: u32 = 0; |
| 24440 | 24483 | while (i < max) : (i += 1) { |
| 24441 | if (mem.eql(u8, struct_ty.structFieldName(i), field_name)) { | |
| 24442 | return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(i), i, object_ptr); | |
| 24484 | if (mem.eql(u8, struct_ty.structFieldName(i, mod), field_name)) { | |
| 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 | 24694 | const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty); |
| 24652 | 24695 | try sema.resolveStructLayout(struct_ty); |
| 24653 | 24696 | |
| 24654 | if (struct_ty.isTuple()) { | |
| 24697 | if (struct_ty.isTuple(mod)) { | |
| 24655 | 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 | 24700 | return sema.analyzeRef(block, src, len_inst); |
| 24658 | 24701 | } |
| 24659 | 24702 | const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src); |
| ... | ... | @@ -24663,7 +24706,7 @@ fn structFieldPtr( |
| 24663 | 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 | 24711 | const field_index_big = struct_obj.fields.getIndex(field_name) orelse |
| 24669 | 24712 | return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name); |
| ... | ... | @@ -24687,7 +24730,7 @@ fn structFieldPtrByIndex( |
| 24687 | 24730 | } |
| 24688 | 24731 | |
| 24689 | 24732 | const mod = sema.mod; |
| 24690 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | |
| 24733 | const struct_obj = mod.typeToStruct(struct_ty).?; | |
| 24691 | 24734 | const field = struct_obj.fields.values()[field_index]; |
| 24692 | 24735 | const struct_ptr_ty = sema.typeOf(struct_ptr); |
| 24693 | 24736 | const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(mod); |
| ... | ... | @@ -24799,8 +24842,11 @@ fn structFieldVal( |
| 24799 | 24842 | const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src); |
| 24800 | 24843 | return sema.tupleFieldValByIndex(block, src, struct_byval, field_index, struct_ty); |
| 24801 | 24844 | }, |
| 24802 | .@"struct" => { | |
| 24803 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | |
| 24845 | else => unreachable, | |
| 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 | 24850 | if (struct_obj.is_tuple) return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty); |
| 24805 | 24851 | |
| 24806 | 24852 | const field_index_usize = struct_obj.fields.getIndex(field_name) orelse |
| ... | ... | @@ -24827,7 +24873,6 @@ fn structFieldVal( |
| 24827 | 24873 | }, |
| 24828 | 24874 | else => unreachable, |
| 24829 | 24875 | }, |
| 24830 | else => unreachable, | |
| 24831 | 24876 | } |
| 24832 | 24877 | } |
| 24833 | 24878 | |
| ... | ... | @@ -24840,8 +24885,9 @@ fn tupleFieldVal( |
| 24840 | 24885 | field_name_src: LazySrcLoc, |
| 24841 | 24886 | tuple_ty: Type, |
| 24842 | 24887 | ) CompileError!Air.Inst.Ref { |
| 24888 | const mod = sema.mod; | |
| 24843 | 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 | 24892 | const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_name_src); |
| 24847 | 24893 | return sema.tupleFieldValByIndex(block, src, tuple_byval, field_index, tuple_ty); |
| ... | ... | @@ -24858,7 +24904,7 @@ fn tupleFieldIndex( |
| 24858 | 24904 | const mod = sema.mod; |
| 24859 | 24905 | assert(!std.mem.eql(u8, field_name, "len")); |
| 24860 | 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 | 24908 | return sema.fail(block, field_name_src, "index '{s}' out of bounds of tuple '{}'", .{ |
| 24863 | 24909 | field_name, tuple_ty.fmt(mod), |
| 24864 | 24910 | }); |
| ... | ... | @@ -24878,7 +24924,7 @@ fn tupleFieldValByIndex( |
| 24878 | 24924 | tuple_ty: Type, |
| 24879 | 24925 | ) CompileError!Air.Inst.Ref { |
| 24880 | 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 | 24929 | if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| { |
| 24884 | 24930 | return sema.addConstant(field_ty, default_value); |
| ... | ... | @@ -25251,7 +25297,7 @@ fn tupleFieldPtr( |
| 25251 | 25297 | const tuple_ptr_ty = sema.typeOf(tuple_ptr); |
| 25252 | 25298 | const tuple_ty = tuple_ptr_ty.childType(mod); |
| 25253 | 25299 | _ = try sema.resolveTypeFields(tuple_ty); |
| 25254 | const field_count = tuple_ty.structFieldCount(); | |
| 25300 | const field_count = tuple_ty.structFieldCount(mod); | |
| 25255 | 25301 | |
| 25256 | 25302 | if (field_count == 0) { |
| 25257 | 25303 | return sema.fail(block, tuple_ptr_src, "indexing into empty tuple is not allowed", .{}); |
| ... | ... | @@ -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 | 25313 | const ptr_field_ty = try Type.ptr(sema.arena, mod, .{ |
| 25268 | 25314 | .pointee_type = field_ty, |
| 25269 | 25315 | .mutable = tuple_ptr_ty.ptrIsMutable(mod), |
| ... | ... | @@ -25308,7 +25354,7 @@ fn tupleField( |
| 25308 | 25354 | ) CompileError!Air.Inst.Ref { |
| 25309 | 25355 | const mod = sema.mod; |
| 25310 | 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 | 25359 | if (field_count == 0) { |
| 25314 | 25360 | return sema.fail(block, tuple_src, "indexing into empty tuple is not allowed", .{}); |
| ... | ... | @@ -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 | 25371 | if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| { |
| 25326 | 25372 | return sema.addConstant(field_ty, default_value); // comptime field |
| ... | ... | @@ -25919,7 +25965,7 @@ fn coerceExtra( |
| 25919 | 25965 | .Array => { |
| 25920 | 25966 | // pointer to tuple to pointer to array |
| 25921 | 25967 | if (inst_ty.isSinglePointer(mod) and |
| 25922 | inst_ty.childType(mod).isTuple() and | |
| 25968 | inst_ty.childType(mod).isTuple(mod) and | |
| 25923 | 25969 | sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) |
| 25924 | 25970 | { |
| 25925 | 25971 | return sema.coerceTupleToArrayPtrs(block, dest_ty, dest_ty_src, inst, inst_src); |
| ... | ... | @@ -25939,11 +25985,11 @@ fn coerceExtra( |
| 25939 | 25985 | |
| 25940 | 25986 | if (!inst_ty.isSinglePointer(mod)) break :to_slice; |
| 25941 | 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 | 25990 | // empty tuple to zero-length slice |
| 25945 | 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 | 25993 | // Optional slice is represented with a null pointer so |
| 25948 | 25994 | // we use a dummy pointer value with the required alignment. |
| 25949 | 25995 | const slice_val = try Value.Tag.slice.create(sema.arena, .{ |
| ... | ... | @@ -26213,7 +26259,7 @@ fn coerceExtra( |
| 26213 | 26259 | if (inst == .empty_struct) { |
| 26214 | 26260 | return sema.arrayInitEmpty(block, inst_src, dest_ty); |
| 26215 | 26261 | } |
| 26216 | if (inst_ty.isTuple()) { | |
| 26262 | if (inst_ty.isTuple(mod)) { | |
| 26217 | 26263 | return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src); |
| 26218 | 26264 | } |
| 26219 | 26265 | }, |
| ... | ... | @@ -26225,7 +26271,7 @@ fn coerceExtra( |
| 26225 | 26271 | .Vector => switch (inst_ty.zigTypeTag(mod)) { |
| 26226 | 26272 | .Array, .Vector => return sema.coerceArrayLike(block, dest_ty, dest_ty_src, inst, inst_src), |
| 26227 | 26273 | .Struct => { |
| 26228 | if (inst_ty.isTuple()) { | |
| 26274 | if (inst_ty.isTuple(mod)) { | |
| 26229 | 26275 | return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src); |
| 26230 | 26276 | } |
| 26231 | 26277 | }, |
| ... | ... | @@ -26238,7 +26284,7 @@ fn coerceExtra( |
| 26238 | 26284 | if (inst == .empty_struct) { |
| 26239 | 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 | 26288 | return sema.coerceTupleToStruct(block, dest_ty, inst, inst_src) catch |err| switch (err) { |
| 26243 | 26289 | error.NotCoercible => break :blk, |
| 26244 | 26290 | else => |e| return e, |
| ... | ... | @@ -27304,8 +27350,8 @@ fn storePtr2( |
| 27304 | 27350 | // this code does not handle tuple-to-struct coercion which requires dealing with missing |
| 27305 | 27351 | // fields. |
| 27306 | 27352 | const operand_ty = sema.typeOf(uncasted_operand); |
| 27307 | if (operand_ty.isTuple() and elem_ty.zigTypeTag(mod) == .Array) { | |
| 27308 | const field_count = operand_ty.structFieldCount(); | |
| 27353 | if (operand_ty.isTuple(mod) and elem_ty.zigTypeTag(mod) == .Array) { | |
| 27354 | const field_count = operand_ty.structFieldCount(mod); | |
| 27309 | 27355 | var i: u32 = 0; |
| 27310 | 27356 | while (i < field_count) : (i += 1) { |
| 27311 | 27357 | const elem_src = operand_src; // TODO better source location |
| ... | ... | @@ -27804,7 +27850,7 @@ fn beginComptimePtrMutation( |
| 27804 | 27850 | |
| 27805 | 27851 | switch (parent.ty.zigTypeTag(mod)) { |
| 27806 | 27852 | .Struct => { |
| 27807 | const fields = try arena.alloc(Value, parent.ty.structFieldCount()); | |
| 27853 | const fields = try arena.alloc(Value, parent.ty.structFieldCount(mod)); | |
| 27808 | 27854 | @memset(fields, Value.undef); |
| 27809 | 27855 | |
| 27810 | 27856 | val_ptr.* = try Value.Tag.aggregate.create(arena, fields); |
| ... | ... | @@ -27813,7 +27859,7 @@ fn beginComptimePtrMutation( |
| 27813 | 27859 | sema, |
| 27814 | 27860 | block, |
| 27815 | 27861 | src, |
| 27816 | parent.ty.structFieldType(field_index), | |
| 27862 | parent.ty.structFieldType(field_index, mod), | |
| 27817 | 27863 | &fields[field_index], |
| 27818 | 27864 | ptr_elem_ty, |
| 27819 | 27865 | parent.decl_ref_mut, |
| ... | ... | @@ -27832,7 +27878,7 @@ fn beginComptimePtrMutation( |
| 27832 | 27878 | sema, |
| 27833 | 27879 | block, |
| 27834 | 27880 | src, |
| 27835 | parent.ty.structFieldType(field_index), | |
| 27881 | parent.ty.structFieldType(field_index, mod), | |
| 27836 | 27882 | &payload.data.val, |
| 27837 | 27883 | ptr_elem_ty, |
| 27838 | 27884 | parent.decl_ref_mut, |
| ... | ... | @@ -27878,7 +27924,7 @@ fn beginComptimePtrMutation( |
| 27878 | 27924 | sema, |
| 27879 | 27925 | block, |
| 27880 | 27926 | src, |
| 27881 | parent.ty.structFieldType(field_index), | |
| 27927 | parent.ty.structFieldType(field_index, mod), | |
| 27882 | 27928 | duped, |
| 27883 | 27929 | ptr_elem_ty, |
| 27884 | 27930 | parent.decl_ref_mut, |
| ... | ... | @@ -27889,7 +27935,7 @@ fn beginComptimePtrMutation( |
| 27889 | 27935 | sema, |
| 27890 | 27936 | block, |
| 27891 | 27937 | src, |
| 27892 | parent.ty.structFieldType(field_index), | |
| 27938 | parent.ty.structFieldType(field_index, mod), | |
| 27893 | 27939 | &val_ptr.castTag(.aggregate).?.data[field_index], |
| 27894 | 27940 | ptr_elem_ty, |
| 27895 | 27941 | parent.decl_ref_mut, |
| ... | ... | @@ -27907,7 +27953,7 @@ fn beginComptimePtrMutation( |
| 27907 | 27953 | sema, |
| 27908 | 27954 | block, |
| 27909 | 27955 | src, |
| 27910 | parent.ty.structFieldType(field_index), | |
| 27956 | parent.ty.structFieldType(field_index, mod), | |
| 27911 | 27957 | &payload.val, |
| 27912 | 27958 | ptr_elem_ty, |
| 27913 | 27959 | parent.decl_ref_mut, |
| ... | ... | @@ -28269,8 +28315,8 @@ fn beginComptimePtrLoad( |
| 28269 | 28315 | var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.container_ptr, field_ptr.container_ty); |
| 28270 | 28316 | |
| 28271 | 28317 | if (field_ptr.container_ty.hasWellDefinedLayout(mod)) { |
| 28272 | const struct_ty = field_ptr.container_ty.castTag(.@"struct"); | |
| 28273 | if (struct_ty != null and struct_ty.?.data.layout == .Packed) { | |
| 28318 | const struct_obj = mod.typeToStruct(field_ptr.container_ty); | |
| 28319 | if (struct_obj != null and struct_obj.?.layout == .Packed) { | |
| 28274 | 28320 | // packed structs are not byte addressable |
| 28275 | 28321 | deref.parent = null; |
| 28276 | 28322 | } else if (deref.parent) |*parent| { |
| ... | ... | @@ -28310,7 +28356,7 @@ fn beginComptimePtrLoad( |
| 28310 | 28356 | else => unreachable, |
| 28311 | 28357 | }; |
| 28312 | 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 | 28360 | deref.pointee = TypedValue{ |
| 28315 | 28361 | .ty = field_ty, |
| 28316 | 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 | 28529 | const inst_info = inst_ty.ptrInfo(mod); |
| 28484 | 28530 | const len0 = (inst_info.pointee_type.zigTypeTag(mod) == .Array and (inst_info.pointee_type.arrayLenIncludingSentinel(mod) == 0 or |
| 28485 | 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 | 28534 | const ok_cv_qualifiers = |
| 28489 | 28535 | ((inst_info.mutable or !dest_info.mutable) or len0) and |
| ... | ... | @@ -28714,8 +28760,9 @@ fn coerceAnonStructToUnion( |
| 28714 | 28760 | inst: Air.Inst.Ref, |
| 28715 | 28761 | inst_src: LazySrcLoc, |
| 28716 | 28762 | ) !Air.Inst.Ref { |
| 28763 | const mod = sema.mod; | |
| 28717 | 28764 | const inst_ty = sema.typeOf(inst); |
| 28718 | const field_count = inst_ty.structFieldCount(); | |
| 28765 | const field_count = inst_ty.structFieldCount(mod); | |
| 28719 | 28766 | if (field_count != 1) { |
| 28720 | 28767 | const msg = msg: { |
| 28721 | 28768 | const msg = if (field_count > 1) try sema.errMsg( |
| ... | ... | @@ -28927,7 +28974,7 @@ fn coerceTupleToSlicePtrs( |
| 28927 | 28974 | const tuple_ty = sema.typeOf(ptr_tuple).childType(mod); |
| 28928 | 28975 | const tuple = try sema.analyzeLoad(block, tuple_src, ptr_tuple, tuple_src); |
| 28929 | 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 | 28978 | const array_inst = try sema.coerceTupleToArray(block, array_ty, slice_ty_src, tuple, tuple_src); |
| 28932 | 28979 | if (slice_info.@"align" != 0) { |
| 28933 | 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 | 29013 | inst: Air.Inst.Ref, |
| 28967 | 29014 | inst_src: LazySrcLoc, |
| 28968 | 29015 | ) !Air.Inst.Ref { |
| 29016 | const mod = sema.mod; | |
| 28969 | 29017 | const struct_ty = try sema.resolveTypeFields(dest_ty); |
| 28970 | 29018 | |
| 28971 | if (struct_ty.isTupleOrAnonStruct()) { | |
| 29019 | if (struct_ty.isTupleOrAnonStruct(mod)) { | |
| 28972 | 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 | 29024 | const field_vals = try sema.arena.alloc(Value, fields.count()); |
| 28977 | 29025 | const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len); |
| 28978 | 29026 | @memset(field_refs, .none); |
| 28979 | 29027 | |
| 28980 | 29028 | const inst_ty = sema.typeOf(inst); |
| 28981 | 29029 | var runtime_src: ?LazySrcLoc = null; |
| 28982 | const field_count = inst_ty.structFieldCount(); | |
| 29030 | const field_count = inst_ty.structFieldCount(mod); | |
| 28983 | 29031 | var field_i: u32 = 0; |
| 28984 | 29032 | while (field_i < field_count) : (field_i += 1) { |
| 28985 | 29033 | const field_src = inst_src; // TODO better source location |
| ... | ... | @@ -29061,13 +29109,14 @@ fn coerceTupleToTuple( |
| 29061 | 29109 | inst: Air.Inst.Ref, |
| 29062 | 29110 | inst_src: LazySrcLoc, |
| 29063 | 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 | 29114 | const field_vals = try sema.arena.alloc(Value, dest_field_count); |
| 29066 | 29115 | const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len); |
| 29067 | 29116 | @memset(field_refs, .none); |
| 29068 | 29117 | |
| 29069 | 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 | 29120 | if (inst_field_count > dest_field_count) return error.NotCoercible; |
| 29072 | 29121 | |
| 29073 | 29122 | var runtime_src: ?LazySrcLoc = null; |
| ... | ... | @@ -29085,8 +29134,8 @@ fn coerceTupleToTuple( |
| 29085 | 29134 | |
| 29086 | 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); | |
| 29089 | const default_val = tuple_ty.structFieldDefaultValue(field_i); | |
| 29137 | const field_ty = tuple_ty.structFieldType(field_i, mod); | |
| 29138 | const default_val = tuple_ty.structFieldDefaultValue(field_i, mod); | |
| 29090 | 29139 | const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i); |
| 29091 | 29140 | const coerced = try sema.coerce(block, field_ty, elem_ref, field_src); |
| 29092 | 29141 | field_refs[field_index] = coerced; |
| ... | ... | @@ -29115,12 +29164,12 @@ fn coerceTupleToTuple( |
| 29115 | 29164 | for (field_refs, 0..) |*field_ref, i| { |
| 29116 | 29165 | if (field_ref.* != .none) continue; |
| 29117 | 29166 | |
| 29118 | const default_val = tuple_ty.structFieldDefaultValue(i); | |
| 29119 | const field_ty = tuple_ty.structFieldType(i); | |
| 29167 | const default_val = tuple_ty.structFieldDefaultValue(i, mod); | |
| 29168 | const field_ty = tuple_ty.structFieldType(i, mod); | |
| 29120 | 29169 | |
| 29121 | 29170 | const field_src = inst_src; // TODO better source location |
| 29122 | 29171 | if (default_val.ip_index == .unreachable_value) { |
| 29123 | if (tuple_ty.isTuple()) { | |
| 29172 | if (tuple_ty.isTuple(mod)) { | |
| 29124 | 29173 | const template = "missing tuple field: {d}"; |
| 29125 | 29174 | if (root_msg) |msg| { |
| 29126 | 29175 | try sema.errNote(block, field_src, msg, template, .{i}); |
| ... | ... | @@ -29130,7 +29179,7 @@ fn coerceTupleToTuple( |
| 29130 | 29179 | continue; |
| 29131 | 29180 | } |
| 29132 | 29181 | const template = "missing struct field: {s}"; |
| 29133 | const args = .{tuple_ty.structFieldName(i)}; | |
| 29182 | const args = .{tuple_ty.structFieldName(i, mod)}; | |
| 29134 | 29183 | if (root_msg) |msg| { |
| 29135 | 29184 | try sema.errNote(block, field_src, msg, template, args); |
| 29136 | 29185 | } else { |
| ... | ... | @@ -31222,17 +31271,17 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void { |
| 31222 | 31271 | } |
| 31223 | 31272 | |
| 31224 | 31273 | fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 31274 | const mod = sema.mod; | |
| 31225 | 31275 | const resolved_ty = try sema.resolveTypeFields(ty); |
| 31226 | if (resolved_ty.castTag(.@"struct")) |payload| { | |
| 31227 | const struct_obj = payload.data; | |
| 31276 | if (mod.typeToStruct(resolved_ty)) |struct_obj| { | |
| 31228 | 31277 | switch (struct_obj.status) { |
| 31229 | 31278 | .none, .have_field_types => {}, |
| 31230 | 31279 | .field_types_wip, .layout_wip => { |
| 31231 | 31280 | const msg = try Module.ErrorMsg.create( |
| 31232 | 31281 | sema.gpa, |
| 31233 | struct_obj.srcLoc(sema.mod), | |
| 31282 | struct_obj.srcLoc(mod), | |
| 31234 | 31283 | "struct '{}' depends on itself", |
| 31235 | .{ty.fmt(sema.mod)}, | |
| 31284 | .{ty.fmt(mod)}, | |
| 31236 | 31285 | ); |
| 31237 | 31286 | return sema.failWithOwnedErrorMsg(msg); |
| 31238 | 31287 | }, |
| ... | ... | @@ -31256,7 +31305,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 31256 | 31305 | } |
| 31257 | 31306 | |
| 31258 | 31307 | if (struct_obj.layout == .Packed) { |
| 31259 | try semaBackingIntType(sema.mod, struct_obj); | |
| 31308 | try semaBackingIntType(mod, struct_obj); | |
| 31260 | 31309 | } |
| 31261 | 31310 | |
| 31262 | 31311 | struct_obj.status = .have_layout; |
| ... | ... | @@ -31265,20 +31314,20 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 31265 | 31314 | if (struct_obj.assumed_runtime_bits and !(try sema.typeHasRuntimeBits(resolved_ty))) { |
| 31266 | 31315 | const msg = try Module.ErrorMsg.create( |
| 31267 | 31316 | sema.gpa, |
| 31268 | struct_obj.srcLoc(sema.mod), | |
| 31317 | struct_obj.srcLoc(mod), | |
| 31269 | 31318 | "struct layout depends on it having runtime bits", |
| 31270 | 31319 | .{}, |
| 31271 | 31320 | ); |
| 31272 | 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 | 31325 | const optimized_order = if (struct_obj.owner_decl == sema.owner_decl_index) |
| 31277 | 31326 | try sema.perm_arena.alloc(u32, struct_obj.fields.count()) |
| 31278 | 31327 | else blk: { |
| 31279 | const decl = sema.mod.declPtr(struct_obj.owner_decl); | |
| 31328 | const decl = mod.declPtr(struct_obj.owner_decl); | |
| 31280 | 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 | 31331 | defer decl.value_arena.?.release(&decl_arena); |
| 31283 | 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 | 31577 | return switch (ty.ip_index) { |
| 31529 | 31578 | .empty_struct_type => false, |
| 31530 | 31579 | .none => switch (ty.tag()) { |
| 31531 | .empty_struct, | |
| 31532 | 31580 | .error_set, |
| 31533 | 31581 | .error_set_single, |
| 31534 | 31582 | .error_set_inferred, |
| ... | ... | @@ -31569,27 +31617,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 31569 | 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 | 31620 | .@"union", .union_safety_tagged, .union_tagged => { |
| 31594 | 31621 | const union_obj = ty.cast(Type.Payload.Union).?.data; |
| 31595 | 31622 | switch (union_obj.requires_comptime) { |
| ... | ... | @@ -31686,7 +31713,27 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 31686 | 31713 | .type_info, |
| 31687 | 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 | 31737 | .union_type => @panic("TODO"), |
| 31691 | 31738 | .opaque_type => false, |
| 31692 | 31739 | |
| ... | ... | @@ -31697,6 +31744,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 31697 | 31744 | .ptr => unreachable, |
| 31698 | 31745 | .opt => unreachable, |
| 31699 | 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 | 31758 | const child_ty = try sema.resolveTypeFields(ty.childType(mod)); |
| 31711 | 31759 | return sema.resolveTypeFully(child_ty); |
| 31712 | 31760 | }, |
| 31713 | .Struct => switch (ty.tag()) { | |
| 31714 | .@"struct" => return sema.resolveStructFully(ty), | |
| 31715 | .tuple, .anon_struct => { | |
| 31716 | const tuple = ty.tupleFields(); | |
| 31761 | .Struct => switch (ty.ip_index) { | |
| 31762 | .none => switch (ty.tag()) { | |
| 31763 | .tuple, .anon_struct => { | |
| 31764 | const tuple = ty.tupleFields(); | |
| 31717 | 31765 | |
| 31718 | for (tuple.types) |field_ty| { | |
| 31719 | try sema.resolveTypeFully(field_ty); | |
| 31720 | } | |
| 31766 | for (tuple.types) |field_ty| { | |
| 31767 | try sema.resolveTypeFully(field_ty); | |
| 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 | 31777 | .Union => return sema.resolveUnionFully(ty), |
| 31725 | 31778 | .Array => return sema.resolveTypeFully(ty.childType(mod)), |
| ... | ... | @@ -31746,9 +31799,9 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void { |
| 31746 | 31799 | fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void { |
| 31747 | 31800 | try sema.resolveStructLayout(ty); |
| 31748 | 31801 | |
| 31802 | const mod = sema.mod; | |
| 31749 | 31803 | const resolved_ty = try sema.resolveTypeFields(ty); |
| 31750 | const payload = resolved_ty.castTag(.@"struct").?; | |
| 31751 | const struct_obj = payload.data; | |
| 31804 | const struct_obj = mod.typeToStruct(resolved_ty).?; | |
| 31752 | 31805 | |
| 31753 | 31806 | switch (struct_obj.status) { |
| 31754 | 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 | 31859 | |
| 31807 | 31860 | switch (ty.ip_index) { |
| 31808 | 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 | 31862 | .@"union", .union_safety_tagged, .union_tagged => { |
| 31815 | 31863 | const union_obj = ty.cast(Type.Payload.Union).?.data; |
| 31816 | 31864 | try sema.resolveTypeFieldsUnion(ty, union_obj); |
| ... | ... | @@ -31904,7 +31952,11 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type { |
| 31904 | 31952 | .prefetch_options_type => return sema.getBuiltinType("PrefetchOptions"), |
| 31905 | 31953 | |
| 31906 | 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 | 31960 | .union_type => @panic("TODO"), |
| 31909 | 31961 | else => return ty, |
| 31910 | 31962 | }, |
| ... | ... | @@ -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 | 33065 | .tuple, .anon_struct => { |
| 33036 | 33066 | const tuple = ty.tupleFields(); |
| 33037 | 33067 | for (tuple.values, 0..) |val, i| { |
| ... | ... | @@ -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 | 33153 | .array => { |
| 33126 | 33154 | if (ty.arrayLen(mod) == 0) |
| 33127 | 33155 | return Value.initTag(.empty_array); |
| ... | ... | @@ -33212,7 +33240,34 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 33212 | 33240 | .generic_poison => return error.GenericPoison, |
| 33213 | 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 | 33271 | .union_type => @panic("TODO"), |
| 33217 | 33272 | .opaque_type => null, |
| 33218 | 33273 | |
| ... | ... | @@ -33223,6 +33278,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 33223 | 33278 | .ptr => unreachable, |
| 33224 | 33279 | .opt => unreachable, |
| 33225 | 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 | 33670 | .empty_struct_type => false, |
| 33615 | 33671 | |
| 33616 | 33672 | .none => switch (ty.tag()) { |
| 33617 | .empty_struct, | |
| 33618 | 33673 | .error_set, |
| 33619 | 33674 | .error_set_single, |
| 33620 | 33675 | .error_set_inferred, |
| ... | ... | @@ -33655,31 +33710,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 33655 | 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 | 33713 | .@"union", .union_safety_tagged, .union_tagged => { |
| 33684 | 33714 | const union_obj = ty.cast(Type.Payload.Union).?.data; |
| 33685 | 33715 | switch (union_obj.requires_comptime) { |
| ... | ... | @@ -33782,7 +33812,31 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 33782 | 33812 | |
| 33783 | 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 | 33840 | .union_type => @panic("TODO"), |
| 33787 | 33841 | .opaque_type => false, |
| 33788 | 33842 | |
| ... | ... | @@ -33793,6 +33847,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 33793 | 33847 | .ptr => unreachable, |
| 33794 | 33848 | .opt => unreachable, |
| 33795 | 33849 | .enum_tag => unreachable, |
| 33850 | .aggregate => unreachable, | |
| 33796 | 33851 | }, |
| 33797 | 33852 | }; |
| 33798 | 33853 | } |
| ... | ... | @@ -33864,11 +33919,12 @@ fn structFieldIndex( |
| 33864 | 33919 | field_name: []const u8, |
| 33865 | 33920 | field_src: LazySrcLoc, |
| 33866 | 33921 | ) !u32 { |
| 33922 | const mod = sema.mod; | |
| 33867 | 33923 | const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty); |
| 33868 | 33924 | if (struct_ty.isAnonStruct()) { |
| 33869 | 33925 | return sema.anonStructFieldIndex(block, struct_ty, field_name, field_src); |
| 33870 | 33926 | } else { |
| 33871 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | |
| 33927 | const struct_obj = mod.typeToStruct(struct_ty).?; | |
| 33872 | 33928 | const field_index_usize = struct_obj.fields.getIndex(field_name) orelse |
| 33873 | 33929 | return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name); |
| 33874 | 33930 | return @intCast(u32, field_index_usize); |
src/TypedValue.zig+13-7| ... | ... | @@ -180,7 +180,7 @@ pub fn print( |
| 180 | 180 | switch (field_ptr.container_ty.tag()) { |
| 181 | 181 | .tuple => return writer.print(".@\"{d}\"", .{field_ptr.field_index}), |
| 182 | 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 | 184 | return writer.print(".{s}", .{field_name}); |
| 185 | 185 | }, |
| 186 | 186 | } |
| ... | ... | @@ -381,21 +381,27 @@ fn printAggregate( |
| 381 | 381 | } |
| 382 | 382 | if (ty.zigTypeTag(mod) == .Struct) { |
| 383 | 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 | 386 | var i: u32 = 0; |
| 387 | 387 | while (i < max_len) : (i += 1) { |
| 388 | 388 | if (i != 0) try writer.writeAll(", "); |
| 389 | switch (ty.tag()) { | |
| 390 | .anon_struct, .@"struct" => try writer.print(".{s} = ", .{ty.structFieldName(i)}), | |
| 391 | else => {}, | |
| 389 | switch (ty.ip_index) { | |
| 390 | .none => switch (ty.tag()) { | |
| 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 | 399 | try print(.{ |
| 394 | .ty = ty.structFieldType(i), | |
| 400 | .ty = ty.structFieldType(i, mod), | |
| 395 | 401 | .val = try val.fieldValue(ty, mod, i), |
| 396 | 402 | }, writer, level - 1, mod); |
| 397 | 403 | } |
| 398 | if (ty.structFieldCount() > max_aggregate_items) { | |
| 404 | if (ty.structFieldCount(mod) > max_aggregate_items) { | |
| 399 | 405 | try writer.writeAll(", ..."); |
| 400 | 406 | } |
| 401 | 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 | 4119 | const mod = self.bin_file.options.module.?; |
| 4120 | 4120 | const mcv = try self.resolveInst(operand); |
| 4121 | 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 | 4123 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod)); |
| 4124 | 4124 | |
| 4125 | 4125 | switch (mcv) { |
| ... | ... | @@ -5466,10 +5466,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 5466 | 5466 | const reg_lock = self.register_manager.lockReg(rwo.reg); |
| 5467 | 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 | 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 | 5473 | const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod)); |
| 5474 | 5474 | const raw_cond_reg = try self.register_manager.allocReg(null, gp); |
| 5475 | 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 | 21 | var maybe_float_bits: ?u16 = null; |
| 22 | 22 | switch (ty.zigTypeTag(mod)) { |
| 23 | 23 | .Struct => { |
| 24 | if (ty.containerLayout() == .Packed) return .byval; | |
| 24 | if (ty.containerLayout(mod) == .Packed) return .byval; | |
| 25 | 25 | const float_count = countFloats(ty, mod, &maybe_float_bits); |
| 26 | 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 | 31 | return .integer; |
| 32 | 32 | }, |
| 33 | 33 | .Union => { |
| 34 | if (ty.containerLayout() == .Packed) return .byval; | |
| 34 | if (ty.containerLayout(mod) == .Packed) return .byval; | |
| 35 | 35 | const float_count = countFloats(ty, mod, &maybe_float_bits); |
| 36 | 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 | 90 | return max_count; |
| 91 | 91 | }, |
| 92 | 92 | .Struct => { |
| 93 | const fields_len = ty.structFieldCount(); | |
| 93 | const fields_len = ty.structFieldCount(mod); | |
| 94 | 94 | var count: u8 = 0; |
| 95 | 95 | var i: u32 = 0; |
| 96 | 96 | while (i < fields_len) : (i += 1) { |
| 97 | const field_ty = ty.structFieldType(i); | |
| 97 | const field_ty = ty.structFieldType(i, mod); | |
| 98 | 98 | const field_count = countFloats(field_ty, mod, maybe_float_bits); |
| 99 | 99 | if (field_count == invalid) return invalid; |
| 100 | 100 | count += field_count; |
| ... | ... | @@ -125,10 +125,10 @@ pub fn getFloatArrayType(ty: Type, mod: *Module) ?Type { |
| 125 | 125 | return null; |
| 126 | 126 | }, |
| 127 | 127 | .Struct => { |
| 128 | const fields_len = ty.structFieldCount(); | |
| 128 | const fields_len = ty.structFieldCount(mod); | |
| 129 | 129 | var i: u32 = 0; |
| 130 | 130 | while (i < fields_len) : (i += 1) { |
| 131 | const field_ty = ty.structFieldType(i); | |
| 131 | const field_ty = ty.structFieldType(i, mod); | |
| 132 | 132 | if (getFloatArrayType(field_ty, mod)) |some| return some; |
| 133 | 133 | } |
| 134 | 134 | return null; |
src/arch/arm/CodeGen.zig+3-3| ... | ... | @@ -2910,7 +2910,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2910 | 2910 | const mcv = try self.resolveInst(operand); |
| 2911 | 2911 | const struct_ty = self.typeOf(operand); |
| 2912 | 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 | 2915 | switch (mcv) { |
| 2916 | 2916 | .dead, .unreach => unreachable, |
| ... | ... | @@ -5404,10 +5404,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 5404 | 5404 | const reg_lock = self.register_manager.lockReg(reg); |
| 5405 | 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 | 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 | 5411 | const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod)); |
| 5412 | 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 | 32 | switch (ty.zigTypeTag(mod)) { |
| 33 | 33 | .Struct => { |
| 34 | 34 | const bit_size = ty.bitSize(mod); |
| 35 | if (ty.containerLayout() == .Packed) { | |
| 35 | if (ty.containerLayout(mod) == .Packed) { | |
| 36 | 36 | if (bit_size > 64) return .memory; |
| 37 | 37 | return .byval; |
| 38 | 38 | } |
| ... | ... | @@ -40,10 +40,10 @@ pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class { |
| 40 | 40 | const float_count = countFloats(ty, mod, &maybe_float_bits); |
| 41 | 41 | if (float_count <= byval_float_count) return .byval; |
| 42 | 42 | |
| 43 | const fields = ty.structFieldCount(); | |
| 43 | const fields = ty.structFieldCount(mod); | |
| 44 | 44 | var i: u32 = 0; |
| 45 | 45 | while (i < fields) : (i += 1) { |
| 46 | const field_ty = ty.structFieldType(i); | |
| 46 | const field_ty = ty.structFieldType(i, mod); | |
| 47 | 47 | const field_alignment = ty.structFieldAlign(i, mod); |
| 48 | 48 | const field_size = field_ty.bitSize(mod); |
| 49 | 49 | if (field_size > 32 or field_alignment > 32) { |
| ... | ... | @@ -54,7 +54,7 @@ pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class { |
| 54 | 54 | }, |
| 55 | 55 | .Union => { |
| 56 | 56 | const bit_size = ty.bitSize(mod); |
| 57 | if (ty.containerLayout() == .Packed) { | |
| 57 | if (ty.containerLayout(mod) == .Packed) { | |
| 58 | 58 | if (bit_size > 64) return .memory; |
| 59 | 59 | return .byval; |
| 60 | 60 | } |
| ... | ... | @@ -132,11 +132,11 @@ fn countFloats(ty: Type, mod: *Module, maybe_float_bits: *?u16) u32 { |
| 132 | 132 | return max_count; |
| 133 | 133 | }, |
| 134 | 134 | .Struct => { |
| 135 | const fields_len = ty.structFieldCount(); | |
| 135 | const fields_len = ty.structFieldCount(mod); | |
| 136 | 136 | var count: u32 = 0; |
| 137 | 137 | var i: u32 = 0; |
| 138 | 138 | while (i < fields_len) : (i += 1) { |
| 139 | const field_ty = ty.structFieldType(i); | |
| 139 | const field_ty = ty.structFieldType(i, mod); | |
| 140 | 140 | const field_count = countFloats(field_ty, mod, maybe_float_bits); |
| 141 | 141 | if (field_count == invalid) return invalid; |
| 142 | 142 | count += field_count; |
src/arch/riscv64/abi.zig+2-2| ... | ... | @@ -15,7 +15,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class { |
| 15 | 15 | switch (ty.zigTypeTag(mod)) { |
| 16 | 16 | .Struct => { |
| 17 | 17 | const bit_size = ty.bitSize(mod); |
| 18 | if (ty.containerLayout() == .Packed) { | |
| 18 | if (ty.containerLayout(mod) == .Packed) { | |
| 19 | 19 | if (bit_size > max_byval_size) return .memory; |
| 20 | 20 | return .byval; |
| 21 | 21 | } |
| ... | ... | @@ -26,7 +26,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class { |
| 26 | 26 | }, |
| 27 | 27 | .Union => { |
| 28 | 28 | const bit_size = ty.bitSize(mod); |
| 29 | if (ty.containerLayout() == .Packed) { | |
| 29 | if (ty.containerLayout(mod) == .Packed) { | |
| 30 | 30 | if (bit_size > max_byval_size) return .memory; |
| 31 | 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 | 3993 | const reg_lock = self.register_manager.lockReg(rwo.reg); |
| 3994 | 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 | 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 | 4000 | const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod)); |
| 4001 | 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 | 1006 | if (info.bits > 32 and info.bits <= 128) break :blk wasm.Valtype.i64; |
| 1007 | 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 | 1010 | .Packed => { |
| 1011 | const struct_obj = ty.castTag(.@"struct").?.data; | |
| 1011 | const struct_obj = mod.typeToStruct(ty).?; | |
| 1012 | 1012 | return typeToValtype(struct_obj.backing_int_ty, mod); |
| 1013 | 1013 | }, |
| 1014 | 1014 | else => wasm.Valtype.i32, |
| ... | ... | @@ -1017,7 +1017,7 @@ fn typeToValtype(ty: Type, mod: *Module) wasm.Valtype { |
| 1017 | 1017 | .direct => wasm.Valtype.v128, |
| 1018 | 1018 | .unrolled => wasm.Valtype.i32, |
| 1019 | 1019 | }, |
| 1020 | .Union => switch (ty.containerLayout()) { | |
| 1020 | .Union => switch (ty.containerLayout(mod)) { | |
| 1021 | 1021 | .Packed => { |
| 1022 | 1022 | const int_ty = mod.intType(.unsigned, @intCast(u16, ty.bitSize(mod))) catch @panic("out of memory"); |
| 1023 | 1023 | return typeToValtype(int_ty, mod); |
| ... | ... | @@ -1747,8 +1747,7 @@ fn isByRef(ty: Type, mod: *Module) bool { |
| 1747 | 1747 | return ty.hasRuntimeBitsIgnoreComptime(mod); |
| 1748 | 1748 | }, |
| 1749 | 1749 | .Struct => { |
| 1750 | if (ty.castTag(.@"struct")) |struct_ty| { | |
| 1751 | const struct_obj = struct_ty.data; | |
| 1750 | if (mod.typeToStruct(ty)) |struct_obj| { | |
| 1752 | 1751 | if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) { |
| 1753 | 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 | 2953 | const parent_ty = field_ptr.container_ty; |
| 2955 | 2954 | |
| 2956 | 2955 | const field_offset = switch (parent_ty.zigTypeTag(mod)) { |
| 2957 | .Struct => switch (parent_ty.containerLayout()) { | |
| 2956 | .Struct => switch (parent_ty.containerLayout(mod)) { | |
| 2958 | 2957 | .Packed => parent_ty.packedStructFieldByteOffset(field_ptr.field_index, mod), |
| 2959 | 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 | 2961 | .Packed => 0, |
| 2963 | 2962 | else => blk: { |
| 2964 | 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 | 3157 | return WValue{ .imm32 = @boolToInt(is_pl) }; |
| 3159 | 3158 | }, |
| 3160 | 3159 | .Struct => { |
| 3161 | const struct_obj = ty.castTag(.@"struct").?.data; | |
| 3160 | const struct_obj = mod.typeToStruct(ty).?; | |
| 3162 | 3161 | assert(struct_obj.layout == .Packed); |
| 3163 | 3162 | var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer |
| 3164 | 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 | 3224 | return WValue{ .imm32 = 0xaaaaaaaa }; |
| 3226 | 3225 | }, |
| 3227 | 3226 | .Struct => { |
| 3228 | const struct_obj = ty.castTag(.@"struct").?.data; | |
| 3227 | const struct_obj = mod.typeToStruct(ty).?; | |
| 3229 | 3228 | assert(struct_obj.layout == .Packed); |
| 3230 | 3229 | return func.emitUndefined(struct_obj.backing_int_ty); |
| 3231 | 3230 | }, |
| ... | ... | @@ -3635,7 +3634,7 @@ fn structFieldPtr( |
| 3635 | 3634 | ) InnerError!WValue { |
| 3636 | 3635 | const mod = func.bin_file.base.options.module.?; |
| 3637 | 3636 | const result_ty = func.typeOfIndex(inst); |
| 3638 | const offset = switch (struct_ty.containerLayout()) { | |
| 3637 | const offset = switch (struct_ty.containerLayout(mod)) { | |
| 3639 | 3638 | .Packed => switch (struct_ty.zigTypeTag(mod)) { |
| 3640 | 3639 | .Struct => offset: { |
| 3641 | 3640 | if (result_ty.ptrInfo(mod).host_size != 0) { |
| ... | ... | @@ -3668,13 +3667,13 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3668 | 3667 | const struct_ty = func.typeOf(struct_field.struct_operand); |
| 3669 | 3668 | const operand = try func.resolveInst(struct_field.struct_operand); |
| 3670 | 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 | 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 | 3674 | .Packed => switch (struct_ty.zigTypeTag(mod)) { |
| 3676 | 3675 | .Struct => result: { |
| 3677 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | |
| 3676 | const struct_obj = mod.typeToStruct(struct_ty).?; | |
| 3678 | 3677 | const offset = struct_obj.packedFieldBitOffset(mod, field_index); |
| 3679 | 3678 | const backing_ty = struct_obj.backing_int_ty; |
| 3680 | 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 | 4997 | } |
| 4999 | 4998 | break :result_value result; |
| 5000 | 4999 | }, |
| 5001 | .Struct => switch (result_ty.containerLayout()) { | |
| 5000 | .Struct => switch (result_ty.containerLayout(mod)) { | |
| 5002 | 5001 | .Packed => { |
| 5003 | 5002 | if (isByRef(result_ty, mod)) { |
| 5004 | 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 | 5006 | const fields = struct_obj.fields.values(); |
| 5008 | 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 | 5050 | for (elements, 0..) |elem, elem_index| { |
| 5052 | 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 | 5054 | const elem_size = @intCast(u32, elem_ty.abiSize(mod)); |
| 5056 | 5055 | const value = try func.resolveInst(elem); |
| 5057 | 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 | 26 | if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return none; |
| 27 | 27 | switch (ty.zigTypeTag(mod)) { |
| 28 | 28 | .Struct => { |
| 29 | if (ty.containerLayout() == .Packed) { | |
| 29 | if (ty.containerLayout(mod) == .Packed) { | |
| 30 | 30 | if (ty.bitSize(mod) <= 64) return direct; |
| 31 | 31 | return .{ .direct, .direct }; |
| 32 | 32 | } |
| 33 | 33 | // When the struct type is non-scalar |
| 34 | if (ty.structFieldCount() > 1) return memory; | |
| 34 | if (ty.structFieldCount(mod) > 1) return memory; | |
| 35 | 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 | 37 | if (field.abi_align != 0) { |
| 38 | 38 | if (field.abi_align > field.ty.abiAlignment(mod)) { |
| 39 | 39 | return memory; |
| ... | ... | @@ -64,7 +64,7 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class { |
| 64 | 64 | return direct; |
| 65 | 65 | }, |
| 66 | 66 | .Union => { |
| 67 | if (ty.containerLayout() == .Packed) { | |
| 67 | if (ty.containerLayout(mod) == .Packed) { | |
| 68 | 68 | if (ty.bitSize(mod) <= 64) return direct; |
| 69 | 69 | return .{ .direct, .direct }; |
| 70 | 70 | } |
| ... | ... | @@ -96,19 +96,19 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class { |
| 96 | 96 | pub fn scalarType(ty: Type, mod: *Module) Type { |
| 97 | 97 | switch (ty.zigTypeTag(mod)) { |
| 98 | 98 | .Struct => { |
| 99 | switch (ty.containerLayout()) { | |
| 99 | switch (ty.containerLayout(mod)) { | |
| 100 | 100 | .Packed => { |
| 101 | const struct_obj = ty.castTag(.@"struct").?.data; | |
| 101 | const struct_obj = mod.typeToStruct(ty).?; | |
| 102 | 102 | return scalarType(struct_obj.backing_int_ty, mod); |
| 103 | 103 | }, |
| 104 | 104 | else => { |
| 105 | std.debug.assert(ty.structFieldCount() == 1); | |
| 106 | return scalarType(ty.structFieldType(0), mod); | |
| 105 | std.debug.assert(ty.structFieldCount(mod) == 1); | |
| 106 | return scalarType(ty.structFieldType(0, mod), mod); | |
| 107 | 107 | }, |
| 108 | 108 | } |
| 109 | 109 | }, |
| 110 | 110 | .Union => { |
| 111 | if (ty.containerLayout() != .Packed) { | |
| 111 | if (ty.containerLayout(mod) != .Packed) { | |
| 112 | 112 | const layout = ty.unionGetLayout(mod); |
| 113 | 113 | if (layout.payload_size == 0 and layout.tag_size != 0) { |
| 114 | 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 | 3252 | try self.genSetMem( |
| 3253 | 3253 | .{ .frame = frame_index }, |
| 3254 | 3254 | @intCast(i32, tuple_ty.structFieldOffset(1, mod)), |
| 3255 | tuple_ty.structFieldType(1), | |
| 3255 | tuple_ty.structFieldType(1, mod), | |
| 3256 | 3256 | .{ .eflags = cc }, |
| 3257 | 3257 | ); |
| 3258 | 3258 | try self.genSetMem( |
| 3259 | 3259 | .{ .frame = frame_index }, |
| 3260 | 3260 | @intCast(i32, tuple_ty.structFieldOffset(0, mod)), |
| 3261 | tuple_ty.structFieldType(0), | |
| 3261 | tuple_ty.structFieldType(0, mod), | |
| 3262 | 3262 | partial_mcv, |
| 3263 | 3263 | ); |
| 3264 | 3264 | break :result .{ .load_frame = .{ .index = frame_index } }; |
| ... | ... | @@ -3289,7 +3289,7 @@ fn genSetFrameTruncatedOverflowCompare( |
| 3289 | 3289 | }; |
| 3290 | 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 | 3293 | const int_info = ty.intInfo(mod); |
| 3294 | 3294 | |
| 3295 | 3295 | const hi_limb_bits = (int_info.bits - 1) % 64 + 1; |
| ... | ... | @@ -3336,7 +3336,7 @@ fn genSetFrameTruncatedOverflowCompare( |
| 3336 | 3336 | try self.genSetMem( |
| 3337 | 3337 | .{ .frame = frame_index }, |
| 3338 | 3338 | @intCast(i32, tuple_ty.structFieldOffset(1, mod)), |
| 3339 | tuple_ty.structFieldType(1), | |
| 3339 | tuple_ty.structFieldType(1, mod), | |
| 3340 | 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 | 3393 | try self.genSetMem( |
| 3394 | 3394 | .{ .frame = frame_index }, |
| 3395 | 3395 | @intCast(i32, tuple_ty.structFieldOffset(0, mod)), |
| 3396 | tuple_ty.structFieldType(0), | |
| 3396 | tuple_ty.structFieldType(0, mod), | |
| 3397 | 3397 | partial_mcv, |
| 3398 | 3398 | ); |
| 3399 | 3399 | try self.genSetMem( |
| 3400 | 3400 | .{ .frame = frame_index }, |
| 3401 | 3401 | @intCast(i32, tuple_ty.structFieldOffset(1, mod)), |
| 3402 | tuple_ty.structFieldType(1), | |
| 3402 | tuple_ty.structFieldType(1, mod), | |
| 3403 | 3403 | .{ .immediate = 0 }, // cc being set is impossible |
| 3404 | 3404 | ); |
| 3405 | 3405 | } else try self.genSetFrameTruncatedOverflowCompare( |
| ... | ... | @@ -5563,7 +5563,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32 |
| 5563 | 5563 | const ptr_field_ty = self.typeOfIndex(inst); |
| 5564 | 5564 | const ptr_container_ty = self.typeOf(operand); |
| 5565 | 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 | 5567 | .Auto, .Extern => container_ty.structFieldOffset(index, mod), |
| 5568 | 5568 | .Packed => if (container_ty.zigTypeTag(mod) == .Struct and |
| 5569 | 5569 | ptr_field_ty.ptrInfo(mod).host_size == 0) |
| ... | ... | @@ -5591,16 +5591,16 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5591 | 5591 | |
| 5592 | 5592 | const container_ty = self.typeOf(operand); |
| 5593 | 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 | 5595 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none; |
| 5596 | 5596 | const field_rc = regClassForType(field_ty, mod); |
| 5597 | 5597 | const field_is_gp = field_rc.supersetOf(gp); |
| 5598 | 5598 | |
| 5599 | 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 | 5601 | .Auto, .Extern => @intCast(u32, container_ty.structFieldOffset(index, mod) * 8), |
| 5602 | .Packed => if (container_ty.castTag(.@"struct")) |struct_obj| | |
| 5603 | struct_obj.data.packedFieldBitOffset(mod, index) | |
| 5602 | .Packed => if (mod.typeToStruct(container_ty)) |struct_obj| | |
| 5603 | struct_obj.packedFieldBitOffset(mod, index) | |
| 5604 | 5604 | else |
| 5605 | 5605 | 0, |
| 5606 | 5606 | }; |
| ... | ... | @@ -10036,13 +10036,13 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal |
| 10036 | 10036 | try self.genSetMem( |
| 10037 | 10037 | base, |
| 10038 | 10038 | disp + @intCast(i32, ty.structFieldOffset(0, mod)), |
| 10039 | ty.structFieldType(0), | |
| 10039 | ty.structFieldType(0, mod), | |
| 10040 | 10040 | .{ .register = ro.reg }, |
| 10041 | 10041 | ); |
| 10042 | 10042 | try self.genSetMem( |
| 10043 | 10043 | base, |
| 10044 | 10044 | disp + @intCast(i32, ty.structFieldOffset(1, mod)), |
| 10045 | ty.structFieldType(1), | |
| 10045 | ty.structFieldType(1, mod), | |
| 10046 | 10046 | .{ .eflags = ro.eflags }, |
| 10047 | 10047 | ); |
| 10048 | 10048 | }, |
| ... | ... | @@ -11259,8 +11259,8 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 11259 | 11259 | .Struct => { |
| 11260 | 11260 | const frame_index = |
| 11261 | 11261 | try self.allocFrameIndex(FrameAlloc.initType(result_ty, mod)); |
| 11262 | if (result_ty.containerLayout() == .Packed) { | |
| 11263 | const struct_obj = result_ty.castTag(.@"struct").?.data; | |
| 11262 | if (result_ty.containerLayout(mod) == .Packed) { | |
| 11263 | const struct_obj = mod.typeToStruct(result_ty).?; | |
| 11264 | 11264 | try self.genInlineMemset( |
| 11265 | 11265 | .{ .lea_frame = .{ .index = frame_index } }, |
| 11266 | 11266 | .{ .immediate = 0 }, |
| ... | ... | @@ -11269,7 +11269,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 11269 | 11269 | for (elements, 0..) |elem, elem_i| { |
| 11270 | 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 | 11273 | const elem_bit_size = @intCast(u32, elem_ty.bitSize(mod)); |
| 11274 | 11274 | if (elem_bit_size > 64) { |
| 11275 | 11275 | return self.fail( |
| ... | ... | @@ -11341,7 +11341,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 11341 | 11341 | } else for (elements, 0..) |elem, elem_i| { |
| 11342 | 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 | 11345 | const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, mod)); |
| 11346 | 11346 | const elem_mcv = try self.resolveInst(elem); |
| 11347 | 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 | 41 | 1, 2, 4, 8 => return .integer, |
| 42 | 42 | else => switch (ty.zigTypeTag(mod)) { |
| 43 | 43 | .Int => return .win_i128, |
| 44 | .Struct, .Union => if (ty.containerLayout() == .Packed) { | |
| 44 | .Struct, .Union => if (ty.containerLayout(mod) == .Packed) { | |
| 45 | 45 | return .win_i128; |
| 46 | 46 | } else { |
| 47 | 47 | return .memory; |
| ... | ... | @@ -210,7 +210,7 @@ pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class { |
| 210 | 210 | // "If the size of the aggregate exceeds a single eightbyte, each is classified |
| 211 | 211 | // separately.". |
| 212 | 212 | const ty_size = ty.abiSize(mod); |
| 213 | if (ty.containerLayout() == .Packed) { | |
| 213 | if (ty.containerLayout(mod) == .Packed) { | |
| 214 | 214 | assert(ty_size <= 128); |
| 215 | 215 | result[0] = .integer; |
| 216 | 216 | if (ty_size > 64) result[1] = .integer; |
| ... | ... | @@ -221,7 +221,7 @@ pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class { |
| 221 | 221 | |
| 222 | 222 | var result_i: usize = 0; // out of 8 |
| 223 | 223 | var byte_i: usize = 0; // out of 8 |
| 224 | const fields = ty.structFields(); | |
| 224 | const fields = ty.structFields(mod); | |
| 225 | 225 | for (fields.values()) |field| { |
| 226 | 226 | if (field.abi_align != 0) { |
| 227 | 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 | 329 | // "If the size of the aggregate exceeds a single eightbyte, each is classified |
| 330 | 330 | // separately.". |
| 331 | 331 | const ty_size = ty.abiSize(mod); |
| 332 | if (ty.containerLayout() == .Packed) { | |
| 332 | if (ty.containerLayout(mod) == .Packed) { | |
| 333 | 333 | assert(ty_size <= 128); |
| 334 | 334 | result[0] = .integer; |
| 335 | 335 | if (ty_size > 64) result[1] = .integer; |
src/codegen.zig+3-3| ... | ... | @@ -503,8 +503,8 @@ pub fn generateSymbol( |
| 503 | 503 | return Result.ok; |
| 504 | 504 | }, |
| 505 | 505 | .Struct => { |
| 506 | if (typed_value.ty.containerLayout() == .Packed) { | |
| 507 | const struct_obj = typed_value.ty.castTag(.@"struct").?.data; | |
| 506 | if (typed_value.ty.containerLayout(mod) == .Packed) { | |
| 507 | const struct_obj = mod.typeToStruct(typed_value.ty).?; | |
| 508 | 508 | const fields = struct_obj.fields.values(); |
| 509 | 509 | const field_vals = typed_value.val.castTag(.aggregate).?.data; |
| 510 | 510 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow; |
| ... | ... | @@ -539,7 +539,7 @@ pub fn generateSymbol( |
| 539 | 539 | const struct_begin = code.items.len; |
| 540 | 540 | const field_vals = typed_value.val.castTag(.aggregate).?.data; |
| 541 | 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 | 543 | if (!field_ty.hasRuntimeBits(mod)) continue; |
| 544 | 544 | |
| 545 | 545 | switch (try generateSymbol(bin_file, src_loc, .{ |
src/codegen/c.zig+119-109| ... | ... | @@ -820,7 +820,7 @@ pub const DeclGen = struct { |
| 820 | 820 | try dg.renderValue(writer, Type.bool, val, initializer_type); |
| 821 | 821 | return writer.writeAll(" }"); |
| 822 | 822 | }, |
| 823 | .Struct => switch (ty.containerLayout()) { | |
| 823 | .Struct => switch (ty.containerLayout(mod)) { | |
| 824 | 824 | .Auto, .Extern => { |
| 825 | 825 | if (!location.isInitializer()) { |
| 826 | 826 | try writer.writeByte('('); |
| ... | ... | @@ -830,9 +830,9 @@ pub const DeclGen = struct { |
| 830 | 830 | |
| 831 | 831 | try writer.writeByte('{'); |
| 832 | 832 | var empty = true; |
| 833 | for (0..ty.structFieldCount()) |field_i| { | |
| 834 | if (ty.structFieldIsComptime(field_i)) continue; | |
| 835 | const field_ty = ty.structFieldType(field_i); | |
| 833 | for (0..ty.structFieldCount(mod)) |field_i| { | |
| 834 | if (ty.structFieldIsComptime(field_i, mod)) continue; | |
| 835 | const field_ty = ty.structFieldType(field_i, mod); | |
| 836 | 836 | if (!field_ty.hasRuntimeBits(mod)) continue; |
| 837 | 837 | |
| 838 | 838 | if (!empty) try writer.writeByte(','); |
| ... | ... | @@ -1328,7 +1328,7 @@ pub const DeclGen = struct { |
| 1328 | 1328 | }, |
| 1329 | 1329 | else => unreachable, |
| 1330 | 1330 | }, |
| 1331 | .Struct => switch (ty.containerLayout()) { | |
| 1331 | .Struct => switch (ty.containerLayout(mod)) { | |
| 1332 | 1332 | .Auto, .Extern => { |
| 1333 | 1333 | const field_vals = val.castTag(.aggregate).?.data; |
| 1334 | 1334 | |
| ... | ... | @@ -1341,8 +1341,8 @@ pub const DeclGen = struct { |
| 1341 | 1341 | try writer.writeByte('{'); |
| 1342 | 1342 | var empty = true; |
| 1343 | 1343 | for (field_vals, 0..) |field_val, field_i| { |
| 1344 | if (ty.structFieldIsComptime(field_i)) continue; | |
| 1345 | const field_ty = ty.structFieldType(field_i); | |
| 1344 | if (ty.structFieldIsComptime(field_i, mod)) continue; | |
| 1345 | const field_ty = ty.structFieldType(field_i, mod); | |
| 1346 | 1346 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1347 | 1347 | |
| 1348 | 1348 | if (!empty) try writer.writeByte(','); |
| ... | ... | @@ -1363,8 +1363,8 @@ pub const DeclGen = struct { |
| 1363 | 1363 | |
| 1364 | 1364 | var eff_num_fields: usize = 0; |
| 1365 | 1365 | for (0..field_vals.len) |field_i| { |
| 1366 | if (ty.structFieldIsComptime(field_i)) continue; | |
| 1367 | const field_ty = ty.structFieldType(field_i); | |
| 1366 | if (ty.structFieldIsComptime(field_i, mod)) continue; | |
| 1367 | const field_ty = ty.structFieldType(field_i, mod); | |
| 1368 | 1368 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1369 | 1369 | |
| 1370 | 1370 | eff_num_fields += 1; |
| ... | ... | @@ -1386,8 +1386,8 @@ pub const DeclGen = struct { |
| 1386 | 1386 | var eff_index: usize = 0; |
| 1387 | 1387 | var needs_closing_paren = false; |
| 1388 | 1388 | for (field_vals, 0..) |field_val, field_i| { |
| 1389 | if (ty.structFieldIsComptime(field_i)) continue; | |
| 1390 | const field_ty = ty.structFieldType(field_i); | |
| 1389 | if (ty.structFieldIsComptime(field_i, mod)) continue; | |
| 1390 | const field_ty = ty.structFieldType(field_i, mod); | |
| 1391 | 1391 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1392 | 1392 | |
| 1393 | 1393 | const cast_context = IntCastContext{ .value = .{ .value = field_val } }; |
| ... | ... | @@ -1416,8 +1416,8 @@ pub const DeclGen = struct { |
| 1416 | 1416 | // a << a_off | b << b_off | c << c_off |
| 1417 | 1417 | var empty = true; |
| 1418 | 1418 | for (field_vals, 0..) |field_val, field_i| { |
| 1419 | if (ty.structFieldIsComptime(field_i)) continue; | |
| 1420 | const field_ty = ty.structFieldType(field_i); | |
| 1419 | if (ty.structFieldIsComptime(field_i, mod)) continue; | |
| 1420 | const field_ty = ty.structFieldType(field_i, mod); | |
| 1421 | 1421 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1422 | 1422 | |
| 1423 | 1423 | if (!empty) try writer.writeAll(" | "); |
| ... | ... | @@ -1453,7 +1453,7 @@ pub const DeclGen = struct { |
| 1453 | 1453 | const field_i = ty.unionTagFieldIndex(union_obj.tag, mod).?; |
| 1454 | 1454 | const field_ty = ty.unionFields().values()[field_i].ty; |
| 1455 | 1455 | const field_name = ty.unionFields().keys()[field_i]; |
| 1456 | if (ty.containerLayout() == .Packed) { | |
| 1456 | if (ty.containerLayout(mod) == .Packed) { | |
| 1457 | 1457 | if (field_ty.hasRuntimeBits(mod)) { |
| 1458 | 1458 | if (field_ty.isPtrAtRuntime(mod)) { |
| 1459 | 1459 | try writer.writeByte('('); |
| ... | ... | @@ -5218,25 +5218,25 @@ fn fieldLocation( |
| 5218 | 5218 | end: void, |
| 5219 | 5219 | } { |
| 5220 | 5220 | return switch (container_ty.zigTypeTag(mod)) { |
| 5221 | .Struct => switch (container_ty.containerLayout()) { | |
| 5222 | .Auto, .Extern => for (field_index..container_ty.structFieldCount()) |next_field_index| { | |
| 5223 | if (container_ty.structFieldIsComptime(next_field_index)) continue; | |
| 5224 | const field_ty = container_ty.structFieldType(next_field_index); | |
| 5221 | .Struct => switch (container_ty.containerLayout(mod)) { | |
| 5222 | .Auto, .Extern => for (field_index..container_ty.structFieldCount(mod)) |next_field_index| { | |
| 5223 | if (container_ty.structFieldIsComptime(next_field_index, mod)) continue; | |
| 5224 | const field_ty = container_ty.structFieldType(next_field_index, mod); | |
| 5225 | 5225 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 5226 | 5226 | |
| 5227 | 5227 | break .{ .field = if (container_ty.isSimpleTuple()) |
| 5228 | 5228 | .{ .field = next_field_index } |
| 5229 | 5229 | else |
| 5230 | .{ .identifier = container_ty.structFieldName(next_field_index) } }; | |
| 5230 | .{ .identifier = container_ty.structFieldName(next_field_index, mod) } }; | |
| 5231 | 5231 | } else if (container_ty.hasRuntimeBitsIgnoreComptime(mod)) .end else .begin, |
| 5232 | 5232 | .Packed => if (field_ptr_ty.ptrInfo(mod).host_size == 0) |
| 5233 | 5233 | .{ .byte_offset = container_ty.packedStructFieldByteOffset(field_index, mod) } |
| 5234 | 5234 | else |
| 5235 | 5235 | .begin, |
| 5236 | 5236 | }, |
| 5237 | .Union => switch (container_ty.containerLayout()) { | |
| 5237 | .Union => switch (container_ty.containerLayout(mod)) { | |
| 5238 | 5238 | .Auto, .Extern => { |
| 5239 | const field_ty = container_ty.structFieldType(field_index); | |
| 5239 | const field_ty = container_ty.structFieldType(field_index, mod); | |
| 5240 | 5240 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) |
| 5241 | 5241 | return if (container_ty.unionTagTypeSafety() != null and |
| 5242 | 5242 | !container_ty.unionHasAllZeroBitFieldTypes(mod)) |
| ... | ... | @@ -5417,101 +5417,111 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5417 | 5417 | // Ensure complete type definition is visible before accessing fields. |
| 5418 | 5418 | _ = try f.typeToIndex(struct_ty, .complete); |
| 5419 | 5419 | |
| 5420 | const field_name: CValue = switch (struct_ty.tag()) { | |
| 5421 | .tuple, .anon_struct, .@"struct" => switch (struct_ty.containerLayout()) { | |
| 5422 | .Auto, .Extern => if (struct_ty.isSimpleTuple()) | |
| 5420 | const field_name: CValue = switch (struct_ty.ip_index) { | |
| 5421 | .none => switch (struct_ty.tag()) { | |
| 5422 | .tuple, .anon_struct => if (struct_ty.isSimpleTuple()) | |
| 5423 | 5423 | .{ .field = extra.field_index } |
| 5424 | 5424 | else |
| 5425 | .{ .identifier = struct_ty.structFieldName(extra.field_index) }, | |
| 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); | |
| 5425 | .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) }, | |
| 5434 | 5426 | |
| 5435 | const field_int_signedness = if (inst_ty.isAbiInt(mod)) | |
| 5436 | inst_ty.intInfo(mod).signedness | |
| 5437 | else | |
| 5438 | .unsigned; | |
| 5439 | const field_int_ty = try mod.intType(field_int_signedness, @intCast(u16, inst_ty.bitSize(mod))); | |
| 5440 | ||
| 5441 | const temp_local = try f.allocLocal(inst, field_int_ty); | |
| 5442 | try f.writeCValue(writer, temp_local, .Other); | |
| 5443 | try writer.writeAll(" = zig_wrap_"); | |
| 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; | |
| 5427 | .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout(mod) == .Packed) { | |
| 5428 | const operand_lval = if (struct_byval == .constant) blk: { | |
| 5429 | const operand_local = try f.allocLocal(inst, struct_ty); | |
| 5430 | try f.writeCValue(writer, operand_local, .Other); | |
| 5431 | try writer.writeAll(" = "); | |
| 5432 | try f.writeCValue(writer, struct_byval, .Initializer); | |
| 5433 | try writer.writeAll(";\n"); | |
| 5434 | break :blk operand_local; | |
| 5435 | } else struct_byval; | |
| 5470 | 5436 | |
| 5471 | 5437 | const local = try f.allocLocal(inst, inst_ty); |
| 5472 | try writer.writeAll("memcpy("); | |
| 5473 | try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument); | |
| 5474 | try writer.writeAll(", "); | |
| 5475 | try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument); | |
| 5438 | try writer.writeAll("memcpy(&"); | |
| 5439 | try f.writeCValue(writer, local, .Other); | |
| 5440 | try writer.writeAll(", &"); | |
| 5441 | try f.writeCValue(writer, operand_lval, .Other); | |
| 5476 | 5442 | try writer.writeAll(", sizeof("); |
| 5477 | 5443 | try f.renderType(writer, inst_ty); |
| 5478 | 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 | 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) { | |
| 5484 | const operand_lval = if (struct_byval == .constant) blk: { | |
| 5485 | const operand_local = try f.allocLocal(inst, struct_ty); | |
| 5486 | try f.writeCValue(writer, operand_local, .Other); | |
| 5487 | try writer.writeAll(" = "); | |
| 5488 | try f.writeCValue(writer, struct_byval, .Initializer); | |
| 5489 | try writer.writeAll(";\n"); | |
| 5490 | break :blk operand_local; | |
| 5491 | } else struct_byval; | |
| 5460 | else => switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) { | |
| 5461 | .struct_type => switch (struct_ty.containerLayout(mod)) { | |
| 5462 | .Auto, .Extern => if (struct_ty.isSimpleTuple()) | |
| 5463 | .{ .field = extra.field_index } | |
| 5464 | else | |
| 5465 | .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) }, | |
| 5466 | .Packed => { | |
| 5467 | const struct_obj = mod.typeToStruct(struct_ty).?; | |
| 5468 | const int_info = struct_ty.intInfo(mod); | |
| 5492 | 5469 | |
| 5493 | const local = try f.allocLocal(inst, inst_ty); | |
| 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"); | |
| 5470 | const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1)); | |
| 5501 | 5471 | |
| 5502 | if (struct_byval == .constant) { | |
| 5503 | try freeLocal(f, inst, operand_lval.new_local, 0); | |
| 5504 | } | |
| 5472 | const bit_offset = struct_obj.packedFieldBitOffset(mod, extra.field_index); | |
| 5473 | const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset); | |
| 5505 | 5474 | |
| 5506 | return local; | |
| 5507 | } else field_name: { | |
| 5508 | const name = struct_ty.unionFields().keys()[extra.field_index]; | |
| 5509 | break :field_name if (struct_ty.unionTagTypeSafety()) |_| | |
| 5510 | .{ .payload_identifier = name } | |
| 5511 | else | |
| 5512 | .{ .identifier = name }; | |
| 5475 | const field_int_signedness = if (inst_ty.isAbiInt(mod)) | |
| 5476 | inst_ty.intInfo(mod).signedness | |
| 5477 | else | |
| 5478 | .unsigned; | |
| 5479 | const field_int_ty = try mod.intType(field_int_signedness, @intCast(u16, inst_ty.bitSize(mod))); | |
| 5480 | ||
| 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 | 5527 | const local = try f.allocLocal(inst, inst_ty); |
| ... | ... | @@ -6805,17 +6815,17 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6805 | 6815 | try a.end(f, writer); |
| 6806 | 6816 | } |
| 6807 | 6817 | }, |
| 6808 | .Struct => switch (inst_ty.containerLayout()) { | |
| 6818 | .Struct => switch (inst_ty.containerLayout(mod)) { | |
| 6809 | 6819 | .Auto, .Extern => for (resolved_elements, 0..) |element, field_i| { |
| 6810 | if (inst_ty.structFieldIsComptime(field_i)) continue; | |
| 6811 | const field_ty = inst_ty.structFieldType(field_i); | |
| 6820 | if (inst_ty.structFieldIsComptime(field_i, mod)) continue; | |
| 6821 | const field_ty = inst_ty.structFieldType(field_i, mod); | |
| 6812 | 6822 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 6813 | 6823 | |
| 6814 | 6824 | const a = try Assignment.start(f, writer, field_ty); |
| 6815 | 6825 | try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple()) |
| 6816 | 6826 | .{ .field = field_i } |
| 6817 | 6827 | else |
| 6818 | .{ .identifier = inst_ty.structFieldName(field_i) }); | |
| 6828 | .{ .identifier = inst_ty.structFieldName(field_i, mod) }); | |
| 6819 | 6829 | try a.assign(f, writer); |
| 6820 | 6830 | try f.writeCValue(writer, element, .Other); |
| 6821 | 6831 | try a.end(f, writer); |
| ... | ... | @@ -6831,8 +6841,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6831 | 6841 | |
| 6832 | 6842 | var empty = true; |
| 6833 | 6843 | for (0..elements.len) |field_i| { |
| 6834 | if (inst_ty.structFieldIsComptime(field_i)) continue; | |
| 6835 | const field_ty = inst_ty.structFieldType(field_i); | |
| 6844 | if (inst_ty.structFieldIsComptime(field_i, mod)) continue; | |
| 6845 | const field_ty = inst_ty.structFieldType(field_i, mod); | |
| 6836 | 6846 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 6837 | 6847 | |
| 6838 | 6848 | if (!empty) { |
| ... | ... | @@ -6844,8 +6854,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6844 | 6854 | } |
| 6845 | 6855 | empty = true; |
| 6846 | 6856 | for (resolved_elements, 0..) |element, field_i| { |
| 6847 | if (inst_ty.structFieldIsComptime(field_i)) continue; | |
| 6848 | const field_ty = inst_ty.structFieldType(field_i); | |
| 6857 | if (inst_ty.structFieldIsComptime(field_i, mod)) continue; | |
| 6858 | const field_ty = inst_ty.structFieldType(field_i, mod); | |
| 6849 | 6859 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 6850 | 6860 | |
| 6851 | 6861 | if (!empty) try writer.writeAll(", "); |
src/codegen/c/type.zig+25-25| ... | ... | @@ -299,7 +299,7 @@ pub const CType = extern union { |
| 299 | 299 | pub fn fieldAlign(struct_ty: Type, field_i: usize, mod: *Module) AlignAs { |
| 300 | 300 | return init( |
| 301 | 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 | 305 | pub fn unionPayloadAlign(union_ty: Type, mod: *Module) AlignAs { |
| ... | ... | @@ -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) { | |
| 1490 | if (ty.castTag(.@"struct")) |struct_obj| { | |
| 1491 | try self.initType(struct_obj.data.backing_int_ty, kind, lookup); | |
| 1489 | .Struct, .Union => |zig_ty_tag| if (ty.containerLayout(mod) == .Packed) { | |
| 1490 | if (mod.typeToStruct(ty)) |struct_obj| { | |
| 1491 | try self.initType(struct_obj.backing_int_ty, kind, lookup); | |
| 1492 | 1492 | } else { |
| 1493 | 1493 | const bits = @intCast(u16, ty.bitSize(mod)); |
| 1494 | 1494 | const int_ty = try mod.intType(.unsigned, bits); |
| 1495 | 1495 | try self.initType(int_ty, kind, lookup); |
| 1496 | 1496 | } |
| 1497 | } else if (ty.isTupleOrAnonStruct()) { | |
| 1497 | } else if (ty.isTupleOrAnonStruct(mod)) { | |
| 1498 | 1498 | if (lookup.isMutable()) { |
| 1499 | 1499 | for (0..switch (zig_ty_tag) { |
| 1500 | .Struct => ty.structFieldCount(), | |
| 1500 | .Struct => ty.structFieldCount(mod), | |
| 1501 | 1501 | .Union => ty.unionFields().count(), |
| 1502 | 1502 | else => unreachable, |
| 1503 | 1503 | }) |field_i| { |
| 1504 | const field_ty = ty.structFieldType(field_i); | |
| 1505 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or | |
| 1504 | const field_ty = ty.structFieldType(field_i, mod); | |
| 1505 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or | |
| 1506 | 1506 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1507 | 1507 | _ = try lookup.typeToIndex(field_ty, switch (kind) { |
| 1508 | 1508 | .forward, .forward_parameter => .forward, |
| ... | ... | @@ -1579,11 +1579,11 @@ pub const CType = extern union { |
| 1579 | 1579 | } else { |
| 1580 | 1580 | var is_packed = false; |
| 1581 | 1581 | for (0..switch (zig_ty_tag) { |
| 1582 | .Struct => ty.structFieldCount(), | |
| 1582 | .Struct => ty.structFieldCount(mod), | |
| 1583 | 1583 | .Union => ty.unionFields().count(), |
| 1584 | 1584 | else => unreachable, |
| 1585 | 1585 | }) |field_i| { |
| 1586 | const field_ty = ty.structFieldType(field_i); | |
| 1586 | const field_ty = ty.structFieldType(field_i, mod); | |
| 1587 | 1587 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1588 | 1588 | |
| 1589 | 1589 | const field_align = AlignAs.fieldAlign(ty, field_i, mod); |
| ... | ... | @@ -1929,15 +1929,15 @@ pub const CType = extern union { |
| 1929 | 1929 | => { |
| 1930 | 1930 | const zig_ty_tag = ty.zigTypeTag(mod); |
| 1931 | 1931 | const fields_len = switch (zig_ty_tag) { |
| 1932 | .Struct => ty.structFieldCount(), | |
| 1932 | .Struct => ty.structFieldCount(mod), | |
| 1933 | 1933 | .Union => ty.unionFields().count(), |
| 1934 | 1934 | else => unreachable, |
| 1935 | 1935 | }; |
| 1936 | 1936 | |
| 1937 | 1937 | var c_fields_len: usize = 0; |
| 1938 | 1938 | for (0..fields_len) |field_i| { |
| 1939 | const field_ty = ty.structFieldType(field_i); | |
| 1940 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or | |
| 1939 | const field_ty = ty.structFieldType(field_i, mod); | |
| 1940 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or | |
| 1941 | 1941 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1942 | 1942 | c_fields_len += 1; |
| 1943 | 1943 | } |
| ... | ... | @@ -1945,8 +1945,8 @@ pub const CType = extern union { |
| 1945 | 1945 | const fields_pl = try arena.alloc(Payload.Fields.Field, c_fields_len); |
| 1946 | 1946 | var c_field_i: usize = 0; |
| 1947 | 1947 | for (0..fields_len) |field_i| { |
| 1948 | const field_ty = ty.structFieldType(field_i); | |
| 1949 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or | |
| 1948 | const field_ty = ty.structFieldType(field_i, mod); | |
| 1949 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or | |
| 1950 | 1950 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1951 | 1951 | |
| 1952 | 1952 | defer c_field_i += 1; |
| ... | ... | @@ -1955,7 +1955,7 @@ pub const CType = extern union { |
| 1955 | 1955 | std.fmt.allocPrintZ(arena, "f{}", .{field_i}) |
| 1956 | 1956 | else |
| 1957 | 1957 | arena.dupeZ(u8, switch (zig_ty_tag) { |
| 1958 | .Struct => ty.structFieldName(field_i), | |
| 1958 | .Struct => ty.structFieldName(field_i, mod), | |
| 1959 | 1959 | .Union => ty.unionFields().keys()[field_i], |
| 1960 | 1960 | else => unreachable, |
| 1961 | 1961 | }), |
| ... | ... | @@ -2074,7 +2074,7 @@ pub const CType = extern union { |
| 2074 | 2074 | .fwd_anon_struct, |
| 2075 | 2075 | .fwd_anon_union, |
| 2076 | 2076 | => { |
| 2077 | if (!ty.isTupleOrAnonStruct()) return false; | |
| 2077 | if (!ty.isTupleOrAnonStruct(mod)) return false; | |
| 2078 | 2078 | |
| 2079 | 2079 | var name_buf: [ |
| 2080 | 2080 | std.fmt.count("f{}", .{std.math.maxInt(usize)}) |
| ... | ... | @@ -2084,12 +2084,12 @@ pub const CType = extern union { |
| 2084 | 2084 | const zig_ty_tag = ty.zigTypeTag(mod); |
| 2085 | 2085 | var c_field_i: usize = 0; |
| 2086 | 2086 | for (0..switch (zig_ty_tag) { |
| 2087 | .Struct => ty.structFieldCount(), | |
| 2087 | .Struct => ty.structFieldCount(mod), | |
| 2088 | 2088 | .Union => ty.unionFields().count(), |
| 2089 | 2089 | else => unreachable, |
| 2090 | 2090 | }) |field_i| { |
| 2091 | const field_ty = ty.structFieldType(field_i); | |
| 2092 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or | |
| 2091 | const field_ty = ty.structFieldType(field_i, mod); | |
| 2092 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or | |
| 2093 | 2093 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2094 | 2094 | |
| 2095 | 2095 | defer c_field_i += 1; |
| ... | ... | @@ -2105,7 +2105,7 @@ pub const CType = extern union { |
| 2105 | 2105 | if (ty.isSimpleTuple()) |
| 2106 | 2106 | std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable |
| 2107 | 2107 | else switch (zig_ty_tag) { |
| 2108 | .Struct => ty.structFieldName(field_i), | |
| 2108 | .Struct => ty.structFieldName(field_i, mod), | |
| 2109 | 2109 | .Union => ty.unionFields().keys()[field_i], |
| 2110 | 2110 | else => unreachable, |
| 2111 | 2111 | }, |
| ... | ... | @@ -2210,12 +2210,12 @@ pub const CType = extern union { |
| 2210 | 2210 | |
| 2211 | 2211 | const zig_ty_tag = ty.zigTypeTag(mod); |
| 2212 | 2212 | for (0..switch (ty.zigTypeTag(mod)) { |
| 2213 | .Struct => ty.structFieldCount(), | |
| 2213 | .Struct => ty.structFieldCount(mod), | |
| 2214 | 2214 | .Union => ty.unionFields().count(), |
| 2215 | 2215 | else => unreachable, |
| 2216 | 2216 | }) |field_i| { |
| 2217 | const field_ty = ty.structFieldType(field_i); | |
| 2218 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or | |
| 2217 | const field_ty = ty.structFieldType(field_i, mod); | |
| 2218 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or | |
| 2219 | 2219 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2220 | 2220 | |
| 2221 | 2221 | self.updateHasherRecurse(hasher, field_ty, switch (self.kind) { |
| ... | ... | @@ -2227,7 +2227,7 @@ pub const CType = extern union { |
| 2227 | 2227 | hasher.update(if (ty.isSimpleTuple()) |
| 2228 | 2228 | std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable |
| 2229 | 2229 | else switch (zig_ty_tag) { |
| 2230 | .Struct => ty.structFieldName(field_i), | |
| 2230 | .Struct => ty.structFieldName(field_i, mod), | |
| 2231 | 2231 | .Union => ty.unionFields().keys()[field_i], |
| 2232 | 2232 | else => unreachable, |
| 2233 | 2233 | }); |
src/codegen/llvm.zig+26-28| ... | ... | @@ -1986,8 +1986,7 @@ pub const Object = struct { |
| 1986 | 1986 | const name = try ty.nameAlloc(gpa, o.module); |
| 1987 | 1987 | defer gpa.free(name); |
| 1988 | 1988 | |
| 1989 | if (ty.castTag(.@"struct")) |payload| { | |
| 1990 | const struct_obj = payload.data; | |
| 1989 | if (mod.typeToStruct(ty)) |struct_obj| { | |
| 1991 | 1990 | if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) { |
| 1992 | 1991 | assert(struct_obj.haveLayout()); |
| 1993 | 1992 | const info = struct_obj.backing_int_ty.intInfo(mod); |
| ... | ... | @@ -2075,8 +2074,7 @@ pub const Object = struct { |
| 2075 | 2074 | return full_di_ty; |
| 2076 | 2075 | } |
| 2077 | 2076 | |
| 2078 | if (ty.castTag(.@"struct")) |payload| { | |
| 2079 | const struct_obj = payload.data; | |
| 2077 | if (mod.typeToStruct(ty)) |struct_obj| { | |
| 2080 | 2078 | if (!struct_obj.haveFieldTypes()) { |
| 2081 | 2079 | // This can happen if a struct type makes it all the way to |
| 2082 | 2080 | // flush() without ever being instantiated or referenced (even |
| ... | ... | @@ -2105,8 +2103,8 @@ pub const Object = struct { |
| 2105 | 2103 | return struct_di_ty; |
| 2106 | 2104 | } |
| 2107 | 2105 | |
| 2108 | const fields = ty.structFields(); | |
| 2109 | const layout = ty.containerLayout(); | |
| 2106 | const fields = ty.structFields(mod); | |
| 2107 | const layout = ty.containerLayout(mod); | |
| 2110 | 2108 | |
| 2111 | 2109 | var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{}; |
| 2112 | 2110 | defer di_fields.deinit(gpa); |
| ... | ... | @@ -2116,7 +2114,7 @@ pub const Object = struct { |
| 2116 | 2114 | comptime assert(struct_layout_version == 2); |
| 2117 | 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 | 2118 | while (it.next()) |field_and_index| { |
| 2121 | 2119 | const field = field_and_index.field; |
| 2122 | 2120 | const field_size = field.ty.abiSize(mod); |
| ... | ... | @@ -2990,7 +2988,7 @@ pub const DeclGen = struct { |
| 2990 | 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 | 2993 | if (struct_obj.layout == .Packed) { |
| 2996 | 2994 | assert(struct_obj.haveLayout()); |
| ... | ... | @@ -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 | 3699 | if (struct_obj.layout == .Packed) { |
| 3702 | 3700 | assert(struct_obj.haveLayout()); |
| ... | ... | @@ -4043,7 +4041,7 @@ pub const DeclGen = struct { |
| 4043 | 4041 | const llvm_u32 = dg.context.intType(32); |
| 4044 | 4042 | switch (parent_ty.zigTypeTag(mod)) { |
| 4045 | 4043 | .Union => { |
| 4046 | if (parent_ty.containerLayout() == .Packed) { | |
| 4044 | if (parent_ty.containerLayout(mod) == .Packed) { | |
| 4047 | 4045 | return parent_llvm_ptr; |
| 4048 | 4046 | } |
| 4049 | 4047 | |
| ... | ... | @@ -4065,14 +4063,14 @@ pub const DeclGen = struct { |
| 4065 | 4063 | return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 4066 | 4064 | }, |
| 4067 | 4065 | .Struct => { |
| 4068 | if (parent_ty.containerLayout() == .Packed) { | |
| 4066 | if (parent_ty.containerLayout(mod) == .Packed) { | |
| 4069 | 4067 | if (!byte_aligned) return parent_llvm_ptr; |
| 4070 | 4068 | const llvm_usize = dg.context.intType(target.ptrBitWidth()); |
| 4071 | 4069 | const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize); |
| 4072 | 4070 | // count bits of fields before this one |
| 4073 | 4071 | const prev_bits = b: { |
| 4074 | 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 | 4074 | if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 4077 | 4075 | b += @intCast(usize, field.ty.bitSize(mod)); |
| 4078 | 4076 | } |
| ... | ... | @@ -5983,7 +5981,7 @@ pub const FuncGen = struct { |
| 5983 | 5981 | const struct_ty = self.typeOf(struct_field.struct_operand); |
| 5984 | 5982 | const struct_llvm_val = try self.resolveInst(struct_field.struct_operand); |
| 5985 | 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 | 5985 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 5988 | 5986 | return null; |
| 5989 | 5987 | } |
| ... | ... | @@ -5991,9 +5989,9 @@ pub const FuncGen = struct { |
| 5991 | 5989 | if (!isByRef(struct_ty, mod)) { |
| 5992 | 5990 | assert(!isByRef(field_ty, mod)); |
| 5993 | 5991 | switch (struct_ty.zigTypeTag(mod)) { |
| 5994 | .Struct => switch (struct_ty.containerLayout()) { | |
| 5992 | .Struct => switch (struct_ty.containerLayout(mod)) { | |
| 5995 | 5993 | .Packed => { |
| 5996 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | |
| 5994 | const struct_obj = mod.typeToStruct(struct_ty).?; | |
| 5997 | 5995 | const bit_offset = struct_obj.packedFieldBitOffset(mod, field_index); |
| 5998 | 5996 | const containing_int = struct_llvm_val; |
| 5999 | 5997 | const shift_amt = containing_int.typeOf().constInt(bit_offset, .False); |
| ... | ... | @@ -6019,7 +6017,7 @@ pub const FuncGen = struct { |
| 6019 | 6017 | }, |
| 6020 | 6018 | }, |
| 6021 | 6019 | .Union => { |
| 6022 | assert(struct_ty.containerLayout() == .Packed); | |
| 6020 | assert(struct_ty.containerLayout(mod) == .Packed); | |
| 6023 | 6021 | const containing_int = struct_llvm_val; |
| 6024 | 6022 | const elem_llvm_ty = try self.dg.lowerType(field_ty); |
| 6025 | 6023 | if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) { |
| ... | ... | @@ -6041,7 +6039,7 @@ pub const FuncGen = struct { |
| 6041 | 6039 | |
| 6042 | 6040 | switch (struct_ty.zigTypeTag(mod)) { |
| 6043 | 6041 | .Struct => { |
| 6044 | assert(struct_ty.containerLayout() != .Packed); | |
| 6042 | assert(struct_ty.containerLayout(mod) != .Packed); | |
| 6045 | 6043 | var ptr_ty_buf: Type.Payload.Pointer = undefined; |
| 6046 | 6044 | const llvm_field_index = llvmFieldIndex(struct_ty, field_index, mod, &ptr_ty_buf).?; |
| 6047 | 6045 | const struct_llvm_ty = try self.dg.lowerType(struct_ty); |
| ... | ... | @@ -9289,8 +9287,8 @@ pub const FuncGen = struct { |
| 9289 | 9287 | return vector; |
| 9290 | 9288 | }, |
| 9291 | 9289 | .Struct => { |
| 9292 | if (result_ty.containerLayout() == .Packed) { | |
| 9293 | const struct_obj = result_ty.castTag(.@"struct").?.data; | |
| 9290 | if (result_ty.containerLayout(mod) == .Packed) { | |
| 9291 | const struct_obj = mod.typeToStruct(result_ty).?; | |
| 9294 | 9292 | assert(struct_obj.haveLayout()); |
| 9295 | 9293 | const big_bits = struct_obj.backing_int_ty.bitSize(mod); |
| 9296 | 9294 | const int_llvm_ty = self.context.intType(@intCast(c_uint, big_bits)); |
| ... | ... | @@ -9795,7 +9793,7 @@ pub const FuncGen = struct { |
| 9795 | 9793 | const mod = self.dg.module; |
| 9796 | 9794 | const struct_ty = struct_ptr_ty.childType(mod); |
| 9797 | 9795 | switch (struct_ty.zigTypeTag(mod)) { |
| 9798 | .Struct => switch (struct_ty.containerLayout()) { | |
| 9796 | .Struct => switch (struct_ty.containerLayout(mod)) { | |
| 9799 | 9797 | .Packed => { |
| 9800 | 9798 | const result_ty = self.typeOfIndex(inst); |
| 9801 | 9799 | const result_ty_info = result_ty.ptrInfo(mod); |
| ... | ... | @@ -9838,7 +9836,7 @@ pub const FuncGen = struct { |
| 9838 | 9836 | }, |
| 9839 | 9837 | .Union => { |
| 9840 | 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 | 9840 | const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); |
| 9843 | 9841 | const union_llvm_ty = try self.dg.lowerType(struct_ty); |
| 9844 | 9842 | const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_ptr, payload_index, ""); |
| ... | ... | @@ -10530,11 +10528,11 @@ fn llvmFieldIndex( |
| 10530 | 10528 | } |
| 10531 | 10529 | return null; |
| 10532 | 10530 | } |
| 10533 | const layout = ty.containerLayout(); | |
| 10531 | const layout = ty.containerLayout(mod); | |
| 10534 | 10532 | assert(layout != .Packed); |
| 10535 | 10533 | |
| 10536 | 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 | 10536 | while (it.next()) |field_and_index| { |
| 10539 | 10537 | const field = field_and_index.field; |
| 10540 | 10538 | const field_align = field.alignment(mod, layout); |
| ... | ... | @@ -11113,7 +11111,7 @@ fn isByRef(ty: Type, mod: *Module) bool { |
| 11113 | 11111 | .Array, .Frame => return ty.hasRuntimeBits(mod), |
| 11114 | 11112 | .Struct => { |
| 11115 | 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 | 11115 | if (ty.isSimpleTupleOrAnonStruct()) { |
| 11118 | 11116 | const tuple = ty.tupleFields(); |
| 11119 | 11117 | var count: usize = 0; |
| ... | ... | @@ -11127,7 +11125,7 @@ fn isByRef(ty: Type, mod: *Module) bool { |
| 11127 | 11125 | return false; |
| 11128 | 11126 | } |
| 11129 | 11127 | var count: usize = 0; |
| 11130 | const fields = ty.structFields(); | |
| 11128 | const fields = ty.structFields(mod); | |
| 11131 | 11129 | for (fields.values()) |field| { |
| 11132 | 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 | 11135 | } |
| 11138 | 11136 | return false; |
| 11139 | 11137 | }, |
| 11140 | .Union => switch (ty.containerLayout()) { | |
| 11138 | .Union => switch (ty.containerLayout(mod)) { | |
| 11141 | 11139 | .Packed => return false, |
| 11142 | 11140 | else => return ty.hasRuntimeBits(mod), |
| 11143 | 11141 | }, |
| ... | ... | @@ -11176,8 +11174,8 @@ fn isScalar(mod: *Module, ty: Type) bool { |
| 11176 | 11174 | .Vector, |
| 11177 | 11175 | => true, |
| 11178 | 11176 | |
| 11179 | .Struct => ty.containerLayout() == .Packed, | |
| 11180 | .Union => ty.containerLayout() == .Packed, | |
| 11177 | .Struct => ty.containerLayout(mod) == .Packed, | |
| 11178 | .Union => ty.containerLayout(mod) == .Packed, | |
| 11181 | 11179 | else => false, |
| 11182 | 11180 | }; |
| 11183 | 11181 | } |
src/codegen/spirv.zig+4-4| ... | ... | @@ -685,7 +685,7 @@ pub const DeclGen = struct { |
| 685 | 685 | if (ty.isSimpleTupleOrAnonStruct()) { |
| 686 | 686 | unreachable; // TODO |
| 687 | 687 | } else { |
| 688 | const struct_ty = ty.castTag(.@"struct").?.data; | |
| 688 | const struct_ty = mod.typeToStruct(ty).?; | |
| 689 | 689 | |
| 690 | 690 | if (struct_ty.layout == .Packed) { |
| 691 | 691 | return dg.todo("packed struct constants", .{}); |
| ... | ... | @@ -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 | 1311 | if (struct_ty.layout == .Packed) { |
| 1312 | 1312 | return try self.resolveType(struct_ty.backing_int_ty, .direct); |
| ... | ... | @@ -2576,7 +2576,7 @@ pub const DeclGen = struct { |
| 2576 | 2576 | const struct_ty = self.typeOf(struct_field.struct_operand); |
| 2577 | 2577 | const object_id = try self.resolve(struct_field.struct_operand); |
| 2578 | 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 | 2581 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) return null; |
| 2582 | 2582 | |
| ... | ... | @@ -2595,7 +2595,7 @@ pub const DeclGen = struct { |
| 2595 | 2595 | const mod = self.module; |
| 2596 | 2596 | const object_ty = object_ptr_ty.childType(mod); |
| 2597 | 2597 | switch (object_ty.zigTypeTag(mod)) { |
| 2598 | .Struct => switch (object_ty.containerLayout()) { | |
| 2598 | .Struct => switch (object_ty.containerLayout(mod)) { | |
| 2599 | 2599 | .Packed => unreachable, // TODO |
| 2600 | 2600 | else => { |
| 2601 | 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 | 360 | dbg_info_buffer.appendSliceAssumeCapacity(struct_name); |
| 361 | 361 | dbg_info_buffer.appendAssumeCapacity(0); |
| 362 | 362 | |
| 363 | const struct_obj = ty.castTag(.@"struct").?.data; | |
| 363 | const struct_obj = mod.typeToStruct(ty).?; | |
| 364 | 364 | if (struct_obj.layout == .Packed) { |
| 365 | 365 | log.debug("TODO implement .debug_info for packed structs", .{}); |
| 366 | 366 | break :blk; |
| 367 | 367 | } |
| 368 | 368 | |
| 369 | const fields = ty.structFields(); | |
| 369 | const fields = ty.structFields(mod); | |
| 370 | 370 | for (fields.keys(), 0..) |field_name, field_index| { |
| 371 | 371 | const field = fields.get(field_name).?; |
| 372 | 372 | if (!field.ty.hasRuntimeBits(mod)) continue; |
src/type.zig+601-582| ... | ... | @@ -59,8 +59,6 @@ pub const Type = struct { |
| 59 | 59 | |
| 60 | 60 | .anyframe_T => return .AnyFrame, |
| 61 | 61 | |
| 62 | .empty_struct, | |
| 63 | .@"struct", | |
| 64 | 62 | .tuple, |
| 65 | 63 | .anon_struct, |
| 66 | 64 | => return .Struct, |
| ... | ... | @@ -148,6 +146,7 @@ pub const Type = struct { |
| 148 | 146 | .opt => unreachable, |
| 149 | 147 | .enum_tag => unreachable, |
| 150 | 148 | .simple_value => unreachable, |
| 149 | .aggregate => unreachable, | |
| 151 | 150 | }, |
| 152 | 151 | } |
| 153 | 152 | } |
| ... | ... | @@ -501,16 +500,6 @@ pub const Type = struct { |
| 501 | 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 | 503 | .tuple => { |
| 515 | 504 | if (!b.isSimpleTuple()) return false; |
| 516 | 505 | |
| ... | ... | @@ -720,15 +709,6 @@ pub const Type = struct { |
| 720 | 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 | 712 | .tuple => { |
| 733 | 713 | std.hash.autoHash(hasher, std.builtin.TypeId.Struct); |
| 734 | 714 | |
| ... | ... | @@ -955,8 +935,6 @@ pub const Type = struct { |
| 955 | 935 | .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet), |
| 956 | 936 | .error_set_inferred => return self.copyPayloadShallow(allocator, Payload.ErrorSetInferred), |
| 957 | 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 | 938 | .@"union", .union_safety_tagged, .union_tagged => return self.copyPayloadShallow(allocator, Payload.Union), |
| 961 | 939 | .enum_simple => return self.copyPayloadShallow(allocator, Payload.EnumSimple), |
| 962 | 940 | .enum_numbered => return self.copyPayloadShallow(allocator, Payload.EnumNumbered), |
| ... | ... | @@ -1033,14 +1011,6 @@ pub const Type = struct { |
| 1033 | 1011 | while (true) { |
| 1034 | 1012 | const t = ty.tag(); |
| 1035 | 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 | 1014 | .@"union", .union_safety_tagged, .union_tagged => { |
| 1045 | 1015 | const union_obj = ty.cast(Payload.Union).?.data; |
| 1046 | 1016 | return writer.print("({s} decl={d})", .{ |
| ... | ... | @@ -1247,22 +1217,10 @@ pub const Type = struct { |
| 1247 | 1217 | /// Prints a name suitable for `@typeName`. |
| 1248 | 1218 | pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void { |
| 1249 | 1219 | switch (ty.ip_index) { |
| 1250 | .empty_struct_type => try writer.writeAll("@TypeOf(.{})"), | |
| 1251 | ||
| 1252 | 1220 | .none => switch (ty.tag()) { |
| 1253 | 1221 | .inferred_alloc_const => unreachable, |
| 1254 | 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 | 1224 | .@"union", .union_safety_tagged, .union_tagged => { |
| 1267 | 1225 | const union_obj = ty.cast(Payload.Union).?.data; |
| 1268 | 1226 | const decl = mod.declPtr(union_obj.owner_decl); |
| ... | ... | @@ -1548,7 +1506,18 @@ pub const Type = struct { |
| 1548 | 1506 | return; |
| 1549 | 1507 | }, |
| 1550 | 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 | 1521 | .union_type => @panic("TODO"), |
| 1553 | 1522 | .opaque_type => |opaque_type| { |
| 1554 | 1523 | const decl = mod.declPtr(opaque_type.decl); |
| ... | ... | @@ -1562,6 +1531,7 @@ pub const Type = struct { |
| 1562 | 1531 | .ptr => unreachable, |
| 1563 | 1532 | .opt => unreachable, |
| 1564 | 1533 | .enum_tag => unreachable, |
| 1534 | .aggregate => unreachable, | |
| 1565 | 1535 | }, |
| 1566 | 1536 | } |
| 1567 | 1537 | } |
| ... | ... | @@ -1624,12 +1594,10 @@ pub const Type = struct { |
| 1624 | 1594 | }, |
| 1625 | 1595 | |
| 1626 | 1596 | // These are false because they are comptime-only types. |
| 1627 | .empty_struct, | |
| 1628 | 1597 | // These are function *bodies*, not pointers. |
| 1629 | 1598 | // Special exceptions have to be made when emitting functions due to |
| 1630 | 1599 | // this returning false. |
| 1631 | .function, | |
| 1632 | => return false, | |
| 1600 | .function => return false, | |
| 1633 | 1601 | |
| 1634 | 1602 | .optional => { |
| 1635 | 1603 | const child_ty = ty.optionalChild(mod); |
| ... | ... | @@ -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 | 1617 | .enum_full => { |
| 1672 | 1618 | const enum_full = ty.castTag(.enum_full).?.data; |
| 1673 | 1619 | return enum_full.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); |
| ... | ... | @@ -1824,7 +1770,31 @@ pub const Type = struct { |
| 1824 | 1770 | .generic_poison => unreachable, |
| 1825 | 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 | 1798 | .union_type => @panic("TODO"), |
| 1829 | 1799 | .opaque_type => true, |
| 1830 | 1800 | |
| ... | ... | @@ -1835,6 +1805,7 @@ pub const Type = struct { |
| 1835 | 1805 | .ptr => unreachable, |
| 1836 | 1806 | .opt => unreachable, |
| 1837 | 1807 | .enum_tag => unreachable, |
| 1808 | .aggregate => unreachable, | |
| 1838 | 1809 | }, |
| 1839 | 1810 | } |
| 1840 | 1811 | } |
| ... | ... | @@ -1862,7 +1833,6 @@ pub const Type = struct { |
| 1862 | 1833 | .anyframe_T, |
| 1863 | 1834 | .tuple, |
| 1864 | 1835 | .anon_struct, |
| 1865 | .empty_struct, | |
| 1866 | 1836 | => false, |
| 1867 | 1837 | |
| 1868 | 1838 | .enum_full, |
| ... | ... | @@ -1877,7 +1847,6 @@ pub const Type = struct { |
| 1877 | 1847 | => ty.childType(mod).hasWellDefinedLayout(mod), |
| 1878 | 1848 | |
| 1879 | 1849 | .optional => ty.isPtrLikeOptional(mod), |
| 1880 | .@"struct" => ty.castTag(.@"struct").?.data.layout != .Auto, | |
| 1881 | 1850 | .@"union", .union_safety_tagged => ty.cast(Payload.Union).?.data.layout != .Auto, |
| 1882 | 1851 | .union_tagged => false, |
| 1883 | 1852 | }, |
| ... | ... | @@ -1936,7 +1905,13 @@ pub const Type = struct { |
| 1936 | 1905 | |
| 1937 | 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 | 1915 | .union_type => @panic("TODO"), |
| 1941 | 1916 | .opaque_type => false, |
| 1942 | 1917 | |
| ... | ... | @@ -1947,6 +1922,7 @@ pub const Type = struct { |
| 1947 | 1922 | .ptr => unreachable, |
| 1948 | 1923 | .opt => unreachable, |
| 1949 | 1924 | .enum_tag => unreachable, |
| 1925 | .aggregate => unreachable, | |
| 1950 | 1926 | }, |
| 1951 | 1927 | }; |
| 1952 | 1928 | } |
| ... | ... | @@ -2146,68 +2122,6 @@ pub const Type = struct { |
| 2146 | 2122 | .optional => return abiAlignmentAdvancedOptional(ty, mod, strat), |
| 2147 | 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 | 2125 | .tuple, .anon_struct => { |
| 2212 | 2126 | const tuple = ty.tupleFields(); |
| 2213 | 2127 | var big_align: u32 = 0; |
| ... | ... | @@ -2241,8 +2155,6 @@ pub const Type = struct { |
| 2241 | 2155 | return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, true); |
| 2242 | 2156 | }, |
| 2243 | 2157 | |
| 2244 | .empty_struct => return AbiAlignmentAdvanced{ .scalar = 0 }, | |
| 2245 | ||
| 2246 | 2158 | .inferred_alloc_const, |
| 2247 | 2159 | .inferred_alloc_mut, |
| 2248 | 2160 | => unreachable, |
| ... | ... | @@ -2337,7 +2249,69 @@ pub const Type = struct { |
| 2337 | 2249 | .generic_poison => unreachable, |
| 2338 | 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 | 2315 | .union_type => @panic("TODO"), |
| 2342 | 2316 | .opaque_type => return AbiAlignmentAdvanced{ .scalar = 1 }, |
| 2343 | 2317 | |
| ... | ... | @@ -2348,6 +2322,7 @@ pub const Type = struct { |
| 2348 | 2322 | .ptr => unreachable, |
| 2349 | 2323 | .opt => unreachable, |
| 2350 | 2324 | .enum_tag => unreachable, |
| 2325 | .aggregate => unreachable, | |
| 2351 | 2326 | }, |
| 2352 | 2327 | } |
| 2353 | 2328 | } |
| ... | ... | @@ -2517,42 +2492,16 @@ pub const Type = struct { |
| 2517 | 2492 | .inferred_alloc_const => unreachable, |
| 2518 | 2493 | .inferred_alloc_mut => unreachable, |
| 2519 | 2494 | |
| 2520 | .empty_struct => return AbiSizeAdvanced{ .scalar = 0 }, | |
| 2521 | ||
| 2522 | .@"struct", .tuple, .anon_struct => switch (ty.containerLayout()) { | |
| 2523 | .Packed => { | |
| 2524 | const struct_obj = ty.castTag(.@"struct").?.data; | |
| 2525 | switch (strat) { | |
| 2526 | .sema => |sema| try sema.resolveTypeLayout(ty), | |
| 2527 | .lazy => |arena| { | |
| 2528 | if (!struct_obj.haveLayout()) { | |
| 2529 | return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) }; | |
| 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 | }, | |
| 2495 | .tuple, .anon_struct => { | |
| 2496 | switch (strat) { | |
| 2497 | .sema => |sema| try sema.resolveTypeLayout(ty), | |
| 2498 | .lazy, .eager => {}, | |
| 2499 | } | |
| 2500 | const field_count = ty.structFieldCount(mod); | |
| 2501 | if (field_count == 0) { | |
| 2502 | return AbiSizeAdvanced{ .scalar = 0 }; | |
| 2503 | } | |
| 2504 | return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) }; | |
| 2556 | 2505 | }, |
| 2557 | 2506 | |
| 2558 | 2507 | .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => { |
| ... | ... | @@ -2752,7 +2701,42 @@ pub const Type = struct { |
| 2752 | 2701 | .generic_poison => unreachable, |
| 2753 | 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 | 2740 | .union_type => @panic("TODO"), |
| 2757 | 2741 | .opaque_type => unreachable, // no size available |
| 2758 | 2742 | |
| ... | ... | @@ -2763,6 +2747,7 @@ pub const Type = struct { |
| 2763 | 2747 | .ptr => unreachable, |
| 2764 | 2748 | .opt => unreachable, |
| 2765 | 2749 | .enum_tag => unreachable, |
| 2750 | .aggregate => unreachable, | |
| 2766 | 2751 | }, |
| 2767 | 2752 | } |
| 2768 | 2753 | } |
| ... | ... | @@ -2850,189 +2835,189 @@ pub const Type = struct { |
| 2850 | 2835 | ) Module.CompileError!u64 { |
| 2851 | 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 | 2838 | const strat: AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager; |
| 2941 | 2839 | |
| 2942 | switch (ty.tag()) { | |
| 2943 | .function => unreachable, // represents machine code; not a pointer | |
| 2944 | .empty_struct => unreachable, | |
| 2945 | .inferred_alloc_const => unreachable, | |
| 2946 | .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 | }, | |
| 2840 | switch (ty.ip_index) { | |
| 2841 | .none => switch (ty.tag()) { | |
| 2842 | .function => unreachable, // represents machine code; not a pointer | |
| 2843 | .inferred_alloc_const => unreachable, | |
| 2844 | .inferred_alloc_mut => unreachable, | |
| 2969 | 2845 | |
| 2970 | .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => { | |
| 2971 | const int_tag_ty = try ty.intTagType(mod); | |
| 2972 | return try bitSizeAdvanced(int_tag_ty, mod, opt_sema); | |
| 2973 | }, | |
| 2846 | .tuple, .anon_struct => { | |
| 2847 | if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty); | |
| 2848 | if (ty.containerLayout(mod) != .Packed) { | |
| 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 => { | |
| 2976 | if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty); | |
| 2977 | if (ty.containerLayout() != .Packed) { | |
| 2978 | return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8; | |
| 2979 | } | |
| 2980 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 2981 | assert(union_obj.haveFieldTypes()); | |
| 2858 | .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => { | |
| 2859 | const int_tag_ty = try ty.intTagType(mod); | |
| 2860 | return try bitSizeAdvanced(int_tag_ty, mod, opt_sema); | |
| 2861 | }, | |
| 2982 | 2862 | |
| 2983 | var size: u64 = 0; | |
| 2984 | for (union_obj.fields.values()) |field| { | |
| 2985 | size = @max(size, try bitSizeAdvanced(field.ty, mod, opt_sema)); | |
| 2986 | } | |
| 2987 | return size; | |
| 2988 | }, | |
| 2863 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 2864 | if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty); | |
| 2865 | if (ty.containerLayout(mod) != .Packed) { | |
| 2866 | return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8; | |
| 2867 | } | |
| 2868 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 2869 | assert(union_obj.haveFieldTypes()); | |
| 2989 | 2870 | |
| 2990 | .array => { | |
| 2991 | const payload = ty.castTag(.array).?.data; | |
| 2992 | const elem_size = std.math.max(payload.elem_type.abiAlignment(mod), payload.elem_type.abiSize(mod)); | |
| 2993 | if (elem_size == 0 or payload.len == 0) | |
| 2994 | return @as(u64, 0); | |
| 2995 | const elem_bit_size = try bitSizeAdvanced(payload.elem_type, mod, opt_sema); | |
| 2996 | return (payload.len - 1) * 8 * elem_size + elem_bit_size; | |
| 2997 | }, | |
| 2998 | .array_sentinel => { | |
| 2999 | const payload = ty.castTag(.array_sentinel).?.data; | |
| 3000 | const elem_size = std.math.max( | |
| 3001 | payload.elem_type.abiAlignment(mod), | |
| 3002 | payload.elem_type.abiSize(mod), | |
| 3003 | ); | |
| 3004 | const elem_bit_size = try bitSizeAdvanced(payload.elem_type, mod, opt_sema); | |
| 3005 | return payload.len * 8 * elem_size + elem_bit_size; | |
| 3006 | }, | |
| 2871 | var size: u64 = 0; | |
| 2872 | for (union_obj.fields.values()) |field| { | |
| 2873 | size = @max(size, try bitSizeAdvanced(field.ty, mod, opt_sema)); | |
| 2874 | } | |
| 2875 | return size; | |
| 2876 | }, | |
| 2877 | ||
| 2878 | .array => { | |
| 2879 | const payload = ty.castTag(.array).?.data; | |
| 2880 | const elem_size = std.math.max(payload.elem_type.abiAlignment(mod), payload.elem_type.abiSize(mod)); | |
| 2881 | if (elem_size == 0 or payload.len == 0) | |
| 2882 | return @as(u64, 0); | |
| 2883 | const elem_bit_size = try bitSizeAdvanced(payload.elem_type, mod, opt_sema); | |
| 2884 | return (payload.len - 1) * 8 * elem_size + elem_bit_size; | |
| 2885 | }, | |
| 2886 | .array_sentinel => { | |
| 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) { | |
| 3011 | .Slice => return target.ptrBitWidth() * 2, | |
| 3012 | else => return target.ptrBitWidth(), | |
| 2898 | .pointer => switch (ty.castTag(.pointer).?.data.size) { | |
| 2899 | .Slice => return target.ptrBitWidth() * 2, | |
| 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, | |
| 3016 | .error_set_single, | |
| 3017 | .error_set_inferred, | |
| 3018 | .error_set_merged, | |
| 3019 | => return 16, // TODO revisit this when we have the concept of the error tag type | |
| 2944 | .usize, | |
| 2945 | .isize, | |
| 2946 | .@"anyframe", | |
| 2947 | => return target.ptrBitWidth(), | |
| 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 => { | |
| 3022 | // Optionals and error unions are not packed so their bitsize | |
| 3023 | // includes padding bits. | |
| 3024 | return (try abiSizeAdvanced(ty, mod, strat)).scalar * 8; | |
| 3002 | // values, not types | |
| 3003 | .simple_value => unreachable, | |
| 3004 | .extern_func => unreachable, | |
| 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 | 3014 | /// Returns true if the type's layout is already resolved and it is safe |
| 3030 | 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 | 3017 | switch (ty.zigTypeTag(mod)) { |
| 3033 | 3018 | .Struct => { |
| 3034 | if (ty.castTag(.@"struct")) |struct_ty| { | |
| 3035 | return struct_ty.data.haveLayout(); | |
| 3019 | if (mod.typeToStruct(ty)) |struct_obj| { | |
| 3020 | return struct_obj.haveLayout(); | |
| 3036 | 3021 | } |
| 3037 | 3022 | return true; |
| 3038 | 3023 | }, |
| ... | ... | @@ -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 | 3489 | return switch (ty.ip_index) { |
| 3505 | 3490 | .empty_struct_type => .Auto, |
| 3506 | 3491 | .none => switch (ty.tag()) { |
| 3507 | 3492 | .tuple, .anon_struct => .Auto, |
| 3508 | .@"struct" => ty.castTag(.@"struct").?.data.layout, | |
| 3509 | 3493 | .@"union" => ty.castTag(.@"union").?.data.layout, |
| 3510 | 3494 | .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.layout, |
| 3511 | 3495 | .union_tagged => ty.castTag(.union_tagged).?.data.layout, |
| 3512 | 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 | 3621 | .array_sentinel => ty.castTag(.array_sentinel).?.data.len, |
| 3632 | 3622 | .tuple => ty.castTag(.tuple).?.data.types.len, |
| 3633 | 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 | 3625 | else => unreachable, |
| 3638 | 3626 | }, |
| 3639 | 3627 | else => switch (ip.indexToKey(ty.ip_index)) { |
| 3640 | 3628 | .vector_type => |vector_type| vector_type.len, |
| 3641 | 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 | 3634 | else => unreachable, |
| 3643 | 3635 | }, |
| 3644 | 3636 | }; |
| ... | ... | @@ -3665,11 +3657,9 @@ pub const Type = struct { |
| 3665 | 3657 | /// Asserts the type is an array, pointer or vector. |
| 3666 | 3658 | pub fn sentinel(ty: Type, mod: *const Module) ?Value { |
| 3667 | 3659 | return switch (ty.ip_index) { |
| 3668 | .empty_struct_type => null, | |
| 3669 | 3660 | .none => switch (ty.tag()) { |
| 3670 | 3661 | .array, |
| 3671 | 3662 | .tuple, |
| 3672 | .@"struct", | |
| 3673 | 3663 | => null, |
| 3674 | 3664 | |
| 3675 | 3665 | .pointer => ty.castTag(.pointer).?.data.sentinel, |
| ... | ... | @@ -3721,16 +3711,16 @@ pub const Type = struct { |
| 3721 | 3711 | |
| 3722 | 3712 | /// Returns true for integers, enums, error sets, and packed structs. |
| 3723 | 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 | 3715 | return switch (ty.zigTypeTag(mod)) { |
| 3726 | 3716 | .Int, .Enum, .ErrorSet => true, |
| 3727 | .Struct => ty.containerLayout() == .Packed, | |
| 3717 | .Struct => ty.containerLayout(mod) == .Packed, | |
| 3728 | 3718 | else => false, |
| 3729 | 3719 | }; |
| 3730 | 3720 | } |
| 3731 | 3721 | |
| 3732 | 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 | 3724 | const target = mod.getTarget(); |
| 3735 | 3725 | var ty = starting_ty; |
| 3736 | 3726 | |
| ... | ... | @@ -3750,12 +3740,6 @@ pub const Type = struct { |
| 3750 | 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 | 3743 | else => unreachable, |
| 3760 | 3744 | }, |
| 3761 | 3745 | .anyerror_type => { |
| ... | ... | @@ -3775,6 +3759,12 @@ pub const Type = struct { |
| 3775 | 3759 | .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulonglong) }, |
| 3776 | 3760 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 3777 | 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 | 3768 | .ptr_type => unreachable, |
| 3779 | 3769 | .array_type => unreachable, |
| 3780 | 3770 | .vector_type => |vector_type| ty = vector_type.child.toType(), |
| ... | ... | @@ -3782,7 +3772,7 @@ pub const Type = struct { |
| 3782 | 3772 | .opt_type => unreachable, |
| 3783 | 3773 | .error_union_type => unreachable, |
| 3784 | 3774 | .simple_type => unreachable, // handled via Index enum tag above |
| 3785 | .struct_type => @panic("TODO"), | |
| 3775 | ||
| 3786 | 3776 | .union_type => unreachable, |
| 3787 | 3777 | .opaque_type => unreachable, |
| 3788 | 3778 | |
| ... | ... | @@ -3793,6 +3783,7 @@ pub const Type = struct { |
| 3793 | 3783 | .ptr => unreachable, |
| 3794 | 3784 | .opt => unreachable, |
| 3795 | 3785 | .enum_tag => unreachable, |
| 3786 | .aggregate => unreachable, | |
| 3796 | 3787 | }, |
| 3797 | 3788 | }; |
| 3798 | 3789 | } |
| ... | ... | @@ -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 | 3990 | .tuple, .anon_struct => { |
| 4011 | 3991 | const tuple = ty.tupleFields(); |
| 4012 | 3992 | for (tuple.values, 0..) |val, i| { |
| ... | ... | @@ -4069,8 +4049,6 @@ pub const Type = struct { |
| 4069 | 4049 | return Value.empty_struct; |
| 4070 | 4050 | }, |
| 4071 | 4051 | |
| 4072 | .empty_struct => return Value.empty_struct, | |
| 4073 | ||
| 4074 | 4052 | .array => { |
| 4075 | 4053 | if (ty.arrayLen(mod) == 0) |
| 4076 | 4054 | return Value.initTag(.empty_array); |
| ... | ... | @@ -4158,7 +4136,23 @@ pub const Type = struct { |
| 4158 | 4136 | .generic_poison => unreachable, |
| 4159 | 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 | 4156 | .union_type => @panic("TODO"), |
| 4163 | 4157 | .opaque_type => return null, |
| 4164 | 4158 | |
| ... | ... | @@ -4169,6 +4163,7 @@ pub const Type = struct { |
| 4169 | 4163 | .ptr => unreachable, |
| 4170 | 4164 | .opt => unreachable, |
| 4171 | 4165 | .enum_tag => unreachable, |
| 4166 | .aggregate => unreachable, | |
| 4172 | 4167 | }, |
| 4173 | 4168 | }; |
| 4174 | 4169 | } |
| ... | ... | @@ -4177,12 +4172,11 @@ pub const Type = struct { |
| 4177 | 4172 | /// resolves field types rather than asserting they are already resolved. |
| 4178 | 4173 | /// TODO merge these implementations together with the "advanced" pattern seen |
| 4179 | 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 | 4176 | return switch (ty.ip_index) { |
| 4182 | 4177 | .empty_struct_type => false, |
| 4183 | 4178 | |
| 4184 | 4179 | .none => switch (ty.tag()) { |
| 4185 | .empty_struct, | |
| 4186 | 4180 | .error_set, |
| 4187 | 4181 | .error_set_single, |
| 4188 | 4182 | .error_set_inferred, |
| ... | ... | @@ -4222,20 +4216,6 @@ pub const Type = struct { |
| 4222 | 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 | 4219 | .@"union", .union_safety_tagged, .union_tagged => { |
| 4240 | 4220 | const union_obj = ty.cast(Type.Payload.Union).?.data; |
| 4241 | 4221 | switch (union_obj.requires_comptime) { |
| ... | ... | @@ -4326,7 +4306,21 @@ pub const Type = struct { |
| 4326 | 4306 | |
| 4327 | 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 | 4324 | .union_type => @panic("TODO"), |
| 4331 | 4325 | .opaque_type => false, |
| 4332 | 4326 | |
| ... | ... | @@ -4337,6 +4331,7 @@ pub const Type = struct { |
| 4337 | 4331 | .ptr => unreachable, |
| 4338 | 4332 | .opt => unreachable, |
| 4339 | 4333 | .enum_tag => unreachable, |
| 4334 | .aggregate => unreachable, | |
| 4340 | 4335 | }, |
| 4341 | 4336 | }; |
| 4342 | 4337 | } |
| ... | ... | @@ -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 | 4351 | return switch (ty.zigTypeTag(mod)) { |
| 4357 | 4352 | .Array, .Vector => true, |
| 4358 | 4353 | .Pointer => switch (ty.ptrSize(mod)) { |
| 4359 | 4354 | .Slice, .Many, .C => true, |
| 4360 | 4355 | .One => ty.childType(mod).zigTypeTag(mod) == .Array, |
| 4361 | 4356 | }, |
| 4362 | .Struct => ty.isTuple(), | |
| 4357 | .Struct => ty.isTuple(mod), | |
| 4363 | 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 | 4363 | return switch (ty.zigTypeTag(mod)) { |
| 4369 | 4364 | .Array, .Vector => true, |
| 4370 | 4365 | .Pointer => switch (ty.ptrSize(mod)) { |
| ... | ... | @@ -4372,7 +4367,7 @@ pub const Type = struct { |
| 4372 | 4367 | .Slice => true, |
| 4373 | 4368 | .One => ty.childType(mod).zigTypeTag(mod) == .Array, |
| 4374 | 4369 | }, |
| 4375 | .Struct => ty.isTuple(), | |
| 4370 | .Struct => ty.isTuple(mod), | |
| 4376 | 4371 | else => false, |
| 4377 | 4372 | }; |
| 4378 | 4373 | } |
| ... | ... | @@ -4381,10 +4376,8 @@ pub const Type = struct { |
| 4381 | 4376 | pub fn getNamespaceIndex(ty: Type, mod: *Module) Module.Namespace.OptionalIndex { |
| 4382 | 4377 | return switch (ty.ip_index) { |
| 4383 | 4378 | .none => switch (ty.tag()) { |
| 4384 | .@"struct" => ty.castTag(.@"struct").?.data.namespace.toOptional(), | |
| 4385 | 4379 | .enum_full => ty.castTag(.enum_full).?.data.namespace.toOptional(), |
| 4386 | 4380 | .enum_nonexhaustive => ty.castTag(.enum_nonexhaustive).?.data.namespace.toOptional(), |
| 4387 | .empty_struct => @panic("TODO"), | |
| 4388 | 4381 | .@"union" => ty.castTag(.@"union").?.data.namespace.toOptional(), |
| 4389 | 4382 | .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.namespace.toOptional(), |
| 4390 | 4383 | .union_tagged => ty.castTag(.union_tagged).?.data.namespace.toOptional(), |
| ... | ... | @@ -4393,6 +4386,7 @@ pub const Type = struct { |
| 4393 | 4386 | }, |
| 4394 | 4387 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 4395 | 4388 | .opaque_type => |opaque_type| opaque_type.namespace.toOptional(), |
| 4389 | .struct_type => |struct_type| struct_type.namespace, | |
| 4396 | 4390 | else => .none, |
| 4397 | 4391 | }, |
| 4398 | 4392 | }; |
| ... | ... | @@ -4618,161 +4612,188 @@ pub const Type = struct { |
| 4618 | 4612 | } |
| 4619 | 4613 | } |
| 4620 | 4614 | |
| 4621 | pub fn structFields(ty: Type) Module.Struct.Fields { | |
| 4622 | return switch (ty.ip_index) { | |
| 4623 | .empty_struct_type => .{}, | |
| 4624 | .none => switch (ty.tag()) { | |
| 4625 | .empty_struct => .{}, | |
| 4626 | .@"struct" => { | |
| 4627 | const struct_obj = ty.castTag(.@"struct").?.data; | |
| 4628 | assert(struct_obj.haveFieldTypes()); | |
| 4629 | return struct_obj.fields; | |
| 4630 | }, | |
| 4631 | else => unreachable, | |
| 4615 | pub fn structFields(ty: Type, mod: *Module) Module.Struct.Fields { | |
| 4616 | switch (mod.intern_pool.indexToKey(ty.ip_index)) { | |
| 4617 | .struct_type => |struct_type| { | |
| 4618 | const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return .{}; | |
| 4619 | assert(struct_obj.haveFieldTypes()); | |
| 4620 | return struct_obj.fields; | |
| 4632 | 4621 | }, |
| 4633 | 4622 | else => unreachable, |
| 4634 | }; | |
| 4623 | } | |
| 4635 | 4624 | } |
| 4636 | 4625 | |
| 4637 | pub fn structFieldName(ty: Type, field_index: usize) []const u8 { | |
| 4638 | switch (ty.tag()) { | |
| 4639 | .@"struct" => { | |
| 4640 | const struct_obj = ty.castTag(.@"struct").?.data; | |
| 4641 | assert(struct_obj.haveFieldTypes()); | |
| 4642 | return struct_obj.fields.keys()[field_index]; | |
| 4626 | pub fn structFieldName(ty: Type, field_index: usize, mod: *Module) []const u8 { | |
| 4627 | switch (ty.ip_index) { | |
| 4628 | .none => switch (ty.tag()) { | |
| 4629 | .anon_struct => return ty.castTag(.anon_struct).?.data.names[field_index], | |
| 4630 | else => unreachable, | |
| 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 | 4644 | return switch (ty.ip_index) { |
| 4651 | 4645 | .empty_struct_type => 0, |
| 4652 | 4646 | .none => switch (ty.tag()) { |
| 4653 | .@"struct" => { | |
| 4654 | const struct_obj = ty.castTag(.@"struct").?.data; | |
| 4647 | .tuple => ty.castTag(.tuple).?.data.types.len, | |
| 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 | 4654 | assert(struct_obj.haveFieldTypes()); |
| 4656 | 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 | 4657 | else => unreachable, |
| 4662 | 4658 | }, |
| 4663 | else => unreachable, | |
| 4664 | 4659 | }; |
| 4665 | 4660 | } |
| 4666 | 4661 | |
| 4667 | 4662 | /// Supports structs and unions. |
| 4668 | pub fn structFieldType(ty: Type, index: usize) Type { | |
| 4669 | switch (ty.tag()) { | |
| 4670 | .@"struct" => { | |
| 4671 | const struct_obj = ty.castTag(.@"struct").?.data; | |
| 4672 | return struct_obj.fields.values()[index].ty; | |
| 4663 | pub fn structFieldType(ty: Type, index: usize, mod: *Module) Type { | |
| 4664 | return switch (ty.ip_index) { | |
| 4665 | .none => switch (ty.tag()) { | |
| 4666 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 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 => { | |
| 4675 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 4676 | return union_obj.fields.values()[index].ty; | |
| 4674 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { | |
| 4675 | .struct_type => |struct_type| { | |
| 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], | |
| 4679 | .anon_struct => return ty.castTag(.anon_struct).?.data.types[index], | |
| 4680 | else => unreachable, | |
| 4681 | } | |
| 4681 | }; | |
| 4682 | 4682 | } |
| 4683 | 4683 | |
| 4684 | 4684 | pub fn structFieldAlign(ty: Type, index: usize, mod: *Module) u32 { |
| 4685 | switch (ty.tag()) { | |
| 4686 | .@"struct" => { | |
| 4687 | const struct_obj = ty.castTag(.@"struct").?.data; | |
| 4688 | assert(struct_obj.layout != .Packed); | |
| 4689 | return struct_obj.fields.values()[index].alignment(mod, struct_obj.layout); | |
| 4685 | switch (ty.ip_index) { | |
| 4686 | .none => switch (ty.tag()) { | |
| 4687 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 4688 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 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 => { | |
| 4692 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 4693 | return union_obj.fields.values()[index].normalAlignment(mod); | |
| 4695 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { | |
| 4696 | .struct_type => |struct_type| { | |
| 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 { | |
| 4702 | switch (ty.tag()) { | |
| 4703 | .@"struct" => { | |
| 4704 | const struct_obj = ty.castTag(.@"struct").?.data; | |
| 4705 | return struct_obj.fields.values()[index].default_val; | |
| 4706 | }, | |
| 4707 | .tuple => { | |
| 4708 | const tuple = ty.castTag(.tuple).?.data; | |
| 4709 | return tuple.values[index]; | |
| 4706 | pub fn structFieldDefaultValue(ty: Type, index: usize, mod: *Module) Value { | |
| 4707 | switch (ty.ip_index) { | |
| 4708 | .none => switch (ty.tag()) { | |
| 4709 | .tuple => { | |
| 4710 | const tuple = ty.castTag(.tuple).?.data; | |
| 4711 | return tuple.values[index]; | |
| 4712 | }, | |
| 4713 | .anon_struct => { | |
| 4714 | const struct_obj = ty.castTag(.anon_struct).?.data; | |
| 4715 | return struct_obj.values[index]; | |
| 4716 | }, | |
| 4717 | else => unreachable, | |
| 4710 | 4718 | }, |
| 4711 | .anon_struct => { | |
| 4712 | const struct_obj = ty.castTag(.anon_struct).?.data; | |
| 4713 | return struct_obj.values[index]; | |
| 4719 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { | |
| 4720 | .struct_type => |struct_type| { | |
| 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 | 4729 | pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value { |
| 4720 | switch (ty.tag()) { | |
| 4721 | .@"struct" => { | |
| 4722 | const struct_obj = ty.castTag(.@"struct").?.data; | |
| 4723 | const field = struct_obj.fields.values()[index]; | |
| 4724 | if (field.is_comptime) { | |
| 4725 | return field.default_val; | |
| 4726 | } else { | |
| 4727 | return field.ty.onePossibleValue(mod); | |
| 4728 | } | |
| 4729 | }, | |
| 4730 | .tuple => { | |
| 4731 | const tuple = ty.castTag(.tuple).?.data; | |
| 4732 | const val = tuple.values[index]; | |
| 4733 | if (val.ip_index == .unreachable_value) { | |
| 4734 | return tuple.types[index].onePossibleValue(mod); | |
| 4735 | } else { | |
| 4736 | return val; | |
| 4737 | } | |
| 4730 | switch (ty.ip_index) { | |
| 4731 | .none => switch (ty.tag()) { | |
| 4732 | .tuple => { | |
| 4733 | const tuple = ty.castTag(.tuple).?.data; | |
| 4734 | const val = tuple.values[index]; | |
| 4735 | if (val.ip_index == .unreachable_value) { | |
| 4736 | return tuple.types[index].onePossibleValue(mod); | |
| 4737 | } else { | |
| 4738 | return val; | |
| 4739 | } | |
| 4740 | }, | |
| 4741 | .anon_struct => { | |
| 4742 | const anon_struct = ty.castTag(.anon_struct).?.data; | |
| 4743 | const val = anon_struct.values[index]; | |
| 4744 | if (val.ip_index == .unreachable_value) { | |
| 4745 | return anon_struct.types[index].onePossibleValue(mod); | |
| 4746 | } else { | |
| 4747 | return val; | |
| 4748 | } | |
| 4749 | }, | |
| 4750 | else => unreachable, | |
| 4738 | 4751 | }, |
| 4739 | .anon_struct => { | |
| 4740 | const anon_struct = ty.castTag(.anon_struct).?.data; | |
| 4741 | const val = anon_struct.values[index]; | |
| 4742 | if (val.ip_index == .unreachable_value) { | |
| 4743 | return anon_struct.types[index].onePossibleValue(mod); | |
| 4744 | } else { | |
| 4745 | return val; | |
| 4746 | } | |
| 4752 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { | |
| 4753 | .struct_type => |struct_type| { | |
| 4754 | const struct_obj = mod.structPtrUnwrap(struct_type.index).?; | |
| 4755 | const field = struct_obj.fields.values()[index]; | |
| 4756 | if (field.is_comptime) { | |
| 4757 | return field.default_val; | |
| 4758 | } else { | |
| 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 { | |
| 4753 | switch (ty.tag()) { | |
| 4754 | .@"struct" => { | |
| 4755 | const struct_obj = ty.castTag(.@"struct").?.data; | |
| 4756 | if (struct_obj.layout == .Packed) return false; | |
| 4757 | const field = struct_obj.fields.values()[index]; | |
| 4758 | return field.is_comptime; | |
| 4759 | }, | |
| 4760 | .tuple => { | |
| 4761 | const tuple = ty.castTag(.tuple).?.data; | |
| 4762 | const val = tuple.values[index]; | |
| 4763 | return val.ip_index != .unreachable_value; | |
| 4767 | pub fn structFieldIsComptime(ty: Type, index: usize, mod: *Module) bool { | |
| 4768 | switch (ty.ip_index) { | |
| 4769 | .none => switch (ty.tag()) { | |
| 4770 | .tuple => { | |
| 4771 | const tuple = ty.castTag(.tuple).?.data; | |
| 4772 | const val = tuple.values[index]; | |
| 4773 | return val.ip_index != .unreachable_value; | |
| 4774 | }, | |
| 4775 | .anon_struct => { | |
| 4776 | const anon_struct = ty.castTag(.anon_struct).?.data; | |
| 4777 | const val = anon_struct.values[index]; | |
| 4778 | return val.ip_index != .unreachable_value; | |
| 4779 | }, | |
| 4780 | else => unreachable, | |
| 4764 | 4781 | }, |
| 4765 | .anon_struct => { | |
| 4766 | const anon_struct = ty.castTag(.anon_struct).?.data; | |
| 4767 | const val = anon_struct.values[index]; | |
| 4768 | return val.ip_index != .unreachable_value; | |
| 4782 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { | |
| 4783 | .struct_type => |struct_type| { | |
| 4784 | const struct_obj = mod.structPtrUnwrap(struct_type.index).?; | |
| 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 | 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 | 4797 | assert(struct_obj.layout == .Packed); |
| 4777 | 4798 | comptime assert(Type.packed_struct_layout_version == 2); |
| 4778 | 4799 | |
| ... | ... | @@ -4833,7 +4854,8 @@ pub const Type = struct { |
| 4833 | 4854 | /// Get an iterator that iterates over all the struct field, returning the field and |
| 4834 | 4855 | /// offset of that field. Asserts that the type is a non-packed struct. |
| 4835 | 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 | 4859 | assert(struct_obj.haveLayout()); |
| 4838 | 4860 | assert(struct_obj.layout != .Packed); |
| 4839 | 4861 | return .{ .struct_obj = struct_obj, .module = mod }; |
| ... | ... | @@ -4841,57 +4863,62 @@ pub const Type = struct { |
| 4841 | 4863 | |
| 4842 | 4864 | /// Supports structs and unions. |
| 4843 | 4865 | pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 { |
| 4844 | switch (ty.tag()) { | |
| 4845 | .@"struct" => { | |
| 4846 | const struct_obj = ty.castTag(.@"struct").?.data; | |
| 4847 | assert(struct_obj.haveLayout()); | |
| 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 | }, | |
| 4866 | switch (ty.ip_index) { | |
| 4867 | .none => switch (ty.tag()) { | |
| 4868 | .tuple, .anon_struct => { | |
| 4869 | const tuple = ty.tupleFields(); | |
| 4857 | 4870 | |
| 4858 | .tuple, .anon_struct => { | |
| 4859 | const tuple = ty.tupleFields(); | |
| 4871 | var offset: u64 = 0; | |
| 4872 | var big_align: u32 = 0; | |
| 4860 | 4873 | |
| 4861 | var offset: u64 = 0; | |
| 4862 | var big_align: u32 = 0; | |
| 4874 | for (tuple.types, 0..) |field_ty, i| { | |
| 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| { | |
| 4865 | const field_val = tuple.values[i]; | |
| 4866 | if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) { | |
| 4867 | // comptime field | |
| 4882 | const field_align = field_ty.abiAlignment(mod); | |
| 4883 | big_align = @max(big_align, field_align); | |
| 4884 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); | |
| 4868 | 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); | |
| 4873 | big_align = @max(big_align, field_align); | |
| 4874 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); | |
| 4875 | if (i == index) return offset; | |
| 4876 | offset += field_ty.abiSize(mod); | |
| 4877 | } | |
| 4878 | offset = std.mem.alignForwardGeneric(u64, offset, @max(big_align, 1)); | |
| 4879 | return offset; | |
| 4892 | .@"union" => return 0, | |
| 4893 | .union_safety_tagged, .union_tagged => { | |
| 4894 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 4895 | const layout = union_obj.getLayout(mod, true); | |
| 4896 | if (layout.tag_align >= layout.payload_align) { | |
| 4897 | // {Tag, Payload} | |
| 4898 | return std.mem.alignForwardGeneric(u64, layout.tag_size, layout.payload_align); | |
| 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, | |
| 4883 | .union_safety_tagged, .union_tagged => { | |
| 4884 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 4885 | const layout = union_obj.getLayout(mod, true); | |
| 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 | } | |
| 4917 | return std.mem.alignForwardGeneric(u64, it.offset, @max(it.big_align, 1)); | |
| 4918 | }, | |
| 4919 | ||
| 4920 | else => unreachable, | |
| 4893 | 4921 | }, |
| 4894 | else => unreachable, | |
| 4895 | 4922 | } |
| 4896 | 4923 | } |
| 4897 | 4924 | |
| ... | ... | @@ -4901,6 +4928,7 @@ pub const Type = struct { |
| 4901 | 4928 | |
| 4902 | 4929 | pub fn declSrcLocOrNull(ty: Type, mod: *Module) ?Module.SrcLoc { |
| 4903 | 4930 | switch (ty.ip_index) { |
| 4931 | .empty_struct_type => return null, | |
| 4904 | 4932 | .none => switch (ty.tag()) { |
| 4905 | 4933 | .enum_full, .enum_nonexhaustive => { |
| 4906 | 4934 | const enum_full = ty.cast(Payload.EnumFull).?.data; |
| ... | ... | @@ -4914,10 +4942,6 @@ pub const Type = struct { |
| 4914 | 4942 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| 4915 | 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 | 4945 | .error_set => { |
| 4922 | 4946 | const error_set = ty.castTag(.error_set).?.data; |
| 4923 | 4947 | return error_set.srcLoc(mod); |
| ... | ... | @@ -4930,7 +4954,10 @@ pub const Type = struct { |
| 4930 | 4954 | else => return null, |
| 4931 | 4955 | }, |
| 4932 | 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 | 4961 | .union_type => @panic("TODO"), |
| 4935 | 4962 | .opaque_type => |opaque_type| mod.opaqueSrcLoc(opaque_type), |
| 4936 | 4963 | else => null, |
| ... | ... | @@ -4954,10 +4981,6 @@ pub const Type = struct { |
| 4954 | 4981 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| 4955 | 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 | 4984 | .error_set => { |
| 4962 | 4985 | const error_set = ty.castTag(.error_set).?.data; |
| 4963 | 4986 | return error_set.owner_decl; |
| ... | ... | @@ -4970,7 +4993,10 @@ pub const Type = struct { |
| 4970 | 4993 | else => return null, |
| 4971 | 4994 | }, |
| 4972 | 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 | 5000 | .union_type => @panic("TODO"), |
| 4975 | 5001 | .opaque_type => |opaque_type| opaque_type.decl, |
| 4976 | 5002 | else => null, |
| ... | ... | @@ -5013,8 +5039,6 @@ pub const Type = struct { |
| 5013 | 5039 | /// The type is the inferred error set of a specific function. |
| 5014 | 5040 | error_set_inferred, |
| 5015 | 5041 | error_set_merged, |
| 5016 | empty_struct, | |
| 5017 | @"struct", | |
| 5018 | 5042 | @"union", |
| 5019 | 5043 | union_safety_tagged, |
| 5020 | 5044 | union_tagged, |
| ... | ... | @@ -5046,12 +5070,10 @@ pub const Type = struct { |
| 5046 | 5070 | .function => Payload.Function, |
| 5047 | 5071 | .error_union => Payload.ErrorUnion, |
| 5048 | 5072 | .error_set_single => Payload.Name, |
| 5049 | .@"struct" => Payload.Struct, | |
| 5050 | 5073 | .@"union", .union_safety_tagged, .union_tagged => Payload.Union, |
| 5051 | 5074 | .enum_full, .enum_nonexhaustive => Payload.EnumFull, |
| 5052 | 5075 | .enum_simple => Payload.EnumSimple, |
| 5053 | 5076 | .enum_numbered => Payload.EnumNumbered, |
| 5054 | .empty_struct => Payload.ContainerScope, | |
| 5055 | 5077 | .tuple => Payload.Tuple, |
| 5056 | 5078 | .anon_struct => Payload.AnonStruct, |
| 5057 | 5079 | }; |
| ... | ... | @@ -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 | 5108 | return switch (ty.ip_index) { |
| 5087 | .empty_struct_type => true, | |
| 5088 | 5109 | .none => switch (ty.tag()) { |
| 5089 | 5110 | .tuple => true, |
| 5090 | .@"struct" => ty.castTag(.@"struct").?.data.is_tuple, | |
| 5091 | 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 | 5127 | .anon_struct => true, |
| 5102 | 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 | 5135 | return switch (ty.ip_index) { |
| 5110 | 5136 | .empty_struct_type => true, |
| 5111 | 5137 | .none => switch (ty.tag()) { |
| 5112 | 5138 | .tuple, .anon_struct => true, |
| 5113 | .@"struct" => ty.castTag(.@"struct").?.data.is_tuple, | |
| 5114 | 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 | 5151 | pub fn isSimpleTuple(ty: Type) bool { |
| 5121 | 5152 | return switch (ty.ip_index) { |
| 5122 | .empty_struct => true, | |
| 5153 | .empty_struct_type => true, | |
| 5123 | 5154 | .none => switch (ty.tag()) { |
| 5124 | 5155 | .tuple => true, |
| 5125 | 5156 | else => false, |
| 5126 | 5157 | }, |
| 5127 | else => false, // TODO | |
| 5158 | else => false, | |
| 5128 | 5159 | }; |
| 5129 | 5160 | } |
| 5130 | 5161 | |
| 5131 | 5162 | pub fn isSimpleTupleOrAnonStruct(ty: Type) bool { |
| 5132 | 5163 | return switch (ty.ip_index) { |
| 5133 | .empty_struct => true, | |
| 5164 | .empty_struct_type => true, | |
| 5134 | 5165 | .none => switch (ty.tag()) { |
| 5135 | 5166 | .tuple, .anon_struct => true, |
| 5136 | 5167 | else => false, |
| ... | ... | @@ -5142,7 +5173,7 @@ pub const Type = struct { |
| 5142 | 5173 | // Only allowed for simple tuple types |
| 5143 | 5174 | pub fn tupleFields(ty: Type) Payload.Tuple.Data { |
| 5144 | 5175 | return switch (ty.ip_index) { |
| 5145 | .empty_struct => .{ .types = &.{}, .values = &.{} }, | |
| 5176 | .empty_struct_type => .{ .types = &.{}, .values = &.{} }, | |
| 5146 | 5177 | .none => switch (ty.tag()) { |
| 5147 | 5178 | .tuple => ty.castTag(.tuple).?.data, |
| 5148 | 5179 | .anon_struct => .{ |
| ... | ... | @@ -5319,18 +5350,6 @@ pub const Type = struct { |
| 5319 | 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 | 5353 | pub const Tuple = struct { |
| 5335 | 5354 | base: Payload = .{ .tag = .tuple }, |
| 5336 | 5355 | data: Data, |
src/value.zig+19-26| ... | ... | @@ -996,10 +996,10 @@ pub const Value = struct { |
| 996 | 996 | const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8; |
| 997 | 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 | 1000 | .Auto => return error.IllDefinedMemoryLayout, |
| 1001 | 1001 | .Extern => { |
| 1002 | const fields = ty.structFields().values(); | |
| 1002 | const fields = ty.structFields(mod).values(); | |
| 1003 | 1003 | const field_vals = val.castTag(.aggregate).?.data; |
| 1004 | 1004 | for (fields, 0..) |field, i| { |
| 1005 | 1005 | const off = @intCast(usize, ty.structFieldOffset(i, mod)); |
| ... | ... | @@ -1017,7 +1017,7 @@ pub const Value = struct { |
| 1017 | 1017 | const int = mod.global_error_set.get(val.castTag(.@"error").?.data.name).?; |
| 1018 | 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 | 1021 | .Auto => return error.IllDefinedMemoryLayout, |
| 1022 | 1022 | .Extern => return error.Unimplemented, |
| 1023 | 1023 | .Packed => { |
| ... | ... | @@ -1119,12 +1119,12 @@ pub const Value = struct { |
| 1119 | 1119 | bits += elem_bit_size; |
| 1120 | 1120 | } |
| 1121 | 1121 | }, |
| 1122 | .Struct => switch (ty.containerLayout()) { | |
| 1122 | .Struct => switch (ty.containerLayout(mod)) { | |
| 1123 | 1123 | .Auto => unreachable, // Sema is supposed to have emitted a compile error already |
| 1124 | 1124 | .Extern => unreachable, // Handled in non-packed writeToMemory |
| 1125 | 1125 | .Packed => { |
| 1126 | 1126 | var bits: u16 = 0; |
| 1127 | const fields = ty.structFields().values(); | |
| 1127 | const fields = ty.structFields(mod).values(); | |
| 1128 | 1128 | const field_vals = val.castTag(.aggregate).?.data; |
| 1129 | 1129 | for (fields, 0..) |field, i| { |
| 1130 | 1130 | const field_bits = @intCast(u16, field.ty.bitSize(mod)); |
| ... | ... | @@ -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 | 1137 | .Auto => unreachable, // Sema is supposed to have emitted a compile error already |
| 1138 | 1138 | .Extern => unreachable, // Handled in non-packed writeToMemory |
| 1139 | 1139 | .Packed => { |
| ... | ... | @@ -1236,14 +1236,14 @@ pub const Value = struct { |
| 1236 | 1236 | const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8; |
| 1237 | 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 | 1240 | .Auto => unreachable, // Sema is supposed to have emitted a compile error already |
| 1241 | 1241 | .Extern => { |
| 1242 | const fields = ty.structFields().values(); | |
| 1242 | const fields = ty.structFields(mod).values(); | |
| 1243 | 1243 | const field_vals = try arena.alloc(Value, fields.len); |
| 1244 | 1244 | for (fields, 0..) |field, i| { |
| 1245 | 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 | 1247 | field_vals[i] = try readFromMemory(field.ty, mod, buffer[off..(off + sz)], arena); |
| 1248 | 1248 | } |
| 1249 | 1249 | return Tag.aggregate.create(arena, field_vals); |
| ... | ... | @@ -1346,12 +1346,12 @@ pub const Value = struct { |
| 1346 | 1346 | } |
| 1347 | 1347 | return Tag.aggregate.create(arena, elems); |
| 1348 | 1348 | }, |
| 1349 | .Struct => switch (ty.containerLayout()) { | |
| 1349 | .Struct => switch (ty.containerLayout(mod)) { | |
| 1350 | 1350 | .Auto => unreachable, // Sema is supposed to have emitted a compile error already |
| 1351 | 1351 | .Extern => unreachable, // Handled by non-packed readFromMemory |
| 1352 | 1352 | .Packed => { |
| 1353 | 1353 | var bits: u16 = 0; |
| 1354 | const fields = ty.structFields().values(); | |
| 1354 | const fields = ty.structFields(mod).values(); | |
| 1355 | 1355 | const field_vals = try arena.alloc(Value, fields.len); |
| 1356 | 1356 | for (fields, 0..) |field, i| { |
| 1357 | 1357 | const field_bits = @intCast(u16, field.ty.bitSize(mod)); |
| ... | ... | @@ -1996,7 +1996,7 @@ pub const Value = struct { |
| 1996 | 1996 | } |
| 1997 | 1997 | |
| 1998 | 1998 | if (ty.zigTypeTag(mod) == .Struct) { |
| 1999 | const fields = ty.structFields().values(); | |
| 1999 | const fields = ty.structFields(mod).values(); | |
| 2000 | 2000 | assert(fields.len == a_field_vals.len); |
| 2001 | 2001 | for (fields, 0..) |field, i| { |
| 2002 | 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 | 2019 | .@"union" => { |
| 2020 | 2020 | const a_union = a.castTag(.@"union").?.data; |
| 2021 | 2021 | const b_union = b.castTag(.@"union").?.data; |
| 2022 | switch (ty.containerLayout()) { | |
| 2022 | switch (ty.containerLayout(mod)) { | |
| 2023 | 2023 | .Packed, .Extern => { |
| 2024 | 2024 | const tag_ty = ty.unionTagTypeHypothetical(); |
| 2025 | 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 | 2252 | .aggregate => { |
| 2253 | 2253 | const field_values = val.castTag(.aggregate).?.data; |
| 2254 | 2254 | for (field_values, 0..) |field_val, i| { |
| 2255 | const field_ty = ty.structFieldType(i); | |
| 2255 | const field_ty = ty.structFieldType(i, mod); | |
| 2256 | 2256 | field_val.hash(field_ty, hasher, mod); |
| 2257 | 2257 | } |
| 2258 | 2258 | }, |
| ... | ... | @@ -2623,7 +2623,7 @@ pub const Value = struct { |
| 2623 | 2623 | const data = val.castTag(.field_ptr).?.data; |
| 2624 | 2624 | if (data.container_ptr.pointerDecl()) |decl_index| { |
| 2625 | 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 | 2627 | const field_val = try container_decl.val.fieldValue(field_type, mod, data.field_index); |
| 2628 | 2628 | return field_val.elemValue(mod, index); |
| 2629 | 2629 | } else unreachable; |
| ... | ... | @@ -2758,16 +2758,6 @@ pub const Value = struct { |
| 2758 | 2758 | pub fn fieldValue(val: Value, ty: Type, mod: *Module, index: usize) !Value { |
| 2759 | 2759 | switch (val.ip_index) { |
| 2760 | 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 | 2762 | .none => switch (val.tag()) { |
| 2773 | 2763 | .aggregate => { |
| ... | ... | @@ -2784,7 +2774,10 @@ pub const Value = struct { |
| 2784 | 2774 | |
| 2785 | 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 |