@@ -208,9 +208,8 @@ static void propagateBasicBlockArgs(SILBasicBlock &BB) {
208
208
static bool constantFoldEnumTerminator (SILBasicBlock &BB,
209
209
UnreachableUserCodeReportingState *State,
210
210
SwitchEnumInstBase *SUI,
211
- const EnumElementDecl *TheEnumElem,
212
- SILValue value = SILValue(),
213
- SILValue defaultValue = SILValue()) {
211
+ EnumElementDecl *TheEnumElem,
212
+ EnumInst *EnumInst) {
214
213
SILBasicBlock *TheSuccessorBlock = nullptr ;
215
214
int ReachableBlockIdx = -1 ;
216
215
for (unsigned Idx = 0 ; Idx < SUI->getNumCases (); ++Idx) {
@@ -251,11 +250,9 @@ static bool constantFoldEnumTerminator(SILBasicBlock &BB,
251
250
// value.
252
251
SILValue branchOperand;
253
252
if (TheSuccessorBlock != DB) {
254
- assert (value);
255
- branchOperand = value;
253
+ branchOperand = B.createUncheckedEnumData (Loc, EnumInst, TheEnumElem);
256
254
} else {
257
- assert (defaultValue);
258
- branchOperand = defaultValue;
255
+ branchOperand = EnumInst;
259
256
}
260
257
B.createBranch (Loc, TheSuccessorBlock, branchOperand);
261
258
} else
@@ -297,6 +294,81 @@ static bool constantFoldEnumTerminator(SILBasicBlock &BB,
297
294
return true ;
298
295
}
299
296
297
+ static bool constantFoldEnumAddrTerminator (
298
+ SILBasicBlock &BB, UnreachableUserCodeReportingState *State,
299
+ SwitchEnumInstBase *SUI, const EnumElementDecl *TheEnumElem) {
300
+ SILBasicBlock *TheSuccessorBlock = nullptr ;
301
+ int ReachableBlockIdx = -1 ;
302
+ for (unsigned Idx = 0 ; Idx < SUI->getNumCases (); ++Idx) {
303
+ const EnumElementDecl *EI;
304
+ SILBasicBlock *BI;
305
+ std::tie (EI, BI) = SUI->getCase (Idx);
306
+ if (EI == TheEnumElem) {
307
+ TheSuccessorBlock = BI;
308
+ ReachableBlockIdx = Idx;
309
+ break ;
310
+ }
311
+ }
312
+
313
+ SILBasicBlock *DB = nullptr ;
314
+ if (!TheSuccessorBlock) {
315
+ if (SUI->hasDefault ()) {
316
+ DB = SUI->getDefaultBB ();
317
+ if (!isa<UnreachableInst>(DB->getTerminator ())) {
318
+ TheSuccessorBlock = DB;
319
+ ReachableBlockIdx = SUI->getNumCases ();
320
+ }
321
+ }
322
+ }
323
+
324
+ // Not fully covered switches will be diagnosed later. SILGen represents
325
+ // them with a Default basic block with an unreachable instruction.
326
+ // We are going to produce an error on all unreachable instructions not
327
+ // eliminated by DCE.
328
+ if (!TheSuccessorBlock)
329
+ return false ;
330
+
331
+ // Replace the switch with a branch to the TheSuccessorBlock.
332
+ SILBuilderWithScope B (&BB, SUI);
333
+ SILLocation Loc = SUI->getLoc ();
334
+ B.createBranch (Loc, TheSuccessorBlock);
335
+
336
+ // Produce diagnostic info if we are not within an inlined function or
337
+ // template instantiation.
338
+ // FIXME: Do not report if we are within a template instantiation.
339
+ assert (ReachableBlockIdx >= 0 );
340
+ if (Loc.is <RegularLocation>() && State) {
341
+ // Find the first unreachable block in the switch so that we could use
342
+ // it for better diagnostics.
343
+ SILBasicBlock *UnreachableBlock = nullptr ;
344
+ if (SUI->getNumCases () > 1 ) {
345
+ // More than one case.
346
+ UnreachableBlock = (ReachableBlockIdx == 0 ) ? SUI->getCase (1 ).second
347
+ : SUI->getCase (0 ).second ;
348
+ } else {
349
+ if (SUI->getNumCases () == 1 && SUI->hasDefault ()) {
350
+ // One case and a default.
351
+ UnreachableBlock = (ReachableBlockIdx == 0 ) ? SUI->getDefaultBB ()
352
+ : SUI->getCase (0 ).second ;
353
+ }
354
+ }
355
+
356
+ // Generate diagnostic info.
357
+ if (UnreachableBlock &&
358
+ !State->PossiblyUnreachableBlocks .count (UnreachableBlock)) {
359
+ State->PossiblyUnreachableBlocks .insert (UnreachableBlock);
360
+ State->MetaMap .insert (std::pair<const SILBasicBlock *, UnreachableInfo>(
361
+ UnreachableBlock,
362
+ UnreachableInfo{UnreachableKind::FoldedSwitchEnum, Loc, true }));
363
+ }
364
+ }
365
+
366
+ LLVM_DEBUG (llvm::dbgs () << " Folding terminator: " << *SUI);
367
+ recursivelyDeleteTriviallyDeadInstructions (SUI, true );
368
+ NumTerminatorsFolded++;
369
+ return true ;
370
+ }
371
+
300
372
static InjectEnumAddrInst *
301
373
getAllocStackSingleInitializingInjectEnumAddr (SwitchEnumAddrInst *SEAI) {
302
374
auto *stackSlot = dyn_cast<AllocStackInst>(SEAI->getOperand ());
@@ -506,10 +578,8 @@ static bool constantFoldTerminator(SILBasicBlock &BB,
506
578
// br bb2
507
579
if (auto *SEI = dyn_cast<SwitchEnumInst>(TI)) {
508
580
if (auto *TheEnum = dyn_cast<EnumInst>(SEI->getOperand ())) {
509
- SILValue operand =
510
- TheEnum->hasOperand () ? TheEnum->getOperand () : SILValue ();
511
581
return constantFoldEnumTerminator (BB, State, SEI, TheEnum->getElement (),
512
- operand /* case */ , TheEnum /* default */ );
582
+ TheEnum);
513
583
}
514
584
}
515
585
if (auto *SEAI = dyn_cast<SwitchEnumAddrInst>(TI)) {
@@ -520,7 +590,8 @@ static bool constantFoldTerminator(SILBasicBlock &BB,
520
590
//
521
591
// TODO: This needs a better name.
522
592
if (auto *IEAI = getAllocStackSingleInitializingInjectEnumAddr (SEAI)) {
523
- return constantFoldEnumTerminator (BB, State, SEAI, IEAI->getElement ());
593
+ return constantFoldEnumAddrTerminator (BB, State, SEAI,
594
+ IEAI->getElement ());
524
595
}
525
596
}
526
597
0 commit comments