Skip to content

Commit 12da08d

Browse files
Merge pull request #14428 from aschwaighofer/mangle_escapeness
Mangling: noescape functions will be trivial and no longer compatible…
2 parents 63fe8c4 + d981bb1 commit 12da08d

File tree

83 files changed

+359
-246
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+359
-246
lines changed

docs/ABI/Mangling.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ Types
350350
type ::= 'Bt' // Builtin.SILToken
351351
type ::= type 'Bv' NATURAL '_' // Builtin.Vec<n>x<type>
352352
type ::= 'Bw' // Builtin.Word
353-
type ::= function-signature 'c' // function type
353+
type ::= function-signature 'c' // function type (escaping)
354354
type ::= function-signature 'X' FUNCTION-KIND // special function type
355355
type ::= bound-generic-type
356356
type ::= type 'Sg' // optional type, shortcut for: type 'ySqG'
@@ -374,9 +374,11 @@ Types
374374

375375
FUNCTION-KIND ::= 'f' // @thin function type
376376
FUNCTION-KIND ::= 'U' // uncurried function type (currently not used)
377-
FUNCTION-KIND ::= 'K' // @auto_closure function type
377+
FUNCTION-KIND ::= 'K' // @auto_closure function type (noescape)
378378
FUNCTION-KIND ::= 'B' // objc block function type
379379
FUNCTION-KIND ::= 'C' // C function pointer type
380+
FUNCTION-KIND ::= 'A' // @auto_closure function type (escaping)
381+
FUNCTION-KIND ::= 'E' // function type (noescape)
380382

381383
function-signature ::= params-type params-type throws? // results and parameters
382384

include/swift/ABI/MetadataValues.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,7 @@ class TargetFunctionTypeFlags {
568568
ConventionShift = 16U,
569569
ThrowsMask = 0x01000000U,
570570
ParamFlagsMask = 0x02000000U,
571+
EscapingMask = 0x04000000U,
571572
};
572573
int_type Data;
573574

@@ -598,6 +599,12 @@ class TargetFunctionTypeFlags {
598599
(hasFlags ? ParamFlagsMask : 0));
599600
}
600601

602+
constexpr TargetFunctionTypeFlags<int_type>
603+
withEscaping(bool isEscaping) const {
604+
return TargetFunctionTypeFlags<int_type>((Data & ~EscapingMask) |
605+
(isEscaping ? EscapingMask : 0));
606+
}
607+
601608
unsigned getNumParameters() const { return Data & NumParametersMask; }
602609

