Skip to content

Commit ae32b8e

Browse files
committed
IRGen: Implement lowering of has_symbol SIL instruction.
1 parent abdc4d9 commit ae32b8e

File tree

7 files changed

+145
-106
lines changed

7 files changed

+145
-106
lines changed

include/swift/SIL/SILModule.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -315,9 +315,6 @@ class SILModule {
315315
/// This is the set of undef values we've created, for uniquing purposes.
316316
llvm::DenseMap<SILType, SILUndef *> UndefValues;
317317

318-
/// The list of decls that require query functions for #_hasSymbol conditions.
319-
llvm::SetVector<ValueDecl *> hasSymbolDecls;
320-
321318
llvm::DenseMap<std::pair<Decl *, VarDecl *>, unsigned> fieldIndices;
322319
llvm::DenseMap<EnumElementDecl *, unsigned> enumCaseIndices;
323320

@@ -703,12 +700,6 @@ class SILModule {
703700
return externallyVisible.count(decl) != 0;
704701
}
705702

706-
void addHasSymbolDecl(ValueDecl *decl) { hasSymbolDecls.insert(decl); }
707-
708-
ArrayRef<ValueDecl *> getHasSymbolDecls() {
709-
return hasSymbolDecls.getArrayRef();
710-
}
711-
712703
using sil_global_iterator = GlobalListType::iterator;
713704
using sil_global_const_iterator = GlobalListType::const_iterator;
714705
GlobalListType &getSILGlobalList() { return silGlobals; }

lib/IRGen/GenHasSymbol.cpp

Lines changed: 39 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -86,48 +86,43 @@ class HasSymbolIRGenVisitor : public IRSymbolVisitor {
8686
}
8787
};
8888

