Skip to content

Commit f0c3ac1

Browse files
authored
Merge pull request #3035 from eeckstein/transparent-codegen
2 parents e69195b + d23551a commit f0c3ac1

File tree

7 files changed

+66
-3
lines changed

7 files changed

+66
-3
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1216,7 +1216,8 @@ bool LinkEntity::isFragile(IRGenModule &IGM) const {
12161216
static std::pair<llvm::GlobalValue::LinkageTypes,
12171217
llvm::GlobalValue::VisibilityTypes>
12181218
getIRLinkage(IRGenModule &IGM,
1219-
SILLinkage linkage, bool isFragile, ForDefinition_t isDefinition,
1219+
SILLinkage linkage, bool isFragile, bool isSILOnly,
1220+
ForDefinition_t isDefinition,
12201221
bool isWeakImported) {
12211222

12221223
#define RESULT(LINKAGE, VISIBILITY) \
@@ -1260,6 +1261,22 @@ llvm::GlobalValue::VISIBILITY##Visibility }
12601261

12611262
switch (linkage) {
12621263
case SILLinkage::Public:
1264+
// Don't code-gen transparent functions. Internal linkage
1265+
// will enable llvm to delete transparent functions except
1266+
// they are referenced from somewhere (i.e. the function pointer
1267+
// is taken).
1268+
if (isSILOnly &&
1269+
// In case we are generating multiple LLVM modules, we still have to
1270+
// use ExternalLinkage so that modules can cross-reference transparent
1271+
// functions.
1272+
!IGM.IRGen.hasMultipleIGMs() &&
1273+
1274+
// TODO: In non-whole-module-opt the generated swiftmodules are "linked"
1275+
// and this strips all serialized transparent functions. So we have to
1276+
// code-gen transparent functions in non-whole-module-opt.
1277+
IGM.getSILModule().isWholeModule()) {
1278+
return RESULT(Internal, Default);
1279+
}
12631280
return {llvm::GlobalValue::ExternalLinkage, PublicDefinitionVisibility};
12641281
case SILLinkage::Shared:
12651282
case SILLinkage::SharedExternal: return RESULT(LinkOnceODR, Hidden);
@@ -1273,6 +1290,10 @@ llvm::GlobalValue::VISIBILITY##Visibility }
12731290
return RESULT(Internal, Default);
12741291
case SILLinkage::PublicExternal:
12751292
if (isDefinition) {
1293+
if (isSILOnly) {
1294+
// Transparent function are not available externally.
1295+
return RESULT(LinkOnceODR, Hidden);
1296+
}
12761297
return RESULT(AvailableExternally, Default);
12771298
}
12781299

@@ -1303,6 +1324,7 @@ static void updateLinkageForDefinition(IRGenModule &IGM,
13031324
IGM,
13041325
entity.getLinkage(IGM, ForDefinition),
13051326
entity.isFragile(IGM),
1327+
entity.isSILOnly(),
13061328
ForDefinition,
13071329
entity.isWeakImported(IGM.getSwiftModule()));
13081330
global->setLinkage(linkage.first);
@@ -1329,6 +1351,7 @@ LinkInfo LinkInfo::get(IRGenModule &IGM, const LinkEntity &entity,
13291351
std::tie(result.Linkage, result.Visibility) =
13301352
getIRLinkage(IGM, entity.getLinkage(IGM, isDefinition),
13311353
entity.isFragile(IGM),
1354+
entity.isSILOnly(),
13321355
isDefinition,
13331356
entity.isWeakImported(IGM.getSwiftModule()));
13341357

lib/IRGen/Linking.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,17 @@ class LinkEntity {
520520
assert(getKind() == Kind::SILFunction);
521521
return reinterpret_cast<SILFunction*>(Pointer);
522522
}
523-
523+
524+
/// Returns true if this function is only serialized, but not necessarily
525+
/// code-gen'd. These are fragile transparent functions.
526+
bool isSILOnly() const {
527+
if (getKind() != Kind::SILFunction)
528+
return false;
529+
530+
SILFunction *F = getSILFunction();
531+
return F->isTransparent() && F->isDefinition() && F->isFragile();
532+
}
533+
524534
SILGlobalVariable *getSILGlobalVariable() const {
525535
assert(getKind() == Kind::SILGlobalVariable);
526536
return reinterpret_cast<SILGlobalVariable*>(Pointer);

lib/SILOptimizer/IPO/ExternalDefsToDecls.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class ExternalDefsToDecls : public SILModuleTransform {
2626
for (auto &F : *getModule()) {
2727
SILLinkage linkage = F.getLinkage();
2828
if (isAvailableExternally(linkage) && F.isDefinition() &&
29-
!hasSharedVisibility(linkage)) {
29+
!hasSharedVisibility(linkage) && !F.isTransparent()) {
3030
F.convertToDeclaration();
3131
invalidateAnalysis(&F, SILAnalysis::InvalidationKind::FunctionBody);
3232
}

lib/SILOptimizer/Mandatory/MandatoryInlining.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,15 @@ class MandatoryInlining : public SILModuleTransform {
464464
SetFactory, SetFactory.getEmptySet(), CHA);
465465
}
466466

467+
// Make sure that we de-serialize all transparent functions,
468+
// even if we didn't inline them for some reason.
469+
// Transparent functions are not available externally, so we
470+
// have to generate code for them.
471+
for (auto &F : *M) {
472+
if (F.isTransparent())
473+
M->linkFunction(&F, Mode);
474+
}
475+
467476
if (!ShouldCleanup)
468477
return;
469478

test/IRGen/Inputs/multithread_module/main.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ private struct MyStruct : MyProto {
1919
}
2020
}
2121

22+
@_transparent public func transparentfunc(_ x: Int) -> Int {
23+
return x + 3
24+
}
25+
2226
public var g1 = 234
2327

2428
let i = testit(27)

test/IRGen/multithread_module.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ func callPrivInc(_ x: Int) -> Int {
4545
return privateInc(x)
4646
}
4747

48+
// Check if we use the correct linkage for a transparent function
49+
public var transparentfuncptr = transparentfunc
50+
4851
protocol MyProto {
4952
func protofunc() -> Int
5053
}

test/IRGen/sil_linkage.sil

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
sil_stage canonical
44

55
// CHECK: define{{( protected)?}} void @public_fragile_function_test() {{.*}} {
6+
// CHECK: define{{( protected)?}} internal void @public_transparent_fragile_function_test() {{.*}} {
7+
// CHECK: define{{( protected)?}} void @public_transparent_function_test() {{.*}} {
68
// CHECK: define{{( protected)?}} void @hidden_fragile_function_test() {{.*}} {
79
// CHECK: define linkonce_odr hidden void @shared_fragile_function_test() {{.*}} {
810
// CHECK: define{{( protected)?}} void @private_fragile_function_test() {{.*}} {
@@ -23,6 +25,16 @@ sil public [fragile] @public_fragile_function_test : $@convention(thin) () -> ()
2325
return %0 : $()
2426
}
2527

28+
sil public [transparent] [fragile] @public_transparent_fragile_function_test : $@convention(thin) () -> () {
29+
%0 = tuple()
30+
return %0 : $()
31+
}
32+
33+
sil public [transparent] @public_transparent_function_test : $@convention(thin) () -> () {
34+
%0 = tuple()
35+
return %0 : $()
36+
}
37+
2638
sil hidden [fragile] @hidden_fragile_function_test : $@convention(thin) () -> () {
2739
%0 = tuple()
2840
return %0 : $()
@@ -122,6 +134,8 @@ sil hidden_external @hidden_external_resilient_function_decl_test : $@convention
122134

123135
sil public @use_all_symbols : $@convention(thin) () -> () {
124136
%0 = function_ref @public_fragile_function_test : $@convention(thin) () -> ()
137+
%t0 = function_ref @public_transparent_fragile_function_test : $@convention(thin) () -> ()
138+
%t1 = function_ref @public_transparent_function_test : $@convention(thin) () -> ()
125139
%1 = function_ref @hidden_fragile_function_test : $@convention(thin) () -> ()
126140
%2 = function_ref @shared_fragile_function_test : $@convention(thin) () -> ()
127141
%3 = function_ref @private_fragile_function_test : $@convention(thin) () -> ()

0 commit comments

Comments
 (0)