Skip to content

Commit b57a73a

Browse files
committed
[Concurrency ABI] Add standard substitutions for _Concurrency types.
Introduce a second level of standard substitutions to the mangling, all of the form `Sc<character>`, and use it to provide standard substitutions for most of the _Concurrency types. This is a precursor to rdar://78269642 and a good mangling-size optimization in its own right.
1 parent a8ae952 commit b57a73a

File tree

16 files changed

+125
-30
lines changed

16 files changed

+125
-30
lines changed

Diff for: docs/ABI/Mangling.rst

+20
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ Types
466466
KNOWN-TYPE-KIND ::= 'a' // Swift.Array
467467
KNOWN-TYPE-KIND ::= 'B' // Swift.BinaryFloatingPoint
468468
KNOWN-TYPE-KIND ::= 'b' // Swift.Bool
469+
KNOWN-TYPE-KIND ::= 'c' KNOWN-TYPE-KIND-2 // Second set of standard types
469470
KNOWN-TYPE-KIND ::= 'D' // Swift.Dictionary
470471
KNOWN-TYPE-KIND ::= 'd' // Swift.Float64
471472
KNOWN-TYPE-KIND ::= 'E' // Swift.Encodable
@@ -511,6 +512,25 @@ Types
511512
KNOWN-TYPE-KIND ::= 'Z' // Swift.SignedInteger
512513
KNOWN-TYPE-KIND ::= 'z' // Swift.BinaryInteger
513514

515+
KNOWN-TYPE-KIND-2 ::= 'A' // Swift.Actor
516+
KNOWN-TYPE-KIND-2 ::= 'C' // Swift.CheckedContinuation
517+
KNOWN-TYPE-KIND-2 ::= 'c' // Swift.UnsafeContinuation
518+
KNOWN-TYPE-KIND-2 ::= 'E' // Swift.CancellationError
519+
KNOWN-TYPE-KIND-2 ::= 'e' // Swift.UnownedSerialExecutor
520+
KNOWN-TYPE-KIND-2 ::= 'F' // Swift.Executor
521+
KNOWN-TYPE-KIND-2 ::= 'f' // Swift.SerialExecutor
522+
KNOWN-TYPE-KIND-2 ::= 'G' // Swift.TaskGroup
523+
KNOWN-TYPE-KIND-2 ::= 'g' // Swift.ThrowingTaskGroup
524+
KNOWN-TYPE-KIND-2 ::= 'I' // Swift.AsyncIteratorProtocol
525+
KNOWN-TYPE-KIND-2 ::= 'i' // Swift.AsyncSequence
526+
KNOWN-TYPE-KIND-2 ::= 'J' // Swift.UnownedJob
527+
KNOWN-TYPE-KIND-2 ::= 'M' // Swift.MainActor
528+
KNOWN-TYPE-KIND-2 ::= 'P' // Swift.TaskPriority
529+
KNOWN-TYPE-KIND-2 ::= 'S' // Swift.AsyncStream
530+
KNOWN-TYPE-KIND-2 ::= 's' // Swift.AsyncThrowingStream
531+
KNOWN-TYPE-KIND-2 ::= 'T' // Swift.Task
532+
KNOWN-TYPE-KIND-2 ::= 't' // Swift.UnsafeCurrentTask
533+
514534
protocol ::= context decl-name
515535
protocol ::= standard-substitutions
516536

Diff for: include/swift/AST/Module.h

