22
22
#include " swift/AST/SILOptions.h"
23
23
#include " swift/Basic/Assertions.h"
24
24
#include " swift/Basic/LLVMInitialize.h"
25
+ #include " swift/Basic/QuotedString.h"
25
26
#include " swift/Frontend/DiagnosticVerifier.h"
26
27
#include " swift/Frontend/Frontend.h"
27
28
#include " swift/Frontend/PrintingDiagnosticConsumer.h"
49
50
#include < cstdio>
50
51
using namespace swift ;
51
52
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
+
52
76
struct SILLLVMGenOptions {
53
77
llvm::cl::opt<std::string>
54
78
InputFilename = llvm::cl::opt<std::string>(llvm::cl::desc(" input file" ),
@@ -66,12 +90,29 @@ struct SILLLVMGenOptions {
66
90
FrameworkPaths = llvm::cl::list<std::string>(
67
91
" F" , llvm::cl::desc(" add a directory to the framework search path" ));
68
92
93
+ llvm::cl::list<std::string> VFSOverlays = llvm::cl::list<std::string>(
94
+ " vfsoverlay" , llvm::cl::desc(" add a VFS overlay" ));
95
+
69
96
llvm::cl::opt<std::string>
70
97
ModuleName = llvm::cl::opt<std::string>(" module-name" ,
71
98
llvm::cl::desc (" The name of the module if processing"
72
99
" a module. Necessary for processing "
73
100
" stdin." ));
74
101
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
+
75
116
llvm::cl::opt<std::string>
76
117
ResourceDir = llvm::cl::opt<std::string>(
77
118
" resource-dir" ,
@@ -96,27 +137,94 @@ struct SILLLVMGenOptions {
96
137
llvm::cl::opt<bool >
97
138
PerformWMO = llvm::cl::opt<bool >(" wmo" , llvm::cl::desc(" Enable whole-module optimizations" ));
98
139
99
- llvm::cl::opt<IRGenOutputKind>
100
- OutputKind = llvm::cl::opt<IRGenOutputKind>(
140
+ llvm::cl::opt<IRGenOutputKind> OutputKind = llvm::cl::opt<IRGenOutputKind>(
101
141
" 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" )),
110
153
llvm::cl::init(IRGenOutputKind::ObjectFile));
111
154
112
155
llvm::cl::opt<bool >
113
156
DisableLegacyTypeInfo = llvm::cl::opt<bool >(" disable-legacy-type-info" ,
114
157
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" )));
115
208
};
116
209
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
+
117
222
int sil_llvm_gen_main (ArrayRef<const char *> argv, void *MainAddr) {
118
223
INITIALIZE_LLVM ();
119
224
225
+ llvm::setBugReportMsg (SWIFT_CRASH_BUG_REPORT_MESSAGE " \n " );
226
+ llvm::EnablePrettyStackTraceOnSigInfoForThisThread ();
227
+
120
228
SILLLVMGenOptions options;
121
229
122
230
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) {
139
247
FramePaths.push_back ({path, /* isSystem=*/ false });
140
248
}
141
249
Invocation.setFrameworkSearchPaths (FramePaths);
250
+
251
+ Invocation.setVFSOverlays (options.VFSOverlays );
252
+
142
253
// Set the SDK path and target if given.
143
254
if (options.SDKPath .getNumOccurrences () == 0 ) {
144
255
const char *SDKROOT = getenv (" SDKROOT" );
@@ -151,17 +262,110 @@ int sil_llvm_gen_main(ArrayRef<const char *> argv, void *MainAddr) {
151
262
Invocation.setTargetTriple (options.Target );
152
263
if (!options.ResourceDir .empty ())
153
264
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
+
154
274
// Set the module cache path. If not passed in we use the default swift module
155
275
// cache.
156
276
Invocation.getClangImporterOptions ().ModuleCachePath = options.ModuleCachePath ;
157
277
Invocation.setParseStdlib ();
158
278
159
279
// 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 ();
165
369
166
370
// Setup the IRGen Options.
167
371
IRGenOptions &Opts = Invocation.getIRGenOptions ();
@@ -217,16 +421,26 @@ int sil_llvm_gen_main(ArrayRef<const char *> argv, void *MainAddr) {
217
421
return IRGenDescriptor::forWholeModule (
218
422
mod, Opts, TBDOpts, SILOpts, SILTypes,
219
423
/* SILMod*/ nullptr , moduleName, PSPs);
220
- } else {
221
- return IRGenDescriptor::forFile (
222
- mod->getFiles ()[0 ], Opts, TBDOpts, SILOpts, SILTypes,
223
- /* SILMod*/ nullptr , moduleName, PSPs, /* discriminator*/ " " );
224
424
}
425
+
426
+ return IRGenDescriptor::forFile (
427
+ mod->getFiles ()[0 ], Opts, TBDOpts, SILOpts, SILTypes,
428
+ /* SILMod*/ nullptr , moduleName, PSPs, /* discriminator*/ " " );
225
429
};
226
430
227
431
auto &eval = CI.getASTContext ().evaluator ;
228
432
auto desc = getDescriptor ();
229
433
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
+
230
444
auto generatedMod = evaluateOrFatal (eval, OptimizedIRRequest{desc});
231
445
if (!generatedMod)
232
446
return 1 ;
0 commit comments