@@ -223,6 +223,63 @@ ManagedValue LogicalPathComponent::getMaterialized(SILGenFunction &SGF,
223
223
SILLocation loc,
224
224
ManagedValue base,
225
225
AccessKind kind) && {
226
+ if (getTypeOfRValue ().getSwiftRValueType ()->hasOpenedExistential ()) {
227
+ if (kind == AccessKind::Read) {
228
+ // Emit a 'get' into the temporary.
229
+ RValue value =
230
+ std::move (*this ).get (SGF, loc, base, SGFContext ());
231
+
232
+ // Create a temporary.
233
+ std::unique_ptr<TemporaryInitialization> temporaryInit =
234
+ SGF.emitFormalAccessTemporary (loc,
235
+ SGF.getTypeLowering (getTypeOfRValue ()));
236
+
237
+ std::move (value).forwardInto (SGF, loc, temporaryInit.get ());
238
+
239
+ return temporaryInit->getManagedAddress ();
240
+ }
241
+
242
+ assert (SGF.InWritebackScope &&
243
+ " materializing l-value for modification without writeback scope" );
244
+
245
+ // Clone anything else about the component that we might need in the
246
+ // writeback.
247
+ auto clonedComponent = clone (SGF, loc);
248
+
249
+ SILValue mv;
250
+ {
251
+ FormalEvaluationScope Scope (SGF);
252
+
253
+ // Otherwise, we need to emit a get and set. Borrow the base for
254
+ // the getter.
255
+ ManagedValue getterBase =
256
+ base ? base.formalAccessBorrow (SGF, loc) : ManagedValue ();
257
+
258
+ // Emit a 'get' into a temporary and then pop the borrow of base.
259
+ RValue value =
260
+ std::move (*this ).get (SGF, loc, getterBase, SGFContext ());
261
+
262
+ mv = std::move (value).forwardAsSingleValue (SGF, loc);
263
+ }
264
+
265
+ auto &TL = SGF.getTypeLowering (getTypeOfRValue ());
266
+
267
+ // Create a temporary.
268
+ std::unique_ptr<TemporaryInitialization> temporaryInit =
269
+ SGF.emitFormalAccessTemporary (loc, TL);
270
+
271
+ SGF.emitSemanticStore (loc, mv, temporaryInit->getAddress (),
272
+ TL, IsInitialization);
273
+ temporaryInit->finishInitialization (SGF);
274
+
275
+ auto temporary = temporaryInit->getManagedAddress ();
276
+
277
+ // Push a writeback for the temporary.
278
+ pushWriteback (SGF, loc, std::move (clonedComponent), base,
279
+ MaterializedLValue (temporary));
280
+ return temporary.unmanagedBorrow ();
281
+ }
282
+
226
283
// If this is just for a read, emit a load into a temporary memory
227
284
// location.
228
285
if (kind == AccessKind::Read) {
@@ -579,20 +636,34 @@ namespace {
579
636
public:
580
637
OpenOpaqueExistentialComponent (CanArchetypeType openedArchetype)
581
638
: PhysicalPathComponent(getOpenedArchetypeTypeData(openedArchetype),
582
- OpenedExistentialKind ) {}
639
+ OpenOpaqueExistentialKind ) {}
583
640
584
641
ManagedValue offset (SILGenFunction &SGF, SILLocation loc, ManagedValue base,
585
642
AccessKind accessKind) && override {
586
643
assert (base.getType ().isExistentialType () &&
587
644
" base for open existential component must be an existential" );
588
645
assert (base.getType ().isAddress () &&
589
646
" base value of open-existential component was not an address?" );
590
- assert (base.getType ().getPreferredExistentialRepresentation (SGF.SGM .M )
591
- == ExistentialRepresentation::Opaque);
647
+ SILValue addr;
592
648
593
- SILValue addr = SGF.B .createOpenExistentialAddr (
649
+ auto rep = base.getType ().getPreferredExistentialRepresentation (SGF.SGM .M );
650
+ switch (rep) {
651
+ case ExistentialRepresentation::Opaque:
652
+ addr = SGF.B .createOpenExistentialAddr (
594
653
loc, base.getValue (), getTypeOfRValue ().getAddressType (),
595
654
getOpenedExistentialAccessFor (accessKind));
655
+ break ;
656
+ case ExistentialRepresentation::Boxed: {
657
+ auto &TL = SGF.getTypeLowering (base.getType ());
658
+ auto error = SGF.emitLoad (loc, base.getValue (), TL,
659
+ SGFContext (), IsNotTake);
660
+ addr = SGF.B .createOpenExistentialBox (
661
+ loc, error.getValue (), getTypeOfRValue ().getAddressType ());
662
+ break ;
663
+ }
664
+ default :
665
+ llvm_unreachable (" Bad existential representation for address-only type" );
666
+ }
596
667
597
668
SGF.setArchetypeOpeningSite (cast<ArchetypeType>(getSubstFormalType ()),
598
669
addr);
@@ -604,6 +675,89 @@ namespace {
604
675
}
605
676
};
606
677
678
+ // / A local path component for the payload of a class existential.
679
+ // /
680
+ // / TODO: Could be physical if we had a way to project out the
681
+ // / payload.
682
+ class OpenClassExistentialComponent : public LogicalPathComponent {
683
+ static LValueTypeData getOpenedArchetypeTypeData (CanArchetypeType type) {
684
+ return {
685
+ AbstractionPattern::getOpaque (), type,
686
+ SILType::getPrimitiveObjectType (type)
687
+ };
688
+ }
689
+ public:
690
+ OpenClassExistentialComponent (CanArchetypeType openedArchetype)
691
+ : LogicalPathComponent(getOpenedArchetypeTypeData(openedArchetype),
692
+ OpenClassExistentialKind) {}
693
+
694
+ AccessKind getBaseAccessKind (SILGenFunction &SGF,
695
+ AccessKind kind) const override {
696
+ // Always use the same access kind for the base.
697
+ return kind;
698
+ }
699
+
700
+ void diagnoseWritebackConflict (LogicalPathComponent *RHS,
701
+ SILLocation loc1, SILLocation loc2,
702
+ SILGenFunction &SGF) override {
703
+ // no useful writeback diagnostics at this point
704
+ }
705
+
706
+ RValue get (SILGenFunction &SGF, SILLocation loc,
707
+ ManagedValue base, SGFContext c) && override {
708
+ auto refType = base.getType ().getObjectType ();
709
+ auto &TL = SGF.getTypeLowering (refType);
710
+
711
+ // Load the original value.
712
+ auto result = SGF.emitLoad (loc, base.getValue (), TL,
713
+ SGFContext (), IsNotTake);
714
+
715
+ assert (refType.isExistentialType () &&
716
+ " base for open existential component must be an existential" );
717
+ assert (refType.getPreferredExistentialRepresentation (SGF.SGM .M )
718
+ == ExistentialRepresentation::Class);
719
+ auto ref = SGF.B .createOpenExistentialRef (
720
+ loc, result, getTypeOfRValue ());
721
+
722
+ SGF.setArchetypeOpeningSite (cast<ArchetypeType>(getSubstFormalType ()),
723
+ ref.getValue ());
724
+
725
+ return RValue (SGF, loc, getSubstFormalType (), ref);
726
+ }
727
+
728
+ void set (SILGenFunction &SGF, SILLocation loc,
729
+ RValue &&value, ManagedValue base) && override {
730
+ auto payload = std::move (value).forwardAsSingleValue (SGF, loc);
731
+
732
+ SmallVector<ProtocolConformanceRef, 2 > conformances;
733
+ for (auto proto : cast<ArchetypeType>(getSubstFormalType ())->getConformsTo ())
734
+ conformances.push_back (ProtocolConformanceRef (proto));
735
+
736
+ auto ref = SGF.B .createInitExistentialRef (
737
+ loc,
738
+ base.getType ().getObjectType (),
739
+ getSubstFormalType (),
740
+ payload,
741
+ SGF.getASTContext ().AllocateCopy (conformances));
742
+
743
+ auto &TL = SGF.getTypeLowering (base.getType ());
744
+ SGF.emitSemanticStore (loc, ref,
745
+ base.getValue (), TL, IsNotInitialization);
746
+ }
747
+
748
+ std::unique_ptr<LogicalPathComponent>
749
+ clone (SILGenFunction &SGF, SILLocation loc) const override {
750
+ LogicalPathComponent *clone =
751
+ new OpenClassExistentialComponent (
752
+ cast<ArchetypeType>(getSubstFormalType ()));
753
+ return std::unique_ptr<LogicalPathComponent>(clone);
754
+ }
755
+
756
+ void print (raw_ostream &OS) const override {
757
+ OS << " OpenClassExistentialComponent(...)\n " ;
758
+ }
759
+ };
760
+
607
761
// / A physical path component which returns a literal address.
608
762
class ValueComponent : public PhysicalPathComponent {
609
763
ManagedValue Value;
@@ -1914,9 +2068,11 @@ LValue SILGenLValue::visitOpaqueValueExpr(OpaqueValueExpr *e,
1914
2068
SGF.OpaqueValueExprs .erase (known);
1915
2069
1916
2070
// Do formal evaluation of the underlying existential lvalue.
1917
- LValue lv = visitRec (opened->getExistentialValue (), accessKind);
1918
- lv.add <OpenOpaqueExistentialComponent>(
1919
- cast<ArchetypeType>(opened->getOpenedArchetype ()->getCanonicalType ()));
2071
+ auto lv = visitRec (opened->getExistentialValue (), accessKind);
2072
+ lv = SGF.emitOpenExistentialLValue (
2073
+ opened, std::move (lv),
2074
+ CanArchetypeType (opened->getOpenedArchetype ()),
2075
+ accessKind);
1920
2076
return lv;
1921
2077
}
1922
2078
@@ -2817,6 +2973,32 @@ ManagedValue SILGenFunction::emitAddressOfLValue(SILLocation loc,
2817
2973
return ManagedValue::forLValue (addr.getValue ());
2818
2974
}
2819
2975
2976
+ LValue
2977
+ SILGenFunction::emitOpenExistentialLValue (SILLocation loc,
2978
+ LValue &&lv,
2979
+ CanArchetypeType openedArchetype,
2980
+ AccessKind accessKind) {
2981
+ // Open up the existential.
2982
+ auto rep = lv.getTypeOfRValue ()
2983
+ .getPreferredExistentialRepresentation (SGM.M );
2984
+ switch (rep) {
2985
+ case ExistentialRepresentation::Opaque:
2986
+ case ExistentialRepresentation::Boxed: {
2987
+ lv.add <OpenOpaqueExistentialComponent>(openedArchetype);
2988
+ break ;
2989
+ }
2990
+ case ExistentialRepresentation::Class: {
2991
+ lv.add <OpenClassExistentialComponent>(openedArchetype);
2992
+ break ;
2993
+ }
2994
+ default :
2995
+ llvm_unreachable (" Cannot perform lvalue access of "
2996
+ " non-opaque, non-class existential" );
2997
+ }
2998
+
2999
+ return std::move (lv);
3000
+ }
3001
+
2820
3002
void SILGenFunction::emitAssignToLValue (SILLocation loc, RValue &&src,
2821
3003
LValue &&dest) {
2822
3004
FormalEvaluationScope scope (*this );
0 commit comments