Skip to content

Commit 198e8d1

Browse files
committed
AST: Introduce a new debug-only mangling for @escaping @convention(block) functions
Our mangling did not encode if an Objective-C block was escaping or not. This is not a huge problem in practice, but for debug info we want type reconstruction to round-trip exactly. There was a previous workaround to paper over this specific problem. Remove the workaround, and add a new 'XL' mangling for escaping blocks. Since we don't actually want to break ABI compatibility, only use the new mangling in DWARF debug info.
1 parent 7890524 commit 198e8d1

File tree

10 files changed

+44
-32
lines changed

10 files changed

+44
-32
lines changed

docs/ABI/Mangling.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ Types
512512
FUNCTION-KIND ::= 'U' // uncurried function type (currently not used)
513513
FUNCTION-KIND ::= 'K' // @auto_closure function type (noescape)
514514
FUNCTION-KIND ::= 'B' // objc block function type
515+
FUNCTION-KIND ::= 'L' // objc block function type (escaping) (DWARF only; otherwise use 'B')
515516
FUNCTION-KIND ::= 'C' // C function pointer type
516517
FUNCTION-KIND ::= 'A' // @auto_closure function type (escaping)
517518
FUNCTION-KIND ::= 'E' // function type (noescape)

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ NODE(NonObjCAttribute)
147147
NODE(Number)
148148
NODE(ObjCAttribute)
149149
NODE(ObjCBlock)
150+
NODE(EscapingObjCBlock)
150151
CONTEXT_NODE(OtherNominalType)
151152
CONTEXT_NODE(OwningAddressor)
152153
CONTEXT_NODE(OwningMutableAddressor)

