Skip to content

Commit 0fd6ef3

Browse files
committed
Add support for lifetime dependence mangling
1 parent 934865b commit 0fd6ef3

20 files changed

+264
-59
lines changed

docs/ABI/Mangling.rst

+6-1
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,12 @@ Types
664664
differentiable ::= 'Yjr' // @differentiable(reverse) on function type
665665
differentiable ::= 'Yjd' // @differentiable on function type
666666
differentiable ::= 'Yjl' // @differentiable(_linear) on function type
667-
667+
#if SWIFT_RUNTIME_VERSION >= 5.TBD
668+
lifetime-dependence ::= 'Yli' // inherit lifetime dependence on param
669+
lifetime-dependence ::= 'Yls' // scoped lifetime dependence on param
670+
self-lifetime-dependence ::= 'YLi' // inherit lifetime dependence on self
671+
self-lifetime-dependence ::= 'YLs' // scoped lifetime dependence on self
672+
#endif
668673
type-list ::= list-type '_' list-type* // list of types
669674
type-list ::= empty-list
670675

include/swift/AST/ASTMangler.h

+12-1
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,7 @@ class ASTMangler : public Mangler {
481481
FunctionManglingKind functionMangling);
482482

483483
void appendFunctionInputType(ArrayRef<AnyFunctionType::Param> params,
484+
LifetimeDependenceInfo lifetimeDependenceInfo,
484485
GenericSignature sig,
485486
const ValueDecl *forDecl = nullptr);
486487
void appendFunctionResultType(Type resultType,
@@ -489,10 +490,17 @@ class ASTMangler : public Mangler {
489490

490491
void appendTypeList(Type listTy, GenericSignature sig,
491492
const ValueDecl *forDecl = nullptr);
493+
492494
void appendTypeListElement(Identifier name, Type elementType,
493-
ParameterTypeFlags flags,
494495
GenericSignature sig,
495496
const ValueDecl *forDecl = nullptr);
497+
void appendParameterTypeListElement(
498+
Identifier name, Type elementType, ParameterTypeFlags flags,
499+
std::optional<LifetimeDependenceKind> lifetimeDependenceKind,
500+
GenericSignature sig, const ValueDecl *forDecl = nullptr);
501+
void appendTupleTypeListElement(Identifier name, Type elementType,
502+
GenericSignature sig,
503+
const ValueDecl *forDecl = nullptr);
496504

497505
/// Append a generic signature to the mangling.
498506
///
@@ -599,6 +607,9 @@ class ASTMangler : public Mangler {
599607

600608
void appendConstrainedExistential(Type base, GenericSignature sig,
601609
const ValueDecl *forDecl);
610+
611+
void appendLifetimeDependenceKind(LifetimeDependenceKind kind,
612+
bool isSelfDependence);
602613
};
603614

604615
} // end namespace Mangle

include/swift/AST/LifetimeDependence.h

+3
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,9 @@ class LifetimeDependenceInfo {
180180
void Profile(llvm::FoldingSetNodeID &ID) const;
181181
void getConcatenatedData(SmallVectorImpl<bool> &concatenatedData) const;
182182

183+
std::optional<LifetimeDependenceKind>
184+
getLifetimeDependenceOnParam(unsigned paramIndex);
185+
183186
static llvm::Optional<LifetimeDependenceInfo>
184187
get(AbstractFunctionDecl *decl, Type resultType, bool allowIndex = false);
185188

include/swift/Demangling/Demangle.h

+2
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ enum class MangledDifferentiabilityKind : char {
135135
Linear = 'l',
136136
};
137137

138+
enum class MangledLifetimeDependenceKind : char { Inherit = 'i', Scope = 's' };
139+
138140
/// The pass that caused the specialization to occur. We use this to make sure
139141
/// that two passes that generate similar changes do not yield the same
140142
/// mangling. This currently cannot happen, so this is just a safety measure

include/swift/Demangling/DemangleNodes.def

+2
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,8 @@ NODE(AsyncRemoved)
382382

383383
// Added in Swift 5.TBD
384384
NODE(ObjectiveCProtocolSymbolicReference)
385+
NODE(ParamLifetimeDependence)
386+
NODE(SelfLifetimeDependence)
385387

386388
NODE(OutlinedInitializeWithCopyNoValueWitness)
387389
NODE(OutlinedAssignWithTakeNoValueWitness)

include/swift/Demangling/Demangler.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,9 @@ class Demangler : public NodeFactory {
632632

633633
bool demangleBoundGenerics(Vector<NodePointer> &TypeListList,
634634
NodePointer &RetroactiveConformances);
635-
635+
636+
NodePointer demangleLifetimeDependenceKind(bool isSelfDependence);
637+
636638
void dump();
637639

638640
public:

lib/AST/ASTMangler.cpp

+76-17
Original file line numberDiff line numberDiff line change
@@ -2809,7 +2809,8 @@ void ASTMangler::appendFunctionSignature(AnyFunctionType *fn,
28092809
const ValueDecl *forDecl,
28102810
FunctionManglingKind functionMangling) {
28112811
appendFunctionResultType(fn->getResult(), sig, forDecl);
2812-
appendFunctionInputType(fn->getParams(), sig, forDecl);
2812+
appendFunctionInputType(fn->getParams(), fn->getLifetimeDependenceInfo(), sig,
2813+
forDecl);
28132814
if (fn->isAsync())
28142815
appendOperator("Ya");
28152816
if (fn->isSendable())
@@ -2843,6 +2844,18 @@ void ASTMangler::appendFunctionSignature(AnyFunctionType *fn,
28432844
appendType(globalActor, sig);
28442845
appendOperator("Yc");
28452846
}
2847+
2848+
if (auto *afd = dyn_cast_or_null<AbstractFunctionDecl>(forDecl)) {
2849+
if (afd->hasImplicitSelfDecl()) {
2850+
auto lifetimeDependenceKind =
2851+
fn->getLifetimeDependenceInfo().getLifetimeDependenceOnParam(
2852+
/*paramIndex*/ 0);
2853+
if (lifetimeDependenceKind) {
2854+
appendLifetimeDependenceKind(*lifetimeDependenceKind,
2855+
/*isSelfDependence*/ true);
2856+
}
2857+
}
2858+
}
28462859
}
28472860

28482861
static ParamSpecifier
@@ -2900,7 +2913,7 @@ getParameterFlagsForMangling(ParameterTypeFlags flags,
29002913

29012914
void ASTMangler::appendFunctionInputType(
29022915
ArrayRef<AnyFunctionType::Param> params,
2903-
GenericSignature sig,
2916+
LifetimeDependenceInfo lifetimeDependenceInfo, GenericSignature sig,
29042917
const ValueDecl *forDecl) {
29052918
auto defaultSpecifier = getDefaultOwnership(forDecl);
29062919

@@ -2921,10 +2934,12 @@ void ASTMangler::appendFunctionInputType(
29212934
// of the input is no longer directly the type of the declaration, so we
29222935
// don't want it to pick up contextual behavior, such as default ownership,
29232936
// from the top-level declaration type.
2924-
appendTypeListElement(Identifier(), type,
2925-
getParameterFlagsForMangling(param.getParameterFlags(),
2926-
defaultSpecifier),
2927-
sig, nullptr);
2937+
appendParameterTypeListElement(
2938+
Identifier(), type,
2939+
getParameterFlagsForMangling(param.getParameterFlags(),
2940+
defaultSpecifier),
2941+
lifetimeDependenceInfo.getLifetimeDependenceOnParam(/*paramIndex*/ 1),
2942+
sig, nullptr);
29282943
break;
29292944
}
29302945

@@ -2935,16 +2950,20 @@ void ASTMangler::appendFunctionInputType(
29352950

29362951
default:
29372952
bool isFirstParam = true;
2953+
unsigned paramIndex = 1; /* 0 is reserved for self*/
29382954
for (auto &param : params) {
29392955
// Note that we pass `nullptr` as the `forDecl` argument, since the type
29402956
// of the input is no longer directly the type of the declaration, so we
29412957
// don't want it to pick up contextual behavior, such as default ownership,
29422958
// from the top-level declaration type.
2943-
appendTypeListElement(Identifier(), param.getPlainType(),
2944-
getParameterFlagsForMangling(param.getParameterFlags(),
2945-
defaultSpecifier),
2946-
sig, nullptr);
2959+
appendParameterTypeListElement(
2960+
Identifier(), param.getPlainType(),
2961+
getParameterFlagsForMangling(param.getParameterFlags(),
2962+
defaultSpecifier),
2963+
lifetimeDependenceInfo.getLifetimeDependenceOnParam(paramIndex), sig,
2964+
nullptr);
29472965
appendListSeparator(isFirstParam);
2966+
paramIndex++;
29482967
}
29492968
appendOperator("t");
29502969
break;
@@ -2964,9 +2983,8 @@ void ASTMangler::appendTypeList(Type listTy, GenericSignature sig,
29642983
return appendOperator("y");
29652984
bool firstField = true;
29662985
for (auto &field : tuple->getElements()) {
2967-
appendTypeListElement(field.getName(), field.getType(),
2968-
ParameterTypeFlags(),
2969-
sig, forDecl);
2986+
appendTupleTypeListElement(field.getName(), field.getType(), sig,
2987+
forDecl);
29702988
appendListSeparator(firstField);
29712989
}
29722990
} else {
@@ -2975,10 +2993,10 @@ void ASTMangler::appendTypeList(Type listTy, GenericSignature sig,
29752993
}
29762994
}
29772995

2978-
void ASTMangler::appendTypeListElement(Identifier name, Type elementType,
2979-
ParameterTypeFlags flags,
2980-
GenericSignature sig,
2981-
const ValueDecl *forDecl) {
2996+
void ASTMangler::appendParameterTypeListElement(
2997+
Identifier name, Type elementType, ParameterTypeFlags flags,
2998+
std::optional<LifetimeDependenceKind> lifetimeDependenceKind,
2999+
GenericSignature sig, const ValueDecl *forDecl) {
29823000
if (auto *fnType = elementType->getAs<FunctionType>())
29833001
appendFunctionType(fnType, sig, flags.isAutoClosure(), forDecl);
29843002
else
@@ -3007,12 +3025,53 @@ void ASTMangler::appendTypeListElement(Identifier name, Type elementType,
30073025
if (flags.isCompileTimeConst())
30083026
appendOperator("Yt");
30093027

3028+
if (lifetimeDependenceKind) {
3029+
appendLifetimeDependenceKind(*lifetimeDependenceKind,
3030+
/*isSelfDependence*/ false);
3031+
}
3032+
30103033
if (!name.empty())
30113034
appendIdentifier(name.str());
30123035
if (flags.isVariadic())
30133036
appendOperator("d");
30143037
}
30153038

3039+
void ASTMangler::appendLifetimeDependenceKind(LifetimeDependenceKind kind,
3040+
bool isSelfDependence) {
3041+
// If we converge on dependsOn(borrowed: paramName)/dependsOn(paramName)
3042+
// syntax, this can be a single case value check.
3043+
if (kind == LifetimeDependenceKind::Borrow ||
3044+
kind == LifetimeDependenceKind::Mutate) {
3045+
if (isSelfDependence) {
3046+
appendOperator("YLs");
3047+
} else {
3048+
appendOperator("Yls");
3049+
}
3050+
} else {
3051+
// If we converge on dependsOn(borrowed: paramName)/dependsOn(paramName)
3052+
// syntax, this can be a single case value check.
3053+
assert(kind == LifetimeDependenceKind::Copy ||
3054+
kind == LifetimeDependenceKind::Consume);
3055+
if (isSelfDependence) {
3056+
appendOperator("YLi");
3057+
} else {
3058+
appendOperator("Yli");
3059+
}
3060+
}
3061+
}
3062+
3063+
void ASTMangler::appendTupleTypeListElement(Identifier name, Type elementType,
3064+
GenericSignature sig,
3065+
const ValueDecl *forDecl) {
3066+
if (auto *fnType = elementType->getAs<FunctionType>())
3067+
appendFunctionType(fnType, sig, /*isAutoClosure*/ false, forDecl);
3068+
else
3069+
appendType(elementType, sig, forDecl);
3070+
3071+
if (!name.empty())
3072+
appendIdentifier(name.str());
3073+
}
3074+
30163075
bool ASTMangler::appendGenericSignature(GenericSignature sig,
30173076
GenericSignature contextSig) {
30183077
auto canSig = sig.getCanonicalSignature();

lib/Demangling/Demangler.cpp

+33
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,10 @@ NodePointer Demangler::demangleTypeAnnotation() {
951951
case 't':
952952
return createType(
953953
createWithChild(Node::Kind::CompileTimeConst, popTypeAndGetChild()));
954+
case 'l':
955+
return demangleLifetimeDependenceKind(/*isSelfDependence*/ false);
956+
case 'L':
957+
return demangleLifetimeDependenceKind(/*isSelfDependence*/ true);
954958
default:
955959
return nullptr;
956960
}
@@ -1559,6 +1563,7 @@ NodePointer Demangler::popFunctionType(Node::Kind kind, bool hasClangType) {
15591563
}));
15601564
addChild(FuncType, popNode(Node::Kind::ConcurrentFunctionType));
15611565
addChild(FuncType, popNode(Node::Kind::AsyncAnnotation));
1566+
addChild(FuncType, popNode(Node::Kind::SelfLifetimeDependence));
15621567

15631568
FuncType = addChild(FuncType, popFunctionParams(Node::Kind::ArgumentTuple));
15641569
FuncType = addChild(FuncType, popFunctionParams(Node::Kind::ReturnType));
@@ -1611,6 +1616,12 @@ NodePointer Demangler::popFunctionParamLabels(NodePointer Type) {
16111616
if (FuncType->getChild(FirstChildIdx)->getKind()
16121617
== Node::Kind::AsyncAnnotation)
16131618
++FirstChildIdx;
1619+
if (FuncType->getChild(FirstChildIdx)->getKind() ==
1620+
Node::Kind::ParamLifetimeDependence)
1621+
++FirstChildIdx;
1622+
if (FuncType->getChild(FirstChildIdx)->getKind() ==
1623+
Node::Kind::SelfLifetimeDependence)
1624+
++FirstChildIdx;
16141625
auto ParameterType = FuncType->getChild(FirstChildIdx);
16151626

16161627
assert(ParameterType->getKind() == Node::Kind::ArgumentTuple);
@@ -3082,6 +3093,28 @@ NodePointer Demangler::demangleDifferentiableFunctionType() {
30823093
Node::Kind::DifferentiableFunctionType, (Node::IndexType)kind);
30833094
}
30843095

3096+
NodePointer Demangler::demangleLifetimeDependenceKind(bool isSelfDependence) {
3097+
MangledLifetimeDependenceKind kind;
3098+
switch (auto c = nextChar()) {
3099+
case 's':
3100+
kind = MangledLifetimeDependenceKind::Scope;
3101+
break;
3102+
case 'i':
3103+
kind = MangledLifetimeDependenceKind::Inherit;
3104+
break;
3105+
default:
3106+
return nullptr;
3107+
}
3108+
if (isSelfDependence) {
3109+
return createNode(Node::Kind::SelfLifetimeDependence,
3110+
(Node::IndexType)kind);
3111+
}
3112+
auto node = createNode(Node::Kind::ParamLifetimeDependence);
3113+
node->addChild(createNode(Node::Kind::Index, unsigned(kind)), *this);
3114+
node->addChild(popTypeAndGetChild(), *this);
3115+
return createType(node);
3116+
}
3117+
30853118
std::string Demangler::demangleBridgedMethodParams() {
30863119
if (nextIf('_'))
30873120
return std::string();

lib/Demangling/NodePrinter.cpp

+34
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,8 @@ class NodePrinter {
639639
case Node::Kind::SymbolicExtendedExistentialType:
640640
case Node::Kind::HasSymbolQuery:
641641
case Node::Kind::ObjectiveCProtocolSymbolicReference:
642+
case Node::Kind::ParamLifetimeDependence:
643+
case Node::Kind::SelfLifetimeDependence:
642644
return false;
643645
}
644646
printer_unreachable("bad node kind");
@@ -897,6 +899,11 @@ class NodePrinter {
897899
(MangledDifferentiabilityKind)node->getChild(startIndex)->getIndex();
898900
++startIndex;
899901
}
902+
if (node->getChild(startIndex)->getKind() ==
903+
Node::Kind::SelfLifetimeDependence) {
904+
print(node->getChild(startIndex), depth + 1);
905+
++startIndex;
906+
}
900907

901908
Node *thrownErrorNode = nullptr;
902909
if (node->getChild(startIndex)->getKind() == Node::Kind::ThrowsAnnotation ||
@@ -1710,6 +1717,33 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
17101717
Printer << "@noDerivative ";
17111718
print(Node->getChild(0), depth + 1);
17121719
return nullptr;
1720+
case Node::Kind::ParamLifetimeDependence: {
1721+
Printer << "lifetime dependence: ";
1722+
auto kind = (MangledLifetimeDependenceKind)Node->getChild(0)->getIndex();
1723+
switch (kind) {
1724+
case MangledLifetimeDependenceKind::Inherit:
1725+
Printer << "inherit ";
1726+
break;
1727+
case MangledLifetimeDependenceKind::Scope:
1728+
Printer << "scope ";
1729+
break;
1730+
}
1731+
print(Node->getChild(1), depth + 1);
1732+
return nullptr;
1733+
}
1734+
case Node::Kind::SelfLifetimeDependence: {
1735+
Printer << "(self lifetime dependence: ";
1736+
auto kind = (MangledLifetimeDependenceKind)Node->getIndex();
1737+
switch (kind) {
1738+
case MangledLifetimeDependenceKind::Inherit:
1739+
Printer << "inherit) ";
1740+
break;
1741+
case MangledLifetimeDependenceKind::Scope:
1742+
Printer << "scope) ";
1743+
break;
1744+
}
1745+
return nullptr;
1746+
}
17131747
case Node::Kind::NonObjCAttribute:
17141748
Printer << "@nonobjc ";
17151749
return nullptr;

lib/Demangling/OldRemangler.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -1897,6 +1897,16 @@ ManglingError Remangler::mangleNoDerivative(Node *node, unsigned depth) {
18971897
return mangleSingleChildNode(node, depth + 1); // type
18981898
}
18991899

1900+
ManglingError Remangler::mangleParamLifetimeDependence(Node *node,
1901+
unsigned depth) {
1902+
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
1903+
}
1904+
1905+
ManglingError Remangler::mangleSelfLifetimeDependence(Node *node,
1906+
unsigned depth) {
1907+
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
1908+
}
1909+
19001910
ManglingError Remangler::mangleTuple(Node *node, unsigned depth) {
19011911
size_t NumElems = node->getNumChildren();
19021912
if (NumElems > 0 &&

0 commit comments

Comments
 (0)