Skip to content

Commit 0eb69d3

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 9172d66 commit 0eb69d3

File tree

3 files changed

+75
-16
lines changed

3 files changed

+75
-16
lines changed

lib/SILGen/LValue.h

+1-1
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

+2-1
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,8 @@ ManagedValue SILGenBuilder::createUncheckedBitCast(SILLocation loc,
625625
// updated.
626626
assert((isa<UncheckedTrivialBitCastInst>(cast) ||
627627
isa<UncheckedRefCastInst>(cast) ||
628-
isa<UncheckedBitwiseCastInst>(cast)) &&
628+
isa<UncheckedBitwiseCastInst>(cast) ||
629+
isa<ConvertFunctionInst>(cast)) &&
629630
"SILGenBuilder is out of sync with SILBuilder.");
630631

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

lib/SILGen/SILGenLValue.cpp

+72-14
Original file line numberDiff line numberDiff line change
@@ -2198,26 +2198,82 @@ namespace {
21982198
}
21992199
};
22002200

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

2208-
ManagedValue project(SILGenFunction &SGF, SILLocation loc,
2209-
ManagedValue base) && override {
2210-
auto toType = SGF.getLoweredType(getTypeData().SubstFormalType)
2211-
.getAddressType();
2249+
bool isLoadingPure() const override { return true; }
22122250

2213-
if (base.getType() == toType)
2214-
return base; // nothing to do
2251+
/// Used during write operations to convert the value prior to writing to
2252+
/// the base.
2253+
RValue untranslate(SILGenFunction &SGF, SILLocation loc,
2254+
RValue &&rv, SGFContext c) && override {
2255+
return doUncheckedConversion(SGF, loc, std::move(rv),
2256+
getUntranslatedType());
2257+
}
22152258

2216-
return SGF.B.createUncheckedAddrCast(loc, base, toType);
2259+
/// Used during read operations to convert the value after reading the base.
2260+
RValue translate(SILGenFunction &SGF, SILLocation loc,
2261+
RValue &&rv, SGFContext c) && override {
2262+
return doUncheckedConversion(SGF, loc, std::move(rv),
2263+
getTranslatedType());
2264+
}
2265+
2266+
std::unique_ptr<LogicalPathComponent>
2267+
clone(SILGenFunction &SGF, SILLocation loc) const override {
2268+
return std::make_unique<UncheckedConversionComponent>(getTypeData(),
2269+
OrigType);
22172270
}
22182271

22192272
void dump(raw_ostream &OS, unsigned indent) const override {
2220-
OS.indent(indent) << "ABISafeConversionComponent\n";
2273+
OS.indent(indent) << "UncheckedConversionComponent"
2274+
<< "\n\tfromType: " << getUntranslatedType()
2275+
<< "\n\ttoType: " << getTranslatedType()
2276+
<< "\n";
22212277
}
22222278
};
22232279
} // end anonymous namespace
@@ -3756,7 +3812,9 @@ LValue SILGenLValue::visitABISafeConversionExpr(ABISafeConversionExpr *e,
37563812
LValue lval = visitRec(e->getSubExpr(), accessKind, options);
37573813
auto typeData = getValueTypeData(SGF, accessKind, e);
37583814

3759-
lval.add<ABISafeConversionComponent>(typeData);
3815+
auto OrigType = e->getSubExpr()->getType();
3816+
3817+
lval.add<UncheckedConversionComponent>(typeData, OrigType);
37603818

37613819
return lval;
37623820
}

0 commit comments

Comments
 (0)