@@ -284,191 +284,247 @@ bool SILDeclRef::isImplicit() const {
284
284
llvm_unreachable (" Unhandled case in switch" );
285
285
}
286
286
287
- SILLinkage SILDeclRef::getLinkage (ForDefinition_t forDefinition) const {
288
-
289
- // Prespecializations are public.
290
- if (getSpecializedSignature ()) {
291
- return SILLinkage::Public;
292
- }
293
-
294
- if (getAbstractClosureExpr ()) {
295
- return isSerialized () ? SILLinkage::Shared : SILLinkage::Private;
296
- }
297
-
298
- // The main entry-point is public.
299
- if (kind == Kind::EntryPoint)
300
- return SILLinkage::Public;
301
- if (kind == Kind::AsyncEntryPoint)
302
- return SILLinkage::Hidden;
303
-
304
- // Add External to the linkage (e.g. Public -> PublicExternal) if this is a
305
- // declaration not a definition.
306
- auto maybeAddExternal = [&](SILLinkage linkage) {
307
- return forDefinition ? linkage : addExternalToLinkage (linkage);
308
- };
309
-
310
- ValueDecl *d = getDecl ();
311
-
312
- // Property wrapper generators of public functions have PublicNonABI linkage
313
- if (isPropertyWrapperBackingInitializer () && isa<ParamDecl>(d)) {
314
- if (isSerialized ())
315
- return maybeAddExternal (SILLinkage::PublicNonABI);
316
- }
317
-
318
- // Function-local declarations have private linkage, unless serialized.
319
- DeclContext *moduleContext = d->getDeclContext ();
320
- while (!moduleContext->isModuleScopeContext ()) {
321
- if (moduleContext->isLocalContext ()) {
322
- return isSerialized () ? SILLinkage::Shared : SILLinkage::Private;
287
+ namespace {
288
+ enum class LinkageLimit {
289
+ // / No limit.
290
+ None,
291
+ // / The linkage should behave as if the decl is private.
292
+ Private,
293
+ // / The declaration is emitted on-demand; it should end up with internal
294
+ // / or shared linkage.
295
+ OnDemand,
296
+ // / The declaration should never be made public.
297
+ NeverPublic,
298
+ // / The declaration should always be emitted into the client,
299
+ AlwaysEmitIntoClient,
300
+ };
301
+ } // end anonymous namespace
302
+
303
+ // / Compute the linkage limit for a given SILDeclRef. This augments the
304
+ // / mapping of access level to linkage to provide a maximum or minimum linkage.
305
+ static LinkageLimit getLinkageLimit (SILDeclRef constant) {
306
+ using Limit = LinkageLimit;
307
+ using Kind = SILDeclRef::Kind;
308
+
309
+ auto *d = constant.getDecl ();
310
+
311
+ // Back deployment thunks and fallbacks are emitted into the client.
312
+ if (constant.backDeploymentKind != SILDeclRef::BackDeploymentKind::None)
313
+ return Limit::AlwaysEmitIntoClient;
314
+
315
+ if (auto *fn = dyn_cast<AbstractFunctionDecl>(d)) {
316
+ // Native-to-foreign thunks for top-level decls are created on-demand,
317
+ // unless they are marked @_cdecl, in which case they expose a dedicated
318
+ // entry-point with the visibility of the function.
319
+ //
320
+ // Native-to-foreign thunks for methods are always just private, since
321
+ // they're anchored by Objective-C metadata.
322
+ auto &attrs = fn->getAttrs ();
323
+ if (constant.isNativeToForeignThunk () && !attrs.hasAttribute <CDeclAttr>()) {
324
+ auto isTopLevel = fn->getDeclContext ()->isModuleScopeContext ();
325
+ return isTopLevel ? Limit::OnDemand : Limit::Private;
323
326
}
324
- moduleContext = moduleContext->getParent ();
325
327
}
326
328
327
- // Calling convention thunks have shared linkage.
328
- if (isForeignToNativeThunk ())
329
- return SILLinkage::Shared;
330
-
331
- // Declarations imported from Clang modules have shared linkage.
332
- if (isClangImported ())
333
- return SILLinkage::Shared;
334
-
335
- // Default argument generators of Public functions have PublicNonABI linkage
336
- // if the function was type-checked in Swift 4 mode.
337
- if (kind == SILDeclRef::Kind::DefaultArgGenerator) {
338
- if (isSerialized ())
339
- return maybeAddExternal (SILLinkage::PublicNonABI);
329
+ if (auto fn = constant.getFuncDecl ()) {
330
+ // Forced-static-dispatch functions are created on-demand and have
331
+ // at best shared linkage.
332
+ if (fn->hasForcedStaticDispatch ())
333
+ return Limit::OnDemand;
340
334
}
341
335
342
- // Back deployment thunks and fallbacks are emitted into the client and
343
- // therefore have PublicNonABI linkage.
344
- if (backDeploymentKind != SILDeclRef::BackDeploymentKind::None)
345
- return maybeAddExternal (SILLinkage::PublicNonABI);
346
-
347
- enum class Limit {
348
- // / No limit.
349
- None,
350
- // / The declaration is emitted on-demand; it should end up with internal
351
- // / or shared linkage.
352
- OnDemand,
353
- // / The declaration should never be made public.
354
- NeverPublic,
355
- // / The declaration should always be emitted into the client,
356
- AlwaysEmitIntoClient,
357
- };
358
- auto limit = Limit::None;
359
-
360
- // @_alwaysEmitIntoClient declarations are like the default arguments of
361
- // public functions; they are roots for dead code elimination and have
362
- // serialized bodies, but no public symbol in the generated binary.
363
- if (d->getAttrs ().hasAttribute <AlwaysEmitIntoClientAttr>())
364
- limit = Limit::AlwaysEmitIntoClient;
365
- if (auto accessor = dyn_cast<AccessorDecl>(d)) {
366
- auto *storage = accessor->getStorage ();
367
- if (storage->getAttrs ().hasAttribute <AlwaysEmitIntoClientAttr>())
368
- limit = Limit::AlwaysEmitIntoClient;
336
+ switch (constant.kind ) {
337
+ case Kind::Func:
338
+ case Kind::Allocator:
339
+ case Kind::Initializer:
340
+ case Kind::Deallocator:
341
+ case Kind::Destroyer: {
342
+ // @_alwaysEmitIntoClient declarations are like the default arguments of
343
+ // public functions; they are roots for dead code elimination and have
344
+ // serialized bodies, but no public symbol in the generated binary.
345
+ if (d->getAttrs ().hasAttribute <AlwaysEmitIntoClientAttr>())
346
+ return Limit::AlwaysEmitIntoClient;
347
+ if (auto accessor = dyn_cast<AccessorDecl>(d)) {
348
+ auto *storage = accessor->getStorage ();
349
+ if (storage->getAttrs ().hasAttribute <AlwaysEmitIntoClientAttr>())
350
+ return Limit::AlwaysEmitIntoClient;
351
+ }
352
+ break ;
369
353
}
370
-
371
- // ivar initializers and destroyers are completely contained within the class
372
- // from which they come, and never get seen externally.
373
- if (isIVarInitializerOrDestroyer ()) {
374
- limit = Limit::NeverPublic;
354
+ case Kind::EnumElement:
355
+ return Limit::OnDemand;
356
+
357
+ case Kind::GlobalAccessor:
358
+ return cast<VarDecl>(d)->isResilient () ? Limit::NeverPublic : Limit::None;
359
+
360
+ case Kind::DefaultArgGenerator:
361
+ // If the default argument is to be serialized, only use non-ABI public
362
+ // linkage. If the argument is not to be serialized, don't use a limit.
363
+ // This actually means that default arguments *can be ABI public* if
364
+ // `isSerialized()` returns false and the effective access level is public,
365
+ // which happens under `-enable-testing` with an internal decl.
366
+ return constant.isSerialized () ? Limit::AlwaysEmitIntoClient : Limit::None;
367
+
368
+ case Kind::PropertyWrapperBackingInitializer:
369
+ case Kind::PropertyWrapperInitFromProjectedValue: {
370
+ if (!d->getDeclContext ()->isTypeContext ()) {
371
+ // If the backing initializer is to be serialized, only use non-ABI public
372
+ // linkage. If the initializer is not to be serialized, don't use a limit.
373
+ // This actually means that it *can be ABI public* if `isSerialized()`
374
+ // returns false and the effective access level is public, which happens
375
+ // under `-enable-testing` with an internal decl.
376
+ return constant.isSerialized () ? Limit::AlwaysEmitIntoClient
377
+ : Limit::None;
378
+ }
379
+ // Otherwise, regular property wrapper backing initializers (for properties)
380
+ // are treated just like stored property intializers.
381
+ LLVM_FALLTHROUGH;
375
382
}
376
-
377
- // Stored property initializers get the linkage of their containing type.
378
- if (isStoredPropertyInitializer () || isPropertyWrapperBackingInitializer ()) {
379
- // Three cases:
383
+ case Kind::StoredPropertyInitializer: {
384
+ // Stored property initializers get the linkage of their containing type.
385
+ // There are three cases:
380
386
//
381
387
// 1) Type is formally @_fixed_layout/@frozen. Root initializers can be
382
388
// declared @inlinable. The property initializer must only reference
383
389
// public symbols, and is serialized, so we give it PublicNonABI linkage.
384
390
//
385
391
// 2) Type is not formally @_fixed_layout/@frozen and the module is not
386
- // resilient. Root initializers can be declared @inlinable. This is the
392
+ // resilient. Root initializers can be declared @inlinable. This is the
387
393
// annoying case. We give the initializer public linkage if the type is
388
394
// public.
389
395
//
390
396
// 3) Type is resilient. The property initializer is never public because
391
397
// root initializers cannot be @inlinable.
392
398
//
393
399
// FIXME: Get rid of case 2 somehow.
394
- if (isSerialized ())
395
- return maybeAddExternal (SILLinkage::PublicNonABI);
396
-
397
- d = cast<NominalTypeDecl>(d->getDeclContext ());
400
+ if (constant.isSerialized ())
401
+ return Limit::AlwaysEmitIntoClient;
398
402
399
403
// FIXME: This should always be true.
400
404
if (d->getModuleContext ()->isResilient ())
401
- limit = Limit::NeverPublic;
402
- }
405
+ return Limit::NeverPublic;
403
406
404
- // The global addressor is never public for resilient globals.
405
- if (kind == Kind::GlobalAccessor) {
406
- if (cast<VarDecl>(d)->isResilient ()) {
407
- limit = Limit::NeverPublic;
408
- }
407
+ break ;
409
408
}
410
-
411
- if (auto fn = dyn_cast<FuncDecl>(d)) {
412
- // Forced-static-dispatch functions are created on-demand and have
413
- // at best shared linkage.
414
- if (fn->hasForcedStaticDispatch ()) {
415
- limit = Limit::OnDemand;
416
- }
409
+ case Kind::IVarInitializer:
410
+ case Kind::IVarDestroyer:
411
+ // ivar initializers and destroyers are completely contained within the
412
+ // class from which they come, and never get seen externally.
413
+ return Limit::NeverPublic;
414
+
415
+ case Kind::EntryPoint:
416
+ case Kind::AsyncEntryPoint:
417
+ llvm_unreachable (" Already handled" );
417
418
}
419
+ return Limit::None;
420
+ }
418
421
419
- if (auto fn = dyn_cast<AbstractFunctionDecl>(d)) {
420
- // Native-to-foreign thunks for top-level decls are created on-demand,
421
- // unless they are marked @_cdecl, in which case they expose a dedicated
422
- // entry-point with the visibility of the function.
423
- //
424
- // Native-to-foreign thunks for methods are always just private, since
425
- // they're anchored by Objective-C metadata.
426
- if (isNativeToForeignThunk () && !fn->getAttrs ().hasAttribute <CDeclAttr>()) {
427
- if (fn->getDeclContext ()->isModuleScopeContext ())
428
- limit = Limit::OnDemand;
429
- else
430
- return SILLinkage::Private;
431
- }
432
- }
422
+ SILLinkage SILDeclRef::getDefinitionLinkage () const {
423
+ using Limit = LinkageLimit;
424
+
425
+ auto privateLinkage = [&]() {
426
+ // Private decls may still be serialized if they are e.g in an inlinable
427
+ // function. In such a case, they receive shared linkage.
428
+ return isSerialized () ? SILLinkage::Shared : SILLinkage::Private;
429
+ };
430
+
431
+ // Prespecializations are public.
432
+ if (getSpecializedSignature ())
433
+ return SILLinkage::Public;
434
+
435
+ // Closures can only be referenced from the same file.
436
+ if (getAbstractClosureExpr ())
437
+ return privateLinkage ();
438
+
439
+ // The main entry-point is public.
440
+ if (kind == Kind::EntryPoint)
441
+ return SILLinkage::Public;
442
+ if (kind == Kind::AsyncEntryPoint)
443
+ return SILLinkage::Hidden;
444
+
445
+ // Calling convention thunks have shared linkage.
446
+ if (isForeignToNativeThunk ())
447
+ return SILLinkage::Shared;
448
+
449
+ // Declarations imported from Clang modules have shared linkage.
450
+ if (isClangImported ())
451
+ return SILLinkage::Shared;
452
+
453
+ const auto limit = getLinkageLimit (*this );
454
+ if (limit == Limit::Private)
455
+ return privateLinkage ();
456
+
457
+ auto *decl = getDecl ();
458
+
459
+ if (isPropertyWrapperBackingInitializer ()) {
460
+ auto *dc = decl->getDeclContext ();
461
+
462
+ // Property wrapper generators of public functions have PublicNonABI
463
+ // linkage.
464
+ if (isa<ParamDecl>(decl) && isSerialized ())
465
+ return SILLinkage::PublicNonABI;
433
466
434
- if (isEnumElement ()) {
435
- limit = Limit::OnDemand;
467
+ // Property wrappers in types have linkage based on the access level of
468
+ // their nominal.
469
+ if (dc->isTypeContext ())
470
+ decl = cast<NominalTypeDecl>(dc);
436
471
}
437
472
438
- auto effectiveAccess = d->getEffectiveAccess ();
439
-
473
+ // Stored property initializers have linkage based on the access level of
474
+ // their nominal.
475
+ if (isStoredPropertyInitializer ())
476
+ decl = cast<NominalTypeDecl>(decl->getDeclContext ());
477
+
478
+ // Compute the effective access level, taking e.g testable into consideration.
479
+ auto effectiveAccess = decl->getEffectiveAccess ();
480
+
440
481
// Private setter implementations for an internal storage declaration should
441
482
// be at least internal as well, so that a dynamically-writable
442
483
// keypath can be formed from other files in the same module.
443
- if (auto accessor = dyn_cast<AccessorDecl>(d )) {
444
- if ( accessor->isSetter ()
445
- && accessor->getStorage ()-> getEffectiveAccess () >= AccessLevel::Internal)
484
+ if (auto * accessor = dyn_cast<AccessorDecl>(decl )) {
485
+ auto storageAccess = accessor->getStorage ()-> getEffectiveAccess ();
486
+ if ( accessor->isSetter () && storageAccess >= AccessLevel::Internal)
446
487
effectiveAccess = std::max (effectiveAccess, AccessLevel::Internal);
447
488
}
448
489
449
490
switch (effectiveAccess) {
450
491
case AccessLevel::Private:
451
492
case AccessLevel::FilePrivate:
452
- return SILLinkage::Private ;
493
+ return privateLinkage () ;
453
494
454
495
case AccessLevel::Internal:
496
+ assert (!isSerialized () &&
497
+ " Serialized decls should either be private (for decls in inlinable "
498
+ " code), or they should be public" );
455
499
if (limit == Limit::OnDemand)
456
500
return SILLinkage::Shared;
457
- return maybeAddExternal ( SILLinkage::Hidden) ;
501
+ return SILLinkage::Hidden;
458
502
459
503
case AccessLevel::Public:
460
504
case AccessLevel::Open:
461
- if (limit == Limit::OnDemand)
505
+ switch (limit) {
506
+ case Limit::None:
507
+ return SILLinkage::Public;
508
+ case Limit::AlwaysEmitIntoClient:
509
+ return SILLinkage::PublicNonABI;
510
+ case Limit::OnDemand:
462
511
return SILLinkage::Shared;
463
- if (limit == Limit::NeverPublic)
464
- return maybeAddExternal ( SILLinkage::Hidden) ;
465
- if (limit == Limit::AlwaysEmitIntoClient)
466
- return maybeAddExternal (SILLinkage::PublicNonABI );
467
- return maybeAddExternal (SILLinkage::Public);
512
+ case Limit::NeverPublic:
513
+ return SILLinkage::Hidden;
514
+ case Limit::Private:
515
+ llvm_unreachable ( " Already handled " );
516
+ }
468
517
}
469
518
llvm_unreachable (" unhandled access" );
470
519
}
471
520
521
+ SILLinkage SILDeclRef::getLinkage (ForDefinition_t forDefinition) const {
522
+ // Add external to the linkage of the definition
523
+ // (e.g. Public -> PublicExternal) if this is a declaration.
524
+ auto linkage = getDefinitionLinkage ();
525
+ return forDefinition ? linkage : addExternalToLinkage (linkage);
526
+ }
527
+
472
528
SILDeclRef SILDeclRef::getDefaultArgGenerator (Loc loc,
473
529
unsigned defaultArgIndex) {
474
530
SILDeclRef result;
0 commit comments