@@ -611,6 +611,33 @@ struct SpecializationContext
611
611
return nullptr ;
612
612
}
613
613
614
+ void maybeInsertGetExistentialValue (IRInst* inst)
615
+ {
616
+ // If inst has `ExistentialBox` type, we need to make sure
617
+ // all uses are through `GetValueFromExistentialBox`.
618
+ if (auto existentialBoxType = as<IRExistentialBoxType>(inst->getDataType ()))
619
+ {
620
+ ShortList<IRUse*> usesToReplace;
621
+ for (auto use = inst->firstUse ; use; use = use->nextUse )
622
+ {
623
+ if (use->getUser ()->op != kIROp_GetValueFromExistentialBox )
624
+ usesToReplace.add (use);
625
+ }
626
+ for (auto use : usesToReplace)
627
+ {
628
+ auto user = use->getUser ();
629
+ IRBuilder builderStorage;
630
+ auto builder = &builderStorage;
631
+ builder->sharedBuilder = &sharedBuilderStorage;
632
+ builder->setInsertBefore (user);
633
+ auto getValueInst = builder->emitGetValueFromExistentialBox (
634
+ builder->getPtrType (existentialBoxType->getValueType ()), inst);
635
+ use->set (getValueInst);
636
+ addToWorkList (getValueInst);
637
+ }
638
+ }
639
+ }
640
+
614
641
// All of the machinery for generic specialization
615
642
// has been defined above, so we will now walk
616
643
// through the flow of the overall specialization pass.
@@ -678,6 +705,10 @@ struct SpecializationContext
678
705
workListSet.Remove (inst);
679
706
cleanInsts.Add (inst);
680
707
708
+ // If inst represents a value of ExistentialBox type, all its uses
709
+ // must be through a `GetValueFromExistentialBox` inst.
710
+ maybeInsertGetExistentialValue (inst);
711
+
681
712
// For each instruction we process, we want to perform
682
713
// a few steps.
683
714
//
@@ -1640,7 +1671,7 @@ struct SpecializationContext
1640
1671
if (slotOperandCount <= 1 ) return ;
1641
1672
1642
1673
auto concreteType = (IRType*) type->getExistentialArg (0 );
1643
- auto newVal = builder.getPtrType ( kIROp_ExistentialBoxType , concreteType );
1674
+ auto newVal = builder.getExistentialBoxType (concreteType, baseInterfaceType );
1644
1675
1645
1676
addUsersToWorkList (type);
1646
1677
type->replaceUsesWith (newVal);
0 commit comments