diff --git a/include/swift/AST/PlatformConditionKinds.def b/include/swift/AST/PlatformConditionKinds.def index bc980fd13f98b..a5a95af283c9e 100644 --- a/include/swift/AST/PlatformConditionKinds.def +++ b/include/swift/AST/PlatformConditionKinds.def @@ -49,5 +49,8 @@ PLATFORM_CONDITION_(PtrAuth, "ptrauth") /// The active arch target's max atomic bit width. PLATFORM_CONDITION_(HasAtomicBitWidth, "hasAtomicBitWidth") +/// The active target's file format (Mach-O, ELF, COFF, WASM) +PLATFORM_CONDITION(ObjectFileFormat, "objectFormat") + #undef PLATFORM_CONDITION #undef PLATFORM_CONDITION_ diff --git a/lib/ASTGen/Sources/ASTGen/CompilerBuildConfiguration.swift b/lib/ASTGen/Sources/ASTGen/CompilerBuildConfiguration.swift index 3dbc62d4d760a..62340fbfebbba 100644 --- a/lib/ASTGen/Sources/ASTGen/CompilerBuildConfiguration.swift +++ b/lib/ASTGen/Sources/ASTGen/CompilerBuildConfiguration.swift @@ -120,6 +120,10 @@ struct CompilerBuildConfiguration: BuildConfiguration { staticBuildConfiguration.targetPointerBitWidth } + func isActiveTargetObjectFormat(name: String) throws -> Bool { + try staticBuildConfiguration.isActiveTargetObjectFormat(name: name) + } + var targetAtomicBitWidths: [Int] { staticBuildConfiguration.targetAtomicBitWidths } diff --git a/lib/ASTGen/Sources/ASTGen/EmbeddedSupport.swift b/lib/ASTGen/Sources/ASTGen/EmbeddedSupport.swift index 0dfc9fa768fbe..324cbffa3e2f8 100644 --- a/lib/ASTGen/Sources/ASTGen/EmbeddedSupport.swift +++ b/lib/ASTGen/Sources/ASTGen/EmbeddedSupport.swift @@ -124,6 +124,10 @@ struct EmbeddedBuildConfiguration: BuildConfiguration { return configuration.targetPointerBitWidth } + func isActiveTargetObjectFormat(name: String) throws -> Bool { + return try configuration.isActiveTargetObjectFormat(name: name) + } + var targetAtomicBitWidths: [Int] { return configuration.targetAtomicBitWidths } diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp index 114b81a20ae53..3b5b13f65535a 100644 --- a/lib/Basic/LangOptions.cpp +++ b/lib/Basic/LangOptions.cpp @@ -141,13 +141,20 @@ static const SupportedConditionalValue SupportedConditionalCompilationHasAtomicB "_128" }; +static const SupportedConditionalValue SupportedConditionalCompilationObjectFileFormats[] = { + "MachO", + "ELF", + "COFF", + "Wasm", +}; + static const PlatformConditionKind AllPublicPlatformConditionKinds[] = { #define PLATFORM_CONDITION(LABEL, IDENTIFIER) PlatformConditionKind::LABEL, #define PLATFORM_CONDITION_(LABEL, IDENTIFIER) #include "swift/AST/PlatformConditionKinds.def" }; -ArrayRef getSupportedConditionalCompilationValues(const PlatformConditionKind &Kind) { +static ArrayRef getSupportedConditionalCompilationValues(const PlatformConditionKind &Kind) { switch (Kind) { case PlatformConditionKind::OS: return SupportedConditionalCompilationOSs; @@ -167,12 +174,14 @@ ArrayRef getSupportedConditionalCompilationValues(con return SupportedConditionalCompilationPtrAuthSchemes; case PlatformConditionKind::HasAtomicBitWidth: return SupportedConditionalCompilationHasAtomicBitWidths; + case PlatformConditionKind::ObjectFileFormat: + return SupportedConditionalCompilationObjectFileFormats; } llvm_unreachable("Unhandled PlatformConditionKind in switch"); } -PlatformConditionKind suggestedPlatformConditionKind(PlatformConditionKind Kind, const StringRef &V, - std::vector &suggestedValues) { +static PlatformConditionKind suggestedPlatformConditionKind(PlatformConditionKind Kind, const StringRef &V, + std::vector &suggestedValues) { std::string lower = V.lower(); for (const PlatformConditionKind& candidateKind : AllPublicPlatformConditionKinds) { if (candidateKind != Kind) { @@ -191,8 +200,8 @@ PlatformConditionKind suggestedPlatformConditionKind(PlatformConditionKind Kind, return Kind; } -bool isMatching(PlatformConditionKind Kind, const StringRef &V, - PlatformConditionKind &suggestedKind, std::vector &suggestions) { +static bool isMatching(PlatformConditionKind Kind, const StringRef &V, + PlatformConditionKind &suggestedKind, std::vector &suggestions) { // Compare against known values, ignoring case to avoid penalizing // characters with incorrect case. unsigned minDistance = std::numeric_limits::max(); @@ -231,6 +240,7 @@ checkPlatformConditionSupported(PlatformConditionKind Kind, StringRef Value, case PlatformConditionKind::TargetEnvironment: case PlatformConditionKind::PtrAuth: case PlatformConditionKind::HasAtomicBitWidth: + case PlatformConditionKind::ObjectFileFormat: return isMatching(Kind, Value, suggestedKind, suggestedValues); case PlatformConditionKind::CanImport: // All importable names are valid. @@ -649,6 +659,17 @@ std::pair LangOptions::setTarget(llvm::Triple triple) { addPlatformConditionValue(PlatformConditionKind::PointerBitWidth, "_64"); } + // Set the "objectFormat" platform condition. + if (Target.isOSBinFormatMachO()) { + addPlatformConditionValue(PlatformConditionKind::ObjectFileFormat, "MachO"); + } else if (Target.isOSBinFormatELF()) { + addPlatformConditionValue(PlatformConditionKind::ObjectFileFormat, "ELF"); + } else if (Target.isOSBinFormatCOFF()) { + addPlatformConditionValue(PlatformConditionKind::ObjectFileFormat, "COFF"); + } else if (Target.isOSBinFormatWasm()) { + addPlatformConditionValue(PlatformConditionKind::ObjectFileFormat, "Wasm"); + } + // Set the "runtime" platform condition. addPlatformConditionValue(PlatformConditionKind::Runtime, EnableObjCInterop ? "_ObjC" : "_Native"); diff --git a/lib/Basic/LangOptionsBridging.cpp b/lib/Basic/LangOptionsBridging.cpp index 5ccc2a8ea1df0..2eacc3f5bd957 100644 --- a/lib/Basic/LangOptionsBridging.cpp +++ b/lib/Basic/LangOptionsBridging.cpp @@ -228,6 +228,7 @@ void BridgedLangOptions_enumerateBuildConfigurationEntries( case PlatformConditionKind::Endianness: case PlatformConditionKind::PointerBitWidth: + case PlatformConditionKind::ObjectFileFormat: case PlatformConditionKind::CanImport: case PlatformConditionKind::HasAtomicBitWidth: // Handled separately. diff --git a/lib/Parse/ParseIfConfig.cpp b/lib/Parse/ParseIfConfig.cpp index 4e05e078aee60..9dc2e7b6b5726 100644 --- a/lib/Parse/ParseIfConfig.cpp +++ b/lib/Parse/ParseIfConfig.cpp @@ -385,7 +385,7 @@ class ValidateIfConfigCondition : return E; } - // ( 'os' | 'arch' | '_endian' | '_pointerBitWidth' | '_runtime' | '_hasAtomicBitWidth' ) '(' identifier ')'' + // ( 'os' | 'arch' | '_endian' | '_pointerBitWidth' | '_runtime' | '_hasAtomicBitWidth' | 'objectFormat' ) '(' identifier ')'' auto Kind = getPlatformConditionKind(*KindName); if (!Kind.has_value()) { D.diagnose(E->getLoc(), diag::unsupported_platform_condition_expression); @@ -429,6 +429,8 @@ class ValidateIfConfigCondition : DiagName = "pointer authentication scheme"; break; case PlatformConditionKind::HasAtomicBitWidth: DiagName = "has atomic bit width"; break; + case PlatformConditionKind::ObjectFileFormat: + DiagName = "object file format"; break; case PlatformConditionKind::Runtime: llvm_unreachable("handled above"); } diff --git a/test/Parse/ConditionalCompilation/object_file_format.swift b/test/Parse/ConditionalCompilation/object_file_format.swift new file mode 100644 index 0000000000000..997e41f17e83a --- /dev/null +++ b/test/Parse/ConditionalCompilation/object_file_format.swift @@ -0,0 +1,48 @@ +// RUN: %swift -typecheck %s -target arm64-apple-none-macho -parse-stdlib 2>&1 | %FileCheck -check-prefix CHECK-MACHO %s +// RUN: %swift -typecheck %s -target arm64-apple-none-elf -parse-stdlib 2>&1 | %FileCheck -check-prefix CHECK-ELF %s +// RUN: %swift -typecheck %s -target wasm32-unknown-wasi -parse-stdlib 2>&1 | %FileCheck -check-prefix CHECK-WASM %s +// RUN: %swift -typecheck %s -target x86_64-unknown-windows-msvc -parse-stdlib 2>&1 | %FileCheck -check-prefix CHECK-COFF %s + +#if objectFormat(MachO) +#warning("I'm MachO") +#else +#warning("I'm not MachO") +#endif + +#if objectFormat(ELF) +#warning("I'm ELF") +#else +#warning("I'm not ELF") +#endif + +#if objectFormat(Wasm) +#warning("I'm Wasm") +#else +#warning("I'm not Wasm") +#endif + +#if objectFormat(COFF) +#warning("I'm COFF") +#else +#warning("I'm not COFF") +#endif + +// CHECK-MACHO: I'm MachO +// CHECK-MACHO: I'm not ELF +// CHECK-MACHO: I'm not Wasm +// CHECK-MACHO: I'm not COFF + +// CHECK-ELF: I'm not MachO +// CHECK-ELF: I'm ELF +// CHECK-ELF: I'm not Wasm +// CHECK-ELF: I'm not COFF + +// CHECK-WASM: I'm not MachO +// CHECK-WASM: I'm not ELF +// CHECK-WASM: I'm Wasm +// CHECK-WASM: I'm not COFF + +// CHECK-COFF: I'm not MachO +// CHECK-COFF: I'm not ELF +// CHECK-COFF: I'm not Wasm +// CHECK-COFF: I'm COFF