@@ -307,6 +307,8 @@ struct StructLoweringState {
307
307
SmallVector<SwitchEnumInst *, 16 > switchEnumInstsToMod;
308
308
// All struct_extract instrs that should be converted to struct_element_addr
309
309
SmallVector<StructExtractInst *, 16 > structExtractInstsToMod;
310
+ // All tuple instructions for which the return type is a function type
311
+ SmallVector<SILInstruction *, 8 > tupleInstsToMod;
310
312
// All Retain and release instrs should be replaced with _addr version
311
313
SmallVector<RetainValueInst *, 16 > retainInstsToMod;
312
314
SmallVector<ReleaseValueInst *, 16 > releaseInstsToMod;
@@ -350,6 +352,7 @@ class LargeValueVisitor {
350
352
void visitReleaseInst (ReleaseValueInst *instr);
351
353
void visitResultTyInst (SILInstruction *instr);
352
354
void visitDebugValueInst (DebugValueInst *instr);
355
+ void visitTupleInst (SILInstruction *instr);
353
356
void visitInstr (SILInstruction *instr);
354
357
};
355
358
} // end anonymous namespace
@@ -411,6 +414,11 @@ void LargeValueVisitor::mapValueStorage() {
411
414
visitSwitchEnumInst (SEI);
412
415
break ;
413
416
}
417
+ case ValueKind::TupleElementAddrInst:
418
+ case ValueKind::TupleExtractInst: {
419
+ visitTupleInst (currIns);
420
+ break ;
421
+ }
414
422
default : {
415
423
assert (!ApplySite::isa (currIns) && " Did not expect an ApplySite" );
416
424
assert (!dyn_cast<MethodInst>(currIns) && " Unhandled Method Inst" );
@@ -607,6 +615,24 @@ void LargeValueVisitor::visitResultTyInst(SILInstruction *instr) {
607
615
}
608
616
}
609
617
618
+ void LargeValueVisitor::visitTupleInst (SILInstruction *instr) {
619
+ SILType currSILType = instr->getType ().getObjectType ();
620
+ CanType currCanType = currSILType.getSwiftRValueType ();
621
+ if (auto funcType = dyn_cast<SILFunctionType>(currCanType)) {
622
+ CanSILFunctionType canFuncType = CanSILFunctionType (funcType);
623
+ GenericEnvironment *genEnv = instr->getFunction ()->getGenericEnvironment ();
624
+ if (!genEnv && canFuncType->isPolymorphic ()) {
625
+ genEnv = getGenericEnvironment (instr->getModule (), canFuncType);
626
+ }
627
+ SILFunctionType *newSILFunctionType =
628
+ getNewSILFunctionTypePtr (genEnv, funcType, pass.Mod );
629
+ if (funcType != newSILFunctionType) {
630
+ pass.tupleInstsToMod .push_back (instr);
631
+ }
632
+ }
633
+ visitInstr (instr);
634
+ }
635
+
610
636
void LargeValueVisitor::visitInstr (SILInstruction *instr) {
611
637
for (Operand &operand : instr->getAllOperands ()) {
612
638
if (std::find (pass.largeLoadableArgs .begin (), pass.largeLoadableArgs .end (),
@@ -1208,6 +1234,40 @@ static bool allUsesAreReplaceable(SILInstruction *instr,
1208
1234
return allUsesAreReplaceable;
1209
1235
}
1210
1236
1237
+ static void castTupleInstr (SILInstruction *instr, IRGenModule &Mod) {
1238
+ SILType currSILType = instr->getType ().getObjectType ();
1239
+ CanType currCanType = currSILType.getSwiftRValueType ();
1240
+ SILFunctionType *funcType = dyn_cast<SILFunctionType>(currCanType);
1241
+ assert (funcType && " Expcted SILFunctionType as tuple's return" );
1242
+ CanSILFunctionType canFuncType = CanSILFunctionType (funcType);
1243
+ GenericEnvironment *genEnv = instr->getFunction ()->getGenericEnvironment ();
1244
+ if (!genEnv && canFuncType->isPolymorphic ()) {
1245
+ genEnv = getGenericEnvironment (instr->getModule (), canFuncType);
1246
+ }
1247
+ SILType newSILType = getNewSILFunctionType (genEnv, funcType, Mod);
1248
+ auto II = instr->getIterator ();
1249
+ ++II;
1250
+ SILBuilder castBuilder (II);
1251
+ SILInstruction *castInstr = nullptr ;
1252
+ switch (instr->getKind ()) {
1253
+ // Add cast to the new sil function type:
1254
+ case ValueKind::TupleExtractInst: {
1255
+ castInstr = castBuilder.createUncheckedBitCast (instr->getLoc (), instr,
1256
+ newSILType.getObjectType ());
1257
+ break ;
1258
+ }
1259
+ case ValueKind::TupleElementAddrInst: {
1260
+ castInstr = castBuilder.createUncheckedAddrCast (
1261
+ instr->getLoc (), instr, newSILType.getAddressType ());
1262
+ break ;
1263
+ }
1264
+ default :
1265
+ llvm_unreachable (" Unexpected instruction inside tupleInstsToMod" );
1266
+ }
1267
+ instr->replaceAllUsesWith (castInstr);
1268
+ castInstr->setOperand (0 , instr);
1269
+ }
1270
+
1211
1271
static void rewriteFunction (StructLoweringState &pass,
1212
1272
LoadableStorageAllocation &allocator) {
1213
1273
@@ -1350,6 +1410,10 @@ static void rewriteFunction(StructLoweringState &pass,
1350
1410
}
1351
1411
}
1352
1412
1413
+ for (SILInstruction *instr : pass.tupleInstsToMod ) {
1414
+ castTupleInstr (instr, pass.Mod );
1415
+ }
1416
+
1353
1417
for (SILInstruction *instr : pass.debugInstsToMod ) {
1354
1418
assert (instr->getAllOperands ().size () == 1 &&
1355
1419
" Debug instructions have one operand" );
0 commit comments