Skip to content

[Frontend] Add a way to print features supported by the compiler #80833

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

Merged
merged 2 commits into from
Apr 18, 2025
Merged
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
4 changes: 2 additions & 2 deletions include/swift/Basic/FileTypes.def
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ TYPE("fine-module-trace", FineModuleTrace, "", "")
// Complete dependency information for the given Swift files as JSON.
TYPE("json-dependencies", JSONDependencies, "dependencies.json", "")

// Complete feature information for the given Swift compiler.
TYPE("json-features", JSONFeatures, "features.json", "")
// Complete supported argument information for the given Swift compiler.
TYPE("json-arguments", JSONArguments, "arguments.json", "")

// Gathered compile-time-known value information for the given Swift input file as JSON.
TYPE("const-values", ConstValues, "swiftconstvalues", "")
Expand Down
28 changes: 28 additions & 0 deletions include/swift/Basic/SupportedFeatures.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//===--- SupportedFeatures.h - Supported Features Output --------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file provides a high-level API for supported features info
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_SUPPORTEDFEATURES_H
#define SWIFT_SUPPORTEDFEATURES_H

#include "swift/Basic/LLVM.h"

namespace swift {
namespace features {
void printSupportedFeatures(llvm::raw_ostream &out);
} // namespace features
} // namespace swift

#endif
6 changes: 5 additions & 1 deletion include/swift/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ class FrontendOptions {

ScanDependencies, ///< Scan dependencies of Swift source files
PrintVersion, ///< Print version information.
PrintFeature, ///< Print supported feature of this compiler
PrintArguments, ///< Print supported arguments of this compiler
};

/// Indicates the action the user requested that the frontend perform.
Expand Down Expand Up @@ -314,6 +314,10 @@ class FrontendOptions {
/// exit.
bool PrintTargetInfo = false;

/// Indicates that the frontend should print the supported features and then
/// exit.
bool PrintSupportedFeatures = false;

/// See the \ref SILOptions.EmitVerboseSIL flag.
bool EmitVerboseSIL = false;

Expand Down
12 changes: 10 additions & 2 deletions include/swift/Option/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,10 @@ def print_target_info : Flag<["-"], "print-target-info">,
Flags<[FrontendOption]>,
HelpText<"Print target information for the given target <triple>, such as x86_64-apple-macos10.9">, MetaVarName<"<triple>">;

def print_supported_features : Flag<["-"], "print-supported-features">,
Flags<[FrontendOption]>,
HelpText<"Print information about features supported by the compiler">;

def target_cpu : Separate<["-"], "target-cpu">, Flags<[FrontendOption, ModuleInterfaceOption]>,
HelpText<"Generate code for a particular CPU variant">;

Expand Down Expand Up @@ -1650,9 +1654,13 @@ def scan_dependencies : Flag<["-"], "scan-dependencies">,
HelpText<"Scan dependencies of the given Swift sources">, ModeOpt,
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>;

def emit_supported_features : Flag<["-"], "emit-supported-features">,
HelpText<"Emit a JSON file including all supported compiler features">, ModeOpt,
def emit_supported_arguments : Flag<["-"], "emit-supported-arguments">,
HelpText<"Emit a JSON file including all supported compiler arguments">, ModeOpt,
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>;
def emit_supported_features : Flag<["-"], "emit-supported-features">,
HelpText<"This is a compatibility alias for '-emit-supported-arguments'">, ModeOpt,
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild, HelpHidden]>,
Alias<emit_supported_arguments>;

