Skip to content

Commit de8e182

Browse files
committed
[AddressLowering] Prevent existential multi-init.
1 parent 5076e7b commit de8e182

File tree

2 files changed

+25
-17
lines changed

2 files changed

+25
-17
lines changed

lib/SILOptimizer/Mandatory/AddressLowering.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ void ValueStorage::dump() const {
439439
llvm::dbgs() << "isDefProjection: " << isDefProjection << "\n";
440440
llvm::dbgs() << "isUseProjection: " << isUseProjection << "\n";
441441
llvm::dbgs() << "isRewritten: " << isRewritten << "\n";
442-
llvm::dbgs() << "initializesEnum: " << initializesEnum << "\n";
442+
llvm::dbgs() << "initializes: " << initializes << "\n";
443443
}
444444
void ValueStorageMap::ValueStoragePair::dump() const {
445445
llvm::dbgs() << "value: ";
@@ -1071,8 +1071,9 @@ void ValueStorageMap::recordComposingUseProjection(Operand *oper,
10711071

10721072
storage.isUseProjection = true;
10731073

1074-
if (userValue->getType().getEnumOrBoundGenericEnum()) {
1075-
storage.initializesEnum = true;
1074+
if (userValue->getType().getEnumOrBoundGenericEnum() ||
1075+
userValue->getType().isExistentialType()) {
1076+
storage.initializes = true;
10761077
}
10771078
assert(!storage.isPhiProjection());
10781079
}
@@ -1266,8 +1267,8 @@ bool OpaqueStorageAllocation::findProjectionIntoUseImpl(
12661267
// TODO: fix the memory verifier to consider the actual store instructions
12671268
// to initialize an enum rather than the init_enum_data_addr to reuse enum
12681269
// storage across multiple subobjects within the payload.
1269-
auto *baseStorage = pass.valueStorageMap.getBaseStorage(
1270-
userValue, /*allowInitEnum*/ !intoPhi);
1270+
auto *baseStorage =
1271+
pass.valueStorageMap.getBaseStorage(userValue, /*allowInit*/ !intoPhi);
12711272
if (!baseStorage)
12721273
continue;
12731274

lib/SILOptimizer/Mandatory/AddressLowering.h

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -147,15 +147,21 @@ struct ValueStorage {
147147
// The definition of this value is fully translated to lowered SIL.
148148
unsigned isRewritten : 1;
149149

150-
// This is a use-projection into an enum. Tracked to avoid projecting enums
151-
// across phis, which would result in piecewise initialization.
152-
unsigned initializesEnum : 1;
150+
// This is a use-projection which performs an initialization side-effect,
151+
// either into an enum or an existential.
152+
//
153+
// Tracked to avoid projecting enums/existentials across phis, which would
154+
// result in piecewise initialization.
155+
//
156+
// Note that the corresponding value is the payload, not the
157+
// enum instruction.
158+
unsigned initializes : 1;
153159

154160
ValueStorage(SILValue storageAddress): storageAddress(storageAddress) {
155161
isDefProjection = false;
156162
isUseProjection = false;
157163
isRewritten = false;
158-
initializesEnum = false;
164+
initializes = false;
159165

160166
// The initial storage address is only valid when the value is effectively
161167
// already rewritten.
@@ -346,12 +352,13 @@ class ValueStorageMap {
346352
}
347353

348354
/// Return the non-projection storage that this storage refers to. If this
349-
/// storage holds an Enum or any intermediate storage that projects into this
350-
/// storage holds an Enum, then return nullptr.
351-
const ValueStorage *getNonEnumBaseStorage(SILValue value) {
355+
/// storage requires materializing an instruction that performs
356+
/// initialization side effects (init_enum_data_addr, init_existential_addr),
357+
/// return nullptr.
358+
const ValueStorage *getNonInitializingBaseStorage(SILValue value) {
352359
for (auto *pair : getProjections(value)) {
353360
auto const &storage = pair->storage;
354-
if (storage.initializesEnum)
361+
if (storage.initializes)
355362
return nullptr;
356363

357364
if (storage.isUseProjection) {
@@ -365,12 +372,12 @@ class ValueStorageMap {
365372
}
366373

367374
/// Return the non-projection storage that this storage refers to, or nullptr
368-
/// if \p allowInitEnum is true and the storage initializes an Enum.
369-
const ValueStorage *getBaseStorage(SILValue value, bool allowInitEnum) {
370-
if (allowInitEnum)
375+
/// if \p allowInit is true and the storage initializes an Enum.
376+
const ValueStorage *getBaseStorage(SILValue value, bool allowInit) {
377+
if (allowInit)
371378
return &getBaseStorage(value);
372379

373-
return getNonEnumBaseStorage(value);
380+
return getNonInitializingBaseStorage(value);
374381
}
375382

376383
void setStorageAddress(SILValue value, SILValue addr) {

0 commit comments

Comments
 (0)