@@ -227,6 +227,63 @@ ManagedValue LogicalPathComponent::getMaterialized(SILGenFunction &SGF,
227
227
SILLocation loc,
228
228
ManagedValue base,
229
229
AccessKind kind) && {
230
+ if (getTypeOfRValue ().getSwiftRValueType ()->hasOpenedExistential ()) {
231
+ if (kind == AccessKind::Read) {
232
+ // Emit a 'get' into the temporary.
233
+ RValue value =
234
+ std::move (*this ).get (SGF, loc, base, SGFContext ());
235
+
236
+ // Create a temporary.
237
+ std::unique_ptr<TemporaryInitialization> temporaryInit =
238
+ SGF.emitFormalAccessTemporary (loc,
239
+ SGF.getTypeLowering (getTypeOfRValue ()));
240
+
241
+ std::move (value).forwardInto (SGF, loc, temporaryInit.get ());
242
+
243
+ return temporaryInit->getManagedAddress ();
244
+ }
245
+
246
+ assert (SGF.InWritebackScope &&
247
+ " materializing l-value for modification without writeback scope" );
248
+
249
+ // Clone anything else about the component that we might need in the
250
+ // writeback.
251
+ auto clonedComponent = clone (SGF, loc);
252
+
253
+ SILValue mv;
254
+ {
255
+ FormalEvaluationScope Scope (SGF);
256
+
257
+ // Otherwise, we need to emit a get and set. Borrow the base for
258
+ // the getter.
259
+ ManagedValue getterBase =
260
+ base ? base.formalAccessBorrow (SGF, loc) : ManagedValue ();
261
+
262
+ // Emit a 'get' into a temporary and then pop the borrow of base.
263
+ RValue value =
264
+ std::move (*this ).get (SGF, loc, getterBase, SGFContext ());
265
+
266
+ mv = std::move (value).forwardAsSingleValue (SGF, loc);
267
+ }
268
+
269
+ auto &TL = SGF.getTypeLowering (getTypeOfRValue ());
270
+
271
+ // Create a temporary.
272
+ std::unique_ptr<TemporaryInitialization> temporaryInit =
273
+ SGF.emitFormalAccessTemporary (loc, TL);
274
+
275
+ SGF.emitSemanticStore (loc, mv, temporaryInit->getAddress (),
276
+ TL, IsInitialization);
277
+ temporaryInit->finishInitialization (SGF);
278
+
279
+ auto temporary = temporaryInit->getManagedAddress ();
280
+
281
+ // Push a writeback for the temporary.
282
+ pushWriteback (SGF, loc, std::move (clonedComponent), base,
283
+ MaterializedLValue (temporary));
284
+ return temporary.unmanagedBorrow ();
285
+ }
286
+
230
287
// If this is just for a read, emit a load into a temporary memory
231
288
// location.
232
289
if (kind == AccessKind::Read) {
@@ -574,30 +631,44 @@ namespace {
574
631
// / A physical path component which projects out an opened archetype
575
632
// / from an existential.
576
633
class OpenOpaqueExistentialComponent : public PhysicalPathComponent {
577
- static LValueTypeData getOpenedArchetypeTypeData (CanArchetypeType type) {
578
- return {
579
- AbstractionPattern::getOpaque (), type,
580
- SILType::getPrimitiveObjectType (type)
581
- };
634
+ CanArchetypeType getOpenedArchetype () const {
635
+ return cast<ArchetypeType>(getSubstFormalType ());
582
636
}
583
637
public:
584
- OpenOpaqueExistentialComponent (CanArchetypeType openedArchetype)
585
- : PhysicalPathComponent(getOpenedArchetypeTypeData(openedArchetype),
586
- OpenedExistentialKind) {}
638
+ OpenOpaqueExistentialComponent (CanArchetypeType openedArchetype,
639
+ LValueTypeData typeData)
640
+ : PhysicalPathComponent(typeData, OpenOpaqueExistentialKind) {
641
+ assert (getOpenedArchetype () == openedArchetype);
642
+ }
587
643
588
644
ManagedValue offset (SILGenFunction &SGF, SILLocation loc, ManagedValue base,
589
645
AccessKind accessKind) && override {
590
646
assert (base.getType ().isExistentialType () &&
591
647
" base for open existential component must be an existential" );
592
648
assert (base.getType ().isAddress () &&
593
649
" base value of open-existential component was not an address?" );
650
+ SILValue addr;
594
651
595
- SILValue addr = SGF.B .createOpenExistentialAddr (
652
+ auto rep = base.getType ().getPreferredExistentialRepresentation (SGF.SGM .M );
653
+ switch (rep) {
654
+ case ExistentialRepresentation::Opaque:
655
+ addr = SGF.B .createOpenExistentialAddr (
596
656
loc, base.getValue (), getTypeOfRValue ().getAddressType (),
597
657
getOpenedExistentialAccessFor (accessKind));
658
+ break ;
659
+ case ExistentialRepresentation::Boxed: {
660
+ auto &TL = SGF.getTypeLowering (base.getType ());
661
+ auto error = SGF.emitLoad (loc, base.getValue (), TL,
662
+ SGFContext (), IsNotTake);
663
+ addr = SGF.B .createOpenExistentialBox (
664
+ loc, error.getValue (), getTypeOfRValue ().getAddressType ());
665
+ break ;
666
+ }
667
+ default :
668
+ llvm_unreachable (" Bad existential representation for address-only type" );
669
+ }
598
670
599
- SGF.setArchetypeOpeningSite (cast<ArchetypeType>(getSubstFormalType ()),
600
- addr);
671
+ SGF.setArchetypeOpeningSite (getOpenedArchetype (), addr);
601
672
return ManagedValue::forLValue (addr);
602
673
}
603
674
@@ -606,6 +677,102 @@ namespace {
606
677
}
607
678
};
608
679
680
+ // / A local path component for the payload of a class or metatype existential.
681
+ // /
682
+ // / TODO: Could be physical if we had a way to project out the
683
+ // / payload.
684
+ class OpenNonOpaqueExistentialComponent : public LogicalPathComponent {
685
+ CanArchetypeType OpenedArchetype;
686
+ public:
687
+ OpenNonOpaqueExistentialComponent (CanArchetypeType openedArchetype,
688
+ LValueTypeData typeData)
689
+ : LogicalPathComponent(typeData, OpenNonOpaqueExistentialKind),
690
+ OpenedArchetype (openedArchetype) {}
691
+
692
+ AccessKind getBaseAccessKind (SILGenFunction &SGF,
693
+ AccessKind kind) const override {
694
+ // Always use the same access kind for the base.
695
+ return kind;
696
+ }
697
+
698
+ void diagnoseWritebackConflict (LogicalPathComponent *RHS,
699
+ SILLocation loc1, SILLocation loc2,
700
+ SILGenFunction &SGF) override {
701
+ // no useful writeback diagnostics at this point
702
+ }
703
+
704
+ RValue get (SILGenFunction &SGF, SILLocation loc,
705
+ ManagedValue base, SGFContext c) && override {
706
+ auto refType = base.getType ().getObjectType ();
707
+ auto &TL = SGF.getTypeLowering (refType);
708
+
709
+ // Load the original value.
710
+ auto result = SGF.emitLoad (loc, base.getValue (), TL,
711
+ SGFContext (), IsNotTake);
712
+
713
+ assert (refType.isAnyExistentialType () &&
714
+ " base for open existential component must be an existential" );
715
+ ManagedValue ref;
716
+ if (refType.is <ExistentialMetatypeType>()) {
717
+ assert (refType.getPreferredExistentialRepresentation (SGF.SGM .M )
718
+ == ExistentialRepresentation::Metatype);
719
+ ref = ManagedValue::forUnmanaged (
720
+ SGF.B .createOpenExistentialMetatype (loc,
721
+ result.getUnmanagedValue (),
722
+ getTypeOfRValue ()));
723
+ } else {
724
+ assert (refType.getPreferredExistentialRepresentation (SGF.SGM .M )
725
+ == ExistentialRepresentation::Class);
726
+ ref = SGF.B .createOpenExistentialRef (loc, result, getTypeOfRValue ());
727
+ }
728
+
729
+ SGF.setArchetypeOpeningSite (OpenedArchetype, ref.getValue ());
730
+
731
+ return RValue (SGF, loc, getSubstFormalType (), ref);
732
+ }
733
+
734
+ void set (SILGenFunction &SGF, SILLocation loc,
735
+ RValue &&value, ManagedValue base) && override {
736
+ auto payload = std::move (value).forwardAsSingleValue (SGF, loc);
737
+
738
+ SmallVector<ProtocolConformanceRef, 2 > conformances;
739
+ for (auto proto : OpenedArchetype->getConformsTo ())
740
+ conformances.push_back (ProtocolConformanceRef (proto));
741
+
742
+ SILValue ref;
743
+ if (base.getType ().is <ExistentialMetatypeType>()) {
744
+ ref = SGF.B .createInitExistentialMetatype (
745
+ loc,
746
+ payload,
747
+ base.getType ().getObjectType (),
748
+ SGF.getASTContext ().AllocateCopy (conformances));
749
+ } else {
750
+ ref = SGF.B .createInitExistentialRef (
751
+ loc,
752
+ base.getType ().getObjectType (),
753
+ getSubstFormalType (),
754
+ payload,
755
+ SGF.getASTContext ().AllocateCopy (conformances));
756
+ }
757
+
758
+ auto &TL = SGF.getTypeLowering (base.getType ());
759
+ SGF.emitSemanticStore (loc, ref,
760
+ base.getValue (), TL, IsNotInitialization);
761
+ }
762
+
763
+ std::unique_ptr<LogicalPathComponent>
764
+ clone (SILGenFunction &SGF, SILLocation loc) const override {
765
+ LogicalPathComponent *clone =
766
+ new OpenNonOpaqueExistentialComponent (OpenedArchetype, getTypeData ());
767
+ return std::unique_ptr<LogicalPathComponent>(clone);
768
+ }
769
+
770
+ void print (raw_ostream &OS) const override {
771
+ OS << " OpenNonOpaqueExistentialComponent(" << OpenedArchetype
772
+ << " , ...)\n " ;
773
+ }
774
+ };
775
+
609
776
// / A physical path component which returns a literal address.
610
777
class ValueComponent : public PhysicalPathComponent {
611
778
ManagedValue Value;
@@ -1916,9 +2083,12 @@ LValue SILGenLValue::visitOpaqueValueExpr(OpaqueValueExpr *e,
1916
2083
openedExistentials.erase (known);
1917
2084
1918
2085
// Do formal evaluation of the underlying existential lvalue.
1919
- LValue lv = visitRec (opened->getExistentialValue (), accessKind);
1920
- lv.add <OpenOpaqueExistentialComponent>(
1921
- cast<ArchetypeType>(opened->getOpenedArchetype ()->getCanonicalType ()));
2086
+ auto lv = visitRec (opened->getExistentialValue (), accessKind);
2087
+ lv = SGF.emitOpenExistentialLValue (
2088
+ opened, std::move (lv),
2089
+ CanArchetypeType (opened->getOpenedArchetype ()),
2090
+ e->getType ()->getLValueOrInOutObjectType ()->getCanonicalType (),
2091
+ accessKind);
1922
2092
return lv;
1923
2093
}
1924
2094
@@ -2815,6 +2985,39 @@ ManagedValue SILGenFunction::emitAddressOfLValue(SILLocation loc,
2815
2985
return ManagedValue::forLValue (addr.getValue ());
2816
2986
}
2817
2987
2988
+ LValue
2989
+ SILGenFunction::emitOpenExistentialLValue (SILLocation loc,
2990
+ LValue &&lv,
2991
+ CanArchetypeType openedArchetype,
2992
+ CanType formalRValueType,
2993
+ AccessKind accessKind) {
2994
+ assert (!formalRValueType->isLValueType ());
2995
+ LValueTypeData typeData = {
2996
+ AbstractionPattern::getOpaque (), formalRValueType,
2997
+ getLoweredType (formalRValueType).getObjectType ()
2998
+ };
2999
+
3000
+ // Open up the existential.
3001
+ auto rep = lv.getTypeOfRValue ()
3002
+ .getPreferredExistentialRepresentation (SGM.M );
3003
+ switch (rep) {
3004
+ case ExistentialRepresentation::Opaque:
3005
+ case ExistentialRepresentation::Boxed: {
3006
+ lv.add <OpenOpaqueExistentialComponent>(openedArchetype, typeData);
3007
+ break ;
3008
+ }
3009
+ case ExistentialRepresentation::Metatype:
3010
+ case ExistentialRepresentation::Class: {
3011
+ lv.add <OpenNonOpaqueExistentialComponent>(openedArchetype, typeData);
3012
+ break ;
3013
+ }
3014
+ case ExistentialRepresentation::None:
3015
+ llvm_unreachable (" cannot open non-existential" );
3016
+ }
3017
+
3018
+ return std::move (lv);
3019
+ }
3020
+
2818
3021
void SILGenFunction::emitAssignToLValue (SILLocation loc, RValue &&src,
2819
3022
LValue &&dest) {
2820
3023
FormalEvaluationScope scope (*this );
0 commit comments