Skip to content

Commit 5af68bb

Browse files
committed
[AddressLowering] Prevent existential multi-init.
1 parent 9688588 commit 5af68bb

File tree

2 files changed

+24
-16
lines changed

2 files changed

+24
-16
lines changed

lib/SILOptimizer/Mandatory/AddressLowering.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ void ValueStorage::dump() const {
434434
llvm::dbgs() << "isDefProjection: " << isDefProjection << "\n";
435435
llvm::dbgs() << "isUseProjection: " << isUseProjection << "\n";
436436
llvm::dbgs() << "isRewritten: " << isRewritten << "\n";
437-
llvm::dbgs() << "initializesEnum: " << initializesEnum << "\n";
437+
llvm::dbgs() << "initializes: " << initializes << "\n";
438438
}
439439
void ValueStorageMap::ValueStoragePair::dump() const {
440440
llvm::dbgs() << "value: ";
@@ -1066,8 +1066,9 @@ void ValueStorageMap::recordComposingUseProjection(Operand *oper,
10661066

10671067
storage.isUseProjection = true;
10681068

1069-
if (userValue->getType().getEnumOrBoundGenericEnum()) {
1070-
storage.initializesEnum = true;
1069+
if (userValue->getType().getEnumOrBoundGenericEnum() ||
1070+
userValue->getType().isExistentialType()) {
1071+
storage.initializes = true;
10711072
}
10721073
assert(!storage.isPhiProjection());
10731074
}
@@ -1262,7 +1263,7 @@ bool OpaqueStorageAllocation::findProjectionIntoUseImpl(
12621263
// to initialize an enum rather than the init_enum_data_addr to reuse enum
12631264
// storage across multiple subobjects within the payload.
12641265
auto *baseStorage = pass.valueStorageMap.getBaseStorage(
1265-
userValue, /*allowInitEnum*/ !intoPhi);
1266+
userValue, /*allowInit*/ !intoPhi);
12661267
if (!baseStorage)
12671268
continue;
12681269

lib/SILOptimizer/Mandatory/AddressLowering.h

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

103-
// This is a use-projection into an enum. Tracked to avoid projecting enums
104-
// across phis, which would result in piecewise initialization.
105-
unsigned initializesEnum : 1;
103+
// This is a use-projection which performs an initialization side-effect,
104+
// either into an enum or an existential.
105+
//
106+
// Tracked to avoid projecting enums/existentials across phis, which would
107+
// result in piecewise initialization.
108+
//
109+
// Note that the corresponding value is the payload, not the
110+
// enum instruction.
111+
unsigned initializes : 1;
106112

107113
ValueStorage(SILValue storageAddress): storageAddress(storageAddress) {
108114
isDefProjection = false;
109115
isUseProjection = false;
110116
isRewritten = false;
111-
initializesEnum = false;
117+
initializes = false;
112118

113119
// The initial storage address is only valid when the value is effectively
114120
// already rewritten.
@@ -299,12 +305,13 @@ class ValueStorageMap {
299305
}
300306

301307
/// Return the non-projection storage that this storage refers to. If this
302-
/// storage holds an Enum or any intermediate storage that projects into this
303-
/// storage holds an Enum, then return nullptr.
304-
const ValueStorage *getNonEnumBaseStorage(SILValue value) {
308+
/// storage requires materializing an instruction that performs
309+
/// initialization side effects (init_enum_data_addr, init_existential_addr),
310+
/// return nullptr.
311+
const ValueStorage *getNonInitializingBaseStorage(SILValue value) {
305312
for (auto *pair : getProjections(value)) {
306313
auto const &storage = pair->storage;
307-
if (storage.initializesEnum)
314+
if (storage.initializes)
308315
return nullptr;
309316

310317
if (storage.isUseProjection) {
@@ -318,12 +325,12 @@ class ValueStorageMap {
318325
}
319326

320327
/// Return the non-projection storage that this storage refers to, or nullptr
321-
/// if \p allowInitEnum is true and the storage initializes an Enum.
322-
const ValueStorage *getBaseStorage(SILValue value, bool allowInitEnum) {
323-
if (allowInitEnum)
328+
/// if \p allowInit is true and the storage initializes an Enum.
329+
const ValueStorage *getBaseStorage(SILValue value, bool allowInit) {
330+
if (allowInit)
324331
return &getBaseStorage(value);
325332

326-
return getNonEnumBaseStorage(value);
333+
return getNonInitializingBaseStorage(value);
327334
}
328335

329336
void setStorageAddress(SILValue value, SILValue addr) {

0 commit comments

Comments
 (0)