603610
FunctionMetadataConvention getConvention() const {
@@ -608,6 +615,10 @@ class TargetFunctionTypeFlags {
608615
return bool(Data & ThrowsMask);
609616
}
610617

618+
bool isEscaping() const {
619+
return bool (Data & EscapingMask);
620+
}
621+
611622
bool hasParameterFlags() const { return bool(Data & ParamFlagsMask); }
612623

613624
int_type getIntValue() const {

include/swift/Demangling/DemangleNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ NODE(DirectMethodReferenceAttribute)
6363
NODE(DynamicSelf)
6464
CONTEXT_NODE(Enum)
6565
NODE(ErrorType)
66+
NODE(EscapingAutoClosureType)
67+
NODE(NoEscapeFunctionType)
6668
NODE(ExistentialMetatype)
6769
CONTEXT_NODE(ExplicitClosure)
6870
CONTEXT_NODE(Extension)

include/swift/Demangling/ManglingMacros.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,16 @@
3636
#define EMPTY_TUPLE_MANGLING yt
3737
#define NO_ARGS_MANGLING yy
3838
#define FUNC_TYPE_MANGLING c
39+
#define NOESCAPE_FUNC_TYPE_MANGLING XE
3940
#define OBJC_PARTIAL_APPLY_THUNK_MANGLING Ta
4041
#define OPTIONAL_MANGLING(Ty) MANGLING_CONCAT2_IMPL(Ty, Sg)
4142

4243
#define FUNCTION_MANGLING \
4344
MANGLING_CONCAT2(NO_ARGS_MANGLING, FUNC_TYPE_MANGLING)
4445

46+
#define NOESCAPE_FUNCTION_MANGLING \
47+
MANGLING_CONCAT2(NO_ARGS_MANGLING, NOESCAPE_FUNC_TYPE_MANGLING)
48+
4549
#define THIN_FUNCTION_MANGLING \
4650
MANGLING_CONCAT2(NO_ARGS_MANGLING, Xf)
4751

include/swift/Demangling/TypeDecoder.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ class TypeDecoder {
242242
case NodeKind::ObjCBlock:
243243
case NodeKind::CFunctionPointer:
244244
case NodeKind::ThinFunctionType:
245+
case NodeKind::NoEscapeFunctionType:
245246
case NodeKind::FunctionType: {
246247
if (Node->getNumChildren() < 2)
247248
return BuiltType();
@@ -268,8 +269,10 @@ class TypeDecoder {
268269
if (!decodeMangledFunctionInputType(Node->getChild(isThrow ? 1 : 0),
269270
parameters, hasParamFlags))
270271
return BuiltType();
271-
flags = flags.withNumParameters(parameters.size())
272-
.withParameterFlags(hasParamFlags);
272+
flags =
273+
flags.withNumParameters(parameters.size())
274+
.withParameterFlags(hasParamFlags)
275+
.withEscaping(Node->getKind() == NodeKind::FunctionType);
273276

274277
auto result = decodeMangledType(Node->getChild(isThrow ? 2 : 1));
275278
if (!result) return BuiltType();
@@ -306,6 +309,8 @@ class TypeDecoder {
306309
flags =
307310
flags.withConvention(FunctionMetadataConvention::Block);
308311
}
312+
} else if (child->getKind() == NodeKind::ImplEscaping) {
313+
flags = flags.withEscaping(true);
309314
}
310315
}
311316

include/swift/Remote/MetadataReader.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,8 @@ class MetadataReader {
335335
auto flags = FunctionTypeFlags()
336336
.withConvention(Function->getConvention())
337337
.withThrows(Function->throws())
338-
.withParameterFlags(Function->hasParameterFlags());
338+
.withParameterFlags(Function->hasParameterFlags())
339+
.withEscaping(Function->isEscaping());
339340
auto BuiltFunction =
340341
Builder.createFunctionType(Parameters, Result, flags);
341342
TypeCache[MetadataAddress] = BuiltFunction;

include/swift/Runtime/Metadata.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,11 @@ SWIFT_RUNTIME_EXPORT
652652
const ExtraInhabitantsValueWitnessTable
653653
VALUE_WITNESS_SYM(FUNCTION_MANGLING); // () -> ()
654654

655+
// The @escaping () -> () table can be used for arbitrary escaping function types.
656+
SWIFT_RUNTIME_EXPORT
657+
const ExtraInhabitantsValueWitnessTable
658+
VALUE_WITNESS_SYM(NOESCAPE_FUNCTION_MANGLING); // @noescape () -> ()
659+
655660
// The @convention(thin) () -> () table can be used for arbitrary thin function types.
656661
SWIFT_RUNTIME_EXPORT
657662
const ExtraInhabitantsValueWitnessTable
@@ -1645,6 +1650,7 @@ struct TargetFunctionTypeMetadata : public TargetMetadata<Runtime> {
16451650
}
16461651
bool throws() const { return Flags.throws(); }
16471652
bool hasParameterFlags() const { return Flags.hasParameterFlags(); }
1653+
bool isEscaping() const { return Flags.isEscaping(); }
16481654

16491655
static constexpr StoredSize OffsetToFlags = sizeof(TargetMetadata<Runtime>);
16501656

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
5454
/// in source control, you should also update the comment to briefly
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
57-
const uint16_t VERSION_MINOR = 394; // Remove IUO serialization and decl
57+
const uint16_t VERSION_MINOR = 395; // Add escape'ness to function type mangling
5858

5959
using DeclIDField = BCFixed<31>;
6060

lib/AST/ASTMangler.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1624,8 +1624,14 @@ void ASTMangler::appendFunctionType(AnyFunctionType *fn) {
16241624
case AnyFunctionType::Representation::Thin:
16251625
return appendOperator("Xf");
16261626
case AnyFunctionType::Representation::Swift:
1627-
if (fn->isAutoClosure())
1628-
return appendOperator("XK");
1627+
if (fn->isAutoClosure()) {
1628+
if (fn->isNoEscape())
1629+
return appendOperator("XK");
1630+
else
1631+
return appendOperator("XA");
1632+
} else if (fn->isNoEscape()) {
1633+
return appendOperator("XE");
1634+
}
16291635
return appendOperator("c");
16301636

16311637
case AnyFunctionType::Representation::CFunctionPointer:

lib/Demangling/Demangler.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -937,7 +937,8 @@ NodePointer Demangler::popFunctionParamLabels(NodePointer Type) {
937937
if (FuncType->getKind() == Node::Kind::DependentGenericType)
938938
FuncType = FuncType->getChild(1)->getFirstChild();
939939

940-
if (FuncType->getKind() != Node::Kind::FunctionType)
940+
if (FuncType->getKind() != Node::Kind::FunctionType &&
941+
FuncType->getKind() != Node::Kind::NoEscapeFunctionType)
941942
return nullptr;
942943

943944
auto ParameterType = FuncType->getFirstChild();
@@ -1981,6 +1982,10 @@ NodePointer Demangler::demangleWitness() {
19811982

19821983
NodePointer Demangler::demangleSpecialType() {
19831984
switch (auto specialChar = nextChar()) {
1985+
case 'E':
1986+
return popFunctionType(Node::Kind::NoEscapeFunctionType);
1987+
case 'A':
1988+
return popFunctionType(Node::Kind::EscapingAutoClosureType);
19841989
case 'f':
19851990
return popFunctionType(Node::Kind::ThinFunctionType);
19861991
case 'K':

lib/Demangling/NodePrinter.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,8 @@ class NodePrinter {
327327
case Node::Kind::DirectMethodReferenceAttribute:
328328
case Node::Kind::Directness:
329329
case Node::Kind::DynamicAttribute:
330+
case Node::Kind::EscapingAutoClosureType:
331+
case Node::Kind::NoEscapeFunctionType:
330332
case Node::Kind::ExplicitClosure:
331333
case Node::Kind::Extension:
332334
case Node::Kind::FieldOffset:
@@ -854,6 +856,7 @@ static bool needSpaceBeforeType(NodePointer Type) {
854856
case Node::Kind::Type:
855857
return needSpaceBeforeType(Type->getFirstChild());
856858
case Node::Kind::FunctionType:
859+
case Node::Kind::NoEscapeFunctionType:
857860
case Node::Kind::UncurriedFunctionType:
858861
case Node::Kind::DependentGenericType:
859862
return false;
@@ -1039,6 +1042,13 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
10391042
case Node::Kind::Index:
10401043
Printer << Node->getIndex();
10411044
return nullptr;
1045+
case Node::Kind::NoEscapeFunctionType:
1046+
printFunctionType(nullptr, Node);
1047+
return nullptr;
1048+
case Node::Kind::EscapingAutoClosureType:
1049+
Printer << "@autoclosure ";
1050+
printFunctionType(nullptr, Node);
1051+
return nullptr;
10421052
case Node::Kind::AutoClosureType:
10431053
Printer << "@autoclosure ";
10441054
printFunctionType(nullptr, Node);
@@ -2013,6 +2023,7 @@ printEntity(NodePointer Entity, bool asPrefixContext, TypePrinting TypePr,
20132023
while (t->getKind() == Node::Kind::DependentGenericType)
20142024
t = t->getChild(1)->getChild(0);
20152025
if (t->getKind() != Node::Kind::FunctionType &&
2026+
t->getKind() != Node::Kind::NoEscapeFunctionType &&
20162027
t->getKind() != Node::Kind::UncurriedFunctionType &&
20172028
t->getKind() != Node::Kind::CFunctionPointer &&
20182029
t->getKind() != Node::Kind::ThinFunctionType) {

lib/Demangling/OldRemangler.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,8 @@ static NodePointer applyParamLabels(NodePointer LabelList, NodePointer OrigType,
372372
};
373373

374374
auto visitTypeChild = [&](NodePointer Child) -> NodePointer {
375-
if (Child->getKind() != Node::Kind::FunctionType)
375+
if (Child->getKind() != Node::Kind::FunctionType &&
376+
Child->getKind() != Node::Kind::NoEscapeFunctionType)
376377
return Child;
377378

378379
auto FuncType = Factory.createNode(Node::Kind::FunctionType);
@@ -1107,9 +1108,13 @@ void Remangler::mangleEntityType(Node *node, EntityContext &ctx) {
11071108

11081109
// Expand certain kinds of type within the entity context.
11091110
switch (node->getKind()) {
1111+
case Node::Kind::NoEscapeFunctionType:
11101112
case Node::Kind::FunctionType:
11111113
case Node::Kind::UncurriedFunctionType: {
1112-
Out << (node->getKind() == Node::Kind::FunctionType ? 'F' : 'f');
1114+
Out << ((node->getKind() == Node::Kind::FunctionType ||
1115+
node->getKind() == Node::Kind::NoEscapeFunctionType)
1116+
? 'F'
1117+
: 'f');
11131118
unsigned inputIndex = node->getNumChildren() - 2;
11141119
assert(inputIndex <= 1);
11151120
for (unsigned i = 0; i <= inputIndex; ++i)
@@ -1231,6 +1236,16 @@ void Remangler::mangleAutoClosureType(Node *node) {
12311236
mangleChildNodes(node); // argument tuple, result type
12321237
}
12331238

1239+
void Remangler::mangleNoEscapeFunctionType(Node *node) {
1240+
Out << 'F';
1241+
mangleChildNodes(node); // argument tuple, result type
1242+
}
1243+
1244+
void Remangler::mangleEscapingAutoClosureType(Node *node) {
1245+
Out << 'K';
1246+
mangleChildNodes(node); // argument tuple, result type
1247+
}
1248+
12341249
void Remangler::mangleThinFunctionType(Node *node) {
12351250
Out << "Xf";
12361251
mangleChildNodes(node); // argument tuple, result type

lib/Demangling/Remangler.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,16 @@ void Remangler::mangleAutoClosureType(Node *node) {
544544
Buffer << "XK";
545545
}
546546

547+
void Remangler::mangleEscapingAutoClosureType(Node *node) {
548+
mangleChildNodesReversed(node); // argument tuple, result type
549+
Buffer << "XA";
550+
}
551+
552+
void Remangler::mangleNoEscapeFunctionType(Node *node) {
553+
mangleChildNodesReversed(node); // argument tuple, result type
554+
Buffer << "XE";
555+
}
556+
547557
void Remangler::mangleBoundGenericClass(Node *node) {
548558
mangleAnyNominalType(node);
549559
}

lib/IDE/TypeReconstruction.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1372,7 +1372,8 @@ static void VisitNodeFunctionType(
13721372
}
13731373
}
13741374
CreateFunctionType(ast, arg_type_result, return_type_result,
1375-
/*escaping=*/true, throws, result);
1375+
cur_node->getKind() == Demangle::Node::Kind::FunctionType,
1376+
throws, result);
13761377
}
13771378

13781379
static void VisitNodeImplFunctionType(
@@ -2161,6 +2162,7 @@ static void VisitNode(
21612162
break;
21622163

21632164
case Demangle::Node::Kind::FunctionType:
2165+
case Demangle::Node::Kind::NoEscapeFunctionType:
21642166
case Demangle::Node::Kind::UncurriedFunctionType: // Out of order on
21652167
// purpose.
21662168
VisitNodeFunctionType(ast, node, result);

lib/IRGen/GenMeta.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -722,9 +722,11 @@ namespace {
722722

723723
// Map the convention to a runtime metadata value.
724724
FunctionMetadataConvention metadataConvention;
725+
bool isEscaping = false;
725726
switch (type->getRepresentation()) {
726727
case FunctionTypeRepresentation::Swift:
727728
metadataConvention = FunctionMetadataConvention::Swift;
729+
isEscaping = !type->isNoEscape();
728730
break;
729731
case FunctionTypeRepresentation::Thin:
730732
metadataConvention = FunctionMetadataConvention::Thin;
@@ -741,7 +743,8 @@ namespace {
741743
.withNumParameters(numParams)
742744
.withConvention(metadataConvention)
743745
.withThrows(type->throws())
744-
.withParameterFlags(hasFlags);
746+
.withParameterFlags(hasFlags)
747+
.withEscaping(isEscaping);
745748

746749
auto flags = llvm::ConstantInt::get(IGF.IGM.SizeTy,
747750
flagsVal.getIntValue());

lib/RemoteAST/RemoteAST.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,10 @@ class RemoteASTTypeBuilder {
332332

333333
auto einfo = AnyFunctionType::ExtInfo(representation,
334334
/*throws*/ flags.throws());
335+
if (flags.isEscaping())
336+
einfo = einfo.withNoEscape(false);
337+
else
338+
einfo = einfo.withNoEscape(true);
335339

336340
// The result type must be materializable.
337341
if (!output->isMaterializable()) return Type();

stdlib/public/runtime/Demangle.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,10 @@ swift::_swift_buildDemanglingForMetadata(const Metadata *type,
461461
Node::Kind kind;
462462
switch (func->getConvention()) {
463463
case FunctionMetadataConvention::Swift:
464-
kind = Node::Kind::FunctionType;
464+
if (!func->isEscaping())
465+
kind = Node::Kind::NoEscapeFunctionType;
466+
else
467+
kind = Node::Kind::FunctionType;
465468
break;
466469
case FunctionMetadataConvention::Block:
467470
kind = Node::Kind::ObjCBlock;

stdlib/public/runtime/KnownMetadata.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,11 @@ const ExtraInhabitantsValueWitnessTable
137137
swift::VALUE_WITNESS_SYM(FUNCTION_MANGLING) =
138138
ValueWitnessTableForBox<ThickFunctionBox>::table;
139139

140+
/// The basic value-witness table for escaping function types.
141+
const ExtraInhabitantsValueWitnessTable
142+
swift::VALUE_WITNESS_SYM(NOESCAPE_FUNCTION_MANGLING) =
143+
ValueWitnessTableForBox<ThickFunctionBox>::table;
144+
140145
/// The basic value-witness table for thin function types.
141146
const ExtraInhabitantsValueWitnessTable
142147
swift::VALUE_WITNESS_SYM(THIN_FUNCTION_MANGLING) =

stdlib/public/runtime/Metadata.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,11 @@ FunctionCacheEntry::FunctionCacheEntry(const Key &key) {
451451
// so they share a value witness table.
452452
switch (flags.getConvention()) {
453453
case FunctionMetadataConvention::Swift:
454-
Data.ValueWitnesses = &VALUE_WITNESS_SYM(FUNCTION_MANGLING);
454+
if (!flags.isEscaping()) {
455+
Data.ValueWitnesses = &VALUE_WITNESS_SYM(NOESCAPE_FUNCTION_MANGLING);
456+
} else {
457+
Data.ValueWitnesses = &VALUE_WITNESS_SYM(FUNCTION_MANGLING);
458+
}
455459
break;
456460

457461
case FunctionMetadataConvention::Thin:

test/Constraints/rdar35142121.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ func foo(_ a: (Int) -> (Int)) -> Int {
88
return 42
99
}
1010

11-
// CHECK: function_ref @$S12rdar351421213fooyS3icF : $@convention(thin) (@owned @noescape @callee_guaranteed (Int) -> Int) -> Int
11+
// CHECK: function_ref @$S12rdar351421213fooyS3iXEF : $@convention(thin) (@owned @noescape @callee_guaranteed (Int) -> Int) -> Int
1212
let _ = foo({ (a: Int) -> Int in a + 1 })

test/DebugInfo/capturelist.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ class C {
33
func withClosure(_ : () -> ()) -> () {}
44

55
func f() {
6-
// CHECK: define{{.*}}$S11capturelist1CC1fyyFyycfU_
6+
// CHECK: define{{.*}}$S11capturelist1CC1fyyFyyXEfU_
77
// There should not be a local weak variable "self" shadowing the
88
// implicit self argument.
99
// let self

test/DebugInfo/closure.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ func foldl1<T>(_ list: [T], _ function: (_ a: T, _ b: T) -> T) -> T {
1414
var a = [Int64](repeating: 0, count: 10)
1515
for i in 0..<10 { a[i] = Int64(i) }
1616
// A closure is not an artificial function (the last i32 0).
17-
// CHECK: !DISubprogram({{.*}}linkageName: "$S7closures5Int64VAC_ACtcfU_",{{.*}} line: 20,{{.*}} scopeLine: 20,
17+
// CHECK: !DISubprogram({{.*}}linkageName: "$S7closures5Int64VAC_ACtXEfU_",{{.*}} line: 20,{{.*}} scopeLine: 20,
1818
// CHECK: !DILocalVariable(name: "$0", arg: 1{{.*}} line: [[@LINE+2]],
1919
// CHECK: !DILocalVariable(name: "$1", arg: 2{{.*}} line: [[@LINE+1]],
2020
var sum:Int64 = foldl1(a, { $0 + $1 })

0 commit comments

Comments
 (0)