|
2683 | 2683 | ;; CHECK-NEXT: ) |
2684 | 2684 | ;; CHECK-NEXT: ) |
2685 | 2685 | ;; CHECK-NEXT: ) |
| 2686 | +(module |
| 2687 | + ;; All tags keep externref parameters unchanged while other reference |
| 2688 | + ;; parameters are lowered to shared types. |
| 2689 | + (tag $js-tag (import "WebAssembly" "JSTag") (param externref)) |
| 2690 | + ;; CHECK: (type $0 (func (result i32 (ref (shared i31))))) |
| 2691 | + |
| 2692 | + ;; CHECK: (type $1 (func (param externref))) |
| 2693 | + |
| 2694 | + ;; CHECK: (type $2 (func (param i32 (ref extern)))) |
| 2695 | + |
| 2696 | + ;; CHECK: (type $3 (func (param (ref null (shared any))))) |
| 2697 | + |
| 2698 | + ;; CHECK: (type $4 (func (param (ref null (shared i31)) (ref (shared i31)) (ref null (shared any))))) |
| 2699 | + |
| 2700 | + ;; CHECK: (type $5 (func (result (ref null (shared i31))))) |
| 2701 | + |
| 2702 | + ;; CHECK: (type $6 (func)) |
| 2703 | + |
| 2704 | + ;; CHECK: (type $7 (func (param externref) (result (ref null (shared i31))))) |
| 2705 | + |
| 2706 | + ;; CHECK: (type $8 (func (param (ref null (shared i31))) (result externref))) |
| 2707 | + |
| 2708 | + ;; CHECK: (import "WebAssembly" "JSTag" (tag $js-tag (type $1) (param externref))) |
| 2709 | + |
| 2710 | + ;; CHECK: (table $externs 0 externref) |
| 2711 | + |
| 2712 | + ;; CHECK: (tag $export-tag (type $2) (param i32 (ref extern))) |
| 2713 | + (tag $export-tag (export "export_tag") (param i32 (ref extern))) |
| 2714 | + ;; CHECK: (tag $internal-tag (type $1) (param externref)) |
| 2715 | + (tag $internal-tag (param externref)) |
| 2716 | + ;; CHECK: (tag $anyref-tag (type $3) (param (ref null (shared any)))) |
| 2717 | + (tag $anyref-tag (param anyref)) |
| 2718 | + |
| 2719 | + ;; CHECK: (export "export_tag" (tag $export-tag)) |
| 2720 | + |
| 2721 | + ;; CHECK: (func $throw-tags (type $4) (param $x (ref null (shared i31))) (param $y (ref (shared i31))) (param $z (ref null (shared any))) |
| 2722 | + ;; CHECK-NEXT: (throw $js-tag |
| 2723 | + ;; CHECK-NEXT: (call $index_to_extern |
| 2724 | + ;; CHECK-NEXT: (local.get $x) |
| 2725 | + ;; CHECK-NEXT: ) |
| 2726 | + ;; CHECK-NEXT: ) |
| 2727 | + ;; CHECK-NEXT: (throw $export-tag |
| 2728 | + ;; CHECK-NEXT: (i32.const 42) |
| 2729 | + ;; CHECK-NEXT: (ref.cast (ref extern) |
| 2730 | + ;; CHECK-NEXT: (call $index_to_extern |
| 2731 | + ;; CHECK-NEXT: (local.get $y) |
| 2732 | + ;; CHECK-NEXT: ) |
| 2733 | + ;; CHECK-NEXT: ) |
| 2734 | + ;; CHECK-NEXT: ) |
| 2735 | + ;; CHECK-NEXT: (throw $internal-tag |
| 2736 | + ;; CHECK-NEXT: (call $index_to_extern |
| 2737 | + ;; CHECK-NEXT: (local.get $x) |
| 2738 | + ;; CHECK-NEXT: ) |
| 2739 | + ;; CHECK-NEXT: ) |
| 2740 | + ;; CHECK-NEXT: (throw $anyref-tag |
| 2741 | + ;; CHECK-NEXT: (local.get $z) |
| 2742 | + ;; CHECK-NEXT: ) |
| 2743 | + ;; CHECK-NEXT: ) |
| 2744 | + (func $throw-tags (param $x externref) (param $y (ref extern)) (param $z anyref) |
| 2745 | + ;; Throwing any tag with externref parameters converts externref operands |
| 2746 | + ;; from i31ref to externref, while other reference parameters are lowered. |
| 2747 | + (throw $js-tag |
| 2748 | + (local.get $x) |
| 2749 | + ) |
| 2750 | + (throw $export-tag |
| 2751 | + (i32.const 42) |
| 2752 | + (local.get $y) |
| 2753 | + ) |
| 2754 | + (throw $internal-tag |
| 2755 | + (local.get $x) |
| 2756 | + ) |
| 2757 | + (throw $anyref-tag |
| 2758 | + (local.get $z) |
| 2759 | + ) |
| 2760 | + ) |
| 2761 | + |
| 2762 | + ;; CHECK: (func $try-legacy (type $5) (result (ref null (shared i31))) |
| 2763 | + ;; CHECK-NEXT: (try (result (ref null (shared i31))) |
| 2764 | + ;; CHECK-NEXT: (do |
| 2765 | + ;; CHECK-NEXT: (ref.null (shared none)) |
| 2766 | + ;; CHECK-NEXT: ) |
| 2767 | + ;; CHECK-NEXT: (catch $js-tag |
| 2768 | + ;; CHECK-NEXT: (call $extern_to_index |
| 2769 | + ;; CHECK-NEXT: (pop externref) |
| 2770 | + ;; CHECK-NEXT: ) |
| 2771 | + ;; CHECK-NEXT: ) |
| 2772 | + ;; CHECK-NEXT: (catch $internal-tag |
| 2773 | + ;; CHECK-NEXT: (call $extern_to_index |
| 2774 | + ;; CHECK-NEXT: (pop externref) |
| 2775 | + ;; CHECK-NEXT: ) |
| 2776 | + ;; CHECK-NEXT: ) |
| 2777 | + ;; CHECK-NEXT: (catch $anyref-tag |
| 2778 | + ;; CHECK-NEXT: (drop |
| 2779 | + ;; CHECK-NEXT: (pop (ref null (shared any))) |
| 2780 | + ;; CHECK-NEXT: ) |
| 2781 | + ;; CHECK-NEXT: (ref.null (shared none)) |
| 2782 | + ;; CHECK-NEXT: ) |
| 2783 | + ;; CHECK-NEXT: ) |
| 2784 | + ;; CHECK-NEXT: ) |
| 2785 | + (func $try-legacy (result externref) |
| 2786 | + ;; Legacy try/catch wraps the pop of any tag with externref parameters in a |
| 2787 | + ;; conversion from externref to i31ref. |
| 2788 | + (try (result externref) |
| 2789 | + (do |
| 2790 | + (ref.null noextern) |
| 2791 | + ) |
| 2792 | + (catch $js-tag |
| 2793 | + (pop externref) |
| 2794 | + ) |
| 2795 | + (catch $internal-tag |
| 2796 | + (pop externref) |
| 2797 | + ) |
| 2798 | + (catch $anyref-tag |
| 2799 | + (drop |
| 2800 | + (pop anyref) |
| 2801 | + ) |
| 2802 | + (ref.null noextern) |
| 2803 | + ) |
| 2804 | + ) |
| 2805 | + ) |
| 2806 | + |
| 2807 | + ;; CHECK: (func $try-legacy-tuple (type $0) (result i32 (ref (shared i31))) |
| 2808 | + ;; CHECK-NEXT: (local $0 (tuple i32 (ref extern))) |
| 2809 | + ;; CHECK-NEXT: (try (type $0) (result i32 (ref (shared i31))) |
| 2810 | + ;; CHECK-NEXT: (do |
| 2811 | + ;; CHECK-NEXT: (tuple.make 2 |
| 2812 | + ;; CHECK-NEXT: (i32.const 0) |
| 2813 | + ;; CHECK-NEXT: (unreachable) |
| 2814 | + ;; CHECK-NEXT: ) |
| 2815 | + ;; CHECK-NEXT: ) |
| 2816 | + ;; CHECK-NEXT: (catch $export-tag |
| 2817 | + ;; CHECK-NEXT: (local.set $0 |
| 2818 | + ;; CHECK-NEXT: (pop (tuple i32 (ref extern))) |
| 2819 | + ;; CHECK-NEXT: ) |
| 2820 | + ;; CHECK-NEXT: (tuple.make 2 |
| 2821 | + ;; CHECK-NEXT: (tuple.extract 2 0 |
| 2822 | + ;; CHECK-NEXT: (local.get $0) |
| 2823 | + ;; CHECK-NEXT: ) |
| 2824 | + ;; CHECK-NEXT: (ref.as_non_null |
| 2825 | + ;; CHECK-NEXT: (call $extern_to_index |
| 2826 | + ;; CHECK-NEXT: (tuple.extract 2 1 |
| 2827 | + ;; CHECK-NEXT: (local.get $0) |
| 2828 | + ;; CHECK-NEXT: ) |
| 2829 | + ;; CHECK-NEXT: ) |
| 2830 | + ;; CHECK-NEXT: ) |
| 2831 | + ;; CHECK-NEXT: ) |
| 2832 | + ;; CHECK-NEXT: ) |
| 2833 | + ;; CHECK-NEXT: ) |
| 2834 | + ;; CHECK-NEXT: ) |
| 2835 | + (func $try-legacy-tuple (result i32 (ref extern)) |
| 2836 | + ;; Legacy try/catch on a multi-value exported tag converts the externref |
| 2837 | + ;; tuple element from externref to i31ref. |
| 2838 | + (try (result i32 (ref extern)) |
| 2839 | + (do |
| 2840 | + (tuple.make 2 |
| 2841 | + (i32.const 0) |
| 2842 | + (unreachable) |
| 2843 | + ) |
| 2844 | + ) |
| 2845 | + (catch $export-tag |
| 2846 | + (pop (tuple i32 (ref extern))) |
| 2847 | + ) |
| 2848 | + ) |
| 2849 | + ) |
| 2850 | + |
| 2851 | + ;; CHECK: (func $try-legacy-tuple-nested (type $6) |
| 2852 | + ;; CHECK-NEXT: (local $t (tuple i32 (ref (shared i31)))) |
| 2853 | + ;; CHECK-NEXT: (local $1 (tuple i32 (ref extern))) |
| 2854 | + ;; CHECK-NEXT: (local $2 (tuple i32 (ref extern))) |
| 2855 | + ;; CHECK-NEXT: (try |
| 2856 | + ;; CHECK-NEXT: (do |
| 2857 | + ;; CHECK-NEXT: (nop) |
| 2858 | + ;; CHECK-NEXT: ) |
| 2859 | + ;; CHECK-NEXT: (catch $export-tag |
| 2860 | + ;; CHECK-NEXT: (local.set $2 |
| 2861 | + ;; CHECK-NEXT: (pop (tuple i32 (ref extern))) |
| 2862 | + ;; CHECK-NEXT: ) |
| 2863 | + ;; CHECK-NEXT: (local.set $t |
| 2864 | + ;; CHECK-NEXT: (block (type $0) (result i32 (ref (shared i31))) |
| 2865 | + ;; CHECK-NEXT: (local.set $1 |
| 2866 | + ;; CHECK-NEXT: (local.get $2) |
| 2867 | + ;; CHECK-NEXT: ) |
| 2868 | + ;; CHECK-NEXT: (tuple.make 2 |
| 2869 | + ;; CHECK-NEXT: (tuple.extract 2 0 |
| 2870 | + ;; CHECK-NEXT: (local.get $1) |
| 2871 | + ;; CHECK-NEXT: ) |
| 2872 | + ;; CHECK-NEXT: (ref.as_non_null |
| 2873 | + ;; CHECK-NEXT: (call $extern_to_index |
| 2874 | + ;; CHECK-NEXT: (tuple.extract 2 1 |
| 2875 | + ;; CHECK-NEXT: (local.get $1) |
| 2876 | + ;; CHECK-NEXT: ) |
| 2877 | + ;; CHECK-NEXT: ) |
| 2878 | + ;; CHECK-NEXT: ) |
| 2879 | + ;; CHECK-NEXT: ) |
| 2880 | + ;; CHECK-NEXT: ) |
| 2881 | + ;; CHECK-NEXT: ) |
| 2882 | + ;; CHECK-NEXT: ) |
| 2883 | + ;; CHECK-NEXT: ) |
| 2884 | + ;; CHECK-NEXT: ) |
| 2885 | + (func $try-legacy-tuple-nested |
| 2886 | + (local $t (tuple i32 (ref extern))) |
| 2887 | + ;; A multi-value pop inside an expression is wrapped in a block by visitPop |
| 2888 | + ;; and then hoisted to the start of the catch body by handleBlockNestedPop. |
| 2889 | + (try |
| 2890 | + (do |
| 2891 | + (nop) |
| 2892 | + ) |
| 2893 | + (catch $export-tag |
| 2894 | + (local.set $t |
| 2895 | + (pop (tuple i32 (ref extern))) |
| 2896 | + ) |
| 2897 | + ) |
| 2898 | + ) |
| 2899 | + ) |
| 2900 | +) |
| 2901 | + |
| 2902 | +;; CHECK: (func $extern_to_index (type $7) (param $0 externref) (result (ref null (shared i31))) |
| 2903 | +;; CHECK-NEXT: (local $1 i32) |
| 2904 | +;; CHECK-NEXT: (if (result (ref null (shared i31))) |
| 2905 | +;; CHECK-NEXT: (ref.is_null |
| 2906 | +;; CHECK-NEXT: (local.get $0) |
| 2907 | +;; CHECK-NEXT: ) |
| 2908 | +;; CHECK-NEXT: (then |
| 2909 | +;; CHECK-NEXT: (ref.null (shared none)) |
| 2910 | +;; CHECK-NEXT: ) |
| 2911 | +;; CHECK-NEXT: (else |
| 2912 | +;; CHECK-NEXT: (if (result (ref (shared i31))) |
| 2913 | +;; CHECK-NEXT: (i32.ge_s |
| 2914 | +;; CHECK-NEXT: (local.tee $1 |
| 2915 | +;; CHECK-NEXT: (table.grow $externs |
| 2916 | +;; CHECK-NEXT: (local.get $0) |
| 2917 | +;; CHECK-NEXT: (i32.const 1) |
| 2918 | +;; CHECK-NEXT: ) |
| 2919 | +;; CHECK-NEXT: ) |
| 2920 | +;; CHECK-NEXT: (i32.const 0) |
| 2921 | +;; CHECK-NEXT: ) |
| 2922 | +;; CHECK-NEXT: (then |
| 2923 | +;; CHECK-NEXT: (ref.i31_shared |
| 2924 | +;; CHECK-NEXT: (local.get $1) |
| 2925 | +;; CHECK-NEXT: ) |
| 2926 | +;; CHECK-NEXT: ) |
| 2927 | +;; CHECK-NEXT: (else |
| 2928 | +;; CHECK-NEXT: (unreachable) |
| 2929 | +;; CHECK-NEXT: ) |
| 2930 | +;; CHECK-NEXT: ) |
| 2931 | +;; CHECK-NEXT: ) |
| 2932 | +;; CHECK-NEXT: ) |
| 2933 | +;; CHECK-NEXT: ) |
| 2934 | + |
| 2935 | +;; CHECK: (func $index_to_extern (type $8) (param $0 (ref null (shared i31))) (result externref) |
| 2936 | +;; CHECK-NEXT: (if (result externref) |
| 2937 | +;; CHECK-NEXT: (ref.is_null |
| 2938 | +;; CHECK-NEXT: (local.get $0) |
| 2939 | +;; CHECK-NEXT: ) |
| 2940 | +;; CHECK-NEXT: (then |
| 2941 | +;; CHECK-NEXT: (ref.null noextern) |
| 2942 | +;; CHECK-NEXT: ) |
| 2943 | +;; CHECK-NEXT: (else |
| 2944 | +;; CHECK-NEXT: (table.get $externs |
| 2945 | +;; CHECK-NEXT: (i31.get_u |
| 2946 | +;; CHECK-NEXT: (local.get $0) |
| 2947 | +;; CHECK-NEXT: ) |
| 2948 | +;; CHECK-NEXT: ) |
| 2949 | +;; CHECK-NEXT: ) |
| 2950 | +;; CHECK-NEXT: ) |
| 2951 | +;; CHECK-NEXT: ) |
0 commit comments