| ... | @@ -883,6 +883,7 @@ pub const Type = struct { | ... | @@ -883,6 +883,7 @@ pub const Type = struct { |
| 883 | strat: AbiAlignmentAdvancedStrat, | 883 | strat: AbiAlignmentAdvancedStrat, |
| 884 | ) Module.CompileError!AbiAlignmentAdvanced { | 884 | ) Module.CompileError!AbiAlignmentAdvanced { |
| 885 | const target = mod.getTarget(); | 885 | const target = mod.getTarget(); |
| | 886 | const use_llvm = mod.comp.config.use_llvm; |
| 886 | const ip = &mod.intern_pool; | 887 | const ip = &mod.intern_pool; |
| 887 | | 888 | |
| 888 | const opt_sema = switch (strat) { | 889 | const opt_sema = switch (strat) { |
| ... | @@ -895,7 +896,7 @@ pub const Type = struct { | ... | @@ -895,7 +896,7 @@ pub const Type = struct { |
| 895 | else => switch (ip.indexToKey(ty.toIntern())) { | 896 | else => switch (ip.indexToKey(ty.toIntern())) { |
| 896 | .int_type => |int_type| { | 897 | .int_type => |int_type| { |
| 897 | if (int_type.bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" }; | 898 | if (int_type.bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" }; |
| 898 | return .{ .scalar = intAbiAlignment(int_type.bits, target) }; | 899 | return .{ .scalar = intAbiAlignment(int_type.bits, target, use_llvm) }; |
| 899 | }, | 900 | }, |
| 900 | .ptr_type, .anyframe_type => { | 901 | .ptr_type, .anyframe_type => { |
| 901 | return .{ .scalar = ptrAbiAlignment(target) }; | 902 | return .{ .scalar = ptrAbiAlignment(target) }; |
| ... | @@ -941,7 +942,7 @@ pub const Type = struct { | ... | @@ -941,7 +942,7 @@ pub const Type = struct { |
| 941 | .error_set_type, .inferred_error_set_type => { | 942 | .error_set_type, .inferred_error_set_type => { |
| 942 | const bits = mod.errorSetBits(); | 943 | const bits = mod.errorSetBits(); |
| 943 | if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" }; | 944 | if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" }; |
| 944 | return .{ .scalar = intAbiAlignment(bits, target) }; | 945 | return .{ .scalar = intAbiAlignment(bits, target, use_llvm) }; |
| 945 | }, | 946 | }, |
| 946 | | 947 | |
| 947 | // represents machine code; not a pointer | 948 | // represents machine code; not a pointer |
| ... | @@ -962,7 +963,7 @@ pub const Type = struct { | ... | @@ -962,7 +963,7 @@ pub const Type = struct { |
| 962 | | 963 | |
| 963 | .usize, | 964 | .usize, |
| 964 | .isize, | 965 | .isize, |
| 965 | => return .{ .scalar = intAbiAlignment(target.ptrBitWidth(), target) }, | 966 | => return .{ .scalar = intAbiAlignment(target.ptrBitWidth(), target, use_llvm) }, |
| 966 | | 967 | |
| 967 | .export_options, | 968 | .export_options, |
| 968 | .extern_options, | 969 | .extern_options, |
| ... | @@ -1001,7 +1002,7 @@ pub const Type = struct { | ... | @@ -1001,7 +1002,7 @@ pub const Type = struct { |
| 1001 | .anyerror, .adhoc_inferred_error_set => { | 1002 | .anyerror, .adhoc_inferred_error_set => { |
| 1002 | const bits = mod.errorSetBits(); | 1003 | const bits = mod.errorSetBits(); |
| 1003 | if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" }; | 1004 | if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" }; |
| 1004 | return .{ .scalar = intAbiAlignment(bits, target) }; | 1005 | return .{ .scalar = intAbiAlignment(bits, target, use_llvm) }; |
| 1005 | }, | 1006 | }, |
| 1006 | | 1007 | |
| 1007 | .void, | 1008 | .void, |
| ... | @@ -1216,6 +1217,7 @@ pub const Type = struct { | ... | @@ -1216,6 +1217,7 @@ pub const Type = struct { |
| 1216 | strat: AbiAlignmentAdvancedStrat, | 1217 | strat: AbiAlignmentAdvancedStrat, |
| 1217 | ) Module.CompileError!AbiSizeAdvanced { | 1218 | ) Module.CompileError!AbiSizeAdvanced { |
| 1218 | const target = mod.getTarget(); | 1219 | const target = mod.getTarget(); |
| | 1220 | const use_llvm = mod.comp.config.use_llvm; |
| 1219 | const ip = &mod.intern_pool; | 1221 | const ip = &mod.intern_pool; |
| 1220 | | 1222 | |
| 1221 | switch (ty.toIntern()) { | 1223 | switch (ty.toIntern()) { |
| ... | @@ -1224,7 +1226,7 @@ pub const Type = struct { | ... | @@ -1224,7 +1226,7 @@ pub const Type = struct { |
| 1224 | else => switch (ip.indexToKey(ty.toIntern())) { | 1226 | else => switch (ip.indexToKey(ty.toIntern())) { |
| 1225 | .int_type => |int_type| { | 1227 | .int_type => |int_type| { |
| 1226 | if (int_type.bits == 0) return AbiSizeAdvanced{ .scalar = 0 }; | 1228 | if (int_type.bits == 0) return AbiSizeAdvanced{ .scalar = 0 }; |
| 1227 | return AbiSizeAdvanced{ .scalar = intAbiSize(int_type.bits, target) }; | 1229 | return AbiSizeAdvanced{ .scalar = intAbiSize(int_type.bits, target, use_llvm) }; |
| 1228 | }, | 1230 | }, |
| 1229 | .ptr_type => |ptr_type| switch (ptr_type.flags.size) { | 1231 | .ptr_type => |ptr_type| switch (ptr_type.flags.size) { |
| 1230 | .Slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 }, | 1232 | .Slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 }, |
| ... | @@ -1286,7 +1288,7 @@ pub const Type = struct { | ... | @@ -1286,7 +1288,7 @@ pub const Type = struct { |
| 1286 | .error_set_type, .inferred_error_set_type => { | 1288 | .error_set_type, .inferred_error_set_type => { |
| 1287 | const bits = mod.errorSetBits(); | 1289 | const bits = mod.errorSetBits(); |
| 1288 | if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 }; | 1290 | if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 }; |
| 1289 | return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) }; | 1291 | return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target, use_llvm) }; |
| 1290 | }, | 1292 | }, |
| 1291 | | 1293 | |
| 1292 | .error_union_type => |error_union_type| { | 1294 | .error_union_type => |error_union_type| { |
| ... | @@ -1384,7 +1386,7 @@ pub const Type = struct { | ... | @@ -1384,7 +1386,7 @@ pub const Type = struct { |
| 1384 | .anyerror, .adhoc_inferred_error_set => { | 1386 | .anyerror, .adhoc_inferred_error_set => { |
| 1385 | const bits = mod.errorSetBits(); | 1387 | const bits = mod.errorSetBits(); |
| 1386 | if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 }; | 1388 | if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 }; |
| 1387 | return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) }; | 1389 | return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target, use_llvm) }; |
| 1388 | }, | 1390 | }, |
| 1389 | | 1391 | |
| 1390 | .prefetch_options => unreachable, // missing call to resolveTypeFields | 1392 | .prefetch_options => unreachable, // missing call to resolveTypeFields |
| ... | @@ -1533,17 +1535,112 @@ pub const Type = struct { | ... | @@ -1533,17 +1535,112 @@ pub const Type = struct { |
| 1533 | return Alignment.fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8)); | 1535 | return Alignment.fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8)); |
| 1534 | } | 1536 | } |
| 1535 | | 1537 | |
| 1536 | pub fn intAbiSize(bits: u16, target: Target) u64 { | 1538 | pub fn intAbiSize(bits: u16, target: Target, use_llvm: bool) u64 { |
| 1537 | return intAbiAlignment(bits, target).forward(@as(u16, @intCast((@as(u17, bits) + 7) / 8))); | 1539 | return intAbiAlignment(bits, target, use_llvm).forward(@as(u16, @intCast((@as(u17, bits) + 7) / 8))); |
| 1538 | } | 1540 | } |
| 1539 | | 1541 | |
| 1540 | pub fn intAbiAlignment(bits: u16, target: Target) Alignment { | 1542 | pub fn intAbiAlignment(bits: u16, target: Target, use_llvm: bool) Alignment { |
| 1541 | return Alignment.fromByteUnits(@min( | 1543 | return Alignment.fromByteUnits(@min( |
| 1542 | std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))), | 1544 | std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))), |
| 1543 | target.maxIntAlignment(), | 1545 | maxIntAlignment(target, use_llvm), |
| 1544 | )); | 1546 | )); |
| 1545 | } | 1547 | } |
| 1546 | | 1548 | |
| | 1549 | pub fn maxIntAlignment(target: std.Target, use_llvm: bool) u16 { |
| | 1550 | return switch (target.cpu.arch) { |
| | 1551 | .avr => 1, |
| | 1552 | .msp430 => 2, |
| | 1553 | .xcore => 4, |
| | 1554 | |
| | 1555 | .arm, |
| | 1556 | .armeb, |
| | 1557 | .thumb, |
| | 1558 | .thumbeb, |
| | 1559 | .hexagon, |
| | 1560 | .mips, |
| | 1561 | .mipsel, |
| | 1562 | .powerpc, |
| | 1563 | .powerpcle, |
| | 1564 | .r600, |
| | 1565 | .amdgcn, |
| | 1566 | .riscv32, |
| | 1567 | .sparc, |
| | 1568 | .sparcel, |
| | 1569 | .s390x, |
| | 1570 | .lanai, |
| | 1571 | .wasm32, |
| | 1572 | .wasm64, |
| | 1573 | => 8, |
| | 1574 | |
| | 1575 | .x86 => if (target.ofmt == .c) 16 else return switch (target.os.tag) { |
| | 1576 | .windows, .uefi => 8, |
| | 1577 | else => 4, |
| | 1578 | }, |
| | 1579 | |
| | 1580 | // For these, LLVMABIAlignmentOfType(i128) reports 8. Note that 16 |
| | 1581 | // is a relevant number in three cases: |
| | 1582 | // 1. Different machine code instruction when loading into SIMD register. |
| | 1583 | // 2. The C ABI wants 16 for extern structs. |
| | 1584 | // 3. 16-byte cmpxchg needs 16-byte alignment. |
| | 1585 | // Same logic for powerpc64, mips64, sparc64. |
| | 1586 | .powerpc64, |
| | 1587 | .powerpc64le, |
| | 1588 | .mips64, |
| | 1589 | .mips64el, |
| | 1590 | .sparc64, |
| | 1591 | => switch (target.ofmt) { |
| | 1592 | .c => 16, |
| | 1593 | else => 8, |
| | 1594 | }, |
| | 1595 | |
| | 1596 | .x86_64 => switch (target_util.zigBackend(target, use_llvm)) { |
| | 1597 | .stage2_x86_64 => 8, |
| | 1598 | else => 16, |
| | 1599 | }, |
| | 1600 | |
| | 1601 | // Even LLVMABIAlignmentOfType(i128) agrees on these targets. |
| | 1602 | .aarch64, |
| | 1603 | .aarch64_be, |
| | 1604 | .aarch64_32, |
| | 1605 | .riscv64, |
| | 1606 | .bpfel, |
| | 1607 | .bpfeb, |
| | 1608 | .nvptx, |
| | 1609 | .nvptx64, |
| | 1610 | => 16, |
| | 1611 | |
| | 1612 | // Below this comment are unverified but based on the fact that C requires |
| | 1613 | // int128_t to be 16 bytes aligned, it's a safe default. |
| | 1614 | .spu_2, |
| | 1615 | .csky, |
| | 1616 | .arc, |
| | 1617 | .m68k, |
| | 1618 | .tce, |
| | 1619 | .tcele, |
| | 1620 | .le32, |
| | 1621 | .amdil, |
| | 1622 | .hsail, |
| | 1623 | .spir, |
| | 1624 | .kalimba, |
| | 1625 | .renderscript32, |
| | 1626 | .spirv, |
| | 1627 | .spirv32, |
| | 1628 | .shave, |
| | 1629 | .le64, |
| | 1630 | .amdil64, |
| | 1631 | .hsail64, |
| | 1632 | .spir64, |
| | 1633 | .renderscript64, |
| | 1634 | .ve, |
| | 1635 | .spirv64, |
| | 1636 | .dxil, |
| | 1637 | .loongarch32, |
| | 1638 | .loongarch64, |
| | 1639 | .xtensa, |
| | 1640 | => 16, |
| | 1641 | }; |
| | 1642 | } |
| | 1643 | |
| 1547 | pub fn bitSize(ty: Type, mod: *Module) u64 { | 1644 | pub fn bitSize(ty: Type, mod: *Module) u64 { |
| 1548 | return bitSizeAdvanced(ty, mod, null) catch unreachable; | 1645 | return bitSizeAdvanced(ty, mod, null) catch unreachable; |
| 1549 | } | 1646 | } |