| ... | @@ -34,8 +34,51 @@ pub const Type = struct { | ... | @@ -34,8 +34,51 @@ pub const Type = struct { |
| 34 | } | 34 | } |
| 35 | | 35 | |
| 36 | pub fn zigTypeTagOrPoison(ty: Type, mod: *const Module) error{GenericPoison}!std.builtin.TypeId { | 36 | pub fn zigTypeTagOrPoison(ty: Type, mod: *const Module) error{GenericPoison}!std.builtin.TypeId { |
| 37 | if (ty.ip_index != .none) { | 37 | switch (ty.ip_index) { |
| 38 | switch (mod.intern_pool.indexToKey(ty.ip_index)) { | 38 | .none => switch (ty.tag()) { |
| | 39 | .error_set, |
| | 40 | .error_set_single, |
| | 41 | .error_set_inferred, |
| | 42 | .error_set_merged, |
| | 43 | => return .ErrorSet, |
| | 44 | |
| | 45 | .@"opaque" => return .Opaque, |
| | 46 | |
| | 47 | .function => return .Fn, |
| | 48 | |
| | 49 | .array, |
| | 50 | .array_sentinel, |
| | 51 | => return .Array, |
| | 52 | |
| | 53 | .pointer, |
| | 54 | .inferred_alloc_const, |
| | 55 | .inferred_alloc_mut, |
| | 56 | => return .Pointer, |
| | 57 | |
| | 58 | .optional => return .Optional, |
| | 59 | |
| | 60 | .error_union => return .ErrorUnion, |
| | 61 | |
| | 62 | .anyframe_T => return .AnyFrame, |
| | 63 | |
| | 64 | .empty_struct, |
| | 65 | .@"struct", |
| | 66 | .tuple, |
| | 67 | .anon_struct, |
| | 68 | => return .Struct, |
| | 69 | |
| | 70 | .enum_full, |
| | 71 | .enum_nonexhaustive, |
| | 72 | .enum_simple, |
| | 73 | .enum_numbered, |
| | 74 | => return .Enum, |
| | 75 | |
| | 76 | .@"union", |
| | 77 | .union_safety_tagged, |
| | 78 | .union_tagged, |
| | 79 | => return .Union, |
| | 80 | }, |
| | 81 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 39 | .int_type => return .Int, | 82 | .int_type => return .Int, |
| 40 | .ptr_type => return .Pointer, | 83 | .ptr_type => return .Pointer, |
| 41 | .array_type => return .Array, | 84 | .array_type => return .Array, |
| ... | @@ -104,51 +147,7 @@ pub const Type = struct { | ... | @@ -104,51 +147,7 @@ pub const Type = struct { |
| 104 | .enum_tag, | 147 | .enum_tag, |
| 105 | .simple_value, | 148 | .simple_value, |
| 106 | => unreachable, // it's a value, not a type | 149 | => unreachable, // it's a value, not a type |
| 107 | } | 150 | }, |
| 108 | } | | |
| 109 | switch (ty.tag()) { | | |
| 110 | .error_set, | | |
| 111 | .error_set_single, | | |
| 112 | .error_set_inferred, | | |
| 113 | .error_set_merged, | | |
| 114 | => return .ErrorSet, | | |
| 115 | | | |
| 116 | .@"opaque" => return .Opaque, | | |
| 117 | | | |
| 118 | .function => return .Fn, | | |
| 119 | | | |
| 120 | .array, | | |
| 121 | .array_sentinel, | | |
| 122 | => return .Array, | | |
| 123 | | | |
| 124 | .pointer, | | |
| 125 | .inferred_alloc_const, | | |
| 126 | .inferred_alloc_mut, | | |
| 127 | => return .Pointer, | | |
| 128 | | | |
| 129 | .optional => return .Optional, | | |
| 130 | | | |
| 131 | .error_union => return .ErrorUnion, | | |
| 132 | | | |
| 133 | .anyframe_T => return .AnyFrame, | | |
| 134 | | | |
| 135 | .empty_struct, | | |
| 136 | .empty_struct_literal, | | |
| 137 | .@"struct", | | |
| 138 | .tuple, | | |
| 139 | .anon_struct, | | |
| 140 | => return .Struct, | | |
| 141 | | | |
| 142 | .enum_full, | | |
| 143 | .enum_nonexhaustive, | | |
| 144 | .enum_simple, | | |
| 145 | .enum_numbered, | | |
| 146 | => return .Enum, | | |
| 147 | | | |
| 148 | .@"union", | | |
| 149 | .union_safety_tagged, | | |
| 150 | .union_tagged, | | |
| 151 | => return .Union, | | |
| 152 | } | 151 | } |
| 153 | } | 152 | } |
| 154 | | 153 | |
| ... | @@ -517,7 +516,7 @@ pub const Type = struct { | ... | @@ -517,7 +516,7 @@ pub const Type = struct { |
| 517 | const b_struct_obj = (b.castTag(.@"struct") orelse return false).data; | 516 | const b_struct_obj = (b.castTag(.@"struct") orelse return false).data; |
| 518 | return a_struct_obj == b_struct_obj; | 517 | return a_struct_obj == b_struct_obj; |
| 519 | }, | 518 | }, |
| 520 | .tuple, .empty_struct_literal => { | 519 | .tuple => { |
| 521 | if (!b.isSimpleTuple()) return false; | 520 | if (!b.isSimpleTuple()) return false; |
| 522 | | 521 | |
| 523 | const a_tuple = a.tupleFields(); | 522 | const a_tuple = a.tupleFields(); |
| ... | @@ -741,7 +740,7 @@ pub const Type = struct { | ... | @@ -741,7 +740,7 @@ pub const Type = struct { |
| 741 | const struct_obj: *const Module.Struct = ty.castTag(.@"struct").?.data; | 740 | const struct_obj: *const Module.Struct = ty.castTag(.@"struct").?.data; |
| 742 | std.hash.autoHash(hasher, struct_obj); | 741 | std.hash.autoHash(hasher, struct_obj); |
| 743 | }, | 742 | }, |
| 744 | .tuple, .empty_struct_literal => { | 743 | .tuple => { |
| 745 | std.hash.autoHash(hasher, std.builtin.TypeId.Struct); | 744 | std.hash.autoHash(hasher, std.builtin.TypeId.Struct); |
| 746 | | 745 | |
| 747 | const tuple = ty.tupleFields(); | 746 | const tuple = ty.tupleFields(); |
| ... | @@ -837,7 +836,6 @@ pub const Type = struct { | ... | @@ -837,7 +836,6 @@ pub const Type = struct { |
| 837 | } else switch (self.legacy.ptr_otherwise.tag) { | 836 | } else switch (self.legacy.ptr_otherwise.tag) { |
| 838 | .inferred_alloc_const, | 837 | .inferred_alloc_const, |
| 839 | .inferred_alloc_mut, | 838 | .inferred_alloc_mut, |
| 840 | .empty_struct_literal, | | |
| 841 | => unreachable, | 839 | => unreachable, |
| 842 | | 840 | |
| 843 | .optional, | 841 | .optional, |
| ... | @@ -1047,7 +1045,7 @@ pub const Type = struct { | ... | @@ -1047,7 +1045,7 @@ pub const Type = struct { |
| 1047 | while (true) { | 1045 | while (true) { |
| 1048 | const t = ty.tag(); | 1046 | const t = ty.tag(); |
| 1049 | switch (t) { | 1047 | switch (t) { |
| 1050 | .empty_struct, .empty_struct_literal => return writer.writeAll("struct {}"), | 1048 | .empty_struct => return writer.writeAll("struct {}"), |
| 1051 | | 1049 | |
| 1052 | .@"struct" => { | 1050 | .@"struct" => { |
| 1053 | const struct_obj = ty.castTag(.@"struct").?.data; | 1051 | const struct_obj = ty.castTag(.@"struct").?.data; |
| ... | @@ -1266,327 +1264,328 @@ pub const Type = struct { | ... | @@ -1266,327 +1264,328 @@ pub const Type = struct { |
| 1266 | | 1264 | |
| 1267 | /// Prints a name suitable for `@typeName`. | 1265 | /// Prints a name suitable for `@typeName`. |
| 1268 | pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void { | 1266 | pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void { |
| 1269 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { | 1267 | switch (ty.ip_index) { |
| 1270 | .int_type => |int_type| { | 1268 | .empty_struct_type => try writer.writeAll("@TypeOf(.{})"), |
| 1271 | const sign_char: u8 = switch (int_type.signedness) { | | |
| 1272 | .signed => 'i', | | |
| 1273 | .unsigned => 'u', | | |
| 1274 | }; | | |
| 1275 | return writer.print("{c}{d}", .{ sign_char, int_type.bits }); | | |
| 1276 | }, | | |
| 1277 | .ptr_type => { | | |
| 1278 | const info = ty.ptrInfo(mod); | | |
| 1279 | | | |
| 1280 | if (info.sentinel) |s| switch (info.size) { | | |
| 1281 | .One, .C => unreachable, | | |
| 1282 | .Many => try writer.print("[*:{}]", .{s.fmtValue(info.pointee_type, mod)}), | | |
| 1283 | .Slice => try writer.print("[:{}]", .{s.fmtValue(info.pointee_type, mod)}), | | |
| 1284 | } else switch (info.size) { | | |
| 1285 | .One => try writer.writeAll("*"), | | |
| 1286 | .Many => try writer.writeAll("[*]"), | | |
| 1287 | .C => try writer.writeAll("[*c]"), | | |
| 1288 | .Slice => try writer.writeAll("[]"), | | |
| 1289 | } | | |
| 1290 | if (info.@"align" != 0 or info.host_size != 0 or info.vector_index != .none) { | | |
| 1291 | if (info.@"align" != 0) { | | |
| 1292 | try writer.print("align({d}", .{info.@"align"}); | | |
| 1293 | } else { | | |
| 1294 | const alignment = info.pointee_type.abiAlignment(mod); | | |
| 1295 | try writer.print("align({d}", .{alignment}); | | |
| 1296 | } | | |
| 1297 | | | |
| 1298 | if (info.bit_offset != 0 or info.host_size != 0) { | | |
| 1299 | try writer.print(":{d}:{d}", .{ info.bit_offset, info.host_size }); | | |
| 1300 | } | | |
| 1301 | if (info.vector_index == .runtime) { | | |
| 1302 | try writer.writeAll(":?"); | | |
| 1303 | } else if (info.vector_index != .none) { | | |
| 1304 | try writer.print(":{d}", .{@enumToInt(info.vector_index)}); | | |
| 1305 | } | | |
| 1306 | try writer.writeAll(") "); | | |
| 1307 | } | | |
| 1308 | if (info.@"addrspace" != .generic) { | | |
| 1309 | try writer.print("addrspace(.{s}) ", .{@tagName(info.@"addrspace")}); | | |
| 1310 | } | | |
| 1311 | if (!info.mutable) try writer.writeAll("const "); | | |
| 1312 | if (info.@"volatile") try writer.writeAll("volatile "); | | |
| 1313 | if (info.@"allowzero" and info.size != .C) try writer.writeAll("allowzero "); | | |
| 1314 | | | |
| 1315 | try print(info.pointee_type, writer, mod); | | |
| 1316 | return; | | |
| 1317 | }, | | |
| 1318 | .array_type => |array_type| { | | |
| 1319 | if (array_type.sentinel == .none) { | | |
| 1320 | try writer.print("[{d}]", .{array_type.len}); | | |
| 1321 | try print(array_type.child.toType(), writer, mod); | | |
| 1322 | } else { | | |
| 1323 | try writer.print("[{d}:{}]", .{ | | |
| 1324 | array_type.len, | | |
| 1325 | array_type.sentinel.toValue().fmtValue(array_type.child.toType(), mod), | | |
| 1326 | }); | | |
| 1327 | try print(array_type.child.toType(), writer, mod); | | |
| 1328 | } | | |
| 1329 | return; | | |
| 1330 | }, | | |
| 1331 | .vector_type => |vector_type| { | | |
| 1332 | try writer.print("@Vector({d}, ", .{vector_type.len}); | | |
| 1333 | try print(vector_type.child.toType(), writer, mod); | | |
| 1334 | try writer.writeAll(")"); | | |
| 1335 | return; | | |
| 1336 | }, | | |
| 1337 | .opt_type => |child| { | | |
| 1338 | try writer.writeByte('?'); | | |
| 1339 | try print(child.toType(), writer, mod); | | |
| 1340 | return; | | |
| 1341 | }, | | |
| 1342 | .error_union_type => |error_union_type| { | | |
| 1343 | try print(error_union_type.error_set_type.toType(), writer, mod); | | |
| 1344 | try writer.writeByte('!'); | | |
| 1345 | try print(error_union_type.payload_type.toType(), writer, mod); | | |
| 1346 | return; | | |
| 1347 | }, | | |
| 1348 | .simple_type => |s| return writer.writeAll(@tagName(s)), | | |
| 1349 | .struct_type => @panic("TODO"), | | |
| 1350 | .union_type => @panic("TODO"), | | |
| 1351 | .simple_value => unreachable, | | |
| 1352 | .extern_func => unreachable, | | |
| 1353 | .int => unreachable, | | |
| 1354 | .enum_tag => unreachable, | | |
| 1355 | }; | | |
| 1356 | const t = ty.tag(); | | |
| 1357 | switch (t) { | | |
| 1358 | .inferred_alloc_const => unreachable, | | |
| 1359 | .inferred_alloc_mut => unreachable, | | |
| 1360 | | 1269 | |
| 1361 | .empty_struct_literal => try writer.writeAll("@TypeOf(.{})"), | 1270 | .none => switch (ty.tag()) { |
| | 1271 | .inferred_alloc_const => unreachable, |
| | 1272 | .inferred_alloc_mut => unreachable, |
| 1362 | | 1273 | |
| 1363 | .empty_struct => { | 1274 | .empty_struct => { |
| 1364 | const namespace = ty.castTag(.empty_struct).?.data; | 1275 | const namespace = ty.castTag(.empty_struct).?.data; |
| 1365 | try namespace.renderFullyQualifiedName(mod, "", writer); | 1276 | try namespace.renderFullyQualifiedName(mod, "", writer); |
| 1366 | }, | 1277 | }, |
| 1367 | | 1278 | |
| 1368 | .@"struct" => { | 1279 | .@"struct" => { |
| 1369 | const struct_obj = ty.castTag(.@"struct").?.data; | 1280 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 1370 | const decl = mod.declPtr(struct_obj.owner_decl); | 1281 | const decl = mod.declPtr(struct_obj.owner_decl); |
| 1371 | try decl.renderFullyQualifiedName(mod, writer); | 1282 | try decl.renderFullyQualifiedName(mod, writer); |
| 1372 | }, | 1283 | }, |
| 1373 | .@"union", .union_safety_tagged, .union_tagged => { | 1284 | .@"union", .union_safety_tagged, .union_tagged => { |
| 1374 | const union_obj = ty.cast(Payload.Union).?.data; | 1285 | const union_obj = ty.cast(Payload.Union).?.data; |
| 1375 | const decl = mod.declPtr(union_obj.owner_decl); | 1286 | const decl = mod.declPtr(union_obj.owner_decl); |
| 1376 | try decl.renderFullyQualifiedName(mod, writer); | 1287 | try decl.renderFullyQualifiedName(mod, writer); |
| 1377 | }, | 1288 | }, |
| 1378 | .enum_full, .enum_nonexhaustive => { | 1289 | .enum_full, .enum_nonexhaustive => { |
| 1379 | const enum_full = ty.cast(Payload.EnumFull).?.data; | 1290 | const enum_full = ty.cast(Payload.EnumFull).?.data; |
| 1380 | const decl = mod.declPtr(enum_full.owner_decl); | 1291 | const decl = mod.declPtr(enum_full.owner_decl); |
| 1381 | try decl.renderFullyQualifiedName(mod, writer); | 1292 | try decl.renderFullyQualifiedName(mod, writer); |
| 1382 | }, | 1293 | }, |
| 1383 | .enum_simple => { | 1294 | .enum_simple => { |
| 1384 | const enum_simple = ty.castTag(.enum_simple).?.data; | 1295 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| 1385 | const decl = mod.declPtr(enum_simple.owner_decl); | 1296 | const decl = mod.declPtr(enum_simple.owner_decl); |
| 1386 | try decl.renderFullyQualifiedName(mod, writer); | 1297 | try decl.renderFullyQualifiedName(mod, writer); |
| 1387 | }, | 1298 | }, |
| 1388 | .enum_numbered => { | 1299 | .enum_numbered => { |
| 1389 | const enum_numbered = ty.castTag(.enum_numbered).?.data; | 1300 | const enum_numbered = ty.castTag(.enum_numbered).?.data; |
| 1390 | const decl = mod.declPtr(enum_numbered.owner_decl); | 1301 | const decl = mod.declPtr(enum_numbered.owner_decl); |
| 1391 | try decl.renderFullyQualifiedName(mod, writer); | 1302 | try decl.renderFullyQualifiedName(mod, writer); |
| 1392 | }, | 1303 | }, |
| 1393 | .@"opaque" => { | 1304 | .@"opaque" => { |
| 1394 | const opaque_obj = ty.cast(Payload.Opaque).?.data; | 1305 | const opaque_obj = ty.cast(Payload.Opaque).?.data; |
| 1395 | const decl = mod.declPtr(opaque_obj.owner_decl); | 1306 | const decl = mod.declPtr(opaque_obj.owner_decl); |
| 1396 | try decl.renderFullyQualifiedName(mod, writer); | 1307 | try decl.renderFullyQualifiedName(mod, writer); |
| 1397 | }, | 1308 | }, |
| 1398 | | 1309 | |
| 1399 | .error_set_inferred => { | 1310 | .error_set_inferred => { |
| 1400 | const func = ty.castTag(.error_set_inferred).?.data.func; | 1311 | const func = ty.castTag(.error_set_inferred).?.data.func; |
| 1401 | | 1312 | |
| 1402 | try writer.writeAll("@typeInfo(@typeInfo(@TypeOf("); | 1313 | try writer.writeAll("@typeInfo(@typeInfo(@TypeOf("); |
| 1403 | const owner_decl = mod.declPtr(func.owner_decl); | 1314 | const owner_decl = mod.declPtr(func.owner_decl); |
| 1404 | try owner_decl.renderFullyQualifiedName(mod, writer); | 1315 | try owner_decl.renderFullyQualifiedName(mod, writer); |
| 1405 | try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set"); | 1316 | try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set"); |
| 1406 | }, | 1317 | }, |
| 1407 | | 1318 | |
| 1408 | .function => { | 1319 | .function => { |
| 1409 | const fn_info = ty.fnInfo(); | 1320 | const fn_info = ty.fnInfo(); |
| 1410 | if (fn_info.is_noinline) { | 1321 | if (fn_info.is_noinline) { |
| 1411 | try writer.writeAll("noinline "); | 1322 | try writer.writeAll("noinline "); |
| 1412 | } | | |
| 1413 | try writer.writeAll("fn("); | | |
| 1414 | for (fn_info.param_types, 0..) |param_ty, i| { | | |
| 1415 | if (i != 0) try writer.writeAll(", "); | | |
| 1416 | if (fn_info.paramIsComptime(i)) { | | |
| 1417 | try writer.writeAll("comptime "); | | |
| 1418 | } | 1323 | } |
| 1419 | if (std.math.cast(u5, i)) |index| if (@truncate(u1, fn_info.noalias_bits >> index) != 0) { | 1324 | try writer.writeAll("fn("); |
| 1420 | try writer.writeAll("noalias "); | 1325 | for (fn_info.param_types, 0..) |param_ty, i| { |
| 1421 | }; | 1326 | if (i != 0) try writer.writeAll(", "); |
| 1422 | if (param_ty.isGenericPoison()) { | 1327 | if (fn_info.paramIsComptime(i)) { |
| 1423 | try writer.writeAll("anytype"); | 1328 | try writer.writeAll("comptime "); |
| 1424 | } else { | 1329 | } |
| 1425 | try print(param_ty, writer, mod); | 1330 | if (std.math.cast(u5, i)) |index| if (@truncate(u1, fn_info.noalias_bits >> index) != 0) { |
| | 1331 | try writer.writeAll("noalias "); |
| | 1332 | }; |
| | 1333 | if (param_ty.isGenericPoison()) { |
| | 1334 | try writer.writeAll("anytype"); |
| | 1335 | } else { |
| | 1336 | try print(param_ty, writer, mod); |
| | 1337 | } |
| 1426 | } | 1338 | } |
| 1427 | } | 1339 | if (fn_info.is_var_args) { |
| 1428 | if (fn_info.is_var_args) { | 1340 | if (fn_info.param_types.len != 0) { |
| 1429 | if (fn_info.param_types.len != 0) { | 1341 | try writer.writeAll(", "); |
| 1430 | try writer.writeAll(", "); | 1342 | } |
| | 1343 | try writer.writeAll("..."); |
| 1431 | } | 1344 | } |
| 1432 | try writer.writeAll("..."); | | |
| 1433 | } | | |
| 1434 | try writer.writeAll(") "); | | |
| 1435 | if (fn_info.alignment != 0) { | | |
| 1436 | try writer.print("align({d}) ", .{fn_info.alignment}); | | |
| 1437 | } | | |
| 1438 | if (fn_info.cc != .Unspecified) { | | |
| 1439 | try writer.writeAll("callconv(."); | | |
| 1440 | try writer.writeAll(@tagName(fn_info.cc)); | | |
| 1441 | try writer.writeAll(") "); | 1345 | try writer.writeAll(") "); |
| 1442 | } | 1346 | if (fn_info.alignment != 0) { |
| 1443 | if (fn_info.return_type.isGenericPoison()) { | 1347 | try writer.print("align({d}) ", .{fn_info.alignment}); |
| 1444 | try writer.writeAll("anytype"); | 1348 | } |
| 1445 | } else { | 1349 | if (fn_info.cc != .Unspecified) { |
| 1446 | try print(fn_info.return_type, writer, mod); | 1350 | try writer.writeAll("callconv(."); |
| 1447 | } | 1351 | try writer.writeAll(@tagName(fn_info.cc)); |
| 1448 | }, | 1352 | try writer.writeAll(") "); |
| | 1353 | } |
| | 1354 | if (fn_info.return_type.isGenericPoison()) { |
| | 1355 | try writer.writeAll("anytype"); |
| | 1356 | } else { |
| | 1357 | try print(fn_info.return_type, writer, mod); |
| | 1358 | } |
| | 1359 | }, |
| 1449 | | 1360 | |
| 1450 | .error_union => { | 1361 | .error_union => { |
| 1451 | const error_union = ty.castTag(.error_union).?.data; | 1362 | const error_union = ty.castTag(.error_union).?.data; |
| 1452 | try print(error_union.error_set, writer, mod); | 1363 | try print(error_union.error_set, writer, mod); |
| 1453 | try writer.writeAll("!"); | 1364 | try writer.writeAll("!"); |
| 1454 | try print(error_union.payload, writer, mod); | 1365 | try print(error_union.payload, writer, mod); |
| 1455 | }, | 1366 | }, |
| 1456 | | 1367 | |
| 1457 | .array => { | 1368 | .array => { |
| 1458 | const payload = ty.castTag(.array).?.data; | 1369 | const payload = ty.castTag(.array).?.data; |
| 1459 | try writer.print("[{d}]", .{payload.len}); | 1370 | try writer.print("[{d}]", .{payload.len}); |
| 1460 | try print(payload.elem_type, writer, mod); | 1371 | try print(payload.elem_type, writer, mod); |
| 1461 | }, | 1372 | }, |
| 1462 | .array_sentinel => { | 1373 | .array_sentinel => { |
| 1463 | const payload = ty.castTag(.array_sentinel).?.data; | 1374 | const payload = ty.castTag(.array_sentinel).?.data; |
| 1464 | try writer.print("[{d}:{}]", .{ | 1375 | try writer.print("[{d}:{}]", .{ |
| 1465 | payload.len, | 1376 | payload.len, |
| 1466 | payload.sentinel.fmtValue(payload.elem_type, mod), | 1377 | payload.sentinel.fmtValue(payload.elem_type, mod), |
| 1467 | }); | 1378 | }); |
| 1468 | try print(payload.elem_type, writer, mod); | 1379 | try print(payload.elem_type, writer, mod); |
| 1469 | }, | 1380 | }, |
| 1470 | .tuple => { | 1381 | .tuple => { |
| 1471 | const tuple = ty.castTag(.tuple).?.data; | 1382 | const tuple = ty.castTag(.tuple).?.data; |
| 1472 | | 1383 | |
| 1473 | try writer.writeAll("tuple{"); | 1384 | try writer.writeAll("tuple{"); |
| 1474 | for (tuple.types, 0..) |field_ty, i| { | 1385 | for (tuple.types, 0..) |field_ty, i| { |
| 1475 | if (i != 0) try writer.writeAll(", "); | 1386 | if (i != 0) try writer.writeAll(", "); |
| 1476 | const val = tuple.values[i]; | 1387 | const val = tuple.values[i]; |
| 1477 | if (val.ip_index != .unreachable_value) { | 1388 | if (val.ip_index != .unreachable_value) { |
| 1478 | try writer.writeAll("comptime "); | 1389 | try writer.writeAll("comptime "); |
| 1479 | } | 1390 | } |
| 1480 | try print(field_ty, writer, mod); | 1391 | try print(field_ty, writer, mod); |
| 1481 | if (val.ip_index != .unreachable_value) { | 1392 | if (val.ip_index != .unreachable_value) { |
| 1482 | try writer.print(" = {}", .{val.fmtValue(field_ty, mod)}); | 1393 | try writer.print(" = {}", .{val.fmtValue(field_ty, mod)}); |
| | 1394 | } |
| 1483 | } | 1395 | } |
| 1484 | } | 1396 | try writer.writeAll("}"); |
| 1485 | try writer.writeAll("}"); | 1397 | }, |
| 1486 | }, | 1398 | .anon_struct => { |
| 1487 | .anon_struct => { | 1399 | const anon_struct = ty.castTag(.anon_struct).?.data; |
| 1488 | const anon_struct = ty.castTag(.anon_struct).?.data; | | |
| 1489 | | 1400 | |
| 1490 | try writer.writeAll("struct{"); | 1401 | try writer.writeAll("struct{"); |
| 1491 | for (anon_struct.types, 0..) |field_ty, i| { | 1402 | for (anon_struct.types, 0..) |field_ty, i| { |
| 1492 | if (i != 0) try writer.writeAll(", "); | 1403 | if (i != 0) try writer.writeAll(", "); |
| 1493 | const val = anon_struct.values[i]; | 1404 | const val = anon_struct.values[i]; |
| 1494 | if (val.ip_index != .unreachable_value) { | 1405 | if (val.ip_index != .unreachable_value) { |
| 1495 | try writer.writeAll("comptime "); | 1406 | try writer.writeAll("comptime "); |
| 1496 | } | 1407 | } |
| 1497 | try writer.writeAll(anon_struct.names[i]); | 1408 | try writer.writeAll(anon_struct.names[i]); |
| 1498 | try writer.writeAll(": "); | 1409 | try writer.writeAll(": "); |
| 1499 | | 1410 | |
| 1500 | try print(field_ty, writer, mod); | 1411 | try print(field_ty, writer, mod); |
| 1501 | | 1412 | |
| 1502 | if (val.ip_index != .unreachable_value) { | 1413 | if (val.ip_index != .unreachable_value) { |
| 1503 | try writer.print(" = {}", .{val.fmtValue(field_ty, mod)}); | 1414 | try writer.print(" = {}", .{val.fmtValue(field_ty, mod)}); |
| | 1415 | } |
| 1504 | } | 1416 | } |
| 1505 | } | 1417 | try writer.writeAll("}"); |
| 1506 | try writer.writeAll("}"); | 1418 | }, |
| 1507 | }, | | |
| 1508 | | 1419 | |
| 1509 | .pointer => { | 1420 | .pointer => { |
| 1510 | const info = ty.ptrInfo(mod); | 1421 | const info = ty.ptrInfo(mod); |
| 1511 | | 1422 | |
| 1512 | if (info.sentinel) |s| switch (info.size) { | 1423 | if (info.sentinel) |s| switch (info.size) { |
| 1513 | .One, .C => unreachable, | 1424 | .One, .C => unreachable, |
| 1514 | .Many => try writer.print("[*:{}]", .{s.fmtValue(info.pointee_type, mod)}), | 1425 | .Many => try writer.print("[*:{}]", .{s.fmtValue(info.pointee_type, mod)}), |
| 1515 | .Slice => try writer.print("[:{}]", .{s.fmtValue(info.pointee_type, mod)}), | 1426 | .Slice => try writer.print("[:{}]", .{s.fmtValue(info.pointee_type, mod)}), |
| 1516 | } else switch (info.size) { | 1427 | } else switch (info.size) { |
| 1517 | .One => try writer.writeAll("*"), | 1428 | .One => try writer.writeAll("*"), |
| 1518 | .Many => try writer.writeAll("[*]"), | 1429 | .Many => try writer.writeAll("[*]"), |
| 1519 | .C => try writer.writeAll("[*c]"), | 1430 | .C => try writer.writeAll("[*c]"), |
| 1520 | .Slice => try writer.writeAll("[]"), | 1431 | .Slice => try writer.writeAll("[]"), |
| 1521 | } | | |
| 1522 | if (info.@"align" != 0 or info.host_size != 0 or info.vector_index != .none) { | | |
| 1523 | if (info.@"align" != 0) { | | |
| 1524 | try writer.print("align({d}", .{info.@"align"}); | | |
| 1525 | } else { | | |
| 1526 | const alignment = info.pointee_type.abiAlignment(mod); | | |
| 1527 | try writer.print("align({d}", .{alignment}); | | |
| 1528 | } | 1432 | } |
| | 1433 | if (info.@"align" != 0 or info.host_size != 0 or info.vector_index != .none) { |
| | 1434 | if (info.@"align" != 0) { |
| | 1435 | try writer.print("align({d}", .{info.@"align"}); |
| | 1436 | } else { |
| | 1437 | const alignment = info.pointee_type.abiAlignment(mod); |
| | 1438 | try writer.print("align({d}", .{alignment}); |
| | 1439 | } |
| 1529 | | 1440 | |
| 1530 | if (info.bit_offset != 0 or info.host_size != 0) { | 1441 | if (info.bit_offset != 0 or info.host_size != 0) { |
| 1531 | try writer.print(":{d}:{d}", .{ info.bit_offset, info.host_size }); | 1442 | try writer.print(":{d}:{d}", .{ info.bit_offset, info.host_size }); |
| | 1443 | } |
| | 1444 | if (info.vector_index == .runtime) { |
| | 1445 | try writer.writeAll(":?"); |
| | 1446 | } else if (info.vector_index != .none) { |
| | 1447 | try writer.print(":{d}", .{@enumToInt(info.vector_index)}); |
| | 1448 | } |
| | 1449 | try writer.writeAll(") "); |
| 1532 | } | 1450 | } |
| 1533 | if (info.vector_index == .runtime) { | 1451 | if (info.@"addrspace" != .generic) { |
| 1534 | try writer.writeAll(":?"); | 1452 | try writer.print("addrspace(.{s}) ", .{@tagName(info.@"addrspace")}); |
| 1535 | } else if (info.vector_index != .none) { | | |
| 1536 | try writer.print(":{d}", .{@enumToInt(info.vector_index)}); | | |
| 1537 | } | 1453 | } |
| 1538 | try writer.writeAll(") "); | 1454 | if (!info.mutable) try writer.writeAll("const "); |
| 1539 | } | 1455 | if (info.@"volatile") try writer.writeAll("volatile "); |
| 1540 | if (info.@"addrspace" != .generic) { | 1456 | if (info.@"allowzero" and info.size != .C) try writer.writeAll("allowzero "); |
| 1541 | try writer.print("addrspace(.{s}) ", .{@tagName(info.@"addrspace")}); | | |
| 1542 | } | | |
| 1543 | if (!info.mutable) try writer.writeAll("const "); | | |
| 1544 | if (info.@"volatile") try writer.writeAll("volatile "); | | |
| 1545 | if (info.@"allowzero" and info.size != .C) try writer.writeAll("allowzero "); | | |
| 1546 | | | |
| 1547 | try print(info.pointee_type, writer, mod); | | |
| 1548 | }, | | |
| 1549 | | 1457 | |
| 1550 | .optional => { | 1458 | try print(info.pointee_type, writer, mod); |
| 1551 | const child_type = ty.castTag(.optional).?.data; | 1459 | }, |
| 1552 | try writer.writeByte('?'); | | |
| 1553 | try print(child_type, writer, mod); | | |
| 1554 | }, | | |
| 1555 | .anyframe_T => { | | |
| 1556 | const return_type = ty.castTag(.anyframe_T).?.data; | | |
| 1557 | try writer.print("anyframe->", .{}); | | |
| 1558 | try print(return_type, writer, mod); | | |
| 1559 | }, | | |
| 1560 | .error_set => { | | |
| 1561 | const names = ty.castTag(.error_set).?.data.names.keys(); | | |
| 1562 | try writer.writeAll("error{"); | | |
| 1563 | for (names, 0..) |name, i| { | | |
| 1564 | if (i != 0) try writer.writeByte(','); | | |
| 1565 | try writer.writeAll(name); | | |
| 1566 | } | | |
| 1567 | try writer.writeAll("}"); | | |
| 1568 | }, | | |
| 1569 | .error_set_single => { | | |
| 1570 | const name = ty.castTag(.error_set_single).?.data; | | |
| 1571 | return writer.print("error{{{s}}}", .{name}); | | |
| 1572 | }, | | |
| 1573 | .error_set_merged => { | | |
| 1574 | const names = ty.castTag(.error_set_merged).?.data.keys(); | | |
| 1575 | try writer.writeAll("error{"); | | |
| 1576 | for (names, 0..) |name, i| { | | |
| 1577 | if (i != 0) try writer.writeByte(','); | | |
| 1578 | try writer.writeAll(name); | | |
| 1579 | } | | |
| 1580 | try writer.writeAll("}"); | | |
| 1581 | }, | | |
| 1582 | } | | |
| 1583 | } | | |
| 1584 | | 1460 | |
| 1585 | pub fn toValue(self: Type, allocator: Allocator) Allocator.Error!Value { | 1461 | .optional => { |
| 1586 | if (self.ip_index != .none) return self.ip_index.toValue(); | 1462 | const child_type = ty.castTag(.optional).?.data; |
| 1587 | switch (self.tag()) { | 1463 | try writer.writeByte('?'); |
| 1588 | .inferred_alloc_const => unreachable, | 1464 | try print(child_type, writer, mod); |
| 1589 | .inferred_alloc_mut => unreachable, | 1465 | }, |
| | 1466 | .anyframe_T => { |
| | 1467 | const return_type = ty.castTag(.anyframe_T).?.data; |
| | 1468 | try writer.print("anyframe->", .{}); |
| | 1469 | try print(return_type, writer, mod); |
| | 1470 | }, |
| | 1471 | .error_set => { |
| | 1472 | const names = ty.castTag(.error_set).?.data.names.keys(); |
| | 1473 | try writer.writeAll("error{"); |
| | 1474 | for (names, 0..) |name, i| { |
| | 1475 | if (i != 0) try writer.writeByte(','); |
| | 1476 | try writer.writeAll(name); |
| | 1477 | } |
| | 1478 | try writer.writeAll("}"); |
| | 1479 | }, |
| | 1480 | .error_set_single => { |
| | 1481 | const name = ty.castTag(.error_set_single).?.data; |
| | 1482 | return writer.print("error{{{s}}}", .{name}); |
| | 1483 | }, |
| | 1484 | .error_set_merged => { |
| | 1485 | const names = ty.castTag(.error_set_merged).?.data.keys(); |
| | 1486 | try writer.writeAll("error{"); |
| | 1487 | for (names, 0..) |name, i| { |
| | 1488 | if (i != 0) try writer.writeByte(','); |
| | 1489 | try writer.writeAll(name); |
| | 1490 | } |
| | 1491 | try writer.writeAll("}"); |
| | 1492 | }, |
| | 1493 | }, |
| | 1494 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| | 1495 | .int_type => |int_type| { |
| | 1496 | const sign_char: u8 = switch (int_type.signedness) { |
| | 1497 | .signed => 'i', |
| | 1498 | .unsigned => 'u', |
| | 1499 | }; |
| | 1500 | return writer.print("{c}{d}", .{ sign_char, int_type.bits }); |
| | 1501 | }, |
| | 1502 | .ptr_type => { |
| | 1503 | const info = ty.ptrInfo(mod); |
| | 1504 | |
| | 1505 | if (info.sentinel) |s| switch (info.size) { |
| | 1506 | .One, .C => unreachable, |
| | 1507 | .Many => try writer.print("[*:{}]", .{s.fmtValue(info.pointee_type, mod)}), |
| | 1508 | .Slice => try writer.print("[:{}]", .{s.fmtValue(info.pointee_type, mod)}), |
| | 1509 | } else switch (info.size) { |
| | 1510 | .One => try writer.writeAll("*"), |
| | 1511 | .Many => try writer.writeAll("[*]"), |
| | 1512 | .C => try writer.writeAll("[*c]"), |
| | 1513 | .Slice => try writer.writeAll("[]"), |
| | 1514 | } |
| | 1515 | if (info.@"align" != 0 or info.host_size != 0 or info.vector_index != .none) { |
| | 1516 | if (info.@"align" != 0) { |
| | 1517 | try writer.print("align({d}", .{info.@"align"}); |
| | 1518 | } else { |
| | 1519 | const alignment = info.pointee_type.abiAlignment(mod); |
| | 1520 | try writer.print("align({d}", .{alignment}); |
| | 1521 | } |
| | 1522 | |
| | 1523 | if (info.bit_offset != 0 or info.host_size != 0) { |
| | 1524 | try writer.print(":{d}:{d}", .{ info.bit_offset, info.host_size }); |
| | 1525 | } |
| | 1526 | if (info.vector_index == .runtime) { |
| | 1527 | try writer.writeAll(":?"); |
| | 1528 | } else if (info.vector_index != .none) { |
| | 1529 | try writer.print(":{d}", .{@enumToInt(info.vector_index)}); |
| | 1530 | } |
| | 1531 | try writer.writeAll(") "); |
| | 1532 | } |
| | 1533 | if (info.@"addrspace" != .generic) { |
| | 1534 | try writer.print("addrspace(.{s}) ", .{@tagName(info.@"addrspace")}); |
| | 1535 | } |
| | 1536 | if (!info.mutable) try writer.writeAll("const "); |
| | 1537 | if (info.@"volatile") try writer.writeAll("volatile "); |
| | 1538 | if (info.@"allowzero" and info.size != .C) try writer.writeAll("allowzero "); |
| | 1539 | |
| | 1540 | try print(info.pointee_type, writer, mod); |
| | 1541 | return; |
| | 1542 | }, |
| | 1543 | .array_type => |array_type| { |
| | 1544 | if (array_type.sentinel == .none) { |
| | 1545 | try writer.print("[{d}]", .{array_type.len}); |
| | 1546 | try print(array_type.child.toType(), writer, mod); |
| | 1547 | } else { |
| | 1548 | try writer.print("[{d}:{}]", .{ |
| | 1549 | array_type.len, |
| | 1550 | array_type.sentinel.toValue().fmtValue(array_type.child.toType(), mod), |
| | 1551 | }); |
| | 1552 | try print(array_type.child.toType(), writer, mod); |
| | 1553 | } |
| | 1554 | return; |
| | 1555 | }, |
| | 1556 | .vector_type => |vector_type| { |
| | 1557 | try writer.print("@Vector({d}, ", .{vector_type.len}); |
| | 1558 | try print(vector_type.child.toType(), writer, mod); |
| | 1559 | try writer.writeAll(")"); |
| | 1560 | return; |
| | 1561 | }, |
| | 1562 | .opt_type => |child| { |
| | 1563 | try writer.writeByte('?'); |
| | 1564 | try print(child.toType(), writer, mod); |
| | 1565 | return; |
| | 1566 | }, |
| | 1567 | .error_union_type => |error_union_type| { |
| | 1568 | try print(error_union_type.error_set_type.toType(), writer, mod); |
| | 1569 | try writer.writeByte('!'); |
| | 1570 | try print(error_union_type.payload_type.toType(), writer, mod); |
| | 1571 | return; |
| | 1572 | }, |
| | 1573 | .simple_type => |s| return writer.writeAll(@tagName(s)), |
| | 1574 | .struct_type => @panic("TODO"), |
| | 1575 | .union_type => @panic("TODO"), |
| | 1576 | .simple_value => unreachable, |
| | 1577 | .extern_func => unreachable, |
| | 1578 | .int => unreachable, |
| | 1579 | .enum_tag => unreachable, |
| | 1580 | }, |
| | 1581 | } |
| | 1582 | } |
| | 1583 | |
| | 1584 | pub fn toValue(self: Type, allocator: Allocator) Allocator.Error!Value { |
| | 1585 | if (self.ip_index != .none) return self.ip_index.toValue(); |
| | 1586 | switch (self.tag()) { |
| | 1587 | .inferred_alloc_const => unreachable, |
| | 1588 | .inferred_alloc_mut => unreachable, |
| 1590 | else => return Value.Tag.ty.create(allocator, self), | 1589 | else => return Value.Tag.ty.create(allocator, self), |
| 1591 | } | 1590 | } |
| 1592 | } | 1591 | } |
| ... | @@ -1610,240 +1609,244 @@ pub const Type = struct { | ... | @@ -1610,240 +1609,244 @@ pub const Type = struct { |
| 1610 | ignore_comptime_only: bool, | 1609 | ignore_comptime_only: bool, |
| 1611 | strat: AbiAlignmentAdvancedStrat, | 1610 | strat: AbiAlignmentAdvancedStrat, |
| 1612 | ) RuntimeBitsError!bool { | 1611 | ) RuntimeBitsError!bool { |
| 1613 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { | 1612 | switch (ty.ip_index) { |
| 1614 | .int_type => |int_type| return int_type.bits != 0, | 1613 | // False because it is a comptime-only type. |
| 1615 | .ptr_type => |ptr_type| { | 1614 | .empty_struct_type => return false, |
| | 1615 | |
| | 1616 | .none => switch (ty.tag()) { |
| | 1617 | .error_set_inferred, |
| | 1618 | |
| | 1619 | .@"opaque", |
| | 1620 | .error_set_single, |
| | 1621 | .error_union, |
| | 1622 | .error_set, |
| | 1623 | .error_set_merged, |
| | 1624 | => return true, |
| | 1625 | |
| 1616 | // Pointers to zero-bit types still have a runtime address; however, pointers | 1626 | // Pointers to zero-bit types still have a runtime address; however, pointers |
| 1617 | // to comptime-only types do not, with the exception of function pointers. | 1627 | // to comptime-only types do not, with the exception of function pointers. |
| 1618 | if (ignore_comptime_only) return true; | 1628 | .anyframe_T, |
| 1619 | const child_ty = ptr_type.elem_type.toType(); | 1629 | .pointer, |
| 1620 | if (child_ty.zigTypeTag(mod) == .Fn) return !child_ty.fnInfo().is_generic; | 1630 | => { |
| 1621 | if (strat == .sema) return !(try strat.sema.typeRequiresComptime(ty)); | 1631 | if (ignore_comptime_only) { |
| 1622 | return !comptimeOnly(ty, mod); | 1632 | return true; |
| 1623 | }, | 1633 | } else if (ty.childType(mod).zigTypeTag(mod) == .Fn) { |
| 1624 | .array_type => |array_type| { | 1634 | return !ty.childType(mod).fnInfo().is_generic; |
| 1625 | if (array_type.sentinel != .none) { | 1635 | } else if (strat == .sema) { |
| 1626 | return array_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); | 1636 | return !(try strat.sema.typeRequiresComptime(ty)); |
| 1627 | } else { | 1637 | } else { |
| 1628 | return array_type.len > 0 and | 1638 | return !comptimeOnly(ty, mod); |
| 1629 | try array_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); | 1639 | } |
| 1630 | } | 1640 | }, |
| 1631 | }, | | |
| 1632 | .vector_type => |vector_type| { | | |
| 1633 | return vector_type.len > 0 and | | |
| 1634 | try vector_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); | | |
| 1635 | }, | | |
| 1636 | .opt_type => |child| { | | |
| 1637 | const child_ty = child.toType(); | | |
| 1638 | if (child_ty.isNoReturn()) { | | |
| 1639 | // Then the optional is comptime-known to be null. | | |
| 1640 | return false; | | |
| 1641 | } | | |
| 1642 | if (ignore_comptime_only) { | | |
| 1643 | return true; | | |
| 1644 | } else if (strat == .sema) { | | |
| 1645 | return !(try strat.sema.typeRequiresComptime(child_ty)); | | |
| 1646 | } else { | | |
| 1647 | return !comptimeOnly(child_ty, mod); | | |
| 1648 | } | | |
| 1649 | }, | | |
| 1650 | .error_union_type => @panic("TODO"), | | |
| 1651 | .simple_type => |t| return switch (t) { | | |
| 1652 | .f16, | | |
| 1653 | .f32, | | |
| 1654 | .f64, | | |
| 1655 | .f80, | | |
| 1656 | .f128, | | |
| 1657 | .usize, | | |
| 1658 | .isize, | | |
| 1659 | .c_char, | | |
| 1660 | .c_short, | | |
| 1661 | .c_ushort, | | |
| 1662 | .c_int, | | |
| 1663 | .c_uint, | | |
| 1664 | .c_long, | | |
| 1665 | .c_ulong, | | |
| 1666 | .c_longlong, | | |
| 1667 | .c_ulonglong, | | |
| 1668 | .c_longdouble, | | |
| 1669 | .bool, | | |
| 1670 | .anyerror, | | |
| 1671 | .@"anyframe", | | |
| 1672 | .anyopaque, | | |
| 1673 | .atomic_order, | | |
| 1674 | .atomic_rmw_op, | | |
| 1675 | .calling_convention, | | |
| 1676 | .address_space, | | |
| 1677 | .float_mode, | | |
| 1678 | .reduce_op, | | |
| 1679 | .call_modifier, | | |
| 1680 | .prefetch_options, | | |
| 1681 | .export_options, | | |
| 1682 | .extern_options, | | |
| 1683 | => true, | | |
| 1684 | | 1641 | |
| 1685 | // These are false because they are comptime-only types. | 1642 | // These are false because they are comptime-only types. |
| 1686 | .void, | 1643 | .empty_struct, |
| 1687 | .type, | 1644 | // These are function *bodies*, not pointers. |
| 1688 | .comptime_int, | 1645 | // Special exceptions have to be made when emitting functions due to |
| 1689 | .comptime_float, | 1646 | // this returning false. |
| 1690 | .noreturn, | 1647 | .function, |
| 1691 | .null, | 1648 | => return false, |
| 1692 | .undefined, | | |
| 1693 | .enum_literal, | | |
| 1694 | .type_info, | | |
| 1695 | => false, | | |
| 1696 | | 1649 | |
| 1697 | .generic_poison => unreachable, | 1650 | .optional => { |
| 1698 | .var_args_param => unreachable, | 1651 | const child_ty = ty.optionalChild(mod); |
| 1699 | }, | 1652 | if (child_ty.isNoReturn()) { |
| 1700 | .struct_type => @panic("TODO"), | 1653 | // Then the optional is comptime-known to be null. |
| 1701 | .union_type => @panic("TODO"), | 1654 | return false; |
| 1702 | .simple_value => unreachable, | 1655 | } |
| 1703 | .extern_func => unreachable, | 1656 | if (ignore_comptime_only) { |
| 1704 | .int => unreachable, | 1657 | return true; |
| 1705 | .enum_tag => unreachable, // it's a value, not a type | 1658 | } else if (strat == .sema) { |
| 1706 | }; | 1659 | return !(try strat.sema.typeRequiresComptime(child_ty)); |
| 1707 | switch (ty.tag()) { | 1660 | } else { |
| 1708 | .error_set_inferred, | 1661 | return !comptimeOnly(child_ty, mod); |
| 1709 | | 1662 | } |
| 1710 | .@"opaque", | 1663 | }, |
| 1711 | .error_set_single, | | |
| 1712 | .error_union, | | |
| 1713 | .error_set, | | |
| 1714 | .error_set_merged, | | |
| 1715 | => return true, | | |
| 1716 | | | |
| 1717 | // Pointers to zero-bit types still have a runtime address; however, pointers | | |
| 1718 | // to comptime-only types do not, with the exception of function pointers. | | |
| 1719 | .anyframe_T, | | |
| 1720 | .pointer, | | |
| 1721 | => { | | |
| 1722 | if (ignore_comptime_only) { | | |
| 1723 | return true; | | |
| 1724 | } else if (ty.childType(mod).zigTypeTag(mod) == .Fn) { | | |
| 1725 | return !ty.childType(mod).fnInfo().is_generic; | | |
| 1726 | } else if (strat == .sema) { | | |
| 1727 | return !(try strat.sema.typeRequiresComptime(ty)); | | |
| 1728 | } else { | | |
| 1729 | return !comptimeOnly(ty, mod); | | |
| 1730 | } | | |
| 1731 | }, | | |
| 1732 | | 1664 | |
| 1733 | // These are false because they are comptime-only types. | 1665 | .@"struct" => { |
| 1734 | .empty_struct, | 1666 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 1735 | .empty_struct_literal, | 1667 | if (struct_obj.status == .field_types_wip) { |
| 1736 | // These are function *bodies*, not pointers. | 1668 | // In this case, we guess that hasRuntimeBits() for this type is true, |
| 1737 | // Special exceptions have to be made when emitting functions due to | 1669 | // and then later if our guess was incorrect, we emit a compile error. |
| 1738 | // this returning false. | 1670 | struct_obj.assumed_runtime_bits = true; |
| 1739 | .function, | 1671 | return true; |
| 1740 | => return false, | 1672 | } |
| | 1673 | switch (strat) { |
| | 1674 | .sema => |sema| _ = try sema.resolveTypeFields(ty), |
| | 1675 | .eager => assert(struct_obj.haveFieldTypes()), |
| | 1676 | .lazy => if (!struct_obj.haveFieldTypes()) return error.NeedLazy, |
| | 1677 | } |
| | 1678 | for (struct_obj.fields.values()) |field| { |
| | 1679 | if (field.is_comptime) continue; |
| | 1680 | if (try field.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) |
| | 1681 | return true; |
| | 1682 | } else { |
| | 1683 | return false; |
| | 1684 | } |
| | 1685 | }, |
| 1741 | | 1686 | |
| 1742 | .optional => { | 1687 | .enum_full => { |
| 1743 | const child_ty = ty.optionalChild(mod); | 1688 | const enum_full = ty.castTag(.enum_full).?.data; |
| 1744 | if (child_ty.isNoReturn()) { | 1689 | return enum_full.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); |
| 1745 | // Then the optional is comptime-known to be null. | 1690 | }, |
| 1746 | return false; | 1691 | .enum_simple => { |
| 1747 | } | 1692 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| 1748 | if (ignore_comptime_only) { | 1693 | return enum_simple.fields.count() >= 2; |
| 1749 | return true; | 1694 | }, |
| 1750 | } else if (strat == .sema) { | 1695 | .enum_numbered, .enum_nonexhaustive => { |
| 1751 | return !(try strat.sema.typeRequiresComptime(child_ty)); | 1696 | const int_tag_ty = try ty.intTagType(mod); |
| 1752 | } else { | 1697 | return int_tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); |
| 1753 | return !comptimeOnly(child_ty, mod); | 1698 | }, |
| 1754 | } | | |
| 1755 | }, | | |
| 1756 | | 1699 | |
| 1757 | .@"struct" => { | 1700 | .@"union" => { |
| 1758 | const struct_obj = ty.castTag(.@"struct").?.data; | 1701 | const union_obj = ty.castTag(.@"union").?.data; |
| 1759 | if (struct_obj.status == .field_types_wip) { | 1702 | if (union_obj.status == .field_types_wip) { |
| 1760 | // In this case, we guess that hasRuntimeBits() for this type is true, | 1703 | // In this case, we guess that hasRuntimeBits() for this type is true, |
| 1761 | // and then later if our guess was incorrect, we emit a compile error. | 1704 | // and then later if our guess was incorrect, we emit a compile error. |
| 1762 | struct_obj.assumed_runtime_bits = true; | 1705 | union_obj.assumed_runtime_bits = true; |
| 1763 | return true; | | |
| 1764 | } | | |
| 1765 | switch (strat) { | | |
| 1766 | .sema => |sema| _ = try sema.resolveTypeFields(ty), | | |
| 1767 | .eager => assert(struct_obj.haveFieldTypes()), | | |
| 1768 | .lazy => if (!struct_obj.haveFieldTypes()) return error.NeedLazy, | | |
| 1769 | } | | |
| 1770 | for (struct_obj.fields.values()) |field| { | | |
| 1771 | if (field.is_comptime) continue; | | |
| 1772 | if (try field.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) | | |
| 1773 | return true; | 1706 | return true; |
| 1774 | } else { | 1707 | } |
| 1775 | return false; | 1708 | switch (strat) { |
| 1776 | } | 1709 | .sema => |sema| _ = try sema.resolveTypeFields(ty), |
| 1777 | }, | 1710 | .eager => assert(union_obj.haveFieldTypes()), |
| | 1711 | .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy, |
| | 1712 | } |
| | 1713 | for (union_obj.fields.values()) |value| { |
| | 1714 | if (try value.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) |
| | 1715 | return true; |
| | 1716 | } else { |
| | 1717 | return false; |
| | 1718 | } |
| | 1719 | }, |
| | 1720 | .union_safety_tagged, .union_tagged => { |
| | 1721 | const union_obj = ty.cast(Payload.Union).?.data; |
| | 1722 | if (try union_obj.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) { |
| | 1723 | return true; |
| | 1724 | } |
| 1778 | | 1725 | |
| 1779 | .enum_full => { | 1726 | switch (strat) { |
| 1780 | const enum_full = ty.castTag(.enum_full).?.data; | 1727 | .sema => |sema| _ = try sema.resolveTypeFields(ty), |
| 1781 | return enum_full.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); | 1728 | .eager => assert(union_obj.haveFieldTypes()), |
| 1782 | }, | 1729 | .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy, |
| 1783 | .enum_simple => { | 1730 | } |
| 1784 | const enum_simple = ty.castTag(.enum_simple).?.data; | 1731 | for (union_obj.fields.values()) |value| { |
| 1785 | return enum_simple.fields.count() >= 2; | 1732 | if (try value.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) |
| 1786 | }, | 1733 | return true; |
| 1787 | .enum_numbered, .enum_nonexhaustive => { | 1734 | } else { |
| 1788 | const int_tag_ty = try ty.intTagType(mod); | 1735 | return false; |
| 1789 | return int_tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); | 1736 | } |
| 1790 | }, | 1737 | }, |
| 1791 | | 1738 | |
| 1792 | .@"union" => { | 1739 | .array => return ty.arrayLen(mod) != 0 and |
| 1793 | const union_obj = ty.castTag(.@"union").?.data; | 1740 | try ty.childType(mod).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat), |
| 1794 | if (union_obj.status == .field_types_wip) { | 1741 | .array_sentinel => return ty.childType(mod).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat), |
| 1795 | // In this case, we guess that hasRuntimeBits() for this type is true, | | |
| 1796 | // and then later if our guess was incorrect, we emit a compile error. | | |
| 1797 | union_obj.assumed_runtime_bits = true; | | |
| 1798 | return true; | | |
| 1799 | } | | |
| 1800 | switch (strat) { | | |
| 1801 | .sema => |sema| _ = try sema.resolveTypeFields(ty), | | |
| 1802 | .eager => assert(union_obj.haveFieldTypes()), | | |
| 1803 | .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy, | | |
| 1804 | } | | |
| 1805 | for (union_obj.fields.values()) |value| { | | |
| 1806 | if (try value.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) | | |
| 1807 | return true; | | |
| 1808 | } else { | | |
| 1809 | return false; | | |
| 1810 | } | | |
| 1811 | }, | | |
| 1812 | .union_safety_tagged, .union_tagged => { | | |
| 1813 | const union_obj = ty.cast(Payload.Union).?.data; | | |
| 1814 | if (try union_obj.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) { | | |
| 1815 | return true; | | |
| 1816 | } | | |
| 1817 | | 1742 | |
| 1818 | switch (strat) { | 1743 | .tuple, .anon_struct => { |
| 1819 | .sema => |sema| _ = try sema.resolveTypeFields(ty), | 1744 | const tuple = ty.tupleFields(); |
| 1820 | .eager => assert(union_obj.haveFieldTypes()), | 1745 | for (tuple.types, 0..) |field_ty, i| { |
| 1821 | .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy, | 1746 | const val = tuple.values[i]; |
| 1822 | } | 1747 | if (val.ip_index != .unreachable_value) continue; // comptime field |
| 1823 | for (union_obj.fields.values()) |value| { | 1748 | if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) return true; |
| 1824 | if (try value.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) | 1749 | } |
| 1825 | return true; | | |
| 1826 | } else { | | |
| 1827 | return false; | 1750 | return false; |
| 1828 | } | 1751 | }, |
| 1829 | }, | | |
| 1830 | | | |
| 1831 | .array => return ty.arrayLen(mod) != 0 and | | |
| 1832 | try ty.childType(mod).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat), | | |
| 1833 | .array_sentinel => return ty.childType(mod).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat), | | |
| 1834 | | 1752 | |
| 1835 | .tuple, .anon_struct => { | 1753 | .inferred_alloc_const => unreachable, |
| 1836 | const tuple = ty.tupleFields(); | 1754 | .inferred_alloc_mut => unreachable, |
| 1837 | for (tuple.types, 0..) |field_ty, i| { | 1755 | }, |
| 1838 | const val = tuple.values[i]; | 1756 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 1839 | if (val.ip_index != .unreachable_value) continue; // comptime field | 1757 | .int_type => |int_type| return int_type.bits != 0, |
| 1840 | if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) return true; | 1758 | .ptr_type => |ptr_type| { |
| 1841 | } | 1759 | // Pointers to zero-bit types still have a runtime address; however, pointers |
| 1842 | return false; | 1760 | // to comptime-only types do not, with the exception of function pointers. |
| | 1761 | if (ignore_comptime_only) return true; |
| | 1762 | const child_ty = ptr_type.elem_type.toType(); |
| | 1763 | if (child_ty.zigTypeTag(mod) == .Fn) return !child_ty.fnInfo().is_generic; |
| | 1764 | if (strat == .sema) return !(try strat.sema.typeRequiresComptime(ty)); |
| | 1765 | return !comptimeOnly(ty, mod); |
| | 1766 | }, |
| | 1767 | .array_type => |array_type| { |
| | 1768 | if (array_type.sentinel != .none) { |
| | 1769 | return array_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); |
| | 1770 | } else { |
| | 1771 | return array_type.len > 0 and |
| | 1772 | try array_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); |
| | 1773 | } |
| | 1774 | }, |
| | 1775 | .vector_type => |vector_type| { |
| | 1776 | return vector_type.len > 0 and |
| | 1777 | try vector_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); |
| | 1778 | }, |
| | 1779 | .opt_type => |child| { |
| | 1780 | const child_ty = child.toType(); |
| | 1781 | if (child_ty.isNoReturn()) { |
| | 1782 | // Then the optional is comptime-known to be null. |
| | 1783 | return false; |
| | 1784 | } |
| | 1785 | if (ignore_comptime_only) { |
| | 1786 | return true; |
| | 1787 | } else if (strat == .sema) { |
| | 1788 | return !(try strat.sema.typeRequiresComptime(child_ty)); |
| | 1789 | } else { |
| | 1790 | return !comptimeOnly(child_ty, mod); |
| | 1791 | } |
| | 1792 | }, |
| | 1793 | .error_union_type => @panic("TODO"), |
| | 1794 | .simple_type => |t| return switch (t) { |
| | 1795 | .f16, |
| | 1796 | .f32, |
| | 1797 | .f64, |
| | 1798 | .f80, |
| | 1799 | .f128, |
| | 1800 | .usize, |
| | 1801 | .isize, |
| | 1802 | .c_char, |
| | 1803 | .c_short, |
| | 1804 | .c_ushort, |
| | 1805 | .c_int, |
| | 1806 | .c_uint, |
| | 1807 | .c_long, |
| | 1808 | .c_ulong, |
| | 1809 | .c_longlong, |
| | 1810 | .c_ulonglong, |
| | 1811 | .c_longdouble, |
| | 1812 | .bool, |
| | 1813 | .anyerror, |
| | 1814 | .@"anyframe", |
| | 1815 | .anyopaque, |
| | 1816 | .atomic_order, |
| | 1817 | .atomic_rmw_op, |
| | 1818 | .calling_convention, |
| | 1819 | .address_space, |
| | 1820 | .float_mode, |
| | 1821 | .reduce_op, |
| | 1822 | .call_modifier, |
| | 1823 | .prefetch_options, |
| | 1824 | .export_options, |
| | 1825 | .extern_options, |
| | 1826 | => true, |
| | 1827 | |
| | 1828 | // These are false because they are comptime-only types. |
| | 1829 | .void, |
| | 1830 | .type, |
| | 1831 | .comptime_int, |
| | 1832 | .comptime_float, |
| | 1833 | .noreturn, |
| | 1834 | .null, |
| | 1835 | .undefined, |
| | 1836 | .enum_literal, |
| | 1837 | .type_info, |
| | 1838 | => false, |
| | 1839 | |
| | 1840 | .generic_poison => unreachable, |
| | 1841 | .var_args_param => unreachable, |
| | 1842 | }, |
| | 1843 | .struct_type => @panic("TODO"), |
| | 1844 | .union_type => @panic("TODO"), |
| | 1845 | .simple_value => unreachable, |
| | 1846 | .extern_func => unreachable, |
| | 1847 | .int => unreachable, |
| | 1848 | .enum_tag => unreachable, // it's a value, not a type |
| 1843 | }, | 1849 | }, |
| 1844 | | | |
| 1845 | .inferred_alloc_const => unreachable, | | |
| 1846 | .inferred_alloc_mut => unreachable, | | |
| 1847 | } | 1850 | } |
| 1848 | } | 1851 | } |
| 1849 | | 1852 | |
| ... | @@ -1851,104 +1854,107 @@ pub const Type = struct { | ... | @@ -1851,104 +1854,107 @@ pub const Type = struct { |
| 1851 | /// readFrom/writeToMemory are supported only for types with a well- | 1854 | /// readFrom/writeToMemory are supported only for types with a well- |
| 1852 | /// defined memory layout | 1855 | /// defined memory layout |
| 1853 | pub fn hasWellDefinedLayout(ty: Type, mod: *Module) bool { | 1856 | pub fn hasWellDefinedLayout(ty: Type, mod: *Module) bool { |
| 1854 | if (ty.ip_index != .none) return switch (mod.intern_pool.indexToKey(ty.ip_index)) { | 1857 | return switch (ty.ip_index) { |
| 1855 | .int_type => true, | 1858 | .empty_struct_type => false, |
| 1856 | .ptr_type => true, | 1859 | |
| 1857 | .array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod), | 1860 | .none => switch (ty.tag()) { |
| 1858 | .vector_type => true, | 1861 | .pointer, |
| 1859 | .opt_type => |child| child.toType().isPtrLikeOptional(mod), | 1862 | .enum_numbered, |
| 1860 | .error_union_type => false, | | |
| 1861 | .simple_type => |t| switch (t) { | | |
| 1862 | .f16, | | |
| 1863 | .f32, | | |
| 1864 | .f64, | | |
| 1865 | .f80, | | |
| 1866 | .f128, | | |
| 1867 | .usize, | | |
| 1868 | .isize, | | |
| 1869 | .c_char, | | |
| 1870 | .c_short, | | |
| 1871 | .c_ushort, | | |
| 1872 | .c_int, | | |
| 1873 | .c_uint, | | |
| 1874 | .c_long, | | |
| 1875 | .c_ulong, | | |
| 1876 | .c_longlong, | | |
| 1877 | .c_ulonglong, | | |
| 1878 | .c_longdouble, | | |
| 1879 | .bool, | | |
| 1880 | .void, | | |
| 1881 | => true, | 1863 | => true, |
| 1882 | | 1864 | |
| 1883 | .anyerror, | 1865 | .error_set, |
| 1884 | .@"anyframe", | 1866 | .error_set_single, |
| 1885 | .anyopaque, | 1867 | .error_set_inferred, |
| 1886 | .atomic_order, | 1868 | .error_set_merged, |
| 1887 | .atomic_rmw_op, | 1869 | .@"opaque", |
| 1888 | .calling_convention, | 1870 | // These are function bodies, not function pointers. |
| 1889 | .address_space, | 1871 | .function, |
| 1890 | .float_mode, | 1872 | .enum_simple, |
| 1891 | .reduce_op, | 1873 | .error_union, |
| 1892 | .call_modifier, | 1874 | .anyframe_T, |
| 1893 | .prefetch_options, | 1875 | .tuple, |
| 1894 | .export_options, | 1876 | .anon_struct, |
| 1895 | .extern_options, | 1877 | .empty_struct, |
| 1896 | .type, | | |
| 1897 | .comptime_int, | | |
| 1898 | .comptime_float, | | |
| 1899 | .noreturn, | | |
| 1900 | .null, | | |
| 1901 | .undefined, | | |
| 1902 | .enum_literal, | | |
| 1903 | .type_info, | | |
| 1904 | .generic_poison, | | |
| 1905 | => false, | 1878 | => false, |
| 1906 | | 1879 | |
| 1907 | .var_args_param => unreachable, | 1880 | .enum_full, |
| 1908 | }, | 1881 | .enum_nonexhaustive, |
| 1909 | .struct_type => @panic("TODO"), | 1882 | => !ty.cast(Payload.EnumFull).?.data.tag_ty_inferred, |
| 1910 | .union_type => @panic("TODO"), | | |
| 1911 | .simple_value => unreachable, | | |
| 1912 | .extern_func => unreachable, | | |
| 1913 | .int => unreachable, | | |
| 1914 | .enum_tag => unreachable, // it's a value, not a type | | |
| 1915 | }; | | |
| 1916 | return switch (ty.tag()) { | | |
| 1917 | .pointer, | | |
| 1918 | .enum_numbered, | | |
| 1919 | => true, | | |
| 1920 | | 1883 | |
| 1921 | .error_set, | 1884 | .inferred_alloc_mut => unreachable, |
| 1922 | .error_set_single, | 1885 | .inferred_alloc_const => unreachable, |
| 1923 | .error_set_inferred, | | |
| 1924 | .error_set_merged, | | |
| 1925 | .@"opaque", | | |
| 1926 | // These are function bodies, not function pointers. | | |
| 1927 | .function, | | |
| 1928 | .enum_simple, | | |
| 1929 | .error_union, | | |
| 1930 | .anyframe_T, | | |
| 1931 | .tuple, | | |
| 1932 | .anon_struct, | | |
| 1933 | .empty_struct_literal, | | |
| 1934 | .empty_struct, | | |
| 1935 | => false, | | |
| 1936 | | 1886 | |
| 1937 | .enum_full, | 1887 | .array, |
| 1938 | .enum_nonexhaustive, | 1888 | .array_sentinel, |
| 1939 | => !ty.cast(Payload.EnumFull).?.data.tag_ty_inferred, | 1889 | => ty.childType(mod).hasWellDefinedLayout(mod), |
| 1940 | | 1890 | |
| 1941 | .inferred_alloc_mut => unreachable, | 1891 | .optional => ty.isPtrLikeOptional(mod), |
| 1942 | .inferred_alloc_const => unreachable, | 1892 | .@"struct" => ty.castTag(.@"struct").?.data.layout != .Auto, |
| | 1893 | .@"union", .union_safety_tagged => ty.cast(Payload.Union).?.data.layout != .Auto, |
| | 1894 | .union_tagged => false, |
| | 1895 | }, |
| | 1896 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| | 1897 | .int_type => true, |
| | 1898 | .ptr_type => true, |
| | 1899 | .array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod), |
| | 1900 | .vector_type => true, |
| | 1901 | .opt_type => |child| child.toType().isPtrLikeOptional(mod), |
| | 1902 | .error_union_type => false, |
| | 1903 | .simple_type => |t| switch (t) { |
| | 1904 | .f16, |
| | 1905 | .f32, |
| | 1906 | .f64, |
| | 1907 | .f80, |
| | 1908 | .f128, |
| | 1909 | .usize, |
| | 1910 | .isize, |
| | 1911 | .c_char, |
| | 1912 | .c_short, |
| | 1913 | .c_ushort, |
| | 1914 | .c_int, |
| | 1915 | .c_uint, |
| | 1916 | .c_long, |
| | 1917 | .c_ulong, |
| | 1918 | .c_longlong, |
| | 1919 | .c_ulonglong, |
| | 1920 | .c_longdouble, |
| | 1921 | .bool, |
| | 1922 | .void, |
| | 1923 | => true, |
| 1943 | | 1924 | |
| 1944 | .array, | 1925 | .anyerror, |
| 1945 | .array_sentinel, | 1926 | .@"anyframe", |
| 1946 | => ty.childType(mod).hasWellDefinedLayout(mod), | 1927 | .anyopaque, |
| | 1928 | .atomic_order, |
| | 1929 | .atomic_rmw_op, |
| | 1930 | .calling_convention, |
| | 1931 | .address_space, |
| | 1932 | .float_mode, |
| | 1933 | .reduce_op, |
| | 1934 | .call_modifier, |
| | 1935 | .prefetch_options, |
| | 1936 | .export_options, |
| | 1937 | .extern_options, |
| | 1938 | .type, |
| | 1939 | .comptime_int, |
| | 1940 | .comptime_float, |
| | 1941 | .noreturn, |
| | 1942 | .null, |
| | 1943 | .undefined, |
| | 1944 | .enum_literal, |
| | 1945 | .type_info, |
| | 1946 | .generic_poison, |
| | 1947 | => false, |
| 1947 | | 1948 | |
| 1948 | .optional => ty.isPtrLikeOptional(mod), | 1949 | .var_args_param => unreachable, |
| 1949 | .@"struct" => ty.castTag(.@"struct").?.data.layout != .Auto, | 1950 | }, |
| 1950 | .@"union", .union_safety_tagged => ty.cast(Payload.Union).?.data.layout != .Auto, | 1951 | .struct_type => @panic("TODO"), |
| 1951 | .union_tagged => false, | 1952 | .union_type => @panic("TODO"), |
| | 1953 | .simple_value => unreachable, |
| | 1954 | .extern_func => unreachable, |
| | 1955 | .int => unreachable, |
| | 1956 | .enum_tag => unreachable, // it's a value, not a type |
| | 1957 | }, |
| 1952 | }; | 1958 | }; |
| 1953 | } | 1959 | } |
| 1954 | | 1960 | |
| ... | @@ -2120,232 +2126,232 @@ pub const Type = struct { | ... | @@ -2120,232 +2126,232 @@ pub const Type = struct { |
| 2120 | else => null, | 2126 | else => null, |
| 2121 | }; | 2127 | }; |
| 2122 | | 2128 | |
| 2123 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { | 2129 | switch (ty.ip_index) { |
| 2124 | .int_type => |int_type| { | 2130 | .empty_struct_type => return AbiAlignmentAdvanced{ .scalar = 0 }, |
| 2125 | if (int_type.bits == 0) return AbiAlignmentAdvanced{ .scalar = 0 }; | 2131 | .none => switch (ty.tag()) { |
| 2126 | return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(int_type.bits, target) }; | 2132 | .@"opaque" => return AbiAlignmentAdvanced{ .scalar = 1 }, |
| 2127 | }, | | |
| 2128 | .ptr_type => { | | |
| 2129 | return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }; | | |
| 2130 | }, | | |
| 2131 | .array_type => |array_type| { | | |
| 2132 | return array_type.child.toType().abiAlignmentAdvanced(mod, strat); | | |
| 2133 | }, | | |
| 2134 | .vector_type => |vector_type| { | | |
| 2135 | const bits_u64 = try bitSizeAdvanced(vector_type.child.toType(), mod, opt_sema); | | |
| 2136 | const bits = @intCast(u32, bits_u64); | | |
| 2137 | const bytes = ((bits * vector_type.len) + 7) / 8; | | |
| 2138 | const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes); | | |
| 2139 | return AbiAlignmentAdvanced{ .scalar = alignment }; | | |
| 2140 | }, | | |
| 2141 | | 2133 | |
| 2142 | .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat), | 2134 | // represents machine code; not a pointer |
| 2143 | .error_union_type => return abiAlignmentAdvancedErrorUnion(ty, mod, strat), | 2135 | .function => { |
| 2144 | .simple_type => |t| switch (t) { | 2136 | const alignment = ty.castTag(.function).?.data.alignment; |
| 2145 | .bool, | 2137 | if (alignment != 0) return AbiAlignmentAdvanced{ .scalar = alignment }; |
| 2146 | .atomic_order, | 2138 | return AbiAlignmentAdvanced{ .scalar = target_util.defaultFunctionAlignment(target) }; |
| 2147 | .atomic_rmw_op, | 2139 | }, |
| 2148 | .calling_convention, | | |
| 2149 | .address_space, | | |
| 2150 | .float_mode, | | |
| 2151 | .reduce_op, | | |
| 2152 | .call_modifier, | | |
| 2153 | .prefetch_options, | | |
| 2154 | .anyopaque, | | |
| 2155 | => return AbiAlignmentAdvanced{ .scalar = 1 }, | | |
| 2156 | | 2140 | |
| 2157 | .usize, | 2141 | .pointer, |
| 2158 | .isize, | 2142 | .anyframe_T, |
| 2159 | .export_options, | | |
| 2160 | .extern_options, | | |
| 2161 | .@"anyframe", | | |
| 2162 | => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }, | 2143 | => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }, |
| 2163 | | 2144 | |
| 2164 | .c_char => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.char) }, | | |
| 2165 | .c_short => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.short) }, | | |
| 2166 | .c_ushort => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ushort) }, | | |
| 2167 | .c_int => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.int) }, | | |
| 2168 | .c_uint => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.uint) }, | | |
| 2169 | .c_long => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.long) }, | | |
| 2170 | .c_ulong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ulong) }, | | |
| 2171 | .c_longlong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longlong) }, | | |
| 2172 | .c_ulonglong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ulonglong) }, | | |
| 2173 | .c_longdouble => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) }, | | |
| 2174 | | | |
| 2175 | .f16 => return AbiAlignmentAdvanced{ .scalar = 2 }, | | |
| 2176 | .f32 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.float) }, | | |
| 2177 | .f64 => switch (target.c_type_bit_size(.double)) { | | |
| 2178 | 64 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.double) }, | | |
| 2179 | else => return AbiAlignmentAdvanced{ .scalar = 8 }, | | |
| 2180 | }, | | |
| 2181 | .f80 => switch (target.c_type_bit_size(.longdouble)) { | | |
| 2182 | 80 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) }, | | |
| 2183 | else => { | | |
| 2184 | const u80_ty: Type = .{ | | |
| 2185 | .ip_index = .u80_type, | | |
| 2186 | .legacy = undefined, | | |
| 2187 | }; | | |
| 2188 | return AbiAlignmentAdvanced{ .scalar = abiAlignment(u80_ty, mod) }; | | |
| 2189 | }, | | |
| 2190 | }, | | |
| 2191 | .f128 => switch (target.c_type_bit_size(.longdouble)) { | | |
| 2192 | 128 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) }, | | |
| 2193 | else => return AbiAlignmentAdvanced{ .scalar = 16 }, | | |
| 2194 | }, | | |
| 2195 | | | |
| 2196 | // TODO revisit this when we have the concept of the error tag type | 2145 | // TODO revisit this when we have the concept of the error tag type |
| 2197 | .anyerror => return AbiAlignmentAdvanced{ .scalar = 2 }, | 2146 | .error_set_inferred, |
| 2198 | | 2147 | .error_set_single, |
| 2199 | .void, | 2148 | .error_set, |
| 2200 | .type, | 2149 | .error_set_merged, |
| 2201 | .comptime_int, | 2150 | => return AbiAlignmentAdvanced{ .scalar = 2 }, |
| 2202 | .comptime_float, | | |
| 2203 | .null, | | |
| 2204 | .undefined, | | |
| 2205 | .enum_literal, | | |
| 2206 | .type_info, | | |
| 2207 | => return AbiAlignmentAdvanced{ .scalar = 0 }, | | |
| 2208 | | | |
| 2209 | .noreturn => unreachable, | | |
| 2210 | .generic_poison => unreachable, | | |
| 2211 | .var_args_param => unreachable, | | |
| 2212 | }, | | |
| 2213 | .struct_type => @panic("TODO"), | | |
| 2214 | .union_type => @panic("TODO"), | | |
| 2215 | .simple_value => unreachable, | | |
| 2216 | .extern_func => unreachable, | | |
| 2217 | .int => unreachable, | | |
| 2218 | .enum_tag => unreachable, // it's a value, not a type | | |
| 2219 | }; | | |
| 2220 | | | |
| 2221 | switch (ty.tag()) { | | |
| 2222 | .@"opaque" => return AbiAlignmentAdvanced{ .scalar = 1 }, | | |
| 2223 | | | |
| 2224 | // represents machine code; not a pointer | | |
| 2225 | .function => { | | |
| 2226 | const alignment = ty.castTag(.function).?.data.alignment; | | |
| 2227 | if (alignment != 0) return AbiAlignmentAdvanced{ .scalar = alignment }; | | |
| 2228 | return AbiAlignmentAdvanced{ .scalar = target_util.defaultFunctionAlignment(target) }; | | |
| 2229 | }, | | |
| 2230 | | | |
| 2231 | .pointer, | | |
| 2232 | .anyframe_T, | | |
| 2233 | => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }, | | |
| 2234 | | 2151 | |
| 2235 | // TODO revisit this when we have the concept of the error tag type | 2152 | .array, .array_sentinel => return ty.childType(mod).abiAlignmentAdvanced(mod, strat), |
| 2236 | .error_set_inferred, | | |
| 2237 | .error_set_single, | | |
| 2238 | .error_set, | | |
| 2239 | .error_set_merged, | | |
| 2240 | => return AbiAlignmentAdvanced{ .scalar = 2 }, | | |
| 2241 | | | |
| 2242 | .array, .array_sentinel => return ty.childType(mod).abiAlignmentAdvanced(mod, strat), | | |
| 2243 | | 2153 | |
| 2244 | .optional => return abiAlignmentAdvancedOptional(ty, mod, strat), | 2154 | .optional => return abiAlignmentAdvancedOptional(ty, mod, strat), |
| 2245 | .error_union => return abiAlignmentAdvancedErrorUnion(ty, mod, strat), | 2155 | .error_union => return abiAlignmentAdvancedErrorUnion(ty, mod, strat), |
| 2246 | | 2156 | |
| 2247 | .@"struct" => { | 2157 | .@"struct" => { |
| 2248 | const struct_obj = ty.castTag(.@"struct").?.data; | 2158 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 2249 | if (opt_sema) |sema| { | 2159 | if (opt_sema) |sema| { |
| 2250 | if (struct_obj.status == .field_types_wip) { | 2160 | if (struct_obj.status == .field_types_wip) { |
| 2251 | // We'll guess "pointer-aligned", if the struct has an | 2161 | // We'll guess "pointer-aligned", if the struct has an |
| 2252 | // underaligned pointer field then some allocations | 2162 | // underaligned pointer field then some allocations |
| 2253 | // might require explicit alignment. | 2163 | // might require explicit alignment. |
| 2254 | return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }; | 2164 | return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }; |
| | 2165 | } |
| | 2166 | _ = try sema.resolveTypeFields(ty); |
| 2255 | } | 2167 | } |
| 2256 | _ = try sema.resolveTypeFields(ty); | 2168 | if (!struct_obj.haveFieldTypes()) switch (strat) { |
| 2257 | } | 2169 | .eager => unreachable, // struct layout not resolved |
| 2258 | if (!struct_obj.haveFieldTypes()) switch (strat) { | 2170 | .sema => unreachable, // handled above |
| 2259 | .eager => unreachable, // struct layout not resolved | 2171 | .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) }, |
| 2260 | .sema => unreachable, // handled above | 2172 | }; |
| 2261 | .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) }, | 2173 | if (struct_obj.layout == .Packed) { |
| 2262 | }; | 2174 | switch (strat) { |
| 2263 | if (struct_obj.layout == .Packed) { | 2175 | .sema => |sema| try sema.resolveTypeLayout(ty), |
| 2264 | switch (strat) { | 2176 | .lazy => |arena| { |
| 2265 | .sema => |sema| try sema.resolveTypeLayout(ty), | 2177 | if (!struct_obj.haveLayout()) { |
| 2266 | .lazy => |arena| { | 2178 | return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) }; |
| 2267 | if (!struct_obj.haveLayout()) { | 2179 | } |
| 2268 | return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) }; | 2180 | }, |
| 2269 | } | 2181 | .eager => {}, |
| 2270 | }, | 2182 | } |
| 2271 | .eager => {}, | 2183 | assert(struct_obj.haveLayout()); |
| | 2184 | return AbiAlignmentAdvanced{ .scalar = struct_obj.backing_int_ty.abiAlignment(mod) }; |
| 2272 | } | 2185 | } |
| 2273 | assert(struct_obj.haveLayout()); | | |
| 2274 | return AbiAlignmentAdvanced{ .scalar = struct_obj.backing_int_ty.abiAlignment(mod) }; | | |
| 2275 | } | | |
| 2276 | | | |
| 2277 | const fields = ty.structFields(); | | |
| 2278 | var big_align: u32 = 0; | | |
| 2279 | for (fields.values()) |field| { | | |
| 2280 | if (!(field.ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { | | |
| 2281 | error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) }, | | |
| 2282 | else => |e| return e, | | |
| 2283 | })) continue; | | |
| 2284 | | 2186 | |
| 2285 | const field_align = if (field.abi_align != 0) | 2187 | const fields = ty.structFields(); |
| 2286 | field.abi_align | 2188 | var big_align: u32 = 0; |
| 2287 | else switch (try field.ty.abiAlignmentAdvanced(mod, strat)) { | 2189 | for (fields.values()) |field| { |
| 2288 | .scalar => |a| a, | 2190 | if (!(field.ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { |
| 2289 | .val => switch (strat) { | 2191 | error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) }, |
| 2290 | .eager => unreachable, // struct layout not resolved | 2192 | else => |e| return e, |
| 2291 | .sema => unreachable, // handled above | 2193 | })) continue; |
| 2292 | .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) }, | 2194 | |
| 2293 | }, | 2195 | const field_align = if (field.abi_align != 0) |
| 2294 | }; | 2196 | field.abi_align |
| 2295 | big_align = @max(big_align, field_align); | 2197 | else switch (try field.ty.abiAlignmentAdvanced(mod, strat)) { |
| | 2198 | .scalar => |a| a, |
| | 2199 | .val => switch (strat) { |
| | 2200 | .eager => unreachable, // struct layout not resolved |
| | 2201 | .sema => unreachable, // handled above |
| | 2202 | .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) }, |
| | 2203 | }, |
| | 2204 | }; |
| | 2205 | big_align = @max(big_align, field_align); |
| | 2206 | |
| | 2207 | // This logic is duplicated in Module.Struct.Field.alignment. |
| | 2208 | if (struct_obj.layout == .Extern or target.ofmt == .c) { |
| | 2209 | if (field.ty.isAbiInt(mod) and field.ty.intInfo(mod).bits >= 128) { |
| | 2210 | // The C ABI requires 128 bit integer fields of structs |
| | 2211 | // to be 16-bytes aligned. |
| | 2212 | big_align = @max(big_align, 16); |
| | 2213 | } |
| | 2214 | } |
| | 2215 | } |
| | 2216 | return AbiAlignmentAdvanced{ .scalar = big_align }; |
| | 2217 | }, |
| 2296 | | 2218 | |
| 2297 | // This logic is duplicated in Module.Struct.Field.alignment. | 2219 | .tuple, .anon_struct => { |
| 2298 | if (struct_obj.layout == .Extern or target.ofmt == .c) { | 2220 | const tuple = ty.tupleFields(); |
| 2299 | if (field.ty.isAbiInt(mod) and field.ty.intInfo(mod).bits >= 128) { | 2221 | var big_align: u32 = 0; |
| 2300 | // The C ABI requires 128 bit integer fields of structs | 2222 | for (tuple.types, 0..) |field_ty, i| { |
| 2301 | // to be 16-bytes aligned. | 2223 | const val = tuple.values[i]; |
| 2302 | big_align = @max(big_align, 16); | 2224 | if (val.ip_index != .unreachable_value) continue; // comptime field |
| | 2225 | if (!(field_ty.hasRuntimeBits(mod))) continue; |
| | 2226 | |
| | 2227 | switch (try field_ty.abiAlignmentAdvanced(mod, strat)) { |
| | 2228 | .scalar => |field_align| big_align = @max(big_align, field_align), |
| | 2229 | .val => switch (strat) { |
| | 2230 | .eager => unreachable, // field type alignment not resolved |
| | 2231 | .sema => unreachable, // passed to abiAlignmentAdvanced above |
| | 2232 | .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) }, |
| | 2233 | }, |
| 2303 | } | 2234 | } |
| 2304 | } | 2235 | } |
| 2305 | } | 2236 | return AbiAlignmentAdvanced{ .scalar = big_align }; |
| 2306 | return AbiAlignmentAdvanced{ .scalar = big_align }; | 2237 | }, |
| 2307 | }, | | |
| 2308 | | 2238 | |
| 2309 | .tuple, .anon_struct => { | 2239 | .enum_full, .enum_nonexhaustive, .enum_simple, .enum_numbered => { |
| 2310 | const tuple = ty.tupleFields(); | 2240 | const int_tag_ty = try ty.intTagType(mod); |
| 2311 | var big_align: u32 = 0; | 2241 | return AbiAlignmentAdvanced{ .scalar = int_tag_ty.abiAlignment(mod) }; |
| 2312 | for (tuple.types, 0..) |field_ty, i| { | 2242 | }, |
| 2313 | const val = tuple.values[i]; | 2243 | .@"union" => { |
| 2314 | if (val.ip_index != .unreachable_value) continue; // comptime field | 2244 | const union_obj = ty.castTag(.@"union").?.data; |
| 2315 | if (!(field_ty.hasRuntimeBits(mod))) continue; | 2245 | return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, false); |
| | 2246 | }, |
| | 2247 | .union_safety_tagged, .union_tagged => { |
| | 2248 | const union_obj = ty.cast(Payload.Union).?.data; |
| | 2249 | return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, true); |
| | 2250 | }, |
| | 2251 | |
| | 2252 | .empty_struct => return AbiAlignmentAdvanced{ .scalar = 0 }, |
| 2316 | | 2253 | |
| 2317 | switch (try field_ty.abiAlignmentAdvanced(mod, strat)) { | 2254 | .inferred_alloc_const, |
| 2318 | .scalar => |field_align| big_align = @max(big_align, field_align), | 2255 | .inferred_alloc_mut, |
| 2319 | .val => switch (strat) { | 2256 | => unreachable, |
| 2320 | .eager => unreachable, // field type alignment not resolved | | |
| 2321 | .sema => unreachable, // passed to abiAlignmentAdvanced above | | |
| 2322 | .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) }, | | |
| 2323 | }, | | |
| 2324 | } | | |
| 2325 | } | | |
| 2326 | return AbiAlignmentAdvanced{ .scalar = big_align }; | | |
| 2327 | }, | 2257 | }, |
| | 2258 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| | 2259 | .int_type => |int_type| { |
| | 2260 | if (int_type.bits == 0) return AbiAlignmentAdvanced{ .scalar = 0 }; |
| | 2261 | return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(int_type.bits, target) }; |
| | 2262 | }, |
| | 2263 | .ptr_type => { |
| | 2264 | return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }; |
| | 2265 | }, |
| | 2266 | .array_type => |array_type| { |
| | 2267 | return array_type.child.toType().abiAlignmentAdvanced(mod, strat); |
| | 2268 | }, |
| | 2269 | .vector_type => |vector_type| { |
| | 2270 | const bits_u64 = try bitSizeAdvanced(vector_type.child.toType(), mod, opt_sema); |
| | 2271 | const bits = @intCast(u32, bits_u64); |
| | 2272 | const bytes = ((bits * vector_type.len) + 7) / 8; |
| | 2273 | const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes); |
| | 2274 | return AbiAlignmentAdvanced{ .scalar = alignment }; |
| | 2275 | }, |
| 2328 | | 2276 | |
| 2329 | .enum_full, .enum_nonexhaustive, .enum_simple, .enum_numbered => { | 2277 | .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat), |
| 2330 | const int_tag_ty = try ty.intTagType(mod); | 2278 | .error_union_type => return abiAlignmentAdvancedErrorUnion(ty, mod, strat), |
| 2331 | return AbiAlignmentAdvanced{ .scalar = int_tag_ty.abiAlignment(mod) }; | 2279 | .simple_type => |t| switch (t) { |
| 2332 | }, | 2280 | .bool, |
| 2333 | .@"union" => { | 2281 | .atomic_order, |
| 2334 | const union_obj = ty.castTag(.@"union").?.data; | 2282 | .atomic_rmw_op, |
| 2335 | return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, false); | 2283 | .calling_convention, |
| 2336 | }, | 2284 | .address_space, |
| 2337 | .union_safety_tagged, .union_tagged => { | 2285 | .float_mode, |
| 2338 | const union_obj = ty.cast(Payload.Union).?.data; | 2286 | .reduce_op, |
| 2339 | return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, true); | 2287 | .call_modifier, |
| 2340 | }, | 2288 | .prefetch_options, |
| | 2289 | .anyopaque, |
| | 2290 | => return AbiAlignmentAdvanced{ .scalar = 1 }, |
| 2341 | | 2291 | |
| 2342 | .empty_struct, | 2292 | .usize, |
| 2343 | .empty_struct_literal, | 2293 | .isize, |
| 2344 | => return AbiAlignmentAdvanced{ .scalar = 0 }, | 2294 | .export_options, |
| | 2295 | .extern_options, |
| | 2296 | .@"anyframe", |
| | 2297 | => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }, |
| | 2298 | |
| | 2299 | .c_char => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.char) }, |
| | 2300 | .c_short => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.short) }, |
| | 2301 | .c_ushort => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ushort) }, |
| | 2302 | .c_int => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.int) }, |
| | 2303 | .c_uint => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.uint) }, |
| | 2304 | .c_long => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.long) }, |
| | 2305 | .c_ulong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ulong) }, |
| | 2306 | .c_longlong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longlong) }, |
| | 2307 | .c_ulonglong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ulonglong) }, |
| | 2308 | .c_longdouble => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) }, |
| | 2309 | |
| | 2310 | .f16 => return AbiAlignmentAdvanced{ .scalar = 2 }, |
| | 2311 | .f32 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.float) }, |
| | 2312 | .f64 => switch (target.c_type_bit_size(.double)) { |
| | 2313 | 64 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.double) }, |
| | 2314 | else => return AbiAlignmentAdvanced{ .scalar = 8 }, |
| | 2315 | }, |
| | 2316 | .f80 => switch (target.c_type_bit_size(.longdouble)) { |
| | 2317 | 80 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) }, |
| | 2318 | else => { |
| | 2319 | const u80_ty: Type = .{ |
| | 2320 | .ip_index = .u80_type, |
| | 2321 | .legacy = undefined, |
| | 2322 | }; |
| | 2323 | return AbiAlignmentAdvanced{ .scalar = abiAlignment(u80_ty, mod) }; |
| | 2324 | }, |
| | 2325 | }, |
| | 2326 | .f128 => switch (target.c_type_bit_size(.longdouble)) { |
| | 2327 | 128 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) }, |
| | 2328 | else => return AbiAlignmentAdvanced{ .scalar = 16 }, |
| | 2329 | }, |
| 2345 | | 2330 | |
| 2346 | .inferred_alloc_const, | 2331 | // TODO revisit this when we have the concept of the error tag type |
| 2347 | .inferred_alloc_mut, | 2332 | .anyerror => return AbiAlignmentAdvanced{ .scalar = 2 }, |
| 2348 | => unreachable, | 2333 | |
| | 2334 | .void, |
| | 2335 | .type, |
| | 2336 | .comptime_int, |
| | 2337 | .comptime_float, |
| | 2338 | .null, |
| | 2339 | .undefined, |
| | 2340 | .enum_literal, |
| | 2341 | .type_info, |
| | 2342 | => return AbiAlignmentAdvanced{ .scalar = 0 }, |
| | 2343 | |
| | 2344 | .noreturn => unreachable, |
| | 2345 | .generic_poison => unreachable, |
| | 2346 | .var_args_param => unreachable, |
| | 2347 | }, |
| | 2348 | .struct_type => @panic("TODO"), |
| | 2349 | .union_type => @panic("TODO"), |
| | 2350 | .simple_value => unreachable, |
| | 2351 | .extern_func => unreachable, |
| | 2352 | .int => unreachable, |
| | 2353 | .enum_tag => unreachable, // it's a value, not a type |
| | 2354 | }, |
| 2349 | } | 2355 | } |
| 2350 | } | 2356 | } |
| 2351 | | 2357 | |
| ... | @@ -2506,255 +2512,256 @@ pub const Type = struct { | ... | @@ -2506,255 +2512,256 @@ pub const Type = struct { |
| 2506 | ) Module.CompileError!AbiSizeAdvanced { | 2512 | ) Module.CompileError!AbiSizeAdvanced { |
| 2507 | const target = mod.getTarget(); | 2513 | const target = mod.getTarget(); |
| 2508 | | 2514 | |
| 2509 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { | 2515 | switch (ty.ip_index) { |
| 2510 | .int_type => |int_type| { | 2516 | .empty_struct_type => return AbiSizeAdvanced{ .scalar = 0 }, |
| 2511 | if (int_type.bits == 0) return AbiSizeAdvanced{ .scalar = 0 }; | | |
| 2512 | return AbiSizeAdvanced{ .scalar = intAbiSize(int_type.bits, target) }; | | |
| 2513 | }, | | |
| 2514 | .ptr_type => |ptr_type| switch (ptr_type.size) { | | |
| 2515 | .Slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 }, | | |
| 2516 | else => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) }, | | |
| 2517 | }, | | |
| 2518 | .array_type => |array_type| { | | |
| 2519 | const len = array_type.len + @boolToInt(array_type.sentinel != .none); | | |
| 2520 | switch (try array_type.child.toType().abiSizeAdvanced(mod, strat)) { | | |
| 2521 | .scalar => |elem_size| return .{ .scalar = len * elem_size }, | | |
| 2522 | .val => switch (strat) { | | |
| 2523 | .sema, .eager => unreachable, | | |
| 2524 | .lazy => |arena| return .{ .val = try Value.Tag.lazy_size.create(arena, ty) }, | | |
| 2525 | }, | | |
| 2526 | } | | |
| 2527 | }, | | |
| 2528 | .vector_type => |vector_type| { | | |
| 2529 | const opt_sema = switch (strat) { | | |
| 2530 | .sema => |sema| sema, | | |
| 2531 | .eager => null, | | |
| 2532 | .lazy => |arena| return AbiSizeAdvanced{ | | |
| 2533 | .val = try Value.Tag.lazy_size.create(arena, ty), | | |
| 2534 | }, | | |
| 2535 | }; | | |
| 2536 | const elem_bits_u64 = try vector_type.child.toType().bitSizeAdvanced(mod, opt_sema); | | |
| 2537 | const elem_bits = @intCast(u32, elem_bits_u64); | | |
| 2538 | const total_bits = elem_bits * vector_type.len; | | |
| 2539 | const total_bytes = (total_bits + 7) / 8; | | |
| 2540 | const alignment = switch (try ty.abiAlignmentAdvanced(mod, strat)) { | | |
| 2541 | .scalar => |x| x, | | |
| 2542 | .val => return AbiSizeAdvanced{ | | |
| 2543 | .val = try Value.Tag.lazy_size.create(strat.lazy, ty), | | |
| 2544 | }, | | |
| 2545 | }; | | |
| 2546 | const result = std.mem.alignForwardGeneric(u32, total_bytes, alignment); | | |
| 2547 | return AbiSizeAdvanced{ .scalar = result }; | | |
| 2548 | }, | | |
| 2549 | | 2517 | |
| 2550 | .opt_type => return ty.abiSizeAdvancedOptional(mod, strat), | 2518 | .none => switch (ty.tag()) { |
| 2551 | .error_union_type => @panic("TODO"), | 2519 | .function => unreachable, // represents machine code; not a pointer |
| 2552 | .simple_type => |t| switch (t) { | 2520 | .@"opaque" => unreachable, // no size available |
| 2553 | .bool, | 2521 | .inferred_alloc_const => unreachable, |
| 2554 | .atomic_order, | 2522 | .inferred_alloc_mut => unreachable, |
| 2555 | .atomic_rmw_op, | 2523 | |
| 2556 | .calling_convention, | 2524 | .empty_struct => return AbiSizeAdvanced{ .scalar = 0 }, |
| 2557 | .address_space, | 2525 | |
| 2558 | .float_mode, | 2526 | .@"struct", .tuple, .anon_struct => switch (ty.containerLayout()) { |
| 2559 | .reduce_op, | 2527 | .Packed => { |
| 2560 | .call_modifier, | 2528 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 2561 | => return AbiSizeAdvanced{ .scalar = 1 }, | 2529 | switch (strat) { |
| 2562 | | 2530 | .sema => |sema| try sema.resolveTypeLayout(ty), |
| 2563 | .f16 => return AbiSizeAdvanced{ .scalar = 2 }, | 2531 | .lazy => |arena| { |
| 2564 | .f32 => return AbiSizeAdvanced{ .scalar = 4 }, | 2532 | if (!struct_obj.haveLayout()) { |
| 2565 | .f64 => return AbiSizeAdvanced{ .scalar = 8 }, | 2533 | return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) }; |
| 2566 | .f128 => return AbiSizeAdvanced{ .scalar = 16 }, | 2534 | } |
| 2567 | .f80 => switch (target.c_type_bit_size(.longdouble)) { | 2535 | }, |
| 2568 | 80 => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) }, | 2536 | .eager => {}, |
| | 2537 | } |
| | 2538 | assert(struct_obj.haveLayout()); |
| | 2539 | return AbiSizeAdvanced{ .scalar = struct_obj.backing_int_ty.abiSize(mod) }; |
| | 2540 | }, |
| 2569 | else => { | 2541 | else => { |
| 2570 | const u80_ty: Type = .{ | 2542 | switch (strat) { |
| 2571 | .ip_index = .u80_type, | 2543 | .sema => |sema| try sema.resolveTypeLayout(ty), |
| 2572 | .legacy = undefined, | 2544 | .lazy => |arena| { |
| 2573 | }; | 2545 | if (ty.castTag(.@"struct")) |payload| { |
| 2574 | return AbiSizeAdvanced{ .scalar = abiSize(u80_ty, mod) }; | 2546 | const struct_obj = payload.data; |
| | 2547 | if (!struct_obj.haveLayout()) { |
| | 2548 | return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) }; |
| | 2549 | } |
| | 2550 | } |
| | 2551 | }, |
| | 2552 | .eager => {}, |
| | 2553 | } |
| | 2554 | const field_count = ty.structFieldCount(); |
| | 2555 | if (field_count == 0) { |
| | 2556 | return AbiSizeAdvanced{ .scalar = 0 }; |
| | 2557 | } |
| | 2558 | return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) }; |
| 2575 | }, | 2559 | }, |
| 2576 | }, | 2560 | }, |
| 2577 | | 2561 | |
| 2578 | .usize, | 2562 | .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => { |
| 2579 | .isize, | 2563 | const int_tag_ty = try ty.intTagType(mod); |
| 2580 | .@"anyframe", | 2564 | return AbiSizeAdvanced{ .scalar = int_tag_ty.abiSize(mod) }; |
| 2581 | => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }, | 2565 | }, |
| 2582 | | 2566 | .@"union" => { |
| 2583 | .c_char => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.char) }, | 2567 | const union_obj = ty.castTag(.@"union").?.data; |
| 2584 | .c_short => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.short) }, | 2568 | return abiSizeAdvancedUnion(ty, mod, strat, union_obj, false); |
| 2585 | .c_ushort => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ushort) }, | 2569 | }, |
| 2586 | .c_int => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.int) }, | 2570 | .union_safety_tagged, .union_tagged => { |
| 2587 | .c_uint => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.uint) }, | 2571 | const union_obj = ty.cast(Payload.Union).?.data; |
| 2588 | .c_long => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.long) }, | 2572 | return abiSizeAdvancedUnion(ty, mod, strat, union_obj, true); |
| 2589 | .c_ulong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulong) }, | 2573 | }, |
| 2590 | .c_longlong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longlong) }, | | |
| 2591 | .c_ulonglong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulonglong) }, | | |
| 2592 | .c_longdouble => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) }, | | |
| 2593 | | | |
| 2594 | .anyopaque, | | |
| 2595 | .void, | | |
| 2596 | .type, | | |
| 2597 | .comptime_int, | | |
| 2598 | .comptime_float, | | |
| 2599 | .null, | | |
| 2600 | .undefined, | | |
| 2601 | .enum_literal, | | |
| 2602 | => return AbiSizeAdvanced{ .scalar = 0 }, | | |
| 2603 | | | |
| 2604 | // TODO revisit this when we have the concept of the error tag type | | |
| 2605 | .anyerror => return AbiSizeAdvanced{ .scalar = 2 }, | | |
| 2606 | | | |
| 2607 | .prefetch_options => unreachable, // missing call to resolveTypeFields | | |
| 2608 | .export_options => unreachable, // missing call to resolveTypeFields | | |
| 2609 | .extern_options => unreachable, // missing call to resolveTypeFields | | |
| 2610 | | | |
| 2611 | .type_info => unreachable, | | |
| 2612 | .noreturn => unreachable, | | |
| 2613 | .generic_poison => unreachable, | | |
| 2614 | .var_args_param => unreachable, | | |
| 2615 | }, | | |
| 2616 | .struct_type => @panic("TODO"), | | |
| 2617 | .union_type => @panic("TODO"), | | |
| 2618 | .simple_value => unreachable, | | |
| 2619 | .extern_func => unreachable, | | |
| 2620 | .int => unreachable, | | |
| 2621 | .enum_tag => unreachable, // it's a value, not a type | | |
| 2622 | }; | | |
| 2623 | | | |
| 2624 | switch (ty.tag()) { | | |
| 2625 | .function => unreachable, // represents machine code; not a pointer | | |
| 2626 | .@"opaque" => unreachable, // no size available | | |
| 2627 | .inferred_alloc_const => unreachable, | | |
| 2628 | .inferred_alloc_mut => unreachable, | | |
| 2629 | | | |
| 2630 | .empty_struct_literal, | | |
| 2631 | .empty_struct, | | |
| 2632 | => return AbiSizeAdvanced{ .scalar = 0 }, | | |
| 2633 | | 2574 | |
| 2634 | .@"struct", .tuple, .anon_struct => switch (ty.containerLayout()) { | 2575 | .array => { |
| 2635 | .Packed => { | 2576 | const payload = ty.castTag(.array).?.data; |
| 2636 | const struct_obj = ty.castTag(.@"struct").?.data; | 2577 | switch (try payload.elem_type.abiSizeAdvanced(mod, strat)) { |
| 2637 | switch (strat) { | 2578 | .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = payload.len * elem_size }, |
| 2638 | .sema => |sema| try sema.resolveTypeLayout(ty), | 2579 | .val => switch (strat) { |
| 2639 | .lazy => |arena| { | 2580 | .sema => unreachable, |
| 2640 | if (!struct_obj.haveLayout()) { | 2581 | .eager => unreachable, |
| 2641 | return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) }; | 2582 | .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) }, |
| 2642 | } | | |
| 2643 | }, | 2583 | }, |
| 2644 | .eager => {}, | | |
| 2645 | } | 2584 | } |
| 2646 | assert(struct_obj.haveLayout()); | | |
| 2647 | return AbiSizeAdvanced{ .scalar = struct_obj.backing_int_ty.abiSize(mod) }; | | |
| 2648 | }, | 2585 | }, |
| 2649 | else => { | 2586 | .array_sentinel => { |
| 2650 | switch (strat) { | 2587 | const payload = ty.castTag(.array_sentinel).?.data; |
| 2651 | .sema => |sema| try sema.resolveTypeLayout(ty), | 2588 | switch (try payload.elem_type.abiSizeAdvanced(mod, strat)) { |
| 2652 | .lazy => |arena| { | 2589 | .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = (payload.len + 1) * elem_size }, |
| 2653 | if (ty.castTag(.@"struct")) |payload| { | 2590 | .val => switch (strat) { |
| 2654 | const struct_obj = payload.data; | 2591 | .sema => unreachable, |
| 2655 | if (!struct_obj.haveLayout()) { | 2592 | .eager => unreachable, |
| 2656 | return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) }; | 2593 | .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) }, |
| 2657 | } | | |
| 2658 | } | | |
| 2659 | }, | 2594 | }, |
| 2660 | .eager => {}, | | |
| 2661 | } | 2595 | } |
| 2662 | const field_count = ty.structFieldCount(); | | |
| 2663 | if (field_count == 0) { | | |
| 2664 | return AbiSizeAdvanced{ .scalar = 0 }; | | |
| 2665 | } | | |
| 2666 | return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) }; | | |
| 2667 | }, | 2596 | }, |
| 2668 | }, | | |
| 2669 | | 2597 | |
| 2670 | .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => { | 2598 | .anyframe_T => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }, |
| 2671 | const int_tag_ty = try ty.intTagType(mod); | | |
| 2672 | return AbiSizeAdvanced{ .scalar = int_tag_ty.abiSize(mod) }; | | |
| 2673 | }, | | |
| 2674 | .@"union" => { | | |
| 2675 | const union_obj = ty.castTag(.@"union").?.data; | | |
| 2676 | return abiSizeAdvancedUnion(ty, mod, strat, union_obj, false); | | |
| 2677 | }, | | |
| 2678 | .union_safety_tagged, .union_tagged => { | | |
| 2679 | const union_obj = ty.cast(Payload.Union).?.data; | | |
| 2680 | return abiSizeAdvancedUnion(ty, mod, strat, union_obj, true); | | |
| 2681 | }, | | |
| 2682 | | 2599 | |
| 2683 | .array => { | 2600 | .pointer => switch (ty.castTag(.pointer).?.data.size) { |
| 2684 | const payload = ty.castTag(.array).?.data; | 2601 | .Slice => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 }, |
| 2685 | switch (try payload.elem_type.abiSizeAdvanced(mod, strat)) { | 2602 | else => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }, |
| 2686 | .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = payload.len * elem_size }, | 2603 | }, |
| 2687 | .val => switch (strat) { | | |
| 2688 | .sema => unreachable, | | |
| 2689 | .eager => unreachable, | | |
| 2690 | .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) }, | | |
| 2691 | }, | | |
| 2692 | } | | |
| 2693 | }, | | |
| 2694 | .array_sentinel => { | | |
| 2695 | const payload = ty.castTag(.array_sentinel).?.data; | | |
| 2696 | switch (try payload.elem_type.abiSizeAdvanced(mod, strat)) { | | |
| 2697 | .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = (payload.len + 1) * elem_size }, | | |
| 2698 | .val => switch (strat) { | | |
| 2699 | .sema => unreachable, | | |
| 2700 | .eager => unreachable, | | |
| 2701 | .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) }, | | |
| 2702 | }, | | |
| 2703 | } | | |
| 2704 | }, | | |
| 2705 | | 2604 | |
| 2706 | .anyframe_T => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }, | 2605 | // TODO revisit this when we have the concept of the error tag type |
| | 2606 | .error_set_inferred, |
| | 2607 | .error_set, |
| | 2608 | .error_set_merged, |
| | 2609 | .error_set_single, |
| | 2610 | => return AbiSizeAdvanced{ .scalar = 2 }, |
| 2707 | | 2611 | |
| 2708 | .pointer => switch (ty.castTag(.pointer).?.data.size) { | 2612 | .optional => return ty.abiSizeAdvancedOptional(mod, strat), |
| 2709 | .Slice => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 }, | | |
| 2710 | else => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }, | | |
| 2711 | }, | | |
| 2712 | | 2613 | |
| 2713 | // TODO revisit this when we have the concept of the error tag type | 2614 | .error_union => { |
| 2714 | .error_set_inferred, | 2615 | // This code needs to be kept in sync with the equivalent switch prong |
| 2715 | .error_set, | 2616 | // in abiAlignmentAdvanced. |
| 2716 | .error_set_merged, | 2617 | const data = ty.castTag(.error_union).?.data; |
| 2717 | .error_set_single, | 2618 | const code_size = abiSize(Type.anyerror, mod); |
| 2718 | => return AbiSizeAdvanced{ .scalar = 2 }, | 2619 | if (!(data.payload.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { |
| | 2620 | error.NeedLazy => return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(strat.lazy, ty) }, |
| | 2621 | else => |e| return e, |
| | 2622 | })) { |
| | 2623 | // Same as anyerror. |
| | 2624 | return AbiSizeAdvanced{ .scalar = code_size }; |
| | 2625 | } |
| | 2626 | const code_align = abiAlignment(Type.anyerror, mod); |
| | 2627 | const payload_align = abiAlignment(data.payload, mod); |
| | 2628 | const payload_size = switch (try data.payload.abiSizeAdvanced(mod, strat)) { |
| | 2629 | .scalar => |elem_size| elem_size, |
| | 2630 | .val => switch (strat) { |
| | 2631 | .sema => unreachable, |
| | 2632 | .eager => unreachable, |
| | 2633 | .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) }, |
| | 2634 | }, |
| | 2635 | }; |
| 2719 | | 2636 | |
| 2720 | .optional => return ty.abiSizeAdvancedOptional(mod, strat), | 2637 | var size: u64 = 0; |
| | 2638 | if (code_align > payload_align) { |
| | 2639 | size += code_size; |
| | 2640 | size = std.mem.alignForwardGeneric(u64, size, payload_align); |
| | 2641 | size += payload_size; |
| | 2642 | size = std.mem.alignForwardGeneric(u64, size, code_align); |
| | 2643 | } else { |
| | 2644 | size += payload_size; |
| | 2645 | size = std.mem.alignForwardGeneric(u64, size, code_align); |
| | 2646 | size += code_size; |
| | 2647 | size = std.mem.alignForwardGeneric(u64, size, payload_align); |
| | 2648 | } |
| | 2649 | return AbiSizeAdvanced{ .scalar = size }; |
| | 2650 | }, |
| | 2651 | }, |
| | 2652 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| | 2653 | .int_type => |int_type| { |
| | 2654 | if (int_type.bits == 0) return AbiSizeAdvanced{ .scalar = 0 }; |
| | 2655 | return AbiSizeAdvanced{ .scalar = intAbiSize(int_type.bits, target) }; |
| | 2656 | }, |
| | 2657 | .ptr_type => |ptr_type| switch (ptr_type.size) { |
| | 2658 | .Slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 }, |
| | 2659 | else => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) }, |
| | 2660 | }, |
| | 2661 | .array_type => |array_type| { |
| | 2662 | const len = array_type.len + @boolToInt(array_type.sentinel != .none); |
| | 2663 | switch (try array_type.child.toType().abiSizeAdvanced(mod, strat)) { |
| | 2664 | .scalar => |elem_size| return .{ .scalar = len * elem_size }, |
| | 2665 | .val => switch (strat) { |
| | 2666 | .sema, .eager => unreachable, |
| | 2667 | .lazy => |arena| return .{ .val = try Value.Tag.lazy_size.create(arena, ty) }, |
| | 2668 | }, |
| | 2669 | } |
| | 2670 | }, |
| | 2671 | .vector_type => |vector_type| { |
| | 2672 | const opt_sema = switch (strat) { |
| | 2673 | .sema => |sema| sema, |
| | 2674 | .eager => null, |
| | 2675 | .lazy => |arena| return AbiSizeAdvanced{ |
| | 2676 | .val = try Value.Tag.lazy_size.create(arena, ty), |
| | 2677 | }, |
| | 2678 | }; |
| | 2679 | const elem_bits_u64 = try vector_type.child.toType().bitSizeAdvanced(mod, opt_sema); |
| | 2680 | const elem_bits = @intCast(u32, elem_bits_u64); |
| | 2681 | const total_bits = elem_bits * vector_type.len; |
| | 2682 | const total_bytes = (total_bits + 7) / 8; |
| | 2683 | const alignment = switch (try ty.abiAlignmentAdvanced(mod, strat)) { |
| | 2684 | .scalar => |x| x, |
| | 2685 | .val => return AbiSizeAdvanced{ |
| | 2686 | .val = try Value.Tag.lazy_size.create(strat.lazy, ty), |
| | 2687 | }, |
| | 2688 | }; |
| | 2689 | const result = std.mem.alignForwardGeneric(u32, total_bytes, alignment); |
| | 2690 | return AbiSizeAdvanced{ .scalar = result }; |
| | 2691 | }, |
| 2721 | | 2692 | |
| 2722 | .error_union => { | 2693 | .opt_type => return ty.abiSizeAdvancedOptional(mod, strat), |
| 2723 | // This code needs to be kept in sync with the equivalent switch prong | 2694 | .error_union_type => @panic("TODO"), |
| 2724 | // in abiAlignmentAdvanced. | 2695 | .simple_type => |t| switch (t) { |
| 2725 | const data = ty.castTag(.error_union).?.data; | 2696 | .bool, |
| 2726 | const code_size = abiSize(Type.anyerror, mod); | 2697 | .atomic_order, |
| 2727 | if (!(data.payload.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { | 2698 | .atomic_rmw_op, |
| 2728 | error.NeedLazy => return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(strat.lazy, ty) }, | 2699 | .calling_convention, |
| 2729 | else => |e| return e, | 2700 | .address_space, |
| 2730 | })) { | 2701 | .float_mode, |
| 2731 | // Same as anyerror. | 2702 | .reduce_op, |
| 2732 | return AbiSizeAdvanced{ .scalar = code_size }; | 2703 | .call_modifier, |
| 2733 | } | 2704 | => return AbiSizeAdvanced{ .scalar = 1 }, |
| 2734 | const code_align = abiAlignment(Type.anyerror, mod); | 2705 | |
| 2735 | const payload_align = abiAlignment(data.payload, mod); | 2706 | .f16 => return AbiSizeAdvanced{ .scalar = 2 }, |
| 2736 | const payload_size = switch (try data.payload.abiSizeAdvanced(mod, strat)) { | 2707 | .f32 => return AbiSizeAdvanced{ .scalar = 4 }, |
| 2737 | .scalar => |elem_size| elem_size, | 2708 | .f64 => return AbiSizeAdvanced{ .scalar = 8 }, |
| 2738 | .val => switch (strat) { | 2709 | .f128 => return AbiSizeAdvanced{ .scalar = 16 }, |
| 2739 | .sema => unreachable, | 2710 | .f80 => switch (target.c_type_bit_size(.longdouble)) { |
| 2740 | .eager => unreachable, | 2711 | 80 => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) }, |
| 2741 | .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) }, | 2712 | else => { |
| | 2713 | const u80_ty: Type = .{ |
| | 2714 | .ip_index = .u80_type, |
| | 2715 | .legacy = undefined, |
| | 2716 | }; |
| | 2717 | return AbiSizeAdvanced{ .scalar = abiSize(u80_ty, mod) }; |
| | 2718 | }, |
| 2742 | }, | 2719 | }, |
| 2743 | }; | | |
| 2744 | | 2720 | |
| 2745 | var size: u64 = 0; | 2721 | .usize, |
| 2746 | if (code_align > payload_align) { | 2722 | .isize, |
| 2747 | size += code_size; | 2723 | .@"anyframe", |
| 2748 | size = std.mem.alignForwardGeneric(u64, size, payload_align); | 2724 | => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }, |
| 2749 | size += payload_size; | 2725 | |
| 2750 | size = std.mem.alignForwardGeneric(u64, size, code_align); | 2726 | .c_char => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.char) }, |
| 2751 | } else { | 2727 | .c_short => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.short) }, |
| 2752 | size += payload_size; | 2728 | .c_ushort => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ushort) }, |
| 2753 | size = std.mem.alignForwardGeneric(u64, size, code_align); | 2729 | .c_int => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.int) }, |
| 2754 | size += code_size; | 2730 | .c_uint => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.uint) }, |
| 2755 | size = std.mem.alignForwardGeneric(u64, size, payload_align); | 2731 | .c_long => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.long) }, |
| 2756 | } | 2732 | .c_ulong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulong) }, |
| 2757 | return AbiSizeAdvanced{ .scalar = size }; | 2733 | .c_longlong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longlong) }, |
| | 2734 | .c_ulonglong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulonglong) }, |
| | 2735 | .c_longdouble => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) }, |
| | 2736 | |
| | 2737 | .anyopaque, |
| | 2738 | .void, |
| | 2739 | .type, |
| | 2740 | .comptime_int, |
| | 2741 | .comptime_float, |
| | 2742 | .null, |
| | 2743 | .undefined, |
| | 2744 | .enum_literal, |
| | 2745 | => return AbiSizeAdvanced{ .scalar = 0 }, |
| | 2746 | |
| | 2747 | // TODO revisit this when we have the concept of the error tag type |
| | 2748 | .anyerror => return AbiSizeAdvanced{ .scalar = 2 }, |
| | 2749 | |
| | 2750 | .prefetch_options => unreachable, // missing call to resolveTypeFields |
| | 2751 | .export_options => unreachable, // missing call to resolveTypeFields |
| | 2752 | .extern_options => unreachable, // missing call to resolveTypeFields |
| | 2753 | |
| | 2754 | .type_info => unreachable, |
| | 2755 | .noreturn => unreachable, |
| | 2756 | .generic_poison => unreachable, |
| | 2757 | .var_args_param => unreachable, |
| | 2758 | }, |
| | 2759 | .struct_type => @panic("TODO"), |
| | 2760 | .union_type => @panic("TODO"), |
| | 2761 | .simple_value => unreachable, |
| | 2762 | .extern_func => unreachable, |
| | 2763 | .int => unreachable, |
| | 2764 | .enum_tag => unreachable, // it's a value, not a type |
| 2758 | }, | 2765 | }, |
| 2759 | } | 2766 | } |
| 2760 | } | 2767 | } |
| ... | @@ -2929,7 +2936,6 @@ pub const Type = struct { | ... | @@ -2929,7 +2936,6 @@ pub const Type = struct { |
| 2929 | switch (ty.tag()) { | 2936 | switch (ty.tag()) { |
| 2930 | .function => unreachable, // represents machine code; not a pointer | 2937 | .function => unreachable, // represents machine code; not a pointer |
| 2931 | .empty_struct => unreachable, | 2938 | .empty_struct => unreachable, |
| 2932 | .empty_struct_literal => unreachable, | | |
| 2933 | .inferred_alloc_const => unreachable, | 2939 | .inferred_alloc_const => unreachable, |
| 2934 | .inferred_alloc_mut => unreachable, | 2940 | .inferred_alloc_mut => unreachable, |
| 2935 | .@"opaque" => unreachable, | 2941 | .@"opaque" => unreachable, |
| ... | @@ -3490,12 +3496,16 @@ pub const Type = struct { | ... | @@ -3490,12 +3496,16 @@ pub const Type = struct { |
| 3490 | } | 3496 | } |
| 3491 | | 3497 | |
| 3492 | pub fn containerLayout(ty: Type) std.builtin.Type.ContainerLayout { | 3498 | pub fn containerLayout(ty: Type) std.builtin.Type.ContainerLayout { |
| 3493 | return switch (ty.tag()) { | 3499 | return switch (ty.ip_index) { |
| 3494 | .tuple, .empty_struct_literal, .anon_struct => .Auto, | 3500 | .empty_struct_type => .Auto, |
| 3495 | .@"struct" => ty.castTag(.@"struct").?.data.layout, | 3501 | .none => switch (ty.tag()) { |
| 3496 | .@"union" => ty.castTag(.@"union").?.data.layout, | 3502 | .tuple, .anon_struct => .Auto, |
| 3497 | .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.layout, | 3503 | .@"struct" => ty.castTag(.@"struct").?.data.layout, |
| 3498 | .union_tagged => ty.castTag(.union_tagged).?.data.layout, | 3504 | .@"union" => ty.castTag(.@"union").?.data.layout, |
| | 3505 | .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.layout, |
| | 3506 | .union_tagged => ty.castTag(.union_tagged).?.data.layout, |
| | 3507 | else => unreachable, |
| | 3508 | }, |
| 3499 | else => unreachable, | 3509 | else => unreachable, |
| 3500 | }; | 3510 | }; |
| 3501 | } | 3511 | } |
| ... | @@ -3610,13 +3620,14 @@ pub const Type = struct { | ... | @@ -3610,13 +3620,14 @@ pub const Type = struct { |
| 3610 | | 3620 | |
| 3611 | pub fn arrayLenIp(ty: Type, ip: InternPool) u64 { | 3621 | pub fn arrayLenIp(ty: Type, ip: InternPool) u64 { |
| 3612 | return switch (ty.ip_index) { | 3622 | return switch (ty.ip_index) { |
| | 3623 | .empty_struct_type => 0, |
| 3613 | .none => switch (ty.tag()) { | 3624 | .none => switch (ty.tag()) { |
| 3614 | .array => ty.castTag(.array).?.data.len, | 3625 | .array => ty.castTag(.array).?.data.len, |
| 3615 | .array_sentinel => ty.castTag(.array_sentinel).?.data.len, | 3626 | .array_sentinel => ty.castTag(.array_sentinel).?.data.len, |
| 3616 | .tuple => ty.castTag(.tuple).?.data.types.len, | 3627 | .tuple => ty.castTag(.tuple).?.data.types.len, |
| 3617 | .anon_struct => ty.castTag(.anon_struct).?.data.types.len, | 3628 | .anon_struct => ty.castTag(.anon_struct).?.data.types.len, |
| 3618 | .@"struct" => ty.castTag(.@"struct").?.data.fields.count(), | 3629 | .@"struct" => ty.castTag(.@"struct").?.data.fields.count(), |
| 3619 | .empty_struct, .empty_struct_literal => 0, | 3630 | .empty_struct => 0, |
| 3620 | | 3631 | |
| 3621 | else => unreachable, | 3632 | else => unreachable, |
| 3622 | }, | 3633 | }, |
| ... | @@ -3649,10 +3660,10 @@ pub const Type = struct { | ... | @@ -3649,10 +3660,10 @@ pub const Type = struct { |
| 3649 | /// Asserts the type is an array, pointer or vector. | 3660 | /// Asserts the type is an array, pointer or vector. |
| 3650 | pub fn sentinel(ty: Type, mod: *const Module) ?Value { | 3661 | pub fn sentinel(ty: Type, mod: *const Module) ?Value { |
| 3651 | return switch (ty.ip_index) { | 3662 | return switch (ty.ip_index) { |
| | 3663 | .empty_struct_type => null, |
| 3652 | .none => switch (ty.tag()) { | 3664 | .none => switch (ty.tag()) { |
| 3653 | .array, | 3665 | .array, |
| 3654 | .tuple, | 3666 | .tuple, |
| 3655 | .empty_struct_literal, | | |
| 3656 | .@"struct", | 3667 | .@"struct", |
| 3657 | => null, | 3668 | => null, |
| 3658 | | 3669 | |
| ... | @@ -3951,197 +3962,200 @@ pub const Type = struct { | ... | @@ -3951,197 +3962,200 @@ pub const Type = struct { |
| 3951 | pub fn onePossibleValue(starting_type: Type, mod: *Module) !?Value { | 3962 | pub fn onePossibleValue(starting_type: Type, mod: *Module) !?Value { |
| 3952 | var ty = starting_type; | 3963 | var ty = starting_type; |
| 3953 | | 3964 | |
| 3954 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { | 3965 | while (true) switch (ty.ip_index) { |
| 3955 | .int_type => |int_type| { | 3966 | .empty_struct_type => return Value.empty_struct, |
| 3956 | if (int_type.bits == 0) { | 3967 | |
| 3957 | return try mod.intValue(ty, 0); | 3968 | .none => switch (ty.tag()) { |
| 3958 | } else { | 3969 | .error_union, |
| 3959 | return null; | 3970 | .error_set_single, |
| 3960 | } | 3971 | .error_set, |
| 3961 | }, | 3972 | .error_set_merged, |
| 3962 | .ptr_type => return null, | 3973 | .function, |
| 3963 | .array_type => |array_type| { | 3974 | .array_sentinel, |
| 3964 | if (array_type.len == 0) | 3975 | .error_set_inferred, |
| 3965 | return Value.initTag(.empty_array); | 3976 | .@"opaque", |
| 3966 | if ((try array_type.child.toType().onePossibleValue(mod)) != null) | 3977 | .anyframe_T, |
| 3967 | return Value.initTag(.the_only_possible_value); | 3978 | .pointer, |
| 3968 | return null; | | |
| 3969 | }, | | |
| 3970 | .vector_type => |vector_type| { | | |
| 3971 | if (vector_type.len == 0) return Value.initTag(.empty_array); | | |
| 3972 | if (try vector_type.child.toType().onePossibleValue(mod)) |v| return v; | | |
| 3973 | return null; | | |
| 3974 | }, | | |
| 3975 | .opt_type => |child| { | | |
| 3976 | if (child.toType().isNoReturn()) { | | |
| 3977 | return Value.null; | | |
| 3978 | } else { | | |
| 3979 | return null; | | |
| 3980 | } | | |
| 3981 | }, | | |
| 3982 | .error_union_type => return null, | | |
| 3983 | .simple_type => |t| switch (t) { | | |
| 3984 | .f16, | | |
| 3985 | .f32, | | |
| 3986 | .f64, | | |
| 3987 | .f80, | | |
| 3988 | .f128, | | |
| 3989 | .usize, | | |
| 3990 | .isize, | | |
| 3991 | .c_char, | | |
| 3992 | .c_short, | | |
| 3993 | .c_ushort, | | |
| 3994 | .c_int, | | |
| 3995 | .c_uint, | | |
| 3996 | .c_long, | | |
| 3997 | .c_ulong, | | |
| 3998 | .c_longlong, | | |
| 3999 | .c_ulonglong, | | |
| 4000 | .c_longdouble, | | |
| 4001 | .anyopaque, | | |
| 4002 | .bool, | | |
| 4003 | .type, | | |
| 4004 | .anyerror, | | |
| 4005 | .comptime_int, | | |
| 4006 | .comptime_float, | | |
| 4007 | .@"anyframe", | | |
| 4008 | .enum_literal, | | |
| 4009 | .atomic_order, | | |
| 4010 | .atomic_rmw_op, | | |
| 4011 | .calling_convention, | | |
| 4012 | .address_space, | | |
| 4013 | .float_mode, | | |
| 4014 | .reduce_op, | | |
| 4015 | .call_modifier, | | |
| 4016 | .prefetch_options, | | |
| 4017 | .export_options, | | |
| 4018 | .extern_options, | | |
| 4019 | .type_info, | | |
| 4020 | => return null, | 3979 | => return null, |
| 4021 | | 3980 | |
| 4022 | .void => return Value.void, | 3981 | .optional => { |
| 4023 | .noreturn => return Value.@"unreachable", | 3982 | const child_ty = ty.optionalChild(mod); |
| 4024 | .null => return Value.null, | 3983 | if (child_ty.isNoReturn()) { |
| 4025 | .undefined => return Value.undef, | 3984 | return Value.null; |
| | 3985 | } else { |
| | 3986 | return null; |
| | 3987 | } |
| | 3988 | }, |
| 4026 | | 3989 | |
| 4027 | .generic_poison => unreachable, | 3990 | .@"struct" => { |
| 4028 | .var_args_param => unreachable, | 3991 | const s = ty.castTag(.@"struct").?.data; |
| 4029 | }, | 3992 | assert(s.haveFieldTypes()); |
| 4030 | .struct_type => @panic("TODO"), | 3993 | for (s.fields.values()) |field| { |
| 4031 | .union_type => @panic("TODO"), | 3994 | if (field.is_comptime) continue; |
| 4032 | .simple_value => unreachable, | 3995 | if ((try field.ty.onePossibleValue(mod)) != null) continue; |
| 4033 | .extern_func => unreachable, | 3996 | return null; |
| 4034 | .int => unreachable, | 3997 | } |
| 4035 | .enum_tag => unreachable, // it's a value, not a type | 3998 | return Value.empty_struct; |
| 4036 | }; | 3999 | }, |
| 4037 | | 4000 | |
| 4038 | while (true) switch (ty.tag()) { | 4001 | .tuple, .anon_struct => { |
| 4039 | .error_union, | 4002 | const tuple = ty.tupleFields(); |
| 4040 | .error_set_single, | 4003 | for (tuple.values, 0..) |val, i| { |
| 4041 | .error_set, | 4004 | const is_comptime = val.ip_index != .unreachable_value; |
| 4042 | .error_set_merged, | 4005 | if (is_comptime) continue; |
| 4043 | .function, | 4006 | if ((try tuple.types[i].onePossibleValue(mod)) != null) continue; |
| 4044 | .array_sentinel, | 4007 | return null; |
| 4045 | .error_set_inferred, | 4008 | } |
| 4046 | .@"opaque", | 4009 | return Value.empty_struct; |
| 4047 | .anyframe_T, | 4010 | }, |
| 4048 | .pointer, | 4011 | |
| 4049 | => return null, | 4012 | .enum_numbered => { |
| | 4013 | const enum_numbered = ty.castTag(.enum_numbered).?.data; |
| | 4014 | // An explicit tag type is always provided for enum_numbered. |
| | 4015 | if (enum_numbered.tag_ty.hasRuntimeBits(mod)) { |
| | 4016 | return null; |
| | 4017 | } |
| | 4018 | assert(enum_numbered.fields.count() == 1); |
| | 4019 | return enum_numbered.values.keys()[0]; |
| | 4020 | }, |
| | 4021 | .enum_full => { |
| | 4022 | const enum_full = ty.castTag(.enum_full).?.data; |
| | 4023 | if (enum_full.tag_ty.hasRuntimeBits(mod)) { |
| | 4024 | return null; |
| | 4025 | } |
| | 4026 | switch (enum_full.fields.count()) { |
| | 4027 | 0 => return Value.@"unreachable", |
| | 4028 | 1 => if (enum_full.values.count() == 0) { |
| | 4029 | return try mod.intValue(ty, 0); // auto-numbered |
| | 4030 | } else { |
| | 4031 | return enum_full.values.keys()[0]; |
| | 4032 | }, |
| | 4033 | else => return null, |
| | 4034 | } |
| | 4035 | }, |
| | 4036 | .enum_simple => { |
| | 4037 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| | 4038 | switch (enum_simple.fields.count()) { |
| | 4039 | 0 => return Value.@"unreachable", |
| | 4040 | 1 => return try mod.intValue(ty, 0), |
| | 4041 | else => return null, |
| | 4042 | } |
| | 4043 | }, |
| | 4044 | .enum_nonexhaustive => { |
| | 4045 | const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty; |
| | 4046 | if (!tag_ty.hasRuntimeBits(mod)) { |
| | 4047 | return try mod.intValue(ty, 0); |
| | 4048 | } else { |
| | 4049 | return null; |
| | 4050 | } |
| | 4051 | }, |
| | 4052 | .@"union", .union_safety_tagged, .union_tagged => { |
| | 4053 | const union_obj = ty.cast(Payload.Union).?.data; |
| | 4054 | const tag_val = (try union_obj.tag_ty.onePossibleValue(mod)) orelse return null; |
| | 4055 | if (union_obj.fields.count() == 0) return Value.@"unreachable"; |
| | 4056 | const only_field = union_obj.fields.values()[0]; |
| | 4057 | const val_val = (try only_field.ty.onePossibleValue(mod)) orelse return null; |
| | 4058 | _ = tag_val; |
| | 4059 | _ = val_val; |
| | 4060 | return Value.empty_struct; |
| | 4061 | }, |
| 4050 | | 4062 | |
| 4051 | .optional => { | 4063 | .empty_struct => return Value.empty_struct, |
| 4052 | const child_ty = ty.optionalChild(mod); | | |
| 4053 | if (child_ty.isNoReturn()) { | | |
| 4054 | return Value.null; | | |
| 4055 | } else { | | |
| 4056 | return null; | | |
| 4057 | } | | |
| 4058 | }, | | |
| 4059 | | 4064 | |
| 4060 | .@"struct" => { | 4065 | .array => { |
| 4061 | const s = ty.castTag(.@"struct").?.data; | 4066 | if (ty.arrayLen(mod) == 0) |
| 4062 | assert(s.haveFieldTypes()); | 4067 | return Value.initTag(.empty_array); |
| 4063 | for (s.fields.values()) |field| { | 4068 | if ((try ty.childType(mod).onePossibleValue(mod)) != null) |
| 4064 | if (field.is_comptime) continue; | 4069 | return Value.initTag(.the_only_possible_value); |
| 4065 | if ((try field.ty.onePossibleValue(mod)) != null) continue; | | |
| 4066 | return null; | 4070 | return null; |
| 4067 | } | 4071 | }, |
| 4068 | return Value.initTag(.empty_struct_value); | | |
| 4069 | }, | | |
| 4070 | | 4072 | |
| 4071 | .tuple, .anon_struct => { | 4073 | .inferred_alloc_const => unreachable, |
| 4072 | const tuple = ty.tupleFields(); | 4074 | .inferred_alloc_mut => unreachable, |
| 4073 | for (tuple.values, 0..) |val, i| { | | |
| 4074 | const is_comptime = val.ip_index != .unreachable_value; | | |
| 4075 | if (is_comptime) continue; | | |
| 4076 | if ((try tuple.types[i].onePossibleValue(mod)) != null) continue; | | |
| 4077 | return null; | | |
| 4078 | } | | |
| 4079 | return Value.initTag(.empty_struct_value); | | |
| 4080 | }, | 4075 | }, |
| 4081 | | 4076 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 4082 | .enum_numbered => { | 4077 | .int_type => |int_type| { |
| 4083 | const enum_numbered = ty.castTag(.enum_numbered).?.data; | 4078 | if (int_type.bits == 0) { |
| 4084 | // An explicit tag type is always provided for enum_numbered. | 4079 | return try mod.intValue(ty, 0); |
| 4085 | if (enum_numbered.tag_ty.hasRuntimeBits(mod)) { | 4080 | } else { |
| | 4081 | return null; |
| | 4082 | } |
| | 4083 | }, |
| | 4084 | .ptr_type => return null, |
| | 4085 | .array_type => |array_type| { |
| | 4086 | if (array_type.len == 0) |
| | 4087 | return Value.initTag(.empty_array); |
| | 4088 | if ((try array_type.child.toType().onePossibleValue(mod)) != null) |
| | 4089 | return Value.initTag(.the_only_possible_value); |
| 4086 | return null; | 4090 | return null; |
| 4087 | } | 4091 | }, |
| 4088 | assert(enum_numbered.fields.count() == 1); | 4092 | .vector_type => |vector_type| { |
| 4089 | return enum_numbered.values.keys()[0]; | 4093 | if (vector_type.len == 0) return Value.initTag(.empty_array); |
| 4090 | }, | 4094 | if (try vector_type.child.toType().onePossibleValue(mod)) |v| return v; |
| 4091 | .enum_full => { | | |
| 4092 | const enum_full = ty.castTag(.enum_full).?.data; | | |
| 4093 | if (enum_full.tag_ty.hasRuntimeBits(mod)) { | | |
| 4094 | return null; | 4095 | return null; |
| 4095 | } | 4096 | }, |
| 4096 | switch (enum_full.fields.count()) { | 4097 | .opt_type => |child| { |
| 4097 | 0 => return Value.@"unreachable", | 4098 | if (child.toType().isNoReturn()) { |
| 4098 | 1 => if (enum_full.values.count() == 0) { | 4099 | return Value.null; |
| 4099 | return try mod.intValue(ty, 0); // auto-numbered | | |
| 4100 | } else { | 4100 | } else { |
| 4101 | return enum_full.values.keys()[0]; | 4101 | return null; |
| 4102 | }, | 4102 | } |
| 4103 | else => return null, | 4103 | }, |
| 4104 | } | 4104 | .error_union_type => return null, |
| 4105 | }, | 4105 | .simple_type => |t| switch (t) { |
| 4106 | .enum_simple => { | 4106 | .f16, |
| 4107 | const enum_simple = ty.castTag(.enum_simple).?.data; | 4107 | .f32, |
| 4108 | switch (enum_simple.fields.count()) { | 4108 | .f64, |
| 4109 | 0 => return Value.@"unreachable", | 4109 | .f80, |
| 4110 | 1 => return try mod.intValue(ty, 0), | 4110 | .f128, |
| 4111 | else => return null, | 4111 | .usize, |
| 4112 | } | 4112 | .isize, |
| 4113 | }, | 4113 | .c_char, |
| 4114 | .enum_nonexhaustive => { | 4114 | .c_short, |
| 4115 | const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty; | 4115 | .c_ushort, |
| 4116 | if (!tag_ty.hasRuntimeBits(mod)) { | 4116 | .c_int, |
| 4117 | return try mod.intValue(ty, 0); | 4117 | .c_uint, |
| 4118 | } else { | 4118 | .c_long, |
| 4119 | return null; | 4119 | .c_ulong, |
| 4120 | } | 4120 | .c_longlong, |
| 4121 | }, | 4121 | .c_ulonglong, |
| 4122 | .@"union", .union_safety_tagged, .union_tagged => { | 4122 | .c_longdouble, |
| 4123 | const union_obj = ty.cast(Payload.Union).?.data; | 4123 | .anyopaque, |
| 4124 | const tag_val = (try union_obj.tag_ty.onePossibleValue(mod)) orelse return null; | 4124 | .bool, |
| 4125 | if (union_obj.fields.count() == 0) return Value.@"unreachable"; | 4125 | .type, |
| 4126 | const only_field = union_obj.fields.values()[0]; | 4126 | .anyerror, |
| 4127 | const val_val = (try only_field.ty.onePossibleValue(mod)) orelse return null; | 4127 | .comptime_int, |
| 4128 | _ = tag_val; | 4128 | .comptime_float, |
| 4129 | _ = val_val; | 4129 | .@"anyframe", |
| 4130 | return Value.initTag(.empty_struct_value); | 4130 | .enum_literal, |
| 4131 | }, | 4131 | .atomic_order, |
| | 4132 | .atomic_rmw_op, |
| | 4133 | .calling_convention, |
| | 4134 | .address_space, |
| | 4135 | .float_mode, |
| | 4136 | .reduce_op, |
| | 4137 | .call_modifier, |
| | 4138 | .prefetch_options, |
| | 4139 | .export_options, |
| | 4140 | .extern_options, |
| | 4141 | .type_info, |
| | 4142 | => return null, |
| 4132 | | 4143 | |
| 4133 | .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value), | 4144 | .void => return Value.void, |
| | 4145 | .noreturn => return Value.@"unreachable", |
| | 4146 | .null => return Value.null, |
| | 4147 | .undefined => return Value.undef, |
| 4134 | | 4148 | |
| 4135 | .array => { | 4149 | .generic_poison => unreachable, |
| 4136 | if (ty.arrayLen(mod) == 0) | 4150 | .var_args_param => unreachable, |
| 4137 | return Value.initTag(.empty_array); | 4151 | }, |
| 4138 | if ((try ty.childType(mod).onePossibleValue(mod)) != null) | 4152 | .struct_type => @panic("TODO"), |
| 4139 | return Value.initTag(.the_only_possible_value); | 4153 | .union_type => @panic("TODO"), |
| 4140 | return null; | 4154 | .simple_value => unreachable, |
| | 4155 | .extern_func => unreachable, |
| | 4156 | .int => unreachable, |
| | 4157 | .enum_tag => unreachable, // it's a value, not a type |
| 4141 | }, | 4158 | }, |
| 4142 | | | |
| 4143 | .inferred_alloc_const => unreachable, | | |
| 4144 | .inferred_alloc_mut => unreachable, | | |
| 4145 | }; | 4159 | }; |
| 4146 | } | 4160 | } |
| 4147 | | 4161 | |
| ... | @@ -4150,159 +4164,161 @@ pub const Type = struct { | ... | @@ -4150,159 +4164,161 @@ pub const Type = struct { |
| 4150 | /// TODO merge these implementations together with the "advanced" pattern seen | 4164 | /// TODO merge these implementations together with the "advanced" pattern seen |
| 4151 | /// elsewhere in this file. | 4165 | /// elsewhere in this file. |
| 4152 | pub fn comptimeOnly(ty: Type, mod: *const Module) bool { | 4166 | pub fn comptimeOnly(ty: Type, mod: *const Module) bool { |
| 4153 | if (ty.ip_index != .none) return switch (mod.intern_pool.indexToKey(ty.ip_index)) { | 4167 | return switch (ty.ip_index) { |
| 4154 | .int_type => false, | 4168 | .empty_struct_type => false, |
| 4155 | .ptr_type => |ptr_type| { | | |
| 4156 | const child_ty = ptr_type.elem_type.toType(); | | |
| 4157 | if (child_ty.zigTypeTag(mod) == .Fn) { | | |
| 4158 | return false; | | |
| 4159 | } else { | | |
| 4160 | return child_ty.comptimeOnly(mod); | | |
| 4161 | } | | |
| 4162 | }, | | |
| 4163 | .array_type => |array_type| array_type.child.toType().comptimeOnly(mod), | | |
| 4164 | .vector_type => |vector_type| vector_type.child.toType().comptimeOnly(mod), | | |
| 4165 | .opt_type => |child| child.toType().comptimeOnly(mod), | | |
| 4166 | .error_union_type => |error_union_type| error_union_type.payload_type.toType().comptimeOnly(mod), | | |
| 4167 | .simple_type => |t| switch (t) { | | |
| 4168 | .f16, | | |
| 4169 | .f32, | | |
| 4170 | .f64, | | |
| 4171 | .f80, | | |
| 4172 | .f128, | | |
| 4173 | .usize, | | |
| 4174 | .isize, | | |
| 4175 | .c_char, | | |
| 4176 | .c_short, | | |
| 4177 | .c_ushort, | | |
| 4178 | .c_int, | | |
| 4179 | .c_uint, | | |
| 4180 | .c_long, | | |
| 4181 | .c_ulong, | | |
| 4182 | .c_longlong, | | |
| 4183 | .c_ulonglong, | | |
| 4184 | .c_longdouble, | | |
| 4185 | .anyopaque, | | |
| 4186 | .bool, | | |
| 4187 | .void, | | |
| 4188 | .anyerror, | | |
| 4189 | .@"anyframe", | | |
| 4190 | .noreturn, | | |
| 4191 | .generic_poison, | | |
| 4192 | .atomic_order, | | |
| 4193 | .atomic_rmw_op, | | |
| 4194 | .calling_convention, | | |
| 4195 | .address_space, | | |
| 4196 | .float_mode, | | |
| 4197 | .reduce_op, | | |
| 4198 | .call_modifier, | | |
| 4199 | .prefetch_options, | | |
| 4200 | .export_options, | | |
| 4201 | .extern_options, | | |
| 4202 | => false, | | |
| 4203 | | 4169 | |
| 4204 | .type, | 4170 | .none => switch (ty.tag()) { |
| 4205 | .comptime_int, | 4171 | .empty_struct, |
| 4206 | .comptime_float, | 4172 | .error_set, |
| 4207 | .null, | 4173 | .error_set_single, |
| 4208 | .undefined, | 4174 | .error_set_inferred, |
| 4209 | .enum_literal, | 4175 | .error_set_merged, |
| 4210 | .type_info, | 4176 | .@"opaque", |
| 4211 | => true, | 4177 | .enum_simple, |
| | 4178 | => false, |
| 4212 | | 4179 | |
| 4213 | .var_args_param => unreachable, | 4180 | // These are function bodies, not function pointers. |
| 4214 | }, | 4181 | .function => true, |
| 4215 | .struct_type => @panic("TODO"), | | |
| 4216 | .union_type => @panic("TODO"), | | |
| 4217 | .simple_value => unreachable, | | |
| 4218 | .extern_func => unreachable, | | |
| 4219 | .int => unreachable, | | |
| 4220 | .enum_tag => unreachable, // it's a value, not a type | | |
| 4221 | }; | | |
| 4222 | | 4182 | |
| 4223 | return switch (ty.tag()) { | 4183 | .inferred_alloc_mut => unreachable, |
| 4224 | .empty_struct_literal, | 4184 | .inferred_alloc_const => unreachable, |
| 4225 | .empty_struct, | | |
| 4226 | .error_set, | | |
| 4227 | .error_set_single, | | |
| 4228 | .error_set_inferred, | | |
| 4229 | .error_set_merged, | | |
| 4230 | .@"opaque", | | |
| 4231 | .enum_simple, | | |
| 4232 | => false, | | |
| 4233 | | 4185 | |
| 4234 | // These are function bodies, not function pointers. | 4186 | .array, |
| 4235 | .function => true, | 4187 | .array_sentinel, |
| | 4188 | => return ty.childType(mod).comptimeOnly(mod), |
| 4236 | | 4189 | |
| 4237 | .inferred_alloc_mut => unreachable, | 4190 | .pointer => { |
| 4238 | .inferred_alloc_const => unreachable, | 4191 | const child_ty = ty.childType(mod); |
| | 4192 | if (child_ty.zigTypeTag(mod) == .Fn) { |
| | 4193 | return false; |
| | 4194 | } else { |
| | 4195 | return child_ty.comptimeOnly(mod); |
| | 4196 | } |
| | 4197 | }, |
| 4239 | | 4198 | |
| 4240 | .array, | 4199 | .optional => { |
| 4241 | .array_sentinel, | 4200 | return ty.optionalChild(mod).comptimeOnly(mod); |
| 4242 | => return ty.childType(mod).comptimeOnly(mod), | 4201 | }, |
| 4243 | | 4202 | |
| 4244 | .pointer => { | 4203 | .tuple, .anon_struct => { |
| 4245 | const child_ty = ty.childType(mod); | 4204 | const tuple = ty.tupleFields(); |
| 4246 | if (child_ty.zigTypeTag(mod) == .Fn) { | 4205 | for (tuple.types, 0..) |field_ty, i| { |
| | 4206 | const have_comptime_val = tuple.values[i].ip_index != .unreachable_value; |
| | 4207 | if (!have_comptime_val and field_ty.comptimeOnly(mod)) return true; |
| | 4208 | } |
| 4247 | return false; | 4209 | return false; |
| 4248 | } else { | 4210 | }, |
| 4249 | return child_ty.comptimeOnly(mod); | | |
| 4250 | } | | |
| 4251 | }, | | |
| 4252 | | 4211 | |
| 4253 | .optional => { | 4212 | .@"struct" => { |
| 4254 | return ty.optionalChild(mod).comptimeOnly(mod); | 4213 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 4255 | }, | 4214 | switch (struct_obj.requires_comptime) { |
| | 4215 | .wip, .unknown => { |
| | 4216 | // Return false to avoid incorrect dependency loops. |
| | 4217 | // This will be handled correctly once merged with |
| | 4218 | // `Sema.typeRequiresComptime`. |
| | 4219 | return false; |
| | 4220 | }, |
| | 4221 | .no => return false, |
| | 4222 | .yes => return true, |
| | 4223 | } |
| | 4224 | }, |
| 4256 | | 4225 | |
| 4257 | .tuple, .anon_struct => { | 4226 | .@"union", .union_safety_tagged, .union_tagged => { |
| 4258 | const tuple = ty.tupleFields(); | 4227 | const union_obj = ty.cast(Type.Payload.Union).?.data; |
| 4259 | for (tuple.types, 0..) |field_ty, i| { | 4228 | switch (union_obj.requires_comptime) { |
| 4260 | const have_comptime_val = tuple.values[i].ip_index != .unreachable_value; | 4229 | .wip, .unknown => { |
| 4261 | if (!have_comptime_val and field_ty.comptimeOnly(mod)) return true; | 4230 | // Return false to avoid incorrect dependency loops. |
| 4262 | } | 4231 | // This will be handled correctly once merged with |
| 4263 | return false; | 4232 | // `Sema.typeRequiresComptime`. |
| 4264 | }, | 4233 | return false; |
| | 4234 | }, |
| | 4235 | .no => return false, |
| | 4236 | .yes => return true, |
| | 4237 | } |
| | 4238 | }, |
| 4265 | | 4239 | |
| 4266 | .@"struct" => { | 4240 | .error_union => return ty.errorUnionPayload().comptimeOnly(mod), |
| 4267 | const struct_obj = ty.castTag(.@"struct").?.data; | 4241 | .anyframe_T => { |
| 4268 | switch (struct_obj.requires_comptime) { | 4242 | const child_ty = ty.castTag(.anyframe_T).?.data; |
| 4269 | .wip, .unknown => { | 4243 | return child_ty.comptimeOnly(mod); |
| 4270 | // Return false to avoid incorrect dependency loops. | 4244 | }, |
| 4271 | // This will be handled correctly once merged with | 4245 | .enum_numbered => { |
| 4272 | // `Sema.typeRequiresComptime`. | 4246 | const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty; |
| 4273 | return false; | 4247 | return tag_ty.comptimeOnly(mod); |
| 4274 | }, | 4248 | }, |
| 4275 | .no => return false, | 4249 | .enum_full, .enum_nonexhaustive => { |
| 4276 | .yes => return true, | 4250 | const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty; |
| 4277 | } | 4251 | return tag_ty.comptimeOnly(mod); |
| | 4252 | }, |
| 4278 | }, | 4253 | }, |
| 4279 | | 4254 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 4280 | .@"union", .union_safety_tagged, .union_tagged => { | 4255 | .int_type => false, |
| 4281 | const union_obj = ty.cast(Type.Payload.Union).?.data; | 4256 | .ptr_type => |ptr_type| { |
| 4282 | switch (union_obj.requires_comptime) { | 4257 | const child_ty = ptr_type.elem_type.toType(); |
| 4283 | .wip, .unknown => { | 4258 | if (child_ty.zigTypeTag(mod) == .Fn) { |
| 4284 | // Return false to avoid incorrect dependency loops. | | |
| 4285 | // This will be handled correctly once merged with | | |
| 4286 | // `Sema.typeRequiresComptime`. | | |
| 4287 | return false; | 4259 | return false; |
| 4288 | }, | 4260 | } else { |
| 4289 | .no => return false, | 4261 | return child_ty.comptimeOnly(mod); |
| 4290 | .yes => return true, | 4262 | } |
| 4291 | } | 4263 | }, |
| 4292 | }, | 4264 | .array_type => |array_type| array_type.child.toType().comptimeOnly(mod), |
| | 4265 | .vector_type => |vector_type| vector_type.child.toType().comptimeOnly(mod), |
| | 4266 | .opt_type => |child| child.toType().comptimeOnly(mod), |
| | 4267 | .error_union_type => |error_union_type| error_union_type.payload_type.toType().comptimeOnly(mod), |
| | 4268 | .simple_type => |t| switch (t) { |
| | 4269 | .f16, |
| | 4270 | .f32, |
| | 4271 | .f64, |
| | 4272 | .f80, |
| | 4273 | .f128, |
| | 4274 | .usize, |
| | 4275 | .isize, |
| | 4276 | .c_char, |
| | 4277 | .c_short, |
| | 4278 | .c_ushort, |
| | 4279 | .c_int, |
| | 4280 | .c_uint, |
| | 4281 | .c_long, |
| | 4282 | .c_ulong, |
| | 4283 | .c_longlong, |
| | 4284 | .c_ulonglong, |
| | 4285 | .c_longdouble, |
| | 4286 | .anyopaque, |
| | 4287 | .bool, |
| | 4288 | .void, |
| | 4289 | .anyerror, |
| | 4290 | .@"anyframe", |
| | 4291 | .noreturn, |
| | 4292 | .generic_poison, |
| | 4293 | .atomic_order, |
| | 4294 | .atomic_rmw_op, |
| | 4295 | .calling_convention, |
| | 4296 | .address_space, |
| | 4297 | .float_mode, |
| | 4298 | .reduce_op, |
| | 4299 | .call_modifier, |
| | 4300 | .prefetch_options, |
| | 4301 | .export_options, |
| | 4302 | .extern_options, |
| | 4303 | => false, |
| 4293 | | 4304 | |
| 4294 | .error_union => return ty.errorUnionPayload().comptimeOnly(mod), | 4305 | .type, |
| 4295 | .anyframe_T => { | 4306 | .comptime_int, |
| 4296 | const child_ty = ty.castTag(.anyframe_T).?.data; | 4307 | .comptime_float, |
| 4297 | return child_ty.comptimeOnly(mod); | 4308 | .null, |
| 4298 | }, | 4309 | .undefined, |
| 4299 | .enum_numbered => { | 4310 | .enum_literal, |
| 4300 | const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty; | 4311 | .type_info, |
| 4301 | return tag_ty.comptimeOnly(mod); | 4312 | => true, |
| 4302 | }, | 4313 | |
| 4303 | .enum_full, .enum_nonexhaustive => { | 4314 | .var_args_param => unreachable, |
| 4304 | const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty; | 4315 | }, |
| 4305 | return tag_ty.comptimeOnly(mod); | 4316 | .struct_type => @panic("TODO"), |
| | 4317 | .union_type => @panic("TODO"), |
| | 4318 | .simple_value => unreachable, |
| | 4319 | .extern_func => unreachable, |
| | 4320 | .int => unreachable, |
| | 4321 | .enum_tag => unreachable, // it's a value, not a type |
| 4306 | }, | 4322 | }, |
| 4307 | }; | 4323 | }; |
| 4308 | } | 4324 | } |
| ... | @@ -4575,15 +4591,19 @@ pub const Type = struct { | ... | @@ -4575,15 +4591,19 @@ pub const Type = struct { |
| 4575 | } | 4591 | } |
| 4576 | | 4592 | |
| 4577 | pub fn structFields(ty: Type) Module.Struct.Fields { | 4593 | pub fn structFields(ty: Type) Module.Struct.Fields { |
| 4578 | switch (ty.tag()) { | 4594 | return switch (ty.ip_index) { |
| 4579 | .empty_struct, .empty_struct_literal => return .{}, | 4595 | .empty_struct_type => .{}, |
| 4580 | .@"struct" => { | 4596 | .none => switch (ty.tag()) { |
| 4581 | const struct_obj = ty.castTag(.@"struct").?.data; | 4597 | .empty_struct => .{}, |
| 4582 | assert(struct_obj.haveFieldTypes()); | 4598 | .@"struct" => { |
| 4583 | return struct_obj.fields; | 4599 | const struct_obj = ty.castTag(.@"struct").?.data; |
| | 4600 | assert(struct_obj.haveFieldTypes()); |
| | 4601 | return struct_obj.fields; |
| | 4602 | }, |
| | 4603 | else => unreachable, |
| 4584 | }, | 4604 | }, |
| 4585 | else => unreachable, | 4605 | else => unreachable, |
| 4586 | } | 4606 | }; |
| 4587 | } | 4607 | } |
| 4588 | | 4608 | |
| 4589 | pub fn structFieldName(ty: Type, field_index: usize) []const u8 { | 4609 | pub fn structFieldName(ty: Type, field_index: usize) []const u8 { |
| ... | @@ -4599,17 +4619,21 @@ pub const Type = struct { | ... | @@ -4599,17 +4619,21 @@ pub const Type = struct { |
| 4599 | } | 4619 | } |
| 4600 | | 4620 | |
| 4601 | pub fn structFieldCount(ty: Type) usize { | 4621 | pub fn structFieldCount(ty: Type) usize { |
| 4602 | switch (ty.tag()) { | 4622 | return switch (ty.ip_index) { |
| 4603 | .@"struct" => { | 4623 | .empty_struct_type => 0, |
| 4604 | const struct_obj = ty.castTag(.@"struct").?.data; | 4624 | .none => switch (ty.tag()) { |
| 4605 | assert(struct_obj.haveFieldTypes()); | 4625 | .@"struct" => { |
| 4606 | return struct_obj.fields.count(); | 4626 | const struct_obj = ty.castTag(.@"struct").?.data; |
| | 4627 | assert(struct_obj.haveFieldTypes()); |
| | 4628 | return struct_obj.fields.count(); |
| | 4629 | }, |
| | 4630 | .empty_struct => 0, |
| | 4631 | .tuple => ty.castTag(.tuple).?.data.types.len, |
| | 4632 | .anon_struct => ty.castTag(.anon_struct).?.data.types.len, |
| | 4633 | else => unreachable, |
| 4607 | }, | 4634 | }, |
| 4608 | .empty_struct, .empty_struct_literal => return 0, | | |
| 4609 | .tuple => return ty.castTag(.tuple).?.data.types.len, | | |
| 4610 | .anon_struct => return ty.castTag(.anon_struct).?.data.types.len, | | |
| 4611 | else => unreachable, | 4635 | else => unreachable, |
| 4612 | } | 4636 | }; |
| 4613 | } | 4637 | } |
| 4614 | | 4638 | |
| 4615 | /// Supports structs and unions. | 4639 | /// Supports structs and unions. |
| ... | @@ -4927,10 +4951,6 @@ pub const Type = struct { | ... | @@ -4927,10 +4951,6 @@ pub const Type = struct { |
| 4927 | return ty.ip_index == .generic_poison_type; | 4951 | return ty.ip_index == .generic_poison_type; |
| 4928 | } | 4952 | } |
| 4929 | | 4953 | |
| 4930 | pub fn isVarArgsParam(ty: Type) bool { | | |
| 4931 | return ty.ip_index == .none and ty.tag() == .var_args_param; | | |
| 4932 | } | | |
| 4933 | | | |
| 4934 | /// This enum does not directly correspond to `std.builtin.TypeId` because | 4954 | /// This enum does not directly correspond to `std.builtin.TypeId` because |
| 4935 | /// it has extra enum tags in it, as a way of using less memory. For example, | 4955 | /// it has extra enum tags in it, as a way of using less memory. For example, |
| 4936 | /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types | 4956 | /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types |
| ... | @@ -4938,8 +4958,6 @@ pub const Type = struct { | ... | @@ -4938,8 +4958,6 @@ pub const Type = struct { |
| 4938 | /// with different enum tags, because the the former requires more payload data than the latter. | 4958 | /// with different enum tags, because the the former requires more payload data than the latter. |
| 4939 | /// See `zigTypeTag` for the function that corresponds to `std.builtin.TypeId`. | 4959 | /// See `zigTypeTag` for the function that corresponds to `std.builtin.TypeId`. |
| 4940 | pub const Tag = enum(usize) { | 4960 | pub const Tag = enum(usize) { |
| 4941 | /// Same as `empty_struct` except it has an empty namespace. | | |
| 4942 | empty_struct_literal, | | |
| 4943 | /// This is a special value that tracks a set of types that have been stored | 4961 | /// This is a special value that tracks a set of types that have been stored |
| 4944 | /// to an inferred allocation. It does not support most of the normal type queries. | 4962 | /// to an inferred allocation. It does not support most of the normal type queries. |
| 4945 | /// However it does respond to `isConstPtr`, `ptrSize`, `zigTypeTag`, etc. | 4963 | /// However it does respond to `isConstPtr`, `ptrSize`, `zigTypeTag`, etc. |
| ... | @@ -4982,7 +5000,6 @@ pub const Type = struct { | ... | @@ -4982,7 +5000,6 @@ pub const Type = struct { |
| 4982 | return switch (t) { | 5000 | return switch (t) { |
| 4983 | .inferred_alloc_const, | 5001 | .inferred_alloc_const, |
| 4984 | .inferred_alloc_mut, | 5002 | .inferred_alloc_mut, |
| 4985 | .empty_struct_literal, | | |
| 4986 | => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"), | 5003 | => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"), |
| 4987 | | 5004 | |
| 4988 | .optional, | 5005 | .optional, |
| ... | @@ -5038,33 +5055,36 @@ pub const Type = struct { | ... | @@ -5038,33 +5055,36 @@ pub const Type = struct { |
| 5038 | | 5055 | |
| 5039 | pub fn isTuple(ty: Type) bool { | 5056 | pub fn isTuple(ty: Type) bool { |
| 5040 | return switch (ty.ip_index) { | 5057 | return switch (ty.ip_index) { |
| | 5058 | .empty_struct_type => true, |
| 5041 | .none => switch (ty.tag()) { | 5059 | .none => switch (ty.tag()) { |
| 5042 | .tuple, .empty_struct_literal => true, | 5060 | .tuple => true, |
| 5043 | .@"struct" => ty.castTag(.@"struct").?.data.is_tuple, | 5061 | .@"struct" => ty.castTag(.@"struct").?.data.is_tuple, |
| 5044 | else => false, | 5062 | else => false, |
| 5045 | }, | 5063 | }, |
| 5046 | else => false, // TODO | 5064 | else => false, // TODO struct |
| 5047 | }; | 5065 | }; |
| 5048 | } | 5066 | } |
| 5049 | | 5067 | |
| 5050 | pub fn isAnonStruct(ty: Type) bool { | 5068 | pub fn isAnonStruct(ty: Type) bool { |
| 5051 | return switch (ty.ip_index) { | 5069 | return switch (ty.ip_index) { |
| | 5070 | .empty_struct_type => true, |
| 5052 | .none => switch (ty.tag()) { | 5071 | .none => switch (ty.tag()) { |
| 5053 | .anon_struct, .empty_struct_literal => true, | 5072 | .anon_struct => true, |
| 5054 | else => false, | 5073 | else => false, |
| 5055 | }, | 5074 | }, |
| 5056 | else => false, // TODO | 5075 | else => false, // TODO struct |
| 5057 | }; | 5076 | }; |
| 5058 | } | 5077 | } |
| 5059 | | 5078 | |
| 5060 | pub fn isTupleOrAnonStruct(ty: Type) bool { | 5079 | pub fn isTupleOrAnonStruct(ty: Type) bool { |
| 5061 | return switch (ty.ip_index) { | 5080 | return switch (ty.ip_index) { |
| | 5081 | .empty_struct_type => true, |
| 5062 | .none => switch (ty.tag()) { | 5082 | .none => switch (ty.tag()) { |
| 5063 | .tuple, .empty_struct_literal, .anon_struct => true, | 5083 | .tuple, .anon_struct => true, |
| 5064 | .@"struct" => ty.castTag(.@"struct").?.data.is_tuple, | 5084 | .@"struct" => ty.castTag(.@"struct").?.data.is_tuple, |
| 5065 | else => false, | 5085 | else => false, |
| 5066 | }, | 5086 | }, |
| 5067 | else => false, // TODO | 5087 | else => false, // TODO struct |
| 5068 | }; | 5088 | }; |
| 5069 | } | 5089 | } |
| 5070 | | 5090 | |
| ... | @@ -5072,7 +5092,7 @@ pub const Type = struct { | ... | @@ -5072,7 +5092,7 @@ pub const Type = struct { |
| 5072 | return switch (ty.ip_index) { | 5092 | return switch (ty.ip_index) { |
| 5073 | .empty_struct => true, | 5093 | .empty_struct => true, |
| 5074 | .none => switch (ty.tag()) { | 5094 | .none => switch (ty.tag()) { |
| 5075 | .tuple, .empty_struct_literal => true, | 5095 | .tuple => true, |
| 5076 | else => false, | 5096 | else => false, |
| 5077 | }, | 5097 | }, |
| 5078 | else => false, // TODO | 5098 | else => false, // TODO |
| ... | @@ -5083,7 +5103,7 @@ pub const Type = struct { | ... | @@ -5083,7 +5103,7 @@ pub const Type = struct { |
| 5083 | return switch (ty.ip_index) { | 5103 | return switch (ty.ip_index) { |
| 5084 | .empty_struct => true, | 5104 | .empty_struct => true, |
| 5085 | .none => switch (ty.tag()) { | 5105 | .none => switch (ty.tag()) { |
| 5086 | .tuple, .empty_struct_literal, .anon_struct => true, | 5106 | .tuple, .anon_struct => true, |
| 5087 | else => false, | 5107 | else => false, |
| 5088 | }, | 5108 | }, |
| 5089 | else => false, | 5109 | else => false, |
| ... | @@ -5100,7 +5120,6 @@ pub const Type = struct { | ... | @@ -5100,7 +5120,6 @@ pub const Type = struct { |
| 5100 | .types = ty.castTag(.anon_struct).?.data.types, | 5120 | .types = ty.castTag(.anon_struct).?.data.types, |
| 5101 | .values = ty.castTag(.anon_struct).?.data.values, | 5121 | .values = ty.castTag(.anon_struct).?.data.values, |
| 5102 | }, | 5122 | }, |
| 5103 | .empty_struct_literal => .{ .types = &.{}, .values = &.{} }, | | |
| 5104 | else => unreachable, | 5123 | else => unreachable, |
| 5105 | }, | 5124 | }, |
| 5106 | else => unreachable, | 5125 | else => unreachable, |
| ... | @@ -5387,6 +5406,7 @@ pub const Type = struct { | ... | @@ -5387,6 +5406,7 @@ pub const Type = struct { |
| 5387 | .ip_index = .const_slice_u8_sentinel_0_type, | 5406 | .ip_index = .const_slice_u8_sentinel_0_type, |
| 5388 | .legacy = undefined, | 5407 | .legacy = undefined, |
| 5389 | }; | 5408 | }; |
| | 5409 | pub const empty_struct_literal: Type = .{ .ip_index = .empty_struct_type, .legacy = undefined }; |
| 5390 | | 5410 | |
| 5391 | pub const generic_poison: Type = .{ .ip_index = .generic_poison_type, .legacy = undefined }; | 5411 | pub const generic_poison: Type = .{ .ip_index = .generic_poison_type, .legacy = undefined }; |
| 5392 | | 5412 | |