Skip to content

Commit c5a7eff

Browse files
authored
Merge pull request #62147 from tshortli/has-symbol-sil-instruction
2 parents 889c543 + 3da18b6 commit c5a7eff

39 files changed

+388
-304
lines changed

docs/SIL.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7882,3 +7882,16 @@ IRGen will replace the application by the constant representing Debug mode (0).
78827882
This happens we can build the standard library .dylib. The generate sil will
78837883
retain the function call but the generated .dylib will contain code with
78847884
assertions enabled.
7885+
7886+
Weak linking support
7887+
~~~~~~~~~~~~~~~~~~~~~~~
7888+
7889+
has_symbol
7890+
```````````````````````````
7891+
::
7892+
7893+
sil-instruction ::= 'has_symbol' sil-decl-ref
7894+
7895+
Returns true if each of the underlying symbol addresses associated with the
7896+
given declaration are non-null. This can be used to determine whether a
7897+
weakly-imported declaration is available at runtime.

include/swift/AST/Decl.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2793,11 +2793,6 @@ class ValueDecl : public Decl {
27932793
/// 'func foo(Int) -> () -> Self?'.
27942794
GenericParameterReferenceInfo findExistentialSelfReferences(
27952795
Type baseTy, bool treatNonResultCovariantSelfAsInvariant) const;
2796-
2797-
/// Returns a synthesized declaration for a query function that provides
2798-
/// the boolean value for a `if #_hasSymbol(...)` condition. The interface
2799-
/// type of the function is `() -> Builtin.Int1`.
2800-
FuncDecl *getHasSymbolQueryDecl() const;
28012796
};
28022797

28032798
/// This is a common base class for declarations which declare a type.

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6029,9 +6029,6 @@ ERROR(availability_macro_in_inlinable, none,
60296029
"availability macro cannot be used in " FRAGILE_FUNC_KIND "0",
60306030
(unsigned))
60316031

6032-
ERROR(has_symbol_condition_in_inlinable, none,
6033-
"'#_hasSymbol' cannot be used in " FRAGILE_FUNC_KIND "0", (unsigned))
6034-
60356032
#undef FRAGILE_FUNC_KIND
60366033

60376034
NOTE(resilience_decl_declared_here_public,

include/swift/AST/TypeCheckRequests.h

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3715,24 +3715,6 @@ class GetTypeWrapperInitializer
37153715
bool isCached() const { return true; }
37163716
};
37173717

3718-
/// Synthesizes and returns a `#_hasSymbol` query function for the given
3719-
/// `ValueDecl`. The function has an interface type of `() -> Builtin.Int1`.
3720-
class SynthesizeHasSymbolQueryRequest
3721-
: public SimpleRequest<SynthesizeHasSymbolQueryRequest,
3722-
FuncDecl *(const ValueDecl *),
3723-
RequestFlags::Cached> {
3724-
public:
3725-
using SimpleRequest::SimpleRequest;
3726-
3727-
private:
3728-
friend SimpleRequest;
3729-
3730-
FuncDecl *evaluate(Evaluator &evaluator, const ValueDecl *decl) const;
3731-
3732-
public:
3733-
bool isCached() const { return true; }
3734-
};
3735-
37363718
/// Lookup all macros with the given name that are visible from the given
37373719
/// module.
37383720
class MacroLookupRequest

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -437,9 +437,6 @@ SWIFT_REQUEST(TypeChecker, SynthesizeLocalVariableForTypeWrapperStorage,
437437
SWIFT_REQUEST(TypeChecker, GetTypeWrapperInitializer,
438438
ConstructorDecl *(NominalTypeDecl *),
439439
Cached, NoLocationInfo)
440-
SWIFT_REQUEST(TypeChecker, SynthesizeHasSymbolQueryRequest,
441-
FuncDecl *(ValueDecl *),
442-
Cached, NoLocationInfo)
443440
SWIFT_REQUEST(TypeChecker, MacroLookupRequest,
444441
ArrayRef<Macro *>(Identifier, ModuleDecl *),
445442
Cached, NoLocationInfo)

include/swift/SIL/SILBuilder.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2725,6 +2725,14 @@ class SILBuilder {
27252725
FunctionType));
27262726
}
27272727

