Skip to content

Commit fe9385a

Browse files
Merge pull request swiftlang#17810 from adrian-prantl/28859432
Add debug info support for inlined and specialized generic variables.
2 parents 238aa2d + 91f6f34 commit fe9385a

File tree

18 files changed

+282
-70
lines changed

18 files changed

+282
-70
lines changed

docs/ABI/Mangling.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,7 @@ Function Specializations
785785

786786
specialization ::= type '_' type* 'Tg' SPEC-INFO // Generic re-abstracted specialization
787787
specialization ::= type '_' type* 'TG' SPEC-INFO // Generic not re-abstracted specialization
788+
specialization ::= type '_' type* 'Ti' SPEC-INFO // Inlined function with generic substitutions.
788789

789790
The types are the replacement types of the substitution list.
790791

include/swift/AST/SubstitutionMap.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ class SubstitutionMap {
153153
/// existential.
154154
bool hasOpenedExistential() const;
155155

156-
/// Query whether any replacement type sin the map contain dynamic Self.
156+
/// Query whether any replacement types in the map contain dynamic Self.
157157
bool hasDynamicSelf() const;
158158

159159
/// Whether the replacement types are all canonical.

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ NODE(ResilientProtocolWitnessTable)
8787
NODE(GenericSpecialization)
8888
NODE(GenericSpecializationNotReAbstracted)
8989
NODE(GenericSpecializationParam)
90+
NODE(InlinedGenericFunction)
9091
NODE(GenericTypeMetadataPattern)
9192
CONTEXT_NODE(Getter)
9293
NODE(Global)

include/swift/SIL/TypeSubstCloner.h

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "swift/SIL/SILCloner.h"
2525
#include "swift/SIL/DynamicCasts.h"
2626
#include "swift/SILOptimizer/Utils/Local.h"
27+
#include "swift/SILOptimizer/Utils/SpecializationMangler.h"
2728
#include "llvm/Support/Debug.h"
2829

2930
namespace swift {
@@ -279,6 +280,84 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
279280
super::visitDestroyValueInst(Destroy);
280281
}
281282

283+
/// One abstract function in the debug info can only have one set of variables
284+
/// and types. This function determines whether applying the substitutions in
285+
/// \p SubsMap on the generic signature \p Sig will change the generic type
286+
/// parameters in the signature. This is used to decide whether it's necessary
287+
/// to clone a unique copy of the function declaration with the substitutions
288+
/// applied for the debug info.
289+
static bool substitutionsChangeGenericTypeParameters(SubstitutionMap SubsMap,
290+
GenericSignature *Sig) {
291+
292+
// If there are no substitutions, just reuse
293+
// the original decl.
294+
if (SubsMap.empty())
295+
return false;
296+
297+
auto Params = Sig->getSubstitutableParams();
298+
return std::any_of(Params.begin(), Params.end(), [&](Type ParamType) {
299+
Type Substitution = Type(ParamType).subst(SubsMap);
300+
return !Substitution->isOpenedExistential() &&
301+
(Substitution->getCanonicalType() !=
302+
ParamType->getCanonicalType());
303+
});
304+
}
305+
306+
enum { ForInlining = true };
307+
/// Helper function to clone the parent function of a SILDebugScope if
308+
/// necessary when inlining said function into a new generic context.
309+
/// \param SubsMap - the substitutions of the inlining/specialization process.
310+
/// \param RemappedSig - the generic signature
311+
static SILFunction *remapParentFunction(SILModule &M,
312+
SILFunction *ParentFunction,
313+
SubstitutionMap SubsMap,
314+
GenericSignature *RemappedSig,
315+
bool ForInlining = false) {
316+
// If the original, non-inlined version of the function had no generic
317+
// environment, there is no need to remap it.
318+
auto *OriginalEnvironment = ParentFunction->getGenericEnvironment();
319+
if (!RemappedSig || !OriginalEnvironment)
320+
return ParentFunction;
321+
322+
if (SubsMap.hasArchetypes())
323+
SubsMap = SubsMap.mapReplacementTypesOutOfContext();
324+
325+
if (!substitutionsChangeGenericTypeParameters(SubsMap, RemappedSig))
326+
return ParentFunction;
327+
328+
// Clone the function with the substituted type for the debug info.
329+
Mangle::GenericSpecializationMangler Mangler(
330+
ParentFunction, SubsMap, IsNotSerialized, false, ForInlining);
331+
std::string MangledName = Mangler.mangle(RemappedSig);
332+
333+
if (ParentFunction->getName() == MangledName)
334+
return ParentFunction;
335+
if (auto *CachedFn = M.lookUpFunction(MangledName))
336+
ParentFunction = CachedFn;
337+
else {
338+
// Create a new function with this mangled name with an empty
339+
// body. There won't be any IR generated for it (hence the linkage),
340+
// but the symbol will be refered to by the debug info metadata.
341+
ParentFunction = M.getOrCreateFunction(
342+
ParentFunction->getLocation(), MangledName, SILLinkage::Shared,
343+
ParentFunction->getLoweredFunctionType(), ParentFunction->isBare(),
344+
ParentFunction->isTransparent(), ParentFunction->isSerialized(), 0,
345+
ParentFunction->isThunk(), ParentFunction->getClassSubclassScope());
346+
// Increment the ref count for the inlined function, so it doesn't
347+
// get deleted before we can emit abstract debug info for it.
348+
if (!ParentFunction->isZombie()) {
349+
ParentFunction->setInlined();
350+
// If the function was newly created with an empty body mark it as
351+
// undead.
352+
if (ParentFunction->empty()) {
353+
M.eraseFunction(ParentFunction);
354+
ParentFunction->setGenericEnvironment(OriginalEnvironment);
355+
}
356+
}
357+
}
358+
return ParentFunction;
359+
}
360+
282361
/// The Swift module that the cloned function belongs to.
283362
ModuleDecl *SwiftMod;
284363
/// The substitutions list for the specialization.
@@ -289,7 +368,7 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
289368
SILFunction &Original;
290369
/// True, if used for inlining.
291370
bool Inlining;
292-
};
371+
};
293372

