Frontend: Add language mode and enabled features to .SWIFT_TRACE.

To allow tooling to analyze use of language mode and experimental/upcoming
features, add that information to the `.SWIFT_TRACE` file.

Resolves rdar://152673681.
This commit is contained in:
Allan Shortlidge
2025-06-05 13:24:22 -07:00
parent 121aa40595
commit 473d83955b
4 changed files with 133 additions and 1 deletions

View File

@@ -65,6 +65,8 @@ struct LoadedModuleTraceFormat {
unsigned Version;
Identifier Name;
std::string Arch;
std::string LanguageMode;
std::vector<StringRef> EnabledLanguageFeatures;
bool StrictMemorySafety;
std::vector<SwiftModuleTraceInfo> SwiftModules;
std::vector<SwiftMacroTraceInfo> SwiftMacros;
@@ -107,6 +109,11 @@ template <> struct ObjectTraits<LoadedModuleTraceFormat> {
out.mapRequired("arch", contents.Arch);
out.mapRequired("languageMode", contents.LanguageMode);
out.mapRequired("enabledLanguageFeatures",
contents.EnabledLanguageFeatures);
out.mapRequired("strictMemorySafety", contents.StrictMemorySafety);
// The 'swiftmodules' key is kept for backwards compatibility.
@@ -723,6 +730,38 @@ computeSwiftMacroTraceInfo(ASTContext &ctx, const DependencyTracker &depTracker,
});
}
static void computeEnabledFeatures(ASTContext &ctx,
std::vector<StringRef> &enabledFeatures) {
struct FeatureAndName {
Feature feature;
StringRef name;
};
static const FeatureAndName features[] = {
#define FEATURE_ENTRY(FeatureName) {Feature::FeatureName, #FeatureName},
#define LANGUAGE_FEATURE(FeatureName, SENumber, Version)
#define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd) \
FEATURE_ENTRY(FeatureName)
#define UPCOMING_FEATURE(FeatureName, SENumber, Version) \
FEATURE_ENTRY(FeatureName)
#define OPTIONAL_LANGUAGE_FEATURE(FeatureName, SENumber, Version) \
FEATURE_ENTRY(FeatureName)
#include "swift/Basic/Features.def"
};
for (auto &featureAndName : features) {
if (ctx.LangOpts.hasFeature(featureAndName.feature))
enabledFeatures.push_back(featureAndName.name);
}
// FIXME: It would be nice if the features were added in sorted order instead.
// However, std::sort is not constexpr until C++20.
std::sort(enabledFeatures.begin(), enabledFeatures.end(),
[](const StringRef &lhs, const StringRef &rhs) -> bool {
return lhs.compare(rhs) < 0;
});
}
// [NOTE: Bailing-vs-crashing-in-trace-emission] There are certain edge cases
// in trace emission where an invariant that you think should hold does not hold
// in practice. For example, sometimes we have seen modules without any
@@ -785,12 +824,18 @@ bool swift::emitLoadedModuleTraceIfNeeded(ModuleDecl *mainModule,
std::vector<SwiftMacroTraceInfo> swiftMacros;
computeSwiftMacroTraceInfo(ctxt, *depTracker, swiftMacros);
std::vector<StringRef> enabledFeatures;
computeEnabledFeatures(ctxt, enabledFeatures);
LoadedModuleTraceFormat trace = {
/*version=*/LoadedModuleTraceFormat::CurrentVersion,
/*name=*/mainModule->getName(),
/*arch=*/ctxt.LangOpts.Target.getArchName().str(),
ctxt.LangOpts.EffectiveLanguageVersion.asAPINotesVersionString(),
enabledFeatures,
mainModule ? mainModule->strictMemorySafety() : false,
swiftModules, swiftMacros};
swiftModules,
swiftMacros};
// raw_fd_ostream is unbuffered, and we may have multiple processes writing,
// so first write to memory and then dump the buffer to the trace file.