@@ -409,20 +409,240 @@ exit:
409
409
ret void
410
410
}
411
411
412
+ ;;; Test with funclets that don't have information for themselves, but have
413
+ ;;; descendants which unwind to other descendants (left.left unwinds to
414
+ ;;; left.right, and right unwinds to far_right). Make sure that these local
415
+ ;;; unwinds don't trip up processing of the ancestor nodes (left and root) that
416
+ ;;; ultimately have no information.
417
+ ;;; CHECK-LABEL: define void @test6(
418
+ define void @test6 () personality void ()* @ProcessCLRException {
419
+ entry:
420
+ ; CHECK-NEXT: entry:
421
+ invoke void @test6_inlinee ()
422
+ to label %exit unwind label %cleanup
423
+ cleanup:
424
+ %pad = cleanuppad within none []
425
+ call void @g () [ "funclet" (token %pad ) ]
426
+ cleanupret from %pad unwind to caller
427
+ exit:
428
+ ret void
429
+ }
430
+
431
+ define void @test6_inlinee () alwaysinline personality void ()* @ProcessCLRException {
432
+ entry:
433
+ invoke void @g ()
434
+ to label %exit unwind label %root
435
+ ; CHECK-NEXT: invoke void @g()
436
+ ; CHECK-NEXT: unwind label %[[root:.+]]
437
+ root:
438
+ %root.pad = cleanuppad within none []
439
+ invoke void @g () [ "funclet" (token %root.pad ) ]
440
+ to label %root.cont unwind label %left
441
+ ; CHECK: [[root]]:
442
+ ; CHECK-NEXT: %[[root_pad:.+]] = cleanuppad within none []
443
+ ; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[root_pad]]) ]
444
+ ; CHECK-NEXT: to label %[[root_cont:.+]] unwind label %[[left:.+]]
445
+
446
+ left:
447
+ %left.cs = catchswitch within %root.pad [label %left.catch ] unwind to caller
448
+ ; CHECK: [[left]]:
449
+ ; CHECK-NEXT: %[[left_cs:.+]] = catchswitch within %[[root_pad]] [label %[[left_catch:.+]]] unwind label %cleanup
450
+
451
+ left.catch:
452
+ %left.cp = catchpad within %left.cs []
453
+ call void @g () [ "funclet" (token %left.cp ) ]
454
+ invoke void @g () [ "funclet" (token %left.cp ) ]
455
+ to label %unreach unwind label %left.left
456
+ ; CHECK: [[left_catch:.+]]:
457
+ ; CHECK-NEXT: %[[left_cp:.+]] = catchpad within %[[left_cs]] []
458
+ ; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[left_cp]]) ]
459
+ ; CHECK-NEXT: to label %[[lc_cont:.+]] unwind label %cleanup
460
+ ; CHECK: [[lc_cont]]:
461
+ ; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[left_cp]]) ]
462
+ ; CHECK-NEXT: to label %[[unreach:.+]] unwind label %[[left_left:.+]]
463
+
464
+ left.left:
465
+ %ll.pad = cleanuppad within %left.cp []
466
+ cleanupret from %ll.pad unwind label %left.right
467
+ ; CHECK: [[left_left]]:
468
+ ; CHECK-NEXT: %[[ll_pad:.+]] = cleanuppad within %[[left_cp]] []
469
+ ; CHECK-NEXT: cleanupret from %[[ll_pad]] unwind label %[[left_right:.+]]
470
+
471
+ left.right:
472
+ %lr.pad = cleanuppad within %left.cp []
473
+ unreachable
474
+ ; CHECK: [[left_right]]:
475
+ ; CHECK-NEXT: %[[lr_pad:.+]] = cleanuppad within %[[left_cp]] []
476
+ ; CHECK-NEXT: unreachable
477
+
478
+ root.cont:
479
+ call void @g () [ "funclet" (token %root.pad ) ]
480
+ invoke void @g () [ "funclet" (token %root.pad ) ]
481
+ to label %unreach unwind label %right
482
+ ; CHECK: [[root_cont]]:
483
+ ; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[root_pad]]) ]
484
+ ; CHECK-NEXT: to label %[[root_cont_cont:.+]] unwind label %cleanup
485
+ ; CHECK: [[root_cont_cont]]:
486
+ ; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[root_pad]]) ]
487
+ ; CHECK-NEXT: to label %[[unreach]] unwind label %[[right:.+]]
488
+
489
+ right:
490
+ %right.pad = cleanuppad within %root.pad []
491
+ invoke void @g () [ "funclet" (token %right.pad ) ]
492
+ to label %unreach unwind label %right.child
493
+ ; CHECK: [[right]]:
494
+ ; CHECK-NEXT: %[[right_pad:.+]] = cleanuppad within %[[root_pad]] []
495
+ ; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[right_pad]]) ]
496
+ ; CHECK-NEXT: to label %[[unreach]] unwind label %[[right_child:.+]]
497
+
498
+ right.child:
499
+ %rc.pad = cleanuppad within %right.pad []
500
+ invoke void @g () [ "funclet" (token %rc.pad ) ]
501
+ to label %unreach unwind label %far_right
502
+ ; CHECK: [[right_child]]:
503
+ ; CHECK-NEXT: %[[rc_pad:.+]] = cleanuppad within %[[right_pad]] []
504
+ ; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[rc_pad]]) ]
505
+ ; CHECK-NEXT: to label %[[unreach]] unwind label %[[far_right:.+]]
506
+
507
+ far_right:
508
+ %fr.cs = catchswitch within %root.pad [label %fr.catch ] unwind to caller
509
+ ; CHECK: [[far_right]]:
510
+ ; CHECK-NEXT: %[[fr_cs:.+]] = catchswitch within %[[root_pad]] [label %[[fr_catch:.+]]] unwind label %cleanup
511
+
512
+ fr.catch:
513
+ %fr.cp = catchpad within %fr.cs []
514
+ unreachable
515
+ ; CHECK: [[fr_catch]]:
516
+ ; CHECK-NEXT: %[[fr_cp:.+]] = catchpad within %[[fr_cs]] []
517
+ ; CHECK-NEXT: unreachable
518
+
519
+ unreach:
520
+ unreachable
521
+ ; CHECK: [[unreach]]:
522
+ ; CHECK-NEXT: unreachable
523
+
524
+ exit:
525
+ ret void
526
+ }
527
+
528
+
529
+ ;;; Test with a no-info funclet (right) which has a cousin (left.left) that
530
+ ;;; unwinds to another cousin (left.right); make sure we don't trip over this
531
+ ;;; when propagating unwind destination info to "right".
532
+ ;;; CHECK-LABEL: define void @test7(
533
+ define void @test7 () personality void ()* @ProcessCLRException {
534
+ entry:
535
+ ; CHECK-NEXT: entry:
536
+ invoke void @test7_inlinee ()
537
+ to label %exit unwind label %cleanup
538
+ cleanup:
539
+ %pad = cleanuppad within none []
540
+ call void @g () [ "funclet" (token %pad ) ]
541
+ cleanupret from %pad unwind to caller
542
+ exit:
543
+ ret void
544
+ }
545
+
546
+ define void @test7_inlinee () alwaysinline personality void ()* @ProcessCLRException {
547
+ entry:
548
+ invoke void @g ()
549
+ to label %exit unwind label %root
550
+ ; CHECK-NEXT: invoke void @g()
551
+ ; CHECK-NEXT: unwind label %[[root:.+]]
552
+
553
+ root:
554
+ %root.cp = cleanuppad within none []
555
+ invoke void @g () [ "funclet" (token %root.cp ) ]
556
+ to label %root.cont unwind label %child
557
+ ; CHECK: [[root]]:
558
+ ; CHECK-NEXT: %[[root_cp:.+]] = cleanuppad within none []
559
+ ; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[root_cp]]) ]
560
+ ; CHECK-NEXT: to label %[[root_cont:.+]] unwind label %[[child:.+]]
561
+
562
+ root.cont:
563
+ cleanupret from %root.cp unwind to caller
564
+ ; CHECK: [[root_cont]]:
565
+ ; CHECK-NEXT: cleanupret from %[[root_cp]] unwind label %cleanup
566
+
567
+ child:
568
+ %child.cp = cleanuppad within %root.cp []
569
+ invoke void @g () [ "funclet" (token %child.cp ) ]
570
+ to label %child.cont unwind label %left
571
+ ; CHECK: [[child]]:
572
+ ; CHECK-NEXT: %[[child_cp:.+]] = cleanuppad within %[[root_cp]] []
573
+ ; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[child_cp]]) ]
574
+ ; CHECK-NEXT: to label %[[child_cont:.+]] unwind label %[[left:.+]]
575
+
576
+ left:
577
+ %left.cp = cleanuppad within %child.cp []
578
+ invoke void @g () [ "funclet" (token %left.cp ) ]
579
+ to label %left.cont unwind label %left.left
580
+ ; CHECK: [[left]]:
581
+ ; CHECK-NEXT: %[[left_cp:.+]] = cleanuppad within %[[child_cp]] []
582
+ ; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[left_cp]]) ]
583
+ ; CHECK-NEXT: to label %[[left_cont:.+]] unwind label %[[left_left:.+]]
584
+
585
+ left.left:
586
+ %ll.cp = cleanuppad within %left.cp []
587
+ cleanupret from %ll.cp unwind label %left.right
588
+ ; CHECK: [[left_left]]:
589
+ ; CHECK-NEXT: %[[ll_cp:.+]] = cleanuppad within %[[left_cp]] []
590
+ ; CHECK-NEXT: cleanupret from %[[ll_cp]] unwind label %[[left_right:.+]]
591
+
592
+ left.cont:
593
+ invoke void @g () [ "funclet" (token %left.cp ) ]
594
+ to label %unreach unwind label %left.right
595
+ ; CHECK: [[left_cont]]:
596
+ ; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[left_cp]]) ]
597
+ ; CHECK-NEXT: to label %[[unreach:.+]] unwind label %[[left_right]]
598
+
599
+ left.right:
600
+ %lr.cp = cleanuppad within %left.cp []
601
+ unreachable
602
+ ; CHECK: [[left_right]]:
603
+ ; CHECK-NEXT: %[[lr_cp:.+]] = cleanuppad within %[[left_cp]] []
604
+ ; CHECK-NEXT: unreachable
605
+
606
+ child.cont:
607
+ invoke void @g () [ "funclet" (token %child.cp ) ]
608
+ to label %unreach unwind label %right
609
+ ; CHECK: [[child_cont]]:
610
+ ; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[child_cp]]) ]
611
+ ; CHECK-NEXT: to label %[[unreach]] unwind label %[[right:.+]]
612
+
613
+ right:
614
+ %right.cp = cleanuppad within %child.cp []
615
+ call void @g () [ "funclet" (token %right.cp ) ]
616
+ unreachable
617
+ ; CHECK: [[right]]:
618
+ ; CHECK-NEXT: %[[right_cp:.+]] = cleanuppad within %[[child_cp]]
619
+ ; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[right_cp]]) ]
620
+ ; CHECK-NEXT: to label %[[right_cont:.+]] unwind label %cleanup
621
+ ; CHECK: [[right_cont]]:
622
+ ; CHECK-NEXT: unreachable
623
+
624
+ unreach:
625
+ unreachable
626
+ ; CHECK: [[unreach]]:
627
+ ; CHECK-NEXT: unreachable
628
+
629
+ exit:
630
+ ret void
631
+ }
412
632
413
633
declare void @ProcessCLRException ()
414
634
415
635
; Make sure the logic doesn't get tripped up when the inlined invoke is
416
636
; itself within a funclet in the caller.
417
- ; CHECK-LABEL: define void @test6 (
418
- define void @test6 () personality void ()* @ProcessCLRException {
637
+ ; CHECK-LABEL: define void @test8 (
638
+ define void @test8 () personality void ()* @ProcessCLRException {
419
639
entry:
420
640
invoke void @g ()
421
641
to label %exit unwind label %callsite_parent
422
642
callsite_parent:
423
643
%callsite_parent.pad = cleanuppad within none []
424
644
; CHECK: %callsite_parent.pad = cleanuppad within none
425
- invoke void @test6_inlinee () [ "funclet" (token %callsite_parent.pad ) ]
645
+ invoke void @test8_inlinee () [ "funclet" (token %callsite_parent.pad ) ]
426
646
to label %ret unwind label %cleanup
427
647
ret:
428
648
cleanupret from %callsite_parent.pad unwind label %cleanup
@@ -434,7 +654,7 @@ exit:
434
654
ret void
435
655
}
436
656
437
- define void @test6_inlinee () alwaysinline personality void ()* @ProcessCLRException {
657
+ define void @test8_inlinee () alwaysinline personality void ()* @ProcessCLRException {
438
658
entry:
439
659
invoke void @g ()
440
660
to label %exit unwind label %inlinee_cleanup
0 commit comments