@@ -78,8 +78,30 @@ enum class EnforceExclusivityMode {
7878 DynamicOnly,
7979 None,
8080};
81+
82+ enum class SILOptStrictConcurrency {
83+ None = 0 ,
84+ Complete,
85+ Targeted,
86+ Minimal,
87+ };
88+
8189} // end anonymous namespace
8290
91+ std::optional<StrictConcurrency>
92+ convertSILOptToRawStrictConcurrencyLevel (SILOptStrictConcurrency level) {
93+ switch (level) {
94+ case SILOptStrictConcurrency::None:
95+ return {};
96+ case SILOptStrictConcurrency::Complete:
97+ return StrictConcurrency::Complete;
98+ case SILOptStrictConcurrency::Targeted:
99+ return StrictConcurrency::Targeted;
100+ case SILOptStrictConcurrency::Minimal:
101+ return StrictConcurrency::Minimal;
102+ }
103+ }
104+
83105namespace llvm {
84106
85107inline raw_ostream &
@@ -489,15 +511,19 @@ struct SILOptOptions {
489511 cl::value_desc(" format" ), cl::init(" yaml" ));
490512
491513 // Strict Concurrency
492- llvm::cl::opt<StrictConcurrency > StrictConcurrencyLevel =
493- llvm::cl::opt<StrictConcurrency >(
514+ llvm::cl::opt<SILOptStrictConcurrency > StrictConcurrencyLevel =
515+ llvm::cl::opt<SILOptStrictConcurrency >(
494516 " strict-concurrency" , cl::desc(" strict concurrency level" ),
495- llvm::cl::values (clEnumValN(StrictConcurrency::Complete, " complete" ,
496- " Enable complete strict concurrency" ),
497- clEnumValN(StrictConcurrency::Targeted, " targeted" ,
498- " Enable targeted strict concurrency" ),
499- clEnumValN(StrictConcurrency::Minimal, " minimal" ,
500- " Enable minimal strict concurrency" )));
517+ llvm::cl::init (SILOptStrictConcurrency::None),
518+ llvm::cl::values(
519+ clEnumValN (SILOptStrictConcurrency::Complete, " complete" ,
520+ " Enable complete strict concurrency" ),
521+ clEnumValN(SILOptStrictConcurrency::Targeted, " targeted" ,
522+ " Enable targeted strict concurrency" ),
523+ clEnumValN(SILOptStrictConcurrency::Minimal, " minimal" ,
524+ " Enable minimal strict concurrency" ),
525+ clEnumValN(SILOptStrictConcurrency::None, " disabled" ,
526+ " Strict concurrency disabled" )));
501527
502528 llvm::cl::opt<bool >
503529 EnableCxxInterop = llvm::cl::opt<bool >(" enable-experimental-cxx-interop" ,
@@ -693,15 +719,26 @@ int sil_opt_main(ArrayRef<const char *> argv, void *MainAddr) {
693719 options.BypassResilienceChecks ;
694720 Invocation.getDiagnosticOptions ().PrintDiagnosticNames =
695721 options.DebugDiagnosticNames ;
722+
696723 for (auto &featureName : options.UpcomingFeatures ) {
697- if (auto feature = getUpcomingFeature (featureName)) {
698- Invocation.getLangOptions ().enableFeature (*feature);
699- } else {
724+ auto feature = getUpcomingFeature (featureName);
725+ if (!feature) {
700726 llvm::errs () << " error: unknown upcoming feature "
701727 << QuotedString (featureName) << " \n " ;
702728 exit (-1 );
703729 }
730+
731+ if (auto firstVersion = getFeatureLanguageVersion (*feature)) {
732+ if (Invocation.getLangOptions ().isSwiftVersionAtLeast (*firstVersion)) {
733+ llvm::errs () << " error: upcoming feature " << QuotedString (featureName)
734+ << " is already enabled as of Swift version "
735+ << *firstVersion << ' \n ' ;
736+ exit (-1 );
737+ }
738+ }
739+ Invocation.getLangOptions ().enableFeature (*feature);
704740 }
741+
705742 for (auto &featureName : options.ExperimentalFeatures ) {
706743 if (auto feature = getExperimentalFeature (featureName)) {
707744 Invocation.getLangOptions ().enableFeature (*feature);
@@ -735,13 +772,26 @@ int sil_opt_main(ArrayRef<const char *> argv, void *MainAddr) {
735772
736773 Invocation.getLangOptions ().UnavailableDeclOptimizationMode =
737774 options.UnavailableDeclOptimization ;
738- if (options.StrictConcurrencyLevel .hasArgStr ()) {
775+
776+ // Enable strict concurrency if we have the feature specified or if it was
777+ // specified via a command line option to sil-opt.
778+ if (Invocation.getLangOptions ().hasFeature (Feature::StrictConcurrency)) {
739779 Invocation.getLangOptions ().StrictConcurrencyLevel =
740- options.StrictConcurrencyLevel ;
741- if (options.StrictConcurrencyLevel == StrictConcurrency::Complete &&
742- !options.DisableRegionBasedIsolationWithStrictConcurrency ) {
743- Invocation.getLangOptions ().enableFeature (Feature::RegionBasedIsolation);
744- }
780+ StrictConcurrency::Complete;
781+ } else if (auto level = convertSILOptToRawStrictConcurrencyLevel (
782+ options.StrictConcurrencyLevel )) {
783+ // If strict concurrency was enabled from the cmdline so the feature flag as
784+ // well.
785+ if (*level == StrictConcurrency::Complete)
786+ Invocation.getLangOptions ().enableFeature (Feature::StrictConcurrency);
787+ Invocation.getLangOptions ().StrictConcurrencyLevel = *level;
788+ }
789+
790+ // If we have strict concurrency set as a feature and were told to turn off
791+ // region based isolation... do so now.
792+ if (Invocation.getLangOptions ().hasFeature (Feature::StrictConcurrency) &&
793+ !options.DisableRegionBasedIsolationWithStrictConcurrency ) {
794+ Invocation.getLangOptions ().enableFeature (Feature::RegionBasedIsolation);
745795 }
746796
747797 Invocation.getDiagnosticOptions ().VerifyMode =
0 commit comments