Skip to content

Commit 649f09f

Browse files
authored
Merge pull request #61563 from tshortli/silgen-has-symbol
SILGen: Implement `if #_hasSymbol(...)` conditions
2 parents 6f77e8b + 8a9eb40 commit 649f09f

19 files changed

+391
-7
lines changed

docs/ABI/Mangling.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,11 @@ Globals
157157
global ::= protocol-conformance 'MA' // metadata for remote mirrors: associated type descriptor
158158
global ::= nominal-type 'MC' // metadata for remote mirrors: superclass descriptor
159159

160-
// TODO check this::
161160
global ::= mangled-name 'TA' // partial application forwarder
162161
global ::= mangled-name 'Ta' // ObjC partial application forwarder
163162
global ::= mangled-name 'TQ' index // Async await continuation partial function
164163
global ::= mangled-name 'TY' index // Async suspend continuation partial function
164+
global ::= mangled-name 'TwS' // #_hasSymbol query function
165165

166166
global ::= type 'w' VALUE-WITNESS-KIND // value witness
167167

include/swift/AST/ASTMangler.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ class ASTMangler : public Mangler {
157157
AccessibleFunctionRecord,
158158
BackDeploymentThunk,
159159
BackDeploymentFallback,
160+
HasSymbolQuery,
160161
};
161162