def enable_incremental_imports :
Flag<["-"], "enable-incremental-imports">,
Expand Down
1 change: 1 addition & 0 deletions lib/Basic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ add_swift_host_library(swiftBasic STATIC
StableHasher.cpp
Statistic.cpp
StringExtras.cpp
SupportedFeatures.cpp
TargetInfo.cpp
TaskQueue.cpp
ThreadSafeRefCounted.cpp
Expand Down
8 changes: 4 additions & 4 deletions lib/Basic/FileTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ bool file_types::isTextual(ID Id) {
case file_types::TY_PackageSwiftModuleInterfaceFile:
case file_types::TY_SwiftOverlayFile:
case file_types::TY_JSONDependencies:
case file_types::TY_JSONFeatures:
case file_types::TY_JSONArguments:
case file_types::TY_SwiftABIDescriptor:
case file_types::TY_SwiftAPIDescriptor:
case file_types::TY_ConstValues:
Expand Down Expand Up @@ -195,7 +195,7 @@ bool file_types::isAfterLLVM(ID Id) {
case file_types::TY_PrivateSwiftModuleInterfaceFile:
case file_types::TY_PackageSwiftModuleInterfaceFile:
case file_types::TY_JSONDependencies:
case file_types::TY_JSONFeatures:
case file_types::TY_JSONArguments:
case file_types::TY_IndexUnitOutputPath:
case file_types::TY_SwiftABIDescriptor:
case file_types::TY_SwiftAPIDescriptor:
Expand Down Expand Up @@ -257,7 +257,7 @@ bool file_types::isPartOfSwiftCompilation(ID Id) {
case file_types::TY_YAMLOptRecord:
case file_types::TY_BitstreamOptRecord:
case file_types::TY_JSONDependencies:
case file_types::TY_JSONFeatures:
case file_types::TY_JSONArguments:
case file_types::TY_IndexUnitOutputPath:
case file_types::TY_SwiftABIDescriptor:
case file_types::TY_SwiftAPIDescriptor:
Expand Down Expand Up @@ -321,7 +321,7 @@ bool file_types::isProducedFromDiagnostics(ID Id) {
case file_types::TY_YAMLOptRecord:
case file_types::TY_BitstreamOptRecord:
case file_types::TY_JSONDependencies:
case file_types::TY_JSONFeatures:
case file_types::TY_JSONArguments:
case file_types::TY_IndexUnitOutputPath:
case file_types::TY_SwiftABIDescriptor:
case file_types::TY_SwiftAPIDescriptor:
Expand Down
74 changes: 74 additions & 0 deletions lib/Basic/SupportedFeatures.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//===--- SupportedFeatures.cpp - Supported features printing --------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include <array>
#include <vector>

#include "swift/Basic/Feature.h"
#include "swift/Frontend/Frontend.h"

#include "llvm/Support/raw_ostream.h"

using namespace swift;

namespace swift {
namespace features {
/// Print information about what features upcoming/experimental are
/// supported by the compiler.
/// The information includes whether a feature is adoptable and for
/// upcoming features - what is the first mode it's introduced.
void printSupportedFeatures(llvm::raw_ostream &out) {
std::array upcoming{
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description)
#define UPCOMING_FEATURE(FeatureName, SENumber, Version) Feature::FeatureName,
#include "swift/Basic/Features.def"
};

std::vector<swift::Feature> experimental{{
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description)
#define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd) Feature::FeatureName,
#include "swift/Basic/Features.def"
}};

// Include only experimental features that are available in production.
llvm::erase_if(experimental, [](auto &feature) {
return feature.isAvailableInProduction();
});

out << "{\n";
auto printFeature = [&out](const Feature &feature) {
out << " ";
out << "{ \"name\": \"" << feature.getName() << "\"";
if (feature.isAdoptable()) {
out << ", \"migratable\": true";
}
if (auto version = feature.getLanguageVersion()) {
out << ", \"enabled_in\": " << *version;
}
out << " }";
};

out << " \"features\": {\n";
out << " \"upcoming\": [\n";
llvm::interleave(upcoming, printFeature, [&out] { out << ",\n"; });
out << "\n ],\n";

out << " \"experimental\": [\n";
llvm::interleave(experimental, printFeature, [&out] { out << ",\n"; });
out << "\n ]\n";

out << " }\n";
out << "}\n";
}

} // end namespace features
} // end namespace swift
24 changes: 23 additions & 1 deletion lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1708,7 +1708,7 @@ void Driver::buildActions(SmallVectorImpl<const Action *> &TopLevelActions,
case file_types::TY_SwiftCrossImportDir:
case file_types::TY_SwiftOverlayFile:
case file_types::TY_JSONDependencies:
case file_types::TY_JSONFeatures:
case file_types::TY_JSONArguments:
case file_types::TY_SwiftABIDescriptor:
case file_types::TY_SwiftAPIDescriptor:
case file_types::TY_ConstValues:
Expand Down Expand Up @@ -2049,6 +2049,28 @@ bool Driver::handleImmediateArgs(const ArgList &Args, const ToolChain &TC) {
return false;
}

if (Args.hasArg(options::OPT_print_supported_features)) {
SmallVector<const char *, 5> commandLine;
commandLine.push_back("-frontend");
commandLine.push_back("-print-supported-features");

std::string executable = getSwiftProgramPath();

// FIXME(https://github.com/apple/swift/issues/54554): This bypasses
// mechanisms like -v and -###.
sys::TaskQueue queue;
queue.addTask(executable.c_str(), commandLine);
queue.execute(nullptr,
[](sys::ProcessId PID, int returnCode, StringRef output,
StringRef errors, sys::TaskProcessInformation ProcInfo,
void *unused) -> sys::TaskFinishedResponse {
llvm::outs() << output;
llvm::errs() << errors;
return sys::TaskFinishedResponse::ContinueExecution;
});
return false;
}

return true;
}

Expand Down
6 changes: 3 additions & 3 deletions lib/Driver/ToolChains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -754,8 +754,8 @@ const char *ToolChain::JobContext::computeFrontendModeForCompile() const {
return "-emit-imported-modules";
case file_types::TY_JSONDependencies:
return "-scan-dependencies";
case file_types::TY_JSONFeatures:
return "-emit-supported-features";
case file_types::TY_JSONArguments:
return "-emit-supported-arguments";
case file_types::TY_IndexData:
return "-typecheck";
case file_types::TY_Remapping:
Expand Down Expand Up @@ -1041,7 +1041,7 @@ ToolChain::constructInvocation(const BackendJobAction &job,
case file_types::TY_ClangModuleFile:
case file_types::TY_IndexData:
case file_types::TY_JSONDependencies:
case file_types::TY_JSONFeatures:
case file_types::TY_JSONArguments:
llvm_unreachable("Cannot be output from backend job");
case file_types::TY_Swift:
case file_types::TY_dSYM:
Expand Down
8 changes: 6 additions & 2 deletions lib/Frontend/ArgsToFrontendOptionsConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ bool ArgsToFrontendOptionsConverter::convert(
Opts.PrintTargetInfo = true;
}

if (Args.hasArg(OPT_print_supported_features)) {
Opts.PrintSupportedFeatures = true;
}

if (const Arg *A = Args.getLastArg(OPT_verify_generic_signatures)) {
Opts.VerifyGenericSignaturesInModule = A->getValue();
}
Expand Down Expand Up @@ -678,8 +682,8 @@ ArgsToFrontendOptionsConverter::determineRequestedAction(const ArgList &args) {
return FrontendOptions::ActionType::CompileModuleFromInterface;
if (Opt.matches(OPT_typecheck_module_from_interface))
return FrontendOptions::ActionType::TypecheckModuleFromInterface;
if (Opt.matches(OPT_emit_supported_features))
return FrontendOptions::ActionType::PrintFeature;
if (Opt.matches(OPT_emit_supported_arguments))
return FrontendOptions::ActionType::PrintArguments;
llvm_unreachable("Unhandled mode option");
}

Expand Down
2 changes: 1 addition & 1 deletion lib/Frontend/ArgsToFrontendOutputsConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ static bool shouldEmitFineModuleTrace(FrontendOptions::ActionType action) {
case swift::FrontendOptions::ActionType::DumpPCM:
case swift::FrontendOptions::ActionType::ScanDependencies:
case swift::FrontendOptions::ActionType::PrintVersion:
case swift::FrontendOptions::ActionType::PrintFeature:
case swift::FrontendOptions::ActionType::PrintArguments:
return false;
}
}
Expand Down
Loading