include/swift/Demangling/TypeDecoder.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,7 @@ class TypeDecoder {
487487
auto index = Node->getChild(1)->getIndex();
488488
return Builder.createGenericTypeParameterType(depth, index);
489489
}
490+
case NodeKind::EscapingObjCBlock:
490491
case NodeKind::ObjCBlock:
491492
case NodeKind::CFunctionPointer:
492493
case NodeKind::ThinFunctionType:
@@ -498,7 +499,8 @@ class TypeDecoder {
498499
return BuiltType();
499500

500501
FunctionTypeFlags flags;
501-
if (Node->getKind() == NodeKind::ObjCBlock) {
502+
if (Node->getKind() == NodeKind::ObjCBlock ||
503+
Node->getKind() == NodeKind::EscapingObjCBlock) {
502504
flags = flags.withConvention(FunctionMetadataConvention::Block);
503505
} else if (Node->getKind() == NodeKind::CFunctionPointer) {
504506
flags =
@@ -524,7 +526,8 @@ class TypeDecoder {
524526
.withParameterFlags(hasParamFlags)
525527
.withEscaping(
526528
Node->getKind() == NodeKind::FunctionType ||
527-
Node->getKind() == NodeKind::EscapingAutoClosureType);
529+
Node->getKind() == NodeKind::EscapingAutoClosureType ||
530+
Node->getKind() == NodeKind::EscapingObjCBlock);
528531

529532
auto result = decodeMangledType(Node->getChild(isThrow ? 2 : 1));
530533
if (!result) return BuiltType();

lib/AST/ASTMangler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1911,6 +1911,10 @@ void ASTMangler::appendFunctionType(AnyFunctionType *fn, bool isAutoClosure,
19111911
// changes to better support thin functions.
19121912
switch (fn->getRepresentation()) {
19131913
case AnyFunctionType::Representation::Block:
1914+
// We distinguish escaping and non-escaping blocks, but only in the DWARF
1915+
// mangling, because the ABI is already set.
1916+
if (!fn->isNoEscape() && DWARFMangling)
1917+
return appendOperator("XL");
19141918
return appendOperator("XB");
19151919
case AnyFunctionType::Representation::Thin:
19161920
return appendOperator("Xf");

lib/Demangling/Demangler.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2709,6 +2709,8 @@ NodePointer Demangler::demangleSpecialType() {
27092709
return popFunctionType(Node::Kind::AutoClosureType);
27102710
case 'U':
27112711
return popFunctionType(Node::Kind::UncurriedFunctionType);
2712+
case 'L':
2713+
return popFunctionType(Node::Kind::EscapingObjCBlock);
27122714
case 'B':
27132715
return popFunctionType(Node::Kind::ObjCBlock);
27142716
case 'C':

lib/Demangling/NodePrinter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ class NodePrinter {
349349
case Node::Kind::Directness:
350350
case Node::Kind::DynamicAttribute:
351351
case Node::Kind::EscapingAutoClosureType:
352+
case Node::Kind::EscapingObjCBlock:
352353
case Node::Kind::NoEscapeFunctionType:
353354
case Node::Kind::ExplicitClosure:
354355
case Node::Kind::Extension:
@@ -1788,6 +1789,11 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
17881789
printFunctionType(nullptr, Node);
17891790
return nullptr;
17901791
}
1792+
case Node::Kind::EscapingObjCBlock: {
1793+
Printer << "@escaping @convention(block) ";
1794+
printFunctionType(nullptr, Node);
1795+
return nullptr;
1796+
}
17911797
case Node::Kind::SILBoxType: {
17921798
Printer << "@box ";
17931799
NodePointer type = Node->getChild(0);

lib/Demangling/OldRemangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,6 +1129,11 @@ void Remangler::mangleObjCBlock(Node *node) {
11291129
mangleChildNodes(node); // argument tuple, result type
11301130
}
11311131

1132+
void Remangler::mangleEscapingObjCBlock(Node *node) {
1133+
// We shouldn't ever be remangling anything with a DWARF-only mangling.
1134+
Buffer << "<escaping block type>";
1135+
}
1136+
11321137
void Remangler::mangleCFunctionPointer(Node *node) {
11331138
Buffer << 'c';
11341139
mangleChildNodes(node); // argument tuple, result type

lib/Demangling/Remangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1646,6 +1646,11 @@ void Remangler::mangleObjCBlock(Node *node) {
16461646
Buffer << "XB";
16471647
}
16481648

1649+
void Remangler::mangleEscapingObjCBlock(Node *node) {
1650+
mangleChildNodesReversed(node);
1651+
Buffer << "XL";
1652+
}
1653+
16491654
void Remangler::mangleOwningAddressor(Node *node) {
16501655
mangleAbstractStorage(node->getFirstChild(), "lO");
16511656
}

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -761,28 +761,6 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
761761
return Size(size);
762762
}
763763

764-
#ifndef NDEBUG
765-
static bool areTypesReallyEqual(Type lhs, Type rhs) {
766-
// Due to an oversight, escaping and non-escaping @convention(block)
767-
// are mangled identically.
768-
auto eraseEscapingBlock = [](Type t) -> Type {
769-
return t.transform([](Type t) -> Type {
770-
if (auto *fnType = t->getAs<FunctionType>()) {
771-
if (fnType->getExtInfo().getRepresentation()
772-
== FunctionTypeRepresentation::Block) {
773-
return FunctionType::get(fnType->getParams(),
774-
fnType->getResult(),
775-
fnType->getExtInfo().withNoEscape(true));
776-
}
777-
}
778-
return t;
779-
});
780-
};
781-
782-
return eraseEscapingBlock(lhs)->isEqual(eraseEscapingBlock(rhs));
783-
}
784-
#endif
785-
786764
StringRef getMangledName(DebugTypeInfo DbgTy) {
787765
if (DbgTy.IsMetadataType)
788766
return MetadataTypeDeclCache.find(DbgTy.getDecl()->getName().str())
@@ -825,14 +803,12 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
825803
Ty->dump();
826804
abort();
827805
} else if (!Reconstructed->isEqual(Ty)) {
828-
if (!areTypesReallyEqual(Reconstructed, Ty)) {
829-
llvm::errs() << "Incorrect reconstructed type for " << Result << "\n";
830-
llvm::errs() << "Original type:\n";
831-
Ty->dump();
832-
llvm::errs() << "Reconstructed type:\n";
833-
Reconstructed->dump();
834-
abort();
835-
}
806+
llvm::errs() << "Incorrect reconstructed type for " << Result << "\n";
807+
llvm::errs() << "Original type:\n";
808+
Ty->dump();
809+
llvm::errs() << "Reconstructed type:\n";
810+
Reconstructed->dump();
811+
abort();
836812
}
837813
#endif
838814
}

test/TypeDecoder/structural_types.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ do {
126126
blackHole(c)
127127
}
128128

129+
do {
130+
let b: [(@escaping @convention(block) () -> (), @convention(block) () -> ()) -> ()] = []
131+
blackHole(b)
132+
}
133+
129134
// DEMANGLE: $syycD
130135
// DEMANGLE: $sySSzcD
131136
// DEMANGLE: $sySSncD
@@ -143,6 +148,7 @@ do {
143148
// DEMANGLE: $sSi1x_SfSim1ytD
144149
// DEMANGLE: $syyyccD
145150
// DEMANGLE: $sSayyyXCGD
151+
// DEMANGLE: $sSayyyyXL_yyXBtcGD
146152

147153
// CHECK: () -> ()
148154
// CHECK: (inout String) -> ()
@@ -161,6 +167,7 @@ do {
161167
// CHECK: (x: Int, Float, y: Int.Type)
162168
// CHECK: (@escaping () -> ()) -> ()
163169
// CHECK: Array<@convention(c) () -> ()>
170+
// CHECK: Array<(@escaping @convention(block) () -> (), @convention(block) () -> ()) -> ()>
164171

165172
// DEMANGLE: $sSimD
166173
// DEMANGLE: $syycmD
@@ -180,6 +187,7 @@ do {
180187
// DEMANGLE: $sSi1x_SfSim1ytmD
181188
// DEMANGLE: $syyyccmD
182189
// DEMANGLE: $sSayyyXCGmD
190+
// DEMANGLE: $sSayyyyXL_yyXBtcGmD
183191

184192
// CHECK: Int.Type
185193
// CHECK: ((inout String) -> ()).Type
@@ -198,3 +206,4 @@ do {
198206
// CHECK: (x: Int, Float, y: Int.Type).Type
199207
// CHECK: ((@escaping () -> ()) -> ()).Type
200208
// CHECK: Array<@convention(c) () -> ()>.Type
209+
// CHECK: Array<(@escaping @convention(block) () -> (), @convention(block) () -> ()) -> ()>.Type

0 commit comments

Comments
 (0)