Skip to content

Commit 2d5276d

Browse files
committed
Clean up l-value emission in SILGen.
There were several bits of code which were unnecessarily repeating the core logic of breaking down an access strategy and either setting up an LValue or directly emitting it. These places have now been unified to just create and then load or othrwise use an LValue. Introduce a visitor which handles the common parts of breaking down an access strategy and computing information like the LValueTypeData. In addition to its direct benefits (which are somewhat lost in the boilerplate of capturing local state into the visitor subclass), this eliminates some of the ad-hocness of how the various emission paths use AccessStrategy. Finally, implement the MaterializeToTemporary strategy in its full generality by using the actual read and write sub-strategies instead of always falling back on calling the getter and setter. This part is not NFC because it causes us to perform the read part of a read/write to a stored-with-observers property by directly accessing the storage instead of calling the getter.
1 parent 08ec1ba commit 2d5276d

File tree

10 files changed

+784
-647
lines changed

10 files changed

+784
-647
lines changed

lib/SILGen/LValue.h

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ class PathComponent {
105105

106106
// Logical LValue kinds
107107
GetterSetterKind, // property or subscript getter/setter
108+
MaterializeToTemporaryKind,
108109
OwnershipKind, // weak pointer remapping
109110
AutoreleasingWritebackKind, // autorelease pointer on set
110111
WritebackPseudoKind, // a fake component to customize writeback
@@ -261,13 +262,15 @@ class LogicalPathComponent : public PathComponent {
261262
virtual RValue get(SILGenFunction &SGF, SILLocation loc,
262263
ManagedValue base, SGFContext c) && = 0;
263264

264-
/// Compare 'this' lvalue and the 'rhs' lvalue (which is guaranteed to have
265-
/// the same dynamic PathComponent type as the receiver) to see if they are
266-
/// identical. If so, there is a conflicting writeback happening, so emit a
267-
/// diagnostic.
268-
virtual void diagnoseWritebackConflict(LogicalPathComponent *rhs,
269-
SILLocation loc1, SILLocation loc2,
270-
SILGenFunction &SGF) = 0;
265+
struct AccessedStorage {
266+
AbstractStorageDecl *Storage;
267+
bool IsSuper;
268+
const RValue *Indices;
269+
Expr *IndexExprForDiagnostics;
270+
};
271+
272+
/// Get the storage accessed by this component.
273+
virtual Optional<AccessedStorage> getAccessedStorage() const = 0;
271274

272275

273276
/// Materialize the storage into memory. If the access is for
@@ -313,10 +316,8 @@ class TranslationPathComponent : public LogicalPathComponent {
313316
return kind;
314317
}
315318

316-
void diagnoseWritebackConflict(LogicalPathComponent *RHS,
317-
SILLocation loc1, SILLocation loc2,
318-
SILGenFunction &SGF) override {
319-
// no useful writeback diagnostics at this point
319+
Optional<AccessedStorage> getAccessedStorage() const override {
320+
return None;
320321
}
321322

322323
RValue get(SILGenFunction &SGF, SILLocation loc,
@@ -428,25 +429,28 @@ class LValue {
428429
Path.emplace_back(new T(std::forward<As>(args)...));
429430
}
430431

432+
void addNonMemberVarComponent(SILGenFunction &SGF, SILLocation loc,
433+
VarDecl *var, Optional<SubstitutionMap> subs,
434+
LValueOptions options,
435+
AccessStrategy strategy,
436+
CanType formalRValueType);
437+
431438
/// Add a member component to the access path of this lvalue.
432439
void addMemberComponent(SILGenFunction &SGF, SILLocation loc,
433440
AbstractStorageDecl *storage,
434441
SubstitutionMap subs,
435442
LValueOptions options,
436443
bool isSuper,
437-
AccessKind accessKind,
438-
AccessSemantics accessSemantics,
439444
AccessStrategy accessStrategy,
440445
CanType formalRValueType,
441-
RValue &&indices);
446+
RValue &&indices,
447+
Expr *indexExprForDiagnostics);
442448

443449
void addMemberVarComponent(SILGenFunction &SGF, SILLocation loc,
444450
VarDecl *var,
445451
SubstitutionMap subs,
446452
LValueOptions options,
447453
bool isSuper,
448-
AccessKind accessKind,
449-
AccessSemantics accessSemantics,
450454
AccessStrategy accessStrategy,
451455
CanType formalRValueType);
452456

@@ -455,8 +459,6 @@ class LValue {
455459
SubstitutionMap subs,
456460
LValueOptions options,
457461
bool isSuper,
458-
AccessKind accessKind,
459-
AccessSemantics accessSemantics,
460462
AccessStrategy accessStrategy,
461463
CanType formalRValueType,
462464
RValue &&indices,

lib/SILGen/SILGen.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,8 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
334334

335335
SILDeclRef getGetterDeclRef(AbstractStorageDecl *decl);
336336
SILDeclRef getSetterDeclRef(AbstractStorageDecl *decl);
337-
SILDeclRef getAddressorDeclRef(AbstractStorageDecl *decl,
338-
AccessKind accessKind);
337+
SILDeclRef getAddressorDeclRef(AbstractStorageDecl *decl);
338+
SILDeclRef getMutableAddressorDeclRef(AbstractStorageDecl *decl);
339339
SILDeclRef getMaterializeForSetDeclRef(AbstractStorageDecl *decl);
340340

341341
KeyPathPatternComponent

lib/SILGen/SILGenApply.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5364,9 +5364,14 @@ emitMaterializeForSetAccessor(SILLocation loc, SILDeclRef materializeForSet,
53645364
optionalCallback, callbackStorage);
53655365
}
53665366

5367-
SILDeclRef SILGenModule::getAddressorDeclRef(AbstractStorageDecl *storage,
5368-
AccessKind accessKind) {
5369-
FuncDecl *addressorFunc = storage->getAddressorForAccess(accessKind);
5367+
SILDeclRef SILGenModule::getAddressorDeclRef(AbstractStorageDecl *storage) {
5368+
FuncDecl *addressorFunc = storage->getAddressor();
5369+
return SILDeclRef(addressorFunc, SILDeclRef::Kind::Func);
5370+
}
5371+
5372+
SILDeclRef SILGenModule::getMutableAddressorDeclRef(
5373+
AbstractStorageDecl *storage) {
5374+
FuncDecl *addressorFunc = storage->getMutableAddressor();
53705375
return SILDeclRef(addressorFunc, SILDeclRef::Kind::Func);
53715376
}
53725377

lib/SILGen/SILGenExpr.cpp

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -955,7 +955,7 @@ static SILDeclRef getRValueAccessorDeclRef(SILGenFunction &SGF,
955955
if (accessor == AccessorKind::Get) {
956956
return SGF.SGM.getGetterDeclRef(storage);
957957
} else {
958-
return SGF.SGM.getAddressorDeclRef(storage, AccessKind::Read);
958+
return SGF.SGM.getAddressorDeclRef(storage);
959959
}
960960
}
961961

@@ -3188,17 +3188,9 @@ static SILFunction *getOrCreateKeyPathSetter(SILGenModule &SGM,
31883188
auto strategy = property->getAccessStrategy(semantics, AccessKind::Write);
31893189

31903190
LValueOptions lvOptions;
3191-
if (auto var = dyn_cast<VarDecl>(property)) {
3192-
lv.addMemberVarComponent(subSGF, loc, var, subs, lvOptions,
3193-
/*super*/ false, AccessKind::Write,
3194-
semantics, strategy, propertyType);
3195-
} else {
3196-
auto sub = cast<SubscriptDecl>(property);
3197-
lv.addMemberSubscriptComponent(subSGF, loc, sub, subs, lvOptions,
3198-
/*super*/ false, AccessKind::Write,
3199-
semantics, strategy, propertyType,
3200-
std::move(indexValue));
3201-
}
3191+
lv.addMemberComponent(subSGF, loc, property, subs, lvOptions,
3192+
/*super*/ false, strategy, propertyType,
3193+
std::move(indexValue), /*index for diags*/ nullptr);
32023194

32033195
subSGF.emitAssignToLValue(loc,
32043196
RValue(subSGF, loc, propertyType, valueSubst),
@@ -5349,14 +5341,8 @@ class AutoreleasingWritebackComponent : public LogicalPathComponent {
53495341
return RValue(SGF, ManagedValue::forUnmanaged(unowned), refType);
53505342
}
53515343

5352-
/// Compare 'this' lvalue and the 'rhs' lvalue (which is guaranteed to have
5353-
/// the same dynamic PathComponent type as the receiver) to see if they are
5354-
/// identical. If so, there is a conflicting writeback happening, so emit a
5355-
/// diagnostic.
5356-
void diagnoseWritebackConflict(LogicalPathComponent *RHS,
5357-
SILLocation loc1, SILLocation loc2,
5358-
SILGenFunction &SGF) override {
5359-
// auto &rhs = (GetterSetterComponent&)*RHS;
5344+
Optional<AccessedStorage> getAccessedStorage() const override {
5345+
return None;
53605346
}
53615347

53625348
void dump(raw_ostream &OS, unsigned indent) const override {

lib/SILGen/SILGenFunction.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,11 +1065,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
10651065
AccessKind accessKind);
10661066

10671067
// FIXME: demote this to private state.
1068-
ManagedValue maybeEmitAddressOfNonMemberVarDecl(SILLocation loc,
1069-
VarDecl *var,
1070-
CanType formalRValueType,
1071-
AccessKind accessKind,
1072-
AccessSemantics semantics);
1068+
ManagedValue maybeEmitValueOfLocalVarDecl(VarDecl *var);
10731069

10741070
/// Produce an RValue for a reference to the specified declaration,
10751071
/// with the given type and in response to the specified expression. Try to

0 commit comments

Comments
 (0)