2728+
//===--------------------------------------------------------------------===//
2729+
// Weak linking support
2730+
//===--------------------------------------------------------------------===//
2731+
HasSymbolInst *createHasSymbol(SILLocation Loc, ValueDecl *Decl) {
2732+
return insert(new (getModule()) HasSymbolInst(
2733+
getModule(), getSILDebugLocation(Loc), Decl));
2734+
}
2735+
27282736
//===--------------------------------------------------------------------===//
27292737
// Private Helper Methods
27302738
//===--------------------------------------------------------------------===//

include/swift/SIL/SILCloner.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3103,6 +3103,14 @@ ::visitExtractExecutorInst(ExtractExecutorInst *Inst) {
31033103
getOpValue(Inst->getExpectedExecutor())));
31043104
}
31053105

3106+
template <typename ImplClass>
3107+
void SILCloner<ImplClass>::visitHasSymbolInst(HasSymbolInst *Inst) {
3108+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
3109+
recordClonedInstruction(
3110+
Inst, getBuilder().createHasSymbol(getOpLocation(Inst->getLoc()),
3111+
Inst->getDecl()));
3112+
}
3113+
31063114
} // end namespace swift
31073115

31083116
#endif

include/swift/SIL/SILInstruction.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4086,6 +4086,32 @@ class StringLiteralInst final
40864086
MutableArrayRef<Operand> getAllOperands() { return {}; }
40874087
};
40884088

4089+
/// HasSymbolInst - Determines whether a weakly-imported declaration is
4090+
/// available at runtime. Produces true if each of the underlying symbol
4091+
/// addresses associated with a given declaration are non-null, false otherwise.
4092+
class HasSymbolInst final : public LiteralInst {
4093+
private:
4094+
friend SILBuilder;
4095+
4096+
ValueDecl *Decl;
4097+
4098+
public:
4099+
HasSymbolInst(SILModule &M, SILDebugLocation Loc, ValueDecl *Decl)
4100+
: LiteralInst(SILInstructionKind::HasSymbolInst, Loc,
4101+
SILType::getBuiltinIntegerType(1, Decl->getASTContext())),
4102+
Decl{Decl} {}
4103+
4104+
ValueDecl *getDecl() const { return Decl; }
4105+
void getReferencedFunctions(llvm::SmallVector<SILFunction *, 4> &fns) const;
4106+
4107+
ArrayRef<Operand> getAllOperands() const { return {}; }
4108+
MutableArrayRef<Operand> getAllOperands() { return {}; }
4109+
4110+
static bool classof(SILNodePointer node) {
4111+
return node->getKind() == SILNodeKind::HasSymbolInst;
4112+
}
4113+
};
4114+
40894115
//===----------------------------------------------------------------------===//
40904116
// Memory instructions.
40914117
//===----------------------------------------------------------------------===//

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; }

include/swift/SIL/SILNodes.def

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,9 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
347347
LiteralInst, None, DoesNotRelease)
348348
SINGLE_VALUE_INST(StringLiteralInst, string_literal,
349349
LiteralInst, None, DoesNotRelease)
350-
SINGLE_VALUE_INST_RANGE(LiteralInst, FunctionRefInst, StringLiteralInst)
350+
SINGLE_VALUE_INST(HasSymbolInst, has_symbol,
351+
LiteralInst, MayRead, DoesNotRelease)
352+
SINGLE_VALUE_INST_RANGE(LiteralInst, FunctionRefInst, HasSymbolInst)
351353

352354
// Dynamic Dispatch
353355
ABSTRACT_SINGLE_VALUE_INST(MethodInst, SingleValueInstruction)

include/swift/SIL/SILSymbolVisitor.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "swift/AST/ProtocolAssociations.h"
1818
#include "swift/AST/ProtocolConformance.h"
1919
#include "swift/SIL/SILDeclRef.h"
20+
#include "swift/SIL/SILModule.h"
2021

