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