Skip to content

Commit bc7c916

Browse files
committed
[rbi] Fix demangling of sending results.
The issue here is that the demangler (since we have a postfix mangling) parses parameters/results/etc and then uses earlier postfix type arguments to attach the relevant types to the parameters/results/etc. Since the flag for a sending result was placed in between the parameters and results, we get an off by one error. Rather than fix that specific issue by introducing an offset for the off by one error, I used the fact that the impl-function part of the mangling is not ABI and can be modified to move the bit used to signify a sending result to before the parameters so the whole problem is avoided. I also while I was doing this looked through the sending result mangling for any further issues and fixed them as I found them. rdar://141962865 (cherry picked from commit cb2d756)
1 parent 06662ce commit bc7c916

File tree

9 files changed

+63
-16
lines changed

9 files changed

+63
-16
lines changed

docs/ABI/Mangling.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,7 @@ mangled in to disambiguate.
836836
impl-function-type ::= type* 'I' FUNC-ATTRIBUTES '_'
837837
impl-function-type ::= type* generic-signature 'I' FUNC-ATTRIBUTES '_'
838838

839-
FUNC-ATTRIBUTES ::= PATTERN-SUBS? INVOCATION-SUBS? PSEUDO-GENERIC? CALLEE-ESCAPE? ISOLATION? DIFFERENTIABILITY-KIND? CALLEE-CONVENTION FUNC-REPRESENTATION? COROUTINE-KIND? SENDABLE? ASYNC? (PARAM-CONVENTION PARAM-DIFFERENTIABILITY?)* RESULT-CONVENTION* ('Y' PARAM-CONVENTION)* ('z' RESULT-CONVENTION RESULT-DIFFERENTIABILITY?)?
839+
FUNC-ATTRIBUTES ::= PATTERN-SUBS? INVOCATION-SUBS? PSEUDO-GENERIC? CALLEE-ESCAPE? ISOLATION? DIFFERENTIABILITY-KIND? CALLEE-CONVENTION FUNC-REPRESENTATION? COROUTINE-KIND? SENDABLE? ASYNC? SENDING-RESULT? (PARAM-CONVENTION PARAM-DIFFERENTIABILITY?)* RESULT-CONVENTION* ('Y' PARAM-CONVENTION)* ('z' RESULT-CONVENTION RESULT-DIFFERENTIABILITY?)?
840840

841841
PATTERN-SUBS ::= 's' // has pattern substitutions
842842
INVOCATION-SUB ::= 'I' // has invocation substitutions
@@ -870,8 +870,9 @@ mangled in to disambiguate.
870870
COROUTINE-KIND ::= 'G' // yield-many coroutine
871871

872872
#if SWIFT_RUNTIME_VERSION >= 5.5
873-
SENDABLE ::= 'h' // @Sendable
874-
ASYNC ::= 'H' // @async
873+
SENDABLE ::= 'h' // @Sendable
874+
ASYNC ::= 'H' // @async
875+
SENDING-RESULT ::= 'T' // sending result
875876
#endif
876877

877878
PARAM-CONVENTION ::= 'i' // indirect in

