Skip to content

Commit 63b2f58

Browse files
authored
Merge pull request swiftlang#79242 from kubamracek/embedded-mergeable-symbols
[embedded] Add an experimental -Xfrontend -mergeable-symbols to allow linking multiple .o modules in Embedded Swift
2 parents 81b7b44 + b2f87e7 commit 63b2f58

File tree

8 files changed

+71
-7
lines changed

8 files changed

+71
-7
lines changed

include/swift/AST/IRGenOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,8 @@ class IRGenOptions {
461461
/// Internalize symbols (static library) - do not export any public symbols.
462462
unsigned InternalizeSymbols : 1;
463463

464+
unsigned MergeableSymbols : 1;
465+
464466
/// Emit a section with references to class_ro_t* in generic class patterns.
465467
unsigned EmitGenericRODatas : 1;
466468

@@ -590,6 +592,7 @@ class IRGenOptions {
590592
EnableGlobalISel(false), VirtualFunctionElimination(false),
591593
WitnessMethodElimination(false), ConditionalRuntimeRecords(false),
592594
InternalizeAtLink(false), InternalizeSymbols(false),
595+
MergeableSymbols(false),
593596
EmitGenericRODatas(true), NoPreallocatedInstantiationCaches(false),
594597
DisableReadonlyStaticObjects(false), CollocatedMetadataFunctions(false),
595598
ColocateTypeDescriptors(true), UseRelativeProtocolWitnessTables(false),

include/swift/IRGen/Linking.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,15 @@ class UniversalLinkageInfo {
5656
/// be promoted to public external. Used by the LLDB expression evaluator.
5757
bool ForcePublicDecls;
5858

59+
/// When true, allows duplicate external and hidden declarations by marking
60+
/// them as linkonce / weak.
61+
bool MergeableSymbols;
62+
5963
explicit UniversalLinkageInfo(IRGenModule &IGM);
6064

6165
UniversalLinkageInfo(const llvm::Triple &triple, bool hasMultipleIGMs,
62-
bool forcePublicDecls, bool isStaticLibrary);
66+
bool forcePublicDecls, bool isStaticLibrary,
67+
bool mergeableSymbols);
6368

6469
/// In case of multiple llvm modules (in multi-threaded compilation) all
6570
/// private decls must be visible from other files.

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,10 @@ def conditional_runtime_records : Flag<["-"], "conditional-runtime-records">,
766766
Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>,
767767
HelpText<"Allow removal of runtime metadata records (public types, protocol conformances) based on whether they're used or unused">;
768768

769+
def mergeable_symbols : Flag<["-"], "mergeable-symbols">,
770+
Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>,
771+
HelpText<"Emit symbol definitions as mergeable (linkonce_odr)">;
772+
769773
def disable_preallocated_instantiation_caches : Flag<["-"], "disable-preallocated-instantiation-caches">,
770774
Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>,
771775
HelpText<"Avoid preallocating metadata instantiation caches in globals">;

lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3553,6 +3553,10 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
35533553

35543554
Opts.InternalizeSymbols = FrontendOpts.Static;
35553555

3556+
if (Args.hasArg(OPT_mergeable_symbols)) {
3557+
Opts.MergeableSymbols = true;
3558+
}
3559+
35563560
if (Args.hasArg(OPT_disable_preallocated_instantiation_caches)) {
35573561
Opts.NoPreallocatedInstantiationCaches = true;
35583562
}

lib/IRGen/GenDecl.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2249,10 +2249,16 @@ getIRLinkage(StringRef name, const UniversalLinkageInfo &info,
22492249

22502250
switch (linkage) {
22512251
case SILLinkage::Public:
2252-
case SILLinkage::Package:
2253-
return {llvm::GlobalValue::ExternalLinkage, PublicDefinitionVisibility,
2252+
case SILLinkage::Package: {
2253+
auto linkage = llvm::GlobalValue::ExternalLinkage;
2254+
2255+
if (info.MergeableSymbols)
2256+
linkage = llvm::GlobalValue::LinkOnceODRLinkage;
2257+
2258+
return {linkage, PublicDefinitionVisibility,
22542259
info.Internalize ? llvm::GlobalValue::DefaultStorageClass
22552260
: ExportedStorage};
2261+
}
22562262

22572263
case SILLinkage::PublicNonABI:
22582264
case SILLinkage::PackageNonABI:
@@ -2264,6 +2270,9 @@ getIRLinkage(StringRef name, const UniversalLinkageInfo &info,
22642270
: RESULT(External, Hidden, Default);
22652271

22662272
case SILLinkage::Hidden:
2273+
if (info.MergeableSymbols)
2274+
return RESULT(LinkOnceODR, Hidden, Default);
2275+
22672276
return RESULT(External, Hidden, Default);
22682277

22692278
case SILLinkage::Private: {

lib/IRGen/Linking.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,19 @@ bool swift::irgen::useDllStorage(const llvm::Triple &triple) {
8282
UniversalLinkageInfo::UniversalLinkageInfo(IRGenModule &IGM)
8383
: UniversalLinkageInfo(IGM.Triple, IGM.IRGen.hasMultipleIGMs(),
8484
IGM.IRGen.Opts.ForcePublicLinkage,
85-
IGM.IRGen.Opts.InternalizeSymbols) {}
85+
IGM.IRGen.Opts.InternalizeSymbols,
86+
IGM.IRGen.Opts.MergeableSymbols) {}
8687

8788
UniversalLinkageInfo::UniversalLinkageInfo(const llvm::Triple &triple,
8889
bool hasMultipleIGMs,
8990
bool forcePublicDecls,
90-
bool isStaticLibrary)
91+
bool isStaticLibrary,
92+
bool mergeableSymbols)
9193
: IsELFObject(triple.isOSBinFormatELF()),
9294
IsMSVCEnvironment(triple.isWindowsMSVCEnvironment()),
9395
UseDLLStorage(useDllStorage(triple)), Internalize(isStaticLibrary),
94-
HasMultipleIGMs(hasMultipleIGMs), ForcePublicDecls(forcePublicDecls) {}
96+
HasMultipleIGMs(hasMultipleIGMs), ForcePublicDecls(forcePublicDecls),
97+
MergeableSymbols(mergeableSymbols) {}
9598

9699
LinkEntity LinkEntity::forSILGlobalVariable(SILGlobalVariable *G,
97100
IRGenModule &IGM) {

lib/IRGen/TBDGenVisitor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ class TBDGenVisitor : public IRSymbolVisitor {
126126
APIRecorder &recorder)
127127
: DataLayoutDescription(dataLayoutString),
128128
UniversalLinkInfo(target, opts.HasMultipleIGMs, /*forcePublic*/ false,
129-
/*static=*/false),
129+
/*static=*/false, /*mergeableSymbols*/false),
130130
SwiftModule(swiftModule), Opts(opts), recorder(recorder),
131131
previousInstallNameMap(parsePreviousModuleInstallNameMap()) {}
132132

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %{python} %utils/split_file.py -o %t %s
3+
4+
// RUN: %target-swift-frontend -mergeable-symbols -c -emit-module -o %t/MyModule.o %t/MyModule.swift -enable-experimental-feature Embedded -parse-as-library
5+
// RUN: %target-swift-frontend -mergeable-symbols -c -o %t/a.o %t/Main.swift -I %t -enable-experimental-feature Embedded
6+
// RUN: %target-clang %t/a.o %t/MyModule.o -o %t/a.out
7+
// RUN: %target-run %t/a.out | %FileCheck %s
8+
9+
// REQUIRES: swift_in_compiler
10+
// REQUIRES: executable_test
11+
// REQUIRES: OS=macosx || OS=linux-gnu
12+
// REQUIRES: swift_feature_Embedded
13+
14+
// BEGIN MyModule.swift
15+
16+
public func module_func() {
17+
print("module_func")
18+
}
19+
20+
public func module_generic_func<T: CustomStringConvertible>(t: T) {
21+
print("module_generic_func: \(t)")
22+
}
23+
24+
// BEGIN Main.swift
25+
26+
import MyModule
27+
28+
func test() {
29+
module_func()
30+
module_generic_func(t: 42)
31+
}
32+
33+
test()
34+
35+
// CHECK: module_func
36+
// CHECK: module_generic_func: 42

0 commit comments

Comments
 (0)