+3
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,9 @@ class ModuleDecl : public DeclContext, public TypeDecl {
729729
/// \returns true if this module is the "swift" standard library module.
730730
bool isStdlibModule() const;
731731

732+
/// \returns true if this module has standard substitutions for mangling.
733+
bool hasStandardSubstitutions() const;
734+
732735
/// \returns true if this module is the "SwiftShims" module;
733736
bool isSwiftShimsModule() const;
734737

Diff for: include/swift/Demangling/Demangler.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ class Demangler : public NodeFactory {
494494
NodePointer pushMultiSubstitutions(int RepeatCount, size_t SubstIdx);
495495
NodePointer createSwiftType(Node::Kind typeKind, const char *name);
496496
NodePointer demangleStandardSubstitution();
497-
NodePointer createStandardSubstitution(char Subst);
497+
NodePointer createStandardSubstitution(char Subst, bool SecondLevel);
498498
NodePointer demangleLocalIdentifier();
499499

500500
NodePointer popModule();

Diff for: include/swift/Demangling/ManglingUtils.h

+13-9
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ char translateOperatorChar(char op);
9999
std::string translateOperator(StringRef Op);
100100

101101
/// Returns the standard type kind for an 'S' substitution, e.g. 'i' for "Int".
102-
char getStandardTypeSubst(StringRef TypeName);
102+
llvm::Optional<StringRef> getStandardTypeSubst(StringRef TypeName);
103103

104104
/// Mangles an identifier using a generic Mangler class.
105105
///
@@ -274,8 +274,9 @@ class SubstitutionMerging {
274274
/// *) getBufferStr(): Returns a StringRef of the current content of Buffer.
275275
/// *) resetBuffer(size_t): Resets the buffer to an old position.
276276
template <typename Mangler>
277-
bool tryMergeSubst(Mangler &M, char Subst, bool isStandardSubst) {
278-
assert(isUpperLetter(Subst) || (isStandardSubst && isLowerLetter(Subst)));
277+
bool tryMergeSubst(Mangler &M, StringRef Subst, bool isStandardSubst) {
278+
assert(isUpperLetter(Subst.back()) ||
279+
(isStandardSubst && isLowerLetter(Subst.back())));
279280
StringRef BufferStr = M.getBufferStr();
280281
if (lastNumSubsts > 0 && lastNumSubsts < MaxRepeatCount
281282
&& BufferStr.size() == lastSubstPosition + lastSubstSize
@@ -284,17 +285,20 @@ class SubstitutionMerging {
284285
// The last mangled thing is a substitution.
285286
assert(lastSubstPosition > 0 && lastSubstPosition < BufferStr.size());
286287
assert(lastSubstSize > 0);
287-
char lastSubst = BufferStr.back();
288-
assert(isUpperLetter(lastSubst)
289-
|| (isStandardSubst && isLowerLetter(lastSubst)));
288+
StringRef lastSubst = BufferStr.take_back(lastSubstSize)
289+
.drop_while([](char c) {
290+
return isDigit(c);
291+
});
292+
assert(isUpperLetter(lastSubst.back())
293+
|| (isStandardSubst && isLowerLetter(lastSubst.back())));
290294
if (lastSubst != Subst && !isStandardSubst) {
291295
// We can merge with a different 'A' substitution,
292296
// e.g. 'AB' -> 'AbC'.
293297
lastSubstPosition = BufferStr.size();
294298
lastNumSubsts = 1;
295299
M.resetBuffer(BufferStr.size() - 1);
296-
assert(isUpperLetter(lastSubst));
297-
M.Buffer << (char)(lastSubst - 'A' + 'a') << Subst;
300+
assert(isUpperLetter(lastSubst.back()));
301+
M.Buffer << (char)(lastSubst.back() - 'A' + 'a') << Subst;
298302
lastSubstSize = 1;
299303
return true;
300304
}
@@ -312,7 +316,7 @@ class SubstitutionMerging {
312316
// We can't merge with the previous substitution, but let's remember this
313317
// substitution which will be mangled by the caller.
314318
lastSubstPosition = BufferStr.size() + 1;
315-
lastSubstSize = 1;
319+
lastSubstSize = Subst.size();
316320
lastNumSubsts = 1;
317321
lastSubstIsStandardSubst = isStandardSubst;
318322
return false;

Diff for: include/swift/Demangling/StandardTypesMangling.def

+27-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@
1212

1313
/// STANDARD_TYPE(KIND, MANGLING, TYPENAME)
1414
/// The 1-character MANGLING for a known TYPENAME of KIND.
15-
15+
///
16+
/// STANDARD_TYPE_2(KIND, MANGLING, TYPENAME)
17+
/// The 1-character MANGLING for a known TYPENAME of KIND that is in the
18+
/// second level of standard types, all of which are mangled with the form
19+
/// Sc<MANGLING>.
20+
///
1621
/// OBJC_INTEROP_STANDARD_TYPE(KIND, MANGLING, TYPENAME)
1722
/// The 1-character MANGLING for a known TYPENAME of KIND, for a type that's
1823
/// only available with ObjC interop enabled.
@@ -22,6 +27,7 @@
2227
STANDARD_TYPE(KIND, MANGLING, TYPENAME)
2328
#endif
2429

30+
2531
OBJC_INTEROP_STANDARD_TYPE(Structure, A, AutoreleasingUnsafeMutablePointer)
2632
STANDARD_TYPE(Structure, a, Array)
2733
STANDARD_TYPE(Structure, b, Bool)
@@ -73,5 +79,25 @@ STANDARD_TYPE(Protocol, y, StringProtocol)
7379
STANDARD_TYPE(Protocol, Z, SignedInteger)
7480
STANDARD_TYPE(Protocol, z, BinaryInteger)
7581

82+
STANDARD_TYPE_2(Protocol, A, Actor)
83+
STANDARD_TYPE_2(Structure, C, CheckedContinuation)
84+
STANDARD_TYPE_2(Structure, c, UnsafeContinuation)
85+
STANDARD_TYPE_2(Structure, E, CancellationError)
86+
STANDARD_TYPE_2(Structure, e, UnownedSerialExecutor)
87+
STANDARD_TYPE_2(Protocol, F, Executor)
88+
STANDARD_TYPE_2(Protocol, f, SerialExecutor)
89+
STANDARD_TYPE_2(Structure, G, TaskGroup)
90+
STANDARD_TYPE_2(Structure, g, ThrowingTaskGroup)
91+
STANDARD_TYPE_2(Protocol, I, AsyncIteratorProtocol)
92+
STANDARD_TYPE_2(Protocol, i, AsyncSequence)
93+
STANDARD_TYPE_2(Structure, J, UnownedJob)
94+
STANDARD_TYPE_2(Class, M, MainActor)
95+
STANDARD_TYPE_2(Structure, P, TaskPriority)
96+
STANDARD_TYPE_2(Structure, S, AsyncStream)
97+
STANDARD_TYPE_2(Structure, s, AsyncThrowingStream)
98+
STANDARD_TYPE_2(Structure, T, Task)
99+
STANDARD_TYPE_2(Structure, t, UnsafeCurrentTask)
100+
76101
#undef STANDARD_TYPE
77102
#undef OBJC_INTEROP_STANDARD_TYPE
103+
#undef STANDARD_TYPE_2

Diff for: lib/AST/ASTDemangler.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,15 @@ ASTBuilder::findTypeDecl(DeclContext *dc,
10601060
result = candidate;
10611061
}
10621062

1063+
// If we looked into the standard library module, but didn't find anything,
1064+
// try the _Concurrency module, which is also mangled into the Swift module.
1065+
if (!result && !dc->getParent() && module->isStdlibModule()) {
1066+
ASTContext &ctx = module->getASTContext();
1067+
if (auto concurrencyModule = ctx.getLoadedModule(ctx.Id_Concurrency)) {
1068+
return findTypeDecl(concurrencyModule, name, privateDiscriminator, kind);
1069+
}
1070+
}
1071+
10631072
return result;
10641073
}
10651074

Diff for: lib/AST/ASTMangler.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -2935,13 +2935,15 @@ void ASTMangler::appendDeclType(const ValueDecl *decl,
29352935

29362936
bool ASTMangler::tryAppendStandardSubstitution(const GenericTypeDecl *decl) {
29372937
// Bail out if our parent isn't the swift standard library.
2938-
if (!decl->isStdlibDecl())
2938+
auto dc = decl->getDeclContext();
2939+
if (!dc->isModuleScopeContext() ||
2940+
!dc->getParentModule()->hasStandardSubstitutions())
29392941
return false;
29402942

29412943
if (isa<NominalTypeDecl>(decl)) {
2942-
if (char Subst = getStandardTypeSubst(decl->getName().str())) {
2943-
if (!SubstMerging.tryMergeSubst(*this, Subst, /*isStandardSubst*/ true)) {
2944-
appendOperator("S", StringRef(&Subst, 1));
2944+
if (auto Subst = getStandardTypeSubst(decl->getName().str())) {
2945+
if (!SubstMerging.tryMergeSubst(*this, *Subst, /*isStandardSubst*/ true)){
2946+
appendOperator("S", *Subst);
29452947
}
29462948
return true;
29472949
}

Diff for: lib/AST/Module.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -1407,6 +1407,12 @@ bool ModuleDecl::isStdlibModule() const {
14071407
return !getParent() && getName() == getASTContext().StdlibModuleName;
14081408
}
14091409

1410+
bool ModuleDecl::hasStandardSubstitutions() const {
1411+
return !getParent() &&
1412+
(getName() == getASTContext().StdlibModuleName ||
1413+
getName() == getASTContext().Id_Concurrency);
1414+
}
1415+
14101416
bool ModuleDecl::isSwiftShimsModule() const {
14111417
return !getParent() && getName() == getASTContext().SwiftShimsModuleName;
14121418
}

Diff for: lib/Basic/Mangler.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -223,13 +223,14 @@ void Mangler::mangleSubstitution(unsigned Idx) {
223223
return appendOperator("A", Index(Idx - 26));
224224
}
225225

226-
char Subst = Idx + 'A';
226+
char SubstChar = Idx + 'A';
227+
StringRef Subst(&SubstChar, 1);
227228
if (SubstMerging.tryMergeSubst(*this, Subst, /*isStandardSubst*/ false)) {
228229
#ifndef NDEBUG
229230
++mergedSubsts;
230231
#endif
231232
} else {
232-
appendOperator("A", StringRef(&Subst, 1));
233+
appendOperator("A", Subst);
233234
}
234235
}
235236

Diff for: lib/Demangling/Demangler.cpp

+12-4
Original file line numberDiff line numberDiff line change
@@ -949,7 +949,9 @@ NodePointer Demangler::demangleStandardSubstitution() {
949949
int RepeatCount = demangleNatural();
950950
if (RepeatCount > SubstitutionMerging::MaxRepeatCount)
951951
return nullptr;
952-
if (NodePointer Nd = createStandardSubstitution(nextChar())) {
952+
bool secondLevelSubstitution = nextIf('c');
953+
if (NodePointer Nd = createStandardSubstitution(
954+
nextChar(), secondLevelSubstitution)) {
953955
while (RepeatCount-- > 1) {
954956
pushNode(Nd);
955957
}
@@ -960,10 +962,16 @@ NodePointer Demangler::demangleStandardSubstitution() {
960962
}
961963
}
962964

963-
NodePointer Demangler::createStandardSubstitution(char Subst) {
965+
NodePointer Demangler::createStandardSubstitution(
966+
char Subst, bool SecondLevel) {
964967
#define STANDARD_TYPE(KIND, MANGLING, TYPENAME) \
965-
if (Subst == #MANGLING[0]) { \
966-
return createSwiftType(Node::Kind::KIND, #TYPENAME); \
968+
if (!SecondLevel && Subst == #MANGLING[0]) { \
969+
return createSwiftType(Node::Kind::KIND, #TYPENAME); \
970+
}
971+
972+
#define STANDARD_TYPE_2(KIND, MANGLING, TYPENAME) \
973+
if (SecondLevel && Subst == #MANGLING[0]) { \
974+
return createSwiftType(Node::Kind::KIND, #TYPENAME); \
967975
}
968976

969977
#include "swift/Demangling/StandardTypesMangling.def"

Diff for: lib/Demangling/ManglingUtils.cpp

+8-3
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,19 @@ std::string Mangle::translateOperator(StringRef Op) {
6666
return Encoded;
6767
}
6868

69-
char Mangle::getStandardTypeSubst(StringRef TypeName) {
69+
llvm::Optional<StringRef> Mangle::getStandardTypeSubst(StringRef TypeName) {
7070
#define STANDARD_TYPE(KIND, MANGLING, TYPENAME) \
7171
if (TypeName == #TYPENAME) { \
72-
return #MANGLING[0]; \
72+
return StringRef(#MANGLING); \
73+
}
74+
75+
#define STANDARD_TYPE_2(KIND, MANGLING, TYPENAME) \
76+
if (TypeName == #TYPENAME) { \
77+
return StringRef("c" #MANGLING); \
7378
}
7479

7580
#include "swift/Demangling/StandardTypesMangling.def"
7681

77-
return 0;
82+
return llvm::None;
7883
}
7984

Diff for: lib/Demangling/Remangler.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,8 @@ bool Remangler::trySubstitution(Node *node, SubstitutionEntry &entry,
350350
mangleIndex(Idx - 26);
351351
return true;
352352
}
353-
char Subst = Idx + 'A';
353+
char SubstChar = Idx + 'A';
354+
StringRef Subst(&SubstChar, 1);
354355
if (!SubstMerging.tryMergeSubst(*this, Subst, /*isStandardSubst*/ false)) {
355356
Buffer << 'A' << Subst;
356357
}
@@ -371,6 +372,7 @@ void Remangler::mangleIdentifierImpl(Node *node, bool isOperator) {
371372

372373
bool Remangler::mangleStandardSubstitution(Node *node) {
373374
if (node->getKind() != Node::Kind::Structure
375+
&& node->getKind() != Node::Kind::Class
374376
&& node->getKind() != Node::Kind::Enum
375377
&& node->getKind() != Node::Kind::Protocol)
376378
return false;
@@ -384,9 +386,9 @@ bool Remangler::mangleStandardSubstitution(Node *node) {
384386
if (node->getChild(1)->getKind() != Node::Kind::Identifier)
385387
return false;
386388

387-
if (char Subst = getStandardTypeSubst(node->getChild(1)->getText())) {
388-
if (!SubstMerging.tryMergeSubst(*this, Subst, /*isStandardSubst*/ true)) {
389-
Buffer << 'S' << Subst;
389+
if (auto Subst = getStandardTypeSubst(node->getChild(1)->getText())) {
390+
if (!SubstMerging.tryMergeSubst(*this, *Subst, /*isStandardSubst*/ true)) {
391+
Buffer << 'S' << *Subst;
390392
}
391393
return true;
392394
}

Diff for: lib/IRGen/IRGenMangler.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ IRGenMangler::withSymbolicReferences(IRGenModule &IGM,
9797
// The short-substitution types in the standard library have compact
9898
// manglings already, and the runtime ought to have a lookup table for
9999
// them. Symbolic referencing would be wasteful.
100-
if (type->getModuleContext()->isStdlibModule()
100+
if (type->getModuleContext()->hasStandardSubstitutions()
101101
&& Mangle::getStandardTypeSubst(type->getName().str())) {
102102
return false;
103103
}

Diff for: stdlib/public/runtime/MetadataLookup.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,10 @@ _searchTypeMetadataRecords(TypeMetadataPrivateState &T,
673673
#define STANDARD_TYPE(KIND, MANGLING, TYPENAME) \
674674
extern "C" const ContextDescriptor DESCRIPTOR_MANGLING(MANGLING, DESCRIPTOR_MANGLING_SUFFIX(KIND));
675675

676+
// FIXME: When the _Concurrency library gets merged into the Standard Library,
677+
// we will be able to reference those symbols directly as well.
678+
#define STANDARD_TYPE_2(KIND, MANGLING, TYPENAME)
679+
676680
#if !SWIFT_OBJC_INTEROP
677681
# define OBJC_INTEROP_STANDARD_TYPE(KIND, MANGLING, TYPENAME)
678682
#endif
@@ -703,6 +707,9 @@ _findContextDescriptor(Demangle::NodePointer node,
703707
if (name.equals(#TYPENAME)) { \
704708
return &DESCRIPTOR_MANGLING(MANGLING, DESCRIPTOR_MANGLING_SUFFIX(KIND)); \
705709
}
710+
// FIXME: When the _Concurrency library gets merged into the Standard Library,
711+
// we will be able to reference those symbols directly as well.
712+
#define STANDARD_TYPE_2(KIND, MANGLING, TYPENAME)
706713
#if !SWIFT_OBJC_INTEROP
707714
# define OBJC_INTEROP_STANDARD_TYPE(KIND, MANGLING, TYPENAME)
708715
#endif

Diff for: test/Demangle/Inputs/manglings.txt

+2
Original file line numberDiff line numberDiff line change
@@ -403,3 +403,5 @@ $s4test3fooyyS2f_SfYkztYjrXEF ---> test.foo(@differentiable(reverse) (Swift.Floa
403403
$s4test3fooyyS2f_SfYkntYjrXEF ---> test.foo(@differentiable(reverse) (Swift.Float, __owned @noDerivative Swift.Float) -> Swift.Float) -> ()
404404
$s4test3fooyyS2f_SfYktYjrXEF ---> test.foo(@differentiable(reverse) (Swift.Float, @noDerivative Swift.Float) -> Swift.Float) -> ()
405405
$s4test3fooyyS2f_SfYktYaYbYjrXEF ---> test.foo(@differentiable(reverse) @Sendable (Swift.Float, @noDerivative Swift.Float) async -> Swift.Float) -> ()
406+
$sScA ---> Swift.Actor
407+
$sScGySiG ---> Swift.TaskGroup<Swift.Int>

Diff for: test/IRGen/async/builtin_executor.sil

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ bb0(%0 : $MyDefaultActor):
5454
sil @test_build_custom_actor : $(@guaranteed MyCustomActor) -> Builtin.Executor {
5555
bb0(%0 : $MyCustomActor):
5656
// CHECK: [[T0:%.*]] = ptrtoint %T4test13MyCustomActorC* %0 to [[INT]]
57-
// CHECK-NEXT: [[T1:%.*]] = call i8** @"$s4test13MyCustomActorCACs14SerialExecutorAAWl"()
57+
// CHECK-NEXT: [[T1:%.*]] = call i8** @"$s4test13MyCustomActorCACScfAAWl"()
5858
// CHECK-NEXT: [[T2:%.*]] = ptrtoint i8** [[T1]] to [[INT]]
5959
// CHECK: [[ONE:%.*]] = insertvalue { [[INT]], [[INT]] } undef, [[INT]] [[T0]], 0
6060
// CHECK-NEXT: [[TWO:%.*]] = insertvalue { [[INT]], [[INT]] } [[ONE]], [[INT]] [[T2]], 1

0 commit comments

Comments
 (0)