Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add #_objectFileFormat compilation conditional #80212

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/swift/AST/ASTBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,9 @@ bool BridgedASTContext_langOptsAttachCommentsToDecls(
SWIFT_NAME("getter:BridgedASTContext.langOptsTargetEndianness(self:)")
BridgedEndianness BridgedASTContext_langOptsTargetEndianness(BridgedASTContext cContext);

SWIFT_NAME("BridgedASTContext.langOptsIsActiveTargetObjectFileFormat(self:_:)")
bool BridgedASTContext_langOptsIsActiveTargetObjectFileFormat(BridgedASTContext cContext, BridgedStringRef cName);

SWIFT_NAME("BridgedASTContext.langOptsGetLanguageVersion(self:_:)")
SwiftInt BridgedASTContext_langOptsGetLanguageVersion(BridgedASTContext cContext,
SwiftInt* _Nullable * _Nonnull cComponents);
Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/DiagnosticsFrontend.def
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ ERROR(error_unsupported_target_os, none,
ERROR(error_unsupported_target_arch, none,
"unsupported target architecture: '%0'", (StringRef))

ERROR(error_unsupported_object_file_format, none,
"unsupported object file format: '%0'", (StringRef))

WARNING(warning_upcoming_feature_on_by_default, none,
"upcoming feature '%0' is already enabled as of Swift version %1",
(StringRef, unsigned))
Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/PlatformConditionKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -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, "objectFileFormat")

#undef PLATFORM_CONDITION
#undef PLATFORM_CONDITION_
8 changes: 3 additions & 5 deletions include/swift/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -652,11 +652,9 @@ namespace swift {
LangOptions();

/// Sets the target we are building for and updates platform conditions
/// to match.
///
/// \returns A pair - the first element is true if the OS was invalid.
/// The second element is true if the Arch was invalid.
std::pair<bool, bool> setTarget(llvm::Triple triple);
/// to match. Emits errors using `Diags` in case of an invalid OS, arch,
/// etc.
void setTarget(llvm::Triple triple, swift::DiagnosticEngine *Diags = nullptr);

/// Returns the minimum platform version to which code will be deployed.
///
Expand Down
7 changes: 7 additions & 0 deletions lib/AST/Bridging/ASTContextBridging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "swift/AST/ASTContext.h"
#include "swift/AST/AvailabilitySpec.h"
#include "llvm/Support/ErrorHandling.h"

using namespace swift;

Expand Down Expand Up @@ -109,6 +110,12 @@ BridgedASTContext_langOptsTargetEndianness(BridgedASTContext cContext) {
: EndianBig;
}

bool BridgedASTContext_langOptsIsActiveTargetObjectFileFormat(
BridgedASTContext cContext, BridgedStringRef cName) {
return cContext.unbridged().LangOpts.checkPlatformCondition(
PlatformConditionKind::ObjectFileFormat, cName.unbridged());
}

/// Convert an array of numbers into a form we can use in Swift.
namespace {
template <typename Arr>
Expand Down
7 changes: 7 additions & 0 deletions lib/ASTGen/Sources/ASTGen/CompilerBuildConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,13 @@ struct CompilerBuildConfiguration: BuildConfiguration {
Int(ctx.langOptsTargetPointerBitWidth)
}

func isActiveTargetObjectFileFormat(name: String) throws -> Bool {
var name = name
return name.withBridgedString { nameRef in
ctx.langOptsIsActiveTargetObjectFileFormat(nameRef)
}
}

var targetAtomicBitWidths: [Int] {
var bitWidthsBuf: UnsafeMutablePointer<SwiftInt>? = nil
let count = ctx.langOptsGetTargetAtomicBitWidths(&bitWidthsBuf)
Expand Down
53 changes: 43 additions & 10 deletions lib/Basic/LangOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "swift/Basic/LangOptions.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/Basic/Assertions.h"
#include "swift/Basic/Feature.h"
#include "swift/Basic/FileTypes.h"
Expand Down Expand Up @@ -146,13 +147,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<SupportedConditionalValue> getSupportedConditionalCompilationValues(const PlatformConditionKind &Kind) {
static ArrayRef<SupportedConditionalValue> getSupportedConditionalCompilationValues(const PlatformConditionKind &Kind) {
switch (Kind) {
case PlatformConditionKind::OS:
return SupportedConditionalCompilationOSs;
Expand All @@ -172,12 +180,14 @@ ArrayRef<SupportedConditionalValue> 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<StringRef> &suggestedValues) {
static PlatformConditionKind suggestedPlatformConditionKind(PlatformConditionKind Kind, const StringRef &V,
std::vector<StringRef> &suggestedValues) {
std::string lower = V.lower();
for (const PlatformConditionKind& candidateKind : AllPublicPlatformConditionKinds) {
if (candidateKind != Kind) {
Expand All @@ -196,8 +206,8 @@ PlatformConditionKind suggestedPlatformConditionKind(PlatformConditionKind Kind,
return Kind;
}

bool isMatching(PlatformConditionKind Kind, const StringRef &V,
PlatformConditionKind &suggestedKind, std::vector<StringRef> &suggestions) {
static bool isMatching(PlatformConditionKind Kind, const StringRef &V,
PlatformConditionKind &suggestedKind, std::vector<StringRef> &suggestions) {
// Compare against known values, ignoring case to avoid penalizing
// characters with incorrect case.
unsigned minDistance = std::numeric_limits<unsigned>::max();
Expand Down Expand Up @@ -236,6 +246,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.
Expand Down Expand Up @@ -479,7 +490,8 @@ static bool isMultiThreadedRuntime(llvm::Triple triple) {
return true;
}

std::pair<bool, bool> LangOptions::setTarget(llvm::Triple triple) {
void LangOptions::setTarget(llvm::Triple triple,
swift::DiagnosticEngine *Diags) {
clearAllPlatformConditionValues();
clearAtomicBitWidths();

Expand Down Expand Up @@ -564,6 +576,11 @@ std::pair<bool, bool> LangOptions::setTarget(llvm::Triple triple) {
break;
}

if (UnsupportedOS && Diags) {
Diags->diagnose(SourceLoc(), diag::error_unsupported_target_os,
Target.getOSName());
}

bool UnsupportedArch = false;

// Set the "arch" platform condition.
Expand Down Expand Up @@ -622,8 +639,10 @@ std::pair<bool, bool> LangOptions::setTarget(llvm::Triple triple) {
}
}

if (UnsupportedOS || UnsupportedArch)
return { UnsupportedOS, UnsupportedArch };
if (UnsupportedArch && Diags) {
Diags->diagnose(SourceLoc(), diag::error_unsupported_target_arch,
Target.getArchName());
}

// Set the "_endian" platform condition.
if (Target.isLittleEndian()) {
Expand All @@ -641,6 +660,22 @@ std::pair<bool, bool> LangOptions::setTarget(llvm::Triple triple) {
addPlatformConditionValue(PlatformConditionKind::PointerBitWidth, "_64");
}

// Set the "_objectFileFormat" 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");
} else {
if (Diags) {
Diags->diagnose(SourceLoc(), diag::error_unsupported_object_file_format,
Target.getObjectFormatTypeName(Target.getObjectFormat()));
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add an else clause here that diagnoses the target is unknown? That way if we add a new port, we'll know to update this code.


// Set the "runtime" platform condition.
addPlatformConditionValue(PlatformConditionKind::Runtime,
EnableObjCInterop ? "_ObjC" : "_Native");
Expand Down Expand Up @@ -674,8 +709,6 @@ std::pair<bool, bool> LangOptions::setTarget(llvm::Triple triple) {
// If you add anything to this list, change the default size of
// PlatformConditionValues to not require an extra allocation
// in the common case.

return { false, false };
}

llvm::StringRef swift::getPlaygroundOptionName(PlaygroundOption option) {
Expand Down
26 changes: 3 additions & 23 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ void CompilerInvocation::setTargetTriple(StringRef Triple) {
}

void CompilerInvocation::setTargetTriple(const llvm::Triple &Triple) {
LangOpts.setTarget(Triple);
LangOpts.setTarget(Triple, /*Diags*/nullptr);
updateRuntimeLibraryPaths(SearchPathOpts, FrontendOpts, LangOpts);
}

Expand Down Expand Up @@ -1474,12 +1474,8 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.SkipNonExportableDecls = false;

llvm::Triple Target = Opts.Target;
StringRef TargetArg;
std::string TargetArgScratch;

if (const Arg *A = Args.getLastArg(OPT_target)) {
Target = llvm::Triple(A->getValue());
TargetArg = A->getValue();

const bool targetNeedsRemapping = Target.isXROS();
if (targetNeedsRemapping && Target.getOSMajorVersion() == 0) {
Expand All @@ -1506,8 +1502,6 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
if (tripleInfersSimulatorEnvironment(Target)) {
// Set the simulator environment.
Target.setEnvironment(llvm::Triple::EnvironmentType::Simulator);
TargetArgScratch = Target.str();
TargetArg = TargetArgScratch;
}
}

Expand Down Expand Up @@ -1562,21 +1556,7 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,

// Must be processed after any other language options that could affect
// platform conditions.
bool UnsupportedOS, UnsupportedArch;
std::tie(UnsupportedOS, UnsupportedArch) = Opts.setTarget(Target);

SmallVector<StringRef, 3> TargetComponents;
TargetArg.split(TargetComponents, "-");

if (UnsupportedArch) {
auto TargetArgArch = TargetComponents.size() ? TargetComponents[0] : "";
Diags.diagnose(SourceLoc(), diag::error_unsupported_target_arch, TargetArgArch);
}

if (UnsupportedOS) {
auto TargetArgOS = TargetComponents.size() > 2 ? TargetComponents[2] : "";
Diags.diagnose(SourceLoc(), diag::error_unsupported_target_os, TargetArgOS);
}
Opts.setTarget(Target, &Diags);

// First, set up default minimum inlining target versions.
auto getDefaultMinimumInliningTargetVersion =
Expand Down Expand Up @@ -1827,7 +1807,7 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.enableFeature(Feature::ParserValidation);
}
#endif
return HadError || UnsupportedOS || UnsupportedArch;
return HadError || Diags.hasFatalErrorOccurred();
}

static bool ParseTypeCheckerArgs(TypeCheckerOptions &Opts, ArgList &Args,
Expand Down
4 changes: 3 additions & 1 deletion lib/Parse/ParseIfConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ class ValidateIfConfigCondition :
return E;
}

// ( 'os' | 'arch' | '_endian' | '_pointerBitWidth' | '_runtime' | '_hasAtomicBitWidth' ) '(' identifier ')''
// ( 'os' | 'arch' | '_endian' | '_pointerBitWidth' | '_runtime' | '_hasAtomicBitWidth' | '_objectFileFormat' ) '(' identifier ')''
auto Kind = getPlatformConditionKind(*KindName);
if (!Kind.has_value()) {
D.diagnose(E->getLoc(), diag::unsupported_platform_condition_expression);
Expand Down Expand Up @@ -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");
}
Expand Down
11 changes: 11 additions & 0 deletions test/Parse/ConditionalCompilation/object_file_format.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// RUN: %swift -typecheck %s -verify -target arm64-apple-none-macho -parse-stdlib
// RUN: %swift -typecheck %s -verify -target arm64-apple-none-elf -parse-stdlib
// RUN: %swift -typecheck %s -verify -target wasm32-unknown-wasi -parse-stdlib
// RUN: %swift -typecheck %s -verify -target x86_64-unknown-windows-msvc -parse-stdlib
// RUN: %swift-ide-test -test-input-complete -source-filename=%s -target arm64-apple-macos

#if _objectFileFormat(MachO) || _objectFileFormat(ELF) || _objectFileFormat(Wasm) || _objectFileFormat(COFF)
class C {}
var x = C()
#endif
var y = x
1 change: 1 addition & 0 deletions unittests/Basic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ add_dependencies(SwiftBasicTests "${gyb_dependency_targets}")
target_link_libraries(SwiftBasicTests
PRIVATE
swiftBasic
swiftFrontend
swiftOption
swiftThreading
clangBasic
Expand Down