Skip to content

Commit f78fe71

Browse files
authored
Merge pull request #37041 from eeckstein/fix-open-archetype-mapping-5.5
[5.5] SILModule: track opened archetypes per function.
2 parents 7685c18 + 0fd6052 commit f78fe71

File tree

8 files changed

+118
-28
lines changed

8 files changed

+118
-28
lines changed

include/swift/SIL/SILFunction.h

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,19 +1020,12 @@ class SILFunction
10201020

10211021
/// Transfer all blocks of \p F into this function, at the begin of the block
10221022
/// list.
1023-
void moveAllBlocksFromOtherFunction(SILFunction *F) {
1024-
BlockList.splice(begin(), F->BlockList);
1025-
}
1023+
void moveAllBlocksFromOtherFunction(SILFunction *F);
10261024

10271025
/// Transfer \p blockInOtherFunction of another function into this function,
10281026
/// before \p insertPointInThisFunction.
10291027
void moveBlockFromOtherFunction(SILBasicBlock *blockInOtherFunction,
1030-
iterator insertPointInThisFunction) {
1031-
SILFunction *otherFunc = blockInOtherFunction->getParent();
1032-
assert(otherFunc != this);
1033-
BlockList.splice(insertPointInThisFunction, otherFunc->BlockList,
1034-
blockInOtherFunction);
1035-
}
1028+
iterator insertPointInThisFunction);
10361029

10371030
/// Move block \p BB to immediately before the iterator \p IP.
10381031
///

