| ... | @@ -1377,6 +1377,151 @@ pub const Type = extern union { | ... | @@ -1377,6 +1377,151 @@ pub const Type = extern union { |
| 1377 | }; | 1377 | }; |
| 1378 | } | 1378 | } |
| 1379 | | 1379 | |
| | 1380 | /// Asserts the type has the bit size already resolved. |
| | 1381 | pub fn bitSize(self: Type, target: Target) u64 { |
| | 1382 | return switch (self.tag()) { |
| | 1383 | .fn_noreturn_no_args => unreachable, // represents machine code; not a pointer |
| | 1384 | .fn_void_no_args => unreachable, // represents machine code; not a pointer |
| | 1385 | .fn_naked_noreturn_no_args => unreachable, // represents machine code; not a pointer |
| | 1386 | .fn_ccc_void_no_args => unreachable, // represents machine code; not a pointer |
| | 1387 | .function => unreachable, // represents machine code; not a pointer |
| | 1388 | .c_void => unreachable, |
| | 1389 | .void => unreachable, |
| | 1390 | .type => unreachable, |
| | 1391 | .comptime_int => unreachable, |
| | 1392 | .comptime_float => unreachable, |
| | 1393 | .noreturn => unreachable, |
| | 1394 | .@"null" => unreachable, |
| | 1395 | .@"undefined" => unreachable, |
| | 1396 | .enum_literal => unreachable, |
| | 1397 | .single_const_pointer_to_comptime_int => unreachable, |
| | 1398 | .empty_struct => unreachable, |
| | 1399 | .empty_struct_literal => unreachable, |
| | 1400 | .inferred_alloc_const => unreachable, |
| | 1401 | .inferred_alloc_mut => unreachable, |
| | 1402 | .@"opaque" => unreachable, |
| | 1403 | .var_args_param => unreachable, |
| | 1404 | |
| | 1405 | .@"struct" => { |
| | 1406 | @panic("TODO bitSize struct"); |
| | 1407 | }, |
| | 1408 | .enum_simple, .enum_full, .enum_nonexhaustive => { |
| | 1409 | var buffer: Payload.Bits = undefined; |
| | 1410 | const int_tag_ty = self.intTagType(&buffer); |
| | 1411 | return int_tag_ty.bitSize(target); |
| | 1412 | }, |
| | 1413 | |
| | 1414 | .u8, .i8 => 8, |
| | 1415 | |
| | 1416 | .bool => 1, |
| | 1417 | |
| | 1418 | .array_u8 => 8 * self.castTag(.array_u8).?.data, |
| | 1419 | .array_u8_sentinel_0 => 8 * (self.castTag(.array_u8_sentinel_0).?.data + 1), |
| | 1420 | .array => { |
| | 1421 | const payload = self.castTag(.array).?.data; |
| | 1422 | const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target)); |
| | 1423 | if (elem_size == 0 or payload.len == 0) |
| | 1424 | return 0; |
| | 1425 | return (payload.len - 1) * 8 * elem_size + payload.elem_type.bitSize(target); |
| | 1426 | }, |
| | 1427 | .array_sentinel => { |
| | 1428 | const payload = self.castTag(.array_sentinel).?.data; |
| | 1429 | const elem_size = std.math.max( |
| | 1430 | payload.elem_type.abiAlignment(target), |
| | 1431 | payload.elem_type.abiSize(target), |
| | 1432 | ); |
| | 1433 | return payload.len * 8 * elem_size + payload.elem_type.bitSize(target); |
| | 1434 | }, |
| | 1435 | .i16, .u16, .f16 => 16, |
| | 1436 | .i32, .u32, .f32 => 32, |
| | 1437 | .i64, .u64, .f64 => 64, |
| | 1438 | .u128, .i128, .f128 => 128, |
| | 1439 | |
| | 1440 | .isize, .usize => target.cpu.arch.ptrBitWidth(), |
| | 1441 | |
| | 1442 | .const_slice, |
| | 1443 | .mut_slice, |
| | 1444 | => { |
| | 1445 | if (self.elemType().hasCodeGenBits()) { |
| | 1446 | return target.cpu.arch.ptrBitWidth() * 2; |
| | 1447 | } else { |
| | 1448 | return target.cpu.arch.ptrBitWidth(); |
| | 1449 | } |
| | 1450 | }, |
| | 1451 | .const_slice_u8 => target.cpu.arch.ptrBitWidth() * 2, |
| | 1452 | |
| | 1453 | .optional_single_const_pointer, |
| | 1454 | .optional_single_mut_pointer, |
| | 1455 | => { |
| | 1456 | if (self.elemType().hasCodeGenBits()) { |
| | 1457 | return target.cpu.arch.ptrBitWidth(); |
| | 1458 | } else { |
| | 1459 | return 1; |
| | 1460 | } |
| | 1461 | }, |
| | 1462 | |
| | 1463 | .single_const_pointer, |
| | 1464 | .single_mut_pointer, |
| | 1465 | .many_const_pointer, |
| | 1466 | .many_mut_pointer, |
| | 1467 | .c_const_pointer, |
| | 1468 | .c_mut_pointer, |
| | 1469 | .pointer, |
| | 1470 | => { |
| | 1471 | if (self.elemType().hasCodeGenBits()) { |
| | 1472 | return target.cpu.arch.ptrBitWidth(); |
| | 1473 | } else { |
| | 1474 | return 0; |
| | 1475 | } |
| | 1476 | }, |
| | 1477 | |
| | 1478 | .c_short => return CType.short.sizeInBits(target), |
| | 1479 | .c_ushort => return CType.ushort.sizeInBits(target), |
| | 1480 | .c_int => return CType.int.sizeInBits(target), |
| | 1481 | .c_uint => return CType.uint.sizeInBits(target), |
| | 1482 | .c_long => return CType.long.sizeInBits(target), |
| | 1483 | .c_ulong => return CType.ulong.sizeInBits(target), |
| | 1484 | .c_longlong => return CType.longlong.sizeInBits(target), |
| | 1485 | .c_ulonglong => return CType.ulonglong.sizeInBits(target), |
| | 1486 | .c_longdouble => 128, |
| | 1487 | |
| | 1488 | .error_set, |
| | 1489 | .error_set_single, |
| | 1490 | .anyerror_void_error_union, |
| | 1491 | .anyerror, |
| | 1492 | => return 16, // TODO revisit this when we have the concept of the error tag type |
| | 1493 | |
| | 1494 | .int_signed, .int_unsigned => self.cast(Payload.Bits).?.data, |
| | 1495 | |
| | 1496 | .optional => { |
| | 1497 | var buf: Payload.ElemType = undefined; |
| | 1498 | const child_type = self.optionalChild(&buf); |
| | 1499 | if (!child_type.hasCodeGenBits()) return 8; |
| | 1500 | |
| | 1501 | if (child_type.zigTypeTag() == .Pointer and !child_type.isCPtr()) |
| | 1502 | return target.cpu.arch.ptrBitWidth(); |
| | 1503 | |
| | 1504 | // Optional types are represented as a struct with the child type as the first |
| | 1505 | // field and a boolean as the second. Since the child type's abi alignment is |
| | 1506 | // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal |
| | 1507 | // to the child type's ABI alignment. |
| | 1508 | return child_type.bitSize(target) + 1; |
| | 1509 | }, |
| | 1510 | |
| | 1511 | .error_union => { |
| | 1512 | const payload = self.castTag(.error_union).?.data; |
| | 1513 | if (!payload.error_set.hasCodeGenBits() and !payload.payload.hasCodeGenBits()) { |
| | 1514 | return 0; |
| | 1515 | } else if (!payload.error_set.hasCodeGenBits()) { |
| | 1516 | return payload.payload.bitSize(target); |
| | 1517 | } else if (!payload.payload.hasCodeGenBits()) { |
| | 1518 | return payload.error_set.bitSize(target); |
| | 1519 | } |
| | 1520 | @panic("TODO abiSize error union"); |
| | 1521 | }, |
| | 1522 | }; |
| | 1523 | } |
| | 1524 | |
| 1380 | /// Asserts the type is an enum. | 1525 | /// Asserts the type is an enum. |
| 1381 | pub fn intTagType(self: Type, buffer: *Payload.Bits) Type { | 1526 | pub fn intTagType(self: Type, buffer: *Payload.Bits) Type { |
| 1382 | switch (self.tag()) { | 1527 | switch (self.tag()) { |