include/swift/Demangling/TypeDecoder.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,7 +1093,14 @@ class TypeDecoder {
10931093
flags = flags.withSendable();
10941094
} else if (child->getText() == "@async") {
10951095
flags = flags.withAsync();
1096+
} else if (child->getText() == "sending-result") {
1097+
flags = flags.withSendingResult();
10961098
}
1099+
} else if (child->getKind() == NodeKind::ImplSendingResult) {
1100+
// NOTE: This flag needs to be set both at the function level and on
1101+
// each of the parameters. The flag on the function just means that
1102+
// all parameters are sending (which is always true today).
1103+
flags = flags.withSendingResult();
10971104
} else if (child->getKind() == NodeKind::ImplCoroutineKind) {
10981105
if (!child->hasText())
10991106
return MAKE_NODE_TYPE_ERROR0(child, "expected text");

lib/AST/ASTDemangler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,10 @@ Type ASTBuilder::createImplFunctionType(
677677
auto type = result.getType()->getCanonicalType();
678678
auto conv = getResultConvention(result.getConvention());
679679
auto options = *getResultOptions(result.getOptions());
680+
// We currently set sending result at the function level, but we set sending
681+
// result on each result.
682+
if (flags.hasSendingResult())
683+
options |= SILResultInfo::IsSending;
680684
funcResults.emplace_back(type, conv, options);
681685
}
682686

lib/AST/ASTMangler.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2200,6 +2200,19 @@ void ASTMangler::appendImplFunctionType(SILFunctionType *fn,
22002200
OpArgs.push_back('H');
22012201
}
22022202

2203+
// Mangle if we have a sending result and we are in a recursive position.
2204+
//
2205+
// DISCUSSION: We only want sending results to change ABI if it is using in a
2206+
// function value passed to a parameter or generic position... but not if it
2207+
// is just added to a return type.
2208+
//
2209+
// E.x.:
2210+
//
2211+
// func foo() -> sending X // No mangling
2212+
// func bar(_ x: () -> sending X) {} // Add to mangling for x
2213+
if (isInRecursion && fn->hasSendingResult())
2214+
OpArgs.push_back('T');
2215+
22032216
GenericSignature sig = fn->getSubstGenericSignature();
22042217

22052218
// Mangle the parameters.
@@ -2212,10 +2225,6 @@ void ASTMangler::appendImplFunctionType(SILFunctionType *fn,
22122225
appendType(param.getInterfaceType(), sig, forDecl);
22132226
}
22142227

2215-
// Mangle if we have a sending result.
2216-
if (isInRecursion && fn->hasSendingResult())
2217-
OpArgs.push_back('T');
2218-
22192228
// Mangle the results.
22202229
for (auto result : fn->getResults()) {
22212230
OpArgs.push_back(getResultConvention(result.getConvention()));

lib/Demangling/Demangler.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2412,6 +2412,10 @@ NodePointer Demangler::demangleImplFunctionType() {
24122412
*this);
24132413
}
24142414

2415+
if (nextIf('T')) {
2416+
type->addChild(createNode(Node::Kind::ImplSendingResult), *this);
2417+
}
2418+
24152419
addChild(type, GenSig);
24162420

24172421
int NumTypesToAdd = 0;
@@ -2425,10 +2429,6 @@ NodePointer Demangler::demangleImplFunctionType() {
24252429
++NumTypesToAdd;
24262430
}
24272431

2428-
if (nextIf('T')) {
2429-
type->addChild(createNode(Node::Kind::ImplSendingResult), *this);
2430-
}
2431-
24322432
while (NodePointer Result = demangleImplResultConvention(
24332433
Node::Kind::ImplResult)) {
24342434
type = addChild(type, Result);
@@ -2461,7 +2461,7 @@ NodePointer Demangler::demangleImplFunctionType() {
24612461
return nullptr;
24622462
type->getChild(type->getNumChildren() - Idx - 1)->addChild(ConvTy, *this);
24632463
}
2464-
2464+
24652465
return createType(type);
24662466
}
24672467

lib/Demangling/OldDemangler.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2252,6 +2252,9 @@ class OldDemangler {
22522252
if (Mangled.nextIf('H'))
22532253
addImplFunctionAttribute(type, "@async");
22542254

2255+
if (Mangled.nextIf('T'))
2256+
addImplFunctionAttribute(type, "sending-result");
2257+
22552258
// Enter a new generic context if this type is generic.
22562259
// FIXME: replace with std::optional, when we have it.
22572260
bool isPseudogeneric = false;

lib/Demangling/Remangler.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2111,9 +2111,10 @@ ManglingError Remangler::mangleImplFunctionType(Node *node, unsigned depth) {
21112111
}
21122112
case Node::Kind::ImplFunctionAttribute: {
21132113
char FuncAttr = llvm::StringSwitch<char>(Child->getText())
2114-
.Case("@Sendable", 'h')
2115-
.Case("@async", 'H')
2116-
.Default(0);
2114+
.Case("@Sendable", 'h')
2115+
.Case("@async", 'H')
2116+
.Case("sending-result", 'T')
2117+
.Default(0);
21172118
if (!FuncAttr) {
21182119
return MANGLING_ERROR(ManglingError::InvalidImplFunctionAttribute,
21192120
Child);

test/Concurrency/sending_mangling.swift

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
// RUN: %target-swift-frontend %s -emit-silgen -swift-version 6 | swift-demangle | %FileCheck -check-prefix=CHECK %s
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend %s -emit-silgen -swift-version 6 | swift-demangle | %FileCheck %s
3+
// RUN: %target-swift-frontend %s -emit-silgen -swift-version 6 | %FileCheck -check-prefix=SIL %s
24

35
// REQUIRES: concurrency
46
// REQUIRES: asserts
@@ -110,3 +112,21 @@ struct ConstructorSharedTest {
110112
// CHECK: sil hidden [ossa] @sending_mangling.ConstructorSharedTest.functionSuppressed(sending_mangling.NonSendableKlass) -> () : $@convention(method) (@sil_sending @guaranteed NonSendableKlass, ConstructorSharedTest) -> () {
111113
func functionSuppressed(_ x: __shared sending NonSendableKlass) {}
112114
}
115+
116+
// Make sure that we produce the appropriate reabstraction thunk.
117+
func reabstractionThunkTest_takeSendingReturnSending<T>(
118+
_ x: sending T) -> sending T { fatalError() }
119+
func reabstractionThunkTest_reabstractionThunkGenerator<T>(
120+
_ x: sending T,
121+
_ f: (sending T) -> T) {}
122+
123+
// CHECK: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @reabstraction thunk helper from @escaping @callee_guaranteed (@in sending sending_mangling.NonSendableKlass) -> sending (@out sending_mangling.NonSendableKlass) to @escaping @callee_guaranteed (@owned sending sending_mangling.NonSendableKlass) -> sending (@owned sending_mangling.NonSendableKlass) : $@convention(thin) (@sil_sending @owned NonSendableKlass, @guaranteed @callee_guaranteed (@sil_sending @in NonSendableKlass) -> @sil_sending @out NonSendableKlass) -> @sil_sending @owned NonSendableKlass {
124+
// SIL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s16sending_mangling16NonSendableKlassCACIegTiTr_A2CIegTxTo_TR : $@convention(thin) (@sil_sending @owned NonSendableKlass, @guaranteed @callee_guaranteed (@sil_sending @in NonSendableKlass) -> @sil_sending @out NonSendableKlass) -> @sil_sending @owned NonSendableKlass {
125+
126+
// CHECK: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @reabstraction thunk helper from @callee_guaranteed (@owned sending sending_mangling.NonSendableKlass) -> (@owned sending_mangling.NonSendableKlass) to @escaping @callee_guaranteed (@in sending sending_mangling.NonSendableKlass) -> (@out sending_mangling.NonSendableKlass) : $@convention(thin) (@sil_sending @in NonSendableKlass, @guaranteed @noescape @callee_guaranteed (@sil_sending @owned NonSendableKlass) -> @owned NonSendableKlass) -> @out NonSendableKlass {
127+
// SIL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s16sending_mangling16NonSendableKlassCACIgxTo_A2CIegiTr_TR : $@convention(thin) (@sil_sending @in NonSendableKlass, @guaranteed @noescape @callee_guaranteed (@sil_sending @owned NonSendableKlass) -> @owned NonSendableKlass) -> @out NonSendableKlass {
128+
func reabstractionThunkTest() {
129+
reabstractionThunkTest_reabstractionThunkGenerator(
130+
NonSendableKlass(),
131+
reabstractionThunkTest_takeSendingReturnSending)
132+
}

test/Demangle/Inputs/manglings.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,3 +485,5 @@ $s4main6VectorVy$1_SiG ---> main.Vector<2, Swift.Int>
485485
$s$n3_SSBV ---> Builtin.FixedArray<-4, Swift.String>
486486
$s3red7MyActorC3runyxxyYaKACYcYTXEYaKlFZ ---> static red.MyActor.run<A>(@red.MyActor () async throws -> sending A) async throws -> A
487487
$s3red7MyActorC3runyxxyYaKYAYTXEYaKlFZ ---> static red.MyActor.run<A>(@isolated(any) () async throws -> sending A) async throws -> A
488+
$s7ToolKit10TypedValueOACs5Error_pIgHTnTrzo_A2CsAD_pIegHiTrzr_TR ---> {T:} reabstraction thunk helper from @callee_guaranteed @async (@in_guaranteed sending ToolKit.TypedValue) -> sending (@out ToolKit.TypedValue, @error @owned Swift.Error) to @escaping @callee_guaranteed @async (@in sending ToolKit.TypedValue) -> (@out ToolKit.TypedValue, @error @out Swift.Error)
489+
$s16sending_mangling16NonSendableKlassCACIegTiTr_A2CIegTxTo_TR ---> {T:} reabstraction thunk helper from @escaping @callee_guaranteed (@in sending sending_mangling.NonSendableKlass) -> sending (@out sending_mangling.NonSendableKlass) to @escaping @callee_guaranteed (@owned sending sending_mangling.NonSendableKlass) -> sending (@owned sending_mangling.NonSendableKlass)

0 commit comments

Comments
 (0)