Skip to content

Commit 5ab0385

Browse files
Merge pull request #77564 from aschwaighofer/outlined_value_ops_private
IRGen: Outlined value functions of types that might expand differently in different TUs must use private linkage
2 parents 942d52f + f9941b3 commit 5ab0385

File tree

5 files changed

+77
-7
lines changed

5 files changed

+77
-7
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6192,13 +6192,18 @@ IRGenModule::getAddrOfContinuationPrototype(CanSILFunctionType fnType) {
61926192
/// Should we be defining the given helper function?
61936193
static llvm::Function *shouldDefineHelper(IRGenModule &IGM,
61946194
llvm::Constant *fn,
6195-
bool setIsNoInline) {
6195+
bool setIsNoInline,
6196+
IRLinkage *linkage) {
61966197
auto *def = dyn_cast<llvm::Function>(fn);
61976198
if (!def) return nullptr;
61986199
if (!def->empty()) return nullptr;
61996200

62006201
def->setAttributes(IGM.constructInitialAttributes());
6201-
ApplyIRLinkage(IRLinkage::InternalLinkOnceODR).to(def);
6202+
if (!linkage)
6203+
ApplyIRLinkage(IRLinkage::InternalLinkOnceODR).to(def);
6204+
else
6205+
ApplyIRLinkage(*linkage).to(def);
6206+
62026207
def->setDoesNotThrow();
62036208
def->setCallingConv(IGM.DefaultCC);
62046209
if (setIsNoInline)
@@ -6220,15 +6225,17 @@ IRGenModule::getOrCreateHelperFunction(StringRef fnName, llvm::Type *resultTy,
62206225
llvm::function_ref<void(IRGenFunction &IGF)> generate,
62216226
bool setIsNoInline,
62226227
bool forPrologue,
6223-
bool isPerformanceConstraint) {
6228+
bool isPerformanceConstraint,
6229+
IRLinkage *optionalLinkageOverride) {
62246230
llvm::FunctionType *fnTy =
62256231
llvm::FunctionType::get(resultTy, paramTys, false);
62266232

62276233
llvm::Constant *fn =
62286234
cast<llvm::Constant>(
62296235
Module.getOrInsertFunction(fnName, fnTy).getCallee());
62306236

6231-
if (llvm::Function *def = shouldDefineHelper(*this, fn, setIsNoInline)) {
6237+
if (llvm::Function *def = shouldDefineHelper(*this, fn, setIsNoInline,
6238+
optionalLinkageOverride)) {
62326239
IRGenFunction IGF(*this, def, isPerformanceConstraint);
62336240
if (DebugInfo && !forPrologue)
62346241
DebugInfo->emitArtificialFunction(IGF, def);

lib/IRGen/IRGenModule.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ namespace irgen {
147147
class StructLayout;
148148
class IRGenDebugInfo;
149149
class IRGenFunction;
150+
struct IRLinkage;
150151
class LinkEntity;
151152
class LoadableTypeInfo;
152153
class MetadataLayout;
@@ -1221,7 +1222,8 @@ class IRGenModule {
12211222
llvm::function_ref<void(IRGenFunction &IGF)> generate,
12221223
bool setIsNoInline = false,
12231224
bool forPrologue = false,
1224-
bool isPerformanceConstraint = false);
1225+
bool isPerformanceConstraint = false,
1226+
IRLinkage *optionalLinkage = nullptr);
12251227

12261228
llvm::Constant *getOrCreateRetainFunction(const TypeInfo &objectTI, SILType t,
12271229
llvm::Type *llvmType, Atomicity atomicity);

lib/IRGen/Outlining.cpp

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "swift/AST/IRGenOptions.h"
3131
#include "swift/Basic/Assertions.h"
3232
#include "swift/IRGen/GenericRequirement.h"
33+
#include "swift/IRGen/Linking.h"
3334
#include "swift/SIL/SILModule.h"
3435

3536
using namespace swift;
@@ -489,6 +490,22 @@ llvm::Constant *IRGenModule::getOrCreateOutlinedCopyAddrHelperFunction(
489490
paramTys.push_back(ptrTy);
490491
collector.addPolymorphicParameterTypes(paramTys);
491492

493+
IRLinkage *linkage = nullptr;
494+
IRLinkage privateLinkage = {
495+
llvm::GlobalValue::PrivateLinkage,
496+
llvm::GlobalValue::DefaultVisibility,
497+
llvm::GlobalValue::DefaultStorageClass,
498+
};
499+
auto &TL =
500+
getSILModule().Types.getTypeLowering(T, TypeExpansionContext::minimal());
501+
// Opaque result types might lead to different expansions in different files.
502+
// The default hidden linkonce_odr might lead to linking an implementation
503+
// from another file that head a different expansion/different
504+
// signature/different implementation.
505+
if (TL.getRecursiveProperties().isTypeExpansionSensitive()) {
506+
linkage = &privateLinkage;
507+
}
508+
492509
return getOrCreateHelperFunction(funcName, ptrTy, paramTys,
493510
[&](IRGenFunction &IGF) {
494511
auto params = IGF.collectParameters();
@@ -500,7 +517,8 @@ llvm::Constant *IRGenModule::getOrCreateOutlinedCopyAddrHelperFunction(
500517
},
501518
true /*setIsNoInline*/,
502519
false /*forPrologue*/,
503-
collector.IGF.isPerformanceConstraint);
520+
collector.IGF.isPerformanceConstraint,
521+
linkage);
504522
}
505523

506524
void TypeInfo::callOutlinedDestroy(IRGenFunction &IGF,
@@ -544,6 +562,22 @@ llvm::Constant *IRGenModule::getOrCreateOutlinedDestroyFunction(
544562
auto funcName = mangler.mangleOutlinedDestroyFunction(manglingBits.first,
545563
manglingBits.second, collector.IGF.isPerformanceConstraint);
546564

565+
IRLinkage *linkage = nullptr;
566+
IRLinkage privateLinkage = {
567+
llvm::GlobalValue::PrivateLinkage,
568+
llvm::GlobalValue::DefaultVisibility,
569+
llvm::GlobalValue::DefaultStorageClass,
570+
};
571+
auto &TL =
572+
getSILModule().Types.getTypeLowering(T, TypeExpansionContext::minimal());
573+
// Opaque result types might lead to different expansions in different files.
574+
// The default hidden linkonce_odr might lead to linking an implementation
575+
// from another file that head a different expansion/different
576+
// signature/different implementation.
577+
if (TL.getRecursiveProperties().isTypeExpansionSensitive()) {
578+
linkage = &privateLinkage;
579+
}
580+
547581
auto ptrTy = ti.getStorageType()->getPointerTo();
548582
llvm::SmallVector<llvm::Type *, 4> paramTys;
549583
paramTys.push_back(ptrTy);
@@ -565,7 +599,8 @@ llvm::Constant *IRGenModule::getOrCreateOutlinedDestroyFunction(
565599
},
566600
true /*setIsNoInline*/,
567601
false /*forPrologue*/,
568-
collector.IGF.isPerformanceConstraint);
602+
collector.IGF.isPerformanceConstraint,
603+
linkage);
569604
}
570605

571606
llvm::Constant *IRGenModule::getOrCreateRetainFunction(const TypeInfo &ti,
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
public func f<T>(_: T) {
2+
var g = G<T>()
3+
print(g.lazyVar)
4+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-swift-frontend -Xllvm -type-lowering-disable-verification -emit-ir -primary-file %s %S/Inputs/opaque_result_type_linkage_2.swift -module-name lib | %FileCheck %s
2+
// RUN: %target-swift-frontend -Xllvm -type-lowering-disable-verification -emit-ir %s -primary-file %S/Inputs/opaque_result_type_linkage_2.swift -module-name lib | %FileCheck %s --check-prefix=OTHER
3+
4+
protocol P {
5+
associatedtype A
6+
var a: A { get }
7+
}
8+
9+
struct G<T>: P {
10+
lazy var lazyVar: A = a
11+
12+
var a: some Any {
13+
"hello"
14+
}
15+
}
16+
17+
// We lower the two outlined destroy functions differently depending on the type
18+
// expansion context (there is an opaque result type).
19+
// We therefore must not use hidden linkonce_odr linkage.
20+
21+
// CHECK: define{{.*}} private ptr @"$s3lib1GVyxGlWOh"(ptr %0)
22+
// OTHER: define{{.*}} private ptr @"$s3lib1GVyxGlWOh"(ptr %0, ptr %"some Any", ptr %"Optional<some Any>", ptr %"G<T>")

0 commit comments

Comments
 (0)