Skip to content

Commit 1ef2a56

Browse files
authored
Merge pull request #62651 from tshortli/has-symbol-dynamic
IRGen: Generate #_hasSymbol helpers for `dynamic` and `@_dynamicReplacement(for:)` functions
2 parents e159040 + 5c13523 commit 1ef2a56

File tree

5 files changed

+72
-5
lines changed

5 files changed

+72
-5
lines changed

include/swift/IRGen/Linking.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,6 +1509,9 @@ class LinkEntity {
15091509
getKind() == Kind::OpaqueTypeDescriptorAccessorKey ||
15101510
getKind() == Kind::OpaqueTypeDescriptorAccessorVar;
15111511
}
1512+
bool isOpaqueTypeDescriptorAccessorImpl() const {
1513+
return getKind() == Kind::OpaqueTypeDescriptorAccessorImpl;
1514+
}
15121515
bool isAllocator() const {
15131516
assert(getKind() == Kind::DynamicallyReplaceableFunctionImpl ||
15141517
getKind() == Kind::DynamicallyReplaceableFunctionKeyAST ||
@@ -1540,6 +1543,9 @@ class LinkEntity {
15401543
bool isDynamicallyReplaceableFunctionKey() const {
15411544
return getKind() == Kind::DynamicallyReplaceableFunctionKey;
15421545
}
1546+
bool isDynamicallyReplaceableFunctionImpl() const {
1547+
return getKind() == Kind::DynamicallyReplaceableFunctionImpl;
1548+
}
15431549
bool isTypeMetadataAccessFunction() const {
15441550
return getKind() == Kind::TypeMetadataAccessFunction;
15451551
}

lib/IRGen/GenHasSymbol.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,37 @@ static llvm::Constant *getAddrOfLLVMVariable(IRGenModule &IGM,
3939
if (entity.isDispatchThunk())
4040
return IGM.getAddrOfDispatchThunk(entity.getSILDeclRef(), NotForDefinition);
4141

42+
if (entity.isOpaqueTypeDescriptorAccessor()) {
43+
OpaqueTypeDecl *decl =
44+
const_cast<OpaqueTypeDecl *>(cast<OpaqueTypeDecl>(entity.getDecl()));
45+
bool isImplementation = entity.isOpaqueTypeDescriptorAccessorImpl();
46+
return IGM
47+
.getAddrOfOpaqueTypeDescriptorAccessFunction(decl, NotForDefinition,
48+
isImplementation)
49+
.getDirectPointer();
50+
}
51+
52+
// FIXME: Look up addr of the replaceable function (has "TI" mangling suffix)
53+
if (entity.isDynamicallyReplaceableFunctionImpl())
54+
return nullptr;
55+
4256
return IGM.getAddrOfLLVMVariable(entity, ConstantInit(), DebugTypeInfo());
4357
}
4458

4559
class HasSymbolIRGenVisitor : public IRSymbolVisitor {
4660
IRGenModule &IGM;
4761
llvm::SmallVector<llvm::Constant *, 4> &Addrs;
4862

63+
void addFunction(SILFunction *fn) {
64+
Addrs.emplace_back(IGM.getAddrOfSILFunction(fn, NotForDefinition));
65+
}
66+
4967
void addFunction(StringRef name) {
5068
SILFunction *silFn = IGM.getSILModule().lookUpFunction(name);
5169
// Definitions for each SIL function should have been emitted by SILGen.
5270
assert(silFn && "missing SIL function?");
5371
if (silFn) {
54-
Addrs.emplace_back(IGM.getAddrOfSILFunction(silFn, NotForDefinition));
72+
addFunction(silFn);
5573
}
5674
}
5775

@@ -74,9 +92,16 @@ class HasSymbolIRGenVisitor : public IRSymbolVisitor {
7492
}
7593

7694
void addLinkEntity(LinkEntity entity) override {
95+
if (entity.hasSILFunction()) {
96+
addFunction(entity.getSILFunction());
97+
return;
98+
}
99+
77100
auto constant = getAddrOfLLVMVariable(IGM, entity);
78-
auto global = cast<llvm::GlobalValue>(constant);
79-
Addrs.emplace_back(global);
101+
if (constant) {
102+
auto global = cast<llvm::GlobalValue>(constant);
103+
Addrs.emplace_back(global);
104+
}
80105
}
81106

82107
void addProtocolWitnessThunk(RootProtocolConformance *C,

lib/IRGen/Linking.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,9 +1065,11 @@ llvm::Type *LinkEntity::getDefaultDeclarationType(IRGenModule &IGM) const {
10651065
case Kind::MethodDescriptorDerivative:
10661066
return IGM.MethodDescriptorStructTy;
10671067
case Kind::DynamicallyReplaceableFunctionKey:
1068+
case Kind::DynamicallyReplaceableFunctionKeyAST:
10681069
case Kind::OpaqueTypeDescriptorAccessorKey:
10691070
return IGM.DynamicReplacementKeyTy;
10701071
case Kind::DynamicallyReplaceableFunctionVariable:
1072+
case Kind::DynamicallyReplaceableFunctionVariableAST:
10711073
case Kind::OpaqueTypeDescriptorAccessorVar:
10721074
return IGM.DynamicReplacementLinkEntryTy;
10731075
case Kind::ObjCMetadataUpdateFunction:
@@ -1158,7 +1160,9 @@ Alignment LinkEntity::getAlignment(IRGenModule &IGM) const {
11581160
case Kind::SwiftMetaclassStub:
11591161
case Kind::CanonicalSpecializedGenericSwiftMetaclassStub:
11601162
case Kind::DynamicallyReplaceableFunctionVariable:
1163+
case Kind::DynamicallyReplaceableFunctionVariableAST:
11611164
case Kind::DynamicallyReplaceableFunctionKey:
1165+
case Kind::DynamicallyReplaceableFunctionKeyAST:
11621166
case Kind::OpaqueTypeDescriptorAccessorKey:
11631167
case Kind::OpaqueTypeDescriptorAccessorVar:
11641168
case Kind::ObjCResilientClassStub:

test/IRGen/Inputs/has_symbol_helper.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ public func funcWithOpaqueResult() -> some P { return S(member: 0) }
1919
public func asyncFunc() async {}
2020
#endif
2121

22+
public dynamic func dynamicFunc() {}
23+
@_dynamicReplacement(for: dynamicFunc) public func replacementFunc() {}
24+
25+
public dynamic func dynamicFuncOpaqueResult() -> some P { return S(member: 0) }
26+
@_dynamicReplacement(for: dynamicFuncOpaqueResult)
27+
public func replacementFuncOpaqueResult() -> some P { return S(member: 1) }
28+
2229
public protocol P {
2330
func requirement()
2431
func requirementWithDefaultImpl()

test/IRGen/has_symbol.swift

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,17 @@ public func testGlobalFunctions() {
2828
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper19forwardDeclaredFuncyyFTwS"()
2929
if #_hasSymbol(forwardDeclaredFunc) {}
3030

31-
// FIXME: Test `dynamic` functions
32-
// FIXME: Test `dynamic` functions with opaque return types
31+
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper11dynamicFuncyyFTwS"()
32+
if #_hasSymbol(dynamicFunc) {}
33+
34+
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper15replacementFuncyyFTwS"()
35+
if #_hasSymbol(replacementFunc) {}
36+
37+
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper23dynamicFuncOpaqueResultQryFTwS"()
38+
if #_hasSymbol(dynamicFuncOpaqueResult) {}
39+
40+
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper27replacementFuncOpaqueResultQryFTwS"()
41+
if #_hasSymbol(replacementFuncOpaqueResult) {}
3342
}
3443

3544
// --- function(with:) ---
@@ -56,6 +65,22 @@ public func testGlobalFunctions() {
5665
// CHECK: define linkonce_odr hidden i1 @"$s17has_symbol_helper19forwardDeclaredFuncyyFTwS"()
5766
// CHECK: ret i1 icmp ne (void ()* @forward_declared_func, void ()* null)
5867

68+
// --- dynamicFunc() ---
69+
// CHECK: define linkonce_odr hidden i1 @"$s17has_symbol_helper11dynamicFuncyyFTwS"()
70+
// CHECK: ret i1 and (i1 and (i1 icmp ne (void ()* @"$s17has_symbol_helper11dynamicFuncyyF", void ()* null), i1 icmp ne (%swift.dyn_repl_link_entry* @"$s17has_symbol_helper11dynamicFuncyyFTX", %swift.dyn_repl_link_entry* null)), i1 icmp ne (%swift.dyn_repl_key* @"$s17has_symbol_helper11dynamicFuncyyFTx", %swift.dyn_repl_key* null))
71+
72+
// --- replacementFunc() ---
73+
// CHECK: define linkonce_odr hidden i1 @"$s17has_symbol_helper15replacementFuncyyFTwS"()
74+
// CHECK: ret i1 and (i1 icmp ne (void ()* @"$s17has_symbol_helper15replacementFuncyyF", void ()* null), i1 icmp ne (%swift.dyn_repl_link_entry* @"$s17has_symbol_helper15replacementFuncyyFTX", %swift.dyn_repl_link_entry* null))
75+
76+
// --- dynamicFuncOpaqueResult() ---
77+
// CHECK: define linkonce_odr hidden i1 @"$s17has_symbol_helper23dynamicFuncOpaqueResultQryFTwS"()
78+
// CHECK: ret i1 and (i1 and (i1 and (i1 and (i1 and (i1 and (i1 and (i1 icmp ne (%swift.type_descriptor* @"$s17has_symbol_helper23dynamicFuncOpaqueResultQryFQOMQ", %swift.type_descriptor* null), i1 icmp ne (%swift.type_descriptor* ()* @"$s17has_symbol_helper23dynamicFuncOpaqueResultQryFQOMg", %swift.type_descriptor* ()* null)), i1 icmp ne (%swift.type_descriptor* ()* @"$s17has_symbol_helper23dynamicFuncOpaqueResultQryFQOMh", %swift.type_descriptor* ()* null)), i1 icmp ne (%swift.type_descriptor* ()* @"$s17has_symbol_helper23dynamicFuncOpaqueResultQryFQOMg", %swift.type_descriptor* ()* null)), i1 icmp ne (%swift.type_descriptor* ()* @"$s17has_symbol_helper23dynamicFuncOpaqueResultQryFQOMg", %swift.type_descriptor* ()* null)), i1 icmp ne (void (%swift.opaque*)* @"$s17has_symbol_helper23dynamicFuncOpaqueResultQryF", void (%swift.opaque*)* null)), i1 icmp ne (%swift.dyn_repl_link_entry* @"$s17has_symbol_helper23dynamicFuncOpaqueResultQryFTX", %swift.dyn_repl_link_entry* null)), i1 icmp ne (%swift.dyn_repl_key* @"$s17has_symbol_helper23dynamicFuncOpaqueResultQryFTx", %swift.dyn_repl_key* null))
79+
80+
// --- replacementFuncOpaqueResult() ---
81+
// CHECK: define linkonce_odr hidden i1 @"$s17has_symbol_helper27replacementFuncOpaqueResultQryFTwS"()
82+
// CHECK: ret i1 and (i1 and (i1 and (i1 and (i1 icmp ne (%swift.type_descriptor* @"$s17has_symbol_helper27replacementFuncOpaqueResultQryFQOMQ", %swift.type_descriptor* null), i1 icmp ne (%swift.type_descriptor* ()* @"$s17has_symbol_helper27replacementFuncOpaqueResultQryFQOMg", %swift.type_descriptor* ()* null)), i1 icmp ne (%swift.type_descriptor* ()* @"$s17has_symbol_helper27replacementFuncOpaqueResultQryFQOMg", %swift.type_descriptor* ()* null)), i1 icmp ne (void (%swift.opaque*)* @"$s17has_symbol_helper27replacementFuncOpaqueResultQryF", void (%swift.opaque*)* null)), i1 icmp ne (%swift.dyn_repl_link_entry* @"$s17has_symbol_helper27replacementFuncOpaqueResultQryFTX", %swift.dyn_repl_link_entry* null))
83+
5984
public func testVars() {
6085
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper6globalSivpTwS"()
6186
if #_hasSymbol(global) {}

0 commit comments

Comments
 (0)