@@ -107,6 +107,12 @@ static const SupportedConditionalValue SupportedConditionalCompilationPtrAuthSch
107107 " _arm64e" ,
108108};
109109
110+ static const SupportedConditionalValue SupportedConditionalCompilationAtomicBitWidths[] = {
111+ " _32" ,
112+ " _64" ,
113+ " _128"
114+ };
115+
110116static const PlatformConditionKind AllPublicPlatformConditionKinds[] = {
111117#define PLATFORM_CONDITION (LABEL, IDENTIFIER ) PlatformConditionKind::LABEL,
112118#define PLATFORM_CONDITION_ (LABEL, IDENTIFIER )
@@ -131,6 +137,8 @@ ArrayRef<SupportedConditionalValue> getSupportedConditionalCompilationValues(con
131137 return SupportedConditionalCompilationTargetEnvironments;
132138 case PlatformConditionKind::PtrAuth:
133139 return SupportedConditionalCompilationPtrAuthSchemes;
140+ case PlatformConditionKind::AtomicBitWidth:
141+ return SupportedConditionalCompilationAtomicBitWidths;
134142 }
135143 llvm_unreachable (" Unhandled PlatformConditionKind in switch" );
136144}
@@ -194,6 +202,7 @@ checkPlatformConditionSupported(PlatformConditionKind Kind, StringRef Value,
194202 case PlatformConditionKind::Runtime:
195203 case PlatformConditionKind::TargetEnvironment:
196204 case PlatformConditionKind::PtrAuth:
205+ case PlatformConditionKind::AtomicBitWidth:
197206 return isMatching (Kind, Value, suggestedKind, suggestedValues);
198207 case PlatformConditionKind::CanImport:
199208 // All importable names are valid.
@@ -268,6 +277,104 @@ bool LangOptions::hasFeature(llvm::StringRef featureName) const {
268277 return false ;
269278}
270279
280+ void LangOptions::setAtomicBitWidth (llvm::Triple triple) {
281+ // We really want to use Clang's getMaxAtomicInlineWidth(), but that requires
282+ // a Clang::TargetInfo and we're setting up lang opts very early in the
283+ // pipeline before any ASTContext or any ClangImporter instance where we can
284+ // access the target's info.
285+
286+ switch (triple.getArch ()) {
287+ // ARM is only a 32 bit arch and all archs besides the microcontroller profile
288+ // ones have double word atomics.
289+ case llvm::Triple::ArchType::arm:
290+ case llvm::Triple::ArchType::thumb:
291+ switch (triple.getSubArch ()) {
292+ case llvm::Triple::SubArchType::ARMSubArch_v6m:
293+ case llvm::Triple::SubArchType::ARMSubArch_v7m:
294+ addPlatformConditionValue (PlatformConditionKind::AtomicBitWidth, " _32" );
295+ break ;
296+
297+ default :
298+ addPlatformConditionValue (PlatformConditionKind::AtomicBitWidth, " _64" );
299+ break ;
300+ }
301+ break ;
302+
303+ // AArch64 (arm64) supports double word atomics on all archs besides the
304+ // microcontroller profiles.
305+ case llvm::Triple::ArchType::aarch64:
306+ switch (triple.getSubArch ()) {
307+ case llvm::Triple::SubArchType::ARMSubArch_v8m_baseline:
308+ case llvm::Triple::SubArchType::ARMSubArch_v8m_mainline:
309+ case llvm::Triple::SubArchType::ARMSubArch_v8_1m_mainline:
310+ addPlatformConditionValue (PlatformConditionKind::AtomicBitWidth, " _64" );
311+ break ;
312+
313+ default :
314+ addPlatformConditionValue (PlatformConditionKind::AtomicBitWidth, " _128" );
315+ break ;
316+ }
317+ break ;
318+
319+ // arm64_32 has 32 bit pointer words, but it has the same architecture as
320+ // arm64 and supports 128 bit atomics.
321+ case llvm::Triple::ArchType::aarch64_32:
322+ addPlatformConditionValue (PlatformConditionKind::AtomicBitWidth, " _128" );
323+ break ;
324+
325+ // PowerPC does not support double word atomics.
326+ case llvm::Triple::ArchType::ppc:
327+ addPlatformConditionValue (PlatformConditionKind::AtomicBitWidth, " _32" );
328+ break ;
329+
330+ // All of the 64 bit PowerPC flavors do not support double word atomics.
331+ case llvm::Triple::ArchType::ppc64:
332+ case llvm::Triple::ArchType::ppc64le:
333+ addPlatformConditionValue (PlatformConditionKind::AtomicBitWidth, " _64" );
334+ break ;
335+
336+ // SystemZ (s390x) does not support double word atomics.
337+ case llvm::Triple::ArchType::systemz:
338+ addPlatformConditionValue (PlatformConditionKind::AtomicBitWidth, " _64" );
339+ break ;
340+
341+ // Wasm32 supports double word atomics.
342+ case llvm::Triple::ArchType::wasm32:
343+ addPlatformConditionValue (PlatformConditionKind::AtomicBitWidth, " _64" );
344+ break ;
345+
346+ // x86 supports double word atomics.
347+ //
348+ // Technically, this is incorrect. However, on all x86 platforms where Swift
349+ // is deployed this is true.
350+ case llvm::Triple::ArchType::x86:
351+ addPlatformConditionValue (PlatformConditionKind::AtomicBitWidth, " _64" );
352+ break ;
353+
354+ // x86_64 supports double word atomics.
355+ //
356+ // Technically, this is incorrect. However, on all x86_64 platforms where Swift
357+ // is deployed this is true. If the ClangImporter ever stops unconditionally
358+ // adding '-mcx16' to its Clang instance, then be sure to update this below.
359+ case llvm::Triple::ArchType::x86_64:
360+ addPlatformConditionValue (PlatformConditionKind::AtomicBitWidth, " _128" );
361+ break ;
362+
363+ default :
364+ // Some exotic architectures may not support atomics at all. If that's the
365+ // case please update the switch with your flavor of arch. Otherwise assume
366+ // every arch supports at least word atomics.
367+
368+ if (triple.isArch32Bit ()) {
369+ addPlatformConditionValue (PlatformConditionKind::AtomicBitWidth, " _32" );
370+ }
371+
372+ if (triple.isArch64Bit ()) {
373+ addPlatformConditionValue (PlatformConditionKind::AtomicBitWidth, " _64" );
374+ }
375+ }
376+ }
377+
271378std::pair<bool , bool > LangOptions::setTarget (llvm::Triple triple) {
272379 clearAllPlatformConditionValues ();
273380
@@ -439,6 +546,9 @@ std::pair<bool, bool> LangOptions::setTarget(llvm::Triple triple) {
439546 addPlatformConditionValue (PlatformConditionKind::TargetEnvironment,
440547 " macabi" );
441548
549+ // Set the "_atomicBitWidth" platform condition.
550+ setAtomicBitWidth (triple);
551+
442552 // If you add anything to this list, change the default size of
443553 // PlatformConditionValues to not require an extra allocation
444554 // in the common case.
0 commit comments