1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438 7439 7440 7441 7442 7443 7444 7445 7446 7447 7448 7449 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519 7520 7521 7522 7523 7524 7525 7526 7527 7528 7529 7530 7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576 7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603
|
//===--- Verifier.cpp - Verification of Swift SIL Code --------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "sil-verifier"
#include "VerifierPrivate.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/AnyFunctionRef.h"
#include "swift/AST/ASTSynthesis.h"
#include "swift/AST/Decl.h"
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Module.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/SemanticAttrs.h"
#include "swift/AST/Types.h"
#include "swift/Basic/Range.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/SIL/AddressWalker.h"
#include "swift/SIL/ApplySite.h"
#include "swift/SIL/BasicBlockBits.h"
#include "swift/SIL/BasicBlockUtils.h"
#include "swift/SIL/CalleeCache.h"
#include "swift/SIL/DebugUtils.h"
#include "swift/SIL/Dominance.h"
#include "swift/SIL/DynamicCasts.h"
#include "swift/SIL/MemAccessUtils.h"
#include "swift/SIL/OwnershipUtils.h"
#include "swift/SIL/PostOrder.h"
#include "swift/SIL/PrettyStackTrace.h"
#include "swift/SIL/PrunedLiveness.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILVTable.h"
#include "swift/SIL/SILVTableVisitor.h"
#include "swift/SIL/SILVisitor.h"
#include "swift/SIL/ScopedAddressUtils.h"
#include "swift/SIL/TypeLowering.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
using namespace swift;
using namespace swift::silverifier;
using Lowering::AbstractionPattern;
// This flag controls the default behaviour when hitting a verification
// failure (abort/exit).
static llvm::cl::opt<bool> AbortOnFailure(
"verify-abort-on-failure",
llvm::cl::init(true));
static llvm::cl::opt<bool> ContinueOnFailure("verify-continue-on-failure",
llvm::cl::init(false));
static llvm::cl::opt<bool> DumpModuleOnFailure("verify-dump-module-on-failure",
llvm::cl::init(false));
// This verification is affects primarily debug info and end users don't derive
// a benefit from seeing its results.
static llvm::cl::opt<bool> VerifyDIHoles("verify-di-holes", llvm::cl::init(
#ifndef NDEBUG
true
#else
false
#endif
));
static llvm::cl::opt<bool> SkipConvertEscapeToNoescapeAttributes(
"verify-skip-convert-escape-to-noescape-attributes", llvm::cl::init(false));
// Allow unit tests to gradually migrate toward -allow-critical-edges=false.
static llvm::cl::opt<bool> AllowCriticalEdges("allow-critical-edges",
llvm::cl::init(true));
extern llvm::cl::opt<bool> SILPrintDebugInfo;
// The verifier is basically all assertions, so don't compile it with NDEBUG to
// prevent release builds from triggering spurious unused variable warnings.
//===----------------------------------------------------------------------===//
// SILVerifier
//===----------------------------------------------------------------------===//
// Augment ASTSynthesis with some operations to synthesize SILTypes.
namespace {
template <class S>
struct ObjectTypeSynthesizer {
S sub;
};
template <class S>
constexpr ObjectTypeSynthesizer<S> _object(const S &s) {
return ObjectTypeSynthesizer<S>{s};
}
template <class S>
SILType synthesizeSILType(SynthesisContext &SC,
const ObjectTypeSynthesizer<S> &s) {
return SILType::getPrimitiveObjectType(
synthesizeType(SC, s.sub)->getCanonicalType());
}
template <class S>
struct AddressTypeSynthesizer {
S sub;
};
template <class S>
constexpr AddressTypeSynthesizer<S> _address(const S &s) {
return AddressTypeSynthesizer<S>{s};
}
template <class S>
SILType synthesizeSILType(SynthesisContext &SC,
const AddressTypeSynthesizer<S> &s) {
return SILType::getPrimitiveAddressType(
synthesizeType(SC, s.sub)->getCanonicalType());
}
} // end anonymous namespace
/// Returns true if A is an opened existential type or is equal to an
/// archetype from F's generic context.
static bool isArchetypeValidInFunction(ArchetypeType *A, const SILFunction *F) {
if (!isa<PrimaryArchetypeType>(A) && !isa<PackArchetypeType>(A))
return true;
if (isa<LocalArchetypeType>(A))
return true;
if (isa<OpaqueTypeArchetypeType>(A))
return true;
// Ok, we have a primary archetype, make sure it is in the nested generic
// environment of our caller.
if (auto *genericEnv = F->getGenericEnvironment())
if (A->getGenericEnvironment() == genericEnv)
return true;
return false;
}
namespace {
/// When resilience is bypassed for debugging or package serialization is enabled,
/// direct access is legal, but the decls are still resilient.
template <typename DeclType>
bool checkResilience(DeclType *D, ModuleDecl *accessingModule,
ResilienceExpansion expansion,
SerializedKind_t serializedKind) {
auto declModule = D->getModuleContext();
// For DEBUGGING: this check looks up
// `bypass-resilience-checks`, which is
// an old flag used for debugging, and
// has nothing to do with optimizations.
if (declModule->getBypassResilience())
return false;
// If the SIL function containing the decl D is
// [serialized_for_package], package-cmo had been
// enabled in its defining module, so direct access
// from a client module should be allowed.
if (accessingModule != declModule &&
expansion == ResilienceExpansion::Maximal &&
serializedKind == IsSerializedForPackage)
return false;
return D->isResilient(accessingModule, expansion);
}
template <typename DeclType>
bool checkResilience(DeclType *D, const SILFunction &f) {
return checkResilience(D, f.getModule().getSwiftModule(),
f.getResilienceExpansion(),
f.getSerializedKind());
}
bool checkTypeABIAccessible(SILFunction const &F, SILType ty) {
return F.getASTContext().LangOpts.BypassResilienceChecks ||
F.isTypeABIAccessible(ty);
}
/// Metaprogramming-friendly base class.
template <class Impl>
class SILVerifierBase : public SILInstructionVisitor<Impl> {
public:
// visitCLASS calls visitPARENT and checkCLASS.
// checkCLASS does nothing by default.
#define INST(CLASS, PARENT) \
void visit##CLASS(CLASS *I) { \
static_cast<Impl*>(this)->visit##PARENT(I); \
static_cast<Impl*>(this)->check##CLASS(I); \
} \
void check##CLASS(CLASS *I) {}
#include "swift/SIL/SILNodes.def"
void visitSILInstruction(SILInstruction *I) {
static_cast<Impl*>(this)->checkSILInstruction(I);
}
void checkSILInstruction(SILInstruction *I) {}
};
} // end anonymous namespace
namespace {
/// Verify invariants on a key path component.
void verifyKeyPathComponent(SILModule &M,
TypeExpansionContext typeExpansionContext,
SerializedKind_t serializedKind,
llvm::function_ref<void(bool, StringRef)> require,
CanType &baseTy,
CanType leafTy,
const KeyPathPatternComponent &component,
ArrayRef<Operand> operands,
CanGenericSignature patternSig,
SubstitutionMap patternSubs,
bool forPropertyDescriptor,
bool hasIndices) {
auto expansion = typeExpansionContext.getResilienceExpansion();
auto opaque = AbstractionPattern::getOpaque();
auto loweredBaseTy =
M.Types.getLoweredType(opaque, baseTy, typeExpansionContext);
auto componentTy = component.getComponentType().subst(patternSubs)
->getCanonicalType();
auto loweredComponentTy =
M.Types.getLoweredType(opaque, componentTy, typeExpansionContext);
auto getTypeInExpansionContext = [&](CanType ty) -> CanType {
return M.Types.getLoweredType(opaque, ty, typeExpansionContext).getASTType();
};
auto checkIndexEqualsAndHash = [&]{
if (!component.getSubscriptIndices().empty()) {
// Equals should be
// <Sig...> @convention(thin) (RawPointer, RawPointer) -> Bool
{
auto equals = component.getSubscriptIndexEquals();
require(equals, "key path pattern with indexes must have equals "
"operator");
auto substEqualsType = equals->getLoweredFunctionType()
->substGenericArgs(M, patternSubs, TypeExpansionContext::minimal());
require(substEqualsType->getRepresentation() ==
SILFunctionTypeRepresentation::KeyPathAccessorEquals,
"equals should be a keypath equals convention");
require(substEqualsType->getParameters().size() == 2,
"must have two arguments");
for (unsigned i = 0; i < 2; ++i) {
auto param = substEqualsType->getParameters()[i];
require(param.getConvention()
== ParameterConvention::Indirect_In_Guaranteed,
"indices pointer should be in_guaranteed");
}
require(substEqualsType->getResults().size() == 1,
"must have one result");
require(substEqualsType->getResults()[0].getConvention()
== ResultConvention::Unowned,
"result should be unowned");
require(substEqualsType->getResults()[0].getInterfaceType()->isBool(),
"result should be Bool");
}
{
// Hash should be
// <Sig...> @convention(thin) (RawPointer) -> Int
auto hash = component.getSubscriptIndexHash();
require(hash, "key path pattern with indexes must have hash "
"operator");
auto substHashType = hash->getLoweredFunctionType()
->substGenericArgs(M, patternSubs, TypeExpansionContext::minimal());
require(substHashType->getRepresentation() ==
SILFunctionTypeRepresentation::KeyPathAccessorHash,
"hash should be a keypath hash convention");
require(substHashType->getParameters().size() == 1,
"must have two arguments");
auto param = substHashType->getParameters()[0];
require(param.getConvention()
== ParameterConvention::Indirect_In_Guaranteed,
"indices pointer should be in_guaranteed");
require(substHashType->getResults().size() == 1,
"must have one result");
require(substHashType->getResults()[0].getConvention()
== ResultConvention::Unowned,
"result should be unowned");
require(substHashType->getResults()[0].getInterfaceType()->isInt(),
"result should be Int");
}
} else {
require(!component.getSubscriptIndexEquals()
&& !component.getSubscriptIndexHash(),
"component without indexes must not have equals/hash");
}
};
switch (auto kind = component.getKind()) {
case KeyPathPatternComponent::Kind::StoredProperty: {
auto property = component.getStoredPropertyDecl();
if (expansion == ResilienceExpansion::Minimal) {
require(property->getEffectiveAccess() >= AccessLevel::Package,
"Key path in serialized function cannot reference non-public "
"property");
}
auto fieldTy = baseTy->getTypeOfMember(M.getSwiftModule(), property)
->getReferenceStorageReferent()
->getCanonicalType();
require(getTypeInExpansionContext(fieldTy) ==
getTypeInExpansionContext(componentTy),
"property decl should be a member of the base with the same type "
"as the component");
require(property->hasStorage(), "property must be stored");
require(!checkResilience(property, M.getSwiftModule(),
expansion, serializedKind),
"cannot access storage of resilient property");
auto propertyTy =
loweredBaseTy.getFieldType(property, M, typeExpansionContext);
require(propertyTy.getObjectType()
== loweredComponentTy.getObjectType(),
"component type should match the maximal abstraction of the "
"formal type");
break;
}
case KeyPathPatternComponent::Kind::GettableProperty:
case KeyPathPatternComponent::Kind::SettableProperty: {
if (forPropertyDescriptor) {
require(component.getSubscriptIndices().empty()
&& !component.getSubscriptIndexEquals()
&& !component.getSubscriptIndexHash(),
"property descriptor should not have index information");
require(component.getExternalDecl() == nullptr
&& component.getExternalSubstitutions().empty(),
"property descriptor should not refer to another external decl");
} else {
require(hasIndices == !component.getSubscriptIndices().empty(),
"component for subscript should have indices");
}
auto normalArgConvention = ParameterConvention::Indirect_In_Guaranteed;
// Getter should be <Sig...> @convention(thin) (@in_guaranteed Base) -> @out Result
{
auto getter = component.getComputedPropertyGetter();
if (expansion == ResilienceExpansion::Minimal) {
require(serializedKind != IsNotSerialized &&
getter->hasValidLinkageForFragileRef(serializedKind),
"Key path in serialized function should not reference "
"less visible getters");
}
auto substGetterType = getter->getLoweredFunctionType()->substGenericArgs(
M, patternSubs, TypeExpansionContext::minimal());
require(substGetterType->getRepresentation() ==
SILFunctionTypeRepresentation::KeyPathAccessorGetter,
"getter should be a keypath getter convention");
require(substGetterType->getNumParameters() == 1 + hasIndices,
"getter should have one parameter");
auto baseParam = substGetterType->getParameters()[0];
require(baseParam.getConvention() == normalArgConvention,
"getter base parameter should have normal arg convention");
require(getTypeInExpansionContext(baseParam.getArgumentType(
M, substGetterType, typeExpansionContext)) ==
loweredBaseTy.getASTType(),
"getter base parameter should match base of component");
if (hasIndices) {
auto indicesParam = substGetterType->getParameters()[1];
require(indicesParam.getConvention()
== ParameterConvention::Indirect_In_Guaranteed,
"indices should be in_guaranteed");
}
require(substGetterType->getNumResults() == 1,
"getter should have one result");
auto result = substGetterType->getResults()[0];
require(result.getConvention() == ResultConvention::Indirect,
"getter result should be @out");
require(getTypeInExpansionContext(result.getReturnValueType(
M, substGetterType, typeExpansionContext)) ==
getTypeInExpansionContext(loweredComponentTy.getASTType()),
"getter result should match the maximal abstraction of the "
"formal component type");
}
if (kind == KeyPathPatternComponent::Kind::SettableProperty) {
// Setter should be
// <Sig...> @convention(thin) (@in_guaranteed Result, @in Base) -> ()
auto setter = component.getComputedPropertySetter();
if (expansion == ResilienceExpansion::Minimal) {
require(serializedKind != IsNotSerialized &&
setter->hasValidLinkageForFragileRef(serializedKind),
"Key path in serialized function should not reference "
"less visible setters");
}
auto substSetterType = setter->getLoweredFunctionType()
->substGenericArgs(M, patternSubs, TypeExpansionContext::minimal());
require(substSetterType->getRepresentation() ==
SILFunctionTypeRepresentation::KeyPathAccessorSetter,
"setter should be keypath setter convention");
require(substSetterType->getNumParameters() == 2 + hasIndices,
"setter should have two parameters");
auto newValueParam = substSetterType->getParameters()[0];
// TODO: This should probably be unconditionally +1 when we
// can represent that.
require(newValueParam.getConvention() == normalArgConvention,
"setter value parameter should have normal arg convention");
auto baseParam = substSetterType->getParameters()[1];
require(baseParam.getConvention() == normalArgConvention
|| baseParam.getConvention() ==
ParameterConvention::Indirect_Inout,
"setter base parameter should be normal arg convention "
"or @inout");
if (hasIndices) {
auto indicesParam = substSetterType->getParameters()[2];
require(indicesParam.getConvention()
== ParameterConvention::Indirect_In_Guaranteed,
"indices pointer should be in_guaranteed");
}
require(getTypeInExpansionContext(newValueParam.getArgumentType(
M, substSetterType, typeExpansionContext)) ==
getTypeInExpansionContext(loweredComponentTy.getASTType()),
"setter value should match the maximal abstraction of the "
"formal component type");
require(substSetterType->getNumResults() == 0,
"setter should have no results");
}
if (!forPropertyDescriptor) {
for (auto &index : component.getSubscriptIndices()) {
auto opIndex = index.Operand;
auto contextType =
index.LoweredType.subst(M, patternSubs);
require(contextType == operands[opIndex].get()->getType(),
"operand must match type required by pattern");
SILType loweredType = index.LoweredType;
require(
loweredType.isLoweringOf(typeExpansionContext, M, index.FormalType),
"pattern index formal type doesn't match lowered type");
}
checkIndexEqualsAndHash();
}
break;
}
case KeyPathPatternComponent::Kind::OptionalChain: {
require(baseTy->getOptionalObjectType()->isEqual(componentTy),
"chaining component should unwrap optional");
require((bool)leafTy->getOptionalObjectType(),
"key path with chaining component should have optional "
"result");
break;
}
case KeyPathPatternComponent::Kind::OptionalForce: {
require(baseTy->getOptionalObjectType()->isEqual(componentTy),
"forcing component should unwrap optional");
break;
}
case KeyPathPatternComponent::Kind::OptionalWrap: {
require(componentTy->getOptionalObjectType()->isEqual(baseTy),
"wrapping component should wrap optional");
break;
}
case KeyPathPatternComponent::Kind::TupleElement: {
require(baseTy->is<TupleType>(),
"invalid baseTy, should have been a TupleType");
auto tupleTy = baseTy->castTo<TupleType>();
auto eltIdx = component.getTupleIndex();
require(eltIdx < tupleTy->getNumElements(),
"invalid element index, greater than # of tuple elements");
auto eltTy = tupleTy->getElementType(eltIdx)
->getReferenceStorageReferent();
require(eltTy->isEqual(componentTy),
"tuple element type should match the type of the component");
break;
}
}
baseTy = componentTy;
}
/// Check if according to the SIL language model this memory /must only/ be used
/// immutably. Today this is only applied to in_guaranteed arguments and
/// open_existential_addr. We should expand it as needed.
struct ImmutableAddressUseVerifier {
SmallVector<Operand *, 32> worklist;
bool isConsumingOrMutatingArgumentConvention(SILArgumentConvention conv) {
switch (conv) {
case SILArgumentConvention::Indirect_In_Guaranteed:
case SILArgumentConvention::Pack_Guaranteed:
return false;
case SILArgumentConvention::Indirect_InoutAliasable:
// DISCUSSION: We do not consider inout_aliasable to be "truly mutating"
// since today it is just used as a way to mark a captured argument and
// not that something truly has mutating semantics. The reason why this
// is safe is that the typechecker guarantees that if our value was
// immutable, then the use in the closure must be immutable as well.
//
// TODO: Remove this in favor of using Inout and In_Guaranteed.
return false;
case SILArgumentConvention::Pack_Out:
case SILArgumentConvention::Pack_Owned:
case SILArgumentConvention::Pack_Inout:
case SILArgumentConvention::Indirect_Out:
case SILArgumentConvention::Indirect_In:
case SILArgumentConvention::Indirect_Inout:
return true;
case SILArgumentConvention::Direct_Unowned:
case SILArgumentConvention::Direct_Guaranteed:
case SILArgumentConvention::Direct_Owned:
assert(conv.isIndirectConvention() && "Expect an indirect convention");
return true; // return something "conservative".
}
llvm_unreachable("covered switch isn't covered?!");
}
bool isConsumingOrMutatingApplyUse(Operand *use) {
ApplySite apply(use->getUser());
assert(apply && "Not an apply instruction kind");
auto conv = apply.getArgumentConvention(*use);
return isConsumingOrMutatingArgumentConvention(conv);
}
bool isConsumingOrMutatingYieldUse(Operand *use) {
// For now, just say that it is non-consuming for now.
auto *yield = cast<YieldInst>(use->getUser());
auto conv = yield->getArgumentConventionForOperand(*use);
return isConsumingOrMutatingArgumentConvention(conv);
}
// A "copy_addr %src [take] to *" is consuming on "%src".
// A "copy_addr * to * %dst" is mutating on "%dst".
bool isConsumingOrMutatingCopyAddrUse(Operand *use) {
auto *copyAddr = cast<CopyAddrInst>(use->getUser());
if (copyAddr->getDest() == use->get())
return true;
if (copyAddr->getSrc() == use->get() && copyAddr->isTakeOfSrc() == IsTake)
return true;
return false;
}
bool isConsumingOrMutatingExplicitCopyAddrUse(Operand *use) {
auto *copyAddr = cast<ExplicitCopyAddrInst>(use->getUser());
if (copyAddr->getDest() == use->get())
return true;
if (copyAddr->getSrc() == use->get() && copyAddr->isTakeOfSrc() == IsTake)
return true;
return false;
}
/// Handle instructions that move a value from one address into another
/// address.
bool isConsumingOrMutatingMoveAddrUse(Operand *use) {
assert(use->getUser()->getNumOperands() == 2);
auto opIdx = use->getOperandNumber();
if (opIdx == CopyLikeInstruction::Dest)
return true;
assert(opIdx == CopyLikeInstruction::Src);
return false;
}
bool isAddrCastToNonConsuming(SingleValueInstruction *i) {
// Check if any of our uses are consuming. If none of them are consuming, we
// are good to go.
return llvm::none_of(i->getUses(), [&](Operand *use) -> bool {
auto *inst = use->getUser();
switch (inst->getKind()) {
default:
return false;
case SILInstructionKind::ApplyInst:
case SILInstructionKind::TryApplyInst:
case SILInstructionKind::PartialApplyInst:
case SILInstructionKind::BeginApplyInst:
return isConsumingOrMutatingApplyUse(use);
}
});
}
bool isMutatingOrConsuming(SILValue address) {
llvm::copy(address->getUses(), std::back_inserter(worklist));
while (!worklist.empty()) {
auto *use = worklist.pop_back_val();
auto *inst = use->getUser();
if (inst->isTypeDependentOperand(*use))
continue;
// TODO: Can this switch be restructured so break -> error, continue ->
// next iteration, return -> return the final result.
switch (inst->getKind()) {
case SILInstructionKind::BuiltinInst: {
// If we are processing a polymorphic builtin that takes an address,
// skip the builtin. This is because the builtin must be specialized to
// a non-memory reading builtin that works on trivial object values
// before the diagnostic passes end (or be DCEed) or we emit a
// diagnostic.
if (auto builtinKind = cast<BuiltinInst>(inst)->getBuiltinKind()) {
if (isPolymorphicBuiltin(*builtinKind)) {
break;
}
// Get enum tag borrows its operand address value.
if (builtinKind == BuiltinValueKind::GetEnumTag) {
return false;
}
// The optimizer cannot reason about a raw layout type's address due
// to it not respecting formal access scopes.
if (builtinKind == BuiltinValueKind::AddressOfRawLayout) {
return false;
}
}
// Otherwise this is a builtin that we are not expecting to see, so bail
// and assert.
llvm::errs() << "Unhandled, unexpected builtin instruction: " << *inst;
llvm_unreachable("invoking standard assertion failure");
break;
}
case SILInstructionKind::MarkDependenceInst:
case SILInstructionKind::LoadBorrowInst:
case SILInstructionKind::ExistentialMetatypeInst:
case SILInstructionKind::ValueMetatypeInst:
case SILInstructionKind::FixLifetimeInst:
case SILInstructionKind::KeyPathInst:
case SILInstructionKind::SwitchEnumAddrInst:
case SILInstructionKind::SelectEnumAddrInst:
break;
case SILInstructionKind::DebugValueInst:
if (cast<DebugValueInst>(inst)->hasAddrVal())
break;
else {
llvm::errs() << "Unhandled, unexpected instruction: " << *inst;
llvm_unreachable("invoking standard assertion failure");
}
case SILInstructionKind::AddressToPointerInst:
// We assume that the user is attempting to do something unsafe since we
// are converting to a raw pointer. So just ignore this use.
//
// TODO: Can we do better?
break;
case SILInstructionKind::BranchInst:
case SILInstructionKind::CondBranchInst:
// We do not analyze through branches and cond_br instructions and just
// assume correctness. This is so that we can avoid having to analyze
// through phi loops and since we want to remove address phis (meaning
// that this eventually would never be able to happen). Once that
// changes happens, we should remove this code and just error below.
break;
case SILInstructionKind::ApplyInst:
case SILInstructionKind::TryApplyInst:
case SILInstructionKind::PartialApplyInst:
case SILInstructionKind::BeginApplyInst:
if (isConsumingOrMutatingApplyUse(use))
return true;
break;
case SILInstructionKind::YieldInst:
if (isConsumingOrMutatingYieldUse(use))
return true;
break;
case SILInstructionKind::BeginAccessInst:
if (cast<BeginAccessInst>(inst)->getAccessKind() != SILAccessKind::Read)
return true;
break;
case SILInstructionKind::EndAccessInst:
break;
case SILInstructionKind::MarkUnresolvedMoveAddrInst:
// We model mark_unresolved_move_addr as a copy_addr [init]. So no
// mutation can happen. The checker will prove eventually that we can
// convert it to a copy_addr [take] [init].
break;
case SILInstructionKind::ExplicitCopyAddrInst:
if (isConsumingOrMutatingExplicitCopyAddrUse(use))
return true;
else
break;
case SILInstructionKind::CopyAddrInst:
if (isConsumingOrMutatingCopyAddrUse(use))
return true;
else
break;
case SILInstructionKind::DestroyAddrInst:
return true;
case SILInstructionKind::UpcastInst:
case SILInstructionKind::UncheckedAddrCastInst: {
if (isAddrCastToNonConsuming(cast<SingleValueInstruction>(inst))) {
break;
}
return true;
}
case SILInstructionKind::UnconditionalCheckedCastAddrInst:
case SILInstructionKind::UncheckedRefCastAddrInst:
if (isConsumingOrMutatingMoveAddrUse(use)) {
return true;
}
break;
case SILInstructionKind::CheckedCastAddrBranchInst:
switch (cast<CheckedCastAddrBranchInst>(inst)->getConsumptionKind()) {
case CastConsumptionKind::BorrowAlways:
llvm_unreachable("checked_cast_addr_br cannot have BorrowAlways");
case CastConsumptionKind::CopyOnSuccess:
break;
case CastConsumptionKind::TakeAlways:
case CastConsumptionKind::TakeOnSuccess:
return true;
}
break;
case SILInstructionKind::LoadInst:
// A 'non-taking' value load is harmless.
if (cast<LoadInst>(inst)->getOwnershipQualifier() ==
LoadOwnershipQualifier::Take)
return true;
break;
#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
case SILInstructionKind::Load##Name##Inst: \
if (cast<Load##Name##Inst>(inst)->isTake()) \
return true; \
break;
#include "swift/AST/ReferenceStorage.def"
case SILInstructionKind::OpenExistentialAddrInst:
// If we have a mutable use, return true. Otherwise fallthrough since we
// want to look through immutable uses.
if (cast<OpenExistentialAddrInst>(inst)->getAccessKind() !=
OpenedExistentialAccess::Immutable)
return true;
LLVM_FALLTHROUGH;
case SILInstructionKind::MoveOnlyWrapperToCopyableAddrInst:
case SILInstructionKind::CopyableToMoveOnlyWrapperAddrInst:
case SILInstructionKind::StructElementAddrInst:
case SILInstructionKind::TupleElementAddrInst:
case SILInstructionKind::IndexAddrInst:
case SILInstructionKind::TailAddrInst:
case SILInstructionKind::IndexRawPointerInst:
case SILInstructionKind::MarkUnresolvedNonCopyableValueInst:
case SILInstructionKind::CopyableToMoveOnlyWrapperValueInst:
case SILInstructionKind::PackElementGetInst:
// Add these to our worklist.
for (auto result : inst->getResults()) {
llvm::copy(result->getUses(), std::back_inserter(worklist));
}
break;
case SILInstructionKind::UncheckedTakeEnumDataAddrInst: {
if (!cast<UncheckedTakeEnumDataAddrInst>(inst)->isDestructive()) {
for (auto result : inst->getResults()) {
llvm::copy(result->getUses(), std::back_inserter(worklist));
}
break;
}
llvm::errs() << "Unhandled, unexpected instruction: " << *inst;
llvm_unreachable("invoking standard assertion failure");
break;
}
case SILInstructionKind::TuplePackElementAddrInst: {
if (&cast<TuplePackElementAddrInst>(inst)->getOperandRef(
TuplePackElementAddrInst::TupleOperand) == use) {
for (auto result : inst->getResults()) {
llvm::copy(result->getUses(), std::back_inserter(worklist));
}
break;
}
return false;
}
case SILInstructionKind::PackElementSetInst: {
if (&cast<PackElementSetInst>(inst)->getOperandRef(
PackElementSetInst::PackOperand) == use)
return true;
return false;
}
default:
llvm::errs() << "Unhandled, unexpected instruction: " << *inst;
llvm_unreachable("invoking standard assertion failure");
break;
}
}
return false;
}
};
static void checkAddressWalkerCanVisitAllTransitiveUses(SILValue address) {
SmallVector<SILInstruction *, 8> badUsers;
struct Visitor : TransitiveAddressWalker<Visitor> {
SmallVectorImpl<SILInstruction *> &badUsers;
Visitor(SmallVectorImpl<SILInstruction *> &badUsers)
: TransitiveAddressWalker<Visitor>(), badUsers(badUsers) {}
bool visitUse(Operand *use) { return true; }
void onError(Operand *use) {
badUsers.push_back(use->getUser());
}
};
Visitor visitor(badUsers);
if (std::move(visitor).walk(address) != AddressUseKind::Unknown)
return;
llvm::errs() << "TransitiveAddressWalker walker failed to know how to visit "
"a user when visiting: "
<< *address;
if (badUsers.size()) {
llvm::errs() << "Bad Users:\n";
for (auto *user : badUsers) {
llvm::errs() << " " << *user;
}
}
llvm::report_fatal_error("invoking standard assertion failure");
}
/// The SIL verifier walks over a SIL function / basic block / instruction,
/// checking and enforcing its invariants.
class SILVerifier : public SILVerifierBase<SILVerifier> {
ModuleDecl *M;
const SILFunction &F;
CalleeCache *calleeCache;
SILFunctionConventions fnConv;
Lowering::TypeConverter &TC;
bool SingleFunction = true;
bool checkLinearLifetime = false;
SmallVector<std::pair<StringRef, SILType>, 16> DebugVars;
const SILInstruction *CurInstruction = nullptr;
const SILArgument *CurArgument = nullptr;
std::unique_ptr<DominanceInfo> Dominance;
// Used for dominance checking within a basic block.
llvm::DenseMap<const SILInstruction *, unsigned> InstNumbers;
std::unique_ptr<DeadEndBlocks> DEBlocks;
LoadBorrowImmutabilityAnalysis loadBorrowImmutabilityAnalysis;
/// A cache of the isOperandInValueUse check. When we process an operand, we
/// fix this for each of its uses.
llvm::DenseSet<std::pair<SILValue, const Operand *>> isOperandInValueUsesCache;
/// Used for checking all equivalent variables have the same type
using VarID = std::tuple<const SILDebugScope *, llvm::StringRef, SILLocation>;
llvm::DenseMap<VarID, SILType> DebugVarTypes;
llvm::StringSet<> VarNames;
/// Check that this operand appears in the use-chain of the value it uses.
bool isOperandInValueUses(const Operand *operand) {
SILValue value = operand->get();
// First check the cache.
if (isOperandInValueUsesCache.contains({value, operand}))
return true;
// Otherwise, compute the value and initialize the cache for each of the
// operand's value uses.
bool foundUse = false;
for (auto *use : value->getUses()) {
if (use == operand) {
foundUse = true;
}
isOperandInValueUsesCache.insert({value, use});
}
return foundUse;
}
SILVerifier(const SILVerifier&) = delete;
void operator=(const SILVerifier&) = delete;
public:
bool isSILOwnershipEnabled() const {
return F.getModule().getOptions().VerifySILOwnership;
}
void _require(bool condition, const Twine &complaint,
const std::function<void()> &extraContext = nullptr) {
if (condition) return;
StringRef funcName;
if (CurInstruction)
funcName = CurInstruction->getFunction()->getName();
else if (CurArgument)
funcName = CurArgument->getFunction()->getName();
if (ContinueOnFailure) {
llvm::dbgs() << "Begin Error in function " << funcName << "\n";
}
llvm::dbgs() << "SIL verification failed: " << complaint << "\n";
if (extraContext)
extraContext();
if (CurInstruction) {
llvm::dbgs() << "Verifying instruction:\n";
CurInstruction->printInContext(llvm::dbgs());
} else if (CurArgument) {
llvm::dbgs() << "Verifying argument:\n";
CurArgument->printInContext(llvm::dbgs());
}
if (ContinueOnFailure) {
llvm::dbgs() << "End Error in function " << funcName << "\n";
return;
}
llvm::dbgs() << "In function:\n";
F.print(llvm::dbgs());
if (DumpModuleOnFailure) {
// Don't do this by default because modules can be _very_ large.
llvm::dbgs() << "In module:\n";
F.getModule().print(llvm::dbgs());
}
// We abort by default because we want to always crash in
// the debugger.
if (AbortOnFailure)
abort();
else
exit(1);
}
#define require(condition, complaint) \
_require(bool(condition), complaint ": " #condition)
template <class T> typename CanTypeWrapperTraits<T>::type
_requireObjectType(SILType type, const Twine &valueDescription,
const char *typeName) {
_require(type.isObject(), valueDescription + " must be an object");
auto result = type.getAs<T>();
_require(bool(result), valueDescription + " must have type " + typeName);
return result;
}
template <class T> typename CanTypeWrapperTraits<T>::type
_requireObjectType(SILValue value, const Twine &valueDescription,
const char *typeName) {
return _requireObjectType<T>(value->getType(), valueDescription, typeName);
}
#define requireObjectType(type, value, valueDescription) \
_requireObjectType<type>(value, valueDescription, #type)
template <class T> typename CanTypeWrapperTraits<T>::type
_requireAddressType(SILType type, const Twine &valueDescription,
const char *typeName) {
_require(type.isAddress(), valueDescription + " must be an address");
auto result = type.getAs<T>();
_require(bool(result), valueDescription + " must have type " + typeName);
return result;
}
template <class T> typename CanTypeWrapperTraits<T>::type
_requireAddressType(SILValue value, const Twine &valueDescription,
const char *typeName) {
return _requireAddressType<T>(value->getType(), valueDescription, typeName);
}
#define requireAddressType(type, value, valueDescription) \
_requireAddressType<type>(value, valueDescription, #type)
template <class T>
typename CanTypeWrapperTraits<T>::type
_forbidObjectType(SILType type, const Twine &valueDescription,
const char *typeName) {
_require(type.isObject(), valueDescription + " must be an object");
auto result = type.getAs<T>();
_require(!bool(result),
valueDescription + " must not have type " + typeName);
return result;
}
template <class T>
typename CanTypeWrapperTraits<T>::type
_forbidObjectType(SILValue value, const Twine &valueDescription,
const char *typeName) {
return _forbidObjectType<T>(value->getType(), valueDescription, typeName);
}
#define forbidObjectType(type, value, valueDescription) \
_forbidObjectType<type>(value, valueDescription, #type)
// Require that the operand is a non-optional, non-unowned reference-counted
// type.
void requireReferenceValue(SILValue value, const Twine &valueDescription) {
require(value->getType().isObject(),
valueDescription + " must be an object");
require(value->getType().isReferenceCounted(F.getModule()) ||
value->getType().isForeignReferenceType(),
valueDescription + " must have reference semantics");
forbidObjectType(UnownedStorageType, value, valueDescription);
}
// Require that the operand is a reference-counted type, or an Optional
// thereof.
void requireReferenceOrOptionalReferenceValue(SILValue value,
const Twine &valueDescription) {
require(value->getType().isObject(), valueDescription +" must be an object");
auto objectTy = value->getType().unwrapOptionalType();
require(objectTy.isReferenceCounted(F.getModule()),
valueDescription + " must have reference semantics");
}
// Require that the operand is a type that supports reference storage
// modifiers.
void requireReferenceStorageCapableValue(SILValue value,
const Twine &valueDescription) {
requireReferenceOrOptionalReferenceValue(value, valueDescription);
require(!value->getType().is<SILFunctionType>(),
valueDescription + " cannot apply to a function type");
}
/// Require the operand to be `$Optional<Builtin.Executor>`.
void requireOptionalExecutorType(SILValue value, const Twine &what) {
auto type = value->getType();
require(type.isObject(), what + " must be an object type");
auto objectType = type.getASTType().getOptionalObjectType();
require(objectType && objectType == M->getASTContext().TheExecutorType,
what + " must be Optional<Builtin.Executor>");
}
/// Assert that two types are equal.
void requireSameType(Type type1, Type type2, const Twine &complaint) {
_require(type1->isEqual(type2), complaint,
[&] { llvm::dbgs() << " " << type1 << "\n " << type2 << '\n'; });
}
/// Assert that two types are equal.
void requireSameType(SILType type1, SILType type2, const Twine &complaint) {
_require(type1 == type2, complaint,
[&] { llvm::dbgs() << " " << type1 << "\n " << type2 << '\n'; });
}
SynthesisContext getSynthesisContext() {
auto dc = F.getDeclContext();
if (!dc) dc = F.getParentModule();
return SynthesisContext(F.getASTContext(), dc);
}
template <class S>
void requireType(SILType type1, const S &s, const Twine &what) {
auto sc = getSynthesisContext();
SILType type2 = synthesizeSILType(sc, s);
requireSameType(type1, type2, "type mismatch in " + what);
}
/// Require two function types to be ABI-compatible.
void requireABICompatibleFunctionTypes(CanSILFunctionType type1,
CanSILFunctionType type2,
const Twine &what,
SILFunction &inFunction) {
auto complain = [=](const char *msg) -> std::function<void()> {
return [=]{
llvm::dbgs() << " " << msg << '\n'
<< " " << type1 << "\n " << type2 << '\n';
};
};
auto complainBy = [=](std::function<void()> msg) -> std::function<void()> {
return [=]{
msg();
llvm::dbgs() << '\n';
llvm::dbgs() << " " << type1 << "\n " << type2 << '\n';
};
};
// If we didn't have a failure, return.
auto Result = type1->isABICompatibleWith(type2, inFunction);
if (Result.isCompatible())
return;
if (!Result.hasPayload()) {
_require(false, what, complain(Result.getMessage().data()));
} else {
_require(false, what, complainBy([=] {
llvm::dbgs() << " " << Result.getMessage().data()
<< ".\nParameter: " << Result.getPayload();
}));
}
}
void requireSameFunctionComponents(CanSILFunctionType type1,
CanSILFunctionType type2,
const Twine &what) {
require(type1->getNumResults() == type2->getNumResults(),
"results of " + what + " do not match in count");
for (auto i : indices(type1->getResults())) {
require(type1->getResults()[i] == type2->getResults()[i],
"result " + Twine(i) + " of " + what + " do not match");
}
require(type1->getParameters().size() ==
type2->getParameters().size(),
"inputs of " + what + " do not match in count");
for (auto i : indices(type1->getParameters())) {
require(type1->getParameters()[i] ==
type2->getParameters()[i],
"input " + Twine(i) + " of " + what + " do not match");
}
}
template <class T>
T *requireValueKind(SILValue value, const Twine &what) {
auto match = dyn_cast<T>(value);
_require(match != nullptr, what, [=] { llvm::dbgs() << value; });
return match;
}
static unsigned numInstsInFunction(const SILFunction &F) {
unsigned numInsts = 0;
for (auto &BB : F) {
numInsts += std::distance(BB.begin(), BB.end());
}
return numInsts;
}
SILVerifier(const SILFunction &F, CalleeCache *calleeCache,
bool SingleFunction, bool checkLinearLifetime)
: M(F.getModule().getSwiftModule()), F(F),
calleeCache(calleeCache),
fnConv(F.getConventionsInContext()), TC(F.getModule().Types),
SingleFunction(SingleFunction),
checkLinearLifetime(checkLinearLifetime),
Dominance(nullptr),
InstNumbers(numInstsInFunction(F)),
loadBorrowImmutabilityAnalysis(DEBlocks.get(), &F) {
if (F.isExternalDeclaration())
return;
// Check to make sure that all blocks are well formed. If not, the
// SILVerifier object will explode trying to compute dominance info.
unsigned InstIdx = 0;
for (auto &BB : F) {
require(!BB.empty(), "Basic blocks cannot be empty");
require(isa<TermInst>(BB.back()),
"Basic blocks must end with a terminator instruction");
for (auto &I : BB)
InstNumbers[&I] = InstIdx++;
}
Dominance.reset(new DominanceInfo(const_cast<SILFunction *>(&F)));
auto *DebugScope = F.getDebugScope();
require(DebugScope, "All SIL functions must have a debug scope");
require(DebugScope->Parent.get<SILFunction *>() == &F,
"Scope of SIL function points to different function");
}
// Checks dominance between two instructions.
// This does not use DominanceInfo.properlyDominates, because for large basic
// blocks it would result in quadratic behavior.
bool properlyDominates(SILInstruction *a, SILInstruction *b) {
auto aBlock = a->getParent(), bBlock = b->getParent();
require(aBlock->getParent() == bBlock->getParent(),
"instructions are not in the same function");
// If the blocks are different, it's as easy as whether A's block
// dominates B's block.
if (aBlock != bBlock)
return Dominance->properlyDominates(aBlock, bBlock);
return InstNumbers[a] < InstNumbers[b];
}
void visitSILPhiArgument(SILPhiArgument *arg) {
// Verify that the `isPhiArgument` property is sound:
// - Phi arguments come from branches.
// - Non-phi arguments have a single predecessor.
assert(arg->isPhi() && "precondition");
for (SILBasicBlock *predBB : arg->getParent()->getPredecessorBlocks()) {
auto *TI = predBB->getTerminator();
if (F.hasOwnership()) {
require(isa<BranchInst>(TI), "All phi inputs must be branch operands.");
// Address-only values are potentially unmovable when borrowed. See also
// checkOwnershipForwardingInst. A phi implies a move of its arguments
// because they can't necessarily all reuse the same storage.
require((!arg->getType().isAddressOnly(F)
|| arg->getOwnershipKind() != OwnershipKind::Guaranteed),
"Guaranteed address-only phi not allowed--implies a copy");
} else {
// FIXME: when critical edges are removed and cond_br arguments are
// disallowed, only allow BranchInst.
require(isa<BranchInst>(TI) || isa<CondBranchInst>(TI),
"All phi argument inputs must be from branches.");
}
}
if (arg->isPhi()) {
// As a property of well-formed SIL, we disallow address-type
// phis. Supporting them would prevent reliably reasoning about the
// underlying storage of memory access. This reasoning is important for
// diagnosing violations of memory access rules and supporting future
// optimizations such as bitfield packing. Address-type block arguments
// also create unnecessary complexity for SIL optimization passes that
// need to reason about memory aliasing.
require(!arg->getType().isAddress(),
"Block arguments cannot be addresses");
}
}
void visitSILArgument(SILArgument *arg) {
CurArgument = arg;
checkLegalType(arg->getFunction(), arg, nullptr);
// Ensure flags on the argument are not stale.
require(!arg->getFunction()->hasOwnership() ||
computeIsReborrow(arg) == arg->isReborrow(),
"Stale reborrow flag");
if (checkLinearLifetime) {
checkValueBaseOwnership(arg);
}
if (auto *phiArg = dyn_cast<SILPhiArgument>(arg)) {
if (phiArg->isPhi())
visitSILPhiArgument(phiArg);
else {
// A non-phi BlockArgument must have a single predecessor unless it is
// unreachable.
require(arg->getParent()->pred_empty()
|| arg->getParent()->getSinglePredecessorBlock(),
"Non-branch terminator must have a unique successor.");
}
return;
}
// If we are not in lowered SIL and have an in_guaranteed function argument,
// verify that we do not mutate or consume it.
auto *fArg = cast<SILFunctionArgument>(arg);
if (fArg->getType().isAddress())
checkAddressWalkerCanVisitAllTransitiveUses(fArg);
if (fArg->getModule().getStage() == SILStage::Lowered ||
!fArg->getType().isAddress() ||
!fArg->hasConvention(SILArgumentConvention::Indirect_In_Guaranteed))
return;
require(!ImmutableAddressUseVerifier().isMutatingOrConsuming(fArg),
"Found mutating or consuming use of an in_guaranteed parameter?!");
}
void visitSILInstruction(SILInstruction *I) {
CurInstruction = I;
checkSILInstruction(I);
// Check the SILLLocation attached to the instruction,
// as well as debug-variable-carrying instructions.
checkInstructionsDebugInfo(I);
// Check ownership and types.
SILFunction *F = I->getFunction();
assert(F && "Expected value base with parent function");
for (auto result : I->getResults()) {
checkLegalType(F, result, I);
if (checkLinearLifetime) {
checkValueBaseOwnership(result);
}
}
}
void checkValueBaseOwnership(ValueBase *V) {
// If ownership is not enabled, bail.
if (!isSILOwnershipEnabled())
return;
SILFunction *F = V->getFunction();
assert(F && "Expected value base with parent function");
// If we do not have qualified ownership, then do not verify value base
// ownership.
if (!F->hasOwnership()) {
require(SILValue(V)->getOwnershipKind() == OwnershipKind::None,
"Once ownership is gone, all values should have none ownership");
return;
}
SILValue(V).verifyOwnership(DEBlocks.get());
}
void checkSILInstruction(SILInstruction *I) {
const SILBasicBlock *BB = I->getParent();
require(BB, "Instruction with null parent");
// Check that non-terminators look ok.
if (!isa<TermInst>(I)) {
require(!BB->empty(), "Can't be in a parent block if it is empty");
if (!I->isStaticInitializerInst()) {
require(&*BB->rbegin() != I,
"Non-terminators cannot be the last in a block");
}
} else {
require(&*BB->rbegin() == I,
"Terminator must be the last in block");
}
// Verify that all of our uses are in this function.
for (auto result : I->getResults()) {
for (Operand *use : result->getUses()) {
auto user = use->getUser();
require(user, "instruction user is null?");
require(isa<SILInstruction>(user),
"instruction used by non-instruction");
auto userI = cast<SILInstruction>(user);
require(userI->getParent(),
"instruction used by unparented instruction");
if (I->isStaticInitializerInst()) {
require(userI->getParent() == BB,
"instruction used by instruction not in same static initializer");
} else {
require(userI->getFunction() == &F,
"instruction used by instruction in different function");
}
auto operands = userI->getAllOperands();
require(operands.begin() <= use && use <= operands.end(),
"use doesn't actually belong to instruction it claims to");
}
}
// Verify some basis structural stuff about an instruction's operands.
for (auto &operand : I->getAllOperands()) {
require(operand.get(), "instruction has null operand");
require(!isa<PlaceholderValue>(operand.get()),
"instruction has placeholder operand");
if (auto *valueI = operand.get()->getDefiningInstruction()) {
require(valueI->getParent(),
"instruction uses value of unparented instruction");
if (I->isStaticInitializerInst()) {
require(valueI->getParent() == BB,
"instruction uses value which is not in same static initializer");
} else {
require(valueI->getFunction() == &F,
"instruction uses value of instruction from another function");
require(properlyDominates(valueI, I),
"instruction isn't dominated by its operand");
}
}
if (auto *valueBBA = dyn_cast<SILArgument>(operand.get())) {
require(!I->isStaticInitializerInst(),
"static initializer inst cannot refer to SILArgument");
require(valueBBA->getParent(),
"instruction uses value of unparented instruction");
require(valueBBA->getFunction() == &F,
"bb argument value from another function");
require(Dominance->dominates(valueBBA->getParent(), I->getParent()),
"instruction isn't dominated by its bb argument operand");
}
if (auto *undef = dyn_cast<SILUndef>(operand.get())) {
require(undef->getParent() == BB->getParent(), "SILUndef in wrong function");
}
require(operand.getUser() == I,
"instruction's operand's owner isn't the instruction");
require(isOperandInValueUses(&operand), "operand value isn't used by operand");
if (operand.isTypeDependent()) {
require(isa<SILInstruction>(I),
"opened archetype operand should refer to a SILInstruction");
}
// Make sure that if operand is generic that its primary archetypes match
// the function context.
checkLegalType(I->getFunction(), operand.get(), I);
// If we are not in OSSA, our operand constraint should be invalid for a
// type dependent operand (that is Optional::None) and if we have a non
// type dependent operand then we should have a constraint of
// OwnershipKind::Any, UseLifetimeConstraint::NonLifetimeEnding.
if (!I->getFunction()->hasOwnership()) {
auto constraint = operand.getOwnershipConstraint();
require(constraint.getPreferredKind() == OwnershipKind::Any &&
constraint.getLifetimeConstraint() ==
UseLifetimeConstraint::NonLifetimeEnding,
"In non-ossa all non-type dependent operands must have a "
"constraint of Any, NonLifetimeEnding");
} else {
// Perform some structural checks on the operand if we have ownership.
// Make sure that our operand constraint isn't Unowned. There do not
// exist in SIL today any instructions that require an Unowned
// value. This is because we want to always allow for guaranteed and
// owned values to be passed as values to operands that take unowned.
auto constraint = operand.getOwnershipConstraint();
require(constraint.getPreferredKind() != OwnershipKind::Unowned,
"Operand constraint should never have an unowned preferred "
"kind since guaranteed and owned values can always be passed "
"in unowned positions");
require(operand.getOperandOwnership() !=
OperandOwnership::InteriorPointer ||
InteriorPointerOperandKind::get(&operand) !=
InteriorPointerOperandKind::Invalid,
"All operands with InteriorPointer operand ownership should be "
"added to the InteriorPointerOperand utility");
}
}
if (I->getFunction()->hasOwnership()) {
if (auto fwdOp = ForwardingOperation(I))
checkOwnershipForwardingInst(fwdOp);
}
}
// Verify the result of any forwarding terminator, including switch_enum.
void checkForwardedTermResult(OwnershipForwardingTermInst *term,
SILBasicBlock *destBB) {
require(destBB->getNumArguments() == 1,
"OwnershipForwardingTermInst needs a single result");
auto *arg = destBB->getArgument(0);
auto argKind = arg->getOwnershipKind();
// A terminator may cast a nontrivial to a trivial type. e.g. a trivial
// payload in a nontrivial enum. If the result is trivial, it no longer
// requires ownership.
if (arg->getType().isTrivial(F) && argKind == OwnershipKind::None)
return;
require(argKind == term->getForwardingOwnershipKind(),
"OwnershipForwardingTermInst nontrivial result "
"must have the same ownership");
}
/// A terminator result is forwarded from the terminator's operand. Forwarding
/// a nontrivial value to another nontrivial value can never gain or lose
/// ownership information. If the terminator's operand has ownership and the
/// result is nontrivial, then the result must have identical ownership.
///
/// The terminator result can only "lose" ownership if the operand is
/// nontrivial but the result is trivial. It is still valid for the trivial
/// result to retain the operand's ownership, but unnecessary and produces
/// less efficient SIL.
void checkOwnershipForwardingTermInst(OwnershipForwardingTermInst *term) {
// Verifying switch_enum ownership requires evaluating the payload
// types. These are fully verified by checkSwitchEnumInst.
if (isa<SwitchEnumInst>(term))
return;
for (auto &succ : term->getSuccessors()) {
checkForwardedTermResult(term, succ.getBB());
}
}
/// For an instruction \p i that forwards ownership from an operand to one
/// of its results, check forwarding invariants.
void checkOwnershipForwardingInst(ForwardingOperation fwdOp) {
auto ownership = fwdOp.getForwardingOwnershipKind();
if (fwdOp.canForwardOwnedCompatibleValuesOnly()) {
ValueOwnershipKind kind = OwnershipKind::Owned;
require(kind.isCompatibleWith(ownership),
"OwnedFirstArgForwardingSingleValueInst's ownership kind must be "
"compatible with owned");
}
if (fwdOp.canForwardGuaranteedCompatibleValuesOnly()) {
ValueOwnershipKind kind = OwnershipKind::Guaranteed;
require(kind.isCompatibleWith(ownership),
"GuaranteedFirstArgForwardingSingleValueInst's ownership kind "
"must be compatible with guaranteed");
}
if (auto *term = dyn_cast<OwnershipForwardingTermInst>(*fwdOp)) {
checkOwnershipForwardingTermInst(term);
}
// Address-only values are potentially unmovable when borrowed. Ensure that
// guaranteed address-only values are forwarded with the same
// representation. Non-destructive projection is allowed. Aggregation and
// destructive disaggregation is not allowed. See SIL.rst, Forwarding
// Address-Only Values.
if (ownership == OwnershipKind::Guaranteed && fwdOp.isAddressOnly()) {
require(fwdOp.hasSameRepresentation(),
"Forwarding a guaranteed address-only value requires the same "
"representation since no move or copy is allowed.");
}
}
void checkDebugVariable(SILInstruction *inst) {
std::optional<SILDebugVariable> varInfo;
if (auto di = DebugVarCarryingInst(inst))
varInfo = di.getVarInfo();
if (!varInfo)
return;
// Retrieve debug variable type
SILType SSAType;
switch (inst->getKind()) {
case SILInstructionKind::AllocStackInst:
case SILInstructionKind::AllocBoxInst:
// TODO: unwrap box for AllocBox
SSAType = inst->getResult(0)->getType().getObjectType();
break;
case SILInstructionKind::DebugValueInst:
SSAType = inst->getOperand(0)->getType();
break;
default:
llvm_unreachable("impossible instruction kind");
}
SILType DebugVarTy = varInfo->Type ? *varInfo->Type :
SSAType.getObjectType();
if (!varInfo->DIExpr && !isa<SILBoxType>(SSAType.getASTType())) {
// FIXME: Remove getObjectType() below when we fix create/createAddr
require(DebugVarTy.removingMoveOnlyWrapper()
== SSAType.getObjectType().removingMoveOnlyWrapper(),
"debug type mismatch without a DIExpr");
}
auto *debugScope = inst->getDebugScope();
if (varInfo->ArgNo)
require(!varInfo->Name.empty(), "function argument without a name");
// Check that there is at most one debug variable defined for each argument
// slot if our debug scope is not an inlined call site.
//
// This catches SIL transformations that accidentally remove inline
// information (stored in the SILDebugScope) from debug-variable-carrying
// instructions.
if (debugScope && !debugScope->InlinedCallSite)
if (unsigned argNum = varInfo->ArgNo) {
// It is a function argument.
if (argNum < DebugVars.size() && !DebugVars[argNum].first.empty()) {
require(DebugVars[argNum].first == varInfo->Name,
"Scope contains conflicting debug variables for one function "
"argument");
// The source variable might change its location (e.g. due to
// optimizations). Check for most common transformations (e.g. loading
// to SSA value and vice versa) as well
require(DebugVars[argNum].second == DebugVarTy ||
(DebugVars[argNum].second.isAddress() &&
DebugVars[argNum].second.getObjectType() == DebugVarTy) ||
(DebugVarTy.isAddress() &&
DebugVars[argNum].second == DebugVarTy.getObjectType()),
"conflicting debug variable type!");
DebugVars[argNum].second = DebugVarTy;
} else {
// Reserve enough space.
while (DebugVars.size() <= argNum) {
DebugVars.push_back({StringRef(), SILType()});
}
}
DebugVars[argNum] = {varInfo->Name, DebugVarTy};
}
// Check the (auxiliary) debug variable scope
if (const SILDebugScope *VarDS = varInfo->Scope)
require(VarDS->getInlinedFunction() == debugScope->getInlinedFunction(),
"Scope of the debug variable should have the same parent function"
" as that of instruction.");
// Check that every var info with the same name, scope and location, refer
// to a variable of the same type
llvm::StringRef UniqueName = VarNames.insert(varInfo->Name).first->getKey();
if (!varInfo->Loc)
varInfo->Loc = inst->getLoc();
if (!varInfo->Loc)
varInfo->Loc = SILLocation::invalid();
VarID Key(varInfo->Scope ? varInfo->Scope : debugScope,
UniqueName, *varInfo->Loc);
auto CachedVar = DebugVarTypes.insert({Key, DebugVarTy});
if (!CachedVar.second) {
auto lhs = CachedVar.first->second.removingMoveOnlyWrapper();
auto rhs = DebugVarTy.removingMoveOnlyWrapper();
require(lhs == rhs ||
(lhs.isAddress() && lhs.getObjectType() == rhs) ||
(DebugVarTy.isAddress() && lhs == rhs.getObjectType()),
"Two variables with different type but same scope!");
}
// Check debug info expression
if (const auto &DIExpr = varInfo->DIExpr) {
bool HasFragment = false;
for (auto It = DIExpr.element_begin(), ItEnd = DIExpr.element_end();
It != ItEnd;) {
require(It->getKind() == SILDIExprElement::OperatorKind,
"dangling di-expression operand");
auto Op = It->getAsOperator();
const auto *DIExprInfo = SILDIExprInfo::get(Op);
require(DIExprInfo, "unrecognized di-expression operator");
++It;
// Check operand kinds
for (auto OpK : DIExprInfo->OperandKinds)
require(It != ItEnd && (It++)->getKind() == OpK,
"di-expression operand kind mismatch");
if (Op == SILDIExprOperator::Fragment ||
Op == SILDIExprOperator::TupleFragment)
HasFragment = true;
else
require(!HasFragment, "no directive allowed after op_fragment"
" in a di-expression");
}
}
}
void checkInstructionsDebugInfo(SILInstruction *inst) {
// First verify structural debug info information.
inst->verifyDebugInfo();
// Check the debug scope.
auto *debugScope = inst->getDebugScope();
if (debugScope && !maybeScopeless(*inst))
require(debugScope, "instruction has a location, but no scope");
require(!debugScope ||
debugScope->getParentFunction() == inst->getFunction(),
"debug scope of instruction belongs to a different function");
checkDebugVariable(inst);
}
/// Check that the types of this value producer are all legal in the function
/// context in which it exists.
void checkLegalType(SILFunction *F, ValueBase *value, SILInstruction *I) {
SILType type = value->getType();
if (type.is<SILTokenType>()) {
require(isLegalSILTokenProducer(value),
"SIL tokens can only be produced as the results of specific "
"instructions");
return;
}
checkLegalType(F, type, I);
}
static bool isLegalSILTokenProducer(SILValue value) {
if (auto *baResult = isaResultOf<BeginApplyInst>(value))
return baResult->isBeginApplyToken();
if (isa<OpenPackElementInst>(value))
return true;
if (auto *bi = dyn_cast<BuiltinInst>(value)) {
if (bi->getBuiltinInfo().ID == BuiltinValueKind::Once)
return true;
}
// Add more token cases here as they arise.
return false;
}
/// Check that the given type is a legal SIL value type.
void checkLegalType(SILFunction *F, SILType type, SILInstruction *I) {
checkLegalSILType(F, type.getASTType(), I);
}
/// Check that the given type is a legal SIL value type.
void checkLegalSILType(SILFunction *F, CanType rvalueType, SILInstruction *I) {
// These types should have been removed by lowering.
require(!isa<LValueType>(rvalueType),
"l-value types are not legal in SIL");
require(!isa<AnyFunctionType>(rvalueType),
"AST function types are not legal in SIL");
// Tuples should have had their element lowered.
if (auto tuple = dyn_cast<TupleType>(rvalueType)) {
for (auto eltTy : tuple.getElementTypes()) {
checkLegalSILType(F, eltTy, I);
}
return;
}
// Optionals should have had their objects lowered.
if (auto objectType = rvalueType.getOptionalObjectType()) {
return checkLegalSILType(F, objectType, I);
}
// Metatypes should have explicit representations.
if (auto metatype = dyn_cast<AnyMetatypeType>(rvalueType)) {
require(metatype->hasRepresentation(),
"metatypes in SIL must have a representation");;
// fallthrough for archetype check
}
rvalueType.visit([&](CanType t) {
auto A = dyn_cast<ArchetypeType>(t);
if (!A)
return;
require(isArchetypeValidInFunction(A, F),
"Operand is of an ArchetypeType that does not exist in the "
"Caller's generic param list.");
if (auto localA = getLocalArchetypeOf(A)) {
auto *openingInst =
F->getModule().getRootLocalArchetypeDefInst(localA.getRoot(), F);
require(I == nullptr || openingInst == I ||
properlyDominates(openingInst, I),
"Use of a local archetype should be dominated by a "
"definition of this root local archetype");
}
});
}
/// \return True if all of the users of the AllocStack instruction \p ASI are
/// inside the same basic block.
static bool isSingleBlockUsage(AllocStackInst *ASI, DominanceInfo *Dominance){
SILBasicBlock *BB = ASI->getParent();
for (auto UI = ASI->use_begin(), E = ASI->use_end(); UI != E; ++UI)
if (UI->getUser()->getParent() != BB &&
Dominance->isReachableFromEntry(UI->getUser()->getParent()))
return false;
return true;
}
void checkAllocStackInst(AllocStackInst *AI) {
require(AI->getType().isAddress(),
"result of alloc_stack must be an address type");
verifyLocalArchetype(AI, AI->getElementType().getASTType());
require(!AI->isVarInfoInvalidated() || !bool(AI->getVarInfo()),
"AllocStack Var Info should be None if invalidated");
checkAddressWalkerCanVisitAllTransitiveUses(AI);
// There used to be a check if all uses of ASI are inside the alloc-dealloc
// range. But apparently it can be the case that ASI has uses after the
// dealloc_stack. This can come up if the source contains a
// withUnsafePointer where the pointer escapes.
// It's illegal code but the compiler should not crash on it.
}
void checkAllocVectorInst(AllocVectorInst *AI) {
require(AI->getType().isAddress(),
"result of alloc_vector must be an address type");
require(AI->getOperand()->getType().is<BuiltinIntegerType>(),
"capacity needs integer type");
}
void checkAllocPackInst(AllocPackInst *AI) {
requireAddressType(SILPackType, AI->getType(),
"result of alloc_pack must be an address of "
"lowered pack type");
checkAddressWalkerCanVisitAllTransitiveUses(AI);
}
void checkAllocRefBase(AllocRefInstBase *ARI) {
requireReferenceValue(ARI, "Result of alloc_ref");
verifyLocalArchetype(ARI, ARI->getType().getASTType());
auto Types = ARI->getTailAllocatedTypes();
auto Counts = ARI->getTailAllocatedCounts();
unsigned NumTypes = Types.size();
require(NumTypes == Counts.size(), "Mismatching types and counts");
require(NumTypes == 0 || !ARI->isObjC(),
"Can't tail allocate with ObjC class");
for (unsigned Idx = 0; Idx < NumTypes; ++Idx) {
verifyLocalArchetype(ARI, Types[Idx].getASTType());
require(Counts[Idx].get()->getType().is<BuiltinIntegerType>(),
"count needs integer type");
}
}
void checkAllocRefInst(AllocRefInst *AI) {
require(AI->isObjC() || AI->getType().getClassOrBoundGenericClass(),
"alloc_ref must allocate class");
checkAllocRefBase(AI);
}
void checkAllocRefDynamicInst(AllocRefDynamicInst *ARDI) {
SILValue Metadata = ARDI->getMetatypeOperand();
require(Metadata->getType().is<AnyMetatypeType>(),
"operand of alloc_ref_dynamic must be of metatype type");
auto metaTy = Metadata->getType().castTo<AnyMetatypeType>();
require(metaTy->hasRepresentation(),
"operand of alloc_ref_dynamic must have a metatype representation");
if (ARDI->isObjC()) {
require(metaTy->getRepresentation() == MetatypeRepresentation::ObjC,
"alloc_ref_dynamic @objc requires operand of ObjC metatype");
} else {
require(metaTy->getRepresentation() == MetatypeRepresentation::Thick,
"alloc_ref_dynamic requires operand of thick metatype");
}
checkAllocRefBase(ARDI);
}
/// Check the substitutions passed to an apply or partial_apply.
CanSILFunctionType checkApplySubstitutions(SubstitutionMap subs,
SILType calleeTy) {
auto fnTy = requireObjectType(SILFunctionType, calleeTy, "callee operand");
// If there are substitutions, verify them and apply them to the callee.
if (!subs.hasAnySubstitutableParams()) {
require(!fnTy->isPolymorphic(),
"callee of apply without substitutions must not be polymorphic");
return fnTy;
}
require(fnTy->isPolymorphic(),
"callee of apply with substitutions must be polymorphic");
// Each archetype occurring in the substitutions list should belong to the
// current function.
for (auto replacementType : subs.getReplacementTypes()) {
replacementType->getCanonicalType().visit([&](CanType t) {
auto A = dyn_cast<ArchetypeType>(t);
if (!A)
return;
require(isArchetypeValidInFunction(A, &F),
"Replacement type of a substitution contains an ArchetypeType "
"that does not exist in the Caller's generic param list.");
});
}
if (subs.getGenericSignature().getCanonicalSignature() !=
fnTy->getInvocationGenericSignature().getCanonicalSignature()) {
llvm::dbgs() << "substitution map's generic signature: ";
subs.getGenericSignature()->print(llvm::dbgs());
llvm::dbgs() << "\n";
llvm::dbgs() << "callee's generic signature: ";
fnTy->getInvocationGenericSignature()->print(llvm::dbgs());
llvm::dbgs() << "\n";
require(false,
"Substitution map does not match callee in apply instruction");
}
// Apply the substitutions.
return fnTy->substGenericArgs(F.getModule(), subs, F.getTypeExpansionContext());
}
/// Check that for each local archetype or dynamic self type in substitutions
/// or the called type, there is a type dependent operand.
void checkApplyTypeDependentArguments(ApplySite AS) {
SILInstruction *AI = AS.getInstruction();
llvm::DenseSet<SILInstruction *> allOpeningInsts;
unsigned hasDynamicSelf = 0;
// Function to collect local archetypes in allOpeningInsts and set
// hasDynamicSelf.
auto handleType = [&](CanType Ty) {
if (const auto A = dyn_cast<LocalArchetypeType>(Ty)) {
require(isArchetypeValidInFunction(A, AI->getFunction()),
"Archetype to be substituted must be valid in function.");
const auto root = A.getRoot();
// Check that opened archetypes are properly tracked inside
// the current function.
auto *openingInst = F.getModule().getRootLocalArchetypeDefInst(
root, AI->getFunction());
require(openingInst,
"Root opened archetype should be registered in SILModule");
require(openingInst == AI || properlyDominates(openingInst, AI),
"Use of a local archetype should be dominated by a "
"definition of this root opened archetype");
// Remember all the opening instructions. We unique by instruction
// identity when building the list of type dependency operands, and
// some instructions can open multiple archetypes.
allOpeningInsts.insert(openingInst);
}
if (Ty->hasDynamicSelfType()) {
hasDynamicSelf = 1;
}
};
// Search for local archetypes and dynamic self.
for (auto Replacement : AS.getSubstitutionMap().getReplacementTypes()) {
Replacement->getCanonicalType().visit(handleType);
}
AS.getSubstCalleeType().visit(handleType);
require(allOpeningInsts.size() + hasDynamicSelf ==
AI->getTypeDependentOperands().size(),
"Number of local archetypes and dynamic self in the substitutions "
"list should match the number of type dependent operands");
for (auto &Op : AI->getTypeDependentOperands()) {
auto V = Op.get();
if (isa<SILArgument>(V)) {
require(hasDynamicSelf,
"dynamic self operand without dynamic self type");
require(AI->getFunction()->hasDynamicSelfMetadata(),
"self metadata operand in function without self metadata param");
require((ValueBase *)V == AI->getFunction()->getDynamicSelfMetadata(),
"wrong self metadata operand");
} else {
auto DI = V->getDefiningInstruction();
require(DI,
"local archetype operand should refer to a SIL instruction");
require(allOpeningInsts.count(DI),
"local archetype operand does not correspond to any local "
"archetype from the substitutions list");
bool matchedDependencyResult = false;
DI->forEachDefinedLocalArchetype(
[&](CanLocalArchetypeType archetype, SILValue dependency) {
if (dependency == V)
matchedDependencyResult = true;
});
require(matchedDependencyResult,
"local archetype operand was not the dependency result "
"of the opening instruction");
}
}
}
void checkFullApplySite(FullApplySite site) {
checkApplyTypeDependentArguments(site);
// Then make sure that we have a type that can be substituted for the
// callee.
auto substTy = checkApplySubstitutions(site.getSubstitutionMap(),
site.getCallee()->getType());
require(site.getOrigCalleeType()->getRepresentation() ==
site.getSubstCalleeType()->getRepresentation(),
"calling convention difference between types");
require(!site.getSubstCalleeType()->isPolymorphic(),
"substituted callee type should not be generic");
requireSameType(SILType::getPrimitiveObjectType(substTy),
SILType::getPrimitiveObjectType(site.getSubstCalleeType()),
"substituted callee type does not match substitutions");
// Check that the arguments and result match.
SILFunctionConventions substConv(substTy, F.getModule());
require(site.getNumArguments() == substConv.getNumSILArguments(),
"apply doesn't have right number of arguments for function");
for (size_t i = 0, size = site.getNumArguments(); i < size; ++i) {
requireSameType(
site.getArguments()[i]->getType(),
substConv.getSILArgumentType(i, F.getTypeExpansionContext()),
"operand of 'apply' doesn't match function input type");
}
// If we have any actor isolation, then our callee and caller must be
// asynchronous.
if (auto isolationCrossing = site.getIsolationCrossing()) {
require(bool(isolationCrossing->getCallerIsolation()) ||
bool(isolationCrossing->getCalleeIsolation()),
"Should only have a non-std::nullopt isolation crossing if one "
"of callee/caller isolation is not Unspecified");
require(site->getFunction()->isAsync(),
"Caller must be asynchronous if we have an isolation corssing");
require(substTy->isAsync(),
"Callee must be asynchronous if we have an isolation crossing");
// If we have an AST node make sure that its isolation matches the
// isolation crossing on the apply site.
if (auto *fn = site.getCalleeFunction()) {
if (auto *fnDecl =
fn->getLocation().getAsASTNode<AbstractFunctionDecl>()) {
require(
getActorIsolation(fnDecl) ==
isolationCrossing->getCalleeIsolation(),
"Callee's isolation must match isolation of isolation crossing");
}
}
}
// Make sure that our subst and orig callee type agree on having sending
// results or not.
require(site.getOrigCalleeType()->hasSendingResult() ==
site.getSubstCalleeType()->hasSendingResult(),
"Callee's orig and subst callee type must have the same sending "
"result");
}
void checkApplyInst(ApplyInst *AI) {
checkFullApplySite(AI);
SILFunctionConventions calleeConv(AI->getSubstCalleeType(), F.getModule());
requireSameType(
AI->getType(), calleeConv.getSILResultType(F.getTypeExpansionContext()),
"type of apply instruction doesn't match function result type");
if (AI->isNonThrowing()) {
require(calleeConv.funcTy->hasErrorResult(),
"nothrow flag used for callee without error result");
} else {
require(!calleeConv.funcTy->hasErrorResult(),
"apply instruction cannot call function with error result");
}
if (AI->isNonAsync()) {
require(calleeConv.funcTy->isAsync(),
"noasync flag used for sync callee");
} else {
require(!calleeConv.funcTy->isAsync() || AI->getFunction()->isAsync(),
"cannot call an async function from a non async function");
}
require(!calleeConv.funcTy->isCoroutine(),
"cannot call coroutine with normal apply");
}
void checkTryApplyInst(TryApplyInst *AI) {
checkFullApplySite(AI);
SILFunctionConventions calleeConv(AI->getSubstCalleeType(), F.getModule());
require(!calleeConv.funcTy->isCoroutine(),
"cannot call coroutine with normal apply");
if (AI->isNonAsync()) {
require(calleeConv.funcTy->isAsync(),
"noasync flag used for sync callee");
} else {
require(!calleeConv.funcTy->isAsync() || AI->getFunction()->isAsync(),
"cannot call an async function from a non async function");
}
auto normalBB = AI->getNormalBB();
require(normalBB->args_size() == 1,
"normal destination of try_apply must take one argument");
requireSameType((*normalBB->args_begin())->getType(),
calleeConv.getSILResultType(F.getTypeExpansionContext()),
"normal destination of try_apply must take argument "
"of normal result type");
auto errorBB = AI->getErrorBB();
require(calleeConv.funcTy->hasErrorResult(),
"try_apply must call function with error result");
if (calleeConv.getNumIndirectSILErrorResults()) {
require(errorBB->args_size() == 0,
"error destination of try_apply must take no argument");
} else {
require(errorBB->args_size() == 1,
"error destination of try_apply must take one argument");
requireSameType((*errorBB->args_begin())->getType(),
calleeConv.getSILErrorType(F.getTypeExpansionContext()),
"error destination of try_apply must take argument "
"of error result type");
}
}
void checkBeginApplyInst(BeginApplyInst *AI) {
checkFullApplySite(AI);
SILFunctionConventions calleeConv(AI->getSubstCalleeType(), F.getModule());
auto yieldResults = AI->getYieldedValues();
auto yields = calleeConv.getYields();
require(yields.size() == yieldResults.size(),
"length mismatch in callee yields vs. begin_apply results");
for (auto i : indices(yields)) {
requireSameType(
yieldResults[i]->getType(),
calleeConv.getSILType(yields[i], F.getTypeExpansionContext()),
"callee yield type does not match begin_apply result type");
}
if (AI->isNonThrowing()) {
require(calleeConv.funcTy->hasErrorResult(),
"nothrow flag used for callee without error result");
} else {
require(!calleeConv.funcTy->hasErrorResult(),
"begin_apply instruction cannot call function with error result");
}
require(calleeConv.funcTy->getCoroutineKind() == SILCoroutineKind::YieldOnce,
"must call yield_once coroutine with begin_apply");
require(!calleeConv.funcTy->isAsync() || AI->getFunction()->isAsync(),
"cannot call an async function from a non async function");
}
void checkAbortApplyInst(AbortApplyInst *AI) {
require(getAsResultOf<BeginApplyInst>(AI->getOperand())->isBeginApplyToken(),
"operand of abort_apply must be a begin_apply");
}
void checkEndApplyInst(EndApplyInst *AI) {
require(getAsResultOf<BeginApplyInst>(AI->getOperand())->isBeginApplyToken(),
"operand of end_apply must be a begin_apply");
}
void verifyLLVMIntrinsic(BuiltinInst *BI, llvm::Intrinsic::ID ID) {
// Certain llvm intrinsic require constant values as their operands.
// Consequently, these must not be phi nodes (aka. basic block arguments).
switch (ID) {
default:
break;
case llvm::Intrinsic::ctlz: // llvm.ctlz
case llvm::Intrinsic::cttz: // llvm.cttz
break;
case llvm::Intrinsic::memcpy:
case llvm::Intrinsic::memmove:
case llvm::Intrinsic::memset:
require(!isa<SILArgument>(BI->getArguments()[3]),
"isvolatile argument of memory intrinsics must be an integer "
"literal");
break;
case llvm::Intrinsic::lifetime_start:
case llvm::Intrinsic::lifetime_end:
case llvm::Intrinsic::invariant_start:
require(!isa<SILArgument>(BI->getArguments()[0]),
"size argument of memory use markers must be an integer literal");
break;
case llvm::Intrinsic::invariant_end:
require(!isa<SILArgument>(BI->getArguments()[1]),
"llvm.invariant.end parameter #2 must be an integer literal");
break;
}
}
void checkMarkDependencInst(MarkDependenceInst *MDI) {
if (MDI->isNonEscaping()) {
require(F.hasOwnership(), "mark_dependence [nonescaping] requires OSSA");
require(MDI->getOwnershipKind() == OwnershipKind::Owned,
"mark_dependence [nonescaping] must be an owned value");
}
}
void checkPartialApplyInst(PartialApplyInst *PAI) {
auto resultInfo = requireObjectType(SILFunctionType, PAI,
"result of partial_apply");
verifySILFunctionType(resultInfo);
require(resultInfo->getExtInfo().hasContext(),
"result of closure cannot have a thin function type");
// We rely on all indirect captures to be in the argument list.
require(PAI->getCallee()->getType().isObject(),
"Closure callee must not be an address type.");
checkApplyTypeDependentArguments(PAI);
auto substTy = checkApplySubstitutions(PAI->getSubstitutionMap(),
PAI->getCallee()->getType());
require(!PAI->getSubstCalleeType()->isPolymorphic(),
"substituted callee type should not be generic");
requireSameType(SILType::getPrimitiveObjectType(substTy),
SILType::getPrimitiveObjectType(PAI->getSubstCalleeType()),
"substituted callee type does not match substitutions");
// The arguments must match the suffix of the original function's input
// types.
require(PAI->getArguments().size() +
resultInfo->getParameters().size()
== substTy->getParameters().size(),
"result of partial_apply should take as many inputs as were not "
"applied by the instruction");
SILFunctionConventions substConv(substTy, F.getModule());
unsigned appliedArgStartIdx =
substConv.getNumSILArguments() - PAI->getNumArguments();
for (auto p : llvm::enumerate(PAI->getArguments())) {
unsigned argIdx = appliedArgStartIdx + p.index();
requireSameType(
p.value()->getType(),
substConv.getSILArgumentType(argIdx, F.getTypeExpansionContext()),
"applied argument types do not match suffix of function type's "
"inputs");
if (PAI->isOnStack()) {
require(!substConv.getSILArgumentConvention(argIdx).isOwnedConvention(),
"on-stack closures do not support owned arguments");
}
}
// The arguments to the result function type must match the prefix of the
// original function's input types.
for (unsigned i = 0, size = resultInfo->getParameters().size();
i < size; ++i) {
require(resultInfo->getParameters()[i] ==
substTy->getParameters()[i],
"inputs to result function type do not match unapplied inputs "
"of original function");
}
require(resultInfo->getNumResults() == substTy->getNumResults(),
"applied results do not agree in count with function type");
for (unsigned i = 0, size = resultInfo->getNumResults(); i < size; ++i) {
auto originalResult = resultInfo->getResults()[i];
auto expectedResult = substTy->getResults()[i];
// The "returns inner pointer" convention doesn't survive through a
// partial application, since the thunk takes responsibility for
// lifetime-extending 'self'.
if (expectedResult.getConvention()
== ResultConvention::UnownedInnerPointer) {
expectedResult = SILResultInfo(
expectedResult.getReturnValueType(F.getModule(), substTy,
F.getTypeExpansionContext()),
ResultConvention::Unowned);
require(originalResult == expectedResult,
"result type of result function type for partially applied "
"@unowned_inner_pointer function should have @unowned"
"convention");
// The "autoreleased" convention doesn't survive through a
// partial application, since the thunk takes responsibility for
// retaining the return value.
} else if (expectedResult.getConvention()
== ResultConvention::Autoreleased) {
expectedResult = SILResultInfo(
expectedResult.getReturnValueType(F.getModule(), substTy,
F.getTypeExpansionContext()),
ResultConvention::Owned);
require(originalResult == expectedResult,
"result type of result function type for partially applied "
"@autoreleased function should have @owned convention");
} else {
require(originalResult == expectedResult,
"result type of result function type does not match original "
"function");
}
}
if (resultInfo->hasErasedIsolation()) {
require(!PAI->getArguments().empty(),
"erasure to @isolated(any) requires an actor argument");
auto isolationTy =
substConv.getSILArgumentType(appliedArgStartIdx,
F.getTypeExpansionContext());
requireSameType(isolationTy,
SILType::getOpaqueIsolationType(F.getASTContext()),
"first applied argument must be the isolation value");
}
// TODO: Impose additional constraints when partial_apply when the
// -disable-sil-partial-apply flag is enabled. We want to reduce
// partial_apply to being only a means of associating a closure invocation
// function with its context.
//
// When we reach that point, we should be able to more deeply redesign
// PartialApplyInst to simplify the representation to carry a single
// argument.
if (PAI->getModule().getOptions().DisableSILPartialApply) {
// Should only be one context argument.
require(PAI->getArguments().size() == 1,
"partial_apply should have a single context argument");
// Callee should already have the thin convention, and result should be
// thick.
require(resultInfo->getRepresentation() ==
SILFunctionTypeRepresentation::Thick,
"partial_apply result should have thick convention");
require(PAI->getCallee()->getType().castTo<SILFunctionType>()
->getRepresentation() ==
SILFunctionTypeRepresentation::Thin,
"partial_apply callee should have thin convention");
// TODO: Check that generic signature matches box's generic signature,
// once we have boxes with generic signatures.
require(!PAI->getCalleeFunction()->getGenericEnvironment(),
"partial_apply context must capture generic environment for "
"callee");
// Result's callee convention should match context argument's convention.
require(substTy->getParameters().back().getConvention()
== resultInfo->getCalleeConvention(),
"partial_apply context argument must have the same convention "
"as the resulting function's callee convention");
auto isSwiftRefcounted = [](SILType t) -> bool {
if (t.is<SILBoxType>())
return true;
if (t.getASTType() == t.getASTContext().TheNativeObjectType)
return true;
if (auto clazz = t.getClassOrBoundGenericClass())
// Must be a class defined in Swift.
return clazz->hasKnownSwiftImplementation();
return false;
};
// The context argument must be a swift-refcounted box or class.
require(isSwiftRefcounted(PAI->getArguments().front()->getType()),
"partial_apply context argument must be swift-refcounted");
}
}
void checkFunctionExtractIsolationInst(FunctionExtractIsolationInst *FEI) {
auto fnType = requireObjectType(SILFunctionType, FEI->getFunction(),
"function_extract_isolation operand");
require(fnType->hasErasedIsolation(),
"function_extract_isolation operand must have erased isolation");
}
void checkBuiltinInst(BuiltinInst *BI) {
// Check for special constraints on llvm intrinsics.
if (BI->getIntrinsicInfo().ID != llvm::Intrinsic::not_intrinsic) {
verifyLLVMIntrinsic(BI, BI->getIntrinsicInfo().ID);
return;
}
auto builtinKind = BI->getBuiltinKind();
auto arguments = BI->getArguments();
// Check that 'getCurrentAsyncTask' only occurs within an async function.
if (builtinKind == BuiltinValueKind::GetCurrentAsyncTask) {
require(F.isAsync(),
"getCurrentAsyncTask builtin can only be used in an async function");
return;
}
if (builtinKind == BuiltinValueKind::InitializeDefaultActor ||
builtinKind == BuiltinValueKind::DestroyDefaultActor) {
require(arguments.size() == 1,
"default-actor builtin can only operate on a single object");
auto argType = arguments[0]->getType().getASTType();
auto argClass = argType.getClassOrBoundGenericClass();
require((argClass && argClass->isRootDefaultActor(M,
F.getResilienceExpansion())) ||
isa<BuiltinNativeObjectType>(argType),
"default-actor builtin can only operate on default actors");
return;
}
// Check that 'getCurrentAsyncTask' only occurs within an async function.
if (builtinKind == BuiltinValueKind::GetCurrentExecutor) {
require(F.isAsync(),
"getCurrentExecutor can only be used in an async function");
require(arguments.empty(), "getCurrentExecutor takes no arguments");
requireOptionalExecutorType(BI, "result of getCurrentExecutor");
return;
}
if (builtinKind == BuiltinValueKind::BuildOrdinaryTaskExecutorRef ||
builtinKind == BuiltinValueKind::BuildOrdinarySerialExecutorRef ||
builtinKind ==
BuiltinValueKind::BuildComplexEqualitySerialExecutorRef ||
builtinKind == BuiltinValueKind::BuildDefaultActorExecutorRef) {
require(arguments.size() == 1,
"builtin expects one argument");
require(arguments[0]->getType().isObject(),
"operand of builtin should have object type");
requireObjectType(BuiltinExecutorType, BI,
"result of build*ExecutorRef");
return;
}
if (builtinKind == BuiltinValueKind::BuildMainActorExecutorRef) {
require(arguments.size() == 0,
"buildMainActorExecutorRef expects no arguments");
requireObjectType(BuiltinExecutorType, BI,
"result of build*ExecutorRef");
return;
}
if (builtinKind == BuiltinValueKind::Copy) {
// We expect that this builtin will be specialized during transparent
// inlining into explicit_copy_value if we inline into a non-generic
// context. If the builtin still remains and is not in the specific copy
// semantic function (which is the only function marked with
// semantics::LIFETIMEMANAGEMENT_COPY), then we know that we did
// transparent inlining into a function that did not result in the Builtin
// being specialized out which is user error.
//
// NOTE: Once we have opaque values, this restriction will go away. This
// is just so we can call Builtin.copy outside of the stdlib.
auto semanticName = semantics::LIFETIMEMANAGEMENT_COPY;
require(BI->getFunction()->hasSemanticsAttr(semanticName),
"_copy used within a generic context");
}
if (builtinKind == BuiltinValueKind::CreateAsyncTask) {
requireType(BI->getType(), _object(_tuple(_nativeObject, _rawPointer)),
"result of createAsyncTask");
require(arguments.size() == 6,
"createAsyncTask expects six arguments");
requireType(arguments[0]->getType(), _object(_swiftInt),
"first argument of createAsyncTask");
requireType(arguments[1]->getType(), _object(_optional(_executor)),
"second argument of createAsyncTask");
requireType(arguments[2]->getType(), _object(_optional(_rawPointer)),
"third argument of createAsyncTask");
requireType(arguments[3]->getType(), _object(_optional(_executor)),
"fourth argument of createAsyncTask");
if (F.getASTContext().getProtocol(swift::KnownProtocolKind::TaskExecutor)) {
requireType(arguments[4]->getType(),
_object(_optional(_existential(_taskExecutor))),
"fifth argument of createAsyncTask");
} else {
// This is just a placeholder type for being able to pass 'nil' for it
// with SDKs which do not have the TaskExecutor type.
requireType(arguments[4]->getType(),
_object(_optional(_executor)),
"fifth argument of createAsyncTask");
}
auto fnType = requireObjectType(SILFunctionType, arguments[5],
"result of createAsyncTask");
bool haveSending =
F.getASTContext().LangOpts.hasFeature(Feature::SendingArgsAndResults);
auto expectedExtInfo = SILExtInfoBuilder()
.withAsync(true)
.withSendable(!haveSending)
.build();
require(fnType->getExtInfo().isEqualTo(expectedExtInfo, /*clang types*/true),
"function argument to createAsyncTask has incorrect ext info");
// FIXME: it'd be better if we took a consuming closure here
require(fnType->getCalleeConvention() ==
ParameterConvention::Direct_Guaranteed,
"function argument to createAsyncTask has wrong callee convention");
require(fnType->getNumParameters() == 0,
"function argument to createAsyncTask cannot take an argument");
require(fnType->getNumYields() == 0,
"function argument to createAsyncTask cannot have yields");
// The absence of substitutions means this is a discarding task.
if (auto subs = BI->getSubstitutions()) {
require(fnType->getNumResults() == 1 &&
fnType->getSingleResult().getConvention() ==
ResultConvention::Indirect,
"function argument to non-discarding createAsyncTask has wrong "
"result convention");
// TODO: type check
} else {
require(fnType->getNumResults() == 0,
"function argument to discarding createAsyncTask has results");
}
// TODO: should we have different SIL-level builtins for discarding
// and non-discarding tasks so that we can't get this wrong?
// If we generalize this to allow an arbitrary error type,
// handle that here.
require(fnType->hasErrorResult() &&
fnType->getErrorResult().getConvention()
== ResultConvention::Owned &&
fnType->getErrorResult().getInterfaceType()
== F.getASTContext().getErrorExistentialType(),
"function argument to createAsyncTask has wrong error convention");
}
if (builtinKind == BuiltinValueKind::ExtractFunctionIsolation) {
require(false, "this builtin is pre-SIL-only");
}
}
void checkFunctionRefBaseInst(FunctionRefBaseInst *FRI) {
auto fnType = requireObjectType(SILFunctionType, FRI,
"result of function_ref");
require(!fnType->getExtInfo().hasContext(),
"function_ref should have a context-free function result");
// Note: in SingleFunction mode, we relax some of these checks because
// we may not have linked everything yet.
SILFunction *RefF = FRI->getInitiallyReferencedFunction();
if (isa<FunctionRefInst>(FRI))
require(
!RefF->isDynamicallyReplaceable(),
"function_ref cannot reference a [dynamically_replaceable] function");
else if (isa<PreviousDynamicFunctionRefInst>(FRI)) {
require(!RefF->isDynamicallyReplaceable(),
"previous_function_ref cannot reference a "
"[dynamically_replaceable] function");
require(RefF->getDynamicallyReplacedFunction(),
"previous_function_ref must reference a "
"[dynamic_replacement_for:...] function");
} else if (isa<DynamicFunctionRefInst>(FRI))
require(RefF->isDynamicallyReplaceable(),
"dynamic_function_ref must reference a "
"[dynamically_replaceable] function");
// In canonical SIL, direct reference to a shared_external declaration
// is an error; we should have deserialized a body. In raw SIL, including
// the merge-modules phase, we may not have deserialized the body yet as we
// may not have run the SILLinker pass.
if (F.getModule().getStage() >= SILStage::Canonical) {
if (RefF->isExternalDeclaration()) {
require(SingleFunction ||
!hasSharedVisibility(RefF->getLinkage()) ||
RefF->hasForeignBody(),
"external declarations of SILFunctions with shared visibility is "
"not allowed");
}
}
// A direct reference to a non-public or shared but not fragile function
// from a fragile function is an error.
if (F.isAnySerialized()) {
require((SingleFunction && RefF->isExternalDeclaration()) ||
RefF->hasValidLinkageForFragileRef(F.getSerializedKind()),
"function_ref inside fragile function cannot "
"reference a private or hidden symbol");
}
verifySILFunctionType(fnType);
}
void checkFunctionRefInst(FunctionRefInst *FRI) {
checkFunctionRefBaseInst(FRI);
}
void checkDynamicFunctionRefInst(DynamicFunctionRefInst *FRI) {
checkFunctionRefBaseInst(FRI);
}
void checkPreviousDynamicFunctionRefInst(PreviousDynamicFunctionRefInst *FRI) {
checkFunctionRefBaseInst(FRI);
}
void checkAllocGlobalInst(AllocGlobalInst *AGI) {
SILGlobalVariable *RefG = AGI->getReferencedGlobal();
if (auto *VD = RefG->getDecl()) {
require(!checkResilience(VD, F),
"cannot access storage of resilient global");
}
if (F.isSerialized()) {
// If it has a package linkage at this point, package CMO must
// have been enabled, so opt in for visibility.
require(RefG->isSerialized()
|| hasPublicOrPackageVisibility(RefG->getLinkage(), /*includePackage*/ true),
"alloc_global inside fragile function cannot "
"reference a private or hidden symbol");
}
}
void checkGlobalAccessInst(GlobalAccessInst *GAI) {
SILGlobalVariable *RefG = GAI->getReferencedGlobal();
requireSameType(
GAI->getType().getObjectType(),
RefG->getLoweredTypeInContext(F.getTypeExpansionContext()),
"global_addr/value must be the type of the variable it references");
if (auto *VD = RefG->getDecl()) {
require(!checkResilience(VD, F),
"cannot access storage of resilient global");
}
// pcmo TODO: replace this with F.canInlineCalleeBody(RefG)
if (F.isSerialized()) {
// If it has a package linkage at this point, package CMO must
// have been enabled, so opt in for visibility.
require(RefG->isSerialized()
|| hasPublicOrPackageVisibility(RefG->getLinkage(), /*includePackage*/ true),
"global_addr/value inside fragile function cannot "
"reference a private or hidden symbol");
}
}
void checkGlobalAddrInst(GlobalAddrInst *GAI) {
require(GAI->getType().isAddress(),
"global_addr must have an address result type");
require(!GAI->getReferencedGlobal()->isInitializedObject(),
"global_addr cannot refer to a statically initialized object");
checkGlobalAccessInst(GAI);
checkAddressWalkerCanVisitAllTransitiveUses(GAI);
if (SILValue token = GAI->getDependencyToken()) {
require(token->getType().is<SILTokenType>(),
"depends_on operand of global_addr must be a token");
}
}
void checkGlobalValueInst(GlobalValueInst *GVI) {
require(GVI->getType().isObject(),
"global_value must have an address result type");
checkGlobalAccessInst(GVI);
}
void checkObjectInst(ObjectInst *) {
require(false, "object instruction is only allowed in a static initializer");
}
void checkVectorInst(VectorInst *) {
require(false, "vector instruction is only allowed in a static initializer");
}
void checkIntegerLiteralInst(IntegerLiteralInst *ILI) {
require(ILI->getType().is<AnyBuiltinIntegerType>(),
"invalid integer literal type");
}
void checkLoadInst(LoadInst *LI) {
require(LI->getType().isObject(), "Result of load must be an object");
require(!fnConv.useLoweredAddresses()
|| LI->getType().isLoadable(*LI->getFunction()),
"Load must have a loadable type");
require(LI->getOperand()->getType().isAddress(),
"Load operand must be an address");
requireSameType(LI->getOperand()->getType().getObjectType(), LI->getType(),
"Load operand type and result type mismatch");
// Ownership semantic checks.
switch (LI->getOwnershipQualifier()) {
case LoadOwnershipQualifier::Unqualified:
// We should not see loads with unqualified ownership when SILOwnership is
// enabled.
require(!F.hasOwnership(),
"Load with unqualified ownership in a qualified function");
break;
case LoadOwnershipQualifier::Copy:
require(LI->getModule().getStage() == SILStage::Raw ||
!LI->getOperand()->getType().isMoveOnly(),
"'MoveOnly' types can only be copied in Raw SIL?!");
[[fallthrough]];
case LoadOwnershipQualifier::Take:
require(F.hasOwnership(),
"Load with qualified ownership in an unqualified function");
// TODO: Could probably make this a bit stricter.
require(!LI->getType().isTrivial(*LI->getFunction()),
"load [copy] or load [take] can only be applied to non-trivial "
"types");
break;
case LoadOwnershipQualifier::Trivial:
require(F.hasOwnership(),
"Load with qualified ownership in an unqualified function");
require(LI->getType().isTrivial(*LI->getFunction()),
"A load with trivial ownership must load a trivial type");
break;
}
}
void checkLoadBorrowInst(LoadBorrowInst *LBI) {
require(
F.hasOwnership(),
"Inst with qualified ownership in a function that is not qualified");
require(LBI->getType().isObject(), "Result of load must be an object");
require(!fnConv.useLoweredAddresses()
|| LBI->getType().isLoadable(*LBI->getFunction()),
"Load must have a loadable type");
require(LBI->getOperand()->getType().isAddress(),
"Load operand must be an address");
requireSameType(LBI->getOperand()->getType().getObjectType(),
LBI->getType(),
"Load operand type and result type mismatch");
if (LBI->isUnchecked()) {
require(LBI->getModule().getStage() == SILStage::Raw,
"load_borrow can only be [unchecked] in raw SIL");
} else {
require(loadBorrowImmutabilityAnalysis.isImmutable(LBI),
"Found load borrow that is invalidated by a local write?!");
}
}
void checkBeginBorrowInst(BeginBorrowInst *bbi) {
if (!bbi->isLexical())
return;
// Lexical begin_borrows of instances of some SILBoxType must derive from
// alloc_boxes or captures.
auto value = bbi->getOperand();
if (!value->getType().is<SILBoxType>())
return;
while (true) {
// Inlining may introduce additional begin_borrow instructions.
if (auto bbi = dyn_cast<BeginBorrowInst>(value))
value = bbi->getOperand();
// SILGen introduces copy_value instructions.
else if (auto cvi = dyn_cast<CopyValueInst>(value))
value = cvi->getOperand();
// SILGen inserts mark_uninitialized instructions of alloc_boxes.
else if (auto *mui = dyn_cast<MarkUninitializedInst>(value))
value = mui->getOperand();
else
break;
}
auto isLegal = [](SILValue value) {
if (auto *a = dyn_cast<MarkUnresolvedReferenceBindingInst>(value))
value = a->getOperand();
return isa<AllocBoxInst>(value) || isa<SILFunctionArgument>(value);
};
require(isLegal(value),
"Lexical borrows of SILBoxTypes must be of vars or captures.");
}
void checkEndBorrowInst(EndBorrowInst *EBI) {
require(
F.hasOwnership(),
"Inst with qualified ownership in a function that is not qualified");
if (EBI->getOperand()->getType().isAddress()) {
require(isa<StoreBorrowInst>(EBI->getOperand()),
"end_borrow of an address not produced by store_borrow");
}
}
void checkEndLifetimeInst(EndLifetimeInst *I) {
require(!I->getOperand()->getType().isTrivial(*I->getFunction()),
"Source value should be non-trivial");
require(!fnConv.useLoweredAddresses() || F.hasOwnership(),
"end_lifetime is only valid in functions with qualified "
"ownership");
}
void checkUncheckedValueCastInst(UncheckedValueCastInst *) {
require(
F.hasOwnership(),
"Inst with qualified ownership in a function that is not qualified");
}
void checkUncheckedOwnershipConversionInst(
UncheckedOwnershipConversionInst *uoci) {
require(
F.hasOwnership(),
"Inst with qualified ownership in a function that is not qualified");
require(!uoci->getType().isAddress(),
"cannot convert ownership of an address");
require(uoci->getType() == uoci->getOperand()->getType(),
"converting ownership does not affect the type");
}
template <class AI>
void checkAccessEnforcement(AI *AccessInst) {
if (AccessInst->getModule().getStage() != SILStage::Raw) {
require(AccessInst->getEnforcement() != SILAccessEnforcement::Unknown,
"access must have known enforcement outside raw stage");
}
}
bool checkScopedAddressUses(ScopedAddressValue scopedAddress,
SSAPrunedLiveness *scopedAddressLiveness,
DeadEndBlocks *deadEndBlocks) {
SmallVector<Operand *, 4> uses;
findTransitiveUsesForAddress(scopedAddress.value, &uses);
// Check if the collected uses are well-scoped.
for (auto *use : uses) {
auto *user = use->getUser();
if (deadEndBlocks && deadEndBlocks->isDeadEnd(user->getParent())) {
continue;
}
if (scopedAddress.isScopeEndingUse(use)) {
continue;
}
if (!scopedAddressLiveness->isWithinBoundary(user)) {
llvm::errs() << "User found outside scope: " << *user;
return false;
}
}
return true;
}
void checkBeginAccessInst(BeginAccessInst *BAI) {
requireSameType(BAI->getType(), BAI->getSource()->getType(),
"result must be same type as operand");
require(BAI->getType().isAddress(),
"begin_access operand must have address type");
checkAccessEnforcement(BAI);
switch (BAI->getAccessKind()) {
case SILAccessKind::Init:
// A signed access preserves the access marker until IRGen
require(BAI->getEnforcement() == SILAccessEnforcement::Static ||
BAI->getEnforcement() == SILAccessEnforcement::Signed,
"init accesses cannot use non-static/non-signed enforcement");
break;
case SILAccessKind::Deinit:
// A signed access preserves the access marker until IRGen.
//
// NOTE: We allow for deinit to be non-static before Lowered SIL to allow
// for it to be used to represent deinit accesses for move only types
// stored in classes, globals, and escaping mutable captures. This is ok
// to do since even though we allow for them to be represented there, the
// move only checker passes will always emit an error for them implying
// that we will never get to LoweredSIL and codegen.
require(BAI->getEnforcement() == SILAccessEnforcement::Static ||
BAI->getEnforcement() == SILAccessEnforcement::Signed ||
BAI->getModule().getStage() != SILStage::Lowered,
"init accesses cannot use non-static/non-signed enforcement");
break;
case SILAccessKind::Read:
case SILAccessKind::Modify:
break;
}
// Verify that all formal accesses patterns are recognized as part of a
// allowlist. The presence of an unknown pattern means that analysis will
// silently fail, and the compiler may be introducing undefined behavior
// with no other way to detect it.
//
// For example, AccessEnforcementWMO runs very late in the
// pipeline and assumes valid storage for all dynamic Read/Modify access. It
// also requires that Unidentified access fit a allowlist on known
// non-internal globals or class properties.
//
// First check that identifyFormalAccess returns without asserting. For
// Unsafe enforcement, that is sufficient. For any other enforcement
// level also require that it returns a valid AccessStorage object.
// Unsafe enforcement is used for some unrecognizable access patterns,
// like debugger variables. The compiler never cares about the source of
// those accesses.
identifyFormalAccess(BAI);
// FIXME: rdar://57291811 - the following check for valid storage will be
// reenabled shortly. A fix is planned. In the meantime, the possibility that
// a real miscompilation could be caused by this failure is insignificant.
// I will probably enable a much broader SILVerification of address-type
// block arguments first to ensure we never hit this check again.
/*
AccessStorage storage = identifyFormalAccess(BAI);
if (BAI->getEnforcement() != SILAccessEnforcement::Unsafe)
require(storage, "Unknown formal access pattern");
*/
}
void checkEndAccessInst(EndAccessInst *EAI) {
auto BAI = dyn_cast<BeginAccessInst>(EAI->getOperand());
require(BAI != nullptr,
"operand of end_access must be a begin_access");
if (EAI->isAborting()) {
require(BAI->getAccessKind() == SILAccessKind::Init ||
BAI->getAccessKind() == SILAccessKind::Deinit,
"aborting access must apply to init or deinit");
}
}
void checkBeginUnpairedAccessInst(BeginUnpairedAccessInst *BUAI) {
require(BUAI->getEnforcement() != SILAccessEnforcement::Unknown,
"unpaired access can never use unknown enforcement");
require(BUAI->getSource()->getType().isAddress(),
"address operand must have address type");
requireAddressType(BuiltinUnsafeValueBufferType, BUAI->getBuffer(),
"scratch buffer operand");
checkAccessEnforcement(BUAI);
switch (BUAI->getAccessKind()) {
case SILAccessKind::Init:
require(BUAI->getEnforcement() == SILAccessEnforcement::Static,
"init accesses cannot use non-static enforcement");
break;
case SILAccessKind::Deinit:
// NOTE: We allow for deinit to be non-static before Lowered SIL to allow
// for it to be used to represent deinit accesses for move only types
// stored in classes, globals, and escaping mutable captures. This is ok
// to do since even though we allow for them to be represented there, the
// move only checker passes will always emit an error for them implying
// that we will never get to LoweredSIL and codegen.
require(
BUAI->getEnforcement() == SILAccessEnforcement::Static ||
BUAI->getModule().getStage() != SILStage::Lowered,
"deinit accesses cannot use non-static enforcement in Lowered SIL");
break;
case SILAccessKind::Read:
case SILAccessKind::Modify:
break;
}
// First check that identifyFormalAccess never asserts.
AccessStorage storage = identifyFormalAccess(BUAI);
// Only allow Unsafe and Builtin access to have invalid storage.
if (BUAI->getEnforcement() != SILAccessEnforcement::Unsafe
&& !BUAI->isFromBuiltin()) {
require(storage, "Unknown formal access pattern");
}
}
void checkEndUnpairedAccessInst(EndUnpairedAccessInst *I) {
require(I->getEnforcement() != SILAccessEnforcement::Unknown,
"unpaired access can never use unknown enforcement");
requireAddressType(BuiltinUnsafeValueBufferType, I->getBuffer(),
"scratch buffer operand");
checkAccessEnforcement(I);
}
void checkStoreInst(StoreInst *SI) {
require(SI->getSrc()->getType().isObject(),
"Can't store from an address source");
require(!fnConv.useLoweredAddresses()
|| SI->getSrc()->getType().isLoadable(*SI->getFunction()),
"Can't store a non loadable type");
require(SI->getDest()->getType().isAddress(),
"Must store to an address dest");
requireSameType(SI->getDest()->getType().getObjectType(),
SI->getSrc()->getType(),
"Store operand type and dest type mismatch");
// Perform ownership checks.
switch (SI->getOwnershipQualifier()) {
case StoreOwnershipQualifier::Unqualified:
// We should not see loads with unqualified ownership when SILOwnership is
// enabled.
require(!F.hasOwnership(),
"Qualified store in function with unqualified ownership?!");
break;
case StoreOwnershipQualifier::Init:
case StoreOwnershipQualifier::Assign:
require(
F.hasOwnership(),
"Inst with qualified ownership in a function that is not qualified");
// TODO: Could probably make this a bit stricter.
require(!SI->getSrc()->getType().isTrivial(*SI->getFunction()),
"store [init] or store [assign] can only be applied to "
"non-trivial types");
break;
case StoreOwnershipQualifier::Trivial: {
require(
F.hasOwnership(),
"Inst with qualified ownership in a function that is not qualified");
SILValue Src = SI->getSrc();
require(Src->getType().isTrivial(*SI->getFunction()) ||
Src->getOwnershipKind() == OwnershipKind::None,
"A store with trivial ownership must store a type with trivial "
"ownership");
break;
}
}
}
void checkStoreBorrowInst(StoreBorrowInst *SI) {
// A store_borrow must be to an alloc_stack. That alloc_stack can only be
// used by store_borrows (and dealloc_stacks).
require(SI->getSrc()->getType().isObject(),
"Can't store from an address source");
require(!fnConv.useLoweredAddresses()
|| SI->getSrc()->getType().isLoadable(*SI->getFunction()),
"Can't store a non loadable type");
require(SI->getDest()->getType().isAddress(),
"Must store to an address dest");
// Note: This is the current implementation and the design is not final.
auto isLegal = [](SILValue value) {
if (auto *mmci = dyn_cast<MarkUnresolvedNonCopyableValueInst>(value))
value = mmci->getOperand();
return isa<AllocStackInst>(value);
};
require(isLegal(SI->getDest()),
"store_borrow destination can only be an alloc_stack");
requireSameType(SI->getDest()->getType().getObjectType(),
SI->getSrc()->getType(),
"Store operand type and dest type mismatch");
SSAPrunedLiveness scopedAddressLiveness(SI->getFunction());
ScopedAddressValue scopedAddress(SI);
// FIXME: Reenable @test_load_borrow_store_borrow_nested in
// store_borrow_verify_errors once computeLivess can successfully handle a
// store_borrow within a load_borrow. This can be fixed in two ways
//
// (1) With complete lifetimes, this no longer needs to perform transitive
// liveness at all.
//
// (2) findInnerTransitiveGuaranteedUses, which ends up being called on the
// load_borrow to compute liveness, can be taught to transitively process
// InteriorPointer uses instead of returning PointerEscape. We need to make
// sure all uses of the utility need to handle this first.
AddressUseKind useKind =
scopedAddress.computeTransitiveLiveness(scopedAddressLiveness);
bool success = useKind == AddressUseKind::NonEscaping;
require(!success || checkScopedAddressUses(
scopedAddress, &scopedAddressLiveness, DEBlocks.get()),
"Ill formed store_borrow scope");
require(!success || !hasOtherStoreBorrowsInLifetime(
SI, &scopedAddressLiveness, DEBlocks.get()),
"A store_borrow cannot be nested within another "
"store_borrow to its destination");
for (auto *use : SI->getDest()->getUses()) {
auto *user = use->getUser();
require(
user == SI || isa<StoreBorrowInst>(user) ||
isa<DeallocStackInst>(user),
"A store_borrow destination can be used only via its return address");
}
}
void checkAssignInst(AssignInst *AI) {
SILValue Src = AI->getSrc(), Dest = AI->getDest();
require(AI->getModule().getStage() == SILStage::Raw,
"assign instruction can only exist in raw SIL");
require(Src->getType().isObject(), "Can't assign from an address source");
require(Dest->getType().isAddress(), "Must store to an address dest");
requireSameType(Dest->getType().getObjectType(), Src->getType(),
"Store operand type and dest type mismatch");
}
// Usually the assign_by_wrapper initializer or setter has a single argument
// (the value). But in case of a tuple, the initializer/setter expect the
// tuple elements as separate arguments.
void checkAssignByWrapperArgsRecursively(SILType ty,
SILFunctionConventions &conv, unsigned &argIdx) {
if (auto tupleTy = ty.getAs<TupleType>()) {
for (Type et : tupleTy->getElementTypes()) {
SILType elTy = SILType::getPrimitiveType(CanType(et), ty.getCategory());
checkAssignByWrapperArgsRecursively(elTy, conv, argIdx);
}
return;
}
require(argIdx < conv.getNumSILArguments(),
"initializer or setter has too few arguments");
SILType argTy =
conv.getSILArgumentType(argIdx++, F.getTypeExpansionContext());
if (ty.isAddress() && argTy.isObject())
ty = ty.getObjectType();
requireSameType(ty, argTy, "wrong argument type of initializer or setter");
}
void checkAssignByWrapperArgs(SILType ty, SILFunctionConventions &conv) {
unsigned argIdx = conv.getSILArgIndexOfFirstParam();
checkAssignByWrapperArgsRecursively(ty, conv, argIdx);
require(argIdx == conv.getNumSILArguments(),
"initializer or setter has too many arguments");
}
void checkAssignByWrapperInst(AssignByWrapperInst *AI) {
SILValue Src = AI->getSrc(), Dest = AI->getDest();
require(AI->getModule().getStage() == SILStage::Raw,
"assign instruction can only exist in raw SIL");
require(Dest->getType().isAddress(), "Must store to an address dest");
SILValue initFn = AI->getInitializer();
CanSILFunctionType initTy = initFn->getType().castTo<SILFunctionType>();
SILFunctionConventions initConv(initTy, AI->getModule());
checkAssignByWrapperArgs(Src->getType(), initConv);
switch (initConv.getNumIndirectSILResults()) {
case 0:
require(initConv.getNumDirectSILResults() == 1,
"wrong number of init function results");
requireSameType(
Dest->getType().getObjectType(),
*initConv.getDirectSILResultTypes(F.getTypeExpansionContext())
.begin(),
"wrong init function result type");
break;
case 1:
require(initConv.getNumDirectSILResults() == 0,
"wrong number of init function results");
requireSameType(
Dest->getType(),
*initConv.getIndirectSILResultTypes(F.getTypeExpansionContext())
.begin(),
"wrong indirect init function result type");
break;
default:
require(false, "wrong number of indirect init function results");
}
SILValue setterFn = AI->getSetter();
CanSILFunctionType setterTy = setterFn->getType().castTo<SILFunctionType>();
SILFunctionConventions setterConv(setterTy, AI->getModule());
require(setterConv.getNumIndirectSILResults() == 0,
"set function has indirect results");
checkAssignByWrapperArgs(Src->getType(), setterConv);
}
void checkAssigOrInitInstAccessorArgs(SILType argTy,
SILFunctionConventions &conv) {
unsigned argIdx = conv.getSILArgIndexOfFirstParam();
checkAssignByWrapperArgsRecursively(argTy, conv, argIdx);
}
void checkAssignOrInitInst(AssignOrInitInst *AI) {
SILValue Src = AI->getSrc();
require(AI->getModule().getStage() == SILStage::Raw,
"assign_or_init can only exist in raw SIL");
SILValue initFn = AI->getInitializer();
SILValue setterFn = AI->getSetter();
// Check init - it's an unapplied reference that takes property addresses
// and `initialValue`.
{
CanSILFunctionType initTy = initFn->getType().castTo<SILFunctionType>();
SILFunctionConventions initConv(initTy, AI->getModule());
require(initConv.getNumIndirectSILResults() ==
AI->getNumInitializedProperties(),
"init function has invalid number of indirect results");
checkAssigOrInitInstAccessorArgs(Src->getType(), initConv);
}
if (isa<SILUndef>(setterFn))
return;
// Check setter - it's a partially applied reference which takes
// `initialValue`.
CanSILFunctionType setterTy = setterFn->getType().castTo<SILFunctionType>();
SILFunctionConventions setterConv(setterTy, AI->getModule());
require(setterConv.getNumIndirectSILResults() == 0,
"set function has indirect results");
checkAssignByWrapperArgs(Src->getType(), setterConv);
};
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \
void checkLoad##Name##Inst(Load##Name##Inst *LWI) { \
require(LWI->getType().isObject(), "Result of load must be an object"); \
auto isOptional = bool(LWI->getType().getOptionalObjectType()); \
auto optionality = optionalityOf(ReferenceOwnership::Name); \
if (optionality == ReferenceOwnershipOptionality::Required) \
require(isOptional, "Optionality mismatch"); \
if (optionality == ReferenceOwnershipOptionality::Disallowed) \
require(!isOptional, "Optionality mismatch"); \
auto PointerType = LWI->getOperand()->getType(); \
auto PointerRVType = PointerType.getASTType(); \
require(PointerType.isAddress() && PointerRVType->is<Name##StorageType>(), \
"load_" #name " operand must be a " #name " address"); \
requireSameType( \
PointerRVType->getReferenceStorageReferent()->getCanonicalType(), \
LWI->getType().getASTType(), \
"Load operand type and result type mismatch"); \
} \
void checkStore##Name##Inst(Store##Name##Inst *SWI) { \
auto SrcTy = SWI->getSrc()->getType(); \
require(SrcTy.isObject(), "Can't store from an address source"); \
auto isOptional = bool(SrcTy.getOptionalObjectType()); \
auto optionality = optionalityOf(ReferenceOwnership::Name); \
if (optionality == ReferenceOwnershipOptionality::Required) \
require(isOptional, "Optionality mismatch"); \
if (optionality == ReferenceOwnershipOptionality::Disallowed) \
require(!isOptional, "Optionality mismatch"); \
auto PointerType = SWI->getDest()->getType(); \
auto PointerRVType = PointerType.getASTType(); \
require(PointerType.isAddress() && PointerRVType->is<Name##StorageType>(), \
"store_" #name " address operand must be a " #name " address"); \
requireSameType( \
PointerRVType->getReferenceStorageReferent()->getCanonicalType(), \
SrcTy.getASTType(), "Store operand type and dest type mismatch"); \
}
#define LOADABLE_REF_STORAGE_HELPER(Name, name) \
void checkRefTo##Name##Inst(RefTo##Name##Inst *I) { \
requireReferenceStorageCapableValue(I->getOperand(), \
"Operand of ref_to_" #name); \
auto operandType = I->getOperand()->getType().getASTType(); \
require(!I->getOperand()->getType().isAddressOnly(F), \
"ref_to_" #name " may not take an address-only operand"); \
auto resultType = \
requireObjectType(Name##StorageType, I, "Result of ref_to_" #name); \
require(!I->getType().isAddressOnly(F), \
"ref_to_" #name " must not produce an address-only value"); \
requireSameType(resultType.getReferentType(), operandType, \
"Result of ref_to_" #name " does not have the " \
"operand's type as its referent type"); \
} \
void check##Name##ToRefInst(Name##ToRefInst *I) { \
auto operandType = requireObjectType(Name##StorageType, I->getOperand(), \
"Operand of " #name "_to_ref"); \
require(!I->getOperand()->getType().isAddressOnly(F), \
#name "_to_ref may not take an address-only operand"); \
requireReferenceStorageCapableValue(I, "Result of " #name "_to_ref"); \
auto resultType = I->getType().getASTType(); \
require(!I->getType().isAddressOnly(F), \
#name "_to_ref may not produce an address-only value"); \
requireSameType(operandType.getReferentType(), resultType, \
"Operand of " #name "_to_ref does not have the " \
"operand's type as its referent type"); \
}
#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE_HELPER(Name, name, closure) \
void checkStrongRetain##Name##Inst(StrongRetain##Name##Inst *RI) { \
auto ty = requireObjectType(Name##StorageType, RI->getOperand(), \
"Operand of strong_retain_" #name); \
closure(); \
(void)ty; \
require(!F.hasOwnership(), "strong_retain_" #name " is only in " \
"functions with unqualified " \
"ownership"); \
} \
void check##Name##RetainInst(Name##RetainInst *RI) { \
auto ty = requireObjectType(Name##StorageType, RI->getOperand(), \
"Operand of " #name "_retain"); \
closure(); \
(void)ty; \
require(!F.hasOwnership(), \
#name "_retain is only in functions with unqualified ownership"); \
} \
void check##Name##ReleaseInst(Name##ReleaseInst *RI) { \
auto ty = requireObjectType(Name##StorageType, RI->getOperand(), \
"Operand of " #name "_release"); \
closure(); \
(void)ty; \
require(!F.hasOwnership(), \
#name "_release is only in functions with unqualified ownership"); \
} \
void StrongcheckCopy##Name##ValueInst(StrongCopy##Name##ValueInst *I) { \
auto ty = requireObjectType(Name##StorageType, I->getOperand(), \
"Operand of " #name "_retain"); \
closure(); \
(void)ty; \
/* *NOTE* We allow copy_##name##_value to be used throughout the entire */ \
/* pipeline even though it is a higher level instruction. */ \
}
#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \
LOADABLE_REF_STORAGE_HELPER(Name, name) \
ALWAYS_LOADABLE_CHECKED_REF_STORAGE_HELPER(Name, name, []{})
#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \
LOADABLE_REF_STORAGE_HELPER(Name, name) \
NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, "...") \
ALWAYS_LOADABLE_CHECKED_REF_STORAGE_HELPER(Name, name, [&]{ \
require(ty->isLoadable(ResilienceExpansion::Maximal), \
"'" #name "' type must be loadable"); \
})
#define UNCHECKED_REF_STORAGE(Name, name, ...) \
LOADABLE_REF_STORAGE_HELPER(Name, name) \
void checkStrongCopy##Name##ValueInst(StrongCopy##Name##ValueInst *I) { \
auto ty = requireObjectType(Name##StorageType, I->getOperand(), \
"Operand of " #name "_retain"); \
(void)ty; \
/* *NOTE* We allow copy_##name##_value to be used throughout the entire */ \
/* pipeline even though it is a higher level instruction. */ \
}
#include "swift/AST/ReferenceStorage.def"
#undef LOADABLE_REF_STORAGE_HELPER
#undef ALWAYS_LOADABLE_CHECKED_REF_STORAGE_HELPER
void checkMarkUninitializedInst(MarkUninitializedInst *MU) {
SILValue Src = MU->getOperand();
require(MU->getModule().getStage() == SILStage::Raw,
"mark_uninitialized instruction can only exist in raw SIL");
require(Src->getType().isAddress() ||
Src->getType().getClassOrBoundGenericClass() ||
Src->getType().getAs<SILBoxType>(),
"mark_uninitialized must be an address, class, or box type");
requireSameType(Src->getType(), MU->getType(),
"operand and result type mismatch");
// FIXME: When the work to force MUI to be on Allocations/SILArguments
// complete, turn on this assertion.
require(isa<AllocationInst>(Src)
|| isa<GlobalAddrInst>(Src)
// TODO: Should we support SILUndef on mark_uninitialized? We
// currently have a test that verifies this behavior, but it seems
// like this would always be a bug due to the implications around
// the code in DI. This just bakes in the current behavior.
|| isa<SILUndef>(Src)
// We allow SILArguments to support the case of initializing
// initializers. In such a case, the underlying case is allocated
// outside by the allocating initializer and we pass in the to be
// initialized value as a SILArgument.
|| isa<SILArgument>(Src)
// FIXME: We only support pointer to address here to not break LLDB. It is
// important that long term we get rid of this since this is a situation
// where LLDB is breaking SILGen/DI invariants by not creating a new
// independent stack location for the pointer to address.
|| isa<PointerToAddressInst>(Src),
"Mark Uninitialized must be applied to a storage location");
}
void checkMarkFunctionEscapeInst(MarkFunctionEscapeInst *MFE) {
require(MFE->getModule().getStage() == SILStage::Raw,
"mark_function_escape instruction can only exist in raw SIL");
for (auto Elt : MFE->getElements())
require(Elt->getType().isAddress(), "MFE must refer to variable addrs");
}
void checkCopyAddrInst(CopyAddrInst *cai) {
require(cai->getSrc()->getType().isAddress(), "Src value should be lvalue");
require(cai->getDest()->getType().isAddress(),
"Dest address should be lvalue");
requireSameType(cai->getDest()->getType(), cai->getSrc()->getType(),
"Store operand type and dest type mismatch");
require(checkTypeABIAccessible(F, cai->getDest()->getType()),
"cannot directly copy type with inaccessible ABI");
require(cai->getModule().getStage() == SILStage::Raw ||
(cai->isTakeOfSrc() || !cai->getSrc()->getType().isMoveOnly()),
"'MoveOnly' types can only be copied in Raw SIL?!");
}
void checkExplicitCopyAddrInst(ExplicitCopyAddrInst *ecai) {
require(F.hasOwnership(), "explicit_copy_* is only valid in OSSA.");
require(ecai->getSrc()->getType().isAddress(),
"Src value should be lvalue");
require(ecai->getDest()->getType().isAddress(),
"Dest address should be lvalue");
requireSameType(ecai->getDest()->getType(), ecai->getSrc()->getType(),
"Store operand type and dest type mismatch");
require(checkTypeABIAccessible(F, ecai->getDest()->getType()),
"cannot directly copy type with inaccessible ABI");
}
void checkMarkUnresolvedMoveAddrInst(MarkUnresolvedMoveAddrInst *SI) {
require(F.hasOwnership(), "Only valid in OSSA.");
require(F.getModule().getStage() == SILStage::Raw, "Only valid in Raw SIL");
require(SI->getSrc()->getType().isAddress(), "Src value should be lvalue");
require(SI->getDest()->getType().isAddress(),
"Dest address should be lvalue");
requireSameType(SI->getDest()->getType(), SI->getSrc()->getType(),
"Store operand type and dest type mismatch");
require(checkTypeABIAccessible(F, SI->getDest()->getType()),
"cannot directly copy type with inaccessible ABI");
}
void checkRetainValueInst(RetainValueInst *I) {
require(I->getOperand()->getType().isObject(),
"Source value should be an object value");
require(!F.hasOwnership(),
"retain_value is only in functions with unqualified ownership");
}
void checkRetainValueAddrInst(RetainValueAddrInst *I) {
require(I->getOperand()->getType().isAddress(),
"Source value should be an address value");
require(!F.hasOwnership(),
"retain_value is only in functions with unqualified ownership");
}
void checkCopyValueInst(CopyValueInst *I) {
require(I->getOperand()->getType().isObject(),
"Source value should be an object value");
require(!I->getOperand()->getType().isTrivial(*I->getFunction()),
"Source value should be non-trivial");
require(!fnConv.useLoweredAddresses() || F.hasOwnership(),
"copy_value is only valid in functions with qualified "
"ownership");
require(I->getModule().getStage() == SILStage::Raw ||
!I->getOperand()->getType().isMoveOnly(),
"'MoveOnly' types can only be copied in Raw SIL?!");
}
void checkUnownedCopyValueInst(UnownedCopyValueInst *I) {
require(!F.getModule().useLoweredAddresses(),
"unowned_copy_value is only valid in opaque values");
require(I->getType().isAddressOnly(F),
"unowned_copy_value must produce an address-only value");
}
void checkWeakCopyValueInst(WeakCopyValueInst *I) {
require(!F.getModule().useLoweredAddresses(),
"weak_copy_value is only valid in opaque values");
require(I->getType().isAddressOnly(F),
"weak_copy_value must produce an address-only value");
}
void checkStrongCopyWeakValueInst(StrongCopyWeakValueInst *I) {
require(!F.getModule().useLoweredAddresses(),
"strong_copy_weak_value is only valid in opaque values");
require(I->getOperand()->getType().isAddressOnly(F),
"strong_copy_weak_value requires an address-only operand");
}
void checkExplicitCopyValueInst(ExplicitCopyValueInst *I) {
require(F.hasOwnership(), "explicit_copy_* is only valid in OSSA.");
require(I->getOperand()->getType().isObject(),
"Source value should be an object value");
require(!I->getOperand()->getType().isTrivial(*I->getFunction()),
"Source value should be non-trivial");
}
void checkDestroyValueInst(DestroyValueInst *I) {
require(I->getOperand()->getType().isObject(),
"Source value should be an object value");
require(!I->getOperand()->getType().isTrivial(*I->getFunction()),
"Source value should be non-trivial");
require(!fnConv.useLoweredAddresses() || F.hasOwnership(),
"destroy_value is only valid in functions with qualified "
"ownership");
}
void checkReleaseValueInst(ReleaseValueInst *I) {
require(I->getOperand()->getType().isObject(),
"Source value should be an object value");
require(!F.hasOwnership(),
"release_value is only in functions with unqualified ownership");
}
void checkReleaseValueAddrInst(ReleaseValueAddrInst *I) {
require(I->getOperand()->getType().isAddress(),
"Source value should be an address value");
require(!F.hasOwnership(),
"release_value is only in functions with unqualified ownership");
}
void checkAutoreleaseValueInst(AutoreleaseValueInst *I) {
require(I->getOperand()->getType().isObject(),
"Source value should be an object value");
// TODO: This instruction could in principle be generalized.
require(I->getOperand()->getType().hasRetainablePointerRepresentation(),
"Source value must be a reference type or optional thereof");
}
void checkBeginDeallocRefInst(BeginDeallocRefInst *I) {
require(I->getReference()->getType().isObject(),
"Source value should be an object value");
require(I->getReference()->getType().hasRetainablePointerRepresentation(),
"Source value must be a reference type");
require(isa<AllocRefInstBase>(I->getOperand(1)),
"allocation must be an alloc_ref or alloc_ref_dynamic");
requireSameType(I->getReference()->getType(), I->getType(),
"result of begin_dealloc_ref should be same type as operand");
}
void checkEndInitLetRefInst(EndInitLetRefInst *I) {
require(I->getOperand()->getType().isObject(),
"Source value should be an object value");
require(I->getOperand()->getType().hasRetainablePointerRepresentation(),
"Source value must be a reference type");
requireSameType(I->getOperand()->getType(), I->getType(),
"result of end_init_let_ref should be same type as operand");
}
void checkCopyBlockInst(CopyBlockInst *I) {
require(I->getOperand()->getType().isBlockPointerCompatible(),
"operand of copy_block should be a block");
requireSameType(I->getOperand()->getType(), I->getType(),
"result of copy_block should be same type as operand");
}
void checkCopyBlockInst(CopyBlockWithoutEscapingInst *I) {
require(I->getBlock()->getType().isBlockPointerCompatible(),
"operand of copy_block should be a block");
requireSameType(I->getBlock()->getType(), I->getType(),
"result of copy_block should be same type as operand");
auto FnTy = requireObjectType(SILFunctionType, I->getClosure(),
"copy_block_without_escaping operand");
require(!FnTy->isNoEscape(),
"closure parameter must not be a @noescape closure");
}
void checkProjectBoxInst(ProjectBoxInst *I) {
require(I->getOperand()->getType().isObject(),
"project_box operand should be a value");
auto boxTy = I->getOperand()->getType().getAs<SILBoxType>();
require(boxTy, "project_box operand should be a @box type");
requireSameType(I->getType(),
getSILBoxFieldType(F.getTypeExpansionContext(), boxTy,
F.getModule().Types, I->getFieldIndex()),
"project_box result should be address of boxed type");
// If we have a mark_uninitialized as a user, the mark_uninitialized must be
// our only user. This is a requirement that is asserted by allocbox to
// stack. This check just embeds the requirement into the IR.
require(I->hasOneUse() ||
none_of(I->getUses(),
[](Operand *Op) -> bool {
return isa<MarkUninitializedInst>(Op->getUser());
}),
"project_box with more than one user when a user is a "
"mark_uninitialized");
checkAddressWalkerCanVisitAllTransitiveUses(I);
}
void checkProjectExistentialBoxInst(ProjectExistentialBoxInst *PEBI) {
SILType operandType = PEBI->getOperand()->getType();
require(operandType.isObject(),
"project_existential_box operand must not be address");
require(operandType.canUseExistentialRepresentation(
ExistentialRepresentation::Boxed),
"project_existential_box operand must be boxed existential");
require(PEBI->getType().isAddress(),
"project_existential_box result must be an address");
if (auto *AEBI = dyn_cast<AllocExistentialBoxInst>(PEBI->getOperand())) {
// The lowered type must be the properly-abstracted form of the AST type.
SILType exType = AEBI->getExistentialType();
auto archetype = OpenedArchetypeType::get(exType.getASTType(),
F.getGenericSignature());
auto loweredTy = F.getLoweredType(Lowering::AbstractionPattern(archetype),
AEBI->getFormalConcreteType())
.getAddressType();
requireSameType(loweredTy, PEBI->getType(),
"project_existential_box result should be the lowered "
"concrete type of its alloc_existential_box");
}
}
void checkStructInst(StructInst *SI) {
auto *structDecl = SI->getType().getStructOrBoundGenericStruct();
require(structDecl, "StructInst must return a struct");
require(!structDecl->hasUnreferenceableStorage(),
"Cannot build a struct with unreferenceable storage from elements "
"using StructInst");
require(!checkResilience(structDecl, F),
"cannot access storage of resilient struct");
require(SI->getType().isObject(),
"StructInst must produce an object");
SILType structTy = SI->getType();
auto opi = SI->getElements().begin(), opEnd = SI->getElements().end();
for (VarDecl *field : structDecl->getStoredProperties()) {
require(opi != opEnd,
"number of struct operands does not match number of stored "
"member variables of struct");
SILType loweredType =
structTy.getFieldType(field, F.getModule(), F.getTypeExpansionContext());
if (SI->getModule().getStage() != SILStage::Lowered) {
requireSameType((*opi)->getType(), loweredType,
"struct operand type does not match field type");
}
++opi;
}
}
void checkEnumInst(EnumInst *UI) {
EnumDecl *ud = UI->getType().getEnumOrBoundGenericEnum();
require(ud, "EnumInst must return an enum");
require(UI->getElement()->getParentEnum() == ud,
"EnumInst case must be a case of the result enum type");
require(UI->getType().isObject(),
"EnumInst must produce an object");
require(UI->hasOperand() == UI->getElement()->hasAssociatedValues(),
"EnumInst must take an argument iff the element does");
if (UI->getElement()->hasAssociatedValues()) {
require(UI->getOperand()->getType().isObject(),
"EnumInst operand must be an object");
SILType caseTy = UI->getType().getEnumElementType(
UI->getElement(), F.getModule(), F.getTypeExpansionContext());
if (UI->getModule().getStage() != SILStage::Lowered) {
requireSameType(caseTy, UI->getOperand()->getType(),
"EnumInst operand type does not match type of case");
}
}
}
void checkInitEnumDataAddrInst(InitEnumDataAddrInst *UI) {
EnumDecl *ud = UI->getOperand()->getType().getEnumOrBoundGenericEnum();
require(ud, "InitEnumDataAddrInst must take an enum operand");
require(UI->getElement()->getParentEnum() == ud,
"InitEnumDataAddrInst case must be a case of the enum operand type");
require(UI->getElement()->hasAssociatedValues(),
"InitEnumDataAddrInst case must have a data type");
require(UI->getOperand()->getType().isAddress(),
"InitEnumDataAddrInst must take an address operand");
require(UI->getType().isAddress(),
"InitEnumDataAddrInst must produce an address");
SILType caseTy = UI->getOperand()->getType().getEnumElementType(
UI->getElement(), F.getModule(), F.getTypeExpansionContext());
if (UI->getModule().getStage() != SILStage::Lowered) {
requireSameType(
caseTy, UI->getType(),
"InitEnumDataAddrInst result does not match type of enum case");
}
}
void checkUncheckedEnumDataInst(UncheckedEnumDataInst *UI) {
EnumDecl *ud = UI->getOperand()->getType().getEnumOrBoundGenericEnum();
require(ud, "UncheckedEnumData must take an enum operand");
require(UI->getElement()->getParentEnum() == ud,
"UncheckedEnumData case must be a case of the enum operand type");
require(UI->getElement()->getArgumentInterfaceType(),
"UncheckedEnumData case must have a data type");
require(UI->getOperand()->getType().isObject(),
"UncheckedEnumData must take an address operand");
require(UI->getType().isObject(),
"UncheckedEnumData must produce an address");
SILType caseTy = UI->getOperand()->getType().getEnumElementType(
UI->getElement(), F.getModule(), F.getTypeExpansionContext());
if (UI->getModule().getStage() != SILStage::Lowered) {
requireSameType(
caseTy, UI->getType(),
"UncheckedEnumData result does not match type of enum case");
}
}
void checkUncheckedTakeEnumDataAddrInst(UncheckedTakeEnumDataAddrInst *UI) {
EnumDecl *ud = UI->getOperand()->getType().getEnumOrBoundGenericEnum();
require(ud, "UncheckedTakeEnumDataAddrInst must take an enum operand");
require(UI->getElement()->getParentEnum() == ud,
"UncheckedTakeEnumDataAddrInst case must be a case of the enum operand type");
require(UI->getElement()->getArgumentInterfaceType(),
"UncheckedTakeEnumDataAddrInst case must have a data type");
require(UI->getOperand()->getType().isAddress(),
"UncheckedTakeEnumDataAddrInst must take an address operand");
require(UI->getType().isAddress(),
"UncheckedTakeEnumDataAddrInst must produce an address");
SILType caseTy = UI->getOperand()->getType().getEnumElementType(
UI->getElement(), F.getModule(), F.getTypeExpansionContext());
if (UI->getModule().getStage() != SILStage::Lowered) {
requireSameType(caseTy, UI->getType(),
"UncheckedTakeEnumDataAddrInst result "
"does not match type of enum case");
}
}
void checkInjectEnumAddrInst(InjectEnumAddrInst *IUAI) {
require(IUAI->getOperand()->getType().is<EnumType>()
|| IUAI->getOperand()->getType().is<BoundGenericEnumType>(),
"InjectEnumAddrInst must take an enum operand");
require(IUAI->getElement()->getParentEnum()
== IUAI->getOperand()->getType().getEnumOrBoundGenericEnum(),
"InjectEnumAddrInst case must be a case of the enum operand type");
require(IUAI->getOperand()->getType().isAddress(),
"InjectEnumAddrInst must take an address operand");
}
void checkTupleInst(TupleInst *TI) {
CanTupleType ResTy = requireObjectType(TupleType, TI, "Result of tuple");
require(!ResTy.containsPackExpansionType(),
"tuple instruction cannot be used with tuples containing "
"pack expansions");
require(TI->getElements().size() == ResTy->getNumElements(),
"Tuple field count mismatch!");
if (TI->getModule().getStage() != SILStage::Lowered) {
for (size_t i = 0, size = TI->getElements().size(); i < size; ++i) {
requireSameType(TI->getElement(i)->getType().getASTType(),
ResTy.getElementType(i),
"Tuple element arguments do not match tuple type!");
}
}
}
void checkTupleAddrConstructorInst(TupleAddrConstructorInst *taci) {
require(F.getModule().useLoweredAddresses(),
"tuple_addr_constructor is invalid in opaque values");
require(taci->getNumElements() > 0,
"Cannot be applied to tuples that do not contain any real "
"elements. E.x.: ((), ())");
for (auto elt : taci->getElements()) {
// We cannot have any elements that contain only tuple elements. This is
// due to our exploded representation. This means when specializing,
// cloners must eliminate these parameters.
bool hasNonTuple = false;
elt->getType().getASTType().visit([&](CanType ty) {
hasNonTuple |= !ty->is<TupleType>();
});
require(hasNonTuple, "Element only consists of tuples");
}
}
// Is a SIL type a potential lowering of a formal type?
bool isLoweringOf(SILType loweredType, CanType formalType) {
return loweredType.isLoweringOf(F.getTypeExpansionContext(), F.getModule(),
formalType);
}
void checkMetatypeInst(MetatypeInst *MI) {
require(MI->getType().is<MetatypeType>(),
"metatype instruction must be of metatype type");
auto MetaTy = MI->getType().castTo<MetatypeType>();
require(MetaTy->hasRepresentation(),
"metatype instruction must have a metatype representation");
verifyLocalArchetype(MI, MetaTy.getInstanceType());
}
void checkValueMetatypeInst(ValueMetatypeInst *MI) {
require(MI->getType().is<MetatypeType>(),
"value_metatype instruction must be of metatype type");
require(MI->getType().castTo<MetatypeType>()->hasRepresentation(),
"value_metatype instruction must have a metatype representation");
auto formalInstanceTy
= MI->getType().castTo<MetatypeType>().getInstanceType();
require(isLoweringOf(MI->getOperand()->getType(), formalInstanceTy),
"value_metatype result must be formal metatype of "
"lowered operand type");
}
void checkExistentialMetatypeInst(ExistentialMetatypeInst *MI) {
require(MI->getType().is<ExistentialMetatypeType>(),
"existential_metatype instruction must be of metatype type");
require(MI->getType().castTo<ExistentialMetatypeType>()->hasRepresentation(),
"value_metatype instruction must have a metatype representation");
require(MI->getOperand()->getType().isAnyExistentialType(),
"existential_metatype operand must be of protocol type");
// The result of an existential_metatype instruction is an existential
// metatype with the same constraint type as its existential operand.
auto formalInstanceTy
= MI->getType().castTo<ExistentialMetatypeType>().getInstanceType();
if (formalInstanceTy->isConstraintType()) {
require(MI->getOperand()->getType().is<ExistentialType>(),
"existential_metatype operand must be an existential type");
formalInstanceTy =
ExistentialType::get(formalInstanceTy)->getCanonicalType();
}
require(isLoweringOf(MI->getOperand()->getType(), formalInstanceTy),
"existential_metatype result must be formal metatype of "
"lowered operand type");
}
void checkStrongRetainInst(StrongRetainInst *RI) {
requireReferenceValue(RI->getOperand(), "Operand of strong_retain");
require(!F.hasOwnership(),
"strong_retain is only in functions with unqualified ownership");
}
void checkStrongReleaseInst(StrongReleaseInst *RI) {
requireReferenceValue(RI->getOperand(), "Operand of release");
require(!F.hasOwnership(),
"strong_release is only in functions with unqualified ownership");
}
void checkDeallocStackInst(DeallocStackInst *DI) {
require(isa<SILUndef>(DI->getOperand()) ||
isa<AllocStackInst>(DI->getOperand()) ||
isa<AllocVectorInst>(DI->getOperand()) ||
(isa<PartialApplyInst>(DI->getOperand()) &&
cast<PartialApplyInst>(DI->getOperand())->isOnStack()),
"Operand of dealloc_stack must be an alloc_stack, alloc_vector or partial_apply "
"[stack]");
}
void checkDeallocPackInst(DeallocPackInst *DI) {
require(isa<SILUndef>(DI->getOperand()) ||
isa<AllocPackInst>(DI->getOperand()),
"Operand of dealloc_pack must be an alloc_pack");
}
void checkDeallocRefInst(DeallocRefInst *DI) {
require(DI->getOperand()->getType().isObject(),
"Operand of dealloc_ref must be object");
auto *cd = DI->getOperand()->getType().getClassOrBoundGenericClass();
require(cd, "Operand of dealloc_ref must be of class type");
require(!checkResilience(cd, F),
"cannot directly deallocate resilient class");
}
void checkDeallocPartialRefInst(DeallocPartialRefInst *DPRI) {
require(DPRI->getInstance()->getType().isObject(),
"First operand of dealloc_partial_ref must be object");
auto class1 = DPRI->getInstance()->getType().getClassOrBoundGenericClass();
require(class1,
"First operand of dealloc_partial_ref must be of class type");
require(DPRI->getMetatype()->getType().is<MetatypeType>(),
"Second operand of dealloc_partial_ref must be a metatype");
auto class2 = DPRI->getMetatype()->getType().castTo<MetatypeType>()
->getInstanceType()->getClassOrBoundGenericClass();
require(class2,
"Second operand of dealloc_partial_ref must be a class metatype");
require(class2->isSuperclassOf(class1),
"First operand not superclass of second instance type");
}
void checkAllocBoxInst(AllocBoxInst *AI) {
auto boxTy = AI->getType().getAs<SILBoxType>();
require(boxTy, "alloc_box must have a @box type");
require(AI->getType().isObject(),
"result of alloc_box must be an object");
for (unsigned field : indices(AI->getBoxType()->getLayout()->getFields())) {
verifyLocalArchetype(AI, getSILBoxFieldLoweredType(
F.getTypeExpansionContext(), AI->getBoxType(),
F.getModule().Types, field));
}
// An alloc_box with a mark_uninitialized user can not have any other users.
require(none_of(AI->getUses(),
[](Operand *Op) -> bool {
return isa<MarkUninitializedInst>(Op->getUser());
}) ||
AI->hasOneUse(),
"An alloc_box with a mark_uninitialized user can not have any "
"other users.");
}
void checkDeallocBoxInst(DeallocBoxInst *DI) {
auto boxTy = DI->getOperand()->getType().getAs<SILBoxType>();
require(boxTy, "operand must be a @box type");
require(DI->getOperand()->getType().isObject(),
"operand must be an object");
}
void checkDestroyAddrInst(DestroyAddrInst *DI) {
require(DI->getOperand()->getType().isAddress(),
"Operand of destroy_addr must be address");
require(checkTypeABIAccessible(F, DI->getOperand()->getType()),
"cannot directly destroy type with inaccessible ABI");
}
void checkBindMemoryInst(BindMemoryInst *BI) {
require(BI->getBoundType(), "BI must have a bound type");
require(BI->getBase()->getType().is<BuiltinRawPointerType>(),
"bind_memory base be a RawPointer");
requireSameType(BI->getIndex()->getType(),
SILType::getBuiltinWordType(F.getASTContext()),
"bind_memory index must be a Word");
}
void checkRebindMemoryInst(RebindMemoryInst *rbi) {
require(rbi->getBase()->getType().is<BuiltinRawPointerType>(),
"rebind_memory base be a RawPointer");
requireSameType(rbi->getInToken()->getType(),
SILType::getBuiltinWordType(F.getASTContext()),
"rebind_memory token must be a Builtin.Int64");
}
void checkIndexAddrInst(IndexAddrInst *IAI) {
require(IAI->getType().isAddress(), "index_addr must produce an address");
requireSameType(
IAI->getType(), IAI->getBase()->getType(),
"index_addr must produce an address of the same type as its base");
require(IAI->getIndex()->getType().is<BuiltinIntegerType>(),
"index_addr index must be of a builtin integer type");
}
void checkTailAddrInst(TailAddrInst *IAI) {
require(IAI->getType().isAddress(), "tail_addr must produce an address");
require(IAI->getIndex()->getType().is<BuiltinIntegerType>(),
"tail_addr index must be of a builtin integer type");
}
void checkIndexRawPointerInst(IndexRawPointerInst *IAI) {
require(IAI->getType().is<BuiltinRawPointerType>(),
"index_raw_pointer must produce a RawPointer");
require(IAI->getBase()->getType().is<BuiltinRawPointerType>(),
"index_raw_pointer base must be a RawPointer");
require(IAI->getIndex()->getType().is<BuiltinIntegerType>(),
"index_raw_pointer index must be of a builtin integer type");
}
void checkTupleExtractInst(TupleExtractInst *EI) {
CanTupleType operandTy = requireObjectType(TupleType, EI->getOperand(),
"Operand of tuple_extract");
require(!operandTy.containsPackExpansionType(),
"tuple_extract cannot be used with tuples containing "
"pack expansions");
require(EI->getType().isObject(),
"result of tuple_extract must be object");
require(EI->getFieldIndex() < operandTy->getNumElements(),
"invalid field index for tuple_extract instruction");
require(EI->getForwardingOwnershipKind() == OwnershipKind::None ||
EI->getForwardingOwnershipKind() == OwnershipKind::Guaranteed,
"invalid forwarding ownership kind on tuple_extract instruction");
if (EI->getModule().getStage() != SILStage::Lowered) {
requireSameType(EI->getType().getASTType(),
operandTy.getElementType(EI->getFieldIndex()),
"type of tuple_extract does not match type of element");
}
}
void checkStructExtractInst(StructExtractInst *EI) {
SILType operandTy = EI->getOperand()->getType();
require(operandTy.isObject(),
"cannot struct_extract from address");
require(EI->getType().isObject(),
"result of struct_extract cannot be address");
StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
require(sd, "must struct_extract from struct");
require(!checkResilience(sd, F),
"cannot access storage of resilient struct");
require(!EI->getField()->isStatic(),
"cannot get address of static property with struct_element_addr");
require(EI->getField()->hasStorage(),
"cannot load computed property with struct_extract");
require(EI->getField()->getDeclContext() == sd,
"struct_extract field is not a member of the struct");
require(EI->getForwardingOwnershipKind() == OwnershipKind::None ||
EI->getForwardingOwnershipKind() == OwnershipKind::Guaranteed,
"invalid forwarding ownership kind on tuple_extract instruction");
require(!EI->getModule()
.getOptions()
.EnableImportPtrauthFieldFunctionPointers ||
!EI->getField()->getPointerAuthQualifier().isPresent(),
"Imported structs with ptrauth qualified fields should not be "
"promoted to a value");
if (EI->getModule().getStage() != SILStage::Lowered) {
SILType loweredFieldTy = operandTy.getFieldType(
EI->getField(), F.getModule(), F.getTypeExpansionContext());
requireSameType(loweredFieldTy, EI->getType(),
"result of struct_extract does not match type of field");
}
}
void checkTupleElementAddrInst(TupleElementAddrInst *EI) {
require(EI->getType().isAddress(),
"result of tuple_element_addr must be address");
SILType operandTy = EI->getOperand()->getType();
auto tupleType = requireAddressType(TupleType, operandTy,
"operand of tuple_element_addr must be the address of a tuple");
require(!tupleType.containsPackExpansionType(),
"tuple_element_addr cannot be used with tuples containing "
"pack expansions");
require(EI->getFieldIndex() < tupleType->getNumElements(),
"invalid field index for tuple_element_addr instruction");
if (EI->getModule().getStage() != SILStage::Lowered) {
requireSameType(
EI->getType().getASTType(),
tupleType.getElementType(EI->getFieldIndex()),
"type of tuple_element_addr does not match type of element");
}
}
void checkStructElementAddrInst(StructElementAddrInst *EI) {
SILType operandTy = EI->getOperand()->getType();
require(operandTy.isAddress(),
"must derive struct_element_addr from address");
StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
require(sd, "struct_element_addr operand must be struct address");
require(!checkResilience(sd, F),
"cannot access storage of resilient struct");
require(EI->getType().isAddress(),
"result of struct_element_addr must be address");
require(!EI->getField()->isStatic(),
"cannot get address of static property with struct_element_addr");
require(EI->getField()->hasStorage(),
"cannot get address of computed property with struct_element_addr");
require(EI->getField()->getDeclContext() == sd,
"struct_element_addr field is not a member of the struct");
if (EI->getModule().getOptions().EnableImportPtrauthFieldFunctionPointers &&
EI->getField()->getPointerAuthQualifier().isPresent()) {
for (auto *use : EI->getUses()) {
auto *bai = dyn_cast<BeginAccessInst>(use->getUser());
require(bai && bai->getEnforcement() == SILAccessEnforcement::Signed,
"Access to ptrauth qualified fields should be scoped with "
"begin_access [signed]/end_access");
}
}
if (EI->getModule().getStage() != SILStage::Lowered) {
SILType loweredFieldTy = operandTy.getFieldType(
EI->getField(), F.getModule(), F.getTypeExpansionContext());
requireSameType(
loweredFieldTy, EI->getType(),
"result of struct_element_addr does not match type of field");
}
}
void checkRefElementAddrInst(RefElementAddrInst *EI) {
requireReferenceValue(EI->getOperand(), "Operand of ref_element_addr");
require(EI->getType().isAddress(),
"result of ref_element_addr must be lvalue");
require(!EI->getField()->isStatic(),
"cannot get address of static property with struct_element_addr");
require(EI->getField()->hasStorage(),
"cannot get address of computed property with ref_element_addr");
SILType operandTy = EI->getOperand()->getType();
ClassDecl *cd = operandTy.getClassOrBoundGenericClass();
require(cd, "ref_element_addr operand must be a class instance");
require(!checkResilience(cd, F),
"cannot access storage of resilient class");
require(EI->getField()->getDeclContext() ==
cd->getImplementationContext()->getAsGenericContext(),
"ref_element_addr field must be a member of the class");
if (EI->getModule().getStage() != SILStage::Lowered) {
SILType loweredFieldTy = operandTy.getFieldType(
EI->getField(), F.getModule(), F.getTypeExpansionContext());
requireSameType(
loweredFieldTy, EI->getType(),
"result of ref_element_addr does not match type of field");
}
EI->getFieldIndex(); // Make sure we can access the field without crashing.
checkAddressWalkerCanVisitAllTransitiveUses(EI);
}
void checkRefTailAddrInst(RefTailAddrInst *RTAI) {
requireReferenceValue(RTAI->getOperand(), "Operand of ref_tail_addr");
require(RTAI->getType().isAddress(),
"result of ref_tail_addr must be lvalue");
SILType operandTy = RTAI->getOperand()->getType();
ClassDecl *cd = operandTy.getClassOrBoundGenericClass();
require(cd, "ref_tail_addr operand must be a class instance");
require(!checkResilience(cd, F),
"cannot access storage of resilient class");
require(cd, "ref_tail_addr operand must be a class instance");
checkAddressWalkerCanVisitAllTransitiveUses(RTAI);
}
void checkDestructureStructInst(DestructureStructInst *DSI) {
SILType operandTy = DSI->getOperand()->getType();
StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
require(sd, "must struct_extract from struct");
require(!checkResilience(sd, F),
"cannot access storage of resilient struct");
if (F.hasOwnership()) {
// Make sure that all of our destructure results ownership kinds are
// compatible with our destructure_struct's ownership kind /and/ that if
// our destructure ownership kind is non-trivial then all non-trivial
// results must have the same ownership kind as our operand.
auto parentKind = DSI->getForwardingOwnershipKind();
for (const auto &result : DSI->getAllResultsBuffer()) {
require(parentKind.isCompatibleWith(result.getOwnershipKind()),
"destructure result with ownership that is incompatible with "
"parent forwarding ownership kind");
require(parentKind != OwnershipKind::None ||
result.getOwnershipKind() == OwnershipKind::None,
"destructure with none ownership kind operand and non-none "
"ownership kind result?!");
}
if (operandTy.getNominalOrBoundGenericNominal()
->getValueTypeDestructor()) {
require(
isa<DropDeinitInst>(lookThroughOwnershipInsts(DSI->getOperand())),
"a destructure of a move-only-type-with-deinit requires a "
"drop_deinit");
}
}
}
void checkDestructureTupleInst(DestructureTupleInst *dti) {
if (F.hasOwnership()) {
// Make sure that all of our destructure results ownership kinds are
// compatible with our destructure_struct's ownership kind /and/ that if
// our destructure ownership kind is non-trivial then all non-trivial
// results must have the same ownership kind as our operand.
auto parentKind = dti->getForwardingOwnershipKind();
for (const auto &result : dti->getAllResultsBuffer()) {
require(parentKind.isCompatibleWith(result.getOwnershipKind()),
"destructure result with ownership that is incompatible with "
"parent forwarding ownership kind");
require(parentKind != OwnershipKind::None ||
result.getOwnershipKind() == OwnershipKind::None,
"destructure with none ownership kind operand and non-none "
"ownership kind result?!");
}
}
}
SILType getMethodSelfType(CanSILFunctionType ft) {
SILFunctionConventions fnConv(ft, F.getModule());
return fnConv.getSILType(ft->getParameters().back(),
F.getTypeExpansionContext());
}
void checkWitnessMethodInst(WitnessMethodInst *AMI) {
auto methodType = requireObjectType(SILFunctionType, AMI,
"result of witness_method");
auto *protocol
= dyn_cast<ProtocolDecl>(AMI->getMember().getDecl()->getDeclContext());
require(protocol,
"witness_method method must be a protocol method");
require(methodType->getRepresentation()
== F.getModule().Types.getProtocolWitnessRepresentation(protocol),
"result of witness_method must have correct representation for protocol");
require(methodType->isPolymorphic(),
"result of witness_method must be polymorphic");
auto genericSig = methodType->getInvocationGenericSignature();
auto selfGenericParam = genericSig.getGenericParams()[0];
require(selfGenericParam->getDepth() == 0
&& selfGenericParam->getIndex() == 0,
"method should be polymorphic on Self parameter at depth 0 index 0");
std::optional<Requirement> selfRequirement;
for (auto req : genericSig.getRequirements()) {
if (req.getKind() != RequirementKind::SameType) {
selfRequirement = req;
break;
}
}
require(selfRequirement &&
selfRequirement->getKind() == RequirementKind::Conformance,
"first non-same-typerequirement should be conformance requirement");
const auto protos = genericSig->getRequiredProtocols(selfGenericParam);
require(std::find(protos.begin(), protos.end(), protocol) != protos.end(),
"requirement Self parameter must conform to called protocol");
auto lookupType = AMI->getLookupType();
if (getLocalArchetypeOf(lookupType) || lookupType->hasDynamicSelfType()) {
require(AMI->getTypeDependentOperands().size() == 1,
"Must have a type dependent operand for the opened archetype");
verifyLocalArchetype(AMI, lookupType);
} else {
require(AMI->getTypeDependentOperands().empty(),
"Should not have an operand for the opened existential");
}
if (!isa<ArchetypeType>(lookupType) && !isa<DynamicSelfType>(lookupType)) {
require(AMI->getConformance().isConcrete(),
"concrete type lookup requires concrete conformance");
auto conformance = AMI->getConformance().getConcrete();
requireSameType(
conformance->getType(), AMI->getLookupType(),
"concrete type lookup requires conformance that matches type");
}
require(AMI->getMember().requiresNewWitnessTableEntry(),
"method does not have a witness table entry");
}
/// Verify the given type of a dynamic or @objc optional method reference.
bool verifyDynamicMethodType(CanSILFunctionType verifiedTy, SILType selfType,
SILDeclRef method) {
auto &C = F.getASTContext();
// The type of the dynamic method must match the usual type of the method,
// but with the more opaque Self type.
auto constantInfo =
F.getModule().Types.getConstantInfo(F.getTypeExpansionContext(), method);
auto methodTy = constantInfo.SILFnType;
assert(!methodTy->isCoroutine());
// Map interface types to archetypes.
if (auto *env = F.getModule().Types.getConstantGenericEnvironment(method)) {
auto subs = env->getForwardingSubstitutionMap();
methodTy = methodTy->substGenericArgs(F.getModule(), subs,
F.getTypeExpansionContext());
}
assert(!methodTy->isPolymorphic());
// Assume the parameter conventions are correct.
SmallVector<SILParameterInfo, 4> params;
{
const auto actualParams = methodTy->getParameters();
const auto verifiedParams = verifiedTy->getParameters();
if (actualParams.size() != verifiedParams.size())
return false;
for (const auto idx : indices(actualParams)) {
params.push_back(actualParams[idx].getWithConvention(
verifiedParams[idx].getConvention()));
}
}
// Have the 'self' parameter assume the type of 'self' at the call site.
params.back() = params.back().getWithInterfaceType(selfType.getASTType());
// Assume the result conventions are correct.
SmallVector<SILResultInfo, 4> results;
{
const auto actualResults = methodTy->getResults();
const auto verifiedResults = verifiedTy->getResults();
if (actualResults.size() != verifiedResults.size())
return false;
for (const auto idx : indices(actualResults)) {
results.push_back(actualResults[idx].getWithConvention(
verifiedResults[idx].getConvention()));
}
}
// If the method returns dynamic Self, substitute AnyObject for the
// result type.
if (auto fnDecl = dyn_cast<FuncDecl>(method.getDecl())) {
if (fnDecl->hasDynamicSelfResult()) {
auto anyObjectTy = C.getAnyObjectType();
for (auto &result : results) {
auto newResultTy =
result
.getReturnValueType(F.getModule(), methodTy,
F.getTypeExpansionContext())
->replaceCovariantResultType(anyObjectTy, 0);
result = SILResultInfo(newResultTy->getCanonicalType(),
result.getConvention());
}
}
}
auto fnTy = SILFunctionType::get(nullptr,
methodTy->getExtInfo(),
methodTy->getCoroutineKind(),
methodTy->getCalleeConvention(),
params,
methodTy->getYields(),
results,
methodTy->getOptionalErrorResult(),
SubstitutionMap(), SubstitutionMap(),
F.getASTContext());
return fnTy->isBindableTo(verifiedTy);
}
/// Visitor class that checks whether a given decl ref has an entry in the
/// class's vtable.
class VerifyClassMethodVisitor
: public SILVTableVisitor<VerifyClassMethodVisitor>
{
public:
SILDeclRef Method;
bool Seen = false;
VerifyClassMethodVisitor(SILDeclRef method)
: Method(method.getOverriddenVTableEntry()) {
auto *theClass = cast<ClassDecl>(Method.getDecl()->getDeclContext());
addVTableEntries(theClass);
}
void addMethod(SILDeclRef method) {
if (Seen)
return;
if (method == Method)
Seen = true;
}
void addMethodOverride(SILDeclRef base, SILDeclRef derived) {}
void addPlaceholder(MissingMemberDecl *) {}
};
void checkClassMethodInst(ClassMethodInst *CMI) {
auto member = CMI->getMember();
auto overrideTy =
TC.getConstantOverrideType(F.getTypeExpansionContext(), member);
SILModule &mod = CMI->getModule();
bool embedded = mod.getASTContext().LangOpts.hasFeature(Feature::Embedded);
if (mod.getStage() != SILStage::Lowered && !embedded) {
requireSameType(
CMI->getType(), SILType::getPrimitiveObjectType(overrideTy),
"result type of class_method must match abstracted type of method");
}
auto methodType = requireObjectType(SILFunctionType, CMI,
"result of class_method");
require(!methodType->getExtInfo().hasContext(),
"result method must be of a context-free function type");
SILType operandType = CMI->getOperand()->getType();
require(operandType.isClassOrClassMetatype(),
"operand must be of a class type");
require(getMethodSelfType(methodType).isClassOrClassMetatype(),
"result must be a method of a class");
require(!member.isForeign,
"foreign method cannot be dispatched natively");
require(!isa<ExtensionDecl>(member.getDecl()->getDeclContext()),
"extension method cannot be dispatched natively");
// The method ought to appear in the class vtable unless it's a foreign
// reference type.
require(VerifyClassMethodVisitor(member).Seen ||
operandType.isForeignReferenceType(),
"method does not appear in the class's vtable");
}
void checkSuperMethodInst(SuperMethodInst *CMI) {
auto member = CMI->getMember();
auto overrideTy =
TC.getConstantOverrideType(F.getTypeExpansionContext(), member);
if (CMI->getModule().getStage() != SILStage::Lowered) {
requireSameType(
CMI->getType(), SILType::getPrimitiveObjectType(overrideTy),
"result type of super_method must match abstracted type of method");
}
auto methodType = requireObjectType(SILFunctionType, CMI,
"result of super_method");
require(!methodType->getExtInfo().hasContext(),
"result method must be of a context-free function type");
SILType operandType = CMI->getOperand()->getType();
require(operandType.isClassOrClassMetatype(),
"operand must be of a class type");
require(getMethodSelfType(methodType).isClassOrClassMetatype(),
"result must be a method of a class");
require(!member.isForeign,
"foreign method cannot be dispatched natively");
require(!isa<ExtensionDecl>(member.getDecl()->getDeclContext()),
"extension method cannot be dispatched natively");
auto decl = CMI->getMember().getDecl();
auto methodClass = decl->getDeclContext()->getDeclaredInterfaceType();
require(methodClass->getClassOrBoundGenericClass(),
"super_method must look up a class method");
// The method ought to appear in the class vtable.
require(VerifyClassMethodVisitor(member).Seen,
"method does not appear in the class's vtable");
}
void checkObjCMethodInst(ObjCMethodInst *OMI) {
auto member = OMI->getMember();
require(member.isForeign,
"native method cannot be dispatched via objc");
auto methodType = requireObjectType(SILFunctionType, OMI,
"result of objc_method");
require(!methodType->getExtInfo().hasContext(),
"result method must be of a context-free function type");
require(methodType->getRepresentation()
== SILFunctionTypeRepresentation::ObjCMethod,
"wrong function type representation");
auto operandType = OMI->getOperand()->getType();
auto operandInstanceType = operandType.getASTType();
if (auto metatypeType = dyn_cast<MetatypeType>(operandInstanceType))
operandInstanceType = metatypeType.getInstanceType();
if (operandInstanceType.getClassOrBoundGenericClass()) {
auto overrideTy =
TC.getConstantOverrideType(F.getTypeExpansionContext(), member);
requireSameType(
OMI->getType(), SILType::getPrimitiveObjectType(overrideTy),
"result type of objc_method must match abstracted type of method");
} else {
require(isa<ArchetypeType>(operandInstanceType) ||
operandInstanceType->isObjCExistentialType(),
"operand type must be an archetype or self-conforming existential");
verifyLocalArchetype(OMI, OMI->getType().getASTType());
}
// TODO: We should enforce that ObjC methods are dispatched on ObjC
// metatypes, but IRGen appears not to care right now.
#if 0
if (auto metaTy = operandType.getAs<AnyMetatypeType>()) {
bool objcMetatype
= metaTy->getRepresentation() == MetatypeRepresentation::ObjC;
require(objcMetatype,
"objc class methods must be invoked on objc metatypes");
}
#endif
}
void checkObjCSuperMethodInst(ObjCSuperMethodInst *OMI) {
auto member = OMI->getMember();
auto overrideTy =
TC.getConstantOverrideType(F.getTypeExpansionContext(), member);
if (OMI->getModule().getStage() != SILStage::Lowered) {
requireSameType(
OMI->getType(), SILType::getPrimitiveObjectType(overrideTy),
"result type of super_method must match abstracted type of method");
}
auto methodType = requireObjectType(SILFunctionType, OMI,
"result of objc_super_method");
require(!methodType->getExtInfo().hasContext(),
"result method must be of a context-free function type");
SILType operandType = OMI->getOperand()->getType();
require(operandType.isClassOrClassMetatype(),
"operand must be of a class type");
require(getMethodSelfType(methodType).isClassOrClassMetatype(),
"result must be a method of a class");
require(member.isForeign,
"native method cannot be dispatched via objc");
auto decl = member.getDecl();
auto methodClass = decl->getDeclContext()->getDeclaredInterfaceType();
require(methodClass->getClassOrBoundGenericClass(),
"objc_super_method must look up a class method");
}
void checkOpenExistentialAddrInst(OpenExistentialAddrInst *OEI) {
SILType operandType = OEI->getOperand()->getType();
require(operandType.isAddress(),
"open_existential_addr must be applied to address");
require(operandType.canUseExistentialRepresentation(
ExistentialRepresentation::Opaque),
"open_existential_addr must be applied to opaque existential");
require(OEI->getType().isAddress(),
"open_existential_addr result must be an address");
auto archetype = getOpenedArchetypeOf(OEI->getType().getASTType());
require(archetype,
"open_existential_addr result must be an opened existential archetype");
require(OEI->getModule().getRootLocalArchetypeDefInst(
archetype, OEI->getFunction()) == OEI,
"Archetype opened by open_existential_addr should be registered in "
"SILFunction");
// Check all the uses. Consuming or mutating uses must have mutable access
// to the opened value.
auto allowedAccessKind = OEI->getAccessKind();
if (allowedAccessKind == OpenedExistentialAccess::Mutable)
return;
require(allowedAccessKind == OpenedExistentialAccess::Mutable ||
!ImmutableAddressUseVerifier().isMutatingOrConsuming(OEI),
"open_existential_addr uses that consumes or mutates but is not "
"opened for mutation");
}
void checkOpenExistentialRefInst(OpenExistentialRefInst *OEI) {
SILType operandType = OEI->getOperand()->getType();
require(operandType.isObject(),
"open_existential_ref operand must not be address");
require(operandType.canUseExistentialRepresentation(
ExistentialRepresentation::Class),
"open_existential_ref operand must be class existential");
CanType resultInstanceTy = OEI->getType().getASTType();
require(OEI->getType().isObject(),
"open_existential_ref result must be an address");
auto archetype = getOpenedArchetypeOf(resultInstanceTy);
require(archetype,
"open_existential_ref result must be an opened existential archetype");
require(OEI->getModule().getRootLocalArchetypeDefInst(
archetype, OEI->getFunction()) == OEI,
"Archetype opened by open_existential_ref should be registered in "
"SILFunction");
}
void checkOpenExistentialBoxInst(OpenExistentialBoxInst *OEI) {
SILType operandType = OEI->getOperand()->getType();
require(operandType.isObject(),
"open_existential_box operand must not be address");
require(operandType.canUseExistentialRepresentation(
ExistentialRepresentation::Boxed),
"open_existential_box operand must be boxed existential");
CanType resultInstanceTy = OEI->getType().getASTType();
require(OEI->getType().isAddress(),
"open_existential_box result must be an address");
auto archetype = getOpenedArchetypeOf(resultInstanceTy);
require(archetype,
"open_existential_box result must be an opened existential archetype");
require(OEI->getModule().getRootLocalArchetypeDefInst(
archetype, OEI->getFunction()) == OEI,
"Archetype opened by open_existential_box should be registered in "
"SILFunction");
}
void checkOpenExistentialBoxValueInst(OpenExistentialBoxValueInst *OEI) {
SILType operandType = OEI->getOperand()->getType();
require(operandType.isObject(),
"open_existential_box operand must not be address");
require(operandType.canUseExistentialRepresentation(
ExistentialRepresentation::Boxed),
"open_existential_box operand must be boxed existential");
CanType resultInstanceTy = OEI->getType().getASTType();
require(!OEI->getType().isAddress(),
"open_existential_box_value result must not be an address");
auto archetype = getOpenedArchetypeOf(resultInstanceTy);
require(archetype,
"open_existential_box_value result not an opened existential archetype");
require(OEI->getModule().getRootLocalArchetypeDefInst(
archetype, OEI->getFunction()) == OEI,
"Archetype opened by open_existential_box_value should be "
"registered in SILFunction");
}
void checkOpenExistentialMetatypeInst(OpenExistentialMetatypeInst *I) {
SILType operandType = I->getOperand()->getType();
require(operandType.isObject(),
"open_existential_metatype operand must not be address");
require(operandType.is<ExistentialMetatypeType>(),
"open_existential_metatype operand must be existential metatype");
require(operandType.castTo<ExistentialMetatypeType>()->hasRepresentation(),
"open_existential_metatype operand must have a representation");
SILType resultType = I->getType();
require(resultType.isObject(),
"open_existential_metatype result must not be address");
require(resultType.is<MetatypeType>(),
"open_existential_metatype result must be metatype");
require(resultType.castTo<MetatypeType>()->hasRepresentation(),
"open_existential_metatype result must have a representation");
require(operandType.castTo<ExistentialMetatypeType>()->getRepresentation()
== resultType.castTo<MetatypeType>()->getRepresentation(),
"open_existential_metatype result must match representation of "
"operand");
CanType operandInstTy =
operandType.castTo<ExistentialMetatypeType>().getInstanceType();
CanType resultInstTy =
resultType.castTo<MetatypeType>().getInstanceType();
while (auto operandMetatype =
dyn_cast<ExistentialMetatypeType>(operandInstTy)) {
require(isa<MetatypeType>(resultInstTy),
"metatype depth mismatch in open_existential_metatype result");
operandInstTy = operandMetatype.getInstanceType();
resultInstTy = cast<MetatypeType>(resultInstTy).getInstanceType();
}
require(operandInstTy.isExistentialType(),
"ill-formed existential metatype in open_existential_metatype "
"operand");
auto archetype = getOpenedArchetypeOf(resultInstTy);
require(archetype, "open_existential_metatype result must be an opened "
"existential metatype");
require(
I->getModule().getRootLocalArchetypeDefInst(archetype,
I->getFunction()) == I,
"Archetype opened by open_existential_metatype should be registered in "
"SILFunction");
}
void checkOpenExistentialValueInst(OpenExistentialValueInst *OEI) {
SILType operandType = OEI->getOperand()->getType();
require(!operandType.isAddress(),
"open_existential_value must not be applied to address");
require(operandType.canUseExistentialRepresentation(
ExistentialRepresentation::Opaque),
"open_existential_value must be applied to opaque existential");
require(!OEI->getType().isAddress(),
"open_existential_value result must not be an address");
auto archetype = getOpenedArchetypeOf(OEI->getType().getASTType());
require(archetype, "open_existential_value result must be an opened "
"existential archetype");
require(OEI->getModule().getRootLocalArchetypeDefInst(
archetype, OEI->getFunction()) == OEI,
"Archetype opened by open_existential should be registered in "
"SILFunction");
}
void checkAllocExistentialBoxInst(AllocExistentialBoxInst *AEBI) {
SILType exType = AEBI->getExistentialType();
require(exType.isObject(),
"alloc_existential_box #0 result should be a value");
require(exType.canUseExistentialRepresentation(
ExistentialRepresentation::Boxed,
AEBI->getFormalConcreteType()),
"alloc_existential_box must be used with a boxed existential "
"type");
checkExistentialProtocolConformances(exType.getASTType(),
AEBI->getFormalConcreteType(),
AEBI->getConformances());
verifyLocalArchetype(AEBI, AEBI->getFormalConcreteType());
}
void checkInitExistentialAddrInst(InitExistentialAddrInst *AEI) {
SILType exType = AEI->getOperand()->getType();
require(exType.isAddress(),
"init_existential_addr must be applied to an address");
require(exType.canUseExistentialRepresentation(
ExistentialRepresentation::Opaque,
AEI->getFormalConcreteType()),
"init_existential_addr must be used with an opaque "
"existential type");
// The lowered type must be the properly-abstracted form of the AST type.
auto archetype = OpenedArchetypeType::get(exType.getASTType(),
F.getGenericSignature());
auto loweredTy = F.getLoweredType(Lowering::AbstractionPattern(archetype),
AEI->getFormalConcreteType())
.getAddressType();
requireSameType(loweredTy, AEI->getLoweredConcreteType(),
"init_existential_addr result type must be the lowered "
"concrete type at the right abstraction level");
require(isLoweringOf(AEI->getLoweredConcreteType(),
AEI->getFormalConcreteType()),
"init_existential_addr payload must be a lowering of the formal "
"concrete type");
checkExistentialProtocolConformances(exType.getASTType(),
AEI->getFormalConcreteType(),
AEI->getConformances());
verifyLocalArchetype(AEI, AEI->getFormalConcreteType());
}
void checkInitExistentialValueInst(InitExistentialValueInst *IEI) {
SILType concreteType = IEI->getOperand()->getType();
require(!concreteType.isAddress(),
"init_existential_value must not be used on addresses");
require(!IEI->getType().isAddress(),
"init_existential_value result must not be an address");
// The operand must be at the right abstraction level for the existential.
SILType exType = IEI->getType();
auto archetype = OpenedArchetypeType::get(exType.getASTType(),
F.getGenericSignature());
auto loweredTy = F.getLoweredType(Lowering::AbstractionPattern(archetype),
IEI->getFormalConcreteType());
requireSameType(
concreteType, loweredTy,
"init_existential_value operand must be lowered to the right "
"abstraction level for the existential");
require(isLoweringOf(IEI->getOperand()->getType(),
IEI->getFormalConcreteType()),
"init_existential_value operand must be a lowering of the formal "
"concrete type");
checkExistentialProtocolConformances(exType.getASTType(),
IEI->getFormalConcreteType(),
IEI->getConformances());
verifyLocalArchetype(IEI, IEI->getFormalConcreteType());
}
void checkInitExistentialRefInst(InitExistentialRefInst *IEI) {
SILType concreteType = IEI->getOperand()->getType();
require(concreteType.getASTType()->isBridgeableObjectType(),
"init_existential_ref operand must be a class instance");
require(IEI->getType().canUseExistentialRepresentation(
ExistentialRepresentation::Class,
IEI->getFormalConcreteType()),
"init_existential_ref must be used with a class existential type");
require(IEI->getType().isObject(),
"init_existential_ref result must not be an address");
// The operand must be at the right abstraction level for the existential.
SILType exType = IEI->getType();
auto archetype = OpenedArchetypeType::get(exType.getASTType(),
F.getGenericSignature());
auto loweredTy = F.getLoweredType(Lowering::AbstractionPattern(archetype),
IEI->getFormalConcreteType());
requireSameType(concreteType, loweredTy,
"init_existential_ref operand must be lowered to the right "
"abstraction level for the existential");
require(isLoweringOf(IEI->getOperand()->getType(),
IEI->getFormalConcreteType()),
"init_existential_ref operand must be a lowering of the formal "
"concrete type");
checkExistentialProtocolConformances(exType.getASTType(),
IEI->getFormalConcreteType(),
IEI->getConformances());
verifyLocalArchetype(IEI, IEI->getFormalConcreteType());
}
void checkDeinitExistentialAddrInst(DeinitExistentialAddrInst *DEI) {
SILType exType = DEI->getOperand()->getType();
require(exType.isAddress(),
"deinit_existential_addr must be applied to an address");
require(exType.canUseExistentialRepresentation(
ExistentialRepresentation::Opaque),
"deinit_existential_addr must be applied to an opaque existential");
}
void checkDeinitExistentialValueInst(DeinitExistentialValueInst *DEI) {
SILType exType = DEI->getOperand()->getType();
require(!exType.isAddress(),
"deinit_existential_value must not be applied to an address");
require(
exType.canUseExistentialRepresentation(
ExistentialRepresentation::Opaque),
"deinit_existential_value must be applied to an opaque existential");
}
void checkDeallocExistentialBoxInst(DeallocExistentialBoxInst *DEBI) {
SILType exType = DEBI->getOperand()->getType();
require(exType.isObject(),
"dealloc_existential_box must be applied to a value");
require(exType.canUseExistentialRepresentation(
ExistentialRepresentation::Boxed),
"dealloc_existential_box must be applied to a boxed "
"existential");
}
void checkInitExistentialMetatypeInst(InitExistentialMetatypeInst *I) {
SILType operandType = I->getOperand()->getType();
require(operandType.isObject(),
"init_existential_metatype operand must not be an address");
require(operandType.is<MetatypeType>(),
"init_existential_metatype operand must be a metatype");
require(operandType.castTo<MetatypeType>()->hasRepresentation(),
"init_existential_metatype operand must have a representation");
SILType resultType = I->getType();
require(resultType.is<ExistentialMetatypeType>(),
"init_existential_metatype result must be an existential metatype");
auto MetaTy = resultType.castTo<ExistentialMetatypeType>();
require(resultType.isObject(),
"init_existential_metatype result must not be an address");
require(MetaTy->hasRepresentation(),
"init_existential_metatype result must have a representation");
require(MetaTy->getRepresentation()
== operandType.castTo<MetatypeType>()->getRepresentation(),
"init_existential_metatype result must match representation of "
"operand");
auto resultInstanceType = resultType.getASTType();
auto operandInstanceType = operandType.getASTType();
while (isa<ExistentialMetatypeType>(resultInstanceType)) {
resultInstanceType =
cast<ExistentialMetatypeType>(resultInstanceType).getInstanceType();
operandInstanceType =
cast<MetatypeType>(operandInstanceType).getInstanceType();
}
checkExistentialProtocolConformances(resultInstanceType,
operandInstanceType,
I->getConformances());
verifyLocalArchetype(I, MetaTy.getInstanceType());
}
void checkExistentialProtocolConformances(CanType resultType,
CanType concreteType,
ArrayRef<ProtocolConformanceRef> conformances) {
auto layout = resultType.getExistentialLayout();
auto protocols = layout.getProtocols();
require(conformances.size() == protocols.size(),
"init_existential instruction must have the "
"right number of conformances");
if (layout.requiresClass()) {
require(concreteType->mayHaveSuperclass() ||
(concreteType.isExistentialType() &&
concreteType.getExistentialLayout().requiresClass()),
"init_existential of class existential with non-class type");
}
if (auto superclass = layout.getSuperclass()) {
require(superclass->isExactSuperclassOf(concreteType),
"init_existential of subclass existential with wrong type");
}
for (auto i : indices(conformances)) {
require(conformances[i].getRequirement() == protocols[i]->getDecl(),
"init_existential instruction must have conformances in "
"proper order");
}
}
void verifyCheckedCast(bool isExact, SILType fromTy, SILType toTy) {
// Verify common invariants.
require(fromTy.isObject() && toTy.isObject(),
"value checked cast src and dest must be objects");
auto fromCanTy = fromTy.getASTType();
auto toCanTy = toTy.getASTType();
require(canSILUseScalarCheckedCastInstructions(F.getModule(),
fromCanTy, toCanTy),
"invalid value checked cast src or dest types");
// Peel off metatypes. If two types are checked-cast-able, so are their
// metatypes.
unsigned MetatyLevel = 0;
while (isa<AnyMetatypeType>(fromCanTy) && isa<AnyMetatypeType>(toCanTy)) {
auto fromMetaty = cast<AnyMetatypeType>(fromCanTy);
auto toMetaty = cast<AnyMetatypeType>(toCanTy);
// Check representations only for the top-level metatypes as only
// those are SIL-lowered.
if (!MetatyLevel) {
// The representations must match.
require(fromMetaty->getRepresentation() == toMetaty->getRepresentation(),
"metatype checked cast cannot change metatype representation");
// We can't handle the 'thin' case yet, but it shouldn't really even be
// interesting.
require(fromMetaty->getRepresentation() != MetatypeRepresentation::Thin,
"metatype checked cast cannot check thin metatypes");
}
fromCanTy = fromMetaty.getInstanceType();
toCanTy = toMetaty.getInstanceType();
++MetatyLevel;
}
if (isExact) {
require(fromCanTy.getClassOrBoundGenericClass(),
"downcast operand must be a class type");
require(toCanTy.getClassOrBoundGenericClass(),
"downcast must convert to a class type");
require(fromCanTy->isBindableToSuperclassOf(toCanTy),
"downcast must convert to a subclass");
}
}
void checkUnconditionalCheckedCastInst(UnconditionalCheckedCastInst *CI) {
verifyCheckedCast(/*exact*/ false,
CI->getOperand()->getType(),
CI->getType());
verifyLocalArchetype(CI, CI->getType().getASTType());
}
// Make sure that opcodes handled by isRCIdentityPreservingCast cannot cast
// from a trivial to a reference type. Such a cast may dynamically
// instantiate a new reference-counted object.
void checkNoTrivialToReferenceCast(SingleValueInstruction *svi) {
require(!svi->getOperand(0)->getType().isTrivial(*svi->getFunction())
|| svi->getType().isTrivial(*svi->getFunction()),
"Unexpected trivial-to-reference conversion: ");
}
/// Verify if a given type is or contains a local archetype or dynamic self.
/// If this is the case, verify that the provided instruction has a type
/// dependent operand for it.
void verifyLocalArchetype(SILInstruction *I, CanType Ty) {
if (!Ty)
return;
// Check the type and all of its contained types.
Ty.visit([&](CanType t) {
SILValue Def;
if (const auto archetypeTy = dyn_cast<LocalArchetypeType>(t)) {
Def = I->getModule().getRootLocalArchetypeDefInst(
archetypeTy.getRoot(), I->getFunction());
require(Def, "Root opened archetype should be registered in SILModule");
} else if (t->hasDynamicSelfType()) {
require(I->getFunction()->hasSelfParam() ||
I->getFunction()->hasDynamicSelfMetadata(),
"Function containing dynamic self type must have self parameter");
if (I->getFunction()->hasDynamicSelfMetadata())
Def = I->getFunction()->getDynamicSelfMetadata();
else
Def = I->getFunction()->getSelfArgument();
} else {
return;
}
for (auto &TypeDefOp : I->getTypeDependentOperands()) {
if (TypeDefOp.get() == Def)
return;
}
require(false, "Instruction should contain a type dependent operand for "
"every used open archetype or dynamic self");
});
}
void checkCheckedCastBranchInst(CheckedCastBranchInst *CBI) {
verifyCheckedCast(CBI->isExact(),
CBI->getSourceLoweredType(),
CBI->getTargetLoweredType());
verifyLocalArchetype(CBI, CBI->getTargetFormalType());
require(CBI->getSuccessBB()->args_size() == 1,
"success dest of checked_cast_br must take one argument");
requireSameType(
CBI->getSuccessBB()->args_begin()[0]->getType(),
CBI->getTargetLoweredType(),
"success dest block argument of checked_cast_br must match type of "
"cast");
if (F.hasOwnership()) {
require(CBI->getFailureBB()->args_size() == 1,
"failure dest of checked_cast_br must take one argument in "
"ownership qualified sil");
requireSameType(
CBI->getFailureBB()->args_begin()[0]->getType(),
CBI->getOperand()->getType(),
"failure dest block argument must match type of original type in "
"ownership qualified sil");
auto succOwnershipKind =
CBI->getSuccessBB()->args_begin()[0]->getOwnershipKind();
require(succOwnershipKind.isCompatibleWith(
CBI->getOperand()->getOwnershipKind()),
"succ dest block argument must have ownership compatible with "
"the checked_cast_br operand");
auto failOwnershipKind =
CBI->getFailureBB()->args_begin()[0]->getOwnershipKind();
require(failOwnershipKind.isCompatibleWith(
CBI->getOperand()->getOwnershipKind()),
"failure dest block argument must have ownership compatible with "
"the checked_cast_br operand");
// Do not allow for checked_cast_br to forward guaranteed ownership if the
// source type is an AnyObject.
//
// EXPLANATION: A checked_cast_br from an AnyObject may return a different
// object. This occurs for instance if one has an AnyObject that is a
// boxed AnyHashable (ClassType). This breaks with the guarantees of
// checked_cast_br guaranteed, so we ban it.
require(!CBI->getOperand()->getType().isAnyObject() ||
CBI->getOperand()->getOwnershipKind() !=
OwnershipKind::Guaranteed,
"checked_cast_br with an AnyObject typed source cannot forward "
"guaranteed ownership");
require(CBI->preservesOwnership() ||
CBI->getOperand()->getOwnershipKind() !=
OwnershipKind::Guaranteed,
"If checked_cast_br is not directly forwarding, it can not have "
"guaranteed ownership");
} else {
require(CBI->getFailureBB()->args_empty(),
"Failure dest of checked_cast_br must not take any argument in "
"non-ownership qualified sil");
}
}
void checkCheckedCastAddrBranchInst(CheckedCastAddrBranchInst *CCABI) {
require(CCABI->getSrc()->getType().isAddress(),
"checked_cast_addr_br src must be an address");
require(CCABI->getDest()->getType().isAddress(),
"checked_cast_addr_br dest must be an address");
require(
CCABI->getSuccessBB()->args_size() == 0,
"success dest block of checked_cast_addr_br must not take an argument");
require(
CCABI->getFailureBB()->args_size() == 0,
"failure dest block of checked_cast_addr_br must not take an argument");
}
void checkThinToThickFunctionInst(ThinToThickFunctionInst *TTFI) {
auto opFTy = requireObjectType(SILFunctionType, TTFI->getOperand(),
"thin_to_thick_function operand");
auto resFTy = requireObjectType(SILFunctionType, TTFI,
"thin_to_thick_function result");
require(opFTy->isPolymorphic() == resFTy->isPolymorphic(),
"thin_to_thick_function operand and result type must differ only "
" in thinness");
requireSameFunctionComponents(opFTy, resFTy,
"thin_to_thick_function operand and result");
require(opFTy->getRepresentation() == SILFunctionType::Representation::Thin,
"operand of thin_to_thick_function must be thin");
require(resFTy->getRepresentation() == SILFunctionType::Representation::Thick,
"result of thin_to_thick_function must be thick");
auto adjustedOperandExtInfo =
opFTy->getExtInfo()
.intoBuilder()
.withRepresentation(SILFunctionType::Representation::Thick)
.withNoEscape(resFTy->isNoEscape())
.build();
require(adjustedOperandExtInfo.isEqualTo(resFTy->getExtInfo(),
useClangTypes(opFTy)),
"operand and result of thin_to_think_function must agree in "
"particulars");
}
void checkThickToObjCMetatypeInst(ThickToObjCMetatypeInst *TTOCI) {
auto opTy = requireObjectType(AnyMetatypeType, TTOCI->getOperand(),
"thick_to_objc_metatype operand");
auto resTy = requireObjectType(AnyMetatypeType, TTOCI,
"thick_to_objc_metatype result");
require(TTOCI->getOperand()->getType().is<MetatypeType>() ==
TTOCI->getType().is<MetatypeType>(),
"thick_to_objc_metatype cannot change metatype kinds");
require(opTy->getRepresentation() == MetatypeRepresentation::Thick,
"operand of thick_to_objc_metatype must be thick");
require(resTy->getRepresentation() == MetatypeRepresentation::ObjC,
"operand of thick_to_objc_metatype must be ObjC");
requireSameType(opTy->getInstanceType(), resTy->getInstanceType(),
"thick_to_objc_metatype instance types do not match");
}
void checkObjCToThickMetatypeInst(ObjCToThickMetatypeInst *OCTTI) {
auto opTy = requireObjectType(AnyMetatypeType, OCTTI->getOperand(),
"objc_to_thick_metatype operand");
auto resTy = requireObjectType(AnyMetatypeType, OCTTI,
"objc_to_thick_metatype result");
require(OCTTI->getOperand()->getType().is<MetatypeType>() ==
OCTTI->getType().is<MetatypeType>(),
"objc_to_thick_metatype cannot change metatype kinds");
require(opTy->getRepresentation() == MetatypeRepresentation::ObjC,
"operand of objc_to_thick_metatype must be ObjC");
require(resTy->getRepresentation() == MetatypeRepresentation::Thick,
"operand of objc_to_thick_metatype must be thick");
requireSameType(opTy->getInstanceType(), resTy->getInstanceType(),
"objc_to_thick_metatype instance types do not match");
}
void checkUpcastInst(UpcastInst *UI) {
require(UI->getType() != UI->getOperand()->getType(),
"can't upcast to same type");
require(UI->getType().isObject(), "cannot upcast address types");
require(UI->getOperand()->getType().isMoveOnlyWrapped() ==
UI->getType().isMoveOnlyWrapped(),
"cast cannot be used to remove move only wrapped?!");
checkNoTrivialToReferenceCast(UI);
if (UI->getType().is<MetatypeType>()) {
CanType instTy(UI->getType().castTo<MetatypeType>()->getInstanceType());
require(UI->getOperand()->getType().is<MetatypeType>(),
"upcast operand must be a class or class metatype instance");
CanType opInstTy(UI->getOperand()->getType().castTo<MetatypeType>()
->getInstanceType());
auto instClass = instTy->getClassOrBoundGenericClass();
require(instClass,
"upcast must convert a class metatype to a class metatype");
if (instClass->isTypeErasedGenericClass()) {
require(instClass->getDeclaredTypeInContext()
->isBindableToSuperclassOf(opInstTy),
"upcast must cast to a superclass or an existential metatype");
} else {
require(instTy->isExactSuperclassOf(opInstTy),
"upcast must cast to a superclass or an existential metatype");
}
return;
}
require(UI->getType().getCategory() ==
UI->getOperand()->getType().getCategory(),
"Upcast can only upcast in between types of the same "
"SILValueCategory. This prevents address types from being cast to "
"object types or vis-a-versa");
auto ToTy = UI->getType();
auto FromTy = UI->getOperand()->getType();
// Upcast from Optional<B> to Optional<A> is legal as long as B is a
// subclass of A.
if (ToTy.getASTType().getOptionalObjectType() &&
FromTy.getASTType().getOptionalObjectType()) {
ToTy = SILType::getPrimitiveObjectType(
ToTy.getASTType().getOptionalObjectType());
FromTy = SILType::getPrimitiveObjectType(
FromTy.getASTType().getOptionalObjectType());
}
auto ToClass = ToTy.getClassOrBoundGenericClass();
require(ToClass,
"upcast must convert a class instance to a class type");
if (ToClass->isTypeErasedGenericClass()) {
require(ToClass->getDeclaredTypeInContext()
->isBindableToSuperclassOf(FromTy.getASTType()),
"upcast must cast to a superclass or an existential metatype");
} else {
require(ToTy.isExactSuperclassOf(FromTy),
"upcast must cast to a superclass or an existential metatype");
}
}
void checkAddressToPointerInst(AddressToPointerInst *AI) {
require(AI->getOperand()->getType().isAddress(),
"address-to-pointer operand must be an address");
require(AI->getType().getASTType()->isEqual(
AI->getType().getASTContext().TheRawPointerType),
"address-to-pointer result type must be RawPointer");
}
void checkUncheckedRefCastInst(UncheckedRefCastInst *AI) {
verifyLocalArchetype(AI, AI->getType().getASTType());
require(AI->getOperand()->getType().isObject(),
"unchecked_ref_cast operand must be a value");
require(AI->getType().isObject(),
"unchecked_ref_cast result must be an object");
require(SILType::canRefCast(AI->getOperand()->getType(), AI->getType(),
AI->getModule()),
"unchecked_ref_cast requires a heap object reference type");
}
void checkUncheckedRefCastAddrInst(UncheckedRefCastAddrInst *AI) {
auto srcTy = AI->getSrc()->getType();
auto destTy = AI->getDest()->getType();
require(srcTy.isAddress(),
"unchecked_ref_cast_addr operand must be an address");
require(destTy.isAddress(),
"unchecked_ref_cast_addr result must be an address");
// The static src/dest types cannot be checked here even if they are
// loadable. unchecked_ref_cast_addr may accept nonreference static types
// (as a result of specialization). These cases will never be promoted to
// value bitcast, thus will cause the subsequent runtime cast to fail.
}
void checkUncheckedAddrCastInst(UncheckedAddrCastInst *AI) {
verifyLocalArchetype(AI, AI->getType().getASTType());
require(AI->getOperand()->getType().isAddress(),
"unchecked_addr_cast operand must be an address");
require(AI->getType().isAddress(),
"unchecked_addr_cast result must be an address");
require(AI->getOperand()->getType().isMoveOnlyWrapped() ==
AI->getType().isMoveOnlyWrapped(),
"Unchecked addr cast cannot be used to remove move only wrapped?!");
}
void checkUncheckedTrivialBitCastInst(UncheckedTrivialBitCastInst *BI) {
verifyLocalArchetype(BI, BI->getType().getASTType());
require(BI->getOperand()->getType().isObject(),
"unchecked_trivial_bit_cast must operate on a value");
require(BI->getType().isObject(),
"unchecked_trivial_bit_cast must produce a value");
require(BI->getType().isTrivial(F),
"unchecked_trivial_bit_cast must produce a value of trivial type");
require(BI->getOperand()->getType().isMoveOnlyWrapped() ==
BI->getType().isMoveOnlyWrapped(),
"cast cannot be used to remove move only wrapped?!");
}
void checkUncheckedBitwiseCastInst(UncheckedBitwiseCastInst *BI) {
verifyLocalArchetype(BI, BI->getType().getASTType());
require(BI->getOperand()->getType().isObject(),
"unchecked_bitwise_cast must operate on a value");
require(BI->getType().isObject(),
"unchecked_bitwise_cast must produce a value");
require(BI->getOperand()->getType().isMoveOnlyWrapped() ==
BI->getType().isMoveOnlyWrapped(),
"cast cannot be used to remove move only wrapped?!");
}
void checkRefToRawPointerInst(RefToRawPointerInst *AI) {
require(AI->getOperand()->getType().isAnyClassReferenceType(),
"ref-to-raw-pointer operand must be a class reference or"
" NativeObject");
requireSameType(AI->getType().getASTType(),
AI->getType().getASTContext().TheRawPointerType,
"ref-to-raw-pointer result must be RawPointer");
}
void checkRawPointerToRefInst(RawPointerToRefInst *AI) {
verifyLocalArchetype(AI, AI->getType().getASTType());
require(AI->getType()
.getASTType()->isBridgeableObjectType()
|| AI->getType().getASTType()->isEqual(
AI->getType().getASTContext().TheNativeObjectType),
"raw-pointer-to-ref result must be a class reference or NativeObject");
requireSameType(AI->getOperand()->getType().getASTType(),
AI->getType().getASTContext().TheRawPointerType,
"raw-pointer-to-ref operand must be NativeObject");
}
void checkRefToBridgeObjectInst(RefToBridgeObjectInst *RI) {
require(RI->getOperand(0)->getType().isObject(),
"ref_to_bridge_object must convert from a value");
require(RI->getOperand(0)->getType().getASTType()->isBridgeableObjectType(),
"ref_to_bridge_object must convert from a heap object ref");
requireSameType(
RI->getBitsOperand()->getType(),
SILType::getBuiltinWordType(F.getASTContext()),
"ref_to_bridge_object must take a Builtin.Word bits operand");
requireSameType(RI->getType(),
SILType::getBridgeObjectType(F.getASTContext()),
"ref_to_bridge_object must produce a BridgeObject");
}
void checkBridgeObjectToRefInst(BridgeObjectToRefInst *RI) {
verifyLocalArchetype(RI, RI->getType().getASTType());
requireSameType(RI->getOperand()->getType(),
SILType::getBridgeObjectType(F.getASTContext()),
"bridge_object_to_ref must take a BridgeObject");
require(RI->getType().isObject(),
"bridge_object_to_ref must produce a value");
require(RI->getType().getASTType()->isBridgeableObjectType(),
"bridge_object_to_ref must produce a heap object reference");
}
void checkBridgeObjectToWordInst(BridgeObjectToWordInst *RI) {
requireSameType(RI->getOperand()->getType(),
SILType::getBridgeObjectType(F.getASTContext()),
"bridge_object_to_word must take a BridgeObject");
require(RI->getType().isObject(),
"bridge_object_to_word must produce a value");
requireSameType(RI->getType(),
SILType::getBuiltinWordType(F.getASTContext()),
"bridge_object_to_word must produce a Word");
}
void checkConvertFunctionInst(ConvertFunctionInst *ICI) {
auto opTI = requireObjectType(SILFunctionType, ICI->getOperand(),
"convert_function operand");
auto resTI = requireObjectType(SILFunctionType, ICI,
"convert_function result");
// convert_function is required to be an ABI-compatible conversion.
requireABICompatibleFunctionTypes(
opTI, resTI, "convert_function cannot change function ABI",
*ICI->getFunction());
}
void checkConvertEscapeToNoEscapeInst(ConvertEscapeToNoEscapeInst *ICI) {
auto opTI = requireObjectType(SILFunctionType, ICI->getOperand(),
"convert_escape_to_noescape operand");
auto resTI = ICI->getType().castTo<SILFunctionType>();
// FIXME: Not yet, to be enabled when this is true.
// require(resTI->isTrivial(F.getModule()),
// "convert_escape_to_noescape should produce a trivial result type");
// convert_escape_to_noescape is required to be an ABI-compatible
// conversion once escapability is the same on both sides.
requireABICompatibleFunctionTypes(
opTI, resTI->getWithExtInfo(resTI->getExtInfo().withNoEscape(false)),
"convert_escape_to_noescape cannot change function ABI",
*ICI->getFunction());
// After mandatory passes convert_escape_to_noescape should not have the
// '[not_guaranteed]' or '[escaped]' attributes.
if (!SkipConvertEscapeToNoescapeAttributes &&
F.getModule().getStage() != SILStage::Raw) {
require(ICI->isLifetimeGuaranteed(),
"convert_escape_to_noescape [not_guaranteed] not "
"allowed after mandatory passes");
}
}
void checkCondFailInst(CondFailInst *CFI) {
requireSameType(CFI->getOperand()->getType(),
SILType::getBuiltinIntegerType(1, F.getASTContext()),
"cond_fail operand must be a Builtin.Int1");
}
void checkReturnInst(ReturnInst *RI) {
LLVM_DEBUG(RI->print(llvm::dbgs()));
SILType functionResultType =
F.getLoweredType(F.mapTypeIntoContext(fnConv.getSILResultType(
F.getTypeExpansionContext()))
.getASTType())
.getCategoryType(
fnConv.getSILResultType(F.getTypeExpansionContext())
.getCategory());
SILType instResultType = RI->getOperand()->getType();
LLVM_DEBUG(llvm::dbgs() << "function return type: ";
functionResultType.dump();
llvm::dbgs() << "return inst type: ";
instResultType.dump(););
requireSameType(functionResultType, instResultType,
"return value type does not match return type of function");
}
void checkThrowInst(ThrowInst *TI) {
LLVM_DEBUG(TI->print(llvm::dbgs()));
require(fnConv.funcTy->hasErrorResult(),
"throw in function that doesn't have an error result");
SILType functionResultType =
F.getLoweredType(F.mapTypeIntoContext(fnConv.getSILErrorType(
F.getTypeExpansionContext()))
.getASTType())
.getCategoryType(fnConv.getSILErrorType(F.getTypeExpansionContext())
.getCategory());
SILType instResultType = TI->getOperand()->getType();
LLVM_DEBUG(llvm::dbgs() << "function error result type: ";
functionResultType.dump();
llvm::dbgs() << "throw operand type: ";
instResultType.dump(););
requireSameType(
functionResultType, instResultType,
"throw operand type does not match error result type of function");
}
void checkUnwindInst(UnwindInst *UI) {
require(F.getLoweredFunctionType()->isCoroutine(),
"unwind in non-coroutine function");
}
void checkYieldInst(YieldInst *YI) {
require(fnConv.funcTy->isCoroutine(),
"yield in non-coroutine function");
auto yieldedValues = YI->getYieldedValues();
auto yieldInfos = fnConv.funcTy->getYields();
require(yieldedValues.size() == yieldInfos.size(),
"wrong number of yielded values for function");
for (auto i : indices(yieldedValues)) {
SILType yieldType = F.mapTypeIntoContext(
fnConv.getSILType(yieldInfos[i], F.getTypeExpansionContext()));
requireSameType(yieldedValues[i]->getType(), yieldType,
"yielded value does not match yield type of coroutine");
}
// We require the resume and unwind destinations to be unique in order
// to prevent either edge from becoming critical.
require(YI->getResumeBB()->getSinglePredecessorBlock(),
"resume dest of 'yield' must be uniquely used");
require(YI->getUnwindBB()->getSinglePredecessorBlock(),
"unwind dest of 'yield' must be uniquely used");
}
void checkSelectEnumCases(SelectEnumOperation SEO) {
EnumDecl *eDecl =
SEO.getEnumOperand()->getType().getEnumOrBoundGenericEnum();
require(eDecl, "select_enum operand must be an enum");
// Find the set of enum elements for the type so we can verify
// exhaustiveness.
llvm::DenseSet<EnumElementDecl*> unswitchedElts;
eDecl->getAllElements(unswitchedElts);
// Verify the set of enum cases we dispatch on.
for (unsigned i = 0, e = SEO.getNumCases(); i < e; ++i) {
EnumElementDecl *elt;
SILValue result;
std::tie(elt, result) = SEO.getCase(i);
require(elt->getDeclContext() == eDecl,
"select_enum dispatches on enum element that is not part of "
"its type");
require(unswitchedElts.count(elt),
"select_enum dispatches on same enum element more than once");
unswitchedElts.erase(elt);
// The result value must match the type of the instruction.
requireSameType(
result->getType(), SEO->getType(),
"select_enum case operand must match type of instruction");
// In canonical SIL, select instructions must not cover any enum elements
// that are unavailable.
if (F.getModule().getStage() >= SILStage::Canonical) {
require(elt->isAvailableDuringLowering(),
"select_enum dispatches on enum element that is unavailable "
"during lowering.");
}
}
// If the select is non-exhaustive, we require a default.
bool isExhaustive =
eDecl->isEffectivelyExhaustive(F.getModule().getSwiftModule(),
F.getResilienceExpansion());
require((isExhaustive && unswitchedElts.empty()) || SEO.hasDefault(),
"nonexhaustive select_:enum must have a default destination");
if (SEO.hasDefault()) {
requireSameType(
SEO.getDefaultResult()->getType(), SEO->getType(),
"select_enum default operand must match type of instruction");
}
}
void checkSelectEnumInst(SelectEnumInst *SEI) {
require(SEI->getEnumOperand()->getType().isObject(),
"select_enum operand must be an object");
// A non-trivial select_enum would result in leaking whatever cases were not
// selected.
require(SEI->getType().isTrivial(SEI->getFunction()),
"select_enum type must be trivial");
checkSelectEnumCases(SelectEnumOperation(SEI));
}
void checkSelectEnumAddrInst(SelectEnumAddrInst *SEI) {
require(SEI->getEnumOperand()->getType().isAddress(),
"select_enum_addr operand must be an address");
checkSelectEnumCases(SelectEnumOperation(SEI));
}
void checkSwitchValueInst(SwitchValueInst *SVI) {
// TODO: Type should be either integer or function
auto Ty = SVI->getOperand()->getType();
require(Ty.is<BuiltinIntegerType>() || Ty.is<SILFunctionType>(),
"switch_value operand should be either of an integer "
"or function type");
auto ult = [](const SILValue &a, const SILValue &b) {
return a == b || a < b;
};
std::set<SILValue, decltype(ult)> cases(ult);
for (unsigned i = 0, e = SVI->getNumCases(); i < e; ++i) {
SILValue value;
SILBasicBlock *dest;
std::tie(value, dest) = SVI->getCase(i);
requireSameType(
value->getType(), Ty,
"switch_value case value should have the same type as its operand");
require(!cases.count(value),
"multiple switch_value cases for same value");
cases.insert(value);
require(dest->args_empty(),
"switch_value case destination cannot take arguments");
}
if (SVI->hasDefault())
require(SVI->getDefaultBB()->args_empty(),
"switch_value default destination cannot take arguments");
}
void checkSwitchEnumInst(SwitchEnumInst *switchEnum) {
require(switchEnum->getOperand()->getType().isObject(),
"switch_enum operand must be an object");
SILType uTy = switchEnum->getOperand()->getType();
EnumDecl *uDecl = uTy.getEnumOrBoundGenericEnum();
require(uDecl, "switch_enum operand is not an enum");
// Find the set of enum elements for the type so we can verify
// exhaustiveness.
llvm::DenseSet<EnumElementDecl*> unswitchedElts;
auto checkSwitchCase = [&](EnumElementDecl *elt, SILBasicBlock *dest) {
require(elt->getDeclContext() == uDecl,
"switch_enum dispatches on enum element that is not part of "
"its type");
require(unswitchedElts.insert(elt).second,
"switch_enum dispatches on same enum element more than once");
if (!elt->hasAssociatedValues()) {
require(dest->getArguments().empty(),
"switch_enum destination for no-argument case must take no "
"arguments");
return;
}
// In canonical SIL, switch instructions must not cover any enum elements
// that are unavailable.
if (F.getModule().getStage() >= SILStage::Canonical) {
require(elt->isAvailableDuringLowering(),
"switch_enum dispatches on enum element that is unavailable "
"during lowering.");
}
// Check for a valid switch result type.
if (dest->getArguments().size() == 1) {
SILType eltArgTy = uTy.getEnumElementType(elt, F.getModule(),
F.getTypeExpansionContext());
SILType bbArgTy = dest->getArguments()[0]->getType();
if (F.getModule().getStage() != SILStage::Lowered) {
// During the lowered stage, a function type might have different
// signature
//
// We allow for move only wrapped enums to have trivial payloads that
// are not move only wrapped. This occurs since we want to lower
// trivial move only wrapped types earlier in the pipeline than
// non-trivial types.
if (bbArgTy.isTrivial(F)) {
require(eltArgTy == bbArgTy.copyingMoveOnlyWrapper(eltArgTy),
"switch_enum destination bbarg must match case arg type");
} else {
require(eltArgTy == bbArgTy,
"switch_enum destination bbarg must match case arg type");
}
}
require(!dest->getArguments()[0]->getType().isAddress(),
"switch_enum destination bbarg type must not be an address");
}
if (!isSILOwnershipEnabled() || !F.hasOwnership()) {
// In non-OSSA, the destBB can optionally ignore the payload.
require(dest->getArguments().empty()
|| dest->getArguments().size() == 1,
"switch_enum destination for case w/ args must take 0 or 1 "
"arguments");
return;
}
checkForwardedTermResult(switchEnum, dest);
};
// Verify the set of enum cases we dispatch on.
for (unsigned i = 0, e = switchEnum->getNumCases(); i < e; ++i) {
EnumElementDecl *elt;
SILBasicBlock *dest;
std::tie(elt, dest) = switchEnum->getCase(i);
checkSwitchCase(elt, dest);
}
// If the switch is non-exhaustive, we require a default.
if (!switchEnum->hasDefault()) {
bool isExhaustive = uDecl->isEffectivelyExhaustive(
F.getModule().getSwiftModule(), F.getResilienceExpansion());
require(isExhaustive
&& (unswitchedElts.size() == uDecl->getNumElements()),
"nonexhaustive switch_enum must have a default destination");
return;
}
auto *defaultBB = switchEnum->getDefaultBB();
if (!isSILOwnershipEnabled() || !F.hasOwnership()) {
require(switchEnum->getDefaultBB()->args_empty(),
"switch_enum default destination must take no arguments");
return;
}
// When the switch has a unique default case, the OSSA result has the same
// requirements as a matched result.
if (NullablePtr<EnumElementDecl> uniqueCase =
switchEnum->getUniqueCaseForDefault()) {
checkSwitchCase(uniqueCase.get(), defaultBB);
return;
}
// With no unique case, the switch_enum operand is simply forwarded.
require(defaultBB->getNumArguments() == 1,
"Switch enum default block should have one argument");
requireSameType(
defaultBB->getArgument(0)->getType(),
switchEnum->getOperand()->getType(),
"Switch enum default block should have one argument that is "
"the same as the input type");
require(defaultBB->getArgument(0)->getOwnershipKind()
== switchEnum->getForwardingOwnershipKind(),
"switch_enum non-trivial destination arg must have the same "
"ownership as switch_enum's operand");
}
void checkSwitchEnumAddrInst(SwitchEnumAddrInst *SOI) {
require(SOI->getOperand()->getType().isAddress(),
"switch_enum_addr operand must be an address");
SILType uTy = SOI->getOperand()->getType();
EnumDecl *uDecl = uTy.getEnumOrBoundGenericEnum();
require(uDecl, "switch_enum_addr operand must be an enum");
// Find the set of enum elements for the type so we can verify
// exhaustiveness.
llvm::DenseSet<EnumElementDecl*> unswitchedElts;
uDecl->getAllElements(unswitchedElts);
// Verify the set of enum cases we dispatch on.
for (unsigned i = 0, e = SOI->getNumCases(); i < e; ++i) {
EnumElementDecl *elt;
SILBasicBlock *dest;
std::tie(elt, dest) = SOI->getCase(i);
require(elt->getDeclContext() == uDecl,
"switch_enum_addr dispatches on enum element that "
"is not part of its type");
require(unswitchedElts.count(elt),
"switch_enum_addr dispatches on same enum element "
"more than once");
unswitchedElts.erase(elt);
// In canonical SIL, switch instructions must not cover any enum elements
// that are unavailable.
if (F.getModule().getStage() >= SILStage::Canonical) {
require(elt->isAvailableDuringLowering(),
"switch_enum_addr dispatches on enum element that is "
"unavailable during lowering.");
}
// The destination BB must not have BB arguments.
require(dest->getArguments().empty(),
"switch_enum_addr destination must take no BB args");
}
// If the switch is non-exhaustive, we require a default.
bool isExhaustive =
uDecl->isEffectivelyExhaustive(F.getModule().getSwiftModule(),
F.getResilienceExpansion());
require((isExhaustive && unswitchedElts.empty()) || SOI->hasDefault(),
"nonexhaustive switch_enum_addr must have a default destination");
if (SOI->hasDefault())
require(SOI->getDefaultBB()->args_empty(),
"switch_enum_addr default destination must take "
"no arguments");
}
bool verifyBranchArgs(SILValue branchArg, SILArgument *bbArg) {
// NOTE: IRGen currently does not support the following method_inst
// variants as branch arguments.
// Once this is supported, the check can be removed.
require(!(isa<MethodInst>(branchArg) &&
cast<MethodInst>(branchArg)->getMember().isForeign),
"branch argument cannot be a witness_method or an objc method_inst");
require(!(branchArg->getType().is<SILFunctionType>() &&
branchArg->getType()
.castTo<SILFunctionType>()
->getExtInfo()
.getRepresentation() ==
SILFunctionTypeRepresentation::ObjCMethod),
"branch argument cannot be a objective-c method");
return branchArg->getType() == bbArg->getType();
}
void checkBranchInst(BranchInst *BI) {
require(BI->getArgs().size() == BI->getDestBB()->args_size(),
"branch has wrong number of arguments for dest bb");
require(std::equal(BI->getArgs().begin(), BI->getArgs().end(),
BI->getDestBB()->args_begin(),
[&](SILValue branchArg, SILArgument *bbArg) {
return verifyBranchArgs(branchArg, bbArg);
}),
"branch argument types do not match arguments for dest bb");
}
void checkCondBranchInst(CondBranchInst *cbi) {
// It is important that cond_br keeps an i1 type. ARC Sequence Opts assumes
// that cond_br does not use reference counted values or decrement reference
// counted values under the assumption that the instruction that computes
// the i1 is the use/decrement that ARC cares about and that after that
// instruction is evaluated, the scalar i1 has a different identity and the
// object can be deallocated.
requireSameType(cbi->getCondition()->getType(),
SILType::getBuiltinIntegerType(
1, cbi->getCondition()->getType().getASTContext()),
"condition of conditional branch must have Int1 type");
require(cbi->getTrueArgs().size() == cbi->getTrueBB()->args_size(),
"true branch has wrong number of arguments for dest bb");
require(cbi->getTrueBB() != cbi->getFalseBB(), "identical destinations");
require(std::equal(cbi->getTrueArgs().begin(), cbi->getTrueArgs().end(),
cbi->getTrueBB()->args_begin(),
[&](SILValue branchArg, SILArgument *bbArg) {
return verifyBranchArgs(branchArg, bbArg);
}),
"true branch argument types do not match arguments for dest bb");
require(cbi->getFalseArgs().size() == cbi->getFalseBB()->args_size(),
"false branch has wrong number of arguments for dest bb");
require(std::equal(cbi->getFalseArgs().begin(), cbi->getFalseArgs().end(),
cbi->getFalseBB()->args_begin(),
[&](SILValue branchArg, SILArgument *bbArg) {
return verifyBranchArgs(branchArg, bbArg);
}),
"false branch argument types do not match arguments for dest bb");
// When we are in ossa, cond_br can not have any arguments that are
// non-trivial.
if (!F.hasOwnership())
return;
require(llvm::all_of(cbi->getOperandValues(),
[&](SILValue v) -> bool {
return v->getType().isTrivial(*cbi->getFunction());
}),
"cond_br must not have a non-trivial value in ossa.");
}
void checkDynamicMethodBranchInst(DynamicMethodBranchInst *DMBI) {
SILType operandType = DMBI->getOperand()->getType();
require(DMBI->getMember().getDecl()->isObjC(), "method must be @objc");
if (!DMBI->getMember().getDecl()->isInstanceMember()) {
require(operandType.is<MetatypeType>(),
"operand must have metatype type");
require(operandType.castTo<MetatypeType>()
->getInstanceType()->mayHaveSuperclass(),
"operand must have metatype of class or class-bound type");
}
// Check that the branch argument is of the expected dynamic method type.
require(DMBI->getHasMethodBB()->args_size() == 1,
"true bb for dynamic_method_br must take an argument");
auto bbArgTy = DMBI->getHasMethodBB()->args_begin()[0]->getType();
require(verifyDynamicMethodType(cast<SILFunctionType>(bbArgTy.getASTType()),
operandType, DMBI->getMember()),
"bb argument for dynamic_method_br must be of the method's type");
}
void checkProjectBlockStorageInst(ProjectBlockStorageInst *PBSI) {
require(PBSI->getOperand()->getType().isAddress(),
"operand must be an address");
auto storageTy = PBSI->getOperand()->getType().getAs<SILBlockStorageType>();
require(storageTy, "operand must be a @block_storage type");
require(PBSI->getType().isAddress(),
"result must be an address");
auto captureTy = PBSI->getType().getASTType();
requireSameType(
storageTy->getCaptureType(), captureTy,
"result must be the capture type of the @block_storage type");
}
void checkInitBlockStorageHeaderInst(InitBlockStorageHeaderInst *IBSHI) {
auto storage = IBSHI->getBlockStorage();
require(storage->getType().isAddress(),
"block storage operand must be an address");
auto storageTy = storage->getType().getAs<SILBlockStorageType>();
require(storageTy, "block storage operand must be a @block_storage type");
auto captureTy = storageTy->getCaptureType();
if (auto capturedFnTy = captureTy->getAs<SILFunctionType>()) {
if (capturedFnTy->isNoEscape()) {
// If the capture is a noescape function then it must be possible to
// locally determine the value stored to initialize the storage for the
// capture. This is required to diagnose static exclusivity violations
// when a noescape closure is converted to a noescape block that
// is then passed to a function.
auto *storageProjection =
storage->getSingleUserOfType<ProjectBlockStorageInst>();
require(storageProjection,
"block storage operand with noescape capture must have "
"projection from block");
auto *storeInst = storageProjection->getSingleUserOfType<StoreInst>();
require(storeInst,
"block storage operand with noescape capture must have "
"store to projection");
}
}
require(IBSHI->getInvokeFunction()->getType().isObject(),
"invoke function operand must be a value");
auto invokeTy
= IBSHI->getInvokeFunction()->getType().getAs<SILFunctionType>();
require(invokeTy, "invoke function operand must be a function");
require(invokeTy->getRepresentation()
== SILFunctionType::Representation::CFunctionPointer,
"invoke function operand must be a c function");
require(invokeTy->getParameters().size() >= 1,
"invoke function must take at least one parameter");
require(!invokeTy->getInvocationGenericSignature() ||
invokeTy->getExtInfo().isPseudogeneric(),
"invoke function must not take reified generic parameters");
invokeTy = checkApplySubstitutions(IBSHI->getSubstitutions(),
SILType::getPrimitiveObjectType(invokeTy));
auto storageParam = invokeTy->getParameters()[0];
require(storageParam.getConvention() ==
ParameterConvention::Indirect_InoutAliasable,
"invoke function must take block storage as @inout_aliasable "
"parameter");
requireSameType(
storageParam.getArgumentType(F.getModule(), invokeTy,
F.getTypeExpansionContext()),
storageTy,
"invoke function must take block storage type as first parameter");
require(IBSHI->getType().isObject(), "result must be a value");
auto blockTy = IBSHI->getType().getAs<SILFunctionType>();
require(blockTy, "result must be a function");
require(blockTy->getRepresentation() == SILFunctionType::Representation::Block,
"result must be a cdecl block function");
require(blockTy->getResults() == invokeTy->getResults(),
"result must have same results as invoke function");
require(blockTy->getParameters().size() + 1
== invokeTy->getParameters().size(),
"result must match all parameters of invoke function but the first");
auto blockParams = blockTy->getParameters();
auto invokeBlockParams = invokeTy->getParameters().slice(1);
for (unsigned i : indices(blockParams)) {
require(blockParams[i] == invokeBlockParams[i],
"result must match all parameters of invoke function but the first");
}
}
void checkHopToExecutorInst(HopToExecutorInst *HI) {
auto executor = HI->getTargetExecutor();
if (HI->getModule().getStage() == SILStage::Lowered) {
requireOptionalExecutorType(executor,
"hop_to_executor operand in lowered SIL");
}
}
void checkExtractExecutorInst(ExtractExecutorInst *EEI) {
if (EEI->getModule().getStage() == SILStage::Lowered) {
require(false,
"extract_executor instruction should have been lowered away");
}
}
void checkObjCProtocolInst(ObjCProtocolInst *OPI) {
require(OPI->getProtocol()->isObjC(),
"objc_protocol must be applied to an @objc protocol");
auto classTy = OPI->getType();
require(classTy.isObject(), "objc_protocol must produce a value");
auto classDecl = classTy.getClassOrBoundGenericClass();
require(classDecl, "objc_protocol must produce a class instance");
require(classDecl->getName() == F.getASTContext().Id_Protocol,
"objc_protocol must produce an instance of ObjectiveC.Protocol class");
require(classDecl->getModuleContext()->getName() == F.getASTContext().Id_ObjectiveC,
"objc_protocol must produce an instance of ObjectiveC.Protocol class");
}
void checkObjCMetatypeToObjectInst(ObjCMetatypeToObjectInst *OMOI) {
require(OMOI->getOperand()->getType().isObject(),
"objc_metatype_to_object must take a value");
auto fromMetaTy = OMOI->getOperand()->getType().getAs<MetatypeType>();
require(fromMetaTy, "objc_metatype_to_object must take an @objc metatype value");
require(fromMetaTy->getRepresentation() == MetatypeRepresentation::ObjC,
"objc_metatype_to_object must take an @objc metatype value");
require(OMOI->getType().isObject(),
"objc_metatype_to_object must produce a value");
require(OMOI->getType().getASTType()->isAnyObject(),
"objc_metatype_to_object must produce an AnyObject value");
}
void checkObjCExistentialMetatypeToObjectInst(
ObjCExistentialMetatypeToObjectInst *OMOI) {
require(OMOI->getOperand()->getType().isObject(),
"objc_metatype_to_object must take a value");
auto fromMetaTy = OMOI->getOperand()->getType()
.getAs<ExistentialMetatypeType>();
require(fromMetaTy, "objc_metatype_to_object must take an @objc existential metatype value");
require(fromMetaTy->getRepresentation() == MetatypeRepresentation::ObjC,
"objc_metatype_to_object must take an @objc existential metatype value");
require(OMOI->getType().isObject(),
"objc_metatype_to_object must produce a value");
require(OMOI->getType().getASTType()->isAnyObject(),
"objc_metatype_to_object must produce an AnyObject value");
}
void checkKeyPathInst(KeyPathInst *KPI) {
auto kpTy = KPI->getType();
require(kpTy.isObject(), "keypath result must be an object type");
auto *kpBGT = KPI->getKeyPathType();
require(kpBGT, "keypath result must be a generic type");
require(kpBGT->isKeyPath() ||
kpBGT->isWritableKeyPath() ||
kpBGT->isReferenceWritableKeyPath(),
"keypath result must be a key path type");
auto baseTy = CanType(kpBGT->getGenericArgs()[0]);
auto pattern = KPI->getPattern();
SubstitutionMap patternSubs = KPI->getSubstitutions();
requireSameType(
F.getLoweredType(baseTy).getASTType(),
F.getLoweredType(
pattern->getRootType().subst(patternSubs)->getCanonicalType()).getASTType(),
"keypath root type should match root type of keypath pattern");
auto leafTy = CanType(kpBGT->getGenericArgs()[1]);
requireSameType(
F.getLoweredType(leafTy).getASTType(),
F.getLoweredType(
pattern->getValueType().subst(patternSubs)->getCanonicalType())
.getASTType(),
"keypath value type should match value type of keypath pattern");
{
for (auto &component : pattern->getComponents()) {
bool hasIndices;
switch (component.getKind()) {
case KeyPathPatternComponent::Kind::GettableProperty:
case KeyPathPatternComponent::Kind::SettableProperty:
hasIndices = !component.getSubscriptIndices().empty();
break;
case KeyPathPatternComponent::Kind::StoredProperty:
case KeyPathPatternComponent::Kind::OptionalChain:
case KeyPathPatternComponent::Kind::OptionalWrap:
case KeyPathPatternComponent::Kind::OptionalForce:
case KeyPathPatternComponent::Kind::TupleElement:
hasIndices = false;
break;
}
verifyKeyPathComponent(F.getModule(),
F.getTypeExpansionContext(),
F.getSerializedKind(),
[&](bool reqt, StringRef message) { _require(reqt, message); },
baseTy,
leafTy,
component,
KPI->getPatternOperands(),
KPI->getPattern()->getGenericSignature(),
KPI->getSubstitutions(),
/*property descriptor*/false,
hasIndices);
}
}
requireSameType(
F.getLoweredType(CanType(baseTy)).getASTType(),
F.getLoweredType(CanType(leafTy)).getASTType(),
"final component should match leaf value type of key path type");
}
void checkIsEscapingClosureInst(IsEscapingClosureInst *IEC) {
// The closure operand is allowed to be an optional closure.
auto operandType = IEC->getOperand()->getType();
if (operandType.getOptionalObjectType())
operandType = operandType.getOptionalObjectType();
auto fnType = operandType.getAs<SILFunctionType>();
require(fnType && fnType->getExtInfo().hasContext() &&
!fnType->isNoEscape() &&
fnType->getExtInfo().getRepresentation() ==
SILFunctionTypeRepresentation::Thick,
"is_escaping_closure must have a thick "
"function operand");
require(IEC->getVerificationType() == IsEscapingClosureInst::ObjCEscaping ||
IEC->getVerificationType() ==
IsEscapingClosureInst::WithoutActuallyEscaping,
"unknown verification type");
}
void checkDifferentiableFunctionInst(DifferentiableFunctionInst *dfi) {
// FIXME(TF-1197): Re-enable verification after substituted SIL function
// types.
return;
#if 0
auto origTy =
dfi->getOriginalFunction()->getType().getAs<SILFunctionType>();
require(origTy, "The original function must have a function type");
require(!origTy->isDifferentiable(),
"The original function must not be @differentiable");
// Skip verification in lowered SIL: LoadableByAddress changes
// parameter/result conventions.
// TODO: Check that derivative function types match excluding
// parameter/result conventions in lowered SIL.
if (F.getModule().getStage() == SILStage::Lowered)
return;
if (dfi->hasDerivativeFunctions()) {
auto jvp = dfi->getJVPFunction();
auto jvpType = jvp->getType().getAs<SILFunctionType>();
require(jvpType, "The JVP function must have a function type");
require(!jvpType->isDifferentiable(),
"The JVP function must not be @differentiable");
auto expectedJVPType = origTy->getAutoDiffDerivativeFunctionType(
dfi->getParameterIndices(), dfi->getResultIndices(),
AutoDiffDerivativeFunctionKind::JVP, TC,
LookUpConformanceInModule(M));
requireSameType(SILType::getPrimitiveObjectType(jvpType),
SILType::getPrimitiveObjectType(expectedJVPType),
"JVP type does not match expected JVP type");
auto vjp = dfi->getVJPFunction();
auto vjpType = vjp->getType().getAs<SILFunctionType>();
require(vjpType, "The VJP function must have a function type");
require(!vjpType->isDifferentiable(),
"The VJP function must not be @differentiable");
auto expectedVJPType = origTy->getAutoDiffDerivativeFunctionType(
dfi->getParameterIndices(), dfi->getResultIndices(),
AutoDiffDerivativeFunctionKind::VJP, TC,
LookUpConformanceInModule(M));
requireSameType(SILType::getPrimitiveObjectType(vjpType),
SILType::getPrimitiveObjectType(expectedVJPType),
"VJP type does not match expected VJP type");
}
#endif
}
void checkLinearFunctionInst(LinearFunctionInst *lfi) {
auto origTy =
lfi->getOriginalFunction()->getType().getAs<SILFunctionType>();
require(origTy, "The original function must have a function type");
require(!origTy->isDifferentiable(),
"The original function must not be differentiable");
// Skip lowered SIL: LoadableByAddress changes parameter/result conventions.
// TODO: Check that transpose function type matches excluding
// parameter/result conventions in lowered SIL.
if (F.getModule().getStage() == SILStage::Lowered)
return;
if (lfi->hasTransposeFunction()) {
auto transpose = lfi->getTransposeFunction();
auto transposeType = transpose->getType().getAs<SILFunctionType>();
require(transposeType,
"The transpose function must have a function type");
require(!transposeType->isDifferentiable(),
"The transpose function must not be differentiable");
auto expectedTransposeType = origTy->getAutoDiffTransposeFunctionType(
lfi->getParameterIndices(), TC, LookUpConformanceInModule(M));
// TODO: Consider tightening verification. This requires changes to
// `SILFunctionType::getAutoDiffTransposeFunctionType`.
requireSameType(
SILType::getPrimitiveObjectType(
transposeType->getUnsubstitutedType(F.getModule())),
SILType::getPrimitiveObjectType(
expectedTransposeType->getUnsubstitutedType(F.getModule())),
"Transpose type does not match expected transpose type");
}
}
void checkDifferentiableFunctionExtractInst(
DifferentiableFunctionExtractInst *dfei) {
auto fnTy = dfei->getOperand()->getType().getAs<SILFunctionType>();
require(fnTy, "The function operand must have a function type");
// TODO: Ban 'Normal' and 'Forward'.
require(
fnTy->getDifferentiabilityKind() == DifferentiabilityKind::Reverse ||
fnTy->getDifferentiabilityKind() == DifferentiabilityKind::Normal ||
fnTy->getDifferentiabilityKind() == DifferentiabilityKind::Forward,
"The function operand must be a '@differentiable(reverse)' function");
}
void checkLinearFunctionExtractInst(LinearFunctionExtractInst *lfei) {
auto fnTy = lfei->getOperand()->getType().getAs<SILFunctionType>();
require(fnTy, "The function operand must have a function type");
require(fnTy->getDifferentiabilityKind() == DifferentiabilityKind::Linear,
"The function operand must be a '@differentiable(_linear)' "
"function");
}
void checkDifferentiabilityWitnessFunctionInst(
DifferentiabilityWitnessFunctionInst *dwfi) {
auto witnessFnTy = dwfi->getType().castTo<SILFunctionType>();
auto *witness = dwfi->getWitness();
// `DifferentiabilityWitnessFunctionInst` constructor asserts that
// `witness` is non-null.
auto witnessKind = dwfi->getWitnessKind();
// Return if not witnessing a derivative function.
auto derivKind = witnessKind.getAsDerivativeFunctionKind();
if (!derivKind)
return;
// Return if witness does not define the referenced derivative.
auto *derivativeFn = witness->getDerivative(*derivKind);
if (!derivativeFn)
return;
auto derivativeFnTy = derivativeFn->getLoweredFunctionType();
requireSameType(SILType::getPrimitiveObjectType(witnessFnTy),
SILType::getPrimitiveObjectType(derivativeFnTy),
"Type of witness instruction does not match actual type of "
"witnessed function");
}
void checkGetAsyncContinuationInstBase(GetAsyncContinuationInstBase *GACI) {
auto resultTy = GACI->getType();
require(resultTy.is<BuiltinRawUnsafeContinuationType>(),
"Instruction type must be a continuation type");
}
void checkGetAsyncContinuationInst(GetAsyncContinuationInst *GACI) {
checkGetAsyncContinuationInstBase(GACI);
}
void checkGetAsyncContinuationAddrInst(GetAsyncContinuationAddrInst *GACI) {
checkGetAsyncContinuationInstBase(GACI);
requireSameType(GACI->getOperand()->getType(),
GACI->getLoweredResumeType().getAddressType(),
"Operand type must match continuation resume type");
}
void checkAwaitAsyncContinuationInst(AwaitAsyncContinuationInst *AACI) {
// The operand must be a GetAsyncContinuation* instruction.
auto cont = dyn_cast<GetAsyncContinuationInstBase>(AACI->getOperand());
require(cont, "can only await the result of a get_async_continuation instruction");
bool isAddressForm = isa<GetAsyncContinuationAddrInst>(cont);
auto &C = cont->getType().getASTContext();
// The shape of the successors depends on the continuation instruction being
// awaited.
require((bool)AACI->getErrorBB() == cont->throws(),
"must have an error successor if and only if the continuation is throwing");
if (cont->throws()) {
require(AACI->getErrorBB()->getNumArguments() == 1,
"error successor must take one argument");
auto arg = AACI->getErrorBB()->getArgument(0);
auto errorType = C.getErrorExistentialType();
requireSameType(arg->getType(),
SILType::getPrimitiveObjectType(errorType),
"error successor argument must have Error type");
if (AACI->getFunction()->hasOwnership()) {
require(arg->getOwnershipKind() == OwnershipKind::Owned,
"error successor argument must be owned");
}
}
if (isAddressForm) {
require(AACI->getResumeBB()->getNumArguments() == 0,
"resume successor must take no arguments for get_async_continuation_addr");
} else {
require(AACI->getResumeBB()->getNumArguments() == 1,
"resume successor must take one argument for get_async_continuation");
auto arg = AACI->getResumeBB()->getArgument(0);
requireSameType(arg->getType(), cont->getLoweredResumeType(),
"resume successor must take an argument of the continuation resume type");
if (AACI->getFunction()->hasOwnership()) {
require(arg->getOwnershipKind() == OwnershipKind::Owned,
"resume successor argument must be owned");
}
}
}
void verifySameShape(CanPackType left, CanPackType right) {
verifySameShape(left, right, 0, right->getNumElements());
}
void verifySameShape(CanPackType left, CanPackType right,
unsigned rightBegin, unsigned rightEnd) {
auto rightElements = right.getElementTypes();
require(rightBegin <= rightEnd && rightEnd <= rightElements.size(),
"slice out of range");
_verifySameShape(left.getElementTypes(),
rightElements.slice(rightBegin, rightEnd - rightBegin));
}
void verifySameShape(CanPackType left, ArrayRef<CanType> right) {
_verifySameShape(left.getElementTypes(), right);
}
template <class LeftArray, class RightArray>
void _verifySameShape(LeftArray left, RightArray right) {
require(left.size() == right.size(), "packs must agree in length");
for (size_t i : indices(left)) {
auto leftExpansion = dyn_cast<PackExpansionType>(left[i]);
auto rightExpansion = dyn_cast<PackExpansionType>(right[i]);
if (leftExpansion && rightExpansion) {
require(leftExpansion.getCountType()->getReducedShape() ==
rightExpansion.getCountType()->getReducedShape(),
"packs must have same shape: corresponding expansion "
"components must expand packs of same shape");
} else {
require(!leftExpansion && !rightExpansion,
"packs must have same shape: must agree in whether "
"corresponding components are expansions");
}
}
}
/// Given that we're indexing into the given pack, verify that the
/// element type is a valid type for the element at the given index.
void verifyPackElementType(CanSILPackType packType,
AnyPackIndexInst *packIndex,
SILType elementType) {
require(elementType.isAddress() == packType->isElementAddress(),
"pack element address-ness must match pack");
verifyPackElementType(packType->getElementTypes(),
packIndex,
elementType.getASTType(),
/*SILType*/ true);
}
/// Verify that the element type is the right type for a particular
/// index of a pack with the given components. This implements the
/// structural type matching for pack indexing algorithm described
/// in the specification for the SIL pack indexing instructions.
void verifyPackElementType(ArrayRef<CanType> indexedPack,
AnyPackIndexInst *packIndex,
CanType targetElementType,
bool typesAreSILTypes) {
verifySameShape(packIndex->getIndexedPackType(), indexedPack);
if (auto spi = dyn_cast<ScalarPackIndexInst>(packIndex)) {
requireSameType(targetElementType,
indexedPack[spi->getComponentIndex()],
"scalar pack index must match exactly");
} else if (auto ppi = dyn_cast<PackPackIndexInst>(packIndex)) {
auto start = ppi->getComponentStartIndex();
auto end = ppi->getComponentEndIndex();
verifyPackElementType(indexedPack.slice(start, end - start),
ppi->getSliceIndexOperand(),
targetElementType,
typesAreSILTypes);
} else {
auto dpi = cast<DynamicPackIndexInst>(packIndex);
verifyDynamicPackIndexStructuralEquality(indexedPack, dpi,
targetElementType,
typesAreSILTypes);
}
}
/// Collect the opened element archetypes in the named type that
/// are opened by an instruction using the given pack-indexing
/// instruction.
llvm::DenseMap<CanType, CanPackType>
collectOpenedElementArchetypeBindings(CanType type,
AnyPackIndexInst *indexedBy) {
llvm::DenseMap<CanType, CanPackType> result;
type.visit([&](CanType type) {
auto opened = dyn_cast<ElementArchetypeType>(type);
if (!opened) return;
opened = opened.getRoot();
// Don't repeat this work if the same archetype is named twice.
if (result.count(opened)) return;
// Ignore archetypes defined by open_pack_elements not based on the
// same pack_index instruction.
auto openingInst =
F.getModule().getRootLocalArchetypeDef(opened,
const_cast<SILFunction*>(&F));
auto opi = dyn_cast<OpenPackElementInst>(openingInst);
if (!opi || opi->getIndexOperand() != indexedBy) return;
// Map each root opened element archetype to its pack substitution.
// FIXME: remember conformances?
auto openedEnv = opi->getOpenedGenericEnvironment();
openedEnv->forEachPackElementBinding(
[&](ElementArchetypeType *elementArchetype, PackType *substitution) {
auto subPack = cast<PackType>(substitution->getCanonicalType());
result.insert({elementArchetype->getCanonicalType(), subPack});
});
});
return result;
}
/// Verify that the lowered element type is a valid type for a
/// particular dynamic_pack_index into a pack operand with the given
/// components.
///
/// This implements part of the structural type matching algorithm
/// for pack indexing:
///
/// Let S be the set of opened pack element archetypes in the element
/// type that were opened by open_pack_element instructions based on
/// the same dynamic_pack_index instruction. By construction,
/// the pack substitutions given to open_pack_element for the opened
/// type parameter packs must all have the same shape as the indexed
/// pack type of the open_pack_element's index operand. That index
/// operand is the given dynamic_pack_index instruction, which is being
/// used to index into a pack with the given pack components, so the
/// components must have the same shape as the pack substitutions.
/// The lowered element type is a valid type for this index if, for
/// each component of this shape, there is a substitution which
/// (optionally) replaces archetypes in S with the correponding
/// component type (pattern types for expansions) of the pack
/// substitution to get the corresponding component type (pattern
/// type for expansions) of the pack operand.
///
/// That is, suppose we have:
/// open_pack_element %index of <each P0, each P1 where (P0,P1):Any>
/// at <Pack{A0, repeat each B0, C0},
/// Pack{A1, repeat each B1, C1}>,
/// shape $P0, uuid "01234"
///
/// And suppose we're indexing into this pack (recalling that the
/// pack shape rules require this to have the same shape as the pack
/// substitutions):
/// $Pack{Ap, repeat each Bp, Cp},
///
/// Finally, suppose that the expected element type of this index is E,
/// a type expression in terms of @pack_element("01234") P0 and
/// @pack_element("01234") P1.
///
/// Then applying this substitution to E:
/// @pack_element("01234") P0 => A0
/// @pack_element("01234") P1 => A1
/// should yield the type expression Ap, and so on for each component
/// of the shape.
void verifyDynamicPackIndexStructuralEquality(
ArrayRef<CanType> indexedPack,
DynamicPackIndexInst *dpi,
CanType targetElementType,
bool typesAreSILTypes) {
// If there are no pack components, this code must be unreachable.
if (indexedPack.empty()) return;
// Collect the set S of opened pack archetypes based on the given
// pack index instruction, mapping them to their pack substitution
// types.
auto allOpened =
collectOpenedElementArchetypeBindings(targetElementType, dpi);
// Expand each of the pack components.
for (unsigned componentIndex : indices(indexedPack)) {
CanType indexedElementType = indexedPack[componentIndex];
CanType indexedShape;
if (auto exp = dyn_cast<PackExpansionType>(indexedElementType)) {
indexedShape = exp.getCountType();
indexedElementType = exp.getPatternType();
}
// If we have an exact match without substitution, that's great.
if (targetElementType == indexedElementType) continue;
// If we don't have any substitutions, this must be a case where the
// expansion is invariant to the archetypes.
if (allOpened.empty()) {
// This condition is always false.
requireSameType(targetElementType, indexedElementType,
"no opened archetypes based on a matching pack index "
"instruction; element type must be invariant");
continue;
}
// Otherwise, we expect lanewise substitution to turn the expected
// element type into the lanewise component of the original pack.
// Provide substitution functions that replace the pack archetypes
// we found above with the corresponding lane of the pack substitution.
auto substTypes = [&](SubstitutableType *type) -> Type {
auto archetype = dyn_cast<ElementArchetypeType>(type);
if (!archetype)
return type;
if (!archetype->isRoot())
return Type();
auto it = allOpened.find(type->getCanonicalType());
assert(it != allOpened.end());
auto pack = it->second;
auto packElementType = pack.getElementType(componentIndex);
if (auto exp = dyn_cast<PackExpansionType>(packElementType)) {
assert(indexedShape && "pack substitution doesn't match in shape");
packElementType = exp.getPatternType();
} else {
assert(!indexedShape && "pack substitution doesn't match in shape");
}
return packElementType;
};
auto substConformances = [&](CanType dependentType,
Type conformingType,
ProtocolDecl *protocol) -> ProtocolConformanceRef {
// FIXME: This violates the spirit of this verifier check.
return protocol->getParentModule()
->lookupConformance(conformingType, protocol);
};
// If the pack components and expected element types are SIL types,
// we need to perform SIL substitution.
if (typesAreSILTypes) {
auto targetElementSILType =
SILType::getPrimitiveObjectType(targetElementType);
auto indexedElementSILType =
SILType::getPrimitiveObjectType(indexedElementType);
auto substTargetElementSILType =
targetElementSILType.subst(F.getModule(),
substTypes, substConformances);
requireSameType(indexedElementSILType, substTargetElementSILType,
"lanewise-substituted pack element type didn't "
"match expected element type");
} else {
auto substTargetElementType =
targetElementType.subst(substTypes, substConformances)
->getCanonicalType();
requireSameType(indexedElementType, substTargetElementType,
"lanewise-substituted pack element type didn't "
"match expected element type");
}
}
}
void checkPackPackIndexInst(PackPackIndexInst *i) {
auto innerIndex = requireValueKind<AnyPackIndexInst>(i->getOperand(),
"component pack index operand");
if (!innerIndex) return;
auto packType = i->getIndexedPackType();
require(i->getComponentStartIndex() < packType->getNumElements(),
"component index must be in bounds for indexed pack type");
verifySameShape(innerIndex->getIndexedPackType(), packType,
i->getComponentStartIndex(), i->getComponentEndIndex());
}
void checkScalarPackIndexInst(ScalarPackIndexInst *i) {
auto packType = i->getIndexedPackType();
require(i->getComponentIndex() < packType->getNumElements(),
"component index must be in bounds for indexed pack type");
require(!isa<PackExpansionType>(
packType.getElementType(i->getComponentIndex())),
"component index must correspond to scalar component of "
"indexed pack type");
}
void checkOpenPackElementInst(OpenPackElementInst *i) {
requireObjectType(BuiltinPackIndexType, i->getOperand()->getType(),
"pack index operand");
auto index = requireValueKind<AnyPackIndexInst>(i->getOperand(),
"pack index operand must be one of the pack_index instructions");
if (!index) return;
verifySameShape(index->getIndexedPackType(), i->getOpenedShapeClass());
}
void checkPackElementGetInst(PackElementGetInst *i) {
auto index = requireValueKind<AnyPackIndexInst>(i->getIndex(),
"pack index operand must be one of the pack_index instructions");
if (!index) return;
verifyPackElementType(i->getPackType(), index, i->getElementType());
}
void checkPackElementSetInst(PackElementSetInst *i) {
auto index = requireValueKind<AnyPackIndexInst>(i->getIndex(),
"pack index operand must be one of the pack_index instructions");
if (!index) return;
verifyPackElementType(i->getPackType(), index, i->getElementType());
}
void checkTuplePackElementAddrInst(TuplePackElementAddrInst *i) {
auto index = requireValueKind<AnyPackIndexInst>(i->getIndex(),
"pack index operand must be one of the pack_index instructions");
if (!index) return;
// Remove the extra tuple element type structure.
SmallVector<CanType, 8> tupleElements; {
auto tupleType = requireAddressType(TupleType, i->getTuple()->getType(),
"tuple operand of tuple_pack_element_addr");
auto eltTypes = tupleType.getElementTypes();
tupleElements.append(eltTypes.begin(), eltTypes.end());
}
require(i->getElementType().isAddress(),
"result of tuple_pack_element_addr must be an address");
verifyPackElementType(tupleElements, index,
i->getElementType().getASTType(),
/*types are SIL types*/ true);
}
void checkTuplePackExtractInst(TuplePackExtractInst *i) {
require(!F.getModule().useLoweredAddresses(),
"tuple_pack_extract is only valid in opaque values");
auto index = requireValueKind<AnyPackIndexInst>(
i->getIndex(),
"pack index operand must be one of the pack_index instructions");
if (!index)
return;
// Remove the extra tuple element type structure.
SmallVector<CanType, 8> tupleElements;
{
auto tupleType = requireObjectType(TupleType, i->getTuple()->getType(),
"tuple operand of tuple_pack_extract");
auto eltTypes = tupleType.getElementTypes();
tupleElements.append(eltTypes.begin(), eltTypes.end());
}
require(i->getElementType().isObject(),
"result of tuple_pack_extract must be an object");
verifyPackElementType(tupleElements, index,
i->getElementType().getASTType(),
/*types are SIL types*/ true);
}
// This verifies that the entry block of a SIL function doesn't have
// any predecessors and also verifies the entry point arguments.
void verifyEntryBlock(SILBasicBlock *entry) {
require(entry->pred_empty(), "entry block cannot have predecessors");
LLVM_DEBUG(
llvm::dbgs() << "Argument types for entry point BB:\n";
for (auto *arg
: make_range(entry->args_begin(), entry->args_end()))
arg->getType()
.dump();
llvm::dbgs() << "Input types for SIL function type ";
F.getLoweredFunctionType()->print(llvm::dbgs()); llvm::dbgs() << ":\n";
for (auto paramTy
: fnConv.getParameterSILTypes(F.getTypeExpansionContext())) {
paramTy.dump();
});
require(entry->args_size() == (fnConv.getNumIndirectSILResults()
+ fnConv.getNumIndirectSILErrorResults()
+ fnConv.getNumParameters()),
"entry point has wrong number of arguments");
bool matched = true;
auto argI = entry->args_begin();
auto check = [&](const char *what, SILType ty) {
auto mappedTy = F.mapTypeIntoContext(ty);
SILArgument *bbarg = *argI;
++argI;
if (bbarg->getType() != mappedTy &&
bbarg->getType() != F.getLoweredType(mappedTy.getASTType())
.getCategoryType(mappedTy.getCategory())) {
llvm::errs() << what << " type mismatch!\n";
llvm::errs() << " argument: "; bbarg->dump();
llvm::errs() << " expected: "; mappedTy.dump();
matched = false;
}
// If we do not have qualified ownership, do not check ownership.
if (!F.hasOwnership()) {
return;
}
auto ownershipkind = ValueOwnershipKind(
F, mappedTy, fnConv.getSILArgumentConvention(bbarg->getIndex()));
if (bbarg->getOwnershipKind() != ownershipkind) {
llvm::errs() << what << " ownership kind mismatch!\n";
llvm::errs() << " argument: " << bbarg->getOwnershipKind() << '\n';
llvm::errs() << " expected: " << ownershipkind << '\n';
matched = false;
}
};
for (auto result : fnConv.getIndirectSILResults()) {
assert(fnConv.isSILIndirect(result));
check("indirect result",
fnConv.getSILType(result, F.getTypeExpansionContext()));
}
if (fnConv.hasIndirectSILErrorResults()) {
auto errorResult = fnConv.getSILErrorType(F.getTypeExpansionContext());
check("indirect error result", errorResult);
}
for (auto param : F.getLoweredFunctionType()->getParameters()) {
check("parameter", fnConv.getSILType(param, F.getTypeExpansionContext()));
}
require(matched, "entry point argument types do not match function type");
// TBAA requirement for all address arguments.
require(std::equal(entry->args_begin() + fnConv.getNumIndirectSILResults()
+ fnConv.getNumIndirectSILErrorResults(),
entry->args_end(),
fnConv.funcTy->getParameters().begin(),
[&](SILArgument *bbarg, SILParameterInfo paramInfo) {
if (!bbarg->getType().isAddress())
return true;
switch (paramInfo.getConvention()) {
case ParameterConvention::Direct_Unowned:
case ParameterConvention::Direct_Guaranteed:
case ParameterConvention::Direct_Owned:
return false;
case ParameterConvention::Indirect_In:
case ParameterConvention::Indirect_Inout:
case ParameterConvention::Indirect_InoutAliasable:
case ParameterConvention::Indirect_In_Guaranteed:
case ParameterConvention::Pack_Owned:
case ParameterConvention::Pack_Guaranteed:
case ParameterConvention::Pack_Inout:
return true;
}
}),
"entry point address argument must have an indirect calling "
"convention");
}
void checkMoveValueInst(MoveValueInst *mvi) {
require(mvi->getOperand()->getType().isObject(),
"Operand value should be an object");
require(mvi->getType() == mvi->getOperand()->getType(),
"Result and operand must have the same type, today.");
}
// check that a drop_deinit can only ever be destroyed or destructured
void checkDropDeinitUses(DropDeinitInst *ddi) {
// Address-type drop_deinit has no special structural requirements. It just
// sits there and blocks optimization on the allocation and downstream uses
// of the address. If we want to optimize around address-type drop_deinit,
// then we need a seperate verifier for its requirements.
if (ddi->getType().isAddress())
return;
visitNonOwnershipUses(ddi, [&](Operand *use) {
auto *user = use->getUser();
require(isa<DestroyValueInst>(user)
|| isa<EndLifetimeInst>(user)
|| isa<DestructureStructInst>(user)
|| isa<SwitchEnumInst>(user),
"A drop_deinit can only be destroyed or destructured");
return true;
});
}
void checkDropDeinitInst(DropDeinitInst *ddi) {
require(F.hasOwnership(), "drop_deinit only allowed in OSSA");
auto type = ddi->getType();
require(type == ddi->getOperand()->getType(),
"Result and operand must have the same type.");
require(type.isMoveOnly(/*orWrapped=*/false),
"drop_deinit only allowed for move-only types");
require(type.getNominalOrBoundGenericNominal()
->getValueTypeDestructor(), "drop_deinit only allowed for "
"struct/enum types that define a deinit");
assert(!type.isTrivial(F) && "a type with a deinit is nontrivial");
checkDropDeinitUses(ddi);
}
void checkMarkUnresolvedNonCopyableValueInst(
MarkUnresolvedNonCopyableValueInst *i) {
require(i->getModule().getStage() == SILStage::Raw,
"Only valid in Raw SIL! Should have been eliminated by /some/ "
"diagnostic pass");
if (i->getType().isAddress())
checkAddressWalkerCanVisitAllTransitiveUses(i);
}
void checkMarkUnresolvedReferenceBindingInst(
MarkUnresolvedReferenceBindingInst *i) {
require(i->getModule().getStage() == SILStage::Raw,
"Only valid in Raw SIL! Should have been eliminated by /some/ "
"diagnostic pass");
}
void checkMoveOnlyWrapperToCopyableValueInst(
MoveOnlyWrapperToCopyableValueInst *cvt) {
require(cvt->getOperand()->getType().isObject(),
"Operand value should be an object");
require(cvt->getOperand()->getType().isMoveOnlyWrapped(),
"Operand should be move only wrapped");
require(cvt->getType() ==
cvt->getOperand()->getType().removingMoveOnlyWrapper(),
"Result and operand must have the same type, today.");
}
void checkMoveOnlyWrapperToCopyableBoxInst(
MoveOnlyWrapperToCopyableBoxInst *cvt) {
require(cvt->getOperand()->getType().isObject(),
"Operand value should be an object");
require(cvt->getOperand()->getType().isBoxedMoveOnlyWrappedType(cvt->getFunction()),
"Operand should be move only wrapped");
require(
cvt->getType() ==
cvt->getOperand()->getType().removingMoveOnlyWrapperFromBoxedType(
cvt->getFunction()),
"Result and operand must have the same type, today.");
}
void checkCopyableToMoveOnlyWrapperValueInst(
CopyableToMoveOnlyWrapperValueInst *cvt) {
require(cvt->getInitialKind() ==
CopyableToMoveOnlyWrapperValueInst::Owned ||
!cvt->getOperand()->getType().isTrivial(*cvt->getFunction()),
"To convert from a trivial value to a move only wrapper value use "
"TrivialToGuaranteedMoveOnlyWrapperValueInst");
require(cvt->getOperand()->getType().isObject(),
"Operand value should be an object");
require(cvt->getType().isMoveOnlyWrapped(), "Output should be move only");
require(cvt->getType() ==
cvt->getOperand()->getType().addingMoveOnlyWrapper(),
"Result and operand must have the same type, today.");
}
void checkAllocPackMetadataInst(AllocPackMetadataInst *apmi) {
require(apmi->getIntroducer()->mayRequirePackMetadata(*apmi->getFunction()),
"Introduces instruction of kind which cannot emit on-stack pack "
"metadata");
require(F.getModule().getStage() == SILStage::Lowered,
"Only supported in lowered SIL");
}
void checkDeallocPackMetadataInst(DeallocPackMetadataInst *dpmi) {
auto *apmi = dpmi->getOperand()->getDefiningInstruction();
require(apmi, "Must have instruction operand.");
require(isa<AllocPackMetadataInst>(apmi),
"Must have alloc_pack_metadata operand");
require(F.getModule().getStage() == SILStage::Lowered,
"Only supported in lowered SIL");
}
void checkMoveOnlyWrapperToCopyableAddrInst(
MoveOnlyWrapperToCopyableAddrInst *cvt) {
require(cvt->getType().isAddress(), "Output should be an address");
require(cvt->getOperand()->getType().isMoveOnlyWrapped(),
"Input should be move only");
require(cvt->getType() ==
cvt->getOperand()->getType().removingMoveOnlyWrapper(),
"Result and operand must have the same type.");
}
void checkCopyableToMoveOnlyWrapperAddrInst(
CopyableToMoveOnlyWrapperAddrInst *cvt) {
require(cvt->getType().isAddress(), "Output should be an address");
require(!cvt->getOperand()->getType().isMoveOnlyWrapped(),
"Input should not be move only wrapped");
require(cvt->getType() ==
cvt->getOperand()->getType().addingMoveOnlyWrapper(),
"Result and operand must have the same underlying type ignoring "
"move only wrappedness.");
}
void verifyEpilogBlocks(SILFunction *F) {
bool FoundReturnBlock = false;
bool FoundThrowBlock = false;
bool FoundUnwindBlock = false;
for (auto &BB : *F) {
if (isa<ReturnInst>(BB.getTerminator())) {
require(!FoundReturnBlock,
"more than one return block in function");
FoundReturnBlock = true;
} else if (isa<ThrowInst>(BB.getTerminator()) ||
isa<ThrowAddrInst>(BB.getTerminator())) {
require(!FoundThrowBlock,
"more than one throw block in function");
FoundThrowBlock = true;
} else if (isa<UnwindInst>(BB.getTerminator())) {
require(!FoundUnwindBlock,
"more than one unwind block in function");
FoundUnwindBlock = true;
} else {
assert(!BB.getTerminator()->isFunctionExiting());
}
}
}
bool isUnreachableAlongAllPathsStartingAt(
SILBasicBlock *StartBlock, BasicBlockSet &Visited) {
if (isa<UnreachableInst>(StartBlock->getTerminator()))
return true;
else if (isa<ReturnInst>(StartBlock->getTerminator()))
return false;
else if (isa<ThrowInst>(StartBlock->getTerminator()) ||
isa<ThrowAddrInst>(StartBlock->getTerminator()))
return false;
// Recursively check all successors.
for (auto *SuccBB : StartBlock->getSuccessorBlocks())
if (!Visited.insert(SuccBB))
if (!isUnreachableAlongAllPathsStartingAt(SuccBB, Visited))
return false;
return true;
}
void verifySILFunctionType(CanSILFunctionType FTy) {
// Make sure that if FTy's calling convention implies that it must have a
// self parameter.
require(!FTy->hasSelfParam() || !FTy->getParameters().empty(),
"Functions with a calling convention with self parameter must "
"have at least one argument for self.");
require(!FTy->hasErasedIsolation() ||
FTy->getRepresentation() == SILFunctionType::Representation::Thick,
"only thick function types can have erased isolation");
// If our function hasSendingResult, then /all/ results must be
// sending.
require(FTy->hasSendingResult() ==
(FTy->getResults().size() &&
llvm::all_of(FTy->getResults(),
[](SILResultInfo result) {
return result.hasOption(
SILResultInfo::IsSending);
})),
"sending result means all results are sending");
require(1 >= std::count_if(FTy->getParameters().begin(), FTy->getParameters().end(),
[](const SILParameterInfo ¶meterInfo) {
return parameterInfo.hasOption(SILParameterInfo::Isolated);
}),
"Should only ever be isolated to a single parameter");
}
struct VerifyFlowSensitiveRulesDetails {
enum CFGState {
/// No special rules are in play.
Normal,
/// We've followed the resume edge of a yield in a yield_once coroutine.
YieldOnceResume,
/// We've followed the unwind edge of a yield.
YieldUnwind
};
struct BBState {
std::vector<SingleValueInstruction*> Stack;
/// Contents: BeginAccessInst*, BeginApplyInst*.
std::set<SILInstruction*> ActiveOps;
CFGState CFG = Normal;
GetAsyncContinuationInstBase *GotAsyncContinuation = nullptr;
};
};
/// Verify the various control-flow-sensitive rules of SIL:
///
/// - stack allocations and deallocations must obey a stack discipline
/// - accesses must be uniquely ended
/// - async continuations must be awaited before getting the continuation again, suspending
/// the task, or exiting the function
/// - flow-sensitive states must be equivalent on all paths into a block
void verifyFlowSensitiveRules(SILFunction *F) {
// Do a traversal of the basic blocks.
// Note that we intentionally don't verify these properties in blocks
// that can't be reached from the entry block.
llvm::DenseMap<SILBasicBlock*, VerifyFlowSensitiveRulesDetails::BBState> visitedBBs;
SmallVector<SILBasicBlock*, 16> Worklist;
visitedBBs.try_emplace(&*F->begin());
Worklist.push_back(&*F->begin());
while (!Worklist.empty()) {
SILBasicBlock *BB = Worklist.pop_back_val();
VerifyFlowSensitiveRulesDetails::BBState state = visitedBBs[BB];
for (SILInstruction &i : *BB) {
CurInstruction = &i;
if (i.maySuspend()) {
// Instructions that may suspend an async context must not happen
// while the continuation is being accessed, with the exception of
// the AwaitAsyncContinuationInst that completes suspending the task.
if (auto aaci = dyn_cast<AwaitAsyncContinuationInst>(&i)) {
require(state.GotAsyncContinuation == aaci->getOperand(),
"encountered await_async_continuation that doesn't match active gotten continuation");
state.GotAsyncContinuation = nullptr;
} else {
require(!state.GotAsyncContinuation,
"cannot suspend async task while unawaited continuation is active");
}
}
if (i.isAllocatingStack()) {
state.Stack.push_back(cast<SingleValueInstruction>(&i));
} else if (i.isDeallocatingStack()) {
SILValue op = i.getOperand(0);
require(!state.Stack.empty(),
"stack dealloc with empty stack");
if (op != state.Stack.back()) {
llvm::errs() << "Recent stack alloc: " << *state.Stack.back();
llvm::errs() << "Matching stack alloc: " << *op;
require(op == state.Stack.back(),
"stack dealloc does not match most recent stack alloc");
}
state.Stack.pop_back();
} else if (isa<BeginAccessInst>(i) || isa<BeginApplyInst>(i) ||
isa<StoreBorrowInst>(i)) {
bool notAlreadyPresent = state.ActiveOps.insert(&i).second;
require(notAlreadyPresent,
"operation was not ended before re-beginning it");
} else if (isa<EndAccessInst>(i) || isa<AbortApplyInst>(i) ||
isa<EndApplyInst>(i)) {
if (auto beginOp = i.getOperand(0)->getDefiningInstruction()) {
bool present = state.ActiveOps.erase(beginOp);
require(present, "operation has already been ended");
}
} else if (auto *endBorrow = dyn_cast<EndBorrowInst>(&i)) {
if (isa<StoreBorrowInst>(endBorrow->getOperand())) {
if (auto beginOp = i.getOperand(0)->getDefiningInstruction()) {
bool present = state.ActiveOps.erase(beginOp);
require(present, "operation has already been ended");
}
}
} else if (auto gaci = dyn_cast<GetAsyncContinuationInstBase>(&i)) {
require(!state.GotAsyncContinuation,
"get_async_continuation while unawaited continuation is already active");
state.GotAsyncContinuation = gaci;
} else if (auto term = dyn_cast<TermInst>(&i)) {
if (term->isFunctionExiting()) {
require(state.Stack.empty(),
"return with stack allocs that haven't been deallocated");
require(state.ActiveOps.empty(),
"return with operations still active");
require(!state.GotAsyncContinuation,
"return with unawaited async continuation");
if (isa<UnwindInst>(term)) {
require(state.CFG == VerifyFlowSensitiveRulesDetails::YieldUnwind,
"encountered 'unwind' when not on unwind path");
} else {
require(state.CFG != VerifyFlowSensitiveRulesDetails::YieldUnwind,
"encountered 'return' or 'throw' when on unwind path");
if (isa<ReturnInst>(term) &&
F->getLoweredFunctionType()->getCoroutineKind() ==
SILCoroutineKind::YieldOnce &&
F->getModule().getStage() != SILStage::Raw) {
require(state.CFG == VerifyFlowSensitiveRulesDetails::YieldOnceResume,
"encountered 'return' before yielding a value in "
"yield_once coroutine");
}
}
}
if (isa<YieldInst>(term)) {
require(state.CFG != VerifyFlowSensitiveRulesDetails::YieldOnceResume,
"encountered multiple 'yield's along single path");
require(state.CFG == VerifyFlowSensitiveRulesDetails::Normal,
"encountered 'yield' on abnormal CFG path");
require(!state.GotAsyncContinuation,
"encountered 'yield' while an unawaited continuation is active");
}
auto successors = term->getSuccessors();
for (auto i : indices(successors)) {
SILBasicBlock *succBB = successors[i].getBB();
// Optimistically try to set our current state as the state
// of the successor. We can use a move on the final successor;
// note that if the insertion fails, the move won't actually
// happen, which is important because we'll still need it
// to compare against the already-recorded state for the block.
auto insertResult =
i + 1 == successors.size()
? visitedBBs.try_emplace(succBB, std::move(state))
: visitedBBs.try_emplace(succBB, state);
// If the insertion was successful, add the successor to the
// worklist and continue.
if (insertResult.second) {
Worklist.push_back(succBB);
// If we're following a 'yield', update the CFG state:
if (isa<YieldInst>(term)) {
// Enforce that the unwind logic is segregated in all stages.
if (i == 1) {
insertResult.first->second.CFG = VerifyFlowSensitiveRulesDetails::YieldUnwind;
// We check the yield_once rule in the mandatory analyses,
// so we can't assert it yet in the raw stage.
} else if (F->getLoweredFunctionType()->getCoroutineKind()
== SILCoroutineKind::YieldOnce &&
F->getModule().getStage() != SILStage::Raw) {
insertResult.first->second.CFG = VerifyFlowSensitiveRulesDetails::YieldOnceResume;
}
}
continue;
}
// This rule is checked elsewhere, but we'd want to assert it
// here anyway.
require(!isa<YieldInst>(term),
"successor of 'yield' should not be encountered twice");
// Check that the stack height is consistent coming from all entry
// points into this BB. We only care about consistency if there is
// a possible return from this function along the path starting at
// this successor bb. (FIXME: Why? Infinite loops should still
// preserve consistency...)
auto isUnreachable = [&] {
BasicBlockSet visited(F);
return isUnreachableAlongAllPathsStartingAt(succBB, visited);
};
const auto &foundState = insertResult.first->second;
require(state.Stack == foundState.Stack || isUnreachable(),
"inconsistent stack heights entering basic block");
require(state.ActiveOps == foundState.ActiveOps || isUnreachable(),
"inconsistent active-operations sets entering basic block");
require(state.CFG == foundState.CFG,
"inconsistent coroutine states entering basic block");
require(state.GotAsyncContinuation == foundState.GotAsyncContinuation,
"inconsistent active async continuations entering basic block");
}
}
}
}
}
void verifyBranches(const SILFunction *F) {
// Verify no critical edge.
auto requireNonCriticalSucc = [this](const TermInst *termInst,
const Twine &message) {
// A critical edge has more than one outgoing edges from the source
// block.
auto succBlocks = termInst->getSuccessorBlocks();
if (succBlocks.size() <= 1)
return;
for (const SILBasicBlock *destBB : succBlocks) {
// And its destination block has more than one predecessor.
_require(destBB->getSinglePredecessorBlock(), message);
}
};
for (auto &bb : *F) {
const TermInst *termInst = bb.getTerminator();
CurInstruction = termInst;
if (isSILOwnershipEnabled() && F->hasOwnership()) {
requireNonCriticalSucc(termInst, "critical edges not allowed in OSSA");
}
// In Lowered SIL, they are allowed on conditional branches only.
if (!AllowCriticalEdges && !isa<CondBranchInst>(termInst)) {
requireNonCriticalSucc(termInst, "only cond_br critical edges allowed");
}
}
}
/// This pass verifies that there are no hole in debug scopes at -Onone.
void verifyDebugScopeHoles(SILBasicBlock *BB) {
if (!VerifyDIHoles)
return;
// These transforms don't set everything they move to implicit.
if (M->getASTContext().LangOpts.Playground ||
M->getASTContext().LangOpts.PCMacro)
return;
// This check only makes sense at -Onone. Optimizations,
// e.g. inlining, can move scopes around.
llvm::DenseSet<const SILDebugScope *> AlreadySeenScopes;
if (BB->getParent()->getEffectiveOptimizationMode() !=
OptimizationMode::NoOptimization)
return;
// Exit early if this BB is empty.
if (BB->empty())
return;
const SILDebugScope *LastSeenScope = nullptr;
SILInstruction *LastSeenScopeInst = nullptr;
for (SILInstruction &SI : *BB) {
if (SI.isMetaInstruction())
continue;
// FIXME: Profile counters for loop bodies may be emitted before the
// instructions for the loop variable, but in a deeper scope.
if (isa<IncrementProfilerCounterInst>(SI))
continue;
if (!SI.getLoc().hasValidLineNumber())
continue;
if (SI.getLoc().getKind() == SILLocation::CleanupKind)
continue;
// FIXME: These still leave holes in the scopes. We should make them
// inherit the sourrounding scope in IRGenSIL.
if (SI.getLoc().getKind() == SILLocation::MandatoryInlinedKind)
continue;
// FIXME: There are situations where the execution legitimately goes
// backwards, such as
//
// while case let w: String? = Optional.some("b") {}
//
// where the RHS of the assignment gets run first and then the
// result is copied into the LHS.
if (!llvm::isa<BeginBorrowInst>(&SI) || !llvm::isa<CopyValueInst>(&SI))
continue;
// If we haven't seen this debug scope yet, update the
// map and go on.
auto *DS = SI.getDebugScope();
assert(DS && "Each instruction should have a debug scope");
// We don't support this verification on inlined call sites yet.
if (DS->InlinedCallSite)
continue;
if (!AlreadySeenScopes.count(DS)) {
AlreadySeenScopes.insert(DS);
LastSeenScope = DS;
LastSeenScopeInst = &SI;
continue;
}
// Otherwise, we're allowed to re-enter a scope only if
// the scope is an ancestor of the scope we're currently leaving.
auto isAncestorScope = [](const SILDebugScope *Cur,
const SILDebugScope *Previous) {
assert(Cur && "null current scope queried");
assert(Previous && "null previous scope queried");
const SILDebugScope *Tmp = Previous;
while (Tmp) {
auto Parent = Tmp->Parent;
auto *ParentScope = Parent.dyn_cast<const SILDebugScope *>();
if (ParentScope == Cur)
return true;
Tmp = ParentScope;
}
return false;
};
if (isAncestorScope(DS, LastSeenScope)) {
LastSeenScope = DS;
LastSeenScopeInst = &SI;
continue;
}
if (DS != LastSeenScope) {
llvm::errs() << "Broken instruction!\n";
SI.dump();
#ifndef NDEBUG
llvm::errs() << "in scope\n";
DS->print(SI.getFunction()->getModule());
#endif
llvm::errs() << "Previous, non-contiguous scope set by";
LastSeenScopeInst->dump();
#ifndef NDEBUG
llvm::errs() << "in scope\n";
LastSeenScope->print(SI.getFunction()->getModule());
#endif
llvm::errs() << "Please report a bug on bugs.swift.org\n";
llvm::errs() <<
"Pass -Xllvm -verify-di-holes=false to disable the verification\n";
// Turn on debug info printing so that the log actually shows the bad
// scopes.
SILPrintDebugInfo.setValue(true);
require(
DS == LastSeenScope,
"Basic block contains a non-contiguous lexical scope at -Onone");
}
}
}
void visitSILBasicBlock(SILBasicBlock *BB) {
SILInstructionVisitor::visitSILBasicBlock(BB);
verifyDebugScopeHoles(BB);
}
void visitBasicBlockArguments(SILBasicBlock *BB) {
CurInstruction = nullptr;
for (auto argI = BB->args_begin(), argEnd = BB->args_end(); argI != argEnd;
++argI)
visitSILArgument(*argI);
}
void visitSILBasicBlocks(SILFunction *F) {
// Visit all basic blocks in the RPOT order.
// This ensures that any open_existential instructions, which
// open archetypes, are seen before the uses of these archetypes.
llvm::ReversePostOrderTraversal<SILFunction *> RPOT(F);
BasicBlockSet VisitedBBs(F);
for (auto Iter = RPOT.begin(), E = RPOT.end(); Iter != E; ++Iter) {
auto *BB = *Iter;
VisitedBBs.insert(BB);
visitSILBasicBlock(BB);
}
// Visit all basic blocks that were not visited during the RPOT traversal,
// e.g. unreachable basic blocks.
for (auto &BB : *F) {
if (VisitedBBs.contains(&BB))
continue;
visitSILBasicBlock(&BB);
}
verifyPredecessorSucessorStructure(F);
}
// Make sure that each of the successors/predecessors of a basic block
// have this basic block in its predecessor/successor list.
void verifyPredecessorSucessorStructure(SILFunction *f) {
using PredSuccPair = std::pair<SILBasicBlock *, SILBasicBlock *>;
llvm::DenseSet<PredSuccPair> foundSuccessors;
llvm::DenseSet<PredSuccPair> foundPredecessors;
for (auto &block : *f) {
for (SILBasicBlock *succ : block.getSuccessorBlocks()) {
foundSuccessors.insert({&block, succ});
}
for (SILBasicBlock *pred : block.getPredecessorBlocks()) {
foundPredecessors.insert({pred, &block});
}
}
for (PredSuccPair predSucc : foundSuccessors) {
require(foundPredecessors.contains(predSucc),
"block is not predecessor of its successor");
}
for (PredSuccPair predSucc : foundPredecessors) {
require(foundSuccessors.contains(predSucc),
"block is not successor of its predecessor");
}
}
void verifyParentFunctionSILFunctionType(CanSILFunctionType FTy) {
bool foundIsolatedParameter = false;
for (const auto ¶meterInfo : FTy->getParameters()) {
if (parameterInfo.hasOption(SILParameterInfo::Isolated)) {
auto argType = parameterInfo.getArgumentType(F.getModule(),
FTy,
F.getTypeExpansionContext());
if (argType->isOptional())
argType = argType->lookThroughAllOptionalTypes()->getCanonicalType();
auto genericSig = FTy->getInvocationGenericSignature();
auto &ctx = F.getASTContext();
auto *actorProtocol = ctx.getProtocol(KnownProtocolKind::Actor);
auto *distributedProtocol = ctx.getProtocol(KnownProtocolKind::DistributedActor);
require(argType->isAnyActorType() ||
genericSig->requiresProtocol(argType, actorProtocol) ||
genericSig->requiresProtocol(argType, distributedProtocol),
"Only any actor types can be isolated");
require(!foundIsolatedParameter, "Two isolated parameters");
foundIsolatedParameter = true;
}
}
}
void visitSILFunction(SILFunction *F) {
PrettyStackTraceSILFunction stackTrace("verifying", F);
CanSILFunctionType FTy = F->getLoweredFunctionType();
verifySILFunctionType(FTy);
verifyParentFunctionSILFunctionType(FTy);
SILModule &mod = F->getModule();
bool embedded = mod.getASTContext().LangOpts.hasFeature(Feature::Embedded);
require(!F->isAnySerialized() || !mod.isSerialized() || mod.isParsedAsSerializedSIL(),
"cannot have a serialized function after the module has been serialized");
switch (F->getLinkage()) {
case SILLinkage::Public:
case SILLinkage::Package:
case SILLinkage::Shared:
require(F->isDefinition() || F->hasForeignBody(),
"public/package/shared function must have a body");
break;
case SILLinkage::PublicNonABI:
case SILLinkage::PackageNonABI:
require(F->isDefinition(),
"alwaysEmitIntoClient function must have a body");
require(F->isAnySerialized() || mod.isSerialized(),
"alwaysEmitIntoClient function must be serialized");
break;
case SILLinkage::Hidden:
case SILLinkage::Private:
require(F->isDefinition() || F->hasForeignBody(),
"internal/private function must have a body");
require(!F->isAnySerialized() || embedded,
"internal/private function cannot be serialized or serializable");
break;
case SILLinkage::PublicExternal:
require(F->isExternalDeclaration() ||
F->isAnySerialized() ||
mod.isSerialized(),
"public-external function definition must be serialized");
break;
case SILLinkage::PackageExternal:
require(F->isExternalDeclaration() ||
F->isAnySerialized() ||
mod.isSerialized(),
"package-external function definition must be serialized");
break;
case SILLinkage::HiddenExternal:
require(F->isExternalDeclaration() || embedded,
"hidden-external function cannot have a body");
break;
}
// Don't verify functions that were skipped. We are likely to see them in
// FunctionBodySkipping::NonInlinableWithoutTypes mode.
auto Ctx = F->getDeclContext();
if (Ctx) {
if (auto AFD = dyn_cast<AbstractFunctionDecl>(Ctx)) {
if (AFD->isBodySkipped())
return;
}
}
if (F->isExternalDeclaration()) {
if (F->hasForeignBody())
return;
require(F->isAvailableExternally(),
"external declaration of internal SILFunction not allowed");
// If F is an external declaration, there is nothing further to do,
// return.
return;
}
require(!FTy->hasErasedIsolation(),
"function declarations cannot have erased isolation");
assert(!F->hasForeignBody());
// Make sure that our SILFunction only has context generic params if our
// SILFunctionType is non-polymorphic.
if (F->getGenericEnvironment() &&
!F->getGenericEnvironment()->getGenericSignature()
->areAllParamsConcrete()) {
require(FTy->isPolymorphic(),
"non-generic function definitions cannot have a "
"generic environment");
} else {
require(!FTy->isPolymorphic(),
"generic function definition must have a generic environment");
}
// Before verifying the body of the function, validate the SILUndef map to
// make sure that all SILUndef in the function's map point at the function
// as the SILUndef's parent.
F->verifySILUndefMap();
// Otherwise, verify the body of the function.
verifyEntryBlock(F->getEntryBlock());
verifyEpilogBlocks(F);
verifyFlowSensitiveRules(F);
verifyBranches(F);
visitSILBasicBlocks(F);
if (F->hasOwnership() && F->shouldVerifyOwnership() &&
!mod.getASTContext().hadError()) {
F->verifyMemoryLifetime(calleeCache);
}
}
void verify(bool isCompleteOSSA) {
if (!isCompleteOSSA || !F.getModule().getOptions().OSSACompleteLifetimes) {
DEBlocks = std::make_unique<DeadEndBlocks>(const_cast<SILFunction *>(&F));
}
visitSILFunction(const_cast<SILFunction*>(&F));
}
};
} // end anonymous namespace
#undef require
#undef requireObjectType
//===----------------------------------------------------------------------===//
// Out of Line Verifier Run Functions
//===----------------------------------------------------------------------===//
static bool verificationEnabled(const SILModule &M) {
// If we are asked to never verify, return false early.
if (M.getOptions().VerifyNone)
return false;
// Otherwise, if verify all is set, we always verify.
if (M.getOptions().VerifyAll)
return true;
#ifndef NDEBUG
// Otherwise if we do have asserts enabled, always verify...
return true;
#else
// And if we don't never verify.
return false;
#endif
}
/// verify - Run the SIL verifier to make sure that the SILFunction follows
/// invariants.
void SILFunction::verify(CalleeCache *calleeCache,
bool SingleFunction, bool isCompleteOSSA,
bool checkLinearLifetime) const {
if (!verificationEnabled(getModule()))
return;
// Please put all checks in visitSILFunction in SILVerifier, not here. This
// ensures that the pretty stack trace in the verifier is included with the
// back trace when the verifier crashes.
SILVerifier verifier(*this, calleeCache, SingleFunction, checkLinearLifetime);
verifier.verify(isCompleteOSSA);
}
void SILFunction::verifyCriticalEdges() const {
if (!verificationEnabled(getModule()))
return;
SILVerifier(*this, /*calleeCache=*/nullptr,
/*SingleFunction=*/true,
/*checkLinearLifetime=*/ false).verifyBranches(this);
}
/// Validate that all SILUndef in \p f have f as a parent.
void SILFunction::verifySILUndefMap() const {
for (auto &pair : undefValues) {
assert(
pair.second->getParent() == this &&
"undef in f->undefValue map with different parent function than f?!");
}
}
/// Verify that a property descriptor follows invariants.
void SILProperty::verify(const SILModule &M) const {
if (!verificationEnabled(M))
return;
auto *decl = getDecl();
auto *dc = decl->getInnermostDeclContext();
// TODO: base type for global/static descriptors
auto sig = dc->getGenericSignatureOfContext();
auto baseTy = dc->getInnermostTypeContext()->getSelfInterfaceType()
->getReducedType(sig);
auto leafTy = decl->getValueInterfaceType()->getReducedType(sig);
SubstitutionMap subs;
if (sig) {
auto env = dc->getGenericEnvironmentOfContext();
subs = env->getForwardingSubstitutionMap();
baseTy = env->mapTypeIntoContext(baseTy)->getCanonicalType();
leafTy = env->mapTypeIntoContext(leafTy)->getCanonicalType();
}
bool hasIndices = false;
if (auto subscript = dyn_cast<SubscriptDecl>(decl)) {
hasIndices = subscript->getIndices()->size() != 0;
}
auto canSig = sig.getCanonicalSignature();
auto require = [&](bool reqt, StringRef message) {
if (!reqt) {
llvm::errs() << message << "\n";
assert(false && "invoking standard assertion failure");
}
};
if (auto &component = getComponent()) {
auto typeExpansionContext =
TypeExpansionContext::noOpaqueTypeArchetypesSubstitution(
ResilienceExpansion::Maximal);
verifyKeyPathComponent(const_cast<SILModule&>(M),
typeExpansionContext,
getSerializedKind(),
require,
baseTy,
leafTy,
*component,
{},
canSig,
subs,
/*property descriptor*/true,
hasIndices);
// verifyKeyPathComponent updates baseTy to be the projected type of the
// component, which should be the same as the type of the declared storage
require(baseTy == leafTy,
"component type of property descriptor should match type of storage");
}
}
/// Verify that a vtable follows invariants.
void SILVTable::verify(const SILModule &M) const {
if (!verificationEnabled(M))
return;
// Compare against the base class vtable if there is one.
const SILVTable *superVTable = nullptr;
auto superclass = getClass()->getSuperclassDecl();
if (superclass) {
for (auto &vt : M.getVTables()) {
if (vt->getClass() == superclass) {
superVTable = vt;
break;
}
}
}
for (unsigned i : indices(getEntries())) {
auto &entry = getEntries()[i];
// Make sure the module's lookup cache is consistent.
assert(entry == *getEntry(const_cast<SILModule &>(M), entry.getMethod())
&& "vtable entry is out of sync with method's vtable cache");
// All vtable entries must be decls in a class context.
assert(entry.getMethod().hasDecl() && "vtable entry is not a decl");
auto baseInfo = M.Types.getConstantInfo(TypeExpansionContext::minimal(),
entry.getMethod());
ValueDecl *decl = entry.getMethod().getDecl();
assert((!isa<AccessorDecl>(decl)
|| !cast<AccessorDecl>(decl)->isObservingAccessor())
&& "observing accessors shouldn't have vtable entries");
// For ivar destroyers, the decl is the class itself.
ClassDecl *theClass;
if (entry.getMethod().kind == SILDeclRef::Kind::IVarDestroyer)
theClass = dyn_cast<ClassDecl>(decl);
else
theClass = dyn_cast<ClassDecl>(decl->getDeclContext());
assert(theClass && "vtable entry must refer to a class member");
// The class context must be the vtable's class, or a superclass thereof.
assert(theClass->isSuperclassOf(getClass()) &&
"vtable entry must refer to a member of the vtable's class");
// Foreign entry points shouldn't appear in vtables.
assert(!entry.getMethod().isForeign && "vtable entry must not be foreign");
// The vtable entry must be ABI-compatible with the overridden vtable slot.
SmallString<32> baseName;
{
llvm::raw_svector_ostream os(baseName);
entry.getMethod().print(os);
}
if (M.getStage() != SILStage::Lowered &&
!M.getASTContext().LangOpts.hasFeature(Feature::Embedded)) {
// Note the direction of the compatibility check: the witness
// function must be compatible with being used as the requirement
// type.
SILVerifier(*entry.getImplementation(), /*calleeCache=*/nullptr,
/*SingleFunction=*/true,
/*checkLinearLifetime=*/ false)
.requireABICompatibleFunctionTypes(
entry.getImplementation()->getLoweredFunctionType(),
baseInfo.getSILType().castTo<SILFunctionType>(),
"vtable entry for " + baseName + " must be ABI-compatible",
*entry.getImplementation());
}
// Validate the entry against its superclass vtable.
if (!superclass) {
// Root methods should not have inherited or overridden entries.
bool validKind;
switch (entry.getKind()) {
case Entry::Normal:
validKind = true;
break;
case Entry::Inherited:
case Entry::Override:
validKind = false;
break;
}
assert(validKind && "vtable entry in root class must not be inherited or override");
} else if (superVTable) {
// Validate the entry against the matching entry from the superclass
// vtable.
const Entry *superEntry = nullptr;
for (auto &se : superVTable->getEntries()) {
if (se.getMethod().getOverriddenVTableEntry() ==
entry.getMethod().getOverriddenVTableEntry()) {
superEntry = &se;
break;
}
}
switch (entry.getKind()) {
case Entry::Normal:
assert(!superEntry && "non-root vtable entry must be inherited or override");
break;
case Entry::Inherited:
if (!superEntry)
break;
assert(entry.isNonOverridden() == superEntry->isNonOverridden()
&& "inherited vtable entry must share overridden-ness of superclass entry");
break;
case Entry::Override:
assert(!entry.isNonOverridden()
&& "override entry can't claim to be nonoverridden");
if (!superEntry)
break;
// The superclass entry must not prohibit overrides.
assert(!superEntry->isNonOverridden()
&& "vtable entry overrides an entry that claims to have no overrides");
// TODO: Check the root vtable entry for the method too.
break;
}
}
}
}
/// Verify that a witness table follows invariants.
void SILWitnessTable::verify(const SILModule &M) const {
if (!verificationEnabled(M))
return;
if (isDeclaration())
assert(getEntries().empty() &&
"A witness table declaration should not have any entries.");
for (const Entry &E : getEntries())
if (E.getKind() == SILWitnessTable::WitnessKind::Method) {
SILFunction *F = E.getMethodWitness().Witness;
if (F) {
// If a SILWitnessTable is going to be serialized, it must only
// reference public or serializable functions.
if (isAnySerialized()) {
assert(F->hasValidLinkageForFragileRef(getSerializedKind()) &&
"Fragile witness tables should not reference "
"less visible functions.");
}
assert(F->getLoweredFunctionType()->getRepresentation() ==
SILFunctionTypeRepresentation::WitnessMethod &&
"Witnesses must have witness_method representation.");
}
}
}
/// Verify that a default witness table follows invariants.
void SILDefaultWitnessTable::verify(const SILModule &M) const {
#ifndef NDEBUG
for (const Entry &E : getEntries()) {
// FIXME: associated type witnesses.
if (!E.isValid() || E.getKind() != SILWitnessTable::Method)
continue;
SILFunction *F = E.getMethodWitness().Witness;
if (!F)
continue;
#if 0
// FIXME: For now, all default witnesses are private.
assert(F->hasValidLinkageForFragileRef(IsSerialized) &&
"Default witness tables should not reference "
"less visible functions.");
#endif
assert(F->getLoweredFunctionType()->getRepresentation() ==
SILFunctionTypeRepresentation::WitnessMethod &&
"Default witnesses must have witness_method representation.");
}
#endif
}
/// Verify that a global variable follows invariants.
void SILGlobalVariable::verify() const {
if (!verificationEnabled(getModule()))
return;
assert(getLoweredType().isObject()
&& "global variable cannot have address type");
// Verify the static initializer.
for (const SILInstruction &I : StaticInitializerBlock) {
auto init = cast<SingleValueInstruction>(&I);
if (init == &StaticInitializerBlock.back()) {
assert(init->use_empty() && "Init value must not have another use");
if (auto *vi = dyn_cast<VectorInst>(init)) {
for (SILValue element : vi->getElements()) {
assert(element->getType() == vi->getType() &&
"all vector elements must be of the same type");
}
}
} else {
assert(!init->use_empty() && "dead instruction in static initializer");
assert(!isa<ObjectInst>(init) &&
"object instruction is only allowed for final initial value");
assert(!isa<VectorInst>(init) &&
"vector instruction is only allowed for final initial value");
}
assert(I.getParent() == &StaticInitializerBlock);
}
}
void SILModule::verify(bool isCompleteOSSA, bool checkLinearLifetime) const {
CalleeCache calleeCache(*const_cast<SILModule *>(this));
verify(&calleeCache, isCompleteOSSA, checkLinearLifetime);
}
/// Verify the module.
void SILModule::verify(CalleeCache *calleeCache,
bool isCompleteOSSA, bool checkLinearLifetime) const {
if (!verificationEnabled(*this))
return;
// Uniquing set to catch symbol name collisions.
llvm::DenseSet<StringRef> symbolNames;
// Check all functions.
for (const SILFunction &f : *this) {
if (!symbolNames.insert(f.getName()).second) {
llvm::errs() << "Symbol redefined: " << f.getName() << "!\n";
assert(false && "triggering standard assertion failure routine");
}
f.verify(calleeCache, /*singleFunction*/ false, isCompleteOSSA, checkLinearLifetime);
}
// Check all globals.
for (const SILGlobalVariable &g : getSILGlobals()) {
if (!symbolNames.insert(g.getName()).second) {
llvm::errs() << "Symbol redefined: " << g.getName() << "!\n";
assert(false && "triggering standard assertion failure routine");
}
g.verify();
}
// Check all vtables and the vtable cache.
llvm::DenseSet<ClassDecl*> vtableClasses;
unsigned EntriesSZ = 0;
for (const auto &vt : getVTables()) {
if (!vt->isSpecialized() && !vtableClasses.insert(vt->getClass()).second) {
llvm::errs() << "Vtable redefined: " << vt->getClass()->getName() << "!\n";
assert(false && "triggering standard assertion failure routine");
}
vt->verify(*this);
// Check if there is a cache entry for each vtable entry
for (auto entry : vt->getEntries()) {
if (VTableEntryCache.find({vt, entry.getMethod()}) ==
VTableEntryCache.end()) {
llvm::errs() << "Vtable entry for function: "
<< entry.getImplementation()->getName()
<< "not in cache!\n";
assert(false && "triggering standard assertion failure routine");
}
++EntriesSZ;
}
}
assert(EntriesSZ == VTableEntryCache.size() &&
"Cache size is not equal to true number of VTable entries");
// Check all witness tables.
LLVM_DEBUG(llvm::dbgs() <<"*** Checking witness tables for duplicates ***\n");
llvm::DenseSet<RootProtocolConformance*> wtableConformances;
for (const SILWitnessTable &wt : getWitnessTables()) {
LLVM_DEBUG(llvm::dbgs() << "Witness Table:\n"; wt.dump());
auto conformance = wt.getConformance();
if (!wtableConformances.insert(conformance).second) {
llvm::errs() << "Witness table redefined: ";
conformance->printName(llvm::errs());
assert(false && "triggering standard assertion failure routine");
}
wt.verify(*this);
}
// Check all default witness tables.
LLVM_DEBUG(llvm::dbgs() << "*** Checking default witness tables for "
"duplicates ***\n");
llvm::DenseSet<const ProtocolDecl *> defaultWitnessTables;
for (const SILDefaultWitnessTable &wt : getDefaultWitnessTables()) {
LLVM_DEBUG(llvm::dbgs() << "Default Witness Table:\n"; wt.dump());
if (!defaultWitnessTables.insert(wt.getProtocol()).second) {
llvm::errs() << "Default witness table redefined: ";
wt.dump();
assert(false && "triggering standard assertion failure routine");
}
wt.verify(*this);
}
// Check property descriptors.
LLVM_DEBUG(llvm::dbgs() << "*** Checking property descriptors ***\n");
for (auto &prop : getPropertyList()) {
prop.verify(*this);
}
}
|