From 80855c872b860a3f05e208f6eac73fdc4a7ea6dd Mon Sep 17 00:00:00 2001 From: Ellie Shin Date: Thu, 16 May 2024 15:25:39 -0700 Subject: [PATCH 1/3] Fix global accessor and class linker errors. Add global accessors to symbol list if VarDecl is fragile, i.e. is non-resilient or its defining module allows non-resilient access. Don't set the class decl to hidden if it's in a package resilience domain; even though its defining module is built resilently, the class symbol should be visible across modules if they are in the same package with resilience-bypass optimization. In such case, treat its SubclassScope to Internal. Resolves rdar://127321129 --- include/swift/AST/Decl.h | 5 + lib/AST/Decl.cpp | 4 + lib/SIL/IR/SILDeclRef.cpp | 14 +- lib/SIL/IR/SILSymbolVisitor.cpp | 6 +- lib/Sema/TypeCheckStorage.cpp | 2 +- .../package_bypass_resilience_class.swift | 150 ++++++++++++++++++ ...ge_bypass_resilience_global_accessor.swift | 21 +++ 7 files changed, 188 insertions(+), 14 deletions(-) create mode 100644 test/IRGen/package_bypass_resilience_class.swift create mode 100644 test/IRGen/package_bypass_resilience_global_accessor.swift diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 6ba37871a4043..21698253ba0f3 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -6015,6 +6015,11 @@ class AbstractStorageDecl : public ValueDecl { /// property from the given module? bool isResilient(ModuleDecl *M, ResilienceExpansion expansion) const; + /// True if the decl is non-resilient, or its defining module allows + /// non-resilient access so its consuming modules within the same + /// package can have visibility into this decl. + bool isFragile() const; + /// True if the storage can be referenced by a keypath directly. /// Otherwise, its override must be referenced. bool isValidKeyPathComponent() const; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 7ef2008c0dec7..d5b5694af9a37 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -3032,6 +3032,10 @@ bool Decl::isOutermostPrivateOrFilePrivateScope() const { !isInPrivateOrLocalContext(this); } +bool AbstractStorageDecl::isFragile() const { + return !isResilient() || getModuleContext()->allowNonResilientAccess(); +} + bool AbstractStorageDecl::isResilient() const { // Check for an explicit @_fixed_layout attribute. if (getAttrs().hasAttribute()) diff --git a/lib/SIL/IR/SILDeclRef.cpp b/lib/SIL/IR/SILDeclRef.cpp index e2cc7b35bb4b2..3289913b69348 100644 --- a/lib/SIL/IR/SILDeclRef.cpp +++ b/lib/SIL/IR/SILDeclRef.cpp @@ -460,12 +460,8 @@ static LinkageLimit getLinkageLimit(SILDeclRef constant) { case Kind::EnumElement: return Limit::OnDemand; - case Kind::GlobalAccessor: { - auto varDecl = cast(d); - return varDecl->isResilient() && - !varDecl->getModuleContext()->allowNonResilientAccess() ? - Limit::NeverPublic : Limit::None; - } + case Kind::GlobalAccessor: + return !cast(d)->isFragile() ? Limit::NeverPublic : Limit::None; case Kind::DefaultArgGenerator: // If the default argument is to be serialized, only use non-ABI public @@ -511,7 +507,8 @@ static LinkageLimit getLinkageLimit(SILDeclRef constant) { return Limit::AlwaysEmitIntoClient; // FIXME: This should always be true. - if (d->getModuleContext()->isResilient()) + if (d->getModuleContext()->isResilient() && + !d->getModuleContext()->allowNonResilientAccess()) return Limit::NeverPublic; break; @@ -1532,7 +1529,8 @@ SubclassScope SILDeclRef::getSubclassScope() const { // FIXME: This is too narrow. Any class with resilient metadata should // probably have this, at least for method overrides that don't add new // vtable entries. - bool isResilientClass = classType->isResilient(); + bool isResilientClass = classType->isResilient() && + !classType->getModuleContext()->allowNonResilientAccess(); if (auto *CD = dyn_cast(decl)) { if (isResilientClass) diff --git a/lib/SIL/IR/SILSymbolVisitor.cpp b/lib/SIL/IR/SILSymbolVisitor.cpp index a9ed6503585cc..cf1d1e6c824d4 100644 --- a/lib/SIL/IR/SILSymbolVisitor.cpp +++ b/lib/SIL/IR/SILSymbolVisitor.cpp @@ -579,7 +579,7 @@ class SILSymbolVisitorImpl : public ASTVisitor { void visitVarDecl(VarDecl *VD) { // Variables inside non-resilient modules have some additional symbols. - if (!VD->isResilient()) { + if (VD->isFragile()) { // Non-global variables might have an explicit initializer symbol in // non-resilient modules. if (VD->getAttrs().hasAttribute() && @@ -589,17 +589,14 @@ class SILSymbolVisitorImpl : public ASTVisitor { // Stored property initializers for public properties are public. addFunction(declRef); } - // Statically/globally stored variables have some special handling. if (VD->hasStorage() && isGlobalOrStaticVar(VD)) { if (!shouldSkipVisit(getDeclLinkage(VD))) { Visitor.addGlobalVar(VD); } - if (VD->isLazilyInitializedGlobal()) addFunction(SILDeclRef(VD, SILDeclRef::Kind::GlobalAccessor)); } - // Wrapped non-static member properties may have a backing initializer. auto initInfo = VD->getPropertyWrapperInitializerInfo(); if (initInfo.hasInitFromWrappedValue() && !VD->isStatic()) { @@ -607,7 +604,6 @@ class SILSymbolVisitorImpl : public ASTVisitor { VD, SILDeclRef::Kind::PropertyWrapperBackingInitializer)); } } - visitAbstractStorageDecl(VD); } diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index a222632c54351..1f15755df2824 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -2537,7 +2537,7 @@ RequiresOpaqueAccessorsRequest::evaluate(Evaluator &evaluator, } else if (dc->isModuleScopeContext()) { // Fixed-layout global variables don't require opaque accessors. - if (!var->isResilient() && !var->shouldUseNativeDynamicDispatch()) + if (var->isFragile() && !var->shouldUseNativeDynamicDispatch()) return false; // Stored properties imported from Clang don't require opaque accessors. diff --git a/test/IRGen/package_bypass_resilience_class.swift b/test/IRGen/package_bypass_resilience_class.swift new file mode 100644 index 0000000000000..07aa8298f49e7 --- /dev/null +++ b/test/IRGen/package_bypass_resilience_class.swift @@ -0,0 +1,150 @@ +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +// RUN: %target-build-swift %t/Core.swift \ +// RUN: -module-name=Core -package-name Pkg \ +// RUN: -Xfrontend -experimental-allow-non-resilient-access \ +// RUN: -enable-library-evolution -O -wmo \ +// RUN: -emit-ir -o %t/Core.ir \ +// RUN: -emit-tbd -emit-tbd-path %t/libCore.tbd \ +// RUN: -Xfrontend -tbd-install_name=libCore.dylib -Xfrontend -validate-tbd-against-ir=all + +// RUN: %FileCheck %s --check-prefix=CHECK-IR < %t/Core.ir +// RUN: %FileCheck %s --check-prefix=CHECK-TBD < %t/libCore.tbd + +//--- Core.swift + +final public class Pub {} + +package class Foo { + package var myFoo: Pub? +} + +final package class Bar { + package var myBar: Pub? +} + +// key path getter for Core.Foo.myFoo +// CHECK-IR-DAG: define linkonce_odr hidden swiftcc void @"$s4Core3FooC02myB0AA3PubCSgvpACTK" + +// key path setter for Core.Foo.myFoo +// CHECK-IR-DAG: define linkonce_odr hidden swiftcc void @"$s4Core3FooC02myB0AA3PubCSgvpACTk" + +// variable initialization expression of Core.Foo.myFoo +// CHECK-IR-DAG: define swiftcc {{i32|i64}} @"$s4Core3FooC02myB0AA3PubCSgvpfi"() #0 { + +// Core.Foo.myFoo.getter +// CHECK-IR-DAG: define swiftcc {{i32|i64}} @"$s4Core3FooC02myB0AA3PubCSgvg"(ptr swiftself %0) + +// merged Core.Foo.myFoo.getter +// CHECK-IR-DAG: define internal swiftcc {{i32|i64}} @"$s4Core3FooC02myB0AA3PubCSgvgTm"(ptr swiftself %0) + +// Core.Foo.myFoo.setter +// CHECK-IR-DAG: define swiftcc void @"$s4Core3FooC02myB0AA3PubCSgvs"({{i32|i64}} %0, ptr swiftself %1) #1 { + +// merged Core.Foo.myFoo.setter +// CHECK-IR-DAG: define internal swiftcc void @"$s4Core3FooC02myB0AA3PubCSgvsTm"({{i32|i64}} %0, ptr swiftself %1) + +// Core.Foo.myFoo.modify +// CHECK-IR-DAG: define swiftcc { ptr, ptr } @"$s4Core3FooC02myB0AA3PubCSgvM" + +// Core.Foo.myFoo.modify +// CHECK-IR-DAG: define internal swiftcc void @"$s4Core3FooC02myB0AA3PubCSgvM.resume.0" + +// type metadata accessor for Core.Foo +// CHECK-IR-DAG: define swiftcc %swift.metadata_response @"$s4Core3FooCMa" + +// method lookup function for Core.Foo +// CHECK-IR-DAG: define swiftcc ptr @"$s4Core3FooCMu"(ptr %0, ptr %1) + +// dispatch thunk of Core.Foo.myFoo.getter +// CHECK-IR-DAG: define swiftcc {{i32|i64}} @"$s4Core3FooC02myB0AA3PubCSgvgTj"(ptr swiftself %0) + +// dispatch thunk of Core.Foo.myFoo.setter +// CHECK-IR-DAG: define swiftcc void @"$s4Core3FooC02myB0AA3PubCSgvsTj"({{i32|i64}} %0, ptr swiftself %1) + +// dispatch thunk of Core.Foo.myFoo.modify +// CHECK-IR-DAG: define swiftcc { ptr, ptr } @"$s4Core3FooC02myB0AA3PubCSgvMTj" + +// Core.Foo.deinit +// CHECK-IR-DAG: define swiftcc ptr @"$s4Core3FooCfd"(ptr readonly returned swiftself %0) + +// Core.Foo.__deallocating_deinit +// CHECK-IR-DAG: define swiftcc void @"$s4Core3FooCfD"(ptr swiftself %0) + + +// Core.Bar.myBar +// CHECK-IR-DAG: define swiftcc {{i32|i64}} @"$s4Core3BarC02myB0AA3PubCSgvpfi"() +// CHECK-IR-DAG: define swiftcc {{i32|i64}} @"$s4Core3BarC02myB0AA3PubCSgvg"(ptr swiftself %0) +// CHECK-IR-DAG: define swiftcc void @"$s4Core3BarC02myB0AA3PubCSgvs"({{i32|i64}} %0, ptr swiftself %1) +// CHECK-IR-DAG: define swiftcc { ptr, ptr } @"$s4Core3BarC02myB0AA3PubCSgvM" +// CHECK-IR-DAG: define internal swiftcc void @"$s4Core3BarC02myB0AA3PubCSgvM.resume.0" + +// Core.Bar +// type metadata accessor for Core.Bar +// CHECK-IR-DAG: define swiftcc %swift.metadata_response @"$s4Core3BarCMa"({{i32|i64}} %0) + +// method lookup function for Core.Bar +// CHECK-IR-DAG: define swiftcc ptr @"$s4Core3BarCMu"(ptr %0, ptr %1) + +// CHECK-IR-DAG: define swiftcc ptr @"$s4Core3BarCfd"(ptr readonly returned swiftself %0) +// CHECK-IR-DAG: define swiftcc void @"$s4Core3BarCfD"(ptr swiftself %0) + +// Core.Pub +// type metadata accessor for Core.Pub +// CHECK-IR-DAG: define swiftcc %swift.metadata_response @"$s4Core3PubCMa"({{i32|i64}} %0) + +// method lookup function for Core.Pub +// CHECK-IR-DAG: define swiftcc ptr @"$s4Core3PubCMu"(ptr %0, ptr %1) + +// CHECK-IR-DAG: define swiftcc ptr @"$s4Core3PubCfd"(ptr readnone returned swiftself %0) +// CHECK-IR-DAG: define swiftcc void @"$s4Core3PubCfD"(ptr swiftself %0) + + +// property descriptor for Core.Foo.myFoo +// CHECK-TBD-DAG: s4Core3FooC02myB0AA3PubCSgvpMV +// method descriptor for Core.Foo.myFoo.getter +// CHECK-TBD-DAG: s4Core3FooC02myB0AA3PubCSgvgTq +// method descriptor for Core.Foo.myFoo.setter +// CHECK-TBD-DAG: s4Core3FooC02myB0AA3PubCSgvsTq +// method descriptor for Core.Foo.myFoo.modify +// CHECK-TBD-DAG: s4Core3FooC02myB0AA3PubCSgvMTq +// dispatch thunk of Core.Foo.myFoo.getter +// CHECK-TBD-DAG: s4Core3FooC02myB0AA3PubCSgvgTj +// dispatch thunk of Core.Foo.myFoo.setter +// CHECK-TBD-DAG: s4Core3FooC02myB0AA3PubCSgvsTj +// dispatch thunk of Core.Foo.myFoo.modify +// CHECK-TBD-DAG: s4Core3FooC02myB0AA3PubCSgvMTj +// type metadata accessor for Core.Foo +// CHECK-TBD-DAG: s4Core3FooCMa +// method lookup function for Core.Foo +// CHECK-TBD-DAG: s4Core3FooCMu +// nominal type descriptor for Core.Foo +// CHECK-TBD-DAG: s4Core3FooCMn +// class metadata base offset for Core.Foo +// CHECK-TBD-DAG: s4Core3FooCMo + +// CHECK-TBD-DAG: s4Core3FooC02myB0AA3PubCSgvpfi +// CHECK-TBD-DAG: s4Core3FooC02myB0AA3PubCSgvg +// CHECK-TBD-DAG: s4Core3FooC02myB0AA3PubCSgvs +// CHECK-TBD-DAG: s4Core3FooCfd +// CHECK-TBD-DAG: s4Core3FooCfD + +// CHECK-TBD-DAG: s4Core3BarC02myB0AA3PubCSgvpMV +// CHECK-TBD-DAG: s4Core3BarC02myB0AA3PubCSgvpfi +// CHECK-TBD-DAG: s4Core3BarC02myB0AA3PubCSgvg +// CHECK-TBD-DAG: s4Core3BarC02myB0AA3PubCSgvs +// CHECK-TBD-DAG: s4Core3BarC02myB0AA3PubCSgvM +// CHECK-TBD-DAG: s4Core3BarCMa +// CHECK-TBD-DAG: s4Core3BarCMu +// CHECK-TBD-DAG: s4Core3BarCMn +// CHECK-TBD-DAG: s4Core3BarCMo +// CHECK-TBD-DAG: s4Core3BarCfd +// CHECK-TBD-DAG: s4Core3BarCfD + +// CHECK-TBD-DAG: s4Core3PubCMa +// CHECK-TBD-DAG: s4Core3PubCMu +// CHECK-TBD-DAG: s4Core3PubCMn +// CHECK-TBD-DAG: s4Core3PubCMo +// CHECK-TBD-DAG: s4Core3PubCfd +// CHECK-TBD-DAG: s4Core3PubCfD diff --git a/test/IRGen/package_bypass_resilience_global_accessor.swift b/test/IRGen/package_bypass_resilience_global_accessor.swift new file mode 100644 index 0000000000000..788663c20e167 --- /dev/null +++ b/test/IRGen/package_bypass_resilience_global_accessor.swift @@ -0,0 +1,21 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-sil %s | %FileCheck %s --check-prefix=CHECK-SIL +// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-sil %s -enable-library-evolution | %FileCheck %s --check-prefix=CHECK-SIL-HID +// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-sil %s -enable-library-evolution -Xfrontend -experimental-allow-non-resilient-access | %FileCheck %s --check-prefix=CHECK-SIL +// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-ir %s | %FileCheck %s --check-prefix=CHECK-IR +// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-ir %s -enable-library-evolution | %FileCheck %s --check-prefix=CHECK-IR-HID +// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-ir %s -enable-library-evolution -Xfrontend -experimental-allow-non-resilient-access | %FileCheck %s --check-prefix=CHECK-IR + +public struct S { + public static var x = "hello world" +} + +// S.x.unsafeMutableAddressor +// CHECK-SIL: sil [global_init] @$s4File1SV1xSSvau : $@convention(thin) () -> Builtin.RawPointer { +// S.x.unsafeMutableAddressor +// CHECK-SIL-HID: sil hidden [global_init] @$s4File1SV1xSSvau : $@convention(thin) () -> Builtin.RawPointer { + +// CHECK-IR: define swiftcc ptr @"$s4File1SV1xSSvau"() +// CHECK-IR-HID: define hidden swiftcc ptr @"$s4File1SV1xSSvau"() + From 36b4d2d3147a0cc2732631866c353a234d5c2513 Mon Sep 17 00:00:00 2001 From: Ellie Shin Date: Mon, 20 May 2024 17:33:24 -0700 Subject: [PATCH 2/3] Update test for windows --- .../package_bypass_resilience_class.swift | 46 +++++++++---------- ...ge_bypass_resilience_global_accessor.swift | 2 +- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/test/IRGen/package_bypass_resilience_class.swift b/test/IRGen/package_bypass_resilience_class.swift index 07aa8298f49e7..3319148afd666 100644 --- a/test/IRGen/package_bypass_resilience_class.swift +++ b/test/IRGen/package_bypass_resilience_class.swift @@ -31,74 +31,74 @@ final package class Bar { // CHECK-IR-DAG: define linkonce_odr hidden swiftcc void @"$s4Core3FooC02myB0AA3PubCSgvpACTk" // variable initialization expression of Core.Foo.myFoo -// CHECK-IR-DAG: define swiftcc {{i32|i64}} @"$s4Core3FooC02myB0AA3PubCSgvpfi"() #0 { +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc {{i32|i64}} @"$s4Core3FooC02myB0AA3PubCSgvpfi"() #0 { // Core.Foo.myFoo.getter -// CHECK-IR-DAG: define swiftcc {{i32|i64}} @"$s4Core3FooC02myB0AA3PubCSgvg"(ptr swiftself %0) +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc {{i32|i64}} @"$s4Core3FooC02myB0AA3PubCSgvg"(ptr swiftself %0) // merged Core.Foo.myFoo.getter // CHECK-IR-DAG: define internal swiftcc {{i32|i64}} @"$s4Core3FooC02myB0AA3PubCSgvgTm"(ptr swiftself %0) // Core.Foo.myFoo.setter -// CHECK-IR-DAG: define swiftcc void @"$s4Core3FooC02myB0AA3PubCSgvs"({{i32|i64}} %0, ptr swiftself %1) #1 { +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc void @"$s4Core3FooC02myB0AA3PubCSgvs"({{i32|i64}} %0, ptr swiftself %1) #1 { // merged Core.Foo.myFoo.setter // CHECK-IR-DAG: define internal swiftcc void @"$s4Core3FooC02myB0AA3PubCSgvsTm"({{i32|i64}} %0, ptr swiftself %1) // Core.Foo.myFoo.modify -// CHECK-IR-DAG: define swiftcc { ptr, ptr } @"$s4Core3FooC02myB0AA3PubCSgvM" +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc { ptr, ptr } @"$s4Core3FooC02myB0AA3PubCSgvM" // Core.Foo.myFoo.modify // CHECK-IR-DAG: define internal swiftcc void @"$s4Core3FooC02myB0AA3PubCSgvM.resume.0" // type metadata accessor for Core.Foo -// CHECK-IR-DAG: define swiftcc %swift.metadata_response @"$s4Core3FooCMa" +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc %swift.metadata_response @"$s4Core3FooCMa" // method lookup function for Core.Foo -// CHECK-IR-DAG: define swiftcc ptr @"$s4Core3FooCMu"(ptr %0, ptr %1) +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc ptr @"$s4Core3FooCMu"(ptr %0, ptr %1) // dispatch thunk of Core.Foo.myFoo.getter -// CHECK-IR-DAG: define swiftcc {{i32|i64}} @"$s4Core3FooC02myB0AA3PubCSgvgTj"(ptr swiftself %0) +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc {{i32|i64}} @"$s4Core3FooC02myB0AA3PubCSgvgTj"(ptr swiftself %0) // dispatch thunk of Core.Foo.myFoo.setter -// CHECK-IR-DAG: define swiftcc void @"$s4Core3FooC02myB0AA3PubCSgvsTj"({{i32|i64}} %0, ptr swiftself %1) +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc void @"$s4Core3FooC02myB0AA3PubCSgvsTj"({{i32|i64}} %0, ptr swiftself %1) // dispatch thunk of Core.Foo.myFoo.modify -// CHECK-IR-DAG: define swiftcc { ptr, ptr } @"$s4Core3FooC02myB0AA3PubCSgvMTj" +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc { ptr, ptr } @"$s4Core3FooC02myB0AA3PubCSgvMTj" // Core.Foo.deinit -// CHECK-IR-DAG: define swiftcc ptr @"$s4Core3FooCfd"(ptr readonly returned swiftself %0) +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc ptr @"$s4Core3FooCfd"(ptr readonly returned swiftself %0) // Core.Foo.__deallocating_deinit -// CHECK-IR-DAG: define swiftcc void @"$s4Core3FooCfD"(ptr swiftself %0) +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc void @"$s4Core3FooCfD"(ptr swiftself %0) // Core.Bar.myBar -// CHECK-IR-DAG: define swiftcc {{i32|i64}} @"$s4Core3BarC02myB0AA3PubCSgvpfi"() -// CHECK-IR-DAG: define swiftcc {{i32|i64}} @"$s4Core3BarC02myB0AA3PubCSgvg"(ptr swiftself %0) -// CHECK-IR-DAG: define swiftcc void @"$s4Core3BarC02myB0AA3PubCSgvs"({{i32|i64}} %0, ptr swiftself %1) -// CHECK-IR-DAG: define swiftcc { ptr, ptr } @"$s4Core3BarC02myB0AA3PubCSgvM" +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc {{i32|i64}} @"$s4Core3BarC02myB0AA3PubCSgvpfi"() +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc {{i32|i64}} @"$s4Core3BarC02myB0AA3PubCSgvg"(ptr swiftself %0) +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc void @"$s4Core3BarC02myB0AA3PubCSgvs"({{i32|i64}} %0, ptr swiftself %1) +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc { ptr, ptr } @"$s4Core3BarC02myB0AA3PubCSgvM" // CHECK-IR-DAG: define internal swiftcc void @"$s4Core3BarC02myB0AA3PubCSgvM.resume.0" // Core.Bar // type metadata accessor for Core.Bar -// CHECK-IR-DAG: define swiftcc %swift.metadata_response @"$s4Core3BarCMa"({{i32|i64}} %0) +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc %swift.metadata_response @"$s4Core3BarCMa"({{i32|i64}} %0) // method lookup function for Core.Bar -// CHECK-IR-DAG: define swiftcc ptr @"$s4Core3BarCMu"(ptr %0, ptr %1) +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc ptr @"$s4Core3BarCMu"(ptr %0, ptr %1) -// CHECK-IR-DAG: define swiftcc ptr @"$s4Core3BarCfd"(ptr readonly returned swiftself %0) -// CHECK-IR-DAG: define swiftcc void @"$s4Core3BarCfD"(ptr swiftself %0) +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc ptr @"$s4Core3BarCfd"(ptr readonly returned swiftself %0) +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc void @"$s4Core3BarCfD"(ptr swiftself %0) // Core.Pub // type metadata accessor for Core.Pub -// CHECK-IR-DAG: define swiftcc %swift.metadata_response @"$s4Core3PubCMa"({{i32|i64}} %0) +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc %swift.metadata_response @"$s4Core3PubCMa"({{i32|i64}} %0) // method lookup function for Core.Pub -// CHECK-IR-DAG: define swiftcc ptr @"$s4Core3PubCMu"(ptr %0, ptr %1) +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc ptr @"$s4Core3PubCMu"(ptr %0, ptr %1) -// CHECK-IR-DAG: define swiftcc ptr @"$s4Core3PubCfd"(ptr readnone returned swiftself %0) -// CHECK-IR-DAG: define swiftcc void @"$s4Core3PubCfD"(ptr swiftself %0) +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc ptr @"$s4Core3PubCfd"(ptr readnone returned swiftself %0) +// CHECK-IR-DAG: define {{(dllexport |protected )?}}swiftcc void @"$s4Core3PubCfD"(ptr swiftself %0) // property descriptor for Core.Foo.myFoo diff --git a/test/IRGen/package_bypass_resilience_global_accessor.swift b/test/IRGen/package_bypass_resilience_global_accessor.swift index 788663c20e167..d95491c51edcc 100644 --- a/test/IRGen/package_bypass_resilience_global_accessor.swift +++ b/test/IRGen/package_bypass_resilience_global_accessor.swift @@ -16,6 +16,6 @@ public struct S { // S.x.unsafeMutableAddressor // CHECK-SIL-HID: sil hidden [global_init] @$s4File1SV1xSSvau : $@convention(thin) () -> Builtin.RawPointer { -// CHECK-IR: define swiftcc ptr @"$s4File1SV1xSSvau"() +// CHECK-IR: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @"$s4File1SV1xSSvau"() // CHECK-IR-HID: define hidden swiftcc ptr @"$s4File1SV1xSSvau"() From 063d159d1bdc2a857cd748354fd911ef977b1649 Mon Sep 17 00:00:00 2001 From: Ellie Shin Date: Tue, 21 May 2024 17:45:34 -0700 Subject: [PATCH 3/3] Rename isFragile() as isStrictlyResilient() in var decl. Add isStrictlyResilient() to nominal type and module decl. --- include/swift/AST/Decl.h | 17 +++++++++++++---- include/swift/AST/Module.h | 9 +++++++++ lib/AST/Decl.cpp | 8 ++++++-- lib/SIL/IR/SILDeclRef.cpp | 14 ++++++-------- lib/SIL/IR/SILSymbolVisitor.cpp | 2 +- lib/Sema/TypeCheckStorage.cpp | 2 +- 6 files changed, 36 insertions(+), 16 deletions(-) diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 21698253ba0f3..a01bda5001fbb 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -4151,6 +4151,13 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext { /// is built resiliently. bool isResilient() const; + /// True if the decl is resilient AND also its defining module does + /// _not_ allow non-resilient access; the module can allow such access + /// if package optimization is enabled so its client modules within the + /// same package can have a direct access to this decl even if it's + /// resilient. + bool isStrictlyResilient() const; + /// Returns whether this decl is accessed non/resiliently at the _use_ site /// in \p accessingModule, depending on \p expansion. /// @@ -6015,10 +6022,12 @@ class AbstractStorageDecl : public ValueDecl { /// property from the given module? bool isResilient(ModuleDecl *M, ResilienceExpansion expansion) const; - /// True if the decl is non-resilient, or its defining module allows - /// non-resilient access so its consuming modules within the same - /// package can have visibility into this decl. - bool isFragile() const; + /// True if the decl is resilient AND also its defining module does + /// _not_ allow non-resilient access; the module can allow such access + /// if package optimization is enabled so its client modules within the + /// same package can have a direct access to this decl even if it's + /// resilient. + bool isStrictlyResilient() const; /// True if the storage can be referenced by a keypath directly. /// Otherwise, its override must be referenced. diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index 80f1e7da5cffb..de5819d870918 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -779,6 +779,15 @@ class ModuleDecl return getResilienceStrategy() != ResilienceStrategy::Default; } + /// True if this module is resilient AND also does _not_ allow + /// non-resilient access; the module can allow such access if + /// package optimization is enabled so its client modules within + /// the same package can have a direct access to decls in this + /// module even if it's built resiliently. + bool isStrictlyResilient() const { + return isResilient() && !allowNonResilientAccess(); + } + /// Look up a (possibly overloaded) value set at top-level scope /// (but with the specified access path, which may come from an import decl) /// within the current module. diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index d5b5694af9a37..2c099eab0e0ac 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -3032,8 +3032,8 @@ bool Decl::isOutermostPrivateOrFilePrivateScope() const { !isInPrivateOrLocalContext(this); } -bool AbstractStorageDecl::isFragile() const { - return !isResilient() || getModuleContext()->allowNonResilientAccess(); +bool AbstractStorageDecl::isStrictlyResilient() const { + return isResilient() && !getModuleContext()->allowNonResilientAccess(); } bool AbstractStorageDecl::isResilient() const { @@ -5146,6 +5146,10 @@ bool NominalTypeDecl::isResilient() const { return getModuleContext()->isResilient(); } +bool NominalTypeDecl::isStrictlyResilient() const { + return isResilient() && !getModuleContext()->allowNonResilientAccess(); +} + DestructorDecl *NominalTypeDecl::getValueTypeDestructor() { if (!isa(this) && !isa(this)) { return nullptr; diff --git a/lib/SIL/IR/SILDeclRef.cpp b/lib/SIL/IR/SILDeclRef.cpp index 3289913b69348..93b4d9e0784d4 100644 --- a/lib/SIL/IR/SILDeclRef.cpp +++ b/lib/SIL/IR/SILDeclRef.cpp @@ -461,7 +461,7 @@ static LinkageLimit getLinkageLimit(SILDeclRef constant) { return Limit::OnDemand; case Kind::GlobalAccessor: - return !cast(d)->isFragile() ? Limit::NeverPublic : Limit::None; + return cast(d)->isStrictlyResilient() ? Limit::NeverPublic : Limit::None; case Kind::DefaultArgGenerator: // If the default argument is to be serialized, only use non-ABI public @@ -507,8 +507,7 @@ static LinkageLimit getLinkageLimit(SILDeclRef constant) { return Limit::AlwaysEmitIntoClient; // FIXME: This should always be true. - if (d->getModuleContext()->isResilient() && - !d->getModuleContext()->allowNonResilientAccess()) + if (d->getModuleContext()->isStrictlyResilient()) return Limit::NeverPublic; break; @@ -1529,11 +1528,10 @@ SubclassScope SILDeclRef::getSubclassScope() const { // FIXME: This is too narrow. Any class with resilient metadata should // probably have this, at least for method overrides that don't add new // vtable entries. - bool isResilientClass = classType->isResilient() && - !classType->getModuleContext()->allowNonResilientAccess(); + bool isStrictResilientClass = classType->isStrictlyResilient(); if (auto *CD = dyn_cast(decl)) { - if (isResilientClass) + if (isStrictResilientClass) return SubclassScope::NotApplicable; // Initializing entry points do not appear in the vtable. if (kind == SILDeclRef::Kind::Initializer) @@ -1564,14 +1562,14 @@ SubclassScope SILDeclRef::getSubclassScope() const { // In the resilient case, we're going to be making symbols _less_ // visible, so make sure we stop now; final methods can always be // called directly. - if (isResilientClass) + if (isStrictResilientClass) return SubclassScope::Internal; } assert(decl->getEffectiveAccess() <= classType->getEffectiveAccess() && "class must be as visible as its members"); - if (isResilientClass) { + if (isStrictResilientClass) { // The symbol should _only_ be reached via the vtable, so we're // going to make it hidden. return SubclassScope::Resilient; diff --git a/lib/SIL/IR/SILSymbolVisitor.cpp b/lib/SIL/IR/SILSymbolVisitor.cpp index cf1d1e6c824d4..25ec721cf36f4 100644 --- a/lib/SIL/IR/SILSymbolVisitor.cpp +++ b/lib/SIL/IR/SILSymbolVisitor.cpp @@ -579,7 +579,7 @@ class SILSymbolVisitorImpl : public ASTVisitor { void visitVarDecl(VarDecl *VD) { // Variables inside non-resilient modules have some additional symbols. - if (VD->isFragile()) { + if (!VD->isStrictlyResilient()) { // Non-global variables might have an explicit initializer symbol in // non-resilient modules. if (VD->getAttrs().hasAttribute() && diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index 1f15755df2824..a222632c54351 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -2537,7 +2537,7 @@ RequiresOpaqueAccessorsRequest::evaluate(Evaluator &evaluator, } else if (dc->isModuleScopeContext()) { // Fixed-layout global variables don't require opaque accessors. - if (var->isFragile() && !var->shouldUseNativeDynamicDispatch()) + if (!var->isResilient() && !var->shouldUseNativeDynamicDispatch()) return false; // Stored properties imported from Clang don't require opaque accessors.