@@ -583,7 +583,7 @@ namespace {
583
583
public:
584
584
OpenOpaqueExistentialComponent (CanArchetypeType openedArchetype)
585
585
: PhysicalPathComponent(getOpenedArchetypeTypeData(openedArchetype),
586
- OpenedExistentialKind ) {}
586
+ OpenOpaqueExistentialKind ) {}
587
587
588
588
ManagedValue offset (SILGenFunction &SGF, SILLocation loc, ManagedValue base,
589
589
AccessKind accessKind) && override {
@@ -606,6 +606,89 @@ namespace {
606
606
}
607
607
};
608
608
609
+ // / A local path component for the payload of a class existential.
610
+ // /
611
+ // / TODO: Could be physical if we had a way to project out the
612
+ // / payload.
613
+ class OpenClassExistentialComponent : public LogicalPathComponent {
614
+ static LValueTypeData getOpenedArchetypeTypeData (CanArchetypeType type) {
615
+ return {
616
+ AbstractionPattern::getOpaque (), type,
617
+ SILType::getPrimitiveObjectType (type)
618
+ };
619
+ }
620
+ public:
621
+ OpenClassExistentialComponent (CanArchetypeType openedArchetype)
622
+ : LogicalPathComponent(getOpenedArchetypeTypeData(openedArchetype),
623
+ OpenClassExistentialKind) {}
624
+
625
+ AccessKind getBaseAccessKind (SILGenFunction &SGF,
626
+ AccessKind kind) const override {
627
+ // Always use the same access kind for the base.
628
+ return kind;
629
+ }
630
+
631
+ void diagnoseWritebackConflict (LogicalPathComponent *RHS,
632
+ SILLocation loc1, SILLocation loc2,
633
+ SILGenFunction &SGF) override {
634
+ // no useful writeback diagnostics at this point
635
+ }
636
+
637
+ RValue get (SILGenFunction &SGF, SILLocation loc,
638
+ ManagedValue base, SGFContext c) && override {
639
+ auto refType = base.getType ().getObjectType ();
640
+ auto &TL = SGF.getTypeLowering (refType);
641
+
642
+ // Load the original value.
643
+ auto result = SGF.emitLoad (loc, base.getValue (), TL,
644
+ SGFContext (), IsNotTake);
645
+
646
+ assert (refType.isExistentialType () &&
647
+ " base for open existential component must be an existential" );
648
+ assert (refType.getPreferredExistentialRepresentation (SGF.SGM .M )
649
+ == ExistentialRepresentation::Class);
650
+ auto ref = SGF.B .createOpenExistentialRef (
651
+ loc, result, getTypeOfRValue ());
652
+
653
+ SGF.setArchetypeOpeningSite (cast<ArchetypeType>(getSubstFormalType ()),
654
+ ref.getValue ());
655
+
656
+ return RValue (SGF, loc, getSubstFormalType (), ref);
657
+ }
658
+
659
+ void set (SILGenFunction &SGF, SILLocation loc,
660
+ RValue &&value, ManagedValue base) && override {
661
+ auto payload = std::move (value).forwardAsSingleValue (SGF, loc);
662
+
663
+ SmallVector<ProtocolConformanceRef, 2 > conformances;
664
+ for (auto proto : cast<ArchetypeType>(getSubstFormalType ())->getConformsTo ())
665
+ conformances.push_back (ProtocolConformanceRef (proto));
666
+
667
+ auto ref = SGF.B .createInitExistentialRef (
668
+ loc,
669
+ base.getType ().getObjectType (),
670
+ getSubstFormalType (),
671
+ payload,
672
+ SGF.getASTContext ().AllocateCopy (conformances));
673
+
674
+ auto &TL = SGF.getTypeLowering (base.getType ());
675
+ SGF.emitSemanticStore (loc, ref,
676
+ base.getValue (), TL, IsNotInitialization);
677
+ }
678
+
679
+ std::unique_ptr<LogicalPathComponent>
680
+ clone (SILGenFunction &SGF, SILLocation loc) const override {
681
+ LogicalPathComponent *clone =
682
+ new OpenClassExistentialComponent (
683
+ cast<ArchetypeType>(getSubstFormalType ()));
684
+ return std::unique_ptr<LogicalPathComponent>(clone);
685
+ }
686
+
687
+ void print (raw_ostream &OS) const override {
688
+ OS << " OpenClassExistentialComponent(...)\n " ;
689
+ }
690
+ };
691
+
609
692
// / A physical path component which returns a literal address.
610
693
class ValueComponent : public PhysicalPathComponent {
611
694
ManagedValue Value;
@@ -2815,6 +2898,31 @@ ManagedValue SILGenFunction::emitAddressOfLValue(SILLocation loc,
2815
2898
return ManagedValue::forLValue (addr.getValue ());
2816
2899
}
2817
2900
2901
+ LValue
2902
+ SILGenFunction::emitOpenExistentialLValue (SILLocation loc,
2903
+ LValue &&lv,
2904
+ CanArchetypeType openedArchetype,
2905
+ AccessKind accessKind) {
2906
+ // Open up the existential.
2907
+ auto rep = lv.getTypeOfRValue ()
2908
+ .getPreferredExistentialRepresentation (SGM.M );
2909
+ switch (rep) {
2910
+ case ExistentialRepresentation::Opaque: {
2911
+ lv.add <OpenOpaqueExistentialComponent>(openedArchetype);
2912
+ break ;
2913
+ }
2914
+ case ExistentialRepresentation::Class: {
2915
+ lv.add <OpenClassExistentialComponent>(openedArchetype);
2916
+ break ;
2917
+ }
2918
+ default :
2919
+ llvm_unreachable (" Cannot perform lvalue access of "
2920
+ " non-opaque, non-class existential" );
2921
+ }
2922
+
2923
+ return std::move (lv);
2924
+ }
2925
+
2818
2926
void SILGenFunction::emitAssignToLValue (SILLocation loc, RValue &&src,
2819
2927
LValue &&dest) {
2820
2928
FormalEvaluationScope scope (*this );
0 commit comments