Skip to content

Commit bc3a2b5

Browse files
committed
ASTDemangler: Fix round-tripping of SILBoxTypeWithLayout
The more awkward setup with pushGenericParams()/popGenericParams() is required so that when demangling requirements and field types we get the correct pack-ness for each type parameter. The pack-ness is encoded as part of the generic signature, and not as part of the type parameter mangling itself. Fixes the ASTDemangler issue from rdar://problem/115459973.
1 parent 8b80ab7 commit bc3a2b5

File tree

6 files changed

+129
-70
lines changed

6 files changed

+129
-70
lines changed

include/swift/AST/ASTDemangler.h

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,14 @@ class ASTBuilder {
5959
/// Created lazily.
6060
DeclContext *NotionalDC = nullptr;
6161

62-
/// The generic signature for interpreting type parameters. This is used
63-
/// because the mangling for a type parameter doesn't record whether it
64-
/// is a pack or not, so we have to find it here.
65-
GenericSignature GenericSig;
62+
/// The depth and index of each parameter pack in the current generic
63+
/// signature. We need this because the mangling for a type parameter
64+
/// doesn't record whether it is a pack or not; we find the correct
65+
/// depth and index in this array, and use its pack-ness.
66+
llvm::SmallVector<std::pair<unsigned, unsigned>, 2> ParameterPacks;
67+
68+
/// For saving and restoring generic parameters.
69+
llvm::SmallVector<decltype(ParameterPacks), 2> ParameterPackStack;
6670

6771
/// This builder doesn't perform "on the fly" substitutions, so we preserve
6872
/// all pack expansions. We still need an active expansion stack though,
@@ -71,7 +75,7 @@ class ASTBuilder {
7175
/// - advancePackExpansion()
7276
/// - createExpandedPackElement()
7377
/// - endPackExpansion()
74-
llvm::SmallVector<Type> ActivePackExpansions;
78+
llvm::SmallVector<Type, 2> ActivePackExpansions;
7579

7680
public:
7781
using BuiltType = swift::Type;
@@ -84,7 +88,12 @@ class ASTBuilder {
8488
static constexpr bool needsToPrecomputeParentGenericContextShapes = false;
8589

8690
explicit ASTBuilder(ASTContext &ctx, GenericSignature genericSig)
87-
: Ctx(ctx), GenericSig(genericSig) {}
91+
: Ctx(ctx) {
92+
for (auto *paramTy : genericSig.getGenericParams()) {
93+
if (paramTy->isParameterPack())
94+
ParameterPacks.emplace_back(paramTy->getDepth(), paramTy->getIndex());
95+
}
96+
}
8897

8998
ASTContext &getASTContext() { return Ctx; }
9099
DeclContext *getNotionalDC();
@@ -165,6 +174,9 @@ class ASTBuilder {
165174
Type instance,
166175
llvm::Optional<Demangle::ImplMetatypeRepresentation> repr = llvm::None);
167176

177+
void pushGenericParams(ArrayRef<std::pair<unsigned, unsigned>> parameterPacks);
178+
void popGenericParams();
179+
168180
Type createGenericTypeParameterType(unsigned depth, unsigned index);
169181

170182
Type createDependentMemberType(StringRef member, Type base);

include/swift/Demangling/TypeDecoder.h

Lines changed: 60 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,8 @@ void decodeRequirement(NodePointer node,
376376
llvm::SmallVectorImpl<BuiltRequirement> &requirements,
377377
BuilderType &Builder) {
378378
for (auto &child : *node) {
379-
if (child->getKind() == Demangle::Node::Kind::DependentGenericParamCount)
379+
if (child->getKind() == Demangle::Node::Kind::DependentGenericParamCount ||
380+
child->getKind() == Demangle::Node::Kind::DependentGenericParamPackMarker)
380381
continue;
381382

382383
if (child->getNumChildren() != 2)
@@ -1180,28 +1181,12 @@ class TypeDecoder {
11801181
llvm::SmallVector<Field, 4> fields;
11811182
llvm::SmallVector<BuiltSubstitution, 4> substitutions;
11821183
llvm::SmallVector<BuiltRequirement, 4> requirements;
1184+
llvm::SmallVector<BuiltType, 4> genericParams;
11831185

11841186
if (Node->getNumChildren() < 1)
11851187
return MAKE_NODE_TYPE_ERROR0(Node, "no children");
11861188

1187-
auto fieldsNode = Node->getChild(0);
1188-
if (fieldsNode->getKind() != NodeKind::SILBoxLayout)
1189-
return MAKE_NODE_TYPE_ERROR0(fieldsNode, "expected layout");
1190-
for (auto *fieldNode : *fieldsNode) {
1191-
bool isMutable;
1192-
switch (fieldNode->getKind()) {
1193-
case NodeKind::SILBoxMutableField: isMutable = true; break;
1194-
case NodeKind::SILBoxImmutableField: isMutable = false; break;
1195-
default:
1196-
return MAKE_NODE_TYPE_ERROR0(fieldNode, "unhandled field type");
1197-
}
1198-
if (fieldNode->getNumChildren() < 1)
1199-
return MAKE_NODE_TYPE_ERROR0(fieldNode, "no children");
1200-
auto type = decodeMangledType(fieldNode->getChild(0), depth + 1);
1201-
if (type.isError())
1202-
return type;
1203-
fields.emplace_back(type.getType(), isMutable);
1204-
}
1189+
bool pushedGenericParams = false;
12051190

12061191
if (Node->getNumChildren() > 1) {
12071192
auto *substNode = Node->getChild(2);
@@ -1218,47 +1203,76 @@ class TypeDecoder {
12181203
dependentGenericSignatureNode,
12191204
"fewer children (%zu) than required (1)",
12201205
dependentGenericSignatureNode->getNumChildren());
1221-
decodeRequirement<BuiltType, BuiltRequirement, BuiltLayoutConstraint,
1222-
BuilderType>(dependentGenericSignatureNode,
1223-
requirements,
1224-
Builder /*,
1225-
[&](NodePointer Node) -> BuiltType {
1226-
return decodeMangledType(Node, depth + 1).getType();
1227-
},
1228-
[&](LayoutConstraintKind Kind) -> BuiltLayoutConstraint {
1229-
return {}; // Not implemented!
1230-
},
1231-
[&](LayoutConstraintKind Kind, unsigned SizeInBits,
1232-
unsigned Alignment) -> BuiltLayoutConstraint {
1233-
return {}; // Not Implemented!
1234-
}*/);
1206+
12351207
// The number of generic parameters at each depth are in a mini
12361208
// state machine and come first.
12371209
llvm::SmallVector<unsigned, 4> genericParamsAtDepth;
12381210
for (auto *reqNode : *dependentGenericSignatureNode)
12391211
if (reqNode->getKind() == NodeKind::DependentGenericParamCount)
12401212
if (reqNode->hasIndex())
12411213
genericParamsAtDepth.push_back(reqNode->getIndex());
1242-
unsigned paramDepth = 0;
1243-
unsigned index = 0;
1244-
for (auto *subst : *substNode) {
1245-
if (paramDepth >= genericParamsAtDepth.size())
1246-
return MAKE_NODE_TYPE_ERROR0(
1247-
dependentGenericSignatureNode,
1248-
"more substitutions than generic params");
1249-
while (index >= genericParamsAtDepth[paramDepth])
1250-
++paramDepth, index = 0;
1214+
1215+
llvm::SmallVector<std::pair<unsigned, unsigned>> parameterPacks;
1216+
for (auto &child : *dependentGenericSignatureNode) {
1217+
if (child->getKind() == Demangle::Node::Kind::DependentGenericParamPackMarker) {
1218+
auto *marker = child->getChild(0)->getChild(0);
1219+
parameterPacks.emplace_back(marker->getChild(0)->getIndex(),
1220+
marker->getChild(1)->getIndex());
1221+
}
1222+
}
1223+
1224+
Builder.pushGenericParams(parameterPacks);
1225+
pushedGenericParams = true;
1226+
1227+
// Decode generic parameter types.
1228+
for (unsigned d = 0; d < genericParamsAtDepth.size(); ++d) {
1229+
for (unsigned i = 0; i < genericParamsAtDepth[d]; ++i) {
1230+
auto paramTy = Builder.createGenericTypeParameterType(d, i);
1231+
genericParams.push_back(paramTy);
1232+
}
1233+
}
1234+
1235+
// Decode requirements.
1236+
decodeRequirement<BuiltType, BuiltRequirement, BuiltLayoutConstraint,
1237+
BuilderType>(dependentGenericSignatureNode,
1238+
requirements,
1239+
Builder);
1240+
1241+
// Decode substitutions.
1242+
for (unsigned i = 0, e = substNode->getNumChildren(); i < e; ++i) {
1243+
auto *subst = substNode->getChild(i);
12511244
auto substTy = decodeMangledType(subst, depth + 1,
12521245
/*forRequirement=*/false);
12531246
if (substTy.isError())
12541247
return substTy;
1255-
auto paramTy = Builder.createGenericTypeParameterType(
1256-
paramDepth, index);
1257-
substitutions.emplace_back(paramTy, substTy.getType());
1258-
++index;
1248+
substitutions.emplace_back(genericParams[i], substTy.getType());
12591249
}
12601250
}
12611251

1252+
// Decode field types.
1253+
auto fieldsNode = Node->getChild(0);
1254+
if (fieldsNode->getKind() != NodeKind::SILBoxLayout)
1255+
return MAKE_NODE_TYPE_ERROR0(fieldsNode, "expected layout");
1256+
for (auto *fieldNode : *fieldsNode) {
1257+
bool isMutable;
1258+
switch (fieldNode->getKind()) {
1259+
case NodeKind::SILBoxMutableField: isMutable = true; break;
1260+
case NodeKind::SILBoxImmutableField: isMutable = false; break;
1261+
default:
1262+
return MAKE_NODE_TYPE_ERROR0(fieldNode, "unhandled field type");
1263+
}
1264+
if (fieldNode->getNumChildren() < 1)
1265+
return MAKE_NODE_TYPE_ERROR0(fieldNode, "no children");
1266+
auto type = decodeMangledType(fieldNode->getChild(0), depth + 1);
1267+
if (type.isError())
1268+
return type;
1269+
fields.emplace_back(type.getType(), isMutable);
1270+
}
1271+
1272+
if (pushedGenericParams) {
1273+
Builder.popGenericParams();
1274+
}
1275+
12621276
return Builder.createSILBoxTypeWithLayout(fields, substitutions,
12631277
requirements);
12641278
}

include/swift/RemoteInspection/TypeRefBuilder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,8 +910,12 @@ class TypeRefBuilder {
910910
return MetatypeTypeRef::create(*this, instance, WasAbstract);
911911
}
912912

913+
void pushGenericParams(llvm::ArrayRef<std::pair<unsigned, unsigned>> parameterPacks) {}
914+
void popGenericParams() {}
915+
913916
const GenericTypeParameterTypeRef *
914917
createGenericTypeParameterType(unsigned depth, unsigned index) {
918+
// FIXME: variadic generics
915919
return GenericTypeParameterTypeRef::create(*this, depth, index);
916920
}
917921

lib/AST/ASTDemangler.cpp

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "swift/AST/Type.h"
3232
#include "swift/AST/TypeCheckRequests.h"
3333
#include "swift/AST/Types.h"
34+
#include "swift/Basic/Defer.h"
3435
#include "swift/Demangling/Demangler.h"
3536
#include "swift/Demangling/ManglingMacros.h"
3637
#include "llvm/ADT/StringSwitch.h"
@@ -731,23 +732,28 @@ Type ASTBuilder::createMetatypeType(
731732
return MetatypeType::get(instance, getMetatypeRepresentation(*repr));
732733
}
733734

735+
void ASTBuilder::pushGenericParams(ArrayRef<std::pair<unsigned, unsigned>> parameterPacks) {
736+
ParameterPackStack.push_back(ParameterPacks);
737+
ParameterPacks.clear();
738+
ParameterPacks.append(parameterPacks.begin(), parameterPacks.end());
739+
}
740+
741+
void ASTBuilder::popGenericParams() {
742+
ParameterPacks = ParameterPackStack.back();
743+
ParameterPackStack.pop_back();
744+
}
745+
734746
Type ASTBuilder::createGenericTypeParameterType(unsigned depth,
735747
unsigned index) {
736-
// If we have a generic signature, find the parameter with the matching
737-
// depth and index and return it, to get the correct value for the
738-
// isParameterPack() bit.
739-
if (GenericSig) {
740-
for (auto paramTy : GenericSig.getGenericParams()) {
741-
if (paramTy->getDepth() == depth && paramTy->getIndex() == index) {
742-
return paramTy;
748+
if (!ParameterPacks.empty()) {
749+
for (auto pair : ParameterPacks) {
750+
if (pair.first == depth && pair.second == index) {
751+
return GenericTypeParamType::get(/*isParameterPack*/ true,
752+
depth, index, Ctx);
743753
}
744754
}
745-
746-
return Type();
747755
}
748756

749-
// Otherwise, just assume we're not working with variadic generics.
750-
// FIXME: Should we always require a generic signature in this case?
751757
return GenericTypeParamType::get(/*isParameterPack*/ false,
752758
depth, index, Ctx);
753759
}
@@ -1039,15 +1045,25 @@ LayoutConstraint ASTBuilder::getLayoutConstraintWithSizeAlign(
10391045
CanGenericSignature ASTBuilder::demangleGenericSignature(
10401046
NominalTypeDecl *nominalDecl,
10411047
NodePointer node) {
1042-
llvm::SaveAndRestore<GenericSignature> savedSignature(
1043-
GenericSig, nominalDecl->getGenericSignature());
1048+
auto baseGenericSig = nominalDecl->getGenericSignature();
1049+
1050+
// The generic signature is for a constrained extension of nominalDecl, so
1051+
// we introduce the parameter packs from the nominal's generic signature.
1052+
ParameterPackStack.push_back(ParameterPacks);
1053+
ParameterPacks.clear();
1054+
for (auto *paramTy : baseGenericSig.getGenericParams()) {
1055+
if (paramTy->isParameterPack())
1056+
ParameterPacks.emplace_back(paramTy->getDepth(), paramTy->getIndex());
1057+
}
1058+
SWIFT_DEFER { popGenericParams(); };
10441059

1060+
// Constrained extensions mangle the subset of requirements not satisfied
1061+
// by the nominal's generic signature.
10451062
SmallVector<Requirement, 2> requirements;
1046-
10471063
decodeRequirement<BuiltType, BuiltRequirement, BuiltLayoutConstraint,
10481064
ASTBuilder>(node, requirements, *this);
1049-
return buildGenericSignature(Ctx, nominalDecl->getGenericSignature(),
1050-
{}, std::move(requirements))
1065+
1066+
return buildGenericSignature(Ctx, baseGenericSig, {}, std::move(requirements))
10511067
.getCanonicalSignature();
10521068
}
10531069

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1869,6 +1869,9 @@ class DecodedMetadataBuilder {
18691869
return BuiltType();
18701870
}
18711871

1872+
void pushGenericParams(llvm::ArrayRef<std::pair<unsigned, unsigned>> parameterPacks) {}
1873+
void popGenericParams() {}
1874+
18721875
BuiltType
18731876
createGenericTypeParameterType(unsigned depth, unsigned index) const {
18741877
// Use the callback, when provided.
Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
1-
// RUN: %target-swift-frontend -emit-ir %s -g | %FileCheck %s
1+
// RUN: %target-swift-frontend -emit-ir %s -g -module-name closure | %FileCheck %s
22

3-
// CHECK: !{{[0-9]+}} = !DICompositeType(tag: DW_TAG_structure_type, name: "$sxxQp_QSiIgp_D", {{.*}})
3+
// CHECK-DAG: !{{[0-9]+}} = !DICompositeType(tag: DW_TAG_structure_type, name: "$sxxQp_QSiIgp_D", {{.*}})
44
public func f<each Input>(builder: (repeat each Input) -> ()) {}
5+
6+
public protocol P {
7+
func f() -> Self
8+
}
9+
10+
// CHECK-DAG: !{{[0-9]+}} = !DICompositeType(tag: DW_TAG_structure_type, name: "$sxxQp_tz_xxQp_QP_Rvz7closure1PRzlXXD", {{.*}})
11+
public func foo<each T: P>(t: repeat each T) -> () -> () {
12+
var x = (repeat each t)
13+
return { x = (repeat (each x).f()) }
14+
}

0 commit comments

Comments
 (0)