Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/swift/SIL/SILFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,10 @@ class SILFunction
/// function, such as swift_retain.
bool isSwiftRuntimeFunction() const;

/// Helper method that determines whether a function with the given name and
/// parent module is a Swift runtime function such as swift_retain.
static bool isSwiftRuntimeFunction(StringRef name, const ModuleDecl *module);

/// Helper method which returns true if the linkage of the SILFunction
/// indicates that the object's definition might be required outside the
/// current SILModule.
Expand Down
11 changes: 8 additions & 3 deletions lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2329,8 +2329,13 @@ getIRLinkage(StringRef name, const UniversalLinkageInfo &info,
case SILLinkage::Package: {
auto linkage = llvm::GlobalValue::ExternalLinkage;

if (hasNonUniqueDefinition)
linkage = llvm::GlobalValue::WeakODRLinkage;
if (hasNonUniqueDefinition) {
// Keep Swift runtime functions around so IRGen can reference them.
if (SILFunction::isSwiftRuntimeFunction(name, nullptr))
linkage = llvm::GlobalValue::WeakODRLinkage;
else
linkage = llvm::GlobalValue::LinkOnceODRLinkage;
}

return {linkage, PublicDefinitionVisibility,
info.Internalize ? llvm::GlobalValue::DefaultStorageClass
Expand All @@ -2348,7 +2353,7 @@ getIRLinkage(StringRef name, const UniversalLinkageInfo &info,

case SILLinkage::Hidden:
if (hasNonUniqueDefinition)
return RESULT(WeakODR, Hidden, Default);
return RESULT(LinkOnceODR, Hidden, Default);

return RESULT(External, Hidden, Default);

Expand Down
7 changes: 7 additions & 0 deletions lib/IRGen/Linking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1757,5 +1757,12 @@ bool LinkEntity::hasNonUniqueDefinition() const {
return true;
}

// Always treat witness tables as having non-unique definitions.
if (getKind() == Kind::ProtocolWitnessTable) {
if (auto context = getDeclContextForEmission())
if (context->getParentModule()->getASTContext().LangOpts.hasFeature(Feature::Embedded))
return true;
}

return false;
}
11 changes: 7 additions & 4 deletions lib/SIL/IR/SILFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1038,17 +1038,20 @@ bool SILFunction::hasValidLinkageForFragileRef(SerializedKind_t callerSerialized
return hasPublicOrPackageVisibility(getLinkage(), /*includePackage*/ true);
}

bool SILFunction::isSwiftRuntimeFunction() const {
if (!getName().starts_with("swift_") &&
!getName().starts_with("_swift_"))
bool SILFunction::isSwiftRuntimeFunction(
StringRef name, const ModuleDecl *module) {
if (!name.starts_with("swift_") && !name.starts_with("_swift_"))
return false;

auto module = getParentModule();
return !module ||
module->getName().str() == "Swift" ||
module->getName().str() == "_Concurrency";
}

bool SILFunction::isSwiftRuntimeFunction() const {
return isSwiftRuntimeFunction(getName(), getParentModule());
}

bool
SILFunction::isPossiblyUsedExternally() const {
auto linkage = getLinkage();
Expand Down
28 changes: 28 additions & 0 deletions test/embedded/linkage/diamond.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,25 @@ public func getPointOffsets() -> [Int] {
enumerateByteOffsets(Point.self)
}

public class PointClass {
public var x, y: Int

public init(x: Int, y: Int) {
self.x = x
self.y = y
}
}

public protocol Reflectable: AnyObject {
func reflect()
}

extension PointClass: Reflectable {
public func reflect() {
swap(&x, &y)
}
}

//--- ClientA.swift
import Root

Expand All @@ -99,6 +118,10 @@ public func getPointAndColorOffsets() -> [Int] {
getPointOffsets() + enumerateByteOffsets(Color.self)
}

public func getReflectableA() -> any AnyObject & Reflectable {
return PointClass(x: 5, y: 5)
}

//--- ClientB.swift
import Root

Expand All @@ -112,6 +135,10 @@ public func getExtraPoint3DOffsets() -> [Int] {
return Array(point3DOffsets[pointOffsets.count...])
}

public func getReflectableB() -> any AnyObject & Reflectable {
return PointClass(x: 5, y: 5)
}

//--- Application.swift
import ClientA
import ClientB
Expand All @@ -124,6 +151,7 @@ struct Main {
print(pointAndColorOffsets.count)
print(extraColor3DOffsets.count)

let reflected = [getReflectableA(), getReflectableB()]
// CHECK: DONE
print("DONE")
}
Expand Down
34 changes: 32 additions & 2 deletions test/embedded/linkage/leaf_application.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@

//--- Library.swift

// LIBRARY-IR: @"$e7Library10PointClassCN" = linkonce_odr {{.*}}global

// Never referenced.
// LIBRARY-IR-NOT: @"$es23_swiftEmptyArrayStorageSi_S3itvp" = weak_odr {{(protected |dllexport )?}}global
// LIBRARY-IR-NOT: @"$es23_swiftEmptyArrayStorageSi_S3itvp" = linkonce_odr {{(protected |dllexport )?}}global

// Note: referenced by swift_allocEmptyBox.
// LIBRARY-IR: @"$es16_emptyBoxStorageSi_Sitvp" = weak_odr {{(protected |dllexport )?}}global
// LIBRARY-IR: @"$es16_emptyBoxStorageSi_Sitvp" = linkonce_odr {{(protected |dllexport )?}}global

// LIBRARY-IR-NOT: define {{.*}}@"$e7Library5helloSaySiGyF"()
public func hello() -> [Int] {
Expand Down Expand Up @@ -54,6 +56,34 @@ public func unnecessary() -> Int64 { 5 }
@_neverEmitIntoClient
public func unusedYetThere() -> Int64 { 5 }

public class PointClass {
public var x, y: Int

public init(x: Int, y: Int) {
self.x = x
self.y = y
}
}

public protocol Reflectable: AnyObject {
func reflect()
}

// LIBRARY-IR: define linkonce_odr hidden swiftcc void @"$es4swapyyxz_xztlFSi_Tg5"
// LIBRARY-IR: define linkonce_odr hidden swiftcc void @"$e7Library10PointClassCAA11ReflectableA2aDP7reflectyyFTW"

extension PointClass: Reflectable {
public func reflect() {
swap(&x, &y)
}
}

// LIBRARY-IR: define {{.*}} @"$e7Library18createsExistentialAA11Reflectable_pyF"()
@_neverEmitIntoClient
public func createsExistential() -> any Reflectable {
return PointClass(x: 5, y: 5)
}

// LIBRARY-IR-NOT: define swiftcc
// LIBRARY-IR-NOT: define hidden swiftcc

Expand Down