|
| 1 | +From 434d3a1ee5e666eec1437615ad328497662aa363 |
| 2 | +From: Allan Shortlidge < [email protected]> |
| 3 | +Date: Thu, 25 Sep 2025 22:34:25 -0700 |
| 4 | +Subject: [PATCH] AST: Give `CustomAvailabilityDomain` 8 byte alignment. |
| 5 | + |
| 6 | +`AvailabilityDomain` is a pointer union over `CustomAvailabilityDomain` and an |
| 7 | +opaque pointer-like 24-bit value, which means the number of spare bits in an |
| 8 | +`AvailabilityDomain` representation is one fewer than a |
| 9 | +`CustomAvailabilityDomain` pointer. Other structures in the compiler rely on |
| 10 | +there being at least 2 spare bits in `AvailabilityDomain`, though, which was |
| 11 | +not the case when building for a 32 bit architecture. To ensure there are |
| 12 | +enough spare bits, always align `CustomAvailabilityDomain` to 8 bytes, the same |
| 13 | +as many AST data structures. |
| 14 | + |
| 15 | +diff --git a/swift/include/swift/AST/AvailabilityDomain.h b/swift/include/swift/AST/AvailabilityDomain.h |
| 16 | +index 7d5ecac7df03c..3c28bf0ba757e 100644 |
| 17 | +--- a/swift/include/swift/AST/AvailabilityDomain.h |
| 18 | ++++ b/swift/include/swift/AST/AvailabilityDomain.h |
| 19 | +@@ -22,6 +22,7 @@ |
| 20 | + #include "swift/AST/AvailabilityRange.h" |
| 21 | + #include "swift/AST/Identifier.h" |
| 22 | + #include "swift/AST/PlatformKind.h" |
| 23 | ++#include "swift/AST/TypeAlignments.h" |
| 24 | + #include "swift/Basic/Assertions.h" |
| 25 | + #include "swift/Basic/LLVM.h" |
| 26 | + #include "swift/Basic/SourceLoc.h" |
| 27 | +@@ -334,7 +335,8 @@ struct StableAvailabilityDomainComparator { |
| 28 | + }; |
| 29 | + |
| 30 | + /// Represents an availability domain that has been defined in a module. |
| 31 | +-class CustomAvailabilityDomain : public llvm::FoldingSetNode { |
| 32 | ++class alignas(1 << CustomAvailabilityDomainAlignInBits) CustomAvailabilityDomain |
| 33 | ++ : public llvm::FoldingSetNode { |
| 34 | + public: |
| 35 | + enum class Kind { |
| 36 | + /// A domain that is known to be enabled at compile time. |
| 37 | +diff --git a/swift/include/swift/AST/TypeAlignments.h b/swift/include/swift/AST/TypeAlignments.h |
| 38 | +index b4eb926d6a1e9..c9b5d49b8f78a 100644 |
| 39 | +--- a/swift/include/swift/AST/TypeAlignments.h |
| 40 | ++++ b/swift/include/swift/AST/TypeAlignments.h |
| 41 | +@@ -34,6 +34,7 @@ namespace swift { |
| 42 | + class AttributeBase; |
| 43 | + class BraceStmt; |
| 44 | + class CaptureListExpr; |
| 45 | ++ class CustomAvailabilityDomain; |
| 46 | + class Decl; |
| 47 | + class DeclContext; |
| 48 | + class DifferentiableAttr; |
| 49 | +@@ -80,6 +81,7 @@ namespace swift { |
| 50 | + constexpr size_t ASTContextAlignInBits = 2; |
| 51 | + constexpr size_t TypeVariableAlignInBits = 4; |
| 52 | + constexpr size_t StoredDefaultArgumentAlignInBits = 3; |
| 53 | ++ constexpr size_t CustomAvailabilityDomainAlignInBits = 3; |
| 54 | + |
| 55 | + // Well, this is the *minimum* pointer alignment; it's going to be 3 on |
| 56 | + // 64-bit targets, but that doesn't matter. |
| 57 | +@@ -165,6 +167,9 @@ LLVM_DECLARE_TYPE_ALIGNMENT(swift::CaseLabelItem, swift::PatternAlignInBits) |
| 58 | + LLVM_DECLARE_TYPE_ALIGNMENT(swift::StmtConditionElement, |
| 59 | + swift::PatternAlignInBits) |
| 60 | + |
| 61 | ++LLVM_DECLARE_TYPE_ALIGNMENT(swift::CustomAvailabilityDomain, |
| 62 | ++ swift::CustomAvailabilityDomainAlignInBits) |
| 63 | ++ |
| 64 | + static_assert(alignof(void*) >= 2, "pointer alignment is too small"); |
| 65 | + |
| 66 | + #endif |
| 67 | +diff --git a/swift/include/swift/Basic/Feature.h b/swift/include/swift/Basic/Feature.h |
| 68 | +index b05080bbf3a..ebec19d9e53 100644 |
| 69 | +--- a/swift/include/swift/Basic/Feature.h |
| 70 | ++++ b/swift/include/swift/Basic/Feature.h |
| 71 | +@@ -35,7 +35,9 @@ struct Feature { |
| 72 | + constexpr Feature(unsigned inputKind) : kind(InnerKind(inputKind)) {} |
| 73 | + |
| 74 | + constexpr operator InnerKind() const { return kind; } |
| 75 | ++#if !defined(__arm__) |
| 76 | + constexpr explicit operator unsigned() const { return unsigned(kind); } |
| 77 | ++#endif |
| 78 | + constexpr explicit operator size_t() const { return size_t(kind); } |
| 79 | + |
| 80 | + static constexpr unsigned getNumFeatures() { |
| 81 | +diff --git a/swift-build/Sources/SWBUtil/FSProxy.swift b/swift-build/Sources/SWBUtil/FSProxy.swift |
| 82 | +index b446d21..f88f3c3 100644 |
| 83 | +--- a/swift-build/Sources/SWBUtil/FSProxy.swift |
| 84 | ++++ b/swift-build/Sources/SWBUtil/FSProxy.swift |
| 85 | +@@ -49,7 +49,7 @@ public struct FileInfo: Equatable, Sendable { |
| 86 | + #if os(Windows) |
| 87 | + return (statBuf.st_mode & UInt16(ucrt.S_IFREG)) != 0 |
| 88 | + #else |
| 89 | +- return (statBuf.st_mode & S_IFREG) != 0 |
| 90 | ++ return (mode_t(statBuf.st_mode) & S_IFREG) != 0 |
| 91 | + #endif |
| 92 | + } |
| 93 | + |
| 94 | +@@ -57,7 +57,7 @@ public struct FileInfo: Equatable, Sendable { |
| 95 | + #if os(Windows) |
| 96 | + return (statBuf.st_mode & UInt16(ucrt.S_IFDIR)) != 0 |
| 97 | + #else |
| 98 | +- return (statBuf.st_mode & S_IFDIR) != 0 |
| 99 | ++ return (mode_t(statBuf.st_mode) & S_IFDIR) != 0 |
| 100 | + #endif |
| 101 | + } |
| 102 | + |
| 103 | +@@ -65,7 +65,7 @@ public struct FileInfo: Equatable, Sendable { |
| 104 | + #if os(Windows) |
| 105 | + return (statBuf.st_mode & UInt16(S_IFLNK)) == S_IFLNK |
| 106 | + #else |
| 107 | +- return (statBuf.st_mode & S_IFMT) == S_IFLNK |
| 108 | ++ return (mode_t(statBuf.st_mode) & S_IFMT) == S_IFLNK |
| 109 | + #endif |
| 110 | + } |
| 111 | + |
| 112 | +@@ -75,7 +75,7 @@ public struct FileInfo: Equatable, Sendable { |
| 113 | + // Don't use FileManager.isExecutableFile due to https://github.com/swiftlang/swift-foundation/issues/860 |
| 114 | + return (statBuf.st_mode & UInt16(_S_IEXEC)) != 0 |
| 115 | + #else |
| 116 | +- return (statBuf.st_mode & S_IXUSR) != 0 |
| 117 | ++ return (mode_t(statBuf.st_mode) & S_IXUSR) != 0 |
| 118 | + #endif |
| 119 | + } |
| 120 | + |
| 121 | +@@ -1395,9 +1395,9 @@ public class PseudoFS: FSProxy, @unchecked Sendable { |
| 122 | + #else |
| 123 | + info.st_mtimespec = timespec(tv_sec: time_t(node.timestamp), tv_nsec: 0) |
| 124 | + #endif |
| 125 | +- info.st_size = off_t(contents.bytes.count) |
| 126 | +- info.st_dev = node.device |
| 127 | +- info.st_ino = node.inode |
| 128 | ++ info.st_size = numericCast(contents.bytes.count) |
| 129 | ++ info.st_dev = numericCast(node.device) |
| 130 | ++ info.st_ino = numericCast(node.inode) |
| 131 | + return createFileInfo(info) |
| 132 | + case .directory(let dir): |
| 133 | + var info = stat() |
| 134 | +@@ -1405,12 +1405,12 @@ public class PseudoFS: FSProxy, @unchecked Sendable { |
| 135 | + info.st_mode = UInt16(ucrt.S_IFDIR) |
| 136 | + info.st_mtimespec = timespec(tv_sec: Int64(node.timestamp), tv_nsec: 0) |
| 137 | + #else |
| 138 | +- info.st_mode = S_IFDIR |
| 139 | ++ info.st_mode = numericCast(S_IFDIR) |
| 140 | + info.st_mtimespec = timespec(tv_sec: time_t(node.timestamp), tv_nsec: 0) |
| 141 | + #endif |
| 142 | +- info.st_size = off_t(dir.contents.count) |
| 143 | +- info.st_dev = node.device |
| 144 | +- info.st_ino = node.inode |
| 145 | ++ info.st_size = numericCast(dir.contents.count) |
| 146 | ++ info.st_dev = numericCast(node.device) |
| 147 | ++ info.st_ino = numericCast(node.inode) |
| 148 | + return createFileInfo(info) |
| 149 | + case .symlink(_): |
| 150 | + var info = stat() |
| 151 | +@@ -1418,12 +1418,12 @@ public class PseudoFS: FSProxy, @unchecked Sendable { |
| 152 | + info.st_mode = UInt16(S_IFLNK) |
| 153 | + info.st_mtimespec = timespec(tv_sec: Int64(node.timestamp), tv_nsec: 0) |
| 154 | + #else |
| 155 | +- info.st_mode = S_IFLNK |
| 156 | ++ info.st_mode = numericCast(S_IFLNK) |
| 157 | + info.st_mtimespec = timespec(tv_sec: time_t(node.timestamp), tv_nsec: 0) |
| 158 | + #endif |
| 159 | +- info.st_size = off_t(0) |
| 160 | +- info.st_dev = node.device |
| 161 | +- info.st_ino = node.inode |
| 162 | ++ info.st_size = numericCast(0) |
| 163 | ++ info.st_dev = numericCast(node.device) |
| 164 | ++ info.st_ino = numericCast(node.inode) |
| 165 | + return createFileInfo(info) |
| 166 | + } |
| 167 | + } |
0 commit comments