89-
void IRGenModule::emitHasSymbolFunctions() {
90-
SILSymbolVisitorOptions opts;
91-
opts.VisitMembers = false;
92-
auto silCtx = SILSymbolVisitorContext(getSwiftModule(), opts);
93-
auto linkInfo = UniversalLinkageInfo(*this);
94-
auto symbolVisitorCtx = IRSymbolVisitorContext(linkInfo, silCtx);
95-
96-
for (ValueDecl *decl : getSILModule().getHasSymbolDecls()) {
97-
PrettyStackTraceDecl trace("emitting #_hasSymbol query for", decl);
98-
Mangle::ASTMangler mangler;
99-
100-
auto func = cast<llvm::Function>(getOrCreateHelperFunction(
101-
mangler.mangleHasSymbolQuery(decl), Int1Ty, {},
102-
[decl, this, symbolVisitorCtx](IRGenFunction &IGF) {
103-
auto &Builder = IGF.Builder;
104-
llvm::SmallVector<llvm::Constant *, 4> addrs;
105-
HasSymbolIRGenVisitor(*this, addrs).visit(decl, symbolVisitorCtx);
106-
107-
llvm::Value *ret = nullptr;
108-
for (llvm::Constant *addr : addrs) {
109-
assert(cast<llvm::GlobalValue>(addr)->hasExternalWeakLinkage());
110-
111-
auto isNonNull = IGF.Builder.CreateIsNotNull(addr);
112-
ret = (ret) ? IGF.Builder.CreateAnd(ret, isNonNull) : isNonNull;
113-
}
114-
115-
if (ret) {
116-
Builder.CreateRet(ret);
117-
} else {
118-
// There were no addresses produced by the visitor, return true.
119-
Builder.CreateRet(llvm::ConstantInt::get(Int1Ty, 1));
120-
}
121-
},
122-
/*IsNoInline*/ false));
123-
124-
func->setDoesNotThrow();
125-
func->setCallingConv(SwiftCC);
126-
func->addFnAttr(llvm::Attribute::ReadOnly);
127-
}
128-
}
129-
130-
void IRGenerator::emitHasSymbolFunctions() {
131-
for (auto &IGM : *this)
132-
IGM.second->emitHasSymbolFunctions();
89+
llvm::Function *IRGenModule::emitHasSymbolFunction(ValueDecl *decl) {
90+
91+
PrettyStackTraceDecl trace("emitting #_hasSymbol query for", decl);
92+
Mangle::ASTMangler mangler;
93+
94+
auto func = cast<llvm::Function>(getOrCreateHelperFunction(
95+
mangler.mangleHasSymbolQuery(decl), Int1Ty, {},
96+
[decl, this](IRGenFunction &IGF) {
97+
SILSymbolVisitorOptions opts;
98+
opts.VisitMembers = false;
99+
auto silCtx = SILSymbolVisitorContext(getSwiftModule(), opts);
100+
auto linkInfo = UniversalLinkageInfo(*this);
101+
auto symbolVisitorCtx = IRSymbolVisitorContext(linkInfo, silCtx);
102+
auto &Builder = IGF.Builder;
103+
llvm::SmallVector<llvm::Constant *, 4> addrs;
104+
HasSymbolIRGenVisitor(*this, addrs).visit(decl, symbolVisitorCtx);
105+
106+
llvm::Value *ret = nullptr;
107+
for (llvm::Constant *addr : addrs) {
108+
assert(cast<llvm::GlobalValue>(addr)->hasExternalWeakLinkage());
109+
110+
auto isNonNull = IGF.Builder.CreateIsNotNull(addr);
111+
ret = (ret) ? IGF.Builder.CreateAnd(ret, isNonNull) : isNonNull;
112+
}
113+
114+
if (ret) {
115+
Builder.CreateRet(ret);
116+
} else {
117+
// There were no addresses produced by the visitor, return true.
118+
Builder.CreateRet(llvm::ConstantInt::get(Int1Ty, 1));
119+
}
120+
},
121+
/*IsNoInline*/ false));
122+
123+
func->setDoesNotThrow();
124+
func->setCallingConv(DefaultCC);
125+
func->addFnAttr(llvm::Attribute::ReadOnly);
126+
127+
return func;
133128
}

lib/IRGen/IRGen.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,9 +1348,6 @@ GeneratedModule IRGenRequest::evaluate(Evaluator &evaluator,
13481348
// Okay, emit any definitions that we suddenly need.
13491349
irgen.emitLazyDefinitions();
13501350

1351-
// Emit functions supporting `if #_hasSymbol(...)` conditions.
1352-
IGM.emitHasSymbolFunctions();
1353-
13541351
// Register our info with the runtime if needed.
13551352
if (Opts.UseJIT) {
13561353
IGM.emitBuiltinReflectionMetadata();

lib/IRGen/IRGenModule.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -432,9 +432,6 @@ class IRGenerator {
432432
/// Emit coverage mapping info.
433433
void emitCoverageMapping();
434434

435-
/// Emit helper functions for `if #_hasSymbol(...)` conditions.
436-
void emitHasSymbolFunctions();
437-
438435
/// Checks if metadata for this type can be emitted lazily. This is true for
439436
/// non-public types as well as imported types, except for classes and
440437
/// protocols which are always emitted eagerly.
@@ -1832,7 +1829,7 @@ private: \
18321829
void emitRuntimeRegistration();
18331830
void emitVTableStubs();
18341831
void emitTypeVerifier();
1835-
void emitHasSymbolFunctions();
1832+
llvm::Function *emitHasSymbolFunction(ValueDecl *decl);
18361833

18371834
/// Create llvm metadata which encodes the branch weights given by
18381835
/// \p TrueCount and \p FalseCount.

lib/IRGen/IRGenSIL.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2614,7 +2614,12 @@ void IRGenSILFunction::visitDifferentiabilityWitnessFunctionInst(
26142614
}
26152615

26162616
void IRGenSILFunction::visitHasSymbolInst(HasSymbolInst *i) {
2617-
llvm_unreachable("unimplemented"); // FIXME: implement lowering
2617+
auto fn = IGM.emitHasSymbolFunction(i->getDecl());
2618+
llvm::CallInst *call = Builder.CreateCall(fn->getFunctionType(), fn, {});
2619+
2620+
Explosion e;
2621+
e.add(call);
2622+
setLoweredValue(i, e);
26182623
}
26192624

26202625
FunctionPointer::Kind irgen::classifyFunctionPointerKind(SILFunction *fn) {

test/IRGen/has_symbol.swift

Lines changed: 77 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,73 +9,115 @@
99

1010
@_weakLinked import has_symbol_helper
1111

12-
func testGlobalFunctions() {
12+
public func testGlobalFunctions() {
13+
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper8function4withySi_tFTwS"()
1314
if #_hasSymbol(function(with:)) {}
14-
// CHECK: define linkonce_odr hidden swiftcc i1 @"$s17has_symbol_helper8function4withySi_tFTwS"()
15-
// CHECK: ret i1 icmp ne (void ({{i32|i64}})* @"$s17has_symbol_helper8function4withySi_tF", void (i64)* null)
1615

16+
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper12throwingFuncyyKFTwS"()
1717
if #_hasSymbol(throwingFunc) {}
18-
// CHECK: define linkonce_odr hidden swiftcc i1 @"$s17has_symbol_helper12throwingFuncyyKFTwS"()
19-
// CHECK: ret i1 icmp ne (void (%swift.refcounted*, %swift.error**)* @"$s17has_symbol_helper12throwingFuncyyKF", void (%swift.refcounted*, %swift.error**)* null)
2018

19+
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper11genericFuncyyxAA1PRzlFTwS"()
2120
if #_hasSymbol(genericFunc(_:) as (S) -> Void) {}
22-
// CHECK: define linkonce_odr hidden swiftcc i1 @"$s17has_symbol_helper11genericFuncyyxAA1PRzlFTwS"()
23-
// CHECK: ret i1 icmp ne (void (%swift.opaque*, %swift.type*, i8**)* @"$s17has_symbol_helper11genericFuncyyxAA1PRzlF", void (%swift.opaque*, %swift.type*, i8**)* null)
2421

22+
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper20funcWithOpaqueResultQryFTwS"()
2523
if #_hasSymbol(funcWithOpaqueResult) {}
26-
// CHECK: define linkonce_odr hidden swiftcc i1 @"$s17has_symbol_helper20funcWithOpaqueResultQryFTwS"()
27-
// CHECK: ret i1 and (i1 icmp ne (%swift.type_descriptor* @"$s17has_symbol_helper20funcWithOpaqueResultQryFQOMQ", %swift.type_descriptor* null), i1 icmp ne (void (%swift.opaque*)* @"$s17has_symbol_helper20funcWithOpaqueResultQryF", void (%swift.opaque*)* null))
2824

25+
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper9cdeclFuncyyFTwS"()
2926
if #_hasSymbol(cdeclFunc) {}
30-
// CHECK: define linkonce_odr hidden swiftcc i1 @"$s17has_symbol_helper9cdeclFuncyyFTwS"()
31-
// CHECK: ret i1 and (i1 icmp ne (void ()* @"$s17has_symbol_helper9cdeclFuncyyF", void ()* null), i1 icmp ne (void ()* @cdecl_func, void ()* null))
3227

28+
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper19forwardDeclaredFuncyyFTwS"()
3329
if #_hasSymbol(forwardDeclaredFunc) {}
34-
// CHECK: define linkonce_odr hidden swiftcc i1 @"$s17has_symbol_helper19forwardDeclaredFuncyyFTwS"()
35-
// CHECK: ret i1 icmp ne (void ()* @forward_declared_func, void ()* null)
36-
30+
3731
// FIXME: Test `dynamic` functions
3832
// FIXME: Test `dynamic` functions with opaque return types
3933
}
4034

41-
func testVars() {
35+
// --- function(with:) ---
36+
// CHECK: define linkonce_odr hidden i1 @"$s17has_symbol_helper8function4withySi_tFTwS"()
37+
// CHECK: ret i1 icmp ne (void ({{i32|i64}})* @"$s17has_symbol_helper8function4withySi_tF", void (i64)* null)
38+
39+
// --- throwingFunc() ---
40+
// CHECK: define linkonce_odr hidden i1 @"$s17has_symbol_helper12throwingFuncyyKFTwS"()
41+
// CHECK: ret i1 icmp ne (void (%swift.refcounted*, %swift.error**)* @"$s17has_symbol_helper12throwingFuncyyKF", void (%swift.refcounted*, %swift.error**)* null)
42+
43+
// --- genericFunc(_:) ---
44+
// CHECK: define linkonce_odr hidden i1 @"$s17has_symbol_helper11genericFuncyyxAA1PRzlFTwS"()
45+
// CHECK: ret i1 icmp ne (void (%swift.opaque*, %swift.type*, i8**)* @"$s17has_symbol_helper11genericFuncyyxAA1PRzlF", void (%swift.opaque*, %swift.type*, i8**)* null)
46+
47+
// --- funcWithOpaqueResult() ---
48+
// CHECK: define linkonce_odr hidden i1 @"$s17has_symbol_helper20funcWithOpaqueResultQryFTwS"()
49+
// CHECK: ret i1 and (i1 icmp ne (%swift.type_descriptor* @"$s17has_symbol_helper20funcWithOpaqueResultQryFQOMQ", %swift.type_descriptor* null), i1 icmp ne (void (%swift.opaque*)* @"$s17has_symbol_helper20funcWithOpaqueResultQryF", void (%swift.opaque*)* null))
50+
51+
// --- cdeclFunc() ---
52+
// CHECK: define linkonce_odr hidden i1 @"$s17has_symbol_helper9cdeclFuncyyFTwS"()
53+
// CHECK: ret i1 and (i1 icmp ne (void ()* @"$s17has_symbol_helper9cdeclFuncyyF", void ()* null), i1 icmp ne (void ()* @cdecl_func, void ()* null))
54+
55+
// --- forwardDeclaredFunc() ---
56+
// CHECK: define linkonce_odr hidden i1 @"$s17has_symbol_helper19forwardDeclaredFuncyyFTwS"()
57+
// CHECK: ret i1 icmp ne (void ()* @forward_declared_func, void ()* null)
58+
59+
public func testVars() {
60+
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper6globalSivpTwS"()
4261
if #_hasSymbol(global) {}
43-
// CHECK: define linkonce_odr hidden swiftcc i1 @"$s17has_symbol_helper6globalSivpTwS"()
44-
// CHECK: ret i1 icmp ne (i64 ()* @"$s17has_symbol_helper6globalSivg", i64 ()* null)
4562
}
4663

47-
func testClass(_ c: C) {
64+
// --- global ---
65+
// CHECK: define linkonce_odr hidden i1 @"$s17has_symbol_helper6globalSivpTwS"()
66+
// CHECK: ret i1 icmp ne (i64 ()* @"$s17has_symbol_helper6globalSivg", i64 ()* null)
67+
68+
public func testClass(_ c: C) {
69+
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper1CCACycfcTwS"()
4870
if #_hasSymbol(C.init) {}
49-
// CHECK: define linkonce_odr hidden swiftcc i1 @"$s17has_symbol_helper1CCACycfcTwS"()
50-
// CHECK: ret i1 and (i1 icmp ne (%T17has_symbol_helper1CC* (%T17has_symbol_helper1CC*)* @"$s17has_symbol_helper1CCACycfc", %T17has_symbol_helper1CC* (%T17has_symbol_helper1CC*)* null), i1 icmp ne (%T17has_symbol_helper1CC* (%swift.type*)* @"$s17has_symbol_helper1CCACycfC", %T17has_symbol_helper1CC* (%swift.type*)* null))
5171

72+
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper1CC6method4withySi_tFTwS"()
5273
if #_hasSymbol(c.method(with:)) {}
53-
// CHECK: define linkonce_odr hidden swiftcc i1 @"$s17has_symbol_helper1CC6method4withySi_tFTwS"()
54-
// CHECK: ret i1 and (i1 icmp ne (void (i64, %T17has_symbol_helper1CC*)* @"$s17has_symbol_helper1CC6method4withySi_tFTj", void (i64, %T17has_symbol_helper1CC*)* null), i1 icmp ne (%swift.method_descriptor* @"$s17has_symbol_helper1CC6method4withySi_tFTq", %swift.method_descriptor* null))
5574
}
5675

57-
func testStruct(_ s: S) {
76+
// --- C.init() ---
77+
// CHECK: define linkonce_odr hidden i1 @"$s17has_symbol_helper1CCACycfcTwS"()
78+
// CHECK: ret i1 and (i1 icmp ne (%T17has_symbol_helper1CC* (%T17has_symbol_helper1CC*)* @"$s17has_symbol_helper1CCACycfc", %T17has_symbol_helper1CC* (%T17has_symbol_helper1CC*)* null), i1 icmp ne (%T17has_symbol_helper1CC* (%swift.type*)* @"$s17has_symbol_helper1CCACycfC", %T17has_symbol_helper1CC* (%swift.type*)* null))
79+
80+
// --- C.method(with:) ---
81+
// CHECK: define linkonce_odr hidden i1 @"$s17has_symbol_helper1CC6method4withySi_tFTwS"()
82+
// CHECK: ret i1 and (i1 icmp ne (void (i64, %T17has_symbol_helper1CC*)* @"$s17has_symbol_helper1CC6method4withySi_tFTj", void (i64, %T17has_symbol_helper1CC*)* null), i1 icmp ne (%swift.method_descriptor* @"$s17has_symbol_helper1CC6method4withySi_tFTq", %swift.method_descriptor* null))
83+
84+
public func testStruct(_ s: S) {
85+
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper1SV6memberSivpTwS"()
5886
if #_hasSymbol(s.member) {}
59-
// CHECK: define linkonce_odr hidden swiftcc i1 @"$s17has_symbol_helper1SV6memberSivpTwS"()
60-
// CHECK: ret i1 and (i1 and (i1 and (i1 icmp ne (%swift.type_descriptor* @"$s17has_symbol_helper1SV6memberSivpMV", %swift.type_descriptor* null), i1 icmp ne (i64 (%swift.opaque*)* @"$s17has_symbol_helper1SV6memberSivg", i64 (%swift.opaque*)* null)), i1 icmp ne (void (i64, %swift.opaque*)* @"$s17has_symbol_helper1SV6memberSivs", void (i64, %swift.opaque*)* null)), i1 icmp ne ({ i8*, %TSi* } (i8*, %swift.opaque*)* @"$s17has_symbol_helper1SV6memberSivM", { i8*, %TSi* } (i8*, %swift.opaque*)* null))
6187

88+
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper1SV6method4withySi_tFTwS"()
6289
if #_hasSymbol(s.method(with:)) {}
63-
// CHECK: define linkonce_odr hidden swiftcc i1 @"$s17has_symbol_helper1SV6method4withySi_tFTwS"()
64-
// CHECK: ret i1 icmp ne (void (i64, %swift.opaque*)* @"$s17has_symbol_helper1SV6method4withySi_tF", void (i64, %swift.opaque*)* null)
6590
}
6691

67-
func testEnum(_ e: E) {
92+
// --- S.member ---
93+
// CHECK: define linkonce_odr hidden i1 @"$s17has_symbol_helper1SV6memberSivpTwS"()
94+
// CHECK: ret i1 and (i1 and (i1 and (i1 icmp ne (%swift.type_descriptor* @"$s17has_symbol_helper1SV6memberSivpMV", %swift.type_descriptor* null), i1 icmp ne (i64 (%swift.opaque*)* @"$s17has_symbol_helper1SV6memberSivg", i64 (%swift.opaque*)* null)), i1 icmp ne (void (i64, %swift.opaque*)* @"$s17has_symbol_helper1SV6memberSivs", void (i64, %swift.opaque*)* null)), i1 icmp ne ({ i8*, %TSi* } (i8*, %swift.opaque*)* @"$s17has_symbol_helper1SV6memberSivM", { i8*, %TSi* } (i8*, %swift.opaque*)* null))
95+
96+
// --- S.method(with:) ---
97+
// CHECK: define linkonce_odr hidden i1 @"$s17has_symbol_helper1SV6method4withySi_tFTwS"()
98+
// CHECK: ret i1 icmp ne (void (i64, %swift.opaque*)* @"$s17has_symbol_helper1SV6method4withySi_tF", void (i64, %swift.opaque*)* null)
99+
100+
public func testEnum(_ e: E) {
101+
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper1EO9basicCaseyA2CmFTwS"()
68102
if #_hasSymbol(E.basicCase) {}
69-
// CHECK: define linkonce_odr hidden swiftcc i1 @"$s17has_symbol_helper1EO9basicCaseyA2CmFTwS"()
70-
// CHECK: ret i1 icmp ne (i32* @"$s17has_symbol_helper1EO9basicCaseyA2CmFWC", i32* null)
71103

104+
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper1EO11payloadCaseyAcA1SVcACmFTwS"()
72105
if #_hasSymbol(E.payloadCase) {}
73-
// CHECK: define linkonce_odr hidden swiftcc i1 @"$s17has_symbol_helper1EO11payloadCaseyAcA1SVcACmFTwS"()
74-
// CHECK: ret i1 icmp ne (i32* @"$s17has_symbol_helper1EO11payloadCaseyAcA1SVcACmFWC", i32* null)
75106
}
76107

77-
func testMetatypes() {
108+
// --- E.basicCase ---
109+
// CHECK: define linkonce_odr hidden i1 @"$s17has_symbol_helper1EO9basicCaseyA2CmFTwS"()
110+
// CHECK: ret i1 icmp ne (i32* @"$s17has_symbol_helper1EO9basicCaseyA2CmFWC", i32* null)
111+
112+
// --- E.payloadCase(_:) ---
113+
// CHECK: define linkonce_odr hidden i1 @"$s17has_symbol_helper1EO11payloadCaseyAcA1SVcACmFTwS"()
114+
// CHECK: ret i1 icmp ne (i32* @"$s17has_symbol_helper1EO11payloadCaseyAcA1SVcACmFWC", i32* null)
115+
116+
public func testMetatypes() {
117+
// CHECK: %{{[0-9]+}} = call i1 @"$s17has_symbol_helper1SVTwS"()
78118
if #_hasSymbol(S.self) {}
79-
// CHECK: define linkonce_odr hidden swiftcc i1 @"$s17has_symbol_helper1SVTwS"()
80-
// CHECK: ret i1 and (i1 and (i1 icmp ne (%swift.type_descriptor* @"$s17has_symbol_helper1SVMn", %swift.type_descriptor* null), i1 icmp ne (%swift.type* @"$s17has_symbol_helper1SVN", %swift.type* null)), i1 icmp ne (%swift.metadata_response (i64)* @"$s17has_symbol_helper1SVMa", %swift.metadata_response (i64)* null))
81119
}
120+
121+
// --- S.self ---
122+
// CHECK: define linkonce_odr hidden i1 @"$s17has_symbol_helper1SVTwS"()
123+
// CHECK: ret i1 and (i1 and (i1 icmp ne (%swift.type_descriptor* @"$s17has_symbol_helper1SVMn", %swift.type_descriptor* null), i1 icmp ne (%swift.type* @"$s17has_symbol_helper1SVN", %swift.type* null)), i1 icmp ne (%swift.metadata_response (i64)* @"$s17has_symbol_helper1SVMa", %swift.metadata_response (i64)* null))

0 commit comments

Comments
 (0)