2222#include " swift/AST/SILOptions.h"
2323#include " swift/Basic/Assertions.h"
2424#include " swift/Basic/LLVMInitialize.h"
25+ #include " swift/Basic/QuotedString.h"
2526#include " swift/Frontend/DiagnosticVerifier.h"
2627#include " swift/Frontend/Frontend.h"
2728#include " swift/Frontend/PrintingDiagnosticConsumer.h"
4950#include < cstdio>
5051using namespace swift ;
5152
53+ namespace {
54+ enum class SILOptStrictConcurrency {
55+ None = 0 ,
56+ Complete,
57+ Targeted,
58+ Minimal,
59+ };
60+ }
61+
62+ static std::optional<StrictConcurrency>
63+ convertSILOptToRawStrictConcurrencyLevel (SILOptStrictConcurrency level) {
64+ switch (level) {
65+ case SILOptStrictConcurrency::None:
66+ return {};
67+ case SILOptStrictConcurrency::Complete:
68+ return StrictConcurrency::Complete;
69+ case SILOptStrictConcurrency::Targeted:
70+ return StrictConcurrency::Targeted;
71+ case SILOptStrictConcurrency::Minimal:
72+ return StrictConcurrency::Minimal;
73+ }
74+ }
75+
5276struct SILLLVMGenOptions {
5377 llvm::cl::opt<std::string>
5478 InputFilename = llvm::cl::opt<std::string>(llvm::cl::desc(" input file" ),
@@ -66,12 +90,29 @@ struct SILLLVMGenOptions {
6690 FrameworkPaths = llvm::cl::list<std::string>(
6791 " F" , llvm::cl::desc(" add a directory to the framework search path" ));
6892
93+ llvm::cl::list<std::string> VFSOverlays = llvm::cl::list<std::string>(
94+ " vfsoverlay" , llvm::cl::desc(" add a VFS overlay" ));
95+
6996 llvm::cl::opt<std::string>
7097 ModuleName = llvm::cl::opt<std::string>(" module-name" ,
7198 llvm::cl::desc (" The name of the module if processing"
7299 " a module. Necessary for processing "
73100 " stdin." ));
74101
102+ llvm::cl::opt<bool > StrictImplicitModuleContext = llvm::cl::opt<bool >(
103+ " strict-implicit-module-context" ,
104+ llvm::cl::desc (" Enable the strict forwarding of compilation "
105+ " context to downstream implicit module dependencies" ));
106+
107+ llvm::cl::opt<bool > DisableImplicitModules =
108+ llvm::cl::opt<bool >(" disable-implicit-swift-modules" ,
109+ llvm::cl::desc (" Disable implicit swift modules." ));
110+
111+ llvm::cl::opt<std::string> ExplicitSwiftModuleMapPath =
112+ llvm::cl::opt<std::string>(
113+ " explicit-swift-module-map-file" ,
114+ llvm::cl::desc (" Explict swift module map file path" ));
115+
75116 llvm::cl::opt<std::string>
76117 ResourceDir = llvm::cl::opt<std::string>(
77118 " resource-dir" ,
@@ -96,27 +137,94 @@ struct SILLLVMGenOptions {
96137 llvm::cl::opt<bool >
97138 PerformWMO = llvm::cl::opt<bool >(" wmo" , llvm::cl::desc(" Enable whole-module optimizations" ));
98139
99- llvm::cl::opt<IRGenOutputKind>
100- OutputKind = llvm::cl::opt<IRGenOutputKind>(
140+ llvm::cl::opt<IRGenOutputKind> OutputKind = llvm::cl::opt<IRGenOutputKind>(
101141 " output-kind" , llvm::cl::desc(" Type of output to produce" ),
102- llvm::cl::values (clEnumValN(IRGenOutputKind::LLVMAssemblyAfterOptimization,
103- " llvm-as" , " Emit llvm assembly" ),
104- clEnumValN(IRGenOutputKind::LLVMBitcode, " llvm-bc" ,
105- " Emit llvm bitcode" ),
106- clEnumValN(IRGenOutputKind::NativeAssembly, " as" ,
107- " Emit native assembly" ),
108- clEnumValN(IRGenOutputKind::ObjectFile, " object" ,
109- " Emit an object file" )),
142+ llvm::cl::values (
143+ clEnumValN (IRGenOutputKind::LLVMAssemblyBeforeOptimization, " llvm-as" ,
144+ " Emit llvm assembly before optimization" ),
145+ clEnumValN(IRGenOutputKind::LLVMAssemblyAfterOptimization,
146+ " llvm-as-opt" , " Emit llvm assembly after optimization" ),
147+ clEnumValN(IRGenOutputKind::LLVMBitcode, " llvm-bc" ,
148+ " Emit llvm bitcode" ),
149+ clEnumValN(IRGenOutputKind::NativeAssembly, " as" ,
150+ " Emit native assembly" ),
151+ clEnumValN(IRGenOutputKind::ObjectFile, " object" ,
152+ " Emit an object file" )),
110153 llvm::cl::init(IRGenOutputKind::ObjectFile));
111154
112155 llvm::cl::opt<bool >
113156 DisableLegacyTypeInfo = llvm::cl::opt<bool >(" disable-legacy-type-info" ,
114157 llvm::cl::desc (" Don't try to load backward deployment layouts" ));
158+
159+ llvm::cl::opt<std::string> SwiftVersionString = llvm::cl::opt<std::string>(
160+ " swift-version" ,
161+ llvm::cl::desc (
162+ " The swift version to assume AST declarations correspond to" ));
163+
164+ llvm::cl::opt<bool > EnableExperimentalConcurrency = llvm::cl::opt<bool >(
165+ " enable-experimental-concurrency" ,
166+ llvm::cl::desc (" Enable experimental concurrency model." ));
167+
168+ llvm::cl::opt<llvm::cl::boolOrDefault> EnableExperimentalMoveOnly =
169+ llvm::cl::opt<llvm::cl::boolOrDefault>(
170+ " enable-experimental-move-only" , llvm::cl::init(llvm::cl::BOU_UNSET),
171+ llvm::cl::desc(" Enable experimental move-only semantics." ));
172+
173+ llvm::cl::list<std::string> ExperimentalFeatures =
174+ llvm::cl::list<std::string>(
175+ " enable-experimental-feature" ,
176+ llvm::cl::desc (" Enable the given experimental feature." ));
177+
178+ llvm::cl::list<std::string> UpcomingFeatures = llvm::cl::list<std::string>(
179+ " enable-upcoming-feature" ,
180+ llvm::cl::desc (" Enable the given upcoming feature." ));
181+
182+ llvm::cl::opt<bool > EnableCxxInterop = llvm::cl::opt<bool >(
183+ " enable-experimental-cxx-interop" , llvm::cl::desc(" Enable C++ interop." ),
184+ llvm::cl::init (false ));
185+
186+ llvm::cl::opt<bool > EnableObjCInterop = llvm::cl::opt<bool >(
187+ " enable-objc-interop" ,
188+ llvm::cl::desc (" Enable Objective-C interoperability." ));
189+
190+ llvm::cl::opt<bool > DisableObjCInterop = llvm::cl::opt<bool >(
191+ " disable-objc-interop" ,
192+ llvm::cl::desc (" Disable Objective-C interoperability." ));
193+
194+ // Strict Concurrency
195+ llvm::cl::opt<SILOptStrictConcurrency> StrictConcurrencyLevel =
196+ llvm::cl::opt<SILOptStrictConcurrency>(
197+ " strict-concurrency" , llvm::cl::desc(" strict concurrency level" ),
198+ llvm::cl::init (SILOptStrictConcurrency::None),
199+ llvm::cl::values(
200+ clEnumValN (SILOptStrictConcurrency::Complete, " complete" ,
201+ " Enable complete strict concurrency" ),
202+ clEnumValN(SILOptStrictConcurrency::Targeted, " targeted" ,
203+ " Enable targeted strict concurrency" ),
204+ clEnumValN(SILOptStrictConcurrency::Minimal, " minimal" ,
205+ " Enable minimal strict concurrency" ),
206+ clEnumValN(SILOptStrictConcurrency::None, " disabled" ,
207+ " Strict concurrency disabled" )));
115208};
116209
210+ static std::optional<bool > toOptionalBool (llvm::cl::boolOrDefault defaultable) {
211+ switch (defaultable) {
212+ case llvm::cl::BOU_TRUE:
213+ return true ;
214+ case llvm::cl::BOU_FALSE:
215+ return false ;
216+ case llvm::cl::BOU_UNSET:
217+ return std::nullopt ;
218+ }
219+ llvm_unreachable (" Bad case for llvm::cl::boolOrDefault!" );
220+ }
221+
117222int sil_llvm_gen_main (ArrayRef<const char *> argv, void *MainAddr) {
118223 INITIALIZE_LLVM ();
119224
225+ llvm::setBugReportMsg (SWIFT_CRASH_BUG_REPORT_MESSAGE " \n " );
226+ llvm::EnablePrettyStackTraceOnSigInfoForThisThread ();
227+
120228 SILLLVMGenOptions options;
121229
122230 llvm::cl::ParseCommandLineOptions (argv.size (), argv.data (), " Swift LLVM IR Generator\n " );
@@ -139,6 +247,9 @@ int sil_llvm_gen_main(ArrayRef<const char *> argv, void *MainAddr) {
139247 FramePaths.push_back ({path, /* isSystem=*/ false });
140248 }
141249 Invocation.setFrameworkSearchPaths (FramePaths);
250+
251+ Invocation.setVFSOverlays (options.VFSOverlays );
252+
142253 // Set the SDK path and target if given.
143254 if (options.SDKPath .getNumOccurrences () == 0 ) {
144255 const char *SDKROOT = getenv (" SDKROOT" );
@@ -151,17 +262,110 @@ int sil_llvm_gen_main(ArrayRef<const char *> argv, void *MainAddr) {
151262 Invocation.setTargetTriple (options.Target );
152263 if (!options.ResourceDir .empty ())
153264 Invocation.setRuntimeResourcePath (options.ResourceDir );
265+
266+ Invocation.getFrontendOptions ().StrictImplicitModuleContext =
267+ options.StrictImplicitModuleContext ;
268+
269+ Invocation.getFrontendOptions ().DisableImplicitModules =
270+ options.DisableImplicitModules ;
271+ Invocation.getSearchPathOptions ().ExplicitSwiftModuleMapPath =
272+ options.ExplicitSwiftModuleMapPath ;
273+
154274 // Set the module cache path. If not passed in we use the default swift module
155275 // cache.
156276 Invocation.getClangImporterOptions ().ModuleCachePath = options.ModuleCachePath ;
157277 Invocation.setParseStdlib ();
158278
159279 // Setup the language options
160- auto &LangOpts = Invocation.getLangOptions ();
161- LangOpts.DisableAvailabilityChecking = true ;
162- LangOpts.EnableAccessControl = false ;
163- LangOpts.EnableObjCAttrRequiresFoundation = false ;
164- LangOpts.EnableObjCInterop = LangOpts.Target .isOSDarwin ();
280+ if (options.SwiftVersionString .size ()) {
281+ auto vers = VersionParser::parseVersionString (options.SwiftVersionString ,
282+ SourceLoc (), nullptr );
283+ bool isValid = false ;
284+ if (vers.has_value ()) {
285+ if (auto effectiveVers = vers.value ().getEffectiveLanguageVersion ()) {
286+ Invocation.getLangOptions ().EffectiveLanguageVersion =
287+ effectiveVers.value ();
288+ isValid = true ;
289+ }
290+ }
291+ if (!isValid) {
292+ llvm::errs () << " error: invalid swift version "
293+ << options.SwiftVersionString << ' \n ' ;
294+ exit (-1 );
295+ }
296+ }
297+ Invocation.getLangOptions ().DisableAvailabilityChecking = true ;
298+ Invocation.getLangOptions ().EnableAccessControl = false ;
299+ Invocation.getLangOptions ().EnableObjCAttrRequiresFoundation = false ;
300+ Invocation.getLangOptions ().EnableDeserializationSafety = false ;
301+ Invocation.getLangOptions ().EnableExperimentalConcurrency =
302+ options.EnableExperimentalConcurrency ;
303+ std::optional<bool > enableExperimentalMoveOnly =
304+ toOptionalBool (options.EnableExperimentalMoveOnly );
305+ if (enableExperimentalMoveOnly && *enableExperimentalMoveOnly) {
306+ // FIXME: drop addition of Feature::MoveOnly once its queries are gone.
307+ Invocation.getLangOptions ().enableFeature (Feature::MoveOnly);
308+ Invocation.getLangOptions ().enableFeature (Feature::NoImplicitCopy);
309+ Invocation.getLangOptions ().enableFeature (
310+ Feature::OldOwnershipOperatorSpellings);
311+ }
312+
313+ for (auto &featureName : options.UpcomingFeatures ) {
314+ auto feature = Feature::getUpcomingFeature (featureName);
315+ if (!feature) {
316+ llvm::errs () << " error: unknown upcoming feature "
317+ << QuotedString (featureName) << " \n " ;
318+ exit (-1 );
319+ }
320+
321+ if (auto firstVersion = feature->getLanguageVersion ()) {
322+ if (Invocation.getLangOptions ().isSwiftVersionAtLeast (*firstVersion)) {
323+ llvm::errs () << " error: upcoming feature " << QuotedString (featureName)
324+ << " is already enabled as of Swift version "
325+ << *firstVersion << ' \n ' ;
326+ exit (-1 );
327+ }
328+ }
329+ Invocation.getLangOptions ().enableFeature (*feature);
330+ }
331+
332+ for (auto &featureName : options.ExperimentalFeatures ) {
333+ if (auto feature = Feature::getExperimentalFeature (featureName)) {
334+ Invocation.getLangOptions ().enableFeature (*feature);
335+ } else {
336+ llvm::errs () << " error: unknown experimental feature "
337+ << QuotedString (featureName) << " \n " ;
338+ exit (-1 );
339+ }
340+ }
341+
342+ // Enable strict concurrency if we have the feature specified or if it was
343+ // specified via a command line option to sil-opt.
344+ if (Invocation.getLangOptions ().hasFeature (Feature::StrictConcurrency)) {
345+ Invocation.getLangOptions ().StrictConcurrencyLevel =
346+ StrictConcurrency::Complete;
347+ } else if (auto level = convertSILOptToRawStrictConcurrencyLevel (
348+ options.StrictConcurrencyLevel )) {
349+ // If strict concurrency was enabled from the cmdline so the feature flag as
350+ // well.
351+ if (*level == StrictConcurrency::Complete)
352+ Invocation.getLangOptions ().enableFeature (Feature::StrictConcurrency);
353+ Invocation.getLangOptions ().StrictConcurrencyLevel = *level;
354+ }
355+
356+ // If we have strict concurrency set as a feature and were told to turn off
357+ // region-based isolation... do so now.
358+ if (Invocation.getLangOptions ().hasFeature (Feature::StrictConcurrency)) {
359+ Invocation.getLangOptions ().enableFeature (Feature::RegionBasedIsolation);
360+ }
361+
362+ Invocation.getLangOptions ().EnableObjCInterop =
363+ options.EnableObjCInterop ? true
364+ : options.DisableObjCInterop ? false
365+ : llvm::Triple (options.Target ).isOSDarwin ();
366+
367+ Invocation.getLangOptions ().EnableCXXInterop = options.EnableCxxInterop ;
368+ Invocation.computeCXXStdlibOptions ();
165369
166370 // Setup the IRGen Options.
167371 IRGenOptions &Opts = Invocation.getIRGenOptions ();
@@ -217,16 +421,26 @@ int sil_llvm_gen_main(ArrayRef<const char *> argv, void *MainAddr) {
217421 return IRGenDescriptor::forWholeModule (
218422 mod, Opts, TBDOpts, SILOpts, SILTypes,
219423 /* SILMod*/ nullptr , moduleName, PSPs);
220- } else {
221- return IRGenDescriptor::forFile (
222- mod->getFiles ()[0 ], Opts, TBDOpts, SILOpts, SILTypes,
223- /* SILMod*/ nullptr , moduleName, PSPs, /* discriminator*/ " " );
224424 }
425+
426+ return IRGenDescriptor::forFile (
427+ mod->getFiles ()[0 ], Opts, TBDOpts, SILOpts, SILTypes,
428+ /* SILMod*/ nullptr , moduleName, PSPs, /* discriminator*/ " " );
225429 };
226430
227431 auto &eval = CI.getASTContext ().evaluator ;
228432 auto desc = getDescriptor ();
229433 desc.out = &outFile->getOS ();
434+
435+ if (options.OutputKind == IRGenOutputKind::LLVMAssemblyBeforeOptimization) {
436+ auto generatedMod = evaluateOrFatal (eval, IRGenRequest{desc});
437+ if (!generatedMod)
438+ return 1 ;
439+
440+ generatedMod.getModule ()->print (*outFile, nullptr );
441+ return 0 ;
442+ }
443+
230444 auto generatedMod = evaluateOrFatal (eval, OptimizedIRRequest{desc});
231445 if (!generatedMod)
232446 return 1 ;
0 commit comments