Skip to content

Commit b84f01d

Browse files
committed
model the ABISafeConversionComponent as a translation component, rather than physical
Also renaming it to be UncheckedConversionComponent since it's a better name. As a physical component, we'd run into problems in assignment statements. The problem was that if we had something like: ``` SomeOtherComponent // first component GetterSetterComponent ABISafeConversionComponent // last component ``` When emitting the assignment, we always drill down through all but the last component by calling `project()` on each one. Then on the last component, we'd do the actual setting operation. But GetterSetterComponent cannot be projected when the access is for writing. So, to work around this I decided to model it as a TranslationComponent, because those are specifically designed to be handled during an assignment by popping those off the end of the component sequence, untranslating the value we're about to assign as we go, until we hit the GetterSetterComponent. By "untranslating" we're effectively putting Sendable back onto the set's argument prior to calling set, because the underlying property's type still has `@Sendable` on it (e.g., it's accessors still have that on its argument type). When "translating" we're effectively taking Sendable off after reading it. I think actually works really well and makes much more sense now. resolves rdar://99619834
1 parent 86def8f commit b84f01d

File tree

3 files changed

+75
-16
lines changed

3 files changed

+75
-16
lines changed

lib/SILGen/LValue.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ class PathComponent {
105105
CoroutineAccessorKind, // coroutine accessor
106106
ValueKind, // random base pointer as an lvalue
107107
PhysicalKeyPathApplicationKind, // applying a key path
108-
ABISafeConversionKind, // unchecked_addr_cast
109108

110109
// Logical LValue kinds
111110
GetterSetterKind, // property or subscript getter/setter
@@ -118,6 +117,7 @@ class PathComponent {
118117
// Translation LValue kinds (a subtype of logical)
119118
OrigToSubstKind, // generic type substitution
120119
SubstToOrigKind, // generic type substitution
120+
UncheckedConversionKind, // unchecked_X_cast
121121

122122
FirstLogicalKind = GetterSetterKind,
123123
FirstTranslationKind = OrigToSubstKind,

lib/SILGen/SILGenBuilder.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,8 @@ ManagedValue SILGenBuilder::createUncheckedBitCast(SILLocation loc,
620620
// updated.
621621
assert((isa<UncheckedTrivialBitCastInst>(cast) ||
622622
isa<UncheckedRefCastInst>(cast) ||
623-
isa<UncheckedBitwiseCastInst>(cast)) &&
623+
isa<UncheckedBitwiseCastInst>(cast) ||
624+
isa<ConvertFunctionInst>(cast)) &&
624625
"SILGenBuilder is out of sync with SILBuilder.");
625626

626627
// If we have a trivial inst, just return early.

lib/SILGen/SILGenLValue.cpp

Lines changed: 72 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2204,26 +2204,82 @@ namespace {
22042204
}
22052205
};
22062206

2207-
/// A physical component which performs an unchecked_addr_cast
2208-
class ABISafeConversionComponent final : public PhysicalPathComponent {
2207+
/// A translation component that performs \c unchecked_*_cast 's as-needed.
2208+
class UncheckedConversionComponent final : public TranslationPathComponent {
2209+
private:
2210+
Type OrigType;
2211+
2212+
/// \returns the type this component is trying to convert \b to
2213+
CanType getTranslatedType() const {
2214+
return getTypeData().SubstFormalType->getCanonicalType();
2215+
}
2216+
2217+
/// \returns the type this component is trying to convert \b from
2218+
CanType getUntranslatedType() const {
2219+
return OrigType->getRValueType()->getCanonicalType();
2220+
}
2221+
2222+
/// perform a conversion of ManagedValue -> ManagedValue
2223+
ManagedValue doUncheckedConversion(SILGenFunction &SGF, SILLocation loc,
2224+
ManagedValue val, CanType toType) {
2225+
auto toTy = SGF.getLoweredType(toType);
2226+
auto fromTy = val.getType();
2227+
2228+
if (fromTy == toTy)
2229+
return val; // nothing to do.
2230+
2231+
// otherwise emit the right kind of cast based on whether it's an address.
2232+
assert(fromTy.isAddress() == toTy.isAddress());
2233+
2234+
if (toTy.isAddress())
2235+
return SGF.B.createUncheckedAddrCast(loc, val, toTy);
2236+
2237+
return SGF.B.createUncheckedBitCast(loc, val, toTy);
2238+
}
2239+
2240+
/// perform a conversion of RValue -> RValue
2241+
RValue doUncheckedConversion(SILGenFunction &SGF, SILLocation loc,
2242+
RValue &&rv, CanType toType) {
2243+
auto val = std::move(rv).getAsSingleValue(SGF, loc);
2244+
val = doUncheckedConversion(SGF, loc, val, toType);
2245+
return RValue(SGF, loc, toType, val);
2246+
}
2247+
22092248
public:
2210-
ABISafeConversionComponent(LValueTypeData typeData)
2211-
: PhysicalPathComponent(typeData, ABISafeConversionKind,
2212-
/*actorIsolation=*/None) {}
2249+
/// \param OrigType is the type we are converting \b from
2250+
/// \param typeData will contain the type we are converting \b to
2251+
UncheckedConversionComponent(LValueTypeData typeData, Type OrigType)
2252+
: TranslationPathComponent(typeData, UncheckedConversionKind),
2253+
OrigType(OrigType) {}
22132254

2214-
ManagedValue project(SILGenFunction &SGF, SILLocation loc,
2215-
ManagedValue base) && override {
2216-
auto toType = SGF.getLoweredType(getTypeData().SubstFormalType)
2217-
.getAddressType();
2255+
bool isLoadingPure() const override { return true; }
22182256

2219-
if (base.getType() == toType)
2220-
return base; // nothing to do
2257+
/// Used during write operations to convert the value prior to writing to
2258+
/// the base.
2259+
RValue untranslate(SILGenFunction &SGF, SILLocation loc,
2260+
RValue &&rv, SGFContext c) && override {
2261+
return doUncheckedConversion(SGF, loc, std::move(rv),
2262+
getUntranslatedType());
2263+
}
22212264

2222-
return SGF.B.createUncheckedAddrCast(loc, base, toType);
2265+
/// Used during read operations to convert the value after reading the base.
2266+
RValue translate(SILGenFunction &SGF, SILLocation loc,
2267+
RValue &&rv, SGFContext c) && override {
2268+
return doUncheckedConversion(SGF, loc, std::move(rv),
2269+
getTranslatedType());
2270+
}
2271+
2272+
std::unique_ptr<LogicalPathComponent>
2273+
clone(SILGenFunction &SGF, SILLocation loc) const override {
2274+
return std::make_unique<UncheckedConversionComponent>(getTypeData(),
2275+
OrigType);
22232276
}
22242277

22252278
void dump(raw_ostream &OS, unsigned indent) const override {
2226-
OS.indent(indent) << "ABISafeConversionComponent\n";
2279+
OS.indent(indent) << "UncheckedConversionComponent"
2280+
<< "\n\tfromType: " << getUntranslatedType()
2281+
<< "\n\ttoType: " << getTranslatedType()
2282+
<< "\n";
22272283
}
22282284
};
22292285
} // end anonymous namespace
@@ -3741,7 +3797,9 @@ LValue SILGenLValue::visitABISafeConversionExpr(ABISafeConversionExpr *e,
37413797
LValue lval = visitRec(e->getSubExpr(), accessKind, options);
37423798
auto typeData = getValueTypeData(SGF, accessKind, e);
37433799

3744-
lval.add<ABISafeConversionComponent>(typeData);
3800+
auto OrigType = e->getSubExpr()->getType();
3801+
3802+
lval.add<UncheckedConversionComponent>(typeData, OrigType);
37453803

37463804
return lval;
37473805
}

0 commit comments

Comments
 (0)