2122
namespace swift {
2223

@@ -126,6 +127,33 @@ class SILSymbolVisitor {
126127
virtual void addTypeMetadataAddress(CanType T) {}
127128
};
128129

130+
template <typename F>
131+
void enumerateFunctionsForHasSymbol(SILModule &M, ValueDecl *D, F Handler) {
132+
class SymbolVisitor : public SILSymbolVisitor {
133+
F Handler;
134+
135+
public:
136+
SymbolVisitor(F Handler) : Handler{Handler} {};
137+
138+
void addFunction(SILDeclRef declRef) override { Handler(declRef); }
139+
140+
virtual void addFunction(StringRef name, SILDeclRef declRef) override {
141+
// The kinds of functions which go through this callback (e.g.
142+
// differentiability witnesses) have custom manglings and are incompatible
143+
// with #_hasSymbol currently.
144+
//
145+
// Ideally, this callback will be removed entirely in favor of SILDeclRef
146+
// being able to represent all function variants with no special cases
147+
// required.
148+
}
149+
};
150+
151+
SILSymbolVisitorOptions opts;
152+
opts.VisitMembers = false;
153+
auto visitorCtx = SILSymbolVisitorContext(M.getSwiftModule(), opts);
154+
SymbolVisitor(Handler).visitDecl(D, visitorCtx);
155+
}
156+
129157
} // end namespace swift
130158

131159
#endif

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: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,6 +1395,8 @@ class IRGenSILFunction :
13951395
llvm_unreachable("test-only instruction in Lowered SIL?!");
13961396
}
13971397

1398+
void visitHasSymbolInst(HasSymbolInst *i);
1399+
13981400
#define LOADABLE_REF_STORAGE_HELPER(Name) \
13991401
void visitRefTo##Name##Inst(RefTo##Name##Inst *i); \
14001402
void visit##Name##ToRefInst(Name##ToRefInst *i); \
@@ -2615,6 +2617,15 @@ void IRGenSILFunction::visitDifferentiabilityWitnessFunctionInst(
26152617
i, FunctionPointer::createUnsigned(fnType, diffWitness, signature, true));
26162618
}
26172619

2620+
void IRGenSILFunction::visitHasSymbolInst(HasSymbolInst *i) {
2621+
auto fn = IGM.emitHasSymbolFunction(i->getDecl());
2622+
llvm::CallInst *call = Builder.CreateCall(fn->getFunctionType(), fn, {});
2623+
2624+
Explosion e;
2625+
e.add(call);
2626+
setLoweredValue(i, e);
2627+
}
2628+
26182629
FunctionPointer::Kind irgen::classifyFunctionPointerKind(SILFunction *fn) {
26192630
using SpecialKind = FunctionPointer::SpecialKind;
26202631

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ SHOULD_NEVER_VISIT_INST(PreviousDynamicFunctionRef)
109109
SHOULD_NEVER_VISIT_INST(GlobalAddr)
110110
SHOULD_NEVER_VISIT_INST(GlobalValue)
111111
SHOULD_NEVER_VISIT_INST(BaseAddrForOffset)
112+
SHOULD_NEVER_VISIT_INST(HasSymbol)
112113
SHOULD_NEVER_VISIT_INST(IntegerLiteral)
113114
SHOULD_NEVER_VISIT_INST(Metatype)
114115
SHOULD_NEVER_VISIT_INST(ObjCProtocol)

lib/SIL/IR/SILInstructions.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "swift/SIL/SILCloner.h"
2727
#include "swift/SIL/SILInstruction.h"
2828
#include "swift/SIL/SILModule.h"
29+
#include "swift/SIL/SILSymbolVisitor.h"
2930
#include "swift/SIL/SILVisitor.h"
3031
#include "llvm/ADT/APInt.h"
3132
#include "llvm/ADT/SmallString.h"
@@ -2993,3 +2994,13 @@ SILPhiArgument *SwitchEnumInst::createOptionalSomeResult() {
29932994
auto someBB = getCaseDestination(someDecl);
29942995
return createResult(someBB, getOperand()->getType().unwrapOptionalType());
29952996
}
2997+
2998+
void HasSymbolInst::getReferencedFunctions(
2999+
llvm::SmallVector<SILFunction *, 4> &fns) const {
3000+
auto &M = getModule();
3001+
enumerateFunctionsForHasSymbol(M, getDecl(), [&M, &fns](SILDeclRef declRef) {
3002+
SILFunction *fn = M.lookUpFunction(declRef);
3003+
assert(fn);
3004+
fns.push_back(fn);
3005+
});
3006+
}

lib/SIL/IR/SILPrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2860,6 +2860,11 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
28602860
*this << dwfi->getType();
28612861
}
28622862
}
2863+
2864+
void visitHasSymbolInst(HasSymbolInst *hsi) {
2865+
*this << "#";
2866+
printValueDecl(hsi->getDecl(), PrintState.OS);
2867+
}
28632868
};
28642869

28652870
} // namespace swift

0 commit comments

Comments
 (0)