294373
} // end namespace swift
295374

include/swift/SILOptimizer/Utils/GenericCloner.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ class GenericCloner : public TypeSubstCloner<GenericCloner> {
3434
IsSerialized_t Serialized;
3535
const ReabstractionInfo &ReInfo;
3636
CloneCollector::CallbackType Callback;
37+
llvm::SmallDenseMap<const SILDebugScope *, const SILDebugScope *, 8>
38+
RemappedScopeCache;
3739

3840
public:
3941
friend class SILCloner<GenericCloner>;
@@ -90,6 +92,9 @@ class GenericCloner : public TypeSubstCloner<GenericCloner> {
9092
/// by initCloned.
9193
void populateCloned();
9294
SILFunction *getCloned() { return &getBuilder().getFunction(); }
95+
96+
const SILDebugScope *remapScope(const SILDebugScope *DS);
97+
9398
};
9499

95100
} // end namespace swift

include/swift/SILOptimizer/Utils/SpecializationMangler.h

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ class SpecializationMangler : public Mangle::ASTMangler {
4848
protected:
4949
SpecializationMangler(SpecializationPass P, IsSerialized_t Serialized,
5050
SILFunction *F)
51-
: Pass(P), Serialized(Serialized), Function(F), ArgOpBuffer(ArgOpStorage) {}
51+
: Pass(P), Serialized(Serialized), Function(F),
52+
ArgOpBuffer(ArgOpStorage) {}
5253

5354
SILFunction *getFunction() const { return Function; }
5455

@@ -67,17 +68,17 @@ class GenericSpecializationMangler : public SpecializationMangler {
6768

6869
SubstitutionMap SubMap;
6970
bool isReAbstracted;
71+
bool isInlined;
7072

7173
public:
72-
73-
GenericSpecializationMangler(SILFunction *F,
74-
SubstitutionMap SubMap,
75-
IsSerialized_t Serialized,
76-
bool isReAbstracted)
77-
: SpecializationMangler(SpecializationPass::GenericSpecializer, Serialized, F),
78-
SubMap(SubMap), isReAbstracted(isReAbstracted) {}
79-
80-
std::string mangle();
74+
GenericSpecializationMangler(SILFunction *F, SubstitutionMap SubMap,
75+
IsSerialized_t Serialized, bool isReAbstracted,
76+
bool isInlined = false)
77+
: SpecializationMangler(SpecializationPass::GenericSpecializer,
78+
Serialized, F),
79+
SubMap(SubMap), isReAbstracted(isReAbstracted), isInlined(isInlined) {}
80+
81+
std::string mangle(GenericSignature *Sig = nullptr);
8182
};
8283

8384
class PartialSpecializationMangler : public SpecializationMangler {
@@ -88,10 +89,10 @@ class PartialSpecializationMangler : public SpecializationMangler {
8889
public:
8990
PartialSpecializationMangler(SILFunction *F,
9091
CanSILFunctionType SpecializedFnTy,
91-
IsSerialized_t Serialized,
92-
bool isReAbstracted)
93-
: SpecializationMangler(SpecializationPass::GenericSpecializer, Serialized, F),
94-
SpecializedFnTy(SpecializedFnTy), isReAbstracted(isReAbstracted) {}
92+
IsSerialized_t Serialized, bool isReAbstracted)
93+
: SpecializationMangler(SpecializationPass::GenericSpecializer,
94+
Serialized, F),
95+
SpecializedFnTy(SpecializedFnTy), isReAbstracted(isReAbstracted) {}
9596

9697
std::string mangle();
9798
};

lib/Demangling/Demangler.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1731,11 +1731,13 @@ NodePointer Demangler::demangleThunkOrSpecialization() {
17311731
Thunk = addChild(Thunk, popNode(Node::Kind::Type));
17321732
return addChild(Thunk, Ty2);
17331733
}
1734-
case'g':
1734+
case 'g':
17351735
return demangleGenericSpecialization(Node::Kind::GenericSpecialization);
1736-
case'G':
1736+
case 'G':
17371737
return demangleGenericSpecialization(Node::Kind::
17381738
GenericSpecializationNotReAbstracted);
1739+
case 'i':
1740+
return demangleGenericSpecialization(Node::Kind::InlinedGenericFunction);
17391741
case'p': {
17401742
NodePointer Spec = demangleSpecAttributes(Node::Kind::
17411743
GenericPartialSpecialization);
@@ -1866,7 +1868,8 @@ NodePointer Demangler::demangleGenericSpecialization(Node::Kind SpecKind) {
18661868
if (!TyList)
18671869
return nullptr;
18681870
for (NodePointer Ty : *TyList) {
1869-
Spec->addChild(createWithChild(Node::Kind::GenericSpecializationParam, Ty), *this);
1871+
Spec->addChild(createWithChild(Node::Kind::GenericSpecializationParam, Ty),
1872+
*this);
18701873
}
18711874
return Spec;
18721875
}

lib/Demangling/NodePrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ class NodePrinter {
351351
case Node::Kind::GenericSpecialization:
352352
case Node::Kind::GenericSpecializationNotReAbstracted:
353353
case Node::Kind::GenericSpecializationParam:
354+
case Node::Kind::InlinedGenericFunction:
354355
case Node::Kind::GenericTypeMetadataPattern:
355356
case Node::Kind::Getter:
356357
case Node::Kind::Global:
@@ -1181,6 +1182,9 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
11811182
case Node::Kind::GenericSpecializationNotReAbstracted:
11821183
printSpecializationPrefix(Node, "generic not re-abstracted specialization");
11831184
return nullptr;
1185+
case Node::Kind::InlinedGenericFunction:
1186+
printSpecializationPrefix(Node, "inlined generic function");
1187+
return nullptr;
11841188
case Node::Kind::SpecializationIsFragile:
11851189
Printer << "preserving fragile attribute";
11861190
return nullptr;

lib/Demangling/OldRemangler.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ void Remangler::mangleGenericSpecialization(Node *node) {
534534
// Start another mangled name.
535535
Out << "__T";
536536
}
537+
537538
void Remangler::mangleGenericSpecializationNotReAbstracted(Node *node) {
538539
Out << "TSr";
539540
mangleChildNodes(node); // GenericSpecializationParams
@@ -545,6 +546,17 @@ void Remangler::mangleGenericSpecializationNotReAbstracted(Node *node) {
545546
Out << "__T";
546547
}
547548

549+
void Remangler::mangleInlinedGenericFunction(Node *node) {
550+
Out << "TSi";
551+
mangleChildNodes(node); // GenericSpecializationParams
552+
553+
// Specializations are just prepended to already-mangled names.
554+
resetSubstitutions();
555+
556+
// Start another mangled name.
557+
Out << "__T";
558+
}
559+
548560
void Remangler::mangleGenericPartialSpecialization(Node *node) {
549561
unreachable("todo");
550562
}

lib/Demangling/Remangler.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,8 +1122,20 @@ void Remangler::mangleGenericSpecialization(Node *node) {
11221122
}
11231123
assert(!FirstParam && "generic specialization with no substitutions");
11241124

1125-
Buffer << (node->getKind() ==
1126-
Node::Kind::GenericSpecializationNotReAbstracted ? "TG" : "Tg");
1125+
switch (node->getKind()) {
1126+
case Node::Kind::GenericSpecialization:
1127+
Buffer << "Tg";
1128+
break;
1129+
case Node::Kind::GenericSpecializationNotReAbstracted:
1130+
Buffer << "TG";
1131+
break;
1132+
case Node::Kind::InlinedGenericFunction:
1133+
Buffer << "Ti";
1134+
break;
1135+
default:
1136+
unreachable("unsupported node");
1137+
}
1138+
11271139
for (NodePointer Child : *node) {
11281140
if (Child->getKind() != Node::Kind::GenericSpecializationParam)
11291141
mangle(Child);
@@ -1134,6 +1146,11 @@ void Remangler::mangleGenericSpecializationNotReAbstracted(Node *node) {
11341146
mangleGenericSpecialization(node);
11351147
}
11361148

1149+
void Remangler::mangleInlinedGenericFunction(Node *node) {
1150+
mangleGenericSpecialization(node);
1151+
}
1152+
1153+
11371154
void Remangler::mangleGenericSpecializationParam(Node *node) {
11381155
unreachable("handled inline");
11391156
}
@@ -1161,6 +1178,7 @@ void Remangler::mangleGlobal(Node *node) {
11611178
case Node::Kind::FunctionSignatureSpecialization:
11621179
case Node::Kind::GenericSpecialization:
11631180
case Node::Kind::GenericSpecializationNotReAbstracted:
1181+
case Node::Kind::InlinedGenericFunction:
11641182
case Node::Kind::GenericPartialSpecialization:
11651183
case Node::Kind::GenericPartialSpecializationNotReAbstracted:
11661184
case Node::Kind::OutlinedBridgedMethod:

0 commit comments

Comments
 (0)