include/swift/SIL/SILModule.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,13 @@ class SILModule {
304304
/// The value is either a SingleValueInstrution or a PlaceholderValue, in case
305305
/// an opened-archetype definition is lookedup during parsing or deserializing
306306
/// SIL, where opened archetypes can be forward referenced.
307-
llvm::DenseMap<ArchetypeType*, SILValue> openedArchetypeDefs;
307+
///
308+
/// In theory we wouldn't need to have the SILFunction in the key, because
309+
/// opened archetypes _should_ be unique across the module. But currently
310+
/// in some rare cases SILGen re-uses the same opened archetype for multiple
311+
/// functions.
312+
using OpenedArchetypeKey = std::pair<ArchetypeType*, SILFunction*>;
313+
llvm::DenseMap<OpenedArchetypeKey, SILValue> openedArchetypeDefs;
308314

309315
/// The number of PlaceholderValues in openedArchetypeDefs.
310316
int numUnresolvedOpenedArchetypes = 0;
@@ -382,15 +388,18 @@ class SILModule {
382388
/// In case the opened archetype is not defined yet (e.g. during parsing or
383389
/// deserilization), a PlaceholderValue is returned. This should not be the
384390
/// case outside of parsing or deserialization.
385-
SILValue getOpenedArchetypeDef(CanArchetypeType archetype);
391+
SILValue getOpenedArchetypeDef(CanArchetypeType archetype,
392+
SILFunction *inFunction);
386393

387394
/// Returns the instruction which defines an opened archetype, e.g. an
388395
/// open_existential_addr.
389396
///
390397
/// In contrast to getOpenedArchetypeDef, it is required that all opened
391398
/// archetypes are resolved.
392-
SingleValueInstruction *getOpenedArchetypeInst(CanArchetypeType archetype) {
393-
return cast<SingleValueInstruction>(getOpenedArchetypeDef(archetype));
399+
SingleValueInstruction *getOpenedArchetypeInst(CanArchetypeType archetype,
400+
SILFunction *inFunction) {
401+
return cast<SingleValueInstruction>(getOpenedArchetypeDef(archetype,
402+
inFunction));
394403
}
395404

396405
/// Returns true if there are unresolved opened archetypes in the module.
@@ -401,6 +410,9 @@ class SILModule {
401410
/// Called by SILBuilder whenever a new instruction is created and inserted.
402411
void notifyAddedInstruction(SILInstruction *inst);
403412

413+
/// Called after an instruction is moved from one function to another.
414+
void notifyMovedInstruction(SILInstruction *inst, SILFunction *fromFunction);
415+
404416
/// Add a delete notification handler \p Handler to the module context.
405417
void registerDeleteNotificationHandler(DeleteNotificationHandler* Handler);
406418

lib/SIL/IR/SILFunction.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,30 @@ SILBasicBlock *SILFunction::createBasicBlockBefore(SILBasicBlock *beforeBB) {
383383
return newBlock;
384384
}
385385

386+
void SILFunction::moveAllBlocksFromOtherFunction(SILFunction *F) {
387+
BlockList.splice(begin(), F->BlockList);
388+
389+
SILModule &mod = getModule();
390+
for (SILBasicBlock &block : *this) {
391+
for (SILInstruction &inst : block) {
392+
mod.notifyMovedInstruction(&inst, F);
393+
}
394+
}
395+
}
396+
397+
void SILFunction::moveBlockFromOtherFunction(SILBasicBlock *blockInOtherFunction,
398+
iterator insertPointInThisFunction) {
399+
SILFunction *otherFunc = blockInOtherFunction->getParent();
400+
assert(otherFunc != this);
401+
BlockList.splice(insertPointInThisFunction, otherFunc->BlockList,
402+
blockInOtherFunction);
403+
404+
SILModule &mod = getModule();
405+
for (SILInstruction &inst : *blockInOtherFunction) {
406+
mod.notifyMovedInstruction(&inst, otherFunc);
407+
}
408+
}
409+
386410
void SILFunction::moveBlockBefore(SILBasicBlock *BB, SILFunction::iterator IP) {
387411
assert(BB->getParent() == this);
388412
if (SILFunction::iterator(BB) == IP)

lib/SIL/IR/SILInstructions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ static void buildTypeDependentOperands(
7676
SmallVectorImpl<SILValue> &TypeDependentOperands, SILFunction &F) {
7777

7878
for (auto archetype : OpenedArchetypes) {
79-
SILValue def = F.getModule().getOpenedArchetypeDef(archetype);
79+
SILValue def = F.getModule().getOpenedArchetypeDef(archetype, &F);
8080
assert(def->getFunction() == &F &&
8181
"def of opened archetype is in wrong function");
8282
TypeDependentOperands.push_back(def);

lib/SIL/IR/SILModule.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -724,8 +724,9 @@ void SILModule::registerDeserializationNotificationHandler(
724724
deserializationNotificationHandlers.add(std::move(handler));
725725
}
726726

727-
SILValue SILModule::getOpenedArchetypeDef(CanArchetypeType archetype) {
728-
SILValue &def = openedArchetypeDefs[archetype];
727+
SILValue SILModule::getOpenedArchetypeDef(CanArchetypeType archetype,
728+
SILFunction *inFunction) {
729+
SILValue &def = openedArchetypeDefs[{archetype, inFunction}];
729730
if (!def) {
730731
numUnresolvedOpenedArchetypes++;
731732
def = ::new PlaceholderValue(SILType::getPrimitiveAddressType(archetype));
@@ -741,7 +742,7 @@ bool SILModule::hasUnresolvedOpenedArchetypeDefinitions() {
741742
void SILModule::notifyAddedInstruction(SILInstruction *inst) {
742743
if (auto *svi = dyn_cast<SingleValueInstruction>(inst)) {
743744
if (CanArchetypeType archeTy = svi->getOpenedArchetype()) {
744-
SILValue &val = openedArchetypeDefs[archeTy];
745+
SILValue &val = openedArchetypeDefs[{archeTy, inst->getFunction()}];
745746
if (val) {
746747
if (!isa<PlaceholderValue>(val)) {
747748
// Print a useful error message (and not just abort with an assert).
@@ -765,6 +766,19 @@ void SILModule::notifyAddedInstruction(SILInstruction *inst) {
765766
}
766767
}
767768

769+
void SILModule::notifyMovedInstruction(SILInstruction *inst,
770+
SILFunction *fromFunction) {
771+
if (auto *svi = dyn_cast<SingleValueInstruction>(inst)) {
772+
if (CanArchetypeType archeTy = svi->getOpenedArchetype()) {
773+
OpenedArchetypeKey key = {archeTy, fromFunction};
774+
assert(openedArchetypeDefs.lookup(key) == svi &&
775+
"archetype def was not registered");
776+
openedArchetypeDefs.erase(key);
777+
openedArchetypeDefs[{archeTy, svi->getFunction()}] = svi;
778+
}
779+
}
780+
}
781+
768782
void SILModule::registerDeleteNotificationHandler(
769783
DeleteNotificationHandler *handler) {
770784
// Ask the handler (that can be an analysis, a pass, or some other data
@@ -783,9 +797,10 @@ void SILModule::notifyDeleteHandlers(SILNode *node) {
783797
// Update openedArchetypeDefs.
784798
if (auto *svi = dyn_cast<SingleValueInstruction>(node)) {
785799
if (CanArchetypeType archeTy = svi->getOpenedArchetype()) {
786-
assert(openedArchetypeDefs.lookup(archeTy) == svi &&
800+
OpenedArchetypeKey key = {archeTy, svi->getFunction()};
801+
assert(openedArchetypeDefs.lookup(key) == svi &&
787802
"archetype def was not registered");
788-
openedArchetypeDefs.erase(archeTy);
803+
openedArchetypeDefs.erase(key);
789804
}
790805
}
791806

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,7 +1329,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
13291329
"Operand is of an ArchetypeType that does not exist in the "
13301330
"Caller's generic param list.");
13311331
if (auto OpenedA = getOpenedArchetypeOf(A)) {
1332-
auto *openingInst = F->getModule().getOpenedArchetypeInst(OpenedA);
1332+
auto *openingInst = F->getModule().getOpenedArchetypeInst(OpenedA, F);
13331333
require(I == nullptr || openingInst == I ||
13341334
properlyDominates(openingInst, I),
13351335
"Use of an opened archetype should be dominated by a "
@@ -1463,7 +1463,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
14631463
FoundOpenedArchetypes.insert(A);
14641464
// Also check that they are properly tracked inside the current
14651465
// function.
1466-
auto *openingInst = F.getModule().getOpenedArchetypeInst(A);
1466+
auto *openingInst = F.getModule().getOpenedArchetypeInst(A,
1467+
AI->getFunction());
14671468
require(openingInst == AI ||
14681469
properlyDominates(openingInst, AI),
14691470
"Use of an opened archetype should be dominated by a "
@@ -3411,7 +3412,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
34113412
auto archetype = getOpenedArchetypeOf(OEI->getType().getASTType());
34123413
require(archetype,
34133414
"open_existential_addr result must be an opened existential archetype");
3414-
require(OEI->getModule().getOpenedArchetypeInst(archetype) == OEI,
3415+
require(OEI->getModule().getOpenedArchetypeInst(archetype,
3416+
OEI->getFunction()) == OEI,
34153417
"Archetype opened by open_existential_addr should be registered in "
34163418
"SILFunction");
34173419

@@ -3444,7 +3446,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
34443446
auto archetype = getOpenedArchetypeOf(resultInstanceTy);
34453447
require(archetype,
34463448
"open_existential_ref result must be an opened existential archetype");
3447-
require(OEI->getModule().getOpenedArchetypeInst(archetype) == OEI,
3449+
require(OEI->getModule().getOpenedArchetypeInst(archetype,
3450+
OEI->getFunction()) == OEI,
34483451
"Archetype opened by open_existential_ref should be registered in "
34493452
"SILFunction");
34503453
}
@@ -3466,7 +3469,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
34663469
auto archetype = getOpenedArchetypeOf(resultInstanceTy);
34673470
require(archetype,
34683471
"open_existential_box result must be an opened existential archetype");
3469-
require(OEI->getModule().getOpenedArchetypeInst(archetype) == OEI,
3472+
require(OEI->getModule().getOpenedArchetypeInst(archetype,
3473+
OEI->getFunction()) == OEI,
34703474
"Archetype opened by open_existential_box should be registered in "
34713475
"SILFunction");
34723476
}
@@ -3488,7 +3492,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
34883492
auto archetype = getOpenedArchetypeOf(resultInstanceTy);
34893493
require(archetype,
34903494
"open_existential_box_value result not an opened existential archetype");
3491-
require(OEI->getModule().getOpenedArchetypeInst(archetype) == OEI,
3495+
require(OEI->getModule().getOpenedArchetypeInst(archetype,
3496+
OEI->getFunction()) == OEI,
34923497
"Archetype opened by open_existential_box_value should be "
34933498
"registered in SILFunction");
34943499
}
@@ -3534,7 +3539,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
35343539
require(archetype, "open_existential_metatype result must be an opened "
35353540
"existential metatype");
35363541
require(
3537-
I->getModule().getOpenedArchetypeInst(archetype) == I,
3542+
I->getModule().getOpenedArchetypeInst(archetype, I->getFunction()) == I,
35383543
"Archetype opened by open_existential_metatype should be registered in "
35393544
"SILFunction");
35403545
}
@@ -3553,7 +3558,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
35533558
auto archetype = getOpenedArchetypeOf(OEI->getType().getASTType());
35543559
require(archetype, "open_existential_value result must be an opened "
35553560
"existential archetype");
3556-
require(OEI->getModule().getOpenedArchetypeInst(archetype) == OEI,
3561+
require(OEI->getModule().getOpenedArchetypeInst(archetype,
3562+
OEI->getFunction()) == OEI,
35573563
"Archetype opened by open_existential should be registered in "
35583564
"SILFunction");
35593565
}
@@ -3841,7 +3847,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
38413847
SILValue Def;
38423848
if (t->isOpenedExistential()) {
38433849
auto archetypeTy = cast<ArchetypeType>(t);
3844-
Def = I->getModule().getOpenedArchetypeInst(archetypeTy);
3850+
Def = I->getModule().getOpenedArchetypeInst(archetypeTy, I->getFunction());
38453851
require(Def, "Opened archetype should be registered in SILModule");
38463852
} else if (t->hasDynamicSelfType()) {
38473853
require(I->getFunction()->hasSelfParam() ||
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
@protocol P
3+
@end
4+
5+
@interface I
6+
@property(class, readonly) I<P> *x;
7+
@end
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: %target-swift-frontend %s -enable-objc-interop -import-objc-header %S/Inputs/duplicate_opened_archetypes.h -emit-sil -o /dev/null
2+
3+
// REQUIRES: objc_interop
4+
5+
// Check that SILGen does not crash because of duplicate opened archetypes
6+
// in two functions.
7+
8+
import Foundation
9+
10+
struct S {
11+
let i: I
12+
}
13+
14+
@propertyWrapper
15+
public struct W<Value> {
16+
public var wrappedValue: Value
17+
18+
public init(wrappedValue: Value) {
19+
self.wrappedValue = wrappedValue
20+
}
21+
22+
public init(initialValue: Value) {
23+
wrappedValue = initialValue
24+
}
25+
26+
}
27+
28+
29+
struct Test {
30+
@W private var s = S(i: .x)
31+
32+
var t: S = S(i: .x)
33+
}

0 commit comments

Comments
 (0)