Skip to content

Commit 7964899

Browse files
Merge pull request #18366 from adrian-prantl/28859432
Add debug info support for inlined and specialized generic variables.
2 parents 7676855 + 58475ef commit 7964899

File tree

18 files changed

+291
-70
lines changed

18 files changed

+291
-70
lines changed

docs/ABI/Mangling.rst

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

788788
specialization ::= type '_' type* 'Tg' SPEC-INFO // Generic re-abstracted specialization
789789
specialization ::= type '_' type* 'TG' SPEC-INFO // Generic not re-abstracted specialization
790+
specialization ::= type '_' type* 'Ti' SPEC-INFO // Inlined function with generic substitutions.
790791

791792
The types are the replacement types of the substitution list.
792793

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: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
#include "swift/AST/Type.h"
2424
#include "swift/SIL/SILCloner.h"
2525
#include "swift/SIL/DynamicCasts.h"
26+
#include "swift/SIL/SILFunctionBuilder.h"
2627
#include "swift/SILOptimizer/Utils/Local.h"
28+
#include "swift/SILOptimizer/Utils/SpecializationMangler.h"
2729
#include "llvm/Support/Debug.h"
2830

2931
namespace swift {
@@ -277,6 +279,92 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
277279
super::visitDestroyValueInst(Destroy);
278280
}
279281

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

292380
} // end namespace swift
293381

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
@@ -1734,11 +1734,13 @@ NodePointer Demangler::demangleThunkOrSpecialization() {
17341734
Thunk = addChild(Thunk, popNode(Node::Kind::Type));
17351735
return addChild(Thunk, Ty2);
17361736
}
1737-
case'g':
1737+
case 'g':
17381738
return demangleGenericSpecialization(Node::Kind::GenericSpecialization);
1739-
case'G':
1739+
case 'G':
17401740
return demangleGenericSpecialization(Node::Kind::
17411741
GenericSpecializationNotReAbstracted);
1742+
case 'i':
1743+
return demangleGenericSpecialization(Node::Kind::InlinedGenericFunction);
17421744
case'p': {
17431745
NodePointer Spec = demangleSpecAttributes(Node::Kind::
17441746
GenericPartialSpecialization);
@@ -1869,7 +1871,8 @@ NodePointer Demangler::demangleGenericSpecialization(Node::Kind SpecKind) {
18691871
if (!TyList)
18701872
return nullptr;
18711873
for (NodePointer Ty : *TyList) {
1872-
Spec->addChild(createWithChild(Node::Kind::GenericSpecializationParam, Ty), *this);
1874+
Spec->addChild(createWithChild(Node::Kind::GenericSpecializationParam, Ty),
1875+
*this);
18731876
}
18741877
return Spec;
18751878
}

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:
@@ -1183,6 +1184,9 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
11831184
case Node::Kind::GenericSpecializationNotReAbstracted:
11841185
printSpecializationPrefix(Node, "generic not re-abstracted specialization");
11851186
return nullptr;
1187+
case Node::Kind::InlinedGenericFunction:
1188+
printSpecializationPrefix(Node, "inlined generic function");
1189+
return nullptr;
11861190
case Node::Kind::SpecializationIsFragile:
11871191
Printer << "preserving fragile attribute";
11881192
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)