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