162163
/// lldb overrides the defaulted argument to 'true'.
@@ -357,6 +358,8 @@ class ASTMangler : public Mangler {
357358

358359
std::string mangleGenericSignature(const GenericSignature sig);
359360

361+
std::string mangleHasSymbolQuery(const ValueDecl *decl);
362+
360363
enum SpecialContext {
361364
ObjCContext,
362365
ClangImporterContext,

include/swift/AST/Decl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2733,6 +2733,11 @@ class ValueDecl : public Decl {
27332733
/// 'func foo(Int) -> () -> Self?'.
27342734
GenericParameterReferenceInfo findExistentialSelfReferences(
27352735
Type baseTy, bool treatNonResultCovariantSelfAsInvariant) const;
2736+
2737+
/// Returns a synthesized declaration for a query function that provides
2738+
/// the boolean value for a `if #_hasSymbol(...)` condition. The interface
2739+
/// type of the function is `() -> Builtin.Int1`.
2740+
FuncDecl *getHasSymbolQueryDecl() const;
27362741
};
27372742

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

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5953,6 +5953,9 @@ ERROR(availability_macro_in_inlinable, none,
59535953
"availability macro cannot be used in " FRAGILE_FUNC_KIND "0",
59545954
(unsigned))
59555955

5956+
ERROR(has_symbol_condition_in_inlinable, none,
5957+
"'#_hasSymbol' cannot be used in " FRAGILE_FUNC_KIND "0", (unsigned))
5958+
59565959
#undef FRAGILE_FUNC_KIND
59575960

59585961
NOTE(resilience_decl_declared_here_public,
@@ -6619,7 +6622,7 @@ WARNING(has_symbol_decl_must_be_weak,none,
66196622
(DescriptiveDeclKind, DeclName))
66206623
ERROR(has_symbol_invalid_expr,none,
66216624
"'#_hasSymbol' condition must refer to a declaration", ())
6622-
ERROR(has_symbol_unsupported,none,
6625+
ERROR(has_symbol_unsupported_on_target,none,
66236626
"'#_hasSymbol' is unsupported on target '%0'", (StringRef))
66246627

66256628
//------------------------------------------------------------------------------

include/swift/AST/TypeCheckRequests.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3736,6 +3736,24 @@ class GetTypeWrapperInitializer
37363736
bool isCached() const { return true; }
37373737
};
37383738

3739+
/// Synthesizes and returns a `#_hasSymbol` query function for the given
3740+
/// `ValueDecl`. The function has an interface type of `() -> Builtin.Int1`.
3741+
class SynthesizeHasSymbolQueryRequest
3742+
: public SimpleRequest<SynthesizeHasSymbolQueryRequest,
3743+
FuncDecl *(const ValueDecl *),
3744+
RequestFlags::Cached> {
3745+
public:
3746+
using SimpleRequest::SimpleRequest;
3747+
3748+
private:
3749+
friend SimpleRequest;
3750+
3751+
FuncDecl *evaluate(Evaluator &evaluator, const ValueDecl *decl) const;
3752+
3753+
public:
3754+
bool isCached() const { return true; }
3755+
};
3756+
37393757
void simple_display(llvm::raw_ostream &out, ASTNode node);
37403758
void simple_display(llvm::raw_ostream &out, Type value);
37413759
void simple_display(llvm::raw_ostream &out, const TypeRepr *TyR);

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,3 +440,6 @@ SWIFT_REQUEST(TypeChecker, SynthesizeLocalVariableForTypeWrapperStorage,
440440
SWIFT_REQUEST(TypeChecker, GetTypeWrapperInitializer,
441441
ConstructorDecl *(NominalTypeDecl *),
442442
Cached, NoLocationInfo)
443+
SWIFT_REQUEST(TypeChecker, SynthesizeHasSymbolQueryRequest,
444+
FuncDecl *(ValueDecl *),
445+
Cached, NoLocationInfo)

include/swift/Demangling/DemangleNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,9 @@ NODE(UniqueExtendedExistentialTypeShapeSymbolicReference)
344344
NODE(NonUniqueExtendedExistentialTypeShapeSymbolicReference)
345345
NODE(SymbolicExtendedExistentialType)
346346

347+
// Added in Swift 5.8
347348
NODE(MetatypeParamsRemoved)
349+
NODE(HasSymbolQuery)
348350

349351
#undef CONTEXT_NODE
350352
#undef NODE

lib/AST/ASTMangler.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,28 @@ std::string ASTMangler::mangleGenericSignature(const GenericSignature sig) {
861861
return finalize();
862862
}
863863

864+
std::string ASTMangler::mangleHasSymbolQuery(const ValueDecl *Decl) {
865+
beginMangling();
866+
867+
if (auto Ctor = dyn_cast<ConstructorDecl>(Decl)) {
868+
appendConstructorEntity(Ctor, /*isAllocating=*/false);
869+
} else if (auto Dtor = dyn_cast<DestructorDecl>(Decl)) {
870+
appendDestructorEntity(Dtor, /*isDeallocating=*/false);
871+
} else if (auto GTD = dyn_cast<GenericTypeDecl>(Decl)) {
872+
appendAnyGenericType(GTD);
873+
} else if (isa<AssociatedTypeDecl>(Decl)) {
874+
appendContextOf(Decl);
875+
appendDeclName(Decl);
876+
appendOperator("Qa");
877+
} else {
878+
appendEntity(Decl);
879+
}
880+
881+
appendSymbolKind(ASTMangler::SymbolKind::HasSymbolQuery);
882+
883+
return finalize();
884+
}
885+
864886
void ASTMangler::appendSymbolKind(SymbolKind SKind) {
865887
switch (SKind) {
866888
case SymbolKind::Default: return;
@@ -872,6 +894,7 @@ void ASTMangler::appendSymbolKind(SymbolKind SKind) {
872894
case SymbolKind::AccessibleFunctionRecord: return appendOperator("HF");
873895
case SymbolKind::BackDeploymentThunk: return appendOperator("Twb");
874896
case SymbolKind::BackDeploymentFallback: return appendOperator("TwB");
897+
case SymbolKind::HasSymbolQuery: return appendOperator("TwS");
875898
}
876899
}
877900

lib/Demangling/Demangler.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ bool swift::Demangle::isFunctionAttr(Node::Kind kind) {
145145
case Node::Kind::AccessibleFunctionRecord:
146146
case Node::Kind::BackDeploymentThunk:
147147
case Node::Kind::BackDeploymentFallback:
148+
case Node::Kind::HasSymbolQuery:
148149
return true;
149150
default:
150151
return false;
@@ -2675,6 +2676,7 @@ NodePointer Demangler::demangleThunkOrSpecialization() {
26752676
switch (nextChar()) {
26762677
case 'b': return createNode(Node::Kind::BackDeploymentThunk);
26772678
case 'B': return createNode(Node::Kind::BackDeploymentFallback);
2679+
case 'S': return createNode(Node::Kind::HasSymbolQuery);
26782680
default:
26792681
return nullptr;
26802682
}

lib/Demangling/NodePrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,7 @@ class NodePrinter {
604604
case Node::Kind::UniqueExtendedExistentialTypeShapeSymbolicReference:
605605
case Node::Kind::NonUniqueExtendedExistentialTypeShapeSymbolicReference:
606606
case Node::Kind::SymbolicExtendedExistentialType:
607+
case Node::Kind::HasSymbolQuery:
607608
return false;
608609
}
609610
printer_unreachable("bad node kind");
@@ -3046,6 +3047,9 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
30463047

30473048
return nullptr;
30483049
}
3050+
case Node::Kind::HasSymbolQuery:
3051+
Printer << "#_hasSymbol query for ";
3052+
return nullptr;
30493053
}
30503054

30513055
printer_unreachable("bad node kind!");

lib/Demangling/OldRemangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2854,3 +2854,8 @@ ManglingError Remangler::mangleBackDeploymentFallback(Node *node,
28542854
Buffer << "TwB";
28552855
return ManglingError::Success;
28562856
}
2857+
2858+
ManglingError Remangler::mangleHasSymbolQuery(Node *node, unsigned depth) {
2859+
Buffer << "TwS";
2860+
return ManglingError::Success;
2861+
}

lib/Demangling/Remangler.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,6 +1669,7 @@ ManglingError Remangler::mangleGlobal(Node *node, unsigned depth) {
16691669
case Node::Kind::AccessibleFunctionRecord:
16701670
case Node::Kind::BackDeploymentThunk:
16711671
case Node::Kind::BackDeploymentFallback:
1672+
case Node::Kind::HasSymbolQuery:
16721673
mangleInReverseOrder = true;
16731674
break;
16741675
default:
@@ -3503,6 +3504,11 @@ ManglingError Remangler::mangleExtendedExistentialTypeShape(Node *node,
35033504
return ManglingError::Success;
35043505
}
35053506

3507+
ManglingError Remangler::mangleHasSymbolQuery(Node *node, unsigned depth) {
3508+
Buffer << "TwS";
3509+
return ManglingError::Success;
3510+
}
3511+
35063512
ManglingError Remangler::mangleSymbolicExtendedExistentialType(Node *node,
35073513
unsigned int depth) {
35083514
RETURN_IF_ERROR(mangle(node->getChild(0), depth+1));

lib/SILGen/SILGenDecl.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1522,7 +1522,22 @@ void SILGenFunction::emitStmtCondition(StmtCondition Cond, JumpDest FalseDest,
15221522
}
15231523

15241524
case StmtConditionElement::CK_HasSymbol: {
1525-
llvm::report_fatal_error("Can't SILGen #_hasSymbol yet!");
1525+
auto info = elt.getHasSymbolInfo();
1526+
assert(!info->isInvalid());
1527+
auto expr = info->getSymbolExpr();
1528+
auto declRef = info->getReferencedDecl();
1529+
assert(declRef);
1530+
1531+
auto queryFunc = declRef.getDecl()->getHasSymbolQueryDecl();
1532+
SILFunction *silFn = SGM.getFunction(
1533+
SILDeclRef(queryFunc, SILDeclRef::Kind::Func), NotForDefinition);
1534+
SILValue fnRef = B.createFunctionRefFor(loc, silFn);
1535+
booleanTestValue = B.createApply(loc, fnRef, {}, {});
1536+
booleanTestValue = emitUnwrapIntegerResult(expr, booleanTestValue);
1537+
booleanTestLoc = expr;
1538+
1539+
// FIXME: Add decl to list of decls that need a has symbol query
1540+
// function to be emitted during IRGen.
15261541
break;
15271542
}
15281543
}

lib/Sema/CodeSynthesis.cpp

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@
1616

1717
#include "CodeSynthesis.h"
1818

19-
#include "TypeChecker.h"
2019
#include "TypeCheckDecl.h"
20+
#include "TypeCheckDistributed.h"
2121
#include "TypeCheckObjC.h"
2222
#include "TypeCheckType.h"
23-
#include "TypeCheckDistributed.h"
23+
#include "TypeChecker.h"
24+
#include "swift/AST/ASTMangler.h"
2425
#include "swift/AST/ASTPrinter.h"
2526
#include "swift/AST/Availability.h"
27+
#include "swift/AST/DistributedDecl.h"
2628
#include "swift/AST/Expr.h"
2729
#include "swift/AST/GenericEnvironment.h"
2830
#include "swift/AST/Initializer.h"
@@ -31,7 +33,6 @@
3133
#include "swift/AST/ProtocolConformance.h"
3234
#include "swift/AST/SourceFile.h"
3335
#include "swift/AST/TypeCheckRequests.h"
34-
#include "swift/AST/DistributedDecl.h"
3536
#include "swift/Basic/Defer.h"
3637
#include "swift/ClangImporter/ClangModule.h"
3738
#include "swift/Sema/ConstraintSystem.h"
@@ -1608,3 +1609,32 @@ ConstructorDecl *SynthesizeTypeWrappedTypeMemberwiseInitializer::evaluate(
16081609
ctor->setBody(body, AbstractFunctionDecl::BodyKind::Parsed);
16091610
return ctor;
16101611
}
1612+
1613+
FuncDecl *ValueDecl::getHasSymbolQueryDecl() const {
1614+
return evaluateOrDefault(getASTContext().evaluator,
1615+
SynthesizeHasSymbolQueryRequest{this}, nullptr);
1616+
}
1617+
1618+
FuncDecl *
1619+
SynthesizeHasSymbolQueryRequest::evaluate(Evaluator &evaluator,
1620+
const ValueDecl *decl) const {
1621+
auto &ctx = decl->getASTContext();
1622+
auto dc = decl->getModuleContext();
1623+
1624+
Mangle::ASTMangler mangler;
1625+
auto mangledName = ctx.AllocateCopy(mangler.mangleHasSymbolQuery(decl));
1626+
1627+
ParameterList *params = ParameterList::createEmpty(ctx);
1628+
1629+
DeclName funcName =
1630+
DeclName(ctx, DeclBaseName(ctx.getIdentifier(mangledName)),
1631+
/*argumentNames=*/ArrayRef<Identifier>());
1632+
1633+
auto i1 = BuiltinIntegerType::get(1, ctx);
1634+
FuncDecl *func = FuncDecl::createImplicit(
1635+
ctx, swift::StaticSpellingKind::None, funcName, SourceLoc(),
1636+
/*async=*/false, /*throws=*/false, nullptr, params, i1, dc);
1637+
1638+
func->getAttrs().add(new (ctx) SILGenNameAttr(mangledName, IsImplicit));
1639+
return func;
1640+
}

lib/Sema/MiscDiagnostics.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4410,11 +4410,29 @@ static bool diagnoseHasSymbolCondition(PoundHasSymbolInfo *info,
44104410
if (!ctx.LangOpts.Target.isOSDarwin()) {
44114411
// SILGen for #_hasSymbol is currently implemented assuming the target OS
44124412
// is a Darwin platform.
4413-
ctx.Diags.diagnose(info->getStartLoc(), diag::has_symbol_unsupported,
4413+
ctx.Diags.diagnose(info->getStartLoc(),
4414+
diag::has_symbol_unsupported_on_target,
44144415
ctx.LangOpts.Target.str());
44154416
return true;
44164417
}
44174418

4419+
if (DC->getAsDecl()) {
4420+
auto fragileKind = DC->getFragileFunctionKind();
4421+
if (fragileKind.kind != FragileFunctionKind::None) {
4422+
// #_hasSymbol cannot be used in inlinable code because of limitations of
4423+
// the current implementation strategy. It relies on recording the
4424+
// referenced ValueDecl, mangling a helper function name using that
4425+
// ValueDecl, and then passing the responsibility of generating the
4426+
// definition for that helper function to IRGen. In order to lift this
4427+
// restriction, we will need teach SIL to encode the ValueDecl, or take
4428+
// another approach entirely.
4429+
ctx.Diags.diagnose(info->getStartLoc(),
4430+
diag::has_symbol_condition_in_inlinable,
4431+
fragileKind.getSelector());
4432+
return true;
4433+
}
4434+
}
4435+
44184436
auto decl = info->getReferencedDecl().getDecl();
44194437
if (!decl) {
44204438
// Diagnose because we weren't able to interpret the expression as one

test/Demangle/Inputs/manglings.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,3 +439,5 @@ $sxIeghHr_xs5Error_pIegHrzo_s8SendableRzs5NeverORs_r0_lTRTQ0_ ---> {T:} (1) awai
439439
$sxIeghHr_xs5Error_pIegHrzo_s8SendableRzs5NeverORs_r0_lTRTY0_ ---> {T:} (1) suspend resume partial function for reabstraction thunk helper <A, B where A: Swift.Sendable, B == Swift.Never> from @escaping @callee_guaranteed @Sendable @async () -> (@out A) to @escaping @callee_guaranteed @async () -> (@out A, @error @owned Swift.Error)
440440
$sxIeghHr_xs5Error_pIegHrzo_s8SendableRzs5NeverORs_r0_lTRTY_ ---> {T:} (0) suspend resume partial function for reabstraction thunk helper <A, B where A: Swift.Sendable, B == Swift.Never> from @escaping @callee_guaranteed @Sendable @async () -> (@out A) to @escaping @callee_guaranteed @async () -> (@out A, @error @owned Swift.Error)
441441
$sxIeghHr_xs5Error_pIegHrzo_s8SendableRzs5NeverORs_r0_lTRTQ12_ ---> {T:} (13) await resume partial function for reabstraction thunk helper <A, B where A: Swift.Sendable, B == Swift.Never> from @escaping @callee_guaranteed @Sendable @async () -> (@out A) to @escaping @callee_guaranteed @async () -> (@out A, @error @owned Swift.Error)
442+
$s7Library3fooyyFTwS ---> #_hasSymbol query for Library.foo() -> ()
443+
$s7Library5KlassCTwS ---> #_hasSymbol query for Library.Klass
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
2+
public let global: Int = 0
3+
4+
public func function(with argument: Int) {}
5+
public func genericFunc<T: P>(_ t: T) {}
6+
@_cdecl("cdecl_func") public func cdeclFunc() {}
7+
@_silgen_name("forward_declared_func") public func forwardDeclaredFunc()
8+
9+
public protocol P {
10+
func requirement()
11+
}
12+
13+
public struct S {
14+
public static var staticMember: Int = 0
15+
public static func staticFunc() {}
16+
17+
public var member: Int
18+
19+
public init(member: Int) {
20+
self.member = member
21+
}
22+
public func method(with argument: Int) {}
23+
public func genericFunc<T: P>(_ t: T) {}
24+
}
25+
26+
extension S: P {
27+
public func requirement() {}
28+
}
29+
30+
public struct GenericS<T: P> {
31+
public var member: T
32+
33+
public init(member: T) {
34+
self.member = member
35+
}
36+
public func method(with argument: T) {}
37+
}
38+
39+
public class C {
40+
public static var staticMember: Int = 0
41+
public class func classFunc() {}
42+
43+
public var member: Int
44+
45+
public init(member: Int) {
46+
self.member = member
47+
}
48+
public func method(with argument: Int) {}
49+
}
50+
51+
public enum E {
52+
case basicCase
53+
case payloadCase(_: S)
54+
55+
public func method() {}
56+
}

0 commit comments

Comments
 (0)