Skip to content

Commit c51e2d1

Browse files
committed
IRGen: Add #_hasSymbol support for clang function decls and ObjC classes.
Resolves rdar://103408651.
1 parent 0a487a5 commit c51e2d1

File tree

10 files changed

+93
-11
lines changed

10 files changed

+93
-11
lines changed

include/swift/SIL/SILSymbolVisitor.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,14 @@ class SILSymbolVisitor {
128128

129129
template <typename F>
130130
void enumerateFunctionsForHasSymbol(SILModule &M, ValueDecl *D, F Handler) {
131+
// Handle clang decls separately.
132+
if (auto *clangDecl = D->getClangDecl()) {
133+
if (isa<clang::FunctionDecl>(clangDecl))
134+
Handler(SILDeclRef(D).asForeign());
135+
136+
return;
137+
}
138+
131139
class SymbolVisitor : public SILSymbolVisitor {
132140
F Handler;
133141

lib/IRGen/GenHasSymbol.cpp

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "swift/SIL/SILFunctionBuilder.h"
2222
#include "swift/SIL/SILModule.h"
2323
#include "swift/SIL/SILSymbolVisitor.h"
24+
#include "clang/AST/DeclObjC.h"
25+
#include "clang/AST/GlobalDecl.h"
2426

2527
#include "GenDecl.h"
2628
#include "IRGenFunction.h"
@@ -68,9 +70,8 @@ class HasSymbolIRGenVisitor : public IRSymbolVisitor {
6870
SILFunction *silFn = IGM.getSILModule().lookUpFunction(name);
6971
// Definitions for each SIL function should have been emitted by SILGen.
7072
assert(silFn && "missing SIL function?");
71-
if (silFn) {
73+
if (silFn)
7274
addFunction(silFn);
73-
}
7475
}
7576

7677
public:
@@ -111,6 +112,39 @@ class HasSymbolIRGenVisitor : public IRSymbolVisitor {
111112
}
112113
};
113114

115+
static llvm::Constant *
116+
getAddrOfLLVMVariableForClangDecl(IRGenModule &IGM, ValueDecl *decl,
117+
const clang::Decl *clangDecl) {
118+
if (isa<clang::FunctionDecl>(clangDecl)) {
119+
SILFunction *silFn =
120+
IGM.getSILModule().lookUpFunction(SILDeclRef(decl).asForeign());
121+
assert(silFn && "missing SIL function?");
122+
return silFn ? IGM.getAddrOfSILFunction(silFn, NotForDefinition) : nullptr;
123+
}
124+
125+
if (auto var = dyn_cast<clang::ObjCInterfaceDecl>(clangDecl))
126+
return IGM.getAddrOfObjCClass(cast<ClassDecl>(decl), NotForDefinition);
127+
128+
llvm::report_fatal_error("Unexpected clang decl kind");
129+
}
130+
131+
static void
132+
getSymbolAddrsForDecl(IRGenModule &IGM, ValueDecl *decl,
133+
llvm::SmallVector<llvm::Constant *, 4> &addrs) {
134+
if (auto *clangDecl = decl->getClangDecl()) {
135+
if (auto *addr = getAddrOfLLVMVariableForClangDecl(IGM, decl, clangDecl))
136+
addrs.push_back(addr);
137+
return;
138+
}
139+
140+
SILSymbolVisitorOptions opts;
141+
opts.VisitMembers = false;
142+
auto silCtx = SILSymbolVisitorContext(IGM.getSwiftModule(), opts);
143+
auto linkInfo = UniversalLinkageInfo(IGM);
144+
auto symbolVisitorCtx = IRSymbolVisitorContext(linkInfo, silCtx);
145+
HasSymbolIRGenVisitor(IGM, addrs).visit(decl, symbolVisitorCtx);
146+
}
147+
114148
llvm::Function *IRGenModule::emitHasSymbolFunction(ValueDecl *decl) {
115149

116150
PrettyStackTraceDecl trace("emitting #_hasSymbol query for", decl);
@@ -119,14 +153,9 @@ llvm::Function *IRGenModule::emitHasSymbolFunction(ValueDecl *decl) {
119153
auto func = cast<llvm::Function>(getOrCreateHelperFunction(
120154
mangler.mangleHasSymbolQuery(decl), Int1Ty, {},
121155
[decl, this](IRGenFunction &IGF) {
122-
SILSymbolVisitorOptions opts;
123-
opts.VisitMembers = false;
124-
auto silCtx = SILSymbolVisitorContext(getSwiftModule(), opts);
125-
auto linkInfo = UniversalLinkageInfo(*this);
126-
auto symbolVisitorCtx = IRSymbolVisitorContext(linkInfo, silCtx);
127156
auto &Builder = IGF.Builder;
128157
llvm::SmallVector<llvm::Constant *, 4> addrs;
129-
HasSymbolIRGenVisitor(*this, addrs).visit(decl, symbolVisitorCtx);
158+
getSymbolAddrsForDecl(*this, decl, addrs);
130159

131160
llvm::Value *ret = nullptr;
132161
for (llvm::Constant *addr : addrs) {
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// NOTE: This header is used on platforms that do not support Obj-C.
2+
3+
extern void clangFunc(int x);
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
@import Foundation;
2+
3+
@interface ObjCClass : NSObject
4+
@end
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module has_symbol_helper_clang {
2+
header "has_symbol_helper_clang.h"
3+
export *
4+
}
5+
6+
module has_symbol_helper_objc {
7+
header "has_symbol_helper_objc.h"
8+
export *
9+
}

test/IRGen/has_symbol.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/has_symbol_helper.swiftmodule -parse-as-library %S/Inputs/has_symbol_helper.swift -enable-library-evolution -disable-availability-checking
3-
// RUN: %target-swift-frontend -emit-irgen %s -I %t -module-name test | %FileCheck %s
2+
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/has_symbol_helper.swiftmodule -parse-as-library %S/Inputs/has_symbol/has_symbol_helper.swift -enable-library-evolution -disable-availability-checking
3+
// RUN: %target-swift-frontend -emit-irgen %s -I %t -I %S/Inputs/has_symbol -module-name test | %FileCheck %s
44

55
// UNSUPPORTED: OS=windows-msvc
66

test/IRGen/has_symbol_async.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/has_symbol_helper.swiftmodule -parse-as-library %S/Inputs/has_symbol_helper.swift -enable-library-evolution -disable-availability-checking -DCONCURRENCY
2+
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/has_symbol_helper.swiftmodule -parse-as-library %S/Inputs/has_symbol/has_symbol_helper.swift -enable-library-evolution -disable-availability-checking -DCONCURRENCY
33
// RUN: %target-swift-frontend -emit-irgen %s -I %t -module-name test | %FileCheck %s
44

55
// REQUIRES: concurrency

test/IRGen/has_symbol_clang.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-irgen %s -I %t -I %S/Inputs/has_symbol -module-name test | %FileCheck %s
3+
4+
// UNSUPPORTED: OS=windows-msvc
5+
6+
@_weakLinked import has_symbol_helper_clang
7+
8+
public func testClangDecls() {
9+
// CHECK: %{{[0-9]+}} = call i1 @"$sSo9clangFuncyys5Int32VFTwS"()
10+
if #_hasSymbol(clangFunc(_:)) {}
11+
}
12+
13+
// --- clangFunc(_:) ---
14+
// CHECK: define linkonce_odr hidden i1 @"$sSo9clangFuncyys5Int32VFTwS"() #1 {
15+
// CHECK: ret i1 icmp ne (void (i32)* @clangFunc, void (i32)* null)

test/IRGen/has_symbol_objc.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-irgen %s -I %t -I %S/Inputs/has_symbol -module-name test | %FileCheck %s
3+
4+
// REQUIRES: objc_interop
5+
6+
@_weakLinked import has_symbol_helper_objc
7+
8+
public func testClassTypes() {
9+
// CHECK: %{{[0-9]+}} = call i1 @"$sSo9ObjCClassCTwS"()
10+
if #_hasSymbol(ObjCClass.self) {}
11+
}
12+
13+
// CHECK: define linkonce_odr hidden i1 @"$sSo9ObjCClassCTwS"()
14+
// CHECK: ret i1 icmp ne (%objc_class* @"OBJC_CLASS_$_ObjCClass", %objc_class* null)

0 commit comments

Comments
 (0)