Skip to content

More variadic generics mangling changes #63911

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -887,8 +887,10 @@ now codified into the ABI; the index 0 is therefore reserved.

::

generic-signature ::= requirement* 'l' // one generic parameter
generic-signature ::= requirement* 'r' GENERIC-PARAM-COUNT* 'l'
generic-signature ::= requirement* generic-param-pack-marker* 'l' // one generic parameter
generic-signature ::= requirement* generic-param-pack-marker* 'r' GENERIC-PARAM-COUNT* 'l'

generic-param-pack-marker ::= 'Rv' GENERIC_PARAM-INDEX // generic parameter pack marker

GENERIC-PARAM-COUNT ::= 'z' // zero parameters
GENERIC-PARAM-COUNT ::= INDEX // N+1 parameters
Expand Down Expand Up @@ -931,9 +933,11 @@ now codified into the ABI; the index 0 is therefore reserved.
LAYOUT-SIZE ::= INDEX // Size only
LAYOUT-SIZE-AND-ALIGNMENT ::= INDEX INDEX // Size followed by alignment

A generic signature begins with an optional list of requirements.

This is followed by an optional list of generic-param-pack-markers to record
which generic parameters are packs (variadic).

A generic signature begins with an optional list of requirements.
The ``<GENERIC-PARAM-COUNT>`` describes the number of generic parameters at
each depth of the signature. As a special case, no ``<GENERIC-PARAM-COUNT>``
values indicates a single generic parameter at the outermost depth::
Expand Down
1 change: 1 addition & 0 deletions include/swift/Demangling/DemangleNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ NODE(DependentGenericParamType)
NODE(DependentGenericSameTypeRequirement)
NODE(DependentGenericSameShapeRequirement)
NODE(DependentGenericLayoutRequirement)
NODE(DependentGenericParamPackMarker)
NODE(DependentGenericSignature)
NODE(DependentGenericType)
NODE(DependentMemberType)
Expand Down
6 changes: 1 addition & 5 deletions lib/AST/ASTDemangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1011,12 +1011,8 @@ LayoutConstraint ASTBuilder::getLayoutConstraintWithSizeAlign(
CanGenericSignature ASTBuilder::demangleGenericSignature(
NominalTypeDecl *nominalDecl,
NodePointer node) {
// The type parameters appearing in the signature's requirements are not
// notionally part of our current generic signature.
//
// FIXME: Fix this to support variadic generics.
llvm::SaveAndRestore<GenericSignature> savedSignature(
GenericSig, GenericSignature());
GenericSig, nominalDecl->getGenericSignature());

SmallVector<Requirement, 2> requirements;

Expand Down
10 changes: 8 additions & 2 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2979,7 +2979,7 @@ void ASTMangler::appendRequirement(const Requirement &reqt,
if (tryMangleTypeSubstitution(DT, sig)) {
switch (reqt.getKind()) {
case RequirementKind::SameShape:
llvm_unreachable("Same-shape requirement not supported here");
llvm_unreachable("Same-shape requirement with dependent member type?");
case RequirementKind::Conformance:
return appendOperator("RQ");
case RequirementKind::Layout:
Expand Down Expand Up @@ -3038,14 +3038,20 @@ void ASTMangler::appendRequirement(const Requirement &reqt,

void ASTMangler::appendGenericSignatureParts(
GenericSignature sig,
ArrayRef<CanTypeWrapper<GenericTypeParamType>> params,
ArrayRef<CanGenericTypeParamType> params,
unsigned initialParamDepth,
ArrayRef<Requirement> requirements) {
// Mangle the requirements.
for (const Requirement &reqt : requirements) {
appendRequirement(reqt, sig);
}

// Mangle which generic parameters are pack parameters.
for (auto param : params) {
if (param->isParameterPack())
appendOpWithGenericParamIndex("Rv", param);
}

if (params.size() == 1 && params[0]->getDepth() == initialParamDepth)
return appendOperator("l");

Expand Down
9 changes: 7 additions & 2 deletions lib/Demangling/Demangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ static bool isEntity(Node::Kind kind) {

static bool isRequirement(Node::Kind kind) {
switch (kind) {
case Node::Kind::DependentGenericParamPackMarker:
case Node::Kind::DependentGenericSameTypeRequirement:
case Node::Kind::DependentGenericSameShapeRequirement:
case Node::Kind::DependentGenericLayoutRequirement:
Expand Down Expand Up @@ -3788,11 +3789,12 @@ NodePointer Demangler::demangleGenericSignature(bool hasParamCounts) {
}

NodePointer Demangler::demangleGenericRequirement() {

enum { Generic, Assoc, CompoundAssoc, Substitution } TypeKind;
enum { Protocol, BaseClass, SameType, SameShape, Layout } ConstraintKind;
enum { Protocol, BaseClass, SameType, SameShape, Layout, PackMarker } ConstraintKind;

switch (nextChar()) {
case 'v': ConstraintKind = PackMarker; TypeKind = Generic; break;
case 'c': ConstraintKind = BaseClass; TypeKind = Assoc; break;
case 'C': ConstraintKind = BaseClass; TypeKind = CompoundAssoc; break;
case 'b': ConstraintKind = BaseClass; TypeKind = Generic; break;
Expand Down Expand Up @@ -3832,6 +3834,9 @@ NodePointer Demangler::demangleGenericRequirement() {
}

switch (ConstraintKind) {
case PackMarker:
return createWithChild(
Node::Kind::DependentGenericParamPackMarker, ConstrTy);
case Protocol:
return createWithChildren(
Node::Kind::DependentGenericConformanceRequirement, ConstrTy,
Expand Down
129 changes: 89 additions & 40 deletions lib/Demangling/NodePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ class NodePrinter {
case Node::Kind::DefaultAssociatedConformanceAccessor:
case Node::Kind::DependentAssociatedTypeRef:
case Node::Kind::DependentGenericSignature:
case Node::Kind::DependentGenericParamPackMarker:
case Node::Kind::DependentGenericParamCount:
case Node::Kind::DependentGenericConformanceRequirement:
case Node::Kind::DependentGenericLayoutRequirement:
Expand Down Expand Up @@ -982,6 +983,92 @@ class NodePrinter {
}
}

void printGenericSignature(NodePointer Node, unsigned depth) {
Printer << '<';

unsigned numChildren = Node->getNumChildren();

unsigned numGenericParams = 0;
for (; numGenericParams < numChildren; ++numGenericParams) {
if (Node->getChild(numGenericParams)->getKind()
!= Node::Kind::DependentGenericParamCount) {
break;
}
}

unsigned firstRequirement = numGenericParams;
for (; firstRequirement < numChildren; ++firstRequirement) {
auto child = Node->getChild(firstRequirement);
if (child->getKind() == Node::Kind::Type)
child = child->getChild(0);
if (child->getKind() != Node::Kind::DependentGenericParamPackMarker) {
break;
}
}

auto isGenericParamPack = [&](unsigned depth, unsigned index) {
for (unsigned i = numGenericParams; i < firstRequirement; ++i) {
auto child = Node->getChild(i);
if (child->getKind() != Node::Kind::DependentGenericParamPackMarker)
continue;
child = child->getChild(0);

if (child->getKind() != Node::Kind::Type)
continue;

child = child->getChild(0);
if (child->getKind() != Node::Kind::DependentGenericParamType)
continue;

if (index == child->getChild(0)->getIndex() &&
depth == child->getChild(1)->getIndex()) {
return true;
}
}

return false;
};

unsigned gpDepth = 0;
for (; gpDepth < numGenericParams; ++gpDepth) {
if (gpDepth != 0)
Printer << "><";

unsigned count = Node->getChild(gpDepth)->getIndex();
for (unsigned index = 0; index < count; ++index) {
if (index != 0)
Printer << ", ";

// Limit the number of printed generic parameters. In practice this
// it will never be exceeded. The limit is only important for malformed
// symbols where count can be really huge.
if (index >= 128) {
Printer << "...";
break;
}

if (isGenericParamPack(gpDepth, index))
Printer << "each ";

// FIXME: Depth won't match when a generic signature applies to a
// method in generic type context.
Printer << Options.GenericParameterName(gpDepth, index);
}
}

if (firstRequirement != numChildren) {
if (Options.DisplayWhereClauses) {
Printer << " where ";
for (unsigned i = firstRequirement; i < numChildren; ++i) {
if (i > firstRequirement)
Printer << ", ";
print(Node->getChild(i), depth + 1);
}
}
}
Printer << '>';
}

void printFunctionSigSpecializationParams(NodePointer Node, unsigned depth);

void printSpecializationPrefix(NodePointer node, StringRef Description,
Expand Down Expand Up @@ -2634,49 +2721,11 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,

case Node::Kind::DependentPseudogenericSignature:
case Node::Kind::DependentGenericSignature: {
Printer << '<';

unsigned depth = 0;
unsigned numChildren = Node->getNumChildren();
for (;
depth < numChildren
&& Node->getChild(depth)->getKind()
== Node::Kind::DependentGenericParamCount;
++depth) {
if (depth != 0)
Printer << "><";

unsigned count = Node->getChild(depth)->getIndex();
for (unsigned index = 0; index < count; ++index) {
if (index != 0)
Printer << ", ";
// Limit the number of printed generic parameters. In practice this
// it will never be exceeded. The limit is only important for malformed
// symbols where count can be really huge.
if (index >= 128) {
Printer << "...";
break;
}
// FIXME: Depth won't match when a generic signature applies to a
// method in generic type context.
Printer << Options.GenericParameterName(depth, index);
}
}

if (depth != numChildren) {
if (Options.DisplayWhereClauses) {
Printer << " where ";
for (unsigned i = depth; i < numChildren; ++i) {
if (i > depth)
Printer << ", ";
print(Node->getChild(i), depth + 1);
}
}
}
Printer << '>';
printGenericSignature(Node, depth);
return nullptr;
}
case Node::Kind::DependentGenericParamCount:
case Node::Kind::DependentGenericParamPackMarker:
printer_unreachable("should be printed as a child of a "
"DependentGenericSignature");
case Node::Kind::DependentGenericConformanceRequirement: {
Expand Down
5 changes: 5 additions & 0 deletions lib/Demangling/OldRemangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1941,6 +1941,11 @@ ManglingError Remangler::mangleDependentPseudogenericSignature(Node *node,
return mangleDependentGenericSignature(node, depth + 1);
}

ManglingError Remangler::mangleDependentGenericParamPackMarker(Node *node,
unsigned depth) {
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}

ManglingError Remangler::mangleDependentGenericSignature(Node *node,
unsigned depth) {
auto i = node->begin(), e = node->end();
Expand Down
9 changes: 9 additions & 0 deletions lib/Demangling/Remangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,15 @@ ManglingError Remangler::mangleDependentGenericSignature(Node *node,
return ManglingError::Success;
}

ManglingError Remangler::mangleDependentGenericParamPackMarker(Node *node,
unsigned depth) {
DEMANGLER_ASSERT(node->getNumChildren() == 1, node);
DEMANGLER_ASSERT(node->getChild(0)->getKind() == Node::Kind::Type, node);
Buffer << "Rv";
mangleDependentGenericParamIndex(node->getChild(0)->getChild(0));
return ManglingError::Success;
}

ManglingError Remangler::mangleDependentGenericType(Node *node,
unsigned depth) {
RETURN_IF_ERROR(
Expand Down
2 changes: 2 additions & 0 deletions lib/IRGen/GenPack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ llvm::Value *IRGenFunction::emitPackShapeExpression(CanType type) {
if (pair.first > 0) {
auto *constant = llvm::ConstantInt::get(IGM.SizeTy, pair.first);
accumulateSum(*this, pair.second, constant);
} else if (pair.second == nullptr) {
pair.second = llvm::ConstantInt::get(IGM.SizeTy, 0);
}

setScopedLocalTypeData(type, kind, pair.second);
Expand Down
12 changes: 12 additions & 0 deletions lib/SILGen/SILGenLazyConformance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@

#include "SILGen.h"
#include "swift/AST/Decl.h"
#include "swift/AST/PackConformance.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/ProtocolConformanceRef.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILVisitor.h"
Expand All @@ -31,6 +33,16 @@ void SILGenModule::useConformance(ProtocolConformanceRef conformanceRef) {
if (conformanceRef.isAbstract())
return;

// Recursively visit pack conformances.
if (conformanceRef.isPack()) {
auto *packConformance = conformanceRef.getPack();

for (auto patternConformanceRef : packConformance->getPatternConformances())
useConformance(patternConformanceRef);

return;
}

auto conformance = conformanceRef.getConcrete();

// Always look through inherited conformances.
Expand Down
8 changes: 4 additions & 4 deletions test/DebugInfo/variadic-generics-count.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
// REQUIRES: asserts

public func f1<T...>(ts: repeat each T) {
// CHECK: define {{.*}} @"$s1a2f12tsyxxQp_tlF"(%swift.opaque** {{.*}}, i{{32|64}} [[COUNT1_1:.*]], %swift.type** {{.*}})
// CHECK: define {{.*}} @"$s1a2f12tsyxxQp_tRvzlF"(%swift.opaque** {{.*}}, i{{32|64}} [[COUNT1_1:.*]], %swift.type** {{.*}})
// CHECK-DAG: store i{{32|64}} [[COUNT1_1]], i{{32|64}}* %[[COUNT1_1_A:.*]], align
// CHECK-DAG: call void @llvm.dbg.declare({{.*}}[[COUNT1_1_A]], metadata ![[COUNT1_1_VAR:[0-9]+]], metadata !DIExpression())
// CHECK-LABEL: ret void
}

public func f2<U..., V...>(us: repeat each U, vs: repeat each V) {
// CHECK: define {{.*}} @"$s1a2f22us2vsyxxQp_q_q_Qptr0_lF"(%swift.opaque** {{.*}}, %swift.opaque** {{.*}}, i{{32|64}} [[COUNT2_1:.*]], i{{32|64}} [[COUNT2_2:.*]], %swift.type** {{.*}}, %swift.type** {{.*}})
// CHECK: define {{.*}} @"$s1a2f22us2vsyxxQp_q_q_QptRvzRv_r0_lF"(%swift.opaque** {{.*}}, %swift.opaque** {{.*}}, i{{32|64}} [[COUNT2_1:.*]], i{{32|64}} [[COUNT2_2:.*]], %swift.type** {{.*}}, %swift.type** {{.*}})
// CHECK-DAG: store i{{32|64}} [[COUNT2_1]], i{{32|64}}* %[[COUNT2_1_A:.*]], align
// CHECK-DAG: store i{{32|64}} [[COUNT2_2]], i{{32|64}}* %[[COUNT2_2_A:.*]], align
// CHECK-DAG: call void @llvm.dbg.declare({{.*}}[[COUNT2_1_A]], metadata ![[COUNT2_1_VAR:[0-9]+]], metadata !DIExpression())
Expand All @@ -22,14 +22,14 @@ public func f2<U..., V...>(us: repeat each U, vs: repeat each V) {
}

public func f3<T...>(ts: repeat each T, more_ts: repeat each T) {
// CHECK: define {{.*}} @"$s1a2f32ts05more_B0yxxQp_xxQptlF"(%swift.opaque** {{.*}}, %swift.opaque** {{.*}}, i{{32|64}} [[COUNT3_1:.*]], %swift.type** {{.*}})
// CHECK: define {{.*}} @"$s1a2f32ts05more_B0yxxQp_xxQptRvzlF"(%swift.opaque** {{.*}}, %swift.opaque** {{.*}}, i{{32|64}} [[COUNT3_1:.*]], %swift.type** {{.*}})
// CHECK-DAG: store i{{32|64}} [[COUNT3_1]], i{{32|64}}* %[[COUNT3_1_A:.*]], align
// CHECK-DAG: call void @llvm.dbg.declare({{.*}}[[COUNT3_1_A]], metadata ![[COUNT3_1_VAR:[0-9]+]], metadata !DIExpression())
// CHECK-LABEL: ret void
}

public func f4<U..., V...>(us: repeat (each U, each V)) {
// CHECK: define {{.*}} @"$s1a2f42usyx_q_txQp_tq_Rhzr0_lF"(%swift.opaque** {{.*}}, i{{32|64}} [[COUNT4_1:.*]], %swift.type** {{.*}}, %swift.type** {{.*}})
// CHECK: define {{.*}} @"$s1a2f42usyx_q_txQp_tq_RhzRvzRv_r0_lF"(%swift.opaque** {{.*}}, i{{32|64}} [[COUNT4_1:.*]], %swift.type** {{.*}}, %swift.type** {{.*}})
// CHECK-DAG: store i{{32|64}} [[COUNT4_1]], i{{32|64}}* %[[COUNT4_1_A:.*]], align
// CHECK-DAG: call void @llvm.dbg.declare({{.*}}[[COUNT4_1_A]], metadata ![[COUNT4_1_VAR:[0-9]+]], metadata !DIExpression())
// CHECK-LABEL: ret void
Expand Down
2 changes: 1 addition & 1 deletion test/DebugInfo/variadic-generics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// REQUIRES: asserts

public func foo<T...>(args: repeat each T) {
// CHECK: define {{.*}} @"$s1a3foo4argsyxxQp_tlF"
// CHECK: define {{.*}} @"$s1a3foo4argsyxxQp_tRvzlF"
// CHECK-SAME: %swift.type** %[[TYPE_PACK_ARG:.*]])
// CHECK: %[[TYPE_PACK_ALLOCA:.*]] = alloca %swift.type**
// CHECK: call void @llvm.dbg.declare(metadata %swift.type*** %[[TYPE_PACK_ALLOCA]], metadata ![[TYPE_PACK_VAR:[0-9]+]], metadata !DIExpression())
Expand Down
6 changes: 3 additions & 3 deletions test/IRGen/variadic_generic_functions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@

// REQUIRES: PTRSIZE=64

// CHECK-LABEL: define hidden swiftcc void @"$s26variadic_generic_functions2f11tyxxQp_tlF"(%swift.opaque** noalias nocapture %0, i64 %1, %swift.type** %T)
// CHECK-LABEL: define hidden swiftcc void @"$s26variadic_generic_functions2f11tyxxQp_tRvzlF"(%swift.opaque** noalias nocapture %0, i64 %1, %swift.type** %T)
func f1<T...>(t: repeat each T) {}

// CHECK-LABEL: define hidden swiftcc void @"$s26variadic_generic_functions2f21t1uyxxQp_q_q_Qptr0_lF"(%swift.opaque** noalias nocapture %0, %swift.opaque** noalias nocapture %1, i64 %2, i64 %3, %swift.type** %T, %swift.type** %U)
// CHECK-LABEL: define hidden swiftcc void @"$s26variadic_generic_functions2f21t1uyxxQp_q_q_QptRvzRv_r0_lF"(%swift.opaque** noalias nocapture %0, %swift.opaque** noalias nocapture %1, i64 %2, i64 %3, %swift.type** %T, %swift.type** %U)
func f2<T..., U...>(t: repeat each T, u: repeat each U) {}

// CHECK-LABEL: define hidden swiftcc void @"$s26variadic_generic_functions2f31t1uyxxQp_q_xQptq_Rhzr0_lF"(%swift.opaque** noalias nocapture %0, %swift.opaque** noalias nocapture %1, i64 %2, %swift.type** %T, %swift.type** %U)
// CHECK-LABEL: define hidden swiftcc void @"$s26variadic_generic_functions2f31t1uyxxQp_q_xQptq_RhzRvzRv_r0_lF"(%swift.opaque** noalias nocapture %0, %swift.opaque** noalias nocapture %1, i64 %2, %swift.type** %T, %swift.type** %U)
func f3<T..., U...>(t: repeat each T, u: repeat each U) where (repeat (each T, each U)): Any {}

protocol P {}
Expand Down
3 changes: 3 additions & 0 deletions test/Interpreter/variadic_generic_types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,8 @@ struct G<T...> {
}
}

// CHECK: ()
G< >().makeTuple()

// CHECK: (Array<Int>, Array<String>, Array<Float>)
G<Int, String, Float>().makeTuple()
Loading