[Embedded] Emit weak definitions for imported symbols

When Embedded Swift emits a symbol that was imported from another
module, ensure that the symbol is emitted as a weak definition. This
way, importing the same module (and using its symbol) into several
different modules doesn't cause duplicate-symbol errors at link time.
Rather, the linker will merge the different symbol definitions. This
makes Embedded Swift libraries work without resorting to
`-mergeable-symbols` or `-emit-empty-object-file`.
This commit is contained in:
Doug Gregor
2025-08-14 16:33:09 -07:00
parent c91a4822d3
commit 9a20ebac5b
18 changed files with 446 additions and 20 deletions

View File

@@ -1850,6 +1850,14 @@ public:
bool isTypeKind() const { return isTypeKind(getKind()); }
bool isAlwaysSharedLinkage() const;
/// Whether the link entity's definitions must be considered non-unique.
///
/// This applies only in the Embedded Swift linkage model, and is used for
/// any symbols that have not been explicitly requested to have unique
/// definitions (e.g., with @_used).
bool hasNonUniqueDefinition() const;
#undef LINKENTITY_GET_FIELD
#undef LINKENTITY_SET_FIELD

View File

@@ -399,6 +399,14 @@ struct SILDeclRef {
/// True if the function has the @backDeployed attribute.
bool isBackDeployed() const;
/// True if this entity should have a non-unique definition based on the
/// embedded linkage model.
bool hasNonUniqueDefinition() const;
/// True if the declaration should have a non-unique definition based on the
/// embedded linkage model.
static bool declHasNonUniqueDefinition(const ValueDecl *decl);
/// Return the expected linkage for a definition of this declaration.
SILLinkage getDefinitionLinkage() const;

View File

@@ -659,6 +659,10 @@ public:
bool isNoReturnFunction(TypeExpansionContext context) const;
/// True if this function should have a non-unique definition based on the
/// embedded linkage model.
bool hasNonUniqueDefinition() const;
/// Unsafely rewrite the lowered type of this function.
///
/// This routine does not touch the entry block arguments
@@ -916,6 +920,10 @@ public:
return swift::isAvailableExternally(getLinkage());
}
/// Helper method that determines whether this SILFunction is a Swift runtime
/// function, such as swift_retain.
bool isSwiftRuntimeFunction() const;
/// Helper method which returns true if the linkage of the SILFunction
/// indicates that the object's definition might be required outside the
/// current SILModule.

View File

@@ -151,6 +151,10 @@ public:
/// might be referenced from outside the current compilation unit.
bool isPossiblyUsedExternally() const;
/// True if this variable should have a non-unique definition based on the
/// embedded linkage model.
bool hasNonUniqueDefinition() const;
/// Returns true if this global variable should be preserved so it can
/// potentially be inspected by the debugger.
bool shouldBePreservedForDebugger() const;

View File

