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
2931namespace 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
0 commit comments