@@ -138,18 +138,30 @@ class OpaqueSpecializerCloner
138
138
void visitEnumInst (EnumInst *Inst) {
139
139
getBuilder ().setCurrentDebugScope (getOpScope (Inst->getDebugScope ()));
140
140
SILValue opd = SILValue ();
141
+ auto newTy = getOpType (Inst->getType ());
141
142
if (Inst->hasOperand ()) {
142
- SILType caseTy = Inst->getType ().getEnumElementType (
143
- Inst->getElement (), getBuilder ().getFunction ().getModule ());
144
143
opd = getOpValue (Inst->getOperand ());
145
- if (opd->getType () != caseTy) {
146
- opd = createCast (getOpLocation (Inst->getLoc ()), opd, caseTy);
147
- }
144
+ SILType newCaseTy = newTy.getEnumElementType (
145
+ Inst->getElement (), getBuilder ().getFunction ().getModule ());
146
+ if (opd->getType () != newCaseTy)
147
+ opd = createCast (getOpLocation (Inst->getLoc ()), opd, newCaseTy);
148
148
}
149
149
recordClonedInstruction (
150
150
Inst, getBuilder ().createEnum (getOpLocation (Inst->getLoc ()), opd,
151
- Inst->getElement (),
152
- getOpType (Inst->getType ())));
151
+ Inst->getElement (), newTy));
152
+ }
153
+
154
+ void visitInitEnumDataAddrInst (InitEnumDataAddrInst *Inst) {
155
+ getBuilder ().setCurrentDebugScope (getOpScope (Inst->getDebugScope ()));
156
+ auto opd = getOpValue (Inst->getOperand ());
157
+ auto caseTy = opd->getType ().getEnumElementType (
158
+ Inst->getElement (), getBuilder ().getFunction ().getModule ());
159
+ auto expectedTy = getOpType (Inst->getType ());
160
+ if (expectedTy != caseTy)
161
+ expectedTy = caseTy;
162
+ recordClonedInstruction (Inst, getBuilder ().createInitEnumDataAddr (
163
+ getOpLocation (Inst->getLoc ()), opd,
164
+ Inst->getElement (), expectedTy));
153
165
}
154
166
155
167
// / Projections should not change the type if the type is not specialized.
@@ -337,24 +349,48 @@ class OpaqueSpecializerCloner
337
349
loc, opd, type, /* withoutActuallyEscaping*/ false );
338
350
} else if (opd->getType ().isTrivial (CurFn)) {
339
351
return getBuilder ().createUncheckedTrivialBitCast (loc, opd, type);
340
- } else if (opd->getType ().isObject ()) {
352
+ } else if (opd->getType ().canRefCast (opd->getType (), type,
353
+ CurFn.getModule ())) {
341
354
return getBuilder ().createUncheckedRefCast (loc, opd, type);
342
355
} else {
343
356
// This could be improved upon by recursively recomposing the type.
344
357
auto *stackLoc = getBuilder ().createAllocStack (loc, type);
345
- auto *addr =
346
- getBuilder (). createUncheckedAddrCast ( loc, stackLoc, opd->getType ());
347
- getBuilder ().createTrivialStoreOr (loc, addr, opd ,
348
- StoreOwnershipQualifier::Init);
358
+ auto *addr = getBuilder (). createUncheckedAddrCast (
359
+ loc, stackLoc, opd->getType (). getAddressType ());
360
+ getBuilder ().createTrivialStoreOr (loc, opd, addr ,
361
+ StoreOwnershipQualifier::Init, true );
349
362
SILValue res = getBuilder ().createTrivialLoadOr (
350
- loc, addr , LoadOwnershipQualifier::Take);
363
+ loc, stackLoc , LoadOwnershipQualifier::Take, true );
351
364
getBuilder ().createDeallocStack (loc, stackLoc);
352
365
return res;
353
366
}
354
367
}
355
368
369
+ void replaceBlockArgumentType (SILLocation loc, SILBasicBlock *destBlock,
370
+ SILType withType) {
371
+ assert (destBlock->getArguments ().size () == 1 );
372
+
373
+ auto origType = (*destBlock->args_begin ())->getType ();
374
+ auto origPhi = destBlock->getPhiArguments ()[0 ];
375
+ SILValue undef = SILUndef::get (origType, getBuilder ().getFunction ());
376
+ SmallVector<Operand *, 8 > useList (origPhi->use_begin (), origPhi->use_end ());
377
+ for (auto *use : useList) {
378
+ use->set (undef);
379
+ }
380
+
381
+ auto *newPhi =
382
+ destBlock->replacePhiArgument (0 , withType, origPhi->getOwnershipKind ());
383
+
384
+ getBuilder ().setInsertionPoint (destBlock->begin ());
385
+ auto cast = createCast (loc, newPhi, origType);
386
+ for (auto *use : useList) {
387
+ use->set (cast);
388
+ }
389
+ }
390
+
356
391
void fixUp (SILFunction *) {
357
- for (auto &BB : getBuilder ().getFunction ()) {
392
+ auto &clonedFunction = getBuilder ().getFunction ();
393
+ for (auto &BB : clonedFunction) {
358
394
for (auto &cloned : BB) {
359
395
// Fix up the type of try_apply successor block arguments.
360
396
if (auto *tryApply = dyn_cast<TryApplyInst>(&cloned)) {
@@ -365,22 +401,25 @@ class OpaqueSpecializerCloner
365
401
auto normalBBType = (*normalBB->args_begin ())->getType ();
366
402
auto applyResultType = calleeConv.getSILResultType ();
367
403
if (normalBBType != calleeConv.getSILResultType ()) {
368
- auto origPhi = normalBB->getPhiArguments ()[0 ];
369
- SILValue undef =
370
- SILUndef::get (normalBBType, getBuilder ().getFunction ());
371
- SmallVector<Operand *, 8 > useList (origPhi->use_begin (),
372
- origPhi->use_end ());
373
- for (auto *use : useList) {
374
- use->set (undef);
375
- }
376
-
377
- auto *newPhi = normalBB->replacePhiArgument (
378
- 0 , applyResultType, origPhi->getOwnershipKind ());
404
+ replaceBlockArgumentType (tryApply->getLoc (), normalBB, applyResultType);
405
+ }
406
+ }
407
+ // Fix up the type of switch_enum successor block arguments.
408
+ if (auto *switchEnum = dyn_cast<SwitchEnumInst>(&cloned)) {
409
+ SILType enumTy = switchEnum->getOperand ()->getType ();
410
+ for (unsigned i = 0 , e = switchEnum->getNumCases (); i < e; ++i) {
411
+ EnumElementDecl *elt;
412
+ SILBasicBlock *dest;
413
+ std::tie (elt, dest) = switchEnum->getCase (i);
414
+
415
+ if (elt->hasAssociatedValues () &&
416
+ dest->getArguments ().size () == 1 ) {
417
+ SILType eltArgTy =
418
+ enumTy.getEnumElementType (elt, clonedFunction.getModule ());
419
+ SILType bbArgTy = dest->getArguments ()[0 ]->getType ();
420
+ if (eltArgTy != bbArgTy)
421
+ replaceBlockArgumentType (switchEnum->getLoc (), dest, eltArgTy);
379
422
380
- getBuilder ().setInsertionPoint (normalBB->begin ());
381
- auto cast = createCast (tryApply->getLoc (), newPhi, normalBBType);
382
- for (auto *use : useList) {
383
- use->set (cast);
384
423
}
385
424
}
386
425
}
0 commit comments