Skip to content

Commit 1fcf92b

Browse files
authored
Merge pull request #20352 from rjmccall/read-accessor-keypaths
Make the general path of emitRValueForStorageLoad use LValues
2 parents 022a2ff + c1b31b4 commit 1fcf92b

File tree

3 files changed

+173
-246
lines changed

3 files changed

+173
-246
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 0 additions & 246 deletions
Original file line numberDiff line numberDiff line change
@@ -903,252 +903,6 @@ emitRValueForDecl(SILLocation loc, ConcreteDeclRef declRef, Type ncRefType,
903903
return RValue(*this, loc, refType, result);
904904
}
905905

906-
static AbstractionPattern
907-
getFormalStorageAbstractionPattern(SILGenFunction &SGF, AbstractStorageDecl *field) {
908-
if (auto var = dyn_cast<VarDecl>(field)) {
909-
auto origType = SGF.SGM.Types.getAbstractionPattern(var);
910-
return origType.getReferenceStorageReferentType();
911-
}
912-
auto sub = cast<SubscriptDecl>(field);
913-
return SGF.SGM.Types.getAbstractionPattern(sub);
914-
}
915-
916-
static SILDeclRef getRValueAccessorDeclRef(SILGenFunction &SGF,
917-
AbstractStorageDecl *storage,
918-
AccessStrategy strategy) {
919-
switch (strategy.getKind()) {
920-
case AccessStrategy::BehaviorStorage:
921-
llvm_unreachable("shouldn't load an rvalue via behavior storage!");
922-
923-
case AccessStrategy::Storage:
924-
llvm_unreachable("should already have been filtered out!");
925-
926-
case AccessStrategy::MaterializeToTemporary:
927-
llvm_unreachable("never used for read accesses");
928-
929-
case AccessStrategy::DirectToAccessor:
930-
case AccessStrategy::DispatchToAccessor: {
931-
auto accessor = strategy.getAccessor();
932-
return SGF.SGM.getAccessorDeclRef(storage->getAccessor(accessor));
933-
}
934-
}
935-
llvm_unreachable("should already have been filtered out!");
936-
}
937-
938-
static RValue getTargetRValue(SILGenFunction &SGF, SILLocation loc,
939-
ManagedValue value,
940-
AbstractionPattern origFormalType,
941-
CanType substFormalType,
942-
SGFContext C) {
943-
SILType loweredSubstType = SGF.getLoweredType(substFormalType);
944-
945-
bool hasAbstraction =
946-
(loweredSubstType.getObjectType() != value.getType().getObjectType());
947-
948-
if (value.isLValue() ||
949-
(value.getType().isAddress() && !loweredSubstType.isAddress())) {
950-
auto isTake =
951-
IsTake_t(!value.isLValue() && !value.isPlusZeroRValueOrTrivial());
952-
value = SGF.emitLoad(loc,
953-
(isTake ? value.forward(SGF)
954-
: value.getUnmanagedValue()),
955-
SGF.getTypeLowering(value.getType()),
956-
(hasAbstraction ? SGFContext() : C),
957-
isTake);
958-
}
959-
960-
RValue result(SGF, loc, substFormalType, value);
961-
if (hasAbstraction) {
962-
result = SGF.emitOrigToSubstValue(loc, std::move(result), origFormalType,
963-
substFormalType, C);
964-
}
965-
return result;
966-
}
967-
968-
static RValue
969-
emitRValueWithAccessor(SILGenFunction &SGF, SILLocation loc,
970-
AbstractStorageDecl *storage,
971-
SubstitutionMap substitutions,
972-
ArgumentSource &&baseRV,
973-
PreparedArguments &&subscriptIndices,
974-
bool isSuper, AccessStrategy strategy,
975-
SILDeclRef accessor,
976-
AbstractionPattern origFormalType,
977-
CanType substFormalType,
978-
SGFContext C) {
979-
assert(strategy.getKind() == AccessStrategy::DirectToAccessor ||
980-
strategy.getKind() == AccessStrategy::DispatchToAccessor);
981-
bool isDirectUse = (strategy.getKind() == AccessStrategy::DirectToAccessor);
982-
983-
// The easy path here is if we don't need to use an addressor.
984-
if (strategy.getAccessor() == AccessorKind::Get) {
985-
return SGF.emitGetAccessor(loc, accessor, substitutions,
986-
std::move(baseRV), isSuper, isDirectUse,
987-
std::move(subscriptIndices), C);
988-
}
989-
990-
assert(strategy.getAccessor() == AccessorKind::Address);
991-
992-
auto &storageTL = SGF.getTypeLowering(origFormalType, substFormalType);
993-
SILType storageType = storageTL.getLoweredType().getAddressType();
994-
995-
auto addressorResult =
996-
SGF.emitAddressorAccessor(loc, accessor, substitutions,
997-
std::move(baseRV), isSuper, isDirectUse,
998-
std::move(subscriptIndices), storageType);
999-
1000-
RValue result = getTargetRValue(SGF, loc, addressorResult.first,
1001-
origFormalType, substFormalType, C);
1002-
1003-
switch (cast<AccessorDecl>(accessor.getDecl())->getAddressorKind()) {
1004-
case AddressorKind::NotAddressor: llvm_unreachable("inconsistent");
1005-
case AddressorKind::Unsafe:
1006-
// Nothing to do.
1007-
break;
1008-
case AddressorKind::Owning:
1009-
case AddressorKind::NativeOwning:
1010-
// Emit the release immediately.
1011-
SGF.B.emitDestroyValueOperation(loc, addressorResult.second.forward(SGF));
1012-
break;
1013-
}
1014-
1015-
return result;
1016-
}
1017-
1018-
/// Produce a singular RValue for a load from the specified property. This is
1019-
/// designed to work with RValue ManagedValue bases that are either +0 or +1.
1020-
RValue SILGenFunction::emitRValueForStorageLoad(
1021-
SILLocation loc, ManagedValue base, CanType baseFormalType,
1022-
bool isSuper, AbstractStorageDecl *storage,
1023-
PreparedArguments &&subscriptIndices,
1024-
SubstitutionMap substitutions,
1025-
AccessSemantics semantics, Type propTy, SGFContext C,
1026-
bool isBaseGuaranteed) {
1027-
AccessStrategy strategy =
1028-
storage->getAccessStrategy(semantics, AccessKind::Read, FunctionDC);
1029-
1030-
// If we should call an accessor of some kind, do so.
1031-
if (strategy.getKind() != AccessStrategy::Storage) {
1032-
auto accessor = getRValueAccessorDeclRef(*this, storage, strategy);
1033-
ArgumentSource baseRV = prepareAccessorBaseArg(loc, base,
1034-
baseFormalType,
1035-
accessor);
1036-
1037-
AbstractionPattern origFormalType =
1038-
getFormalStorageAbstractionPattern(*this, storage);
1039-
auto substFormalType = propTy->getCanonicalType();
1040-
1041-
return emitRValueWithAccessor(*this, loc, storage, substitutions,
1042-
std::move(baseRV),
1043-
std::move(subscriptIndices),
1044-
isSuper, strategy, accessor,
1045-
origFormalType, substFormalType, C);
1046-
}
1047-
assert(isa<VarDecl>(storage) && "only properties should have storage");
1048-
auto field = cast<VarDecl>(storage);
1049-
assert(field->hasStorage() &&
1050-
"Cannot directly access value without storage");
1051-
1052-
// For static variables, emit a reference to the global variable backing
1053-
// them.
1054-
// FIXME: This has to be dynamically looked up for classes, and
1055-
// dynamically instantiated for generics.
1056-
if (field->isStatic()) {
1057-
auto baseMeta = base.getType().castTo<MetatypeType>().getInstanceType();
1058-
(void)baseMeta;
1059-
assert(!baseMeta->is<BoundGenericType>() &&
1060-
"generic static stored properties not implemented");
1061-
if (field->getDeclContext()->getSelfClassDecl() &&
1062-
field->hasStorage())
1063-
// FIXME: don't need to check hasStorage, already done above
1064-
assert(field->isFinal() && "non-final class stored properties not implemented");
1065-
1066-
return emitRValueForDecl(loc, field, propTy, semantics, C);
1067-
}
1068-
1069-
1070-
// rvalue MemberRefExprs are produced in two cases: when accessing a 'let'
1071-
// decl member, and when the base is a (non-lvalue) struct.
1072-
assert(baseFormalType->getAnyNominal() &&
1073-
base.getType().getASTType()->getAnyNominal() &&
1074-
"The base of an rvalue MemberRefExpr should be an rvalue value");
1075-
1076-
// If the accessed field is stored, emit a StructExtract on the base.
1077-
1078-
auto substFormalType = propTy->getCanonicalType();
1079-
auto &lowering = getTypeLowering(substFormalType);
1080-
1081-
// Check for an abstraction difference.
1082-
AbstractionPattern origFormalType = getFormalStorageAbstractionPattern(*this, field);
1083-
bool hasAbstractionChange = false;
1084-
auto &abstractedTL = getTypeLowering(origFormalType, substFormalType);
1085-
if (!origFormalType.isExactType(substFormalType)) {
1086-
hasAbstractionChange =
1087-
(abstractedTL.getLoweredType() != lowering.getLoweredType());
1088-
}
1089-
1090-
// If the base is a reference type, just handle this as loading the lvalue.
1091-
ManagedValue result;
1092-
if (baseFormalType->hasReferenceSemantics()) {
1093-
LValue LV = emitPropertyLValue(loc, base, baseFormalType, field,
1094-
LValueOptions(),
1095-
SGFAccessKind::OwnedObjectRead,
1096-
AccessSemantics::DirectToStorage);
1097-
auto loaded = emitLoadOfLValue(loc, std::move(LV), C, isBaseGuaranteed);
1098-
// If we don't have to reabstract, the load is sufficient.
1099-
if (!hasAbstractionChange)
1100-
return loaded;
1101-
1102-
// Otherwise, bring the component up to +1 so we can reabstract it.
1103-
result = std::move(loaded).getAsSingleValue(*this, loc)
1104-
.copyUnmanaged(*this, loc);
1105-
} else if (!base.getType().isAddress()) {
1106-
// For non-address-only structs, we emit a struct_extract sequence.
1107-
result = B.createStructExtract(loc, base, field);
1108-
1109-
if (result.getType().is<ReferenceStorageType>()) {
1110-
// For weak and unowned types, convert the reference to the right
1111-
// pointer, producing a +1.
1112-
result = emitConversionToSemanticRValue(loc, result, lowering);
1113-
1114-
} else if (hasAbstractionChange ||
1115-
(!C.isImmediatePlusZeroOk() &&
1116-
!(C.isGuaranteedPlusZeroOk() && isBaseGuaranteed))) {
1117-
// If we have an abstraction change or if we have to produce a result at
1118-
// +1, then copy the value. If we know that our base will stay alive for
1119-
// the entire usage of this value, we can borrow the value at +0 for a
1120-
// guaranteed consumer. Otherwise, since we do not have enough information
1121-
// to know if the base's lifetime last's as long as our use of the access,
1122-
// we can only emit at +0 for immediate clients.
1123-
result = result.copyUnmanaged(*this, loc);
1124-
}
1125-
} else {
1126-
// Create a tiny unenforced access scope around a load from local memory. No
1127-
// cleanup is necessary since we directly emit the load here. This will
1128-
// probably go away with opaque values.
1129-
UnenforcedAccess access;
1130-
SILValue accessAddress =
1131-
access.beginAccess(*this, loc, base.getValue(), SILAccessKind::Read);
1132-
1133-
// For address-only sequences, the base is in memory. Emit a
1134-
// struct_element_addr to get to the field, and then load the element as an
1135-
// rvalue.
1136-
SILValue ElementPtr = B.createStructElementAddr(loc, accessAddress, field);
1137-
1138-
result = emitLoad(loc, ElementPtr, abstractedTL,
1139-
hasAbstractionChange ? SGFContext() : C, IsNotTake);
1140-
access.endAccess(*this);
1141-
}
1142-
1143-
// If we're accessing this member with an abstraction change, perform that
1144-
// now.
1145-
if (hasAbstractionChange)
1146-
result =
1147-
emitOrigToSubstValue(loc, result, origFormalType, substFormalType, C);
1148-
return RValue(*this, loc, substFormalType, result);
1149-
}
1150-
1151-
1152906
RValue RValueEmitter::visitDeclRefExpr(DeclRefExpr *E, SGFContext C) {
1153907
return SGF.emitRValueForDecl(E, E->getDeclRef(), E->getType(),
1154908
E->getAccessSemantics(), C);

0 commit comments

Comments
 (0)