Skip to content

Commit 8631a24

Browse files
committed
SILGen: Rewrite captured local archetypes into primary archetypes
1 parent db95353 commit 8631a24

File tree

5 files changed

+162
-0
lines changed

5 files changed

+162
-0
lines changed

lib/SILGen/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ add_swift_host_library(swiftSILGen STATIC
2828
SILGenFunction.cpp
2929
SILGenGlobalVariable.cpp
3030
SILGenLazyConformance.cpp
31+
SILGenLocalArchetype.cpp
3132
SILGenLValue.cpp
3233
SILGenPack.cpp
3334
SILGenPattern.cpp

lib/SILGen/SILGen.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -1260,6 +1260,9 @@ void SILGenModule::postEmitFunction(SILDeclRef constant,
12601260
SILFunction *F) {
12611261
emitLazyConformancesForFunction(F);
12621262

1263+
auto sig = Types.getGenericSignatureWithCapturedEnvironments(constant);
1264+
recontextualizeCapturedLocalArchetypes(F, sig);
1265+
12631266
assert(!F->isExternalDeclaration() && "did not emit any function body?!");
12641267
LLVM_DEBUG(llvm::dbgs() << "lowered sil:\n";
12651268
F->print(llvm::dbgs()));

lib/SILGen/SILGen.h

+5
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,11 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
625625
/// Emit a property descriptor for the given storage decl if it needs one.
626626
void tryEmitPropertyDescriptor(AbstractStorageDecl *decl);
627627

628+
/// Replace local archetypes captured from outer AST contexts with primary
629+
/// archetypes.
630+
void recontextualizeCapturedLocalArchetypes(
631+
SILFunction *F, GenericSignatureWithCapturedEnvironments sig);
632+
628633
private:
629634
/// The most recent declaration we considered for emission.
630635
SILDeclRef lastEmittedFunction;

lib/SILGen/SILGenLazyConformance.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
1010
//
1111
//===----------------------------------------------------------------------===//
12+
//
13+
// This file forces emission of lazily-generated ClangImporter-synthesized
14+
// conformances.
15+
//
16+
//===----------------------------------------------------------------------===//
1217

1318
#include "SILGen.h"
1419
#include "swift/AST/Decl.h"

lib/SILGen/SILGenLocalArchetype.cpp

+148
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
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+
}

0 commit comments

Comments
 (0)