@@ -1156,9 +1156,17 @@ static bool isLazilyEmittedFunction(SILFunction &f, SILModule &m) {
f.getLoweredFunctionType()->getSubstGenericSignature()) {
return true;
}
if (f.isPossiblyUsedExternally())
if (f.isPossiblyUsedExternally()) {
// Under the embedded linkage model, if it has a non-unique definition,
// treat it lazily.
if (f.hasNonUniqueDefinition() && !f.isSwiftRuntimeFunction()
&& !f.markedAsUsed()) {
return true;
}
return false;
}
if (f.getDynamicallyReplacedFunction())
return false;
@@ -2244,7 +2252,8 @@ void IRGenerator::emitEntryPointInfo() {
static IRLinkage
getIRLinkage(StringRef name, const UniversalLinkageInfo &info,
SILLinkage linkage, ForDefinition_t isDefinition,
bool isWeakImported, bool isKnownLocal = false) {
bool isWeakImported, bool isKnownLocal,
bool hasNonUniqueDefinition) {
#define RESULT(LINKAGE, VISIBILITY, DLL_STORAGE) \
IRLinkage{llvm::GlobalValue::LINKAGE##Linkage, \
llvm::GlobalValue::VISIBILITY##Visibility, \
@@ -2275,7 +2284,9 @@ getIRLinkage(StringRef name, const UniversalLinkageInfo &info,
case SILLinkage::Package: {
auto linkage = llvm::GlobalValue::ExternalLinkage;
if (info.MergeableSymbols)
if (hasNonUniqueDefinition)
linkage = llvm::GlobalValue::WeakODRLinkage;
else if (info.MergeableSymbols)
linkage = llvm::GlobalValue::WeakODRLinkage;
return {linkage, PublicDefinitionVisibility,
@@ -2293,6 +2304,8 @@ getIRLinkage(StringRef name, const UniversalLinkageInfo &info,
: RESULT(External, Hidden, Default);
case SILLinkage::Hidden:
if (hasNonUniqueDefinition)
return RESULT(WeakODR, Hidden, Default);
if (info.MergeableSymbols)
return RESULT(WeakODR, Hidden, Default);
@@ -2301,7 +2314,7 @@ getIRLinkage(StringRef name, const UniversalLinkageInfo &info,
case SILLinkage::Private: {
if (info.forcePublicDecls() && !isDefinition)
return getIRLinkage(name, info, SILLinkage::PublicExternal, isDefinition,
isWeakImported, isKnownLocal);
isWeakImported, isKnownLocal, hasNonUniqueDefinition);
auto linkage = info.needLinkerToMergeDuplicateSymbols()
? llvm::GlobalValue::LinkOnceODRLinkage
@@ -2357,7 +2370,8 @@ void irgen::updateLinkageForDefinition(IRGenModule &IGM,
auto IRL =
getIRLinkage(global->hasName() ? global->getName() : StringRef(),
linkInfo, entity.getLinkage(ForDefinition), ForDefinition,
weakImported, isKnownLocal);
weakImported, isKnownLocal,
entity.hasNonUniqueDefinition());
ApplyIRLinkage(IRL).to(global);
LinkInfo link = LinkInfo::get(IGM, entity, ForDefinition);
@@ -2410,7 +2424,8 @@ LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo,
bool weakImported = entity.isWeakImported(swiftModule);
result.IRL = getIRLinkage(result.Name, linkInfo,
entity.getLinkage(isDefinition), isDefinition,
weakImported, isKnownLocal);
weakImported, isKnownLocal,
entity.hasNonUniqueDefinition());
result.ForDefinition = isDefinition;
return result;
}
@@ -2421,7 +2436,8 @@ LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo, StringRef name,
LinkInfo result;
result.Name += name;
result.IRL = getIRLinkage(name, linkInfo, linkage, isDefinition,
isWeakImported, linkInfo.Internalize);
isWeakImported, linkInfo.Internalize,
/*hasNonUniqueDefinition=*/false);
result.ForDefinition = isDefinition;
return result;
}

View File

@@ -1734,3 +1734,31 @@ bool LinkEntity::isAlwaysSharedLinkage() const {
return false;
}
}
bool LinkEntity::hasNonUniqueDefinition() const {
if (isDeclKind(getKind())) {
auto decl = getDecl();
return SILDeclRef::declHasNonUniqueDefinition(decl);
}
if (hasSILFunction()) {
return getSILFunction()->hasNonUniqueDefinition();
}
if (getKind() == Kind::SILGlobalVariable ||
getKind() == Kind::ReadOnlyGlobalObject)
return getSILGlobalVariable()->hasNonUniqueDefinition();
if (getKind() == Kind::TypeMetadata) {
// For a nominal type, check its declaration.
CanType type = getType();
if (auto nominal = type->getAnyNominal()) {
return SILDeclRef::declHasNonUniqueDefinition(nominal);
}
// All other type metadata is nonuniqued.
return true;
}
return false;
}

View File

@@ -571,6 +571,7 @@ static LinkageLimit getLinkageLimit(SILDeclRef constant) {
case Kind::AsyncEntryPoint:
llvm_unreachable("Already handled");
}
return Limit::None;
}
@@ -1089,6 +1090,25 @@ bool SILDeclRef::isBackDeployed() const {
return false;
}
bool SILDeclRef::hasNonUniqueDefinition() const {
if (auto decl = getDecl())
return declHasNonUniqueDefinition(decl);
return false;
}
bool SILDeclRef::declHasNonUniqueDefinition(const ValueDecl *decl) {
// This function only forces the issue in embedded.
if (!decl->getASTContext().LangOpts.hasFeature(Feature::Embedded))
return false;
// If the declaration is not from the main module, treat its definition as
// non-unique.
auto module = decl->getModuleContext();
auto &ctx = module->getASTContext();
return module != ctx.MainModule && ctx.MainModule;
}
bool SILDeclRef::isForeignToNativeThunk() const {
// If this isn't a native entry-point, it's not a foreign-to-native thunk.
if (isForeign)

View File

@@ -553,6 +553,24 @@ bool SILFunction::isNoReturnFunction(TypeExpansionContext context) const {
.isNoReturnFunction(getModule(), context);
}
bool SILFunction::hasNonUniqueDefinition() const {
// Non-uniqueness is a property of the Embedded linkage model.
if (!getASTContext().LangOpts.hasFeature(Feature::Embedded))
return false;
// If this is for a declaration, ask it.
if (auto declRef = getDeclRef()) {
return declRef.hasNonUniqueDefinition();
}
// If this function is from a different module than the one we are emitting
// code for, then it must have a non-unique definition.
if (getParentModule() != getModule().getSwiftModule())
return true;
return false;
}
ResilienceExpansion SILFunction::getResilienceExpansion() const {
// If a function definition is in another module, and
// it was serialized due to package serialization opt,
@@ -1016,6 +1034,17 @@ bool SILFunction::hasValidLinkageForFragileRef(SerializedKind_t callerSerialized
return hasPublicOrPackageVisibility(getLinkage(), /*includePackage*/ true);
}
bool SILFunction::isSwiftRuntimeFunction() const {
if (!getName().starts_with("swift_") &&
!getName().starts_with("_swift_"))
return false;
auto module = getParentModule();
return !module ||
module->getName().str() == "Swift" ||
module->getName().str() == "_Concurrency";
}
bool
SILFunction::isPossiblyUsedExternally() const {
auto linkage = getLinkage();
@@ -1046,6 +1075,11 @@ SILFunction::isPossiblyUsedExternally() const {
hasOpaqueResultTypeWithAvailabilityConditions())
return true;
// All Swift runtime functions can be used externally.
if (getASTContext().LangOpts.hasFeature(Feature::Embedded) &&
isSwiftRuntimeFunction())
return true;
return swift::isPossiblyUsedExternally(linkage, getModule().isWholeModule());
}

View File

@@ -88,6 +88,14 @@ bool SILGlobalVariable::isPossiblyUsedExternally() const {
return swift::isPossiblyUsedExternally(linkage, getModule().isWholeModule());
}
bool SILGlobalVariable::hasNonUniqueDefinition() const {
auto decl = getDecl();
if (!decl)
return false;
return SILDeclRef::declHasNonUniqueDefinition(decl);
}
bool SILGlobalVariable::shouldBePreservedForDebugger() const {
if (getModule().getOptions().OptMode != OptimizationMode::NoOptimization)
return false;

View File

@@ -950,7 +950,9 @@ void CrossModuleOptimization::serializeInstruction(SILInstruction *inst,
}
serializeFunction(callee, canSerializeFlags);
assert(isSerializedWithRightKind(M, callee) ||
isPackageOrPublic(callee->getLinkage()));
isPackageOrPublic(callee->getLinkage()) ||
M.getSwiftModule()->getASTContext().LangOpts.hasFeature(
Feature::Embedded));
return;
}
@@ -1005,7 +1007,10 @@ void CrossModuleOptimization::keepMethodAlive(SILDeclRef method) {
void CrossModuleOptimization::makeFunctionUsableFromInline(SILFunction *function) {
assert(canUseFromInline(function));
if (!isAvailableExternally(function->getLinkage()) &&
!isPackageOrPublic(function->getLinkage())) {
!isPackageOrPublic(function->getLinkage()) &&
!(function->getLinkage() == SILLinkage::Shared &&
M.getSwiftModule()->getASTContext().LangOpts.hasFeature(
Feature::Embedded))) {
function->setLinkage(SILLinkage::Public);
}
}

View File

@@ -124,11 +124,13 @@ class IRGenPrepare : public SILFunctionTransform {
SILFunction *F = getFunction();
if (getOptions().EmbeddedSwift) {
// In embedded swift all the code is generated in the top-level module.
// Even de-serialized functions must be code-gen'd.
// In Embedded Swift, code for a module can be generated into the clients
// that import that module (based on the de-serialized representation).
// When the model has a non-unique definition, use shared linkage for
// such definitions so they will be de-duplicated by the linker.
SILLinkage linkage = F->getLinkage();
if (isAvailableExternally(linkage)) {
F->setLinkage(SILLinkage::Hidden);
if (isAvailableExternally(linkage) && F->hasNonUniqueDefinition()) {
F->setLinkage(SILLinkage::Shared);
}
}

View File

@@ -20,9 +20,9 @@
// SIL: @_used @_hasStorage @_hasInitialValue var g2: Bool { get set }
// SIL: @_used func foo()
// SIL: sil_global hidden @$s4used2g0Sivp : $Int
// SIL: sil_global hidden @$s4used2g1Si_Sitvp : $(Int, Int)
// SIL: sil_global hidden @$s4used2g2Sbvp : $Bool
// SIL: sil_global hidden [used] @$s4used2g0Sivp : $Int
// SIL: sil_global hidden [used] @$s4used2g1Si_Sitvp : $(Int, Int)
// SIL: sil_global hidden [used] @$s4used2g2Sbvp : $Bool
// SIL: sil hidden [used] @$s4used3fooyyF : $@convention(thin)

View File

@@ -45,6 +45,6 @@ actor MyActor {
// CHECK-IR-NOT: $e4main7MyActorC12thisIsUnusedyyYaF
// CHECK-IR: define {{swifttailcc|swiftcc}} void @swift_deletedAsyncMethodError(ptr swiftasync %0)
// CHECK-IR: define weak_odr {{swifttailcc|swiftcc}} void @swift_deletedAsyncMethodError(ptr swiftasync %0)
// CHECK: value: 42

View File

@@ -0,0 +1,130 @@
// This test makes sure that we can build, link, and execute an Embedded Swift
// application that's composed of multiple libraries. It tests various
// combinations of "leaf" and "non-leaf" modules along the way to ensure that
// every combination produces a working binary that is free of either missing or
// (incorrectly) duplicated symbols. All of the modules implicitly depend on the
// Swift standard library.
//
// The overall shape of the module dependencies looks like this:
//
//
// Swift
// |
// |
// Root
// / \
// / \
// ClientA ClientB
// \ /
// \ /
// Application
//
// RUN: %empty-directory(%t)
// RUN: split-file %s %t
// Test #1: Defaults for everything
// RUN: %target-swift-frontend -c -emit-module -o %t/Root.o %t/Root.swift -enable-experimental-feature Embedded -parse-as-library
// RUN: %target-swift-frontend -c -I %t -emit-module -o %t/ClientA.o %t/ClientA.swift -enable-experimental-feature Embedded -parse-as-library
// RUN: %target-swift-frontend -c -I %t -emit-module -o %t/ClientB.o %t/ClientB.swift -enable-experimental-feature Embedded -parse-as-library
// RUN: %target-swift-frontend -c -I %t -emit-module -o %t/Application.o %t/Application.swift -enable-experimental-feature Embedded -parse-as-library
// RUN: %target-clang %target-clang-resource-dir-opt %t/Root.o %t/ClientA.o %t/ClientB.o %t/Application.o -o %t/Application
// RUN: %target-run %t/Application | %FileCheck %s
// Test #2: Root is an "intermediate" library for everything
// RUN: %target-swift-frontend -c -emit-module -o %t/Root.o %t/Root.swift -enable-experimental-feature Embedded -emit-empty-object-file -parse-as-library
// RUN: %target-swift-frontend -c -I %t -emit-module -o %t/ClientA.o %t/ClientA.swift -enable-experimental-feature Embedded -parse-as-library
// RUN: %target-swift-frontend -c -I %t -emit-module -o %t/ClientB.o %t/ClientB.swift -enable-experimental-feature Embedded -parse-as-library
// RUN: %target-swift-frontend -c -I %t -emit-module -o %t/Application.o %t/Application.swift -enable-experimental-feature Embedded -parse-as-library
// RUN: %target-clang %target-clang-resource-dir-opt %t/Root.o %t/ClientA.o %t/ClientB.o %t/Application.o -o %t/Application
// RUN: %target-run %t/Application | %FileCheck %s
// Test #3: ClientA as an "intermediate" library
// RUN: %target-swift-frontend -c -emit-module -o %t/Root.o %t/Root.swift -enable-experimental-feature Embedded -parse-as-library
// RUN: %target-swift-frontend -c -I %t -emit-module -o %t/ClientA.o %t/ClientA.swift -enable-experimental-feature Embedded -emit-empty-object-file -parse-as-library
// RUN: %target-swift-frontend -c -I %t -emit-module -o %t/ClientB.o %t/ClientB.swift -enable-experimental-feature Embedded -parse-as-library
// RUN: %target-swift-frontend -c -I %t -emit-module -o %t/Application.o %t/Application.swift -enable-experimental-feature Embedded -parse-as-library
// RUN: %target-clang %target-clang-resource-dir-opt %t/Root.o %t/ClientA.o %t/ClientB.o %t/Application.o -o %t/Application
// RUN: %target-run %t/Application | %FileCheck %s
// Test #4: Root and ClientA as "intermediate" libraries
// RUN: %target-swift-frontend -c -emit-module -o %t/Root.o %t/Root.swift -enable-experimental-feature Embedded -emit-empty-object-file -parse-as-library
// RUN: %target-swift-frontend -c -I %t -emit-module -o %t/ClientA.o %t/ClientA.swift -enable-experimental-feature Embedded -emit-empty-object-file -parse-as-library
// RUN: %target-swift-frontend -c -I %t -emit-module -o %t/ClientB.o %t/ClientB.swift -enable-experimental-feature Embedded -parse-as-library
// RUN: %target-swift-frontend -c -I %t -emit-module -o %t/Application.o %t/Application.swift -enable-experimental-feature Embedded -parse-as-library
// RUN: %target-clang %target-clang-resource-dir-opt %t/Root.o %t/ClientA.o %t/ClientB.o %t/Application.o -o %t/Application
// RUN: %target-run %t/Application | %FileCheck %s
// Test #%: All "intermediate", all the time. Main drives code generation
// TODO: This requires -emit-empty-object-file to still emit the main symbol.
// RUN: %target-swift-frontend -c -emit-module -o %t/Root.o %t/Root.swift -enable-experimental-feature Embedded -emit-empty-object-file -parse-as-library
// RUN: %target-swift-frontend -c -I %t -emit-module -o %t/ClientA.o %t/ClientA.swift -enable-experimental-feature Embedded -emit-empty-object-file -parse-as-library
// RUN: %target-swift-frontend -c -I %t -emit-module -o %t/ClientB.o %t/ClientB.swift -enable-experimental-feature Embedded -emit-empty-object-file -parse-as-library
// RUN: %target-swift-frontend -c -I %t -emit-module -o %t/Application.o %t/Application.swift -enable-experimental-feature Embedded -emit-empty-object-file -parse-as-library
// RUN-TODO: %target-clang %target-clang-resource-dir-opt %t/Root.o %t/ClientA.o %t/ClientB.o %t/Application.o -o %t/Application
// RUN-TODO: %target-run %t/Application | %FileCheck %s
// REQUIRES: swift_in_compiler
// REQUIRES: executable_test
// REQUIRES: swift_feature_Embedded
//--- Root.swift
struct Point {
var x, y: Int
}
public func enumerateByteOffsets<T>(_: T.Type) -> [Int] {
var array: [Int] = []
for i in 0..<MemoryLayout<T>.size {
array.append(i)
}
return array
}
public func getPointOffsets() -> [Int] {
enumerateByteOffsets(Point.self)
}
//--- ClientA.swift
import Root
public struct Color {
var red: UInt8
var green: UInt8
var blue: UInt8
}
public func getPointAndColorOffsets() -> [Int] {
getPointOffsets() + enumerateByteOffsets(Color.self)
}
//--- ClientB.swift
import Root
struct Point3D {
var x, y, z: Double
}
public func getExtraPoint3DOffsets() -> [Int] {
let pointOffsets = getPointOffsets()
let point3DOffsets = enumerateByteOffsets(Point3D.self)
return Array(point3DOffsets[pointOffsets.count...])
}
//--- Application.swift
import ClientA
import ClientB
@main
struct Main {
static func main() {
let pointAndColorOffsets = getPointAndColorOffsets()
let extraColor3DOffsets = getExtraPoint3DOffsets()
print(pointAndColorOffsets.count)
print(extraColor3DOffsets.count)
// CHECK: DONE
print("DONE")
}
}

View File

@@ -0,0 +1,82 @@
// RUN: %empty-directory(%t)
// RUN: split-file %s %t
// Library module
// SIL checking
// RUN: %target-swift-frontend %t/Library.swift -parse-as-library -entry-point-function-name Library_main -enable-experimental-feature Embedded -emit-empty-object-file -emit-sil -emit-module-path %t/Modules/Library.swiftmodule -o - | %FileCheck -check-prefix LIBRARY-SIL %s
// IR checking to ensure we get the right weak symbols.
// RUN: %target-swift-frontend %t/Library.swift -parse-as-library -entry-point-function-name Library_main -enable-experimental-feature Embedded -emit-empty-object-file -emit-ir -o - | %FileCheck -check-prefix LIBRARY-IR --dump-input-filter all %s
// Application module
// RUN: %target-swift-frontend %t/Application.swift -I %t/Modules -parse-as-library -entry-point-function-name Application_main -enable-experimental-feature Embedded -emit-sil -o - | %FileCheck -check-prefix APPLICATION-SIL %s
// RUN: %target-swift-frontend %t/Application.swift -I %t/Modules -parse-as-library -entry-point-function-name Application_main -enable-experimental-feature Embedded -emit-ir -o - | %FileCheck -check-prefix APPLICATION-IR --dump-input-filter all %s
// REQUIRES: swift_in_compiler
// REQUIRES: swift_feature_Embedded
//--- Library.swift
// TODO: These are expected once "emit empty object file" becomes "be lazy".
// LIBRARY-IR-NOT: @"$es23_swiftEmptyArrayStorageSi_S3itvp" = linkonce_odr {{(protected |dllexport )?}}global
// LIBRARY-IR-NOT: @"$es16_emptyBoxStorageSi_Sitvp" = linkonce_odr {{(protected |dllexport )?}}global
// LIBRARY-IR-NOT: define {{.*}}@"$e7Library5helloSaySiGyF"()
public func hello() -> [Int] {
getArray()
}
// LIBRARY-IR-NOT: define {{.*}} @"$e7Library8getArraySaySiGyF"()
public func getArray() -> [Int] {
throughInternal()
}
// LIBRARY-IR-NOT: define {{.*}} @"$e7Library15throughInternalSaySiGyF"()
func throughInternal() -> [Int] {
throughPrivate()
}
// LIBRARY-IR-NOT: define {{.*}} @"$e7Library14throughPrivate
private func throughPrivate() -> [Int] {
[5, 6, 7]
}
// LIBRARY-IR-NOT: unnecessary
public func unnecessary() -> Int64 { 5 }
// LIBRARY-IR-NOT: define swiftcc
// LIBRARY-IR-NOT: define hidden swiftcc
// LIBRARY-IR-NOT: define {{.*}} @"$es27_allocateUninitializedArrayySayxG_BptBwlFSi_Tg5"
// LIBRARY-SIL: sil [ossa] @$e7Library5helloSaySiGyF
// LIBRARY-SIL: sil [ossa] @$e7Library8getArraySaySiGyF : $@convention(thin) () -> @owned Array<Int> {
//--- Application.swift
import Library
public func testMe() {
_ = hello()
_ = getArray()
}
// APPLICATION-IR: define {{(protected |dllexport )?}}swiftcc void @"$e11Application6testMeyyF"()
// APPLICATION-SIL: sil public_external @$e7Library5helloSaySiGyF : $@convention(thin) () -> @owned Array<Int> {
// APPLICATION-IR: define linkonce_odr hidden swiftcc ptr @"$e7Library5helloSaySiGyF"()
// APPLICATION-SIL: sil public_external @$e7Library8getArraySaySiGyF : $@convention(thin) () -> @owned Array<Int> {
// APPLICATION-IR: define linkonce_odr hidden swiftcc ptr @"$e7Library8getArraySaySiGyF"()
// APPLICATION-IR: define {{(protected |dllexport )?}}i32 @Application_main
// APPLICATION-IR: define linkonce_odr hidden swiftcc { ptr, ptr } @"$es27_allocateUninitializedArrayySayxG_BptBwlFSi_Tg5"
@main
struct Main {
static func main() {
}
}

View File

@@ -0,0 +1,73 @@
// RUN: %empty-directory(%t)
// RUN: split-file %s %t
// Library module
// SIL checking
// RUN: %target-swift-frontend %t/Library.swift -parse-as-library -entry-point-function-name Library_main -enable-experimental-feature Embedded -emit-sil -emit-module-path %t/Modules/Library.swiftmodule -o - | %FileCheck -check-prefix LIBRARY-SIL %s
// IR checking to ensure we get the right weak symbols.
// RUN: %target-swift-frontend %t/Library.swift -parse-as-library -entry-point-function-name Library_main -enable-experimental-feature Embedded -emit-ir -o - | %FileCheck -check-prefix LIBRARY-IR --dump-input-filter all %s
// Application module
// RUN: %target-swift-frontend %t/Application.swift -I %t/Modules -parse-as-library -entry-point-function-name Application_main -enable-experimental-feature Embedded -emit-sil -o - | %FileCheck -check-prefix APPLICATION-SIL %s
// RUN: %target-swift-frontend %t/Application.swift -I %t/Modules -parse-as-library -entry-point-function-name Application_main -enable-experimental-feature Embedded -emit-ir -o - | %FileCheck -check-prefix APPLICATION-IR --dump-input-filter all %s
// REQUIRES: swift_in_compiler
// REQUIRES: swift_feature_Embedded
//--- Library.swift
// LIBRARY-IR: define {{(protected |dllexport )?}}swiftcc ptr @"$e7Library5helloSaySiGyF"()
public func hello() -> [Int] {
getArray()
}
// LIBRARY-IR: define {{(protected |dllexport )?}}swiftcc ptr @"$e7Library8getArraySaySiGyF"()
public func getArray() -> [Int] {
throughInternal()
}
// LIBRARY-IR: define {{(protected |dllexport )?}}swiftcc ptr @"$e7Library15throughInternalSaySiGyF"()
func throughInternal() -> [Int] {
throughPrivate()
}
// LIBRARY-IR: define {{(protected |dllexport )?}}swiftcc ptr @"$e7Library14throughPrivate33_
private func throughPrivate() -> [Int] {
[5, 6, 7]
}
// LIBRARY-IR: define linkonce_odr hidden swiftcc { ptr, ptr } @"$es27_allocateUninitializedArrayySayxG_BptBwlFSi_Tg5"
// LIBRARY-IR: define {{(protected |dllexport )?}}swiftcc i64 @"$e7Library11unnecessarys5Int64VyF"()
public func unnecessary() -> Int64 { 5 }
// LIBRARY-SIL: sil @$e7Library5helloSaySiGyF
// LIBRARY-SIL: sil @$e7Library8getArraySaySiGyF : $@convention(thin) () -> @owned Array<Int> {
//--- Application.swift
import Library
public func testMe() {
_ = hello()
_ = getArray()
}
// APPLICATION-IR: define {{(protected |dllexport )?}}swiftcc void @"$e11Application6testMeyyF"()
// APPLICATION-SIL: sil public_external @$e7Library5helloSaySiGyF : $@convention(thin) () -> @owned Array<Int> {
// APPLICATION-IR: define linkonce_odr hidden swiftcc ptr @"$e7Library5helloSaySiGyF"()
// APPLICATION-SIL: sil public_external @$e7Library8getArraySaySiGyF : $@convention(thin) () -> @owned Array<Int> {
// APPLICATION-IR: define linkonce_odr hidden swiftcc ptr @"$e7Library8getArraySaySiGyF"()
// APPLICATION-IR: define {{(protected |dllexport )?}}i32 @Application_main
@main
struct Main {
static func main() {
}
}

View File

@@ -19,4 +19,4 @@ public func test() {
// CHECK: sil hidden [Onone] @$s4main8MyStructV3fooyyF : $@convention(method) <T> (MyStruct<T>) -> () {
// EMBEDDED: // specialized MyStruct.foo()
// EMBEDDED: sil [Onone] @$e4main8MyStructV3fooyyFAA1XV_Tg5 : $@convention(method) (MyStruct<X>) -> () {
// EMBEDDED: sil shared [Onone] @$e4main8MyStructV3fooyyFAA1XV_Tg5 : $@convention(method) (MyStruct<X>) -> () {

View File

@@ -31,6 +31,6 @@ public func test() {
createFoo(x: 1)
}
// CHECK-LABEL: sil @$e8MyModule9createFoo1xyx_ts17FixedWidthIntegerRzlFSi_Ttg5 :
// CHECK-LABEL: sil shared @$e8MyModule9createFoo1xyx_ts17FixedWidthIntegerRzlFSi_Ttg5 :
// CHECK-NOT: release
// CHECK: } // end sil function '$e8MyModule9createFoo1xyx_ts17FixedWidthIntegerRzlFSi_Ttg5'