1
+ // ===--- SILGenLocalArchetype.cpp - Local archetype transform -------------===//
2
+ //
3
+ // This source file is part of the Swift.org open source project
4
+ //
5
+ // Copyright (c) 2024 Apple Inc. and the Swift project authors
6
+ // Licensed under Apache License v2.0 with Runtime Library Exception
7
+ //
8
+ // See https://swift.org/LICENSE.txt for license information
9
+ // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10
+ //
11
+ // ===----------------------------------------------------------------------===//
12
+ //
13
+ // This file implements the transformation which rewrites captured local
14
+ // archetypes into primary archetypes in the enclosing function's generic
15
+ // signature.
16
+ //
17
+ // ===----------------------------------------------------------------------===//
18
+
19
+ #include " SILGen.h"
20
+ #include " swift/AST/LocalArchetypeRequirementCollector.h"
21
+ #include " swift/SIL/SILInstruction.h"
22
+ #include " swift/SIL/SILCloner.h"
23
+
24
+ using namespace swift ;
25
+ using namespace swift ::Lowering;
26
+
27
+ namespace {
28
+
29
+ class LocalArchetypeTransform : public SILCloner <LocalArchetypeTransform> {
30
+ friend class SILCloner <LocalArchetypeTransform>;
31
+ friend class SILInstructionVisitor <LocalArchetypeTransform>;
32
+
33
+ GenericSignatureWithCapturedEnvironments sig;
34
+ GenericEnvironment *env;
35
+
36
+ public:
37
+ LocalArchetypeTransform (SILFunction *F,
38
+ GenericSignatureWithCapturedEnvironments sig)
39
+ : SILCloner(*F), env(sig.genericSig.getGenericEnvironment()) {
40
+
41
+ assert (!sig.capturedEnvs .empty () && " Why are we doing this?" );
42
+
43
+ // The primary archetypes of the old generic environment map to
44
+ // primary archetypes of the new generic environment at the same
45
+ // index and depth.
46
+ Functor.SubsMap = env->getForwardingSubstitutionMap ();
47
+
48
+ // Local archetypes map to generic parameters at higher depths.
49
+ MapLocalArchetypesOutOfContext mapOutOfContext (sig.baseGenericSig ,
50
+ sig.capturedEnvs );
51
+
52
+ // For each captured environment...
53
+ for (auto *capturedEnv : sig.capturedEnvs ) {
54
+ // For each introduced generic parameter...
55
+ auto localParams = capturedEnv->getGenericSignature ()
56
+ .getInnermostGenericParams ();
57
+ for (auto *gp : localParams) {
58
+ // Get the local archetype from the captured environment.
59
+ auto origArchetypeTy = capturedEnv->mapTypeIntoContext (gp)
60
+ ->castTo <LocalArchetypeType>();
61
+
62
+ // Map the local archetype to an interface type in the new generic
63
+ // signature.
64
+ auto substInterfaceTy = mapOutOfContext (origArchetypeTy);
65
+
66
+ // Map this interface type into the new generic environment to get
67
+ // a primary archetype.
68
+ auto substArchetypeTy = env->mapTypeIntoContext (substInterfaceTy)
69
+ ->castTo <PrimaryArchetypeType>();
70
+
71
+ // Remember this correspondence.
72
+ registerLocalArchetypeRemapping (origArchetypeTy, substArchetypeTy);
73
+ }
74
+ }
75
+ }
76
+
77
+ void doIt () {
78
+ auto &F = getBuilder ().getFunction ();
79
+
80
+ // Collect the old basic blocks that we're going to delete.
81
+ llvm::SmallVector<SILBasicBlock *, 4 > bbs;
82
+ for (auto &bb : F)
83
+ bbs.push_back (&bb);
84
+
85
+ // Make F.mapTypeIntoContext() use the new environment.
86
+ F.setGenericEnvironment (env);
87
+
88
+ // Start by cloning the entry block.
89
+ auto *origEntryBlock = F.getEntryBlock ();
90
+ auto *clonedEntryBlock = F.createBasicBlock ();
91
+
92
+ // Clone arguments.
93
+ SmallVector<SILValue, 4 > entryArgs;
94
+ entryArgs.reserve (origEntryBlock->getArguments ().size ());
95
+ for (auto &origArg : origEntryBlock->getArguments ()) {
96
+
97
+ // Remap the argument type into the new generic environment.
98
+ SILType mappedType = remapType (origArg->getType ());
99
+ auto *NewArg = clonedEntryBlock->createFunctionArgument (
100
+ mappedType, origArg->getDecl (), true );
101
+ NewArg->copyFlags (cast<SILFunctionArgument>(origArg));
102
+ entryArgs.push_back (NewArg);
103
+ }
104
+
105
+ // Clone the remaining body.
106
+ getBuilder ().setInsertionPoint (clonedEntryBlock);
107
+ cloneFunctionBody (&F, clonedEntryBlock, entryArgs,
108
+ true /* replaceOriginalFunctionInPlace*/ );
109
+
110
+ // Insert the new entry block at the beginning.
111
+ F.moveBlockBefore (clonedEntryBlock, F.begin ());
112
+
113
+ // FIXME: This should be a common utility.
114
+
115
+ // Erase the old basic blocks.
116
+ for (auto *bb : bbs) {
117
+ for (SILArgument *arg : bb->getArguments ()) {
118
+ arg->replaceAllUsesWithUndef ();
119
+ // To appease the ownership verifier, just set to None.
120
+ arg->setOwnershipKind (OwnershipKind::None);
121
+ }
122
+
123
+ // Instructions in the dead block may be used by other dead blocks. Replace
124
+ // any uses of them with undef values.
125
+ while (!bb->empty ()) {
126
+ // Grab the last instruction in the bb.
127
+ auto *inst = &bb->back ();
128
+
129
+ // Replace any still-remaining uses with undef values and erase.
130
+ inst->replaceAllUsesOfAllResultsWithUndef ();
131
+ inst->eraseFromParent ();
132
+ }
133
+
134
+ // Finally, erase the basic block itself.
135
+ bb->eraseFromParent ();
136
+ }
137
+ }
138
+ };
139
+
140
+ } // end anonymous namespace
141
+
142
+ void SILGenModule::recontextualizeCapturedLocalArchetypes (
143
+ SILFunction *F, GenericSignatureWithCapturedEnvironments sig) {
144
+ if (sig.capturedEnvs .empty ())
145
+ return ;
146
+
147
+ LocalArchetypeTransform (F, sig).doIt ();
148
+ reclaimUnresolvedLocalArchetypeDefinitions ();
149
+ }
0 commit comments