�����JFIF��XX����������    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222�����"����4���������������������������� ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������,�PG"Z_�4�˷����kjز�Z�,F+��_z�,�© �����zh6�٨�ic�fu������������������������������������#ډb���_�N��?�����������wQ���5-�~�I���8���������������������������������TK<5o�Iv-������������������k�_U_������������������������������~b�M��d��������Ӝ�U�Hh��?]��E�w��Q���k�{��_}qFW7HTՑ��Y��F�����?_�'ϔ��_�Ջt������������������������=||I �����6�έ"�����D���/[�k�9����Y�8������ds|\���Ҿp6�Ҵ���]��.����6���z<�v��@]�i%������������������������$j��~����g��J>��no����pM[me�i$[�����������s�o�ᘨ�˸ nɜG-�ĨU�ycP���3.DB�li�;���������������������hj���x����7Z^�N�h��������N3u{�:j�����x�힞��#M��&��jL P@��_���� P�������������������&��o8��������9������@Sz���6�t7#O�ߋ �����s}Yf�T������lmr����Z)'N��k�۞p�����w\�T���������������ȯ?�8`���O��i{wﭹW�[�r�� ��Q4F�׊������3m&L�=��h3�������z~��#����\�l :�F,j@�� ʱ�wQT����8�"kJO����6�֚l������������������}����R�>ډK���]��y����&����p�}b������;N�1�m�r$����|��7�>e�@���B�TM*-i�H��g�D�)� E�m�|�ؘbҗ�a���Ҿ����������������t4�����o���G��*oCN�rP���Q��@z,|?W[0���������:�n,j���WiE��W������$~/�hp\��?��{(�0���+�Y8rΟ�+����>S-S���������������VN;���}�s?.����� w��9��˟<���Mq4�Wv'������{)0�1mB����V����W[��������8�/<� �%���wT^�5���b��)iM� p�g�N�&ݝ������������VO~��q���u���9��� ����!��J27�����$����O-���! �:���%H��� ـ�������y�ΠM=t{!S�� �oK8�������t<����è��������:a��������[������ա�H���~��w��Qz`�p����o�^ ������Q��n����� �,uu�C��$ ^���,�������8�#��:�6��e�|~�����������!�3��3.�\0�����q��o�4`.|� ����y�Q�`~;�d�ׯ,��O�Zw�������`73�v�܋�<�����Ȏ�� ـ4k��5�K�a�u�=9Yd��$>x�A�&�� j0� ���vF��� Y���|�y��� ~�6�@c��1vOp��������Ig�����4��l�OD�����L����� R���c���j�_�uX�6��3?nk��Wy�f;^*B� ��@���~a�`��Eu�������+�����6�L��.ü>��}y���}_�O�6�͐�:�Yr���G�X��kG������l^w����������~㒶sy���Iu�!���� W ��X��N�7BV��O��!X�2����wvG�R�f�T#�����t�/?���%8�^�W�aT����G�cL�M���I��(J����1~�8�?aT ���]����AS�E��(��*E}� 2������#I/�׍qz��^t�̔���������b�Yz4x����t�){ OH�����+(E��A&�N�������XT��o��"�XC����'���)}�J�z�p� ����~5�}�^����+�6����w��c��Q�|�Lp�d�H��}�(�.|����k��c4^�����"�����Z?ȕ ��a<�������L�!0�39C� �Eu�����C�F�Ew�ç ;�n?�*o���B�8�bʝ���'#Rqf����M}7����]�������s2tcS{�\icTx;�\��7K���P������ʇ Z O-��~�������c>"��?��������P�����E��O�8��@�8��G��Q�g�a�Վ���󁶠��䧘��_%#r�>�����1�z�a���eb��qcP��ѵ��n���#L��� =��׀t� L�7�`�����V����A{�C:�g���e@�����w1 Xp�3�c3�ġ�������p��M"'-�@n4���fG���B3�DJ�8[Jo�ߐ���gK)ƛ��$���� �������8�3�����+���� �����6�ʻ���� ���S�kI�*KZlT _`�������?��K�����QK�d���������B`�s}�>���`������*�>��,*@J�d�oF*�����弝��O}�k��s��]��y�ߘ�������c1G�V���<=�7��7����6��q�PT��tXԀ�!9*4�4Tހ���3XΛex�46�������Y��D ����� ����BdemDa����\�_l,����G�/���֌7���Y�](�xTt^%�GE�����4�}bT����ڹ�����;��Y)���B�Q��u��>J/J ���⮶.�XԄ��j�ݳ������+E��d ���r�5�_D�����1 ���o�� �B�x�΢�#����<��W�����8���R6�@���g�M�.��� dr�D��>(otU��@�x=��~v���2� ӣ�d�oBd�����3�eO�6�㣷����������ݜ�6��6Y��Qz`����S��{���\P��~z m5{J/L��1������<�e�ͅPu���b�]�ϔ��������'�������f�b� Zpw��c`"��i���BD@:)ִ�:�]��h���v�E��w���T�l�������P����"Ju�}��وV ��J��G6��. J/�Qgl߭�e�����@�z�Zev2u����)]կ���������7x�������s�M�-<ɯ�c��r��v�����@��$�ޮ}lk���a����'����>x��O\�Z������Fu>������ck#��&:��`�$��ai�>2Δ����l���oF[h�������lE�ܺ�Π���k:)���`������� $[6�����9�����kOw�\|�����8}������ބ:��񶐕��������I�A1/���=�2[�,�!��.}gN#�u����b���� ~���������݊��}34q�����d�E��L��������c��$���"�[q�U�硬g^��%B ��z���r�p�������J�ru%v\h�����1Y�ne`������ǥ:g����pQM~�^��Xi� ��`S�:V2������9.�P���V������?B�k�� ��������AEvw%�_�9C�Q����wKekP�ؠ�\������;Io d�{ ߞo�c1eP�����\� `����E=���@K<�Y��������eڼ�J����w����{av�F�'�M�@��������������/J��+9p����|]���������Iw &`���8���&�M�hg���[�{�������Xj���%��Ӓ�������������������$��(�����ʹN�������<>�I���RY�����K2�NPlL�ɀ�)��&e��������B+ь����(������������������� � �JTx����_?EZ� }@���� 6�U���뙢ط�z��dWI��n` D����噥�[��uV��"�G&�����Ú����2�g�}&m���������������������?ċ���"����Om#�������������������������� ��{���������������������ON��"S�X���Ne��ysQ���@�������������Fn��Vg�����dX�~nj����������������������]J�<�K]:����FW���b�������62����������=��5f����JKw����bf�X������������������������55��~J �%^�������:�-�QIE��P��v�nZum� z � ~ə ���� ���ة����;�f��\v�������g�8�1��f2�������������������������4;�V���ǔ�)�������������������9���1\������������������������������c��v�/'Ƞ�w������������������$�4�R-��t����������������������������������� e�6�/�ġ �̕Ecy�J���u�B���<�W�ַ~�w[B1L۲�-JS΂�{���΃�������������������������������������������A��20�c#���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@���� 0!1@AP"#2Q`$3V�%45a6�FRUq����� ������^7ׅ,$n��������+��F�`��2X'��0vM��p�L=�������5��8������u�p~���.�`r�����\����O��,ư�0oS ��_�M�����l���4�kv\JSd���x���SW�<��Ae�IX����������$I���w�:S���y���›R��9�Q[���,�5�;�@]�%���u�@ *ro�lbI �� ��+���%m:�͇ZV�����u�̉����θau<�fc�.����{�4Ա� �Q����*�Sm��8\ujqs]{kN���)qO�y�_*dJ�b�7���yQqI&9�ԌK!�M}�R�;�������S�T���1���i[U�ɵz�]��U)V�S6���3$K{��ߊ<�(� E]Զ[ǼENg�����'�\?#)Dkf��J���o��v���'�%ƞ�&K�u��!��b�35LX�Ϸ��63$K�a�;�9>,R��W��3�3� d�JeTYE.Mϧ��-�o�j3+y��y^�c�������VO�9NV\nd�1 ��!͕_)a�v;����թ�M�lWR1��)El��P;��yوÏ�u 3�k�5Pr6<�⒲l�!˞*��u־�n�!�l:����UNW ��%��Chx8vL'��X�@��*��)���̮��ˍ��� ����D-M�+J�U�kvK����+�x8��cY������?�Ԡ��~3mo��|�u@[XeY�C�\Kp�x8�oC�C�&����N�~3-H���� ��MX�s�u<`���~"WL��$8ξ��3���a�)|:@�m�\���^�`�@ҷ)�5p+��6���p�%i)P M���ngc�����#0Aruz���RL+xSS?���ʮ}()#�t��mˇ!��0}}y����<�e� �-ή�Ԩ��X������ MF���ԙ~l L.3���}�V뽺�v������멬��Nl�)�2����^�Iq��a��M��qG��T�����c3#������3U�Ǎ���}��לS�|qa��ڃ�+���-��2�f����/��bz��ڐ�� �ݼ[2�ç����k�X�2�* �Z�d���J�G����M*9W���s{��w���T��x��y,�in�O�v��]���n����P�$��JB@=4�OTI�n��e�22a\����q�d���%�$��(���:���: /*�K[PR�fr\nڙdN���F�n�$�4��[�� U�zƶ����� �mʋ���,�ao�u 3�z� �x��Kn����\[��VFmbE;�_U��&V�Gg�]L�۪&#n%�$ɯ��dG���D�TI=�%+AB�Ru#��b4�1�»x�cs�YzڙJG��f��Il���d�eF'T� iA��T���uC�$����Y��H?����[!G`}���ͪ� �纤Hv\������j�Ex�K���!���OiƸ�Yj�+u-<���'q����uN�*�r\��+�]���<�wOZ.fp�ێ��,-*)V?j-kÊ#�`�r��dV����(�ݽBk�����G�ƛk�QmUڗe��Z���f}|����8�8��a���i��3'J�����~G_�^���d�8w������ R�`(�~�.��u���l�s+g�bv���W���lGc}��u���afE~1�Ue������Z�0�8�=e�� f@/�jqEKQQ�J���oN��J���W5~M>$6�Lt�;$ʳ{���^��6�{����v6���ķܰg�V�cnn �~z�x�«�,2�u�?cE+Ș�H؎�%�Za�)���X>uW�Tz�Nyo����s���FQƤ��$��*�&�LLXL)�1�" L��eO��ɟ�9=���:t��Z���c��Ž���Y?�ӭV�wv�~,Y��r�ۗ�|�y��GaF�����C�����.�+� ���v1���fήJ�����]�S��T��B��n5sW}y�$��~z�'�c ��8 ��� ,! �p��VN�S��N�N�q��y8z˱�A��4��*��'������2n<�s���^ǧ˭P�Jޮɏ�U�G�L�J�*#��<�V��t7�8����TĜ>��i}K%,���)[��z�21z ?�N�i�n1?T�I�R#��m-�����������������1����lA�`��fT5+��ܐ�c�q՝��ʐ��,���3�f2U�եmab��#ŠdQ�y>\��)�SLY����w#��.���ʑ�f��� ,"+�w�~�N�'�c�O�3F�������N<���)j��&��,-� �љ���֊�_�zS���TǦ����w�>��?�������n��U仆�V���e�����0���$�C�d���rP �m�׈e�Xm�Vu� �L��.�bֹ��� �[Դaզ���*��\y�8�Է:�Ez\�0�Kq�C b��̘��cө���Q��=0Y��s�N��S.����3.���O�o:���#���v7�[#߫ ��5�܎�L���Er4���9n��COWlG�^��0k�%<���ZB���aB_���������'=��{i�v�l�$�uC���mƎҝ{�c㱼�y]���W�i ��ߧc��m�H� m�"�"�����;Y�ߝ�Z�Ǔ�����:S#��|}�y�,/k�Ld� TA�(�AI$+I3��;Y*���Z��}|��ӧO��d�v��..#:n��f>�>���ȶI�TX��� 8��y����"d�R�|�)0���=���n4��6ⲑ�+��r<�O�܂~zh�z����7ܓ�HH�Ga롏���nCo�>������a ���~]���R���̲c?�6(�q�;5%� |�uj�~z8R�=X��I�V=�|{v�Gj\gc��q����z�؋%M�ߍ����1y��#��@f^���^�>N������#x#۹��6�Y~�?�dfPO��{��P�4��V��u1E1J �*|���%����JN��`eWu�zk M6���q t[�� ��g�G���v��WIG��u_ft����5�j�"�Y�:T��ɐ���*�;� e5���4����q$C��2d�}���� _S�L#m�Yp��O�.�C�;��c����Hi#֩%+) �Ӎ��ƲV���SYź��g |���tj��3�8���r|���V��1#;.SQ�A[���S������#���`n�+���$��$�I �P\[�@�s��(�ED�z���P��])8�G#��0B��[ى��X�II�q<��9�~[Z멜�Z�⊔IWU&A>�P~�#��dp<�?����7���c��'~���5 ��+$���lx@�M�dm��n<=e�dyX��?{�|Aef ,|n3�<~z�ƃ�uۧ�����P��Y,�ӥQ�*g�#먙R�\���;T��i,��[9Qi歉����c>]9�� ��"�c��P�� �Md?٥��If�ت�u��k��/����F��9�c*9��Ǎ:�ØF���z�n*�@|I�ށ9����N3{'��[�'ͬ�Ҳ4��#}��!�V� Fu��,�,mTIk���v C�7v���B�6k�T9��1�*l� '~��ƞF��lU��'�M ����][ΩũJ_�{�i�I�n��$����L�� j��O�dx�����kza۪��#�E��Cl����x˘�o�����V���ɞ�ljr��)�/,�߬h�L��#��^��L�ф�,íMƁe�̩�NB�L�����iL����q�}��(��q��6IçJ$�W�E$��:������=#����(�K�B����zђ <��K(�N�۫K�w��^O{!����)��H���>x�������lx�?>Պ�+�>�W���,Ly!_�D���Ō�l���Q�!�[ �S����J��1��Ɛ�Y}��b,+�Lo�x�ɓ)����=�y�oh�@�꥟/��I��ѭ=��P�y9��� �ۍYӘ�e+�p�Jnϱ?V\SO%�(�t� ���=?MR�[Ș�����d�/ ��n�l��B�7j� ��!�;ӥ�/�[-���A�>��dN�sLj ��,ɪv��=1c�.SQ�O3�U���ƀ�ܽ�E����������̻��9G�ϷD�7(�}��Ävӌ\��y�_0[w ���<΍>����a_��[0+�L��F.�޺��f�>oN�T����q;���y\��bՃ��y�jH�<|q-eɏ�_?_9+P���Hp$�����[ux�K w�Mw��N�ی'$Y2�=��q���KB��P��~�������Yul:�[<����F1�2�O���5=d����]Y�sw:���Ϯ���E��j,_Q��X��z`H1,#II ��d�wr��P˂@�ZJV����y$�\y�{}��^~���[:N����ߌ�U�������O��d�����ؾe��${p>G��3c���Ė�lʌ�� ת��[��`ϱ�-W����dg�I��ig2��� ��}s ��ؤ(%#sS@���~���3�X�nRG�~\jc3�v��ӍL��M[JB�T��s3}��j�Nʖ��W����;7���ç?=X�F=-�=����q�ߚ���#���='�c��7���ڑW�I(O+=:uxq�������������e2�zi+�kuG�R��������0�&e�n���iT^J����~\jy���p'dtG��s����O��3����9* �b#Ɋ�� p������[Bws�T�>d4�ۧs���nv�n���U���_�~,�v����ƜJ1��s�� �QIz���)�(lv8M���U=�;����56��G���s#�K���MP�=��LvyGd��}�VwWBF�'�à �?MH�U�g2�� ����!�p�7Q��j��ڴ����=��j�u��� Jn�A s���uM������e��Ɔ�Ҕ�!)�'��8Ϣ�ٔ���ޝ(��Vp���צ֖d=�IC�J�Ǡ{q������kԭ�߸���i��@K����u�|�p=..�*+����x�����z[Aqġ#s2a�Ɗ���RR�)*HRsi�~�a &f��M��P����-K�L@��Z��Xy�'x�{}��Zm+���:�)�) IJ�-i�u���� ���ܒH��'��L(7�y�GӜq���� j��� 6ߌg1�g�o���,kر���tY�?W,���p���e���f�OQS��!K�۟cҒA�|ս�j�>��=⬒��˧L[�� �߿2JaB~R��u�:��Q�] �0H~���]�7��Ƽ�I���(�}��cq '�ήET���q�?f�ab���ӥvr� �)o��-Q��_'����ᴎo��K������;��V���o��%���~OK ����*��b�f:���-ťIR��`B�5!RB@���ï�� �u �̯e\�_U�_������� g�ES��3��������QT��a�����x����U<~�c?�*�#]�MW,[8O�a�x��]�1bC|踤�P��lw5V%�)�{t�<��d��5���0i�XSU��m:��Z�┵�i�"��1�^B�-��P�hJ��&)O��*�D��c�W��vM��)����}���P��ܗ-q����\mmζZ-l@�}��a��E�6��F�@��&Sg@���ݚ�M����� ȹ 4����#p�\H����dYDo�H���"��\��..R�B�H�z_�/5˘����6��KhJR��P�mƶi�m���3��,#c�co��q�a)*P�t����R�m�k�7x�D�E�\Y�閣_X�<���~�)���c[[�BP����6�Yq���S��0����%_����;��Àv�~�| VS؇ ��'O0��F0��\���U�-�d@�����7�SJ*z��3n��y��P����O����������m�~�P�3|Y��ʉr#�C�<�G~�.,! ���bqx���h~0=��!ǫ�jy����l��O,�[B��~��|9��ٱ����Xly�#�i�B��g%�S��������tˋ���e���ې��\[d�t)��.+u�|1 ������#�~Oj����hS�%��i.�~X���I�H�m��0n���c�1uE�q��cF�RF�o���7� �O�ꮧ� ���ۛ{��ʛi5�rw?׌#Qn�TW��~?y$��m\�\o����%W� ?=>S�N@�� �Ʈ���R����N�)�r"C�:��:����� �����#��qb��Y�. �6[��2K����2u�Ǧ�HYR��Q�MV��� �G�$��Q+.>�����nNH��q�^��� ����q��mM��V��D�+�-�#*�U�̒ ���p욳��u:�������IB���m����PV@O���r[b= �� ��1U�E��_Nm�yKbN�O���U�}�the�`�|6֮P>�\2�P�V���I�D�i�P�O;�9�r�mAHG�W�S]��J*�_�G��+kP�2����Ka�Z���H�'K�x�W�MZ%�O�YD�Rc+o��?�q��Ghm��d�S�oh�\�D�|:W������UA�Qc yT�q��������~^�H��/��#p�CZ���T�I�1�ӏT����4��"�ČZ�����}��`w�#�*,ʹ�� ��0�i��課�Om�*�da��^gJ݅{���l�e9uF#T�ֲ��̲�ٞC"�q���ߍ ոޑ�o#�XZTp����@ o�8��(jd��xw�]�,f���`~��|,s��^����f�1���t��|��m�򸄭/ctr��5s��7�9Q�4�H1꠲BB@�l9@���C�����+�wp�xu�£Yc�9��?`@#�o�mH�s2��)�=��2�.�l����jg�9$�Y�S�%*L������R�Y������7Z���,*=�䷘$�������arm�o�ϰ���UW.|�r�uf����IGw�t����Zwo��~5 ��YյhO+=8fF�)�W�7�L9lM�̘·Y���֘YLf�큹�pRF���99.A �"wz��=E\Z���'a� 2��Ǚ�#;�'}�G���*��l��^"q��+2FQ� hj��kŦ��${���ޮ-�T�٭cf�|�3#~�RJ����t��$b�(R��(����r���dx� >U b�&9,>���%E\� Ά�e�$��'�q't��*�א���ެ�b��-|d���SB�O�O��$�R+�H�)�܎�K��1m`;�J�2�Y~9��O�g8=vqD`K[�F)k�[���1m޼c��n���]s�k�z$@��)!I �x՝"v��9=�ZA=`Ɠi �:�E��)`�7��vI��}d�YI�_ �o�:ob���o ���3Q��&D&�2=�� �Ά��;>�h����y.*ⅥS������Ӭ�+q&����j|UƧ�����}���J0��WW< ۋS�)jQR�j���Ư��rN)�Gű�4Ѷ(�S)Ǣ�8��i��W52���No˓� ۍ%�5brOn�L�;�n��\G����=�^U�dI���8$�&���h��'���+�(������cȁ߫k�l��S^���cƗjԌE�ꭔ��gF���Ȓ��@���}O���*;e�v�WV���YJ\�]X'5��ղ�k�F��b 6R�o՜m��i N�i�����>J����?��lPm�U��}>_Z&�KK��q�r��I�D�Չ~�q�3fL�:S�e>���E���-G���{L�6p�e,8��������QI��h��a�Xa��U�A'���ʂ���s�+טIjP�-��y�8ۈZ?J$��W�P� ��R�s�]��|�l(�ԓ��sƊi��o(��S0���Y� 8�T97.�����WiL��c�~�dxc�E|�2!�X�K�Ƙਫ਼�$((�6�~|d9u+�qd�^3�89��Y�6L�.I�����?���iI�q���9�)O/뚅����O���X��X�V��ZF[�یgQ�L��K1���RҖr@v�#��X�l��F���Нy�S�8�7�kF!A��sM���^rkp�jP�DyS$N���q���nxҍ!U�f�!eh�i�2�m����`�Y�I�9r�6� �TF���C}/�y�^���Η���5d�'��9A-��J��>{�_l+�`��A���[�'��յ�ϛ#w:݅�%��X�}�&�PSt�Q�"�-��\縵�/����$Ɨh�Xb�*�y��BS����;W�ջ_mc�����vt?2}1�;qS�d�d~u:2k5�2�R�~�z+|HE!)�Ǟl��7`��0�<�,�2*���Hl-��x�^����'_TV�gZA�'j� ^�2Ϊ��N7t�����?w�� �x1��f��Iz�C-Ȗ��K�^q�;���-W�DvT�7��8�Z�������� hK�(P:��Q- �8�n�Z���܃e貾�<�1�YT<�,�����"�6{�/ �?�͟��|1�:�#g��W�>$����d��J��d�B���=��jf[��%rE^��il:��B���x���Sּ�1հ��,�=��*�7 fcG��#q� �eh?��2�7�����,�!7x��6�n�LC�4x��},Geǝ�tC.��vS �F�43��zz\��;QYC,6����~;RYS/6���|2���5���v��T��i����������mlv��������&� �nRh^ejR�LG�f���? �ۉҬܦƩ��|��Ȱ����>3����!v��i�ʯ�>�v��オ�X3e���_1z�Kȗ\<������!�8���V��]��?b�k41�Re��T�q��mz��TiOʦ�Z��Xq���L������q"+���2ۨ��8}�&N7XU7Ap�d�X��~�׿��&4e�o�F��� �H�����O���č�c�� 懴�6���͉��+)��v;j��ݷ�� �UV�� i��� j���Y9GdÒJ1��詞�����V?h��l�����l�cGs�ځ�������y�Ac������\V3�? �� ܙg�>qH�S,�E�W�[�㺨�uch�⍸�O�}���a��>�q�6�n6�����N6�q��������N� ���! 1AQaq�0@����"2BRb�#Pr���3C`��Scst���$4D���%Td���� ?�����N����a��3��m���C���w��������xA�m�q�m����m������$����4n淿t'��C"w��zU=D�\R+w�p+Y�T�&�պ@��ƃ��3ޯ?�Aﶂ��aŘ���@-�����Q�=���9D��ռ�ѻ@��M�V��P��܅�G5�f�Y<�u=,EC)�<�Fy'�"�&�չ�X~f��l�KԆV��?�� �W�N����=(� �;���{�r����ٌ�Y���h{�١������jW����P���Tc�����X�K�r��}���w�R��%��?���E��m�� �Y�q|����\lEE4����r���}�lsI�Y������f�$�=�d�yO����p�����yBj8jU�o�/�S��?�U��*������ˍ�0�������u�q�m [�?f����a�� )Q�>����6#������� ?����0UQ����,IX���(6ڵ[�DI�MNލ�c&���υ�j\��X�R|,4��� j������T�hA�e��^���d���b<����n�� �즇�=!���3�^�`j�h�ȓr��jẕ�c�,ٞX����-����a�ﶔ���#�$��]w�O��Ӫ�1y%��L�Y<�wg#�ǝ�̗`�x�xa�t�w��»1���o7o5��>�m뭛C���Uƃߜ}�C���y1Xνm�F8�jI���]����H���ۺиE@I�i;r�8ӭ�����V�F�Շ| ��&?�3|x�B�MuS�Ge�=Ӕ�#BE5G������Y!z��_e��q�р/W>|-�Ci߇�t�1ޯќd�R3�u��g�=0 5��[?�#͏��q�cf���H��{ ?u�=?�?ǯ���}Z��z���hmΔ�BFTW�����<�q��(v� ��!��z���iW]*�J�V�z��gX֧A�q�&��/w���u�gYӘa���; �i=����g:��?2�dž6�ى�k�4�>�Pxs����}������G�9���3 ���)gG�R<>r h�$��'nc�h�P��Bj��J�ҧH� -��N1���N��?��~��}-q!=��_2hc�M��l�vY%UE�@|�v����M2�.Y[|y�"Eï��K�ZF,�ɯ?,q�?v�M 80jx�"�;�9vk�����+ ֧�� �ȺU��?�%�vcV��mA�6��Qg^M�����A}�3�nl� QRN�l8�kkn�'�����(��M�7m9و�q���%ޟ���*h$Zk"��$�9��: �?U8�Sl��,,|ɒ��xH(ѷ����Gn�/Q�4�P��G�%��Ա8�N��!� �&�7�;���eKM7�4��9R/%����l�c>�x;������>��C�:�����t��h?aKX�bhe�ᜋ^�$�Iհ �hr7%F$�E��Fd���t��5���+�(M6�t����Ü�UU|zW�=a�Ts�Tg������dqP�Q����b'�m���1{|Y����X�N��b �P~��F^F:����k6�"�j!�� �I�r�`��1&�-$�Bevk:y���#y�w��I0��x��=D�4��tU���P�ZH��ڠ底taP��6����b>�xa�����Q�#� WeF��ŮNj�p�J* mQ�N�����*I�-*�ȩ�F�g�3 �5��V�ʊ�ɮ�a��5F���O@{���NX��?����H�]3��1�Ri_u��������ѕ�� ����0��� F��~��:60�p�͈�S��qX#a�5>���`�o&+�<2�D����: �������ڝ�$�nP���*)�N�|y�Ej�F�5ټ�e���ihy�Z �>���k�bH�a�v��h�-#���!�Po=@k̆IEN��@��}Ll?j�O������߭�ʞ���Q|A07x���wt!xf���I2?Z��<ץ�T���cU�j��]���陎Ltl �}5�ϓ��$�,��O�mˊ�;�@O��jE��j(�ا,��LX���LO���Ц�90�O �.����a��nA���7������j4 ��W��_ٓ���zW�jcB������y՗+EM�)d���N�g6�y1_x��p�$Lv�:��9�"z��p���ʙ$��^��JԼ*�ϭ����o���=x�Lj�6�J��u82�A�H�3$�ٕ@�=Vv�]�'�qEz�;I˼��)��=��ɯ���x �/�W(V���p�����$ �m�������u�����񶤑Oqˎ�T����r��㠚x�sr�GC��byp�G��1ߠ�w e�8�$⿄����/�M{*}��W�]˷.�CK\�ުx���/$�WP�w���r� |i���&�}�{�X� �>��$-��l���?-z���g����lΆ���(F���h�vS*���b���߲ڡn,|)mrH[���a�3�ר�[1��3o_�U�3�TC�$��(�=�)0�kgP���� ��u�^=��4 �WYCҸ:��vQ�ר�X�à��tk�m,�t*��^�,�}D*�� �"(�I��9R����>`�`��[~Q]�#af��i6l��8���6�:,s�s�N6�j"�A4���IuQ��6E,�GnH��zS�HO�uk�5$�I�4��ؤ�Q9�@��C����wp��BGv[]�u�Ov����0I4���\��y�����Q�Ѹ��~>Z��8�T��a��q�ޣ;z��a���/��S��I:�ܫ_�|������>=Z����8:�S��U�I�J��"IY���8%b8���H��:�QO�6�;7�I�S��J��ҌAά3��>c���E+&jf$eC+�z�;��V����� �r���ʺ������my�e���aQ�f&��6�ND���.:��NT�vm�<- u���ǝ\MvZY�N�NT��-A�>jr!S��n�O 1�3�Ns�%�3D@���`������ܟ 1�^c<���� �a�ɽ�̲�Xë#�w�|y�cW�=�9I*H8�p�^(4���՗�k��arOcW�tO�\�ƍR��8����'�K���I�Q�����?5�>[�}��yU�ײ -h��=��% q�ThG�2�)���"ו3]�!kB��*p�FDl�A���,�eEi�H�f�Ps�����5�H:�Փ~�H�0Dت�D�I����h�F3�������c��2���E��9�H��5�zԑ�ʚ�i�X�=:m�xg�hd(�v����׊�9iS��O��d@0ڽ���:�p�5�h-��t�&���X�q�ӕ,��ie�|���7A�2���O%P��E��htj��Y1��w�Ѓ!����  ���� ࢽ��My�7�\�a�@�ţ�J ��4�Ȼ�F�@o�̒?4�wx��)��]�P��~�����u�����5�����7X ��9��^ܩ�U;Iꭆ 5 �������eK2�7(�{|��Y׎ �V��\"���Z�1� Z�����}��(�Ǝ"�1S���_�vE30>���p;� ΝD��%x�W�?W?v����o�^V�i�d��r[��/&>�~`�9Wh��y�;���R���� ;;ɮT��?����r$�g1�K����A��C��c��K��l:�'��3 c�ﳯ*"t8�~l��)���m��+U,z��`(��>yJ�?����h>��]��v��ЍG*�{`��;y]��I�T� ;c��NU�fo¾h���/$���|NS���1�S�"�H��V���T���4��uhǜ�]�v;���5�͠x��'C\�SBpl���h}�N����� A�Bx���%��ޭ�l��/����T��w�ʽ]D�=����K���ž�r㻠l4�S�O?=�k �M:� ��c�C�a�#ha���)�ѐxc�s���gP�iG���{+���x���Q���I= �� z��ԫ+ �8"�k�ñ�j=|����c ��y��CF��/���*9ж�h{ �?4�o� ��k�m�Q�N�x��;�Y��4膚�a�w?�6�>�e]�����Q�r�:����g�,i"�����ԩA��*M�<�G��b�if��l^M��5�� �Ҩ�{����6J��ZJ�����P�*�����Y���ݛu�_4�9�I8�7���������,^ToR���m4�H��?�N�S�ѕw��/S��甍�@�9H�S�T��t�ƻ���ʒU��*{Xs�@����f������֒Li�K{H�w^���������Ϥm�tq���s� ���ք��f:��o~s��g�r��ט� �S�ѱC�e]�x���a��) ���(b-$(�j>�7q�B?ӕ�F��hV25r[7 Y� }L�R��}����*sg+��x�r�2�U=�*'WS��ZDW]�WǞ�<��叓���{�$�9Ou4��y�90-�1�'*D`�c�^o?(�9��u���ݐ��'PI&� f�Jݮ�������:wS����jfP1F:X �H�9dԯ����˝[�_54 �}*;@�ܨ�� ð�yn�T���?�ןd�#���4rG�ͨ��H�1�|-#���Mr�S3��G�3�����)�.᧏3v�z֑��r����$G"�`j �1t��x0<Ɔ�Wh6�y�6��,œ�Ga��gA����y��b��)���h�D��ß�_�m��ü �gG;��e�v��ݝ�nQ� ��C����-�*��o���y�a��M��I�>�<���]obD��"�:���G�A��-\%LT�8���c�)��+y76���o�Q�#*{�(F�⽕�y����=���rW�\p���۩�c���A���^e6��K������ʐ�cVf5$�'->���ՉN"���F�"�UQ@�f��Gb~��#�&�M=��8�ט�JNu9��D��[̤�s�o�~������� G��9T�tW^g5y$b��Y'��س�Ǵ�=��U-2 #�MC�t(�i� �lj�@Q 5�̣i�*�O����s�x�K�f��}\��M{E�V�{�υ��Ƈ�����);�H����I��fe�Lȣr�2��>��W��I�Ȃ6������i��k�� �5�YOxȺ����>��Y�f5'��|��H+��98pj�n�.O�y�������jY��~��i�w'������l�;�s�2��Y��:'lg�ꥴ)o#'Sa�a�K��Z� �m��}�`169�n���"���x��I ��*+� }F<��cГ���F�P�������ֹ*�PqX�x۩��,� ��N�� �4<-����%����:��7����W���u�`����� $�?�I��&����o��o��`v�>��P��"��l���4��5'�Z�gE���8���?��[�X�7(��.Q�-��*���ތL@̲����v��.5���[��=�t\+�CNܛ��,g�SQnH����}*F�G16���&:�t��4ُ"A��̣��$�b �|����#rs��a�����T�� ]�<�j��B�S�('$�ɻ� �wP;�/�n��?�ݜ��x�F��yUn�~mL*-�������Xf�wd^�a�}��f�,=t�׵i�.2/wpN�Ep8�OР���•��R�FJ� 55TZ��T �ɭ�<��]��/�0�r�@�f��V��V����Nz�G��^���7hZi����k��3�,kN�e|�vg�1{9]_i��X5y7� 8e]�U����'�-2,���e"����]ot�I��Y_��n�(JҼ��1�O ]bXc���Nu�No��pS���Q_���_�?i�~�x h5d'�(qw52] ��'ޤ�q��o1�R!���`ywy�A4u���h<קy���\[~�4�\ X�Wt/� 6�����n�F�a8��f���z �3$�t(���q��q�x��^�XWeN'p<-v�!�{�(>ӽDP7��ո0�y)�e$ٕv�Ih'Q�EA�m*�H��RI��=:��� ���4牢) �%_iN�ݧ�l]� �Nt���G��H�L��� ɱ�g<���1V�,�J~�ٹ�"K��Q�� 9�HS�9�?@��k����r�;we݁�]I�!{ �@�G�[�"��`���J:�n]�{�cA�E����V��ʆ���#��U9�6����j�#Y�m\��q�e4h�B�7��C�������d<�?J����1g:ٳ���=Y���D�p�ц� ׈ǔ��1�]26؜oS�'��9�V�FVu�P�h�9�xc�oq�X��p�o�5��Ա5$�9W�V(�[Ak�aY錎qf;�'�[�|���b�6�Ck��)��#a#a˙��8���=äh�4��2��C��4tm^ �n'c����]GQ$[Wҿ��i���vN�{Fu ��1�gx��1┷���N�m��{j-,��x�� Ūm�ЧS�[�s���Gna���䑴�� x�p 8<������97�Q���ϴ�v�aϚG��Rt�Һ׈�f^\r��WH�JU�7Z���y)�vg=����n��4�_)y��D'y�6�]�c�5̪��\� �PF�k����&�c;��cq�$~T�7j ���nç]�<�g ":�to�t}�159�<�/�8������m�b�K#g'I'.W������6��I/��>v��\�MN��g���m�A�yQL�4u�Lj�j9��#44�t��l^�}L����n��R��!��t��±]��r��h6ٍ>�yҏ�N��fU�� ���� Fm@�8}�/u��jb9������he:A�y�ծw��GpΧh�5����l}�3p468��)U��d��c����;Us/�֔�YX�1�O2��uq�s��`hwg�r~�{ R��mhN��؎*q 42�*th��>�#���E����#��Hv�O����q�}������6�e��\�,Wk�#���X��b>��p}�դ��3���T5��†��6��[��@��P�y*n��|'f�֧>�lư΂�̺����SU�'*�q�p�_S�����M�� '��c�6������m�� ySʨ;M��r���Ƌ�m�Kxo,���Gm�P��A�G�:��i��w�9�}M(�^�V��$ǒ�ѽ�9���|���� �a����J�SQ�a���r�B;����}���ٻ֢�2�%U���c�#�g���N�a�ݕ�'�v�[�OY'��3L�3�;,p�]@�S��{ls��X�'���c�jw��k'a�.��}�}&�� �dP�*�bK=ɍ!����;3n�gΊU�ߴmt�'*{,=SzfD� A��ko~�G�aoq�_mi}#�m�������P�Xhύ�����mxǍ�΂���巿zf��Q���c���|kc�����?���W��Y�$���_Lv����l߶��c���`?����l�j�ݲˏ!V��6����U�Ђ(A���4y)H���p�Z_�x��>���e���R��$�/�`^'3qˏ�-&Q�=?��CFVR �D�fV�9��{�8g�������n�h�(P"��6�[�D���< E�����~0<@�`�G�6����Hг�cc�� �c�K.5��D��d�B���`?�XQ��2��ٿyqo&+�1^� DW�0�ꊩ���G�#��Q�nL3��c���������/��x ��1�1�[y�x�პCW��C�c�UĨ80�m�e�4.{�m��u���I=��f�����0QRls9���f���������9���~f�����Ǩ��a�"@�8���ȁ�Q����#c�ic������G��$���G���r/$W�(��W���V�"��m�7�[m�A�m����bo��D� j����۳� l���^�k�h׽����� ��#� iXn�v��eT�k�a�^Y�4�BN���ĕ���0������� !01@Q"2AaPq3BR�������?�����@4�Q�����T3,���㺠�W�[=JK�Ϟ���2�r^7��vc�:�9 �E�ߴ�w�S#d���Ix��u��:��Hp��9E!�� V 2;73|F��9Y���*ʬ�F��D����u&���y؟��^EA��A��(ɩ���^��GV:ݜDy�`��Jr29ܾ�㝉��[���E;Fzx��YG��U�e�Y�C���� ����v-tx����I�sם�Ę�q��Eb�+P\ :>�i�C'�;�����k|z�رn�y]�#ǿb��Q��������w�����(�r|ӹs��[�D��2v-%��@;�8<a���[\o[ϧw��I!��*0�krs)�[�J9^��ʜ��p1)� "��/_>��o��<1����A�E�y^�C��`�x1'ܣn�p��s`l���fQ��):�l����b>�Me�jH^?�kl3(�z:���1ŠK&?Q�~�{�ٺ�h�y���/�[��V�|6��}�KbX����mn[-��7�5q�94�������dm���c^���h� X��5��<�eޘ>G���-�}�دB�ޟ� ��|�rt�M��V+�]�c?�-#ڛ��^ǂ}���Lkr���O��u�>�-D�ry� D?:ޞ�U��ǜ�7�V��?瓮�"�#���r��չģVR;�n���/_� ؉v�ݶe5d�b9��/O��009�G���5n�W����JpA�*�r9�>�1��.[t���s�F���nQ� V 77R�]�ɫ8����_0<՜�IF�u(v��4��F�k�3��E)��N:��yڮe��P�`�1}�$WS��J�SQ�N�j��ٺ��޵�#l���ј(�5=��5�lǏmoW�v-�1����v,W�mn��߀$x�<����v�j(����c]��@#��1������Ǔ���o'��u+����;G�#�޸��v-lη��/(`i⣍Pm^����ԯ̾9Z��F��������n��1��� ��]�[��)�'�������:�֪�W��FC����� �B9،!?���]��V��A�Վ�M��b�w��G F>_DȬ0¤�#�QR�[V��kz���m�w�"��9ZG�7'[��=�Q����j8R?�zf�\a�=��O�U����*oB�A�|G���2�54 �p��.w7� �� ���&������ξxGHp� B%��$g�����t�Џ򤵍z���HN�u�Я�-�'4��0���;_���3������� !01"@AQa2Pq#3BR�������?����ʩca��en��^��8���<�u#��m*08r��y�N"�<�Ѳ0��@\�p��� �����Kv�D��J8�Fҽ� �f�Y��-m�ybX�NP����}�!*8t(�OqѢ��Q�wW�K��ZD��Δ^e��!� ��B�K��p~�����e*l}z#9ң�k���q#�Ft�o��S�R����-�w�!�S���Ӥß|M�l޶V��!eˈ�8Y���c�ЮM2��tk���� ������J�fS����Ö*i/2�����n]�k�\���|4yX�8��U�P.���Ы[���l��@"�t�<������5�lF���vU�����W��W��;�b�cД^6[#7@vU�xgZv��F�6��Q,K�v��� �+Ъ��n��Ǣ��Ft���8��0��c�@�!�Zq s�v�t�;#](B��-�nῃ~���3g������5�J�%���O������n�kB�ĺ�.r��+���#�N$?�q�/�s�6��p��a����a��J/��M�8��6�ܰ"�*������ɗud"\w���aT(����[��F��U՛����RT�b���n�*��6���O��SJ�.�ij<�v�MT��R\c��5l�sZB>F��<7�;EA��{��E���Ö��1U/�#��d1�a�n.1ě����0�ʾR�h��|�R��Ao�3�m3 ��%�� ���28Q�� ��y��φ���H�To�7�lW>����#i`�q���c����a��� �m,B�-j����݋�'mR1Ήt�>��V��p���s�0IbI�C.���1R�ea�����]H�6�����������4B>��o��](��$B���m�����a�!=���?�B� K�Ǿ+�Ծ"�n���K��*��+��[T#�{�E�J�S����Q�����s�5�:�U�\wĐ�f�3����܆&�)�����I���Ԇw��E T�lrTf6Q|R�h:��[K�� �z��c֧�G�C��%\��_�a��84��HcO�bi��ؖV��7H �)*ģK~Xhչ0��4?�0��� �E<���}3���#���u�?�� ��|g�S�6ꊤ�|�I#Hڛ� �ա��w�X��9��7���Ŀ%�SL��y6č��|�F�a 8���b���$�sק�h���b9RAu7�˨p�Č�_\*w��묦��F ����4D~�f����|(�"m���NK��i�S�>�$d7SlA��/�²����SL��|6N�}���S�˯���g��]6��; �#�.��<���q'Q�1|KQ$�����񛩶"�$r�b:���N8�w@��8$�� �AjfG|~�9F ���Y��ʺ��Bwؒ������M:I岎�G��`s�YV5����6��A �b:�W���G�q%l�����F��H���7�������Fsv7���k�� 403WebShell
403Webshell
Server IP : 185.170.199.186  /  Your IP : 216.73.216.167
Web Server : LiteSpeed
System : Linux lt-bnk-web922.main-hosting.eu 4.18.0-553.70.1.lve.el8.x86_64 #1 SMP Wed Aug 20 14:42:18 UTC 2025 x86_64
User : u970350538 ( 970350538)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : OFF  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /opt/golang/1.19.4/src/cmd/compile/internal/noder/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /opt/golang/1.19.4/src/cmd/compile/internal/noder/stencil.go
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file will evolve, since we plan to do a mix of stenciling and passing
// around dictionaries.

package noder

import (
	"cmd/compile/internal/base"
	"cmd/compile/internal/ir"
	"cmd/compile/internal/objw"
	"cmd/compile/internal/reflectdata"
	"cmd/compile/internal/typecheck"
	"cmd/compile/internal/types"
	"cmd/internal/obj"
	"cmd/internal/src"
	"fmt"
	"go/constant"
)

// Enable extra consistency checks.
const doubleCheck = false

func assert(p bool) {
	base.Assert(p)
}

// For outputting debug information on dictionary format and instantiated dictionaries
// (type arg, derived types, sub-dictionary, and itab entries).
var infoPrintMode = false

func infoPrint(format string, a ...interface{}) {
	if infoPrintMode {
		fmt.Printf(format, a...)
	}
}

var geninst genInst

func BuildInstantiations() {
	geninst.instInfoMap = make(map[*types.Sym]*instInfo)
	geninst.buildInstantiations()
	geninst.instInfoMap = nil
}

// buildInstantiations scans functions for generic function calls and methods, and
// creates the required instantiations. It also creates instantiated methods for all
// fully-instantiated generic types that have been encountered already or new ones
// that are encountered during the instantiation process. It scans all declarations
// in typecheck.Target.Decls first, before scanning any new instantiations created.
func (g *genInst) buildInstantiations() {
	// Instantiate the methods of instantiated generic types that we have seen so far.
	g.instantiateMethods()

	// Scan all currentdecls for call to generic functions/methods.
	n := len(typecheck.Target.Decls)
	for i := 0; i < n; i++ {
		g.scanForGenCalls(typecheck.Target.Decls[i])
	}

	// Scan all new instantiations created due to g.instantiateMethods() and the
	// scan of current decls. This loop purposely runs until no new
	// instantiations are created.
	for i := 0; i < len(g.newInsts); i++ {
		g.scanForGenCalls(g.newInsts[i])
	}

	g.finalizeSyms()

	// All the instantiations and dictionaries have been created. Now go through
	// each new instantiation and transform the various operations that need to make
	// use of their dictionary.
	l := len(g.newInsts)
	for _, fun := range g.newInsts {
		info := g.instInfoMap[fun.Sym()]
		g.dictPass(info)
		if doubleCheck {
			ir.Visit(info.fun, func(n ir.Node) {
				if n.Op() != ir.OCONVIFACE {
					return
				}
				c := n.(*ir.ConvExpr)
				if c.X.Type().HasShape() && !c.X.Type().IsInterface() {
					ir.Dump("BAD FUNCTION", info.fun)
					ir.Dump("BAD CONVERSION", c)
					base.Fatalf("converting shape type to interface")
				}
			})
		}
		if base.Flag.W > 1 {
			ir.Dump(fmt.Sprintf("\ndictpass %v", info.fun), info.fun)
		}
	}
	assert(l == len(g.newInsts))
	g.newInsts = nil
}

// scanForGenCalls scans a single function (or global assignment), looking for
// references to generic functions/methods. At each such reference, it creates any
// required instantiation and transforms the reference.
func (g *genInst) scanForGenCalls(decl ir.Node) {
	switch decl.Op() {
	case ir.ODCLFUNC:
		if decl.Type().HasTParam() {
			// Skip any generic functions
			return
		}
		// transformCall() below depends on CurFunc being set.
		ir.CurFunc = decl.(*ir.Func)

	case ir.OAS, ir.OAS2, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV, ir.OASOP:
		// These are all the various kinds of global assignments,
		// whose right-hand-sides might contain a function
		// instantiation.

	default:
		// The other possible ops at the top level are ODCLCONST
		// and ODCLTYPE, which don't have any function
		// instantiations.
		return
	}

	// Search for any function references using generic function/methods. Then
	// create the needed instantiated function if it hasn't been created yet, and
	// change to calling that function directly.
	modified := false
	closureRequired := false
	// declInfo will be non-nil exactly if we are scanning an instantiated function
	declInfo := g.instInfoMap[decl.Sym()]

	ir.Visit(decl, func(n ir.Node) {
		if n.Op() == ir.OFUNCINST {
			// generic F, not immediately called
			closureRequired = true
		}
		if (n.Op() == ir.OMETHEXPR || n.Op() == ir.OMETHVALUE) && len(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) > 0 && !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) {
			// T.M or x.M, where T or x is generic, but not immediately
			// called. Not necessary if the method selected is
			// actually for an embedded interface field.
			closureRequired = true
		}
		if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OFUNCINST {
			// We have found a function call using a generic function
			// instantiation.
			call := n.(*ir.CallExpr)
			inst := call.X.(*ir.InstExpr)
			nameNode, isMeth := g.getInstNameNode(inst)
			targs := typecheck.TypesOf(inst.Targs)
			st := g.getInstantiation(nameNode, targs, isMeth).fun
			dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, nameNode, targs, isMeth)
			if infoPrintMode {
				dictkind := "Main dictionary"
				if usingSubdict {
					dictkind = "Sub-dictionary"
				}
				if inst.X.Op() == ir.OMETHVALUE {
					fmt.Printf("%s in %v at generic method call: %v - %v\n", dictkind, decl, inst.X, call)
				} else {
					fmt.Printf("%s in %v at generic function call: %v - %v\n", dictkind, decl, inst.X, call)
				}
			}

			// Transform the Call now, which changes OCALL to
			// OCALLFUNC and does typecheckaste/assignconvfn. Do
			// it before installing the instantiation, so we are
			// checking against non-shape param types in
			// typecheckaste.
			transformCall(call)

			// Replace the OFUNCINST with a direct reference to the
			// new stenciled function
			call.X = st.Nname
			if inst.X.Op() == ir.OMETHVALUE {
				// When we create an instantiation of a method
				// call, we make it a function. So, move the
				// receiver to be the first arg of the function
				// call.
				call.Args.Prepend(inst.X.(*ir.SelectorExpr).X)
			}

			// Add dictionary to argument list.
			call.Args.Prepend(dictValue)
			modified = true
		}
		if n.Op() == ir.OCALLMETH && n.(*ir.CallExpr).X.Op() == ir.ODOTMETH && len(deref(n.(*ir.CallExpr).X.Type().Recv().Type).RParams()) > 0 {
			// Method call on a generic type, which was instantiated by stenciling.
			// Method calls on explicitly instantiated types will have an OFUNCINST
			// and are handled above.
			call := n.(*ir.CallExpr)
			meth := call.X.(*ir.SelectorExpr)
			targs := deref(meth.Type().Recv().Type).RParams()

			t := meth.X.Type()
			baseType := deref(t).OrigType()
			var gf *ir.Name
			for _, m := range baseType.Methods().Slice() {
				if meth.Sel == m.Sym {
					gf = m.Nname.(*ir.Name)
					break
				}
			}

			// Transform the Call now, which changes OCALL
			// to OCALLFUNC and does typecheckaste/assignconvfn.
			transformCall(call)

			st := g.getInstantiation(gf, targs, true).fun
			dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, gf, targs, true)
			if hasShapeTypes(targs) {
				// We have to be using a subdictionary, since this is
				// a generic method call.
				assert(usingSubdict)
			} else {
				// We should use main dictionary, because the receiver is
				// an instantiation already, see issue #53406.
				assert(!usingSubdict)
			}

			// Transform to a function call, by appending the
			// dictionary and the receiver to the args.
			call.SetOp(ir.OCALLFUNC)
			call.X = st.Nname
			call.Args.Prepend(dictValue, meth.X)
			modified = true
		}
	})

	// If we found a reference to a generic instantiation that wasn't an
	// immediate call, then traverse the nodes of decl again (with
	// EditChildren rather than Visit), where we actually change the
	// reference to the instantiation to a closure that captures the
	// dictionary, then does a direct call.
	// EditChildren is more expensive than Visit, so we only do this
	// in the infrequent case of an OFUNCINST without a corresponding
	// call.
	if closureRequired {
		modified = true
		var edit func(ir.Node) ir.Node
		var outer *ir.Func
		if f, ok := decl.(*ir.Func); ok {
			outer = f
		}
		edit = func(x ir.Node) ir.Node {
			if x.Op() == ir.OFUNCINST {
				child := x.(*ir.InstExpr).X
				if child.Op() == ir.OMETHEXPR || child.Op() == ir.OMETHVALUE {
					// Call EditChildren on child (x.X),
					// not x, so that we don't do
					// buildClosure() on the
					// METHEXPR/METHVALUE nodes as well.
					ir.EditChildren(child, edit)
					return g.buildClosure(outer, x)
				}
			}
			ir.EditChildren(x, edit)
			switch {
			case x.Op() == ir.OFUNCINST:
				return g.buildClosure(outer, x)
			case (x.Op() == ir.OMETHEXPR || x.Op() == ir.OMETHVALUE) &&
				len(deref(x.(*ir.SelectorExpr).X.Type()).RParams()) > 0 &&
				!types.IsInterfaceMethod(x.(*ir.SelectorExpr).Selection.Type):
				return g.buildClosure(outer, x)
			}
			return x
		}
		edit(decl)
	}
	if base.Flag.W > 1 && modified {
		ir.Dump(fmt.Sprintf("\nmodified %v", decl), decl)
	}
	ir.CurFunc = nil
	// We may have seen new fully-instantiated generic types while
	// instantiating any needed functions/methods in the above
	// function. If so, instantiate all the methods of those types
	// (which will then lead to more function/methods to scan in the loop).
	g.instantiateMethods()
}

// buildClosure makes a closure to implement x, a OFUNCINST or OMETHEXPR/OMETHVALUE
// of generic type. outer is the containing function (or nil if closure is
// in a global assignment instead of a function).
func (g *genInst) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
	pos := x.Pos()
	var target *ir.Func   // target instantiated function/method
	var dictValue ir.Node // dictionary to use
	var rcvrValue ir.Node // receiver, if a method value
	typ := x.Type()       // type of the closure
	var outerInfo *instInfo
	if outer != nil {
		outerInfo = g.instInfoMap[outer.Sym()]
	}
	usingSubdict := false
	valueMethod := false
	if x.Op() == ir.OFUNCINST {
		inst := x.(*ir.InstExpr)

		// Type arguments we're instantiating with.
		targs := typecheck.TypesOf(inst.Targs)

		// Find the generic function/method.
		var gf *ir.Name
		if inst.X.Op() == ir.ONAME {
			// Instantiating a generic function call.
			gf = inst.X.(*ir.Name)
		} else if inst.X.Op() == ir.OMETHVALUE {
			// Instantiating a method value x.M.
			se := inst.X.(*ir.SelectorExpr)
			rcvrValue = se.X
			gf = se.Selection.Nname.(*ir.Name)
		} else {
			panic("unhandled")
		}

		// target is the instantiated function we're trying to call.
		// For functions, the target expects a dictionary as its first argument.
		// For method values, the target expects a dictionary and the receiver
		// as its first two arguments.
		// dictValue is the value to use for the dictionary argument.
		target = g.getInstantiation(gf, targs, rcvrValue != nil).fun
		dictValue, usingSubdict = g.getDictOrSubdict(outerInfo, x, gf, targs, rcvrValue != nil)
		if infoPrintMode {
			dictkind := "Main dictionary"
			if usingSubdict {
				dictkind = "Sub-dictionary"
			}
			if rcvrValue == nil {
				fmt.Printf("%s in %v for generic function value %v\n", dictkind, outer, inst.X)
			} else {
				fmt.Printf("%s in %v for generic method value %v\n", dictkind, outer, inst.X)
			}
		}
	} else { // ir.OMETHEXPR or ir.METHVALUE
		// Method expression T.M where T is a generic type.
		se := x.(*ir.SelectorExpr)
		if x.Op() == ir.OMETHVALUE {
			rcvrValue = se.X
		}

		// se.X.Type() is the top-level type of the method expression. To
		// correctly handle method expressions involving embedded fields,
		// look up the generic method below using the type of the receiver
		// of se.Selection, since that will be the type that actually has
		// the method.
		recv := deref(se.Selection.Type.Recv().Type)
		targs := recv.RParams()
		if len(targs) == 0 {
			// The embedded type that actually has the method is not
			// actually generic, so no need to build a closure.
			return x
		}
		baseType := recv.OrigType()
		var gf *ir.Name
		for _, m := range baseType.Methods().Slice() {
			if se.Sel == m.Sym {
				gf = m.Nname.(*ir.Name)
				break
			}
		}
		if !gf.Type().Recv().Type.IsPtr() {
			// Remember if value method, so we can detect (*T).M case.
			valueMethod = true
		}
		target = g.getInstantiation(gf, targs, true).fun
		dictValue, usingSubdict = g.getDictOrSubdict(outerInfo, x, gf, targs, true)
		if infoPrintMode {
			dictkind := "Main dictionary"
			if usingSubdict {
				dictkind = "Sub-dictionary"
			}
			fmt.Printf("%s in %v for method expression %v\n", dictkind, outer, x)
		}
	}

	// Build a closure to implement a function instantiation.
	//
	//   func f[T any] (int, int) (int, int) { ...whatever... }
	//
	// Then any reference to f[int] not directly called gets rewritten to
	//
	//   .dictN := ... dictionary to use ...
	//   func(a0, a1 int) (r0, r1 int) {
	//     return .inst.f[int](.dictN, a0, a1)
	//   }
	//
	// Similarly for method expressions,
	//
	//   type g[T any] ....
	//   func (rcvr g[T]) f(a0, a1 int) (r0, r1 int) { ... }
	//
	// Any reference to g[int].f not directly called gets rewritten to
	//
	//   .dictN := ... dictionary to use ...
	//   func(rcvr g[int], a0, a1 int) (r0, r1 int) {
	//     return .inst.g[int].f(.dictN, rcvr, a0, a1)
	//   }
	//
	// Also method values
	//
	//   var x g[int]
	//
	// Any reference to x.f not directly called gets rewritten to
	//
	//   .dictN := ... dictionary to use ...
	//   x2 := x
	//   func(a0, a1 int) (r0, r1 int) {
	//     return .inst.g[int].f(.dictN, x2, a0, a1)
	//   }

	// Make a new internal function.
	fn, formalParams, formalResults := startClosure(pos, outer, typ)
	fn.SetWrapper(true) // See issue 52237

	// This is the dictionary we want to use.
	// It may be a constant, it may be the outer functions's dictionary, or it may be
	// a subdictionary acquired from the outer function's dictionary.
	// For the latter, dictVar is a variable in the outer function's scope, set to the subdictionary
	// read from the outer function's dictionary.
	var dictVar *ir.Name
	var dictAssign *ir.AssignStmt
	if outer != nil {
		dictVar = ir.NewNameAt(pos, closureSym(outer, typecheck.LocalDictName, g.dnum))
		g.dnum++
		dictVar.Class = ir.PAUTO
		typed(types.Types[types.TUINTPTR], dictVar)
		dictVar.Curfn = outer
		dictAssign = ir.NewAssignStmt(pos, dictVar, dictValue)
		dictAssign.SetTypecheck(1)
		dictVar.Defn = dictAssign
		outer.Dcl = append(outer.Dcl, dictVar)
	}
	// assign the receiver to a temporary.
	var rcvrVar *ir.Name
	var rcvrAssign ir.Node
	if rcvrValue != nil {
		rcvrVar = ir.NewNameAt(pos, closureSym(outer, ".rcvr", g.dnum))
		g.dnum++
		typed(rcvrValue.Type(), rcvrVar)
		rcvrAssign = ir.NewAssignStmt(pos, rcvrVar, rcvrValue)
		rcvrAssign.SetTypecheck(1)
		rcvrVar.Defn = rcvrAssign
		if outer == nil {
			rcvrVar.Class = ir.PEXTERN
			typecheck.Target.Decls = append(typecheck.Target.Decls, rcvrAssign)
			typecheck.Target.Externs = append(typecheck.Target.Externs, rcvrVar)
		} else {
			rcvrVar.Class = ir.PAUTO
			rcvrVar.Curfn = outer
			outer.Dcl = append(outer.Dcl, rcvrVar)
		}
	}

	// Build body of closure. This involves just calling the wrapped function directly
	// with the additional dictionary argument.

	// First, figure out the dictionary argument.
	var dict2Var ir.Node
	if usingSubdict {
		// Capture sub-dictionary calculated in the outer function
		dict2Var = ir.CaptureName(pos, fn, dictVar)
		typed(types.Types[types.TUINTPTR], dict2Var)
	} else {
		// Static dictionary, so can be used directly in the closure
		dict2Var = dictValue
	}
	// Also capture the receiver variable.
	var rcvr2Var *ir.Name
	if rcvrValue != nil {
		rcvr2Var = ir.CaptureName(pos, fn, rcvrVar)
	}

	// Build arguments to call inside the closure.
	var args []ir.Node

	// First the dictionary argument.
	args = append(args, dict2Var)
	// Then the receiver.
	if rcvrValue != nil {
		args = append(args, rcvr2Var)
	}
	// Then all the other arguments (including receiver for method expressions).
	for i := 0; i < typ.NumParams(); i++ {
		if x.Op() == ir.OMETHEXPR && i == 0 {
			// If we are doing a method expression, we need to
			// explicitly traverse any embedded fields in the receiver
			// argument in order to call the method instantiation.
			arg0 := formalParams[0].Nname.(ir.Node)
			arg0 = typecheck.AddImplicitDots(ir.NewSelectorExpr(x.Pos(), ir.OXDOT, arg0, x.(*ir.SelectorExpr).Sel)).X
			if valueMethod && arg0.Type().IsPtr() {
				// For handling the (*T).M case: if we have a pointer
				// receiver after following all the embedded fields,
				// but it's a value method, add a star operator.
				arg0 = ir.NewStarExpr(arg0.Pos(), arg0)
			}
			args = append(args, arg0)
		} else {
			args = append(args, formalParams[i].Nname.(*ir.Name))
		}
	}

	// Build call itself.
	var innerCall ir.Node = ir.NewCallExpr(pos, ir.OCALL, target.Nname, args)
	innerCall.(*ir.CallExpr).IsDDD = typ.IsVariadic()
	if len(formalResults) > 0 {
		innerCall = ir.NewReturnStmt(pos, []ir.Node{innerCall})
	}
	// Finish building body of closure.
	ir.CurFunc = fn
	// TODO: set types directly here instead of using typecheck.Stmt
	typecheck.Stmt(innerCall)
	ir.CurFunc = nil
	fn.Body = []ir.Node{innerCall}

	// We're all done with the captured dictionary (and receiver, for method values).
	ir.FinishCaptureNames(pos, outer, fn)

	// Make a closure referencing our new internal function.
	c := ir.UseClosure(fn.OClosure, typecheck.Target)
	var init []ir.Node
	if outer != nil {
		init = append(init, dictAssign)
	}
	if rcvrValue != nil {
		init = append(init, rcvrAssign)
	}
	return ir.InitExpr(init, c)
}

// instantiateMethods instantiates all the methods (and associated dictionaries) of
// all fully-instantiated generic types that have been added to typecheck.instTypeList.
// It continues until no more types are added to typecheck.instTypeList.
func (g *genInst) instantiateMethods() {
	for {
		instTypeList := typecheck.GetInstTypeList()
		if len(instTypeList) == 0 {
			break
		}
		typecheck.ClearInstTypeList()
		for _, typ := range instTypeList {
			assert(!typ.HasShape())
			// Mark runtime type as needed, since this ensures that the
			// compiler puts out the needed DWARF symbols, when this
			// instantiated type has a different package from the local
			// package.
			typecheck.NeedRuntimeType(typ)
			// Lookup the method on the base generic type, since methods may
			// not be set on imported instantiated types.
			baseType := typ.OrigType()
			for j, _ := range typ.Methods().Slice() {
				if baseType.Methods().Slice()[j].Nointerface() {
					typ.Methods().Slice()[j].SetNointerface(true)
				}
				baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name)
				// Eagerly generate the instantiations and dictionaries that implement these methods.
				// We don't use the instantiations here, just generate them (and any
				// further instantiations those generate, etc.).
				// Note that we don't set the Func for any methods on instantiated
				// types. Their signatures don't match so that would be confusing.
				// Direct method calls go directly to the instantiations, implemented above.
				// Indirect method calls use wrappers generated in reflectcall. Those wrappers
				// will use these instantiations if they are needed (for interface tables or reflection).
				_ = g.getInstantiation(baseNname, typ.RParams(), true)
				_ = g.getDictionarySym(baseNname, typ.RParams(), true)
			}
		}
	}
}

// getInstNameNode returns the name node for the method or function being instantiated, and a bool which is true if a method is being instantiated.
func (g *genInst) getInstNameNode(inst *ir.InstExpr) (*ir.Name, bool) {
	if meth, ok := inst.X.(*ir.SelectorExpr); ok {
		return meth.Selection.Nname.(*ir.Name), true
	} else {
		return inst.X.(*ir.Name), false
	}
}

// getDictOrSubdict returns, for a method/function call or reference (node n) in an
// instantiation (described by instInfo), a node which is accessing a sub-dictionary
// or main/static dictionary, as needed, and also returns a boolean indicating if a
// sub-dictionary was accessed. nameNode is the particular function or method being
// called/referenced, and targs are the type arguments.
func (g *genInst) getDictOrSubdict(declInfo *instInfo, n ir.Node, nameNode *ir.Name, targs []*types.Type, isMeth bool) (ir.Node, bool) {
	var dict ir.Node
	usingSubdict := false
	if declInfo != nil {
		entry := -1
		for i, de := range declInfo.dictInfo.subDictCalls {
			if n == de.callNode {
				entry = declInfo.dictInfo.startSubDict + i
				break
			}
		}
		// If the entry is not found, it may be that this node did not have
		// any type args that depend on type params, so we need a main
		// dictionary, not a sub-dictionary.
		if entry >= 0 {
			dict = getDictionaryEntry(n.Pos(), declInfo.dictParam, entry, declInfo.dictInfo.dictLen)
			usingSubdict = true
		}
	}
	if !usingSubdict {
		dict = g.getDictionaryValue(n.Pos(), nameNode, targs, isMeth)
	}
	return dict, usingSubdict
}

// checkFetchBody checks if a generic body can be fetched, but hasn't been loaded
// yet. If so, it imports the body.
func checkFetchBody(nameNode *ir.Name) {
	if nameNode.Func.Body == nil && nameNode.Func.Inl != nil {
		// If there is no body yet but Func.Inl exists, then we can
		// import the whole generic body.
		assert(nameNode.Func.Inl.Cost == 1 && nameNode.Sym().Pkg != types.LocalPkg)
		typecheck.ImportBody(nameNode.Func)
		assert(nameNode.Func.Inl.Body != nil)
		nameNode.Func.Body = nameNode.Func.Inl.Body
		nameNode.Func.Dcl = nameNode.Func.Inl.Dcl
	}
}

// getInstantiation gets the instantiation and dictionary of the function or method nameNode
// with the type arguments shapes. If the instantiated function is not already
// cached, then it calls genericSubst to create the new instantiation.
func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth bool) *instInfo {
	if nameNode.Func == nil {
		// If nameNode.Func is nil, this must be a reference to a method of
		// an imported instantiated type. We will have already called
		// g.instantiateMethods() on the fully-instantiated type, so
		// g.instInfoMap[sym] will be non-nil below.
		rcvr := nameNode.Type().Recv()
		if rcvr == nil || !deref(rcvr.Type).IsFullyInstantiated() {
			base.FatalfAt(nameNode.Pos(), "Unexpected function instantiation %v with no body", nameNode)
		}
	} else {
		checkFetchBody(nameNode)
	}

	var tparams []*types.Type
	if isMeth {
		// Get the type params from the method receiver (after skipping
		// over any pointer)
		recvType := nameNode.Type().Recv().Type
		recvType = deref(recvType)
		if recvType.IsFullyInstantiated() {
			// Get the type of the base generic type, so we get
			// its original typeparams.
			recvType = recvType.OrigType()
		}
		tparams = recvType.RParams()
	} else {
		fields := nameNode.Type().TParams().Fields().Slice()
		tparams = make([]*types.Type, len(fields))
		for i, f := range fields {
			tparams[i] = f.Type
		}
	}

	// Convert any non-shape type arguments to their shape, so we can reduce the
	// number of instantiations we have to generate. You can actually have a mix
	// of shape and non-shape arguments, because of inferred or explicitly
	// specified concrete type args.
	s1 := make([]*types.Type, len(shapes))
	for i, t := range shapes {
		var tparam *types.Type
		// Shapes are grouped differently for structural types, so we
		// pass the type param to Shapify(), so we can distinguish.
		tparam = tparams[i]
		if !t.IsShape() {
			s1[i] = typecheck.Shapify(t, i, tparam)
		} else {
			// Already a shape, but make sure it has the correct index.
			s1[i] = typecheck.Shapify(shapes[i].Underlying(), i, tparam)
		}
	}
	shapes = s1

	sym := typecheck.MakeFuncInstSym(nameNode.Sym(), shapes, false, isMeth)
	info := g.instInfoMap[sym]
	if info == nil {
		// If instantiation doesn't exist yet, create it and add
		// to the list of decls.
		info = &instInfo{
			dictInfo: &dictInfo{},
		}
		info.dictInfo.shapeToBound = make(map[*types.Type]*types.Type)

		if sym.Def != nil {
			// This instantiation must have been imported from another
			// package (because it was needed for inlining), so we should
			// not re-generate it and have conflicting definitions for the
			// symbol (issue #50121). It will have already gone through the
			// dictionary transformations of dictPass, so we don't actually
			// need the info.dictParam and info.shapeToBound info filled in
			// below. We just set the imported instantiation as info.fun.
			assert(sym.Pkg != types.LocalPkg)
			info.fun = sym.Def.(*ir.Name).Func
			assert(info.fun != nil)
			g.instInfoMap[sym] = info
			return info
		}

		// genericSubst fills in info.dictParam and info.shapeToBound.
		st := g.genericSubst(sym, nameNode, tparams, shapes, isMeth, info)
		info.fun = st
		g.instInfoMap[sym] = info

		// getInstInfo fills in info.dictInfo.
		g.getInstInfo(st, shapes, info)
		if base.Flag.W > 1 {
			ir.Dump(fmt.Sprintf("\nstenciled %v", st), st)
		}

		// This ensures that the linker drops duplicates of this instantiation.
		// All just works!
		st.SetDupok(true)
		typecheck.Target.Decls = append(typecheck.Target.Decls, st)
		g.newInsts = append(g.newInsts, st)
	}
	return info
}

// Struct containing info needed for doing the substitution as we create the
// instantiation of a generic function with specified type arguments.
type subster struct {
	g           *genInst
	isMethod    bool     // If a method is being instantiated
	newf        *ir.Func // Func node for the new stenciled function
	ts          typecheck.Tsubster
	info        *instInfo // Place to put extra info in the instantiation
	skipClosure bool      // Skip substituting closures

	// Map from non-nil, non-ONAME node n to slice of all m, where m.Defn = n
	defnMap map[ir.Node][]**ir.Name
}

// genericSubst returns a new function with name newsym. The function is an
// instantiation of a generic function or method specified by namedNode with type
// args shapes. For a method with a generic receiver, it returns an instantiated
// function type where the receiver becomes the first parameter. For either a generic
// method or function, a dictionary parameter is the added as the very first
// parameter. genericSubst fills in info.dictParam and info.shapeToBound.
func (g *genInst) genericSubst(newsym *types.Sym, nameNode *ir.Name, tparams []*types.Type, shapes []*types.Type, isMethod bool, info *instInfo) *ir.Func {
	gf := nameNode.Func
	// Pos of the instantiated function is same as the generic function
	newf := ir.NewFunc(gf.Pos())
	newf.Pragma = gf.Pragma // copy over pragmas from generic function to stenciled implementation.
	newf.Endlineno = gf.Endlineno
	newf.Nname = ir.NewNameAt(gf.Pos(), newsym)
	newf.Nname.Func = newf
	newf.Nname.Defn = newf
	newsym.Def = newf.Nname
	savef := ir.CurFunc
	// transformCall/transformReturn (called during stenciling of the body)
	// depend on ir.CurFunc being set.
	ir.CurFunc = newf

	assert(len(tparams) == len(shapes))

	subst := &subster{
		g:        g,
		isMethod: isMethod,
		newf:     newf,
		info:     info,
		ts: typecheck.Tsubster{
			Tparams: tparams,
			Targs:   shapes,
			Vars:    make(map[*ir.Name]*ir.Name),
		},
		defnMap: make(map[ir.Node][]**ir.Name),
	}

	newf.Dcl = make([]*ir.Name, 0, len(gf.Dcl)+1)

	// Create the needed dictionary param
	dictionarySym := newsym.Pkg.Lookup(typecheck.LocalDictName)
	dictionaryType := types.Types[types.TUINTPTR]
	dictionaryName := ir.NewNameAt(gf.Pos(), dictionarySym)
	typed(dictionaryType, dictionaryName)
	dictionaryName.Class = ir.PPARAM
	dictionaryName.Curfn = newf
	newf.Dcl = append(newf.Dcl, dictionaryName)
	for _, n := range gf.Dcl {
		if n.Sym().Name == typecheck.LocalDictName {
			panic("already has dictionary")
		}
		newf.Dcl = append(newf.Dcl, subst.localvar(n))
	}
	dictionaryArg := types.NewField(gf.Pos(), dictionarySym, dictionaryType)
	dictionaryArg.Nname = dictionaryName
	info.dictParam = dictionaryName

	// We add the dictionary as the first parameter in the function signature.
	// We also transform a method type to the corresponding function type
	// (make the receiver be the next parameter after the dictionary).
	oldt := nameNode.Type()
	var args []*types.Field
	args = append(args, dictionaryArg)
	args = append(args, oldt.Recvs().FieldSlice()...)
	args = append(args, oldt.Params().FieldSlice()...)

	// Replace the types in the function signature via subst.fields.
	// Ugly: also, we have to insert the Name nodes of the parameters/results into
	// the function type. The current function type has no Nname fields set,
	// because it came via conversion from the types2 type.
	newt := types.NewSignature(oldt.Pkg(), nil, nil,
		subst.fields(ir.PPARAM, args, newf.Dcl),
		subst.fields(ir.PPARAMOUT, oldt.Results().FieldSlice(), newf.Dcl))

	typed(newt, newf.Nname)
	ir.MarkFunc(newf.Nname)
	newf.SetTypecheck(1)

	// Make sure name/type of newf is set before substituting the body.
	newf.Body = subst.list(gf.Body)
	if len(newf.Body) == 0 {
		// Ensure the body is nonempty, for issue 49524.
		// TODO: have some other way to detect the difference between
		// a function declared with no body, vs. one with an empty body?
		newf.Body = append(newf.Body, ir.NewBlockStmt(gf.Pos(), nil))
	}

	if len(subst.defnMap) > 0 {
		base.Fatalf("defnMap is not empty")
	}

	for i, tp := range tparams {
		info.dictInfo.shapeToBound[shapes[i]] = subst.ts.Typ(tp.Bound())
	}

	ir.CurFunc = savef

	return subst.newf
}

// localvar creates a new name node for the specified local variable and enters it
// in subst.vars. It substitutes type arguments for type parameters in the type of
// name as needed.
func (subst *subster) localvar(name *ir.Name) *ir.Name {
	m := ir.NewNameAt(name.Pos(), name.Sym())
	if name.IsClosureVar() {
		m.SetIsClosureVar(true)
	}
	m.SetType(subst.ts.Typ(name.Type()))
	m.BuiltinOp = name.BuiltinOp
	m.Curfn = subst.newf
	m.Class = name.Class
	assert(name.Class != ir.PEXTERN && name.Class != ir.PFUNC)
	m.Func = name.Func
	subst.ts.Vars[name] = m
	m.SetTypecheck(1)
	m.DictIndex = name.DictIndex
	if name.Defn != nil {
		if name.Defn.Op() == ir.ONAME {
			// This is a closure variable, so its Defn is the outer
			// captured variable, which has already been substituted.
			m.Defn = subst.node(name.Defn)
		} else {
			// The other values of Defn are nodes in the body of the
			// function, so just remember the mapping so we can set Defn
			// properly in node() when we create the new body node. We
			// always call localvar() on all the local variables before
			// we substitute the body.
			slice := subst.defnMap[name.Defn]
			subst.defnMap[name.Defn] = append(slice, &m)
		}
	}
	if name.Outer != nil {
		m.Outer = subst.node(name.Outer).(*ir.Name)
	}

	return m
}

// getDictionaryEntry gets the i'th entry in the dictionary dict.
func getDictionaryEntry(pos src.XPos, dict *ir.Name, i int, size int) ir.Node {
	// Convert dictionary to *[N]uintptr
	// All entries in the dictionary are pointers. They all point to static data, though, so we
	// treat them as uintptrs so the GC doesn't need to keep track of them.
	d := ir.NewConvExpr(pos, ir.OCONVNOP, types.Types[types.TUNSAFEPTR], dict)
	d.SetTypecheck(1)
	d = ir.NewConvExpr(pos, ir.OCONVNOP, types.NewArray(types.Types[types.TUINTPTR], int64(size)).PtrTo(), d)
	d.SetTypecheck(1)
	types.CheckSize(d.Type().Elem())

	// Load entry i out of the dictionary.
	deref := ir.NewStarExpr(pos, d)
	typed(d.Type().Elem(), deref)
	idx := ir.NewConstExpr(constant.MakeUint64(uint64(i)), dict) // TODO: what to set orig to?
	typed(types.Types[types.TUINTPTR], idx)
	r := ir.NewIndexExpr(pos, deref, idx)
	typed(types.Types[types.TUINTPTR], r)
	return r
}

// getDictionaryEntryAddr gets the address of the i'th entry in dictionary dict.
func getDictionaryEntryAddr(pos src.XPos, dict *ir.Name, i int, size int) ir.Node {
	a := ir.NewAddrExpr(pos, getDictionaryEntry(pos, dict, i, size))
	typed(types.Types[types.TUINTPTR].PtrTo(), a)
	return a
}

// getDictionaryType returns a *runtime._type from the dictionary entry i (which
// refers to a type param or a derived type that uses type params). It uses the
// specified dictionary dictParam, rather than the one in info.dictParam.
func getDictionaryType(info *instInfo, dictParam *ir.Name, pos src.XPos, i int) ir.Node {
	if i < 0 || i >= info.dictInfo.startSubDict {
		base.Fatalf(fmt.Sprintf("bad dict index %d", i))
	}

	r := getDictionaryEntry(pos, dictParam, i, info.dictInfo.startSubDict)
	// change type of retrieved dictionary entry to *byte, which is the
	// standard typing of a *runtime._type in the compiler
	typed(types.Types[types.TUINT8].PtrTo(), r)
	return r
}

// node is like DeepCopy(), but substitutes ONAME nodes based on subst.ts.vars, and
// also descends into closures. It substitutes type arguments for type parameters in
// all the new nodes and does the transformations that were delayed on the generic
// function.
func (subst *subster) node(n ir.Node) ir.Node {
	// Use closure to capture all state needed by the ir.EditChildren argument.
	var edit func(ir.Node) ir.Node
	edit = func(x ir.Node) ir.Node {
		// Analogous to ir.SetPos() at beginning of typecheck.typecheck() -
		// allows using base.Pos during the transform functions, just like
		// the tc*() functions.
		ir.SetPos(x)
		switch x.Op() {
		case ir.OTYPE:
			return ir.TypeNode(subst.ts.Typ(x.Type()))

		case ir.ONAME:
			if v := subst.ts.Vars[x.(*ir.Name)]; v != nil {
				return v
			}
			if ir.IsBlank(x) {
				// Special case, because a blank local variable is
				// not in the fn.Dcl list.
				m := ir.NewNameAt(x.Pos(), ir.BlankNode.Sym())
				return typed(subst.ts.Typ(x.Type()), m)
			}
			return x
		case ir.ONONAME:
			// This handles the identifier in a type switch guard
			fallthrough
		case ir.OLITERAL, ir.ONIL:
			if x.Sym() != nil {
				return x
			}
		}
		m := ir.Copy(x)

		slice, ok := subst.defnMap[x]
		if ok {
			// We just copied a non-ONAME node which was the Defn value
			// of a local variable. Set the Defn value of the copied
			// local variable to this new Defn node.
			for _, ptr := range slice {
				(*ptr).Defn = m
			}
			delete(subst.defnMap, x)
		}

		if _, isExpr := m.(ir.Expr); isExpr {
			t := x.Type()
			if t == nil {
				// Check for known cases where t can be nil (call
				// that has no return values, and key expressions)
				// and otherwise cause a fatal error.
				_, isCallExpr := m.(*ir.CallExpr)
				_, isStructKeyExpr := m.(*ir.StructKeyExpr)
				_, isKeyExpr := m.(*ir.KeyExpr)
				if !isCallExpr && !isStructKeyExpr && !isKeyExpr && x.Op() != ir.OPANIC &&
					x.Op() != ir.OCLOSE {
					base.FatalfAt(m.Pos(), "Nil type for %v", x)
				}
			} else if x.Op() != ir.OCLOSURE {
				m.SetType(subst.ts.Typ(x.Type()))
			}
		}

		old := subst.skipClosure
		// For unsafe.{Alignof,Offsetof,Sizeof}, subster will transform them to OLITERAL nodes,
		// and discard their arguments. However, their children nodes were already process before,
		// thus if they contain any closure, the closure was still be added to package declarations
		// queue for processing later. Thus, genInst will fail to generate instantiation for the
		// closure because of lacking dictionary information, see issue #53390.
		if call, ok := m.(*ir.CallExpr); ok && call.X.Op() == ir.ONAME {
			switch call.X.Name().BuiltinOp {
			case ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF:
				subst.skipClosure = true
			}
		}
		ir.EditChildren(m, edit)
		subst.skipClosure = old

		m.SetTypecheck(1)

		// Do the transformations that we delayed on the generic function
		// node, now that we have substituted in the type args.
		switch x.Op() {
		case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
			transformCompare(m.(*ir.BinaryExpr))

		case ir.OSLICE, ir.OSLICE3:
			transformSlice(m.(*ir.SliceExpr))

		case ir.OADD:
			m = transformAdd(m.(*ir.BinaryExpr))

		case ir.OINDEX:
			transformIndex(m.(*ir.IndexExpr))

		case ir.OAS2:
			as2 := m.(*ir.AssignListStmt)
			transformAssign(as2, as2.Lhs, as2.Rhs)

		case ir.OAS:
			as := m.(*ir.AssignStmt)
			if as.Y != nil {
				// transformAssign doesn't handle the case
				// of zeroing assignment of a dcl (rhs[0] is nil).
				lhs, rhs := []ir.Node{as.X}, []ir.Node{as.Y}
				transformAssign(as, lhs, rhs)
				as.X, as.Y = lhs[0], rhs[0]
			}

		case ir.OASOP:
			as := m.(*ir.AssignOpStmt)
			transformCheckAssign(as, as.X)

		case ir.ORETURN:
			transformReturn(m.(*ir.ReturnStmt))

		case ir.OSEND:
			transformSend(m.(*ir.SendStmt))

		case ir.OSELECT:
			transformSelect(m.(*ir.SelectStmt))

		case ir.OCOMPLIT:
			transformCompLit(m.(*ir.CompLitExpr))

		case ir.OADDR:
			transformAddr(m.(*ir.AddrExpr))

		case ir.OLITERAL:
			t := m.Type()
			if t != x.Type() {
				// types2 will give us a constant with a type T,
				// if an untyped constant is used with another
				// operand of type T (in a provably correct way).
				// When we substitute in the type args during
				// stenciling, we now know the real type of the
				// constant. We may then need to change the
				// BasicLit.val to be the correct type (e.g.
				// convert an int64Val constant to a floatVal
				// constant).
				m.SetType(types.UntypedInt) // use any untyped type for DefaultLit to work
				m = typecheck.DefaultLit(m, t)
			}

		case ir.OXDOT:
			// Finish the transformation of an OXDOT, unless this is
			// bound call or field access on a type param. A bound call
			// or field access on a type param will be transformed during
			// the dictPass. Otherwise, m will be transformed to an
			// OMETHVALUE node. It will be transformed to an ODOTMETH or
			// ODOTINTER node if we find in the OCALL case below that the
			// method value is actually called.
			mse := m.(*ir.SelectorExpr)
			if src := mse.X.Type(); !src.IsShape() {
				transformDot(mse, false)
			}

		case ir.OCALL:
			call := m.(*ir.CallExpr)
			switch call.X.Op() {
			case ir.OTYPE:
				// Transform the conversion, now that we know the
				// type argument.
				m = transformConvCall(call)

			case ir.OMETHVALUE, ir.OMETHEXPR:
				// Redo the transformation of OXDOT, now that we
				// know the method value is being called. Then
				// transform the call.
				call.X.(*ir.SelectorExpr).SetOp(ir.OXDOT)
				transformDot(call.X.(*ir.SelectorExpr), true)
				transformCall(call)

			case ir.ODOT, ir.ODOTPTR:
				// An OXDOT for a generic receiver was resolved to
				// an access to a field which has a function
				// value. Transform the call to that function, now
				// that the OXDOT was resolved.
				transformCall(call)

			case ir.ONAME:
				name := call.X.Name()
				if name.BuiltinOp != ir.OXXX {
					m = transformBuiltin(call)
				} else {
					// This is the case of a function value that was a
					// type parameter (implied to be a function via a
					// structural constraint) which is now resolved.
					transformCall(call)
				}

			case ir.OFUNCINST:
				// A call with an OFUNCINST will get transformed
				// in stencil() once we have created & attached the
				// instantiation to be called.
				// We must transform the arguments of the call now, though,
				// so that any needed CONVIFACE nodes are exposed,
				// so the dictionary format is correct.
				transformEarlyCall(call)

			case ir.OXDOT:
				// This is the case of a bound call or a field access
				// on a typeparam, which will be handled in the
				// dictPass. As with OFUNCINST, we must transform the
				// arguments of the call now, so any needed CONVIFACE
				// nodes are exposed.
				transformEarlyCall(call)

			case ir.ODOTTYPE, ir.ODOTTYPE2:
				// These are DOTTYPEs that could get transformed into
				// ODYNAMIC DOTTYPEs by the dict pass.

			default:
				// Transform a call for all other values of
				// call.X.Op() that don't require any special
				// handling.
				transformCall(call)

			}

		case ir.OCLOSURE:
			if subst.skipClosure {
				break
			}
			// We're going to create a new closure from scratch, so clear m
			// to avoid using the ir.Copy by accident until we reassign it.
			m = nil

			x := x.(*ir.ClosureExpr)
			// Need to duplicate x.Func.Nname, x.Func.Dcl, x.Func.ClosureVars, and
			// x.Func.Body.
			oldfn := x.Func
			newfn := ir.NewClosureFunc(oldfn.Pos(), subst.newf != nil)
			ir.NameClosure(newfn.OClosure, subst.newf)

			saveNewf := subst.newf
			ir.CurFunc = newfn
			subst.newf = newfn
			newfn.Dcl = subst.namelist(oldfn.Dcl)

			// Make a closure variable for the dictionary of the
			// containing function.
			cdict := ir.CaptureName(oldfn.Pos(), newfn, subst.info.dictParam)
			typed(types.Types[types.TUINTPTR], cdict)
			ir.FinishCaptureNames(oldfn.Pos(), saveNewf, newfn)
			newfn.ClosureVars = append(newfn.ClosureVars, subst.namelist(oldfn.ClosureVars)...)

			// Copy that closure variable to a local one.
			// Note: this allows the dictionary to be captured by child closures.
			// See issue 47723.
			ldict := ir.NewNameAt(x.Pos(), newfn.Sym().Pkg.Lookup(typecheck.LocalDictName))
			typed(types.Types[types.TUINTPTR], ldict)
			ldict.Class = ir.PAUTO
			ldict.Curfn = newfn
			newfn.Dcl = append(newfn.Dcl, ldict)
			as := ir.NewAssignStmt(x.Pos(), ldict, cdict)
			as.SetTypecheck(1)
			ldict.Defn = as
			newfn.Body.Append(as)

			// Create inst info for the instantiated closure. The dict
			// param is the closure variable for the dictionary of the
			// outer function. Since the dictionary is shared, use the
			// same dictInfo.
			cinfo := &instInfo{
				fun:       newfn,
				dictParam: ldict,
				dictInfo:  subst.info.dictInfo,
			}
			subst.g.instInfoMap[newfn.Nname.Sym()] = cinfo

			typed(subst.ts.Typ(oldfn.Nname.Type()), newfn.Nname)
			typed(newfn.Nname.Type(), newfn.OClosure)
			newfn.SetTypecheck(1)

			outerinfo := subst.info
			subst.info = cinfo
			// Make sure type of closure function is set before doing body.
			newfn.Body.Append(subst.list(oldfn.Body)...)
			subst.info = outerinfo
			subst.newf = saveNewf
			ir.CurFunc = saveNewf

			m = ir.UseClosure(newfn.OClosure, typecheck.Target)
			subst.g.newInsts = append(subst.g.newInsts, m.(*ir.ClosureExpr).Func)
			m.(*ir.ClosureExpr).SetInit(subst.list(x.Init()))

		case ir.OSWITCH:
			m := m.(*ir.SwitchStmt)
			if m.Tag != nil && m.Tag.Op() == ir.OTYPESW {
				break // Nothing to do here for type switches.
			}
			if m.Tag != nil && !types.IsComparable(m.Tag.Type()) {
				break // Nothing to do here for un-comparable types.
			}
			if m.Tag != nil && !m.Tag.Type().IsEmptyInterface() && m.Tag.Type().HasShape() {
				// To implement a switch on a value that is or has a type parameter, we first convert
				// that thing we're switching on to an interface{}.
				m.Tag = assignconvfn(m.Tag, types.Types[types.TINTER])
			}
			for _, c := range m.Cases {
				for i, x := range c.List {
					// If we have a case that is or has a type parameter, convert that case
					// to an interface{}.
					if !x.Type().IsEmptyInterface() && x.Type().HasShape() {
						c.List[i] = assignconvfn(x, types.Types[types.TINTER])
					}
				}
			}

		}
		return m
	}

	return edit(n)
}

// dictPass takes a function instantiation and does the transformations on the
// operations that need to make use of the dictionary param.
func (g *genInst) dictPass(info *instInfo) {
	savef := ir.CurFunc
	ir.CurFunc = info.fun

	callMap := make(map[ir.Node]bool)

	var edit func(ir.Node) ir.Node
	edit = func(m ir.Node) ir.Node {
		if m.Op() == ir.OCALL && m.(*ir.CallExpr).X.Op() == ir.OXDOT {
			callMap[m.(*ir.CallExpr).X] = true
		}

		ir.EditChildren(m, edit)

		switch m.Op() {
		case ir.OCLOSURE:
			newf := m.(*ir.ClosureExpr).Func
			ir.CurFunc = newf
			outerinfo := info
			info = g.instInfoMap[newf.Nname.Sym()]

			body := newf.Body
			for i, n := range body {
				body[i] = edit(n)
			}

			info = outerinfo
			ir.CurFunc = info.fun

		case ir.OXDOT:
			// This is the case of a dot access on a type param. This is
			// typically a bound call on the type param, but could be a
			// field access, if the constraint has a single structural type.
			mse := m.(*ir.SelectorExpr)
			src := mse.X.Type()
			assert(src.IsShape())

			if mse.X.Op() == ir.OTYPE {
				// Method expression T.M
				idx := findMethodExprClosure(info.dictInfo, mse)
				c := getDictionaryEntryAddr(m.Pos(), info.dictParam, info.dictInfo.startMethodExprClosures+idx, info.dictInfo.dictLen)
				m = ir.NewConvExpr(m.Pos(), ir.OCONVNOP, mse.Type(), c)
				m.SetTypecheck(1)
			} else {
				// If we can't find the selected method in the
				// AllMethods of the bound, then this must be an access
				// to a field of a structural type. If so, we skip the
				// dictionary lookups - transformDot() will convert to
				// the desired direct field access.
				if isBoundMethod(info.dictInfo, mse) {
					if callMap[m] {
						// The OCALL surrounding this XDOT will rewrite the call
						// to use the method expression closure directly.
						break
					}
					// Convert this method value to a closure.
					// TODO: use method expression closure.
					dst := info.dictInfo.shapeToBound[mse.X.Type()]
					// Implement x.M as a conversion-to-bound-interface
					//  1) convert x to the bound interface
					//  2) select method value M on that interface
					if src.IsInterface() {
						// If type arg is an interface (unusual case),
						// we do a type assert to the type bound.
						mse.X = assertToBound(info, info.dictParam, m.Pos(), mse.X, dst)
					} else {
						mse.X = convertUsingDictionary(info, info.dictParam, m.Pos(), mse.X, m, dst)
					}
				}
				transformDot(mse, false)
			}
		case ir.OCALL:
			call := m.(*ir.CallExpr)
			op := call.X.Op()
			if op == ir.OXDOT {
				// This is a call of a method value where the value has a type parameter type.
				// We transform to a call of the appropriate method expression closure
				// in the dictionary.
				// So if x has a type parameter type:
				//   _ = x.m(a)
				// Rewrite to:
				//   _ = methexpr<m>(x, a)
				se := call.X.(*ir.SelectorExpr)
				call.SetOp(ir.OCALLFUNC)
				idx := findMethodExprClosure(info.dictInfo, se)
				c := getDictionaryEntryAddr(se.Pos(), info.dictParam, info.dictInfo.startMethodExprClosures+idx, info.dictInfo.dictLen)
				t := typecheck.NewMethodType(se.Type(), se.X.Type())
				call.X = ir.NewConvExpr(se.Pos(), ir.OCONVNOP, t, c)
				typed(t, call.X)
				call.Args.Prepend(se.X)
				break
				// TODO: deref case?
			}
			if op == ir.OMETHVALUE {
				// Redo the transformation of OXDOT, now that we
				// know the method value is being called.
				call.X.(*ir.SelectorExpr).SetOp(ir.OXDOT)
				transformDot(call.X.(*ir.SelectorExpr), true)
			}
			transformCall(call)

		case ir.OCONVIFACE:
			if m.Type().IsEmptyInterface() && m.(*ir.ConvExpr).X.Type().IsEmptyInterface() {
				// Was T->interface{}, after stenciling it is now interface{}->interface{}.
				// No longer need the conversion. See issue 48276.
				m.(*ir.ConvExpr).SetOp(ir.OCONVNOP)
				break
			}
			mce := m.(*ir.ConvExpr)
			// Note: x's argument is still typed as a type parameter.
			// m's argument now has an instantiated type.
			if mce.X.Type().HasShape() || (m.Type().HasShape() && !m.Type().IsEmptyInterface()) {
				m = convertUsingDictionary(info, info.dictParam, m.Pos(), mce.X, m, m.Type())
			}
		case ir.ODOTTYPE, ir.ODOTTYPE2:
			dt := m.(*ir.TypeAssertExpr)
			if dt.Type().IsEmptyInterface() || (dt.Type().IsInterface() && !dt.Type().HasShape()) {
				break
			}
			if !dt.Type().HasShape() && !(dt.X.Type().HasShape() && !dt.X.Type().IsEmptyInterface()) {
				break
			}
			var rtype, itab ir.Node
			if dt.Type().IsInterface() || dt.X.Type().IsEmptyInterface() {
				// TODO(mdempsky): Investigate executing this block unconditionally.
				ix := findDictType(info, m.Type())
				assert(ix >= 0)
				rtype = getDictionaryType(info, info.dictParam, dt.Pos(), ix)
			} else {
				// nonempty interface to noninterface. Need an itab.
				ix := -1
				for i, ic := range info.dictInfo.itabConvs {
					if ic == m {
						ix = info.dictInfo.startItabConv + i
						break
					}
				}
				assert(ix >= 0)
				itab = getDictionaryEntry(dt.Pos(), info.dictParam, ix, info.dictInfo.dictLen)
			}
			op := ir.ODYNAMICDOTTYPE
			if m.Op() == ir.ODOTTYPE2 {
				op = ir.ODYNAMICDOTTYPE2
			}
			m = ir.NewDynamicTypeAssertExpr(dt.Pos(), op, dt.X, rtype)
			m.(*ir.DynamicTypeAssertExpr).ITab = itab
			m.SetType(dt.Type())
			m.SetTypecheck(1)
		case ir.OCASE:
			if _, ok := m.(*ir.CommClause); ok {
				// This is not a type switch. TODO: Should we use an OSWITCH case here instead of OCASE?
				break
			}
			m := m.(*ir.CaseClause)
			for i, c := range m.List {
				if c.Op() == ir.OTYPE && c.Type().HasShape() {
					// Use a *runtime._type for the dynamic type.
					ix := findDictType(info, m.List[i].Type())
					assert(ix >= 0)
					dt := ir.NewDynamicType(c.Pos(), getDictionaryEntry(c.Pos(), info.dictParam, ix, info.dictInfo.dictLen))

					// For type switch from nonempty interfaces to non-interfaces, we need an itab as well.
					if !m.List[i].Type().IsInterface() {
						if _, ok := info.dictInfo.type2switchType[m.List[i]]; ok {
							// Type switch from nonempty interface. We need a *runtime.itab
							// for the dynamic type.
							ix := -1
							for j, ic := range info.dictInfo.itabConvs {
								if ic == m.List[i] {
									ix = info.dictInfo.startItabConv + j
									break
								}
							}
							assert(ix >= 0)
							dt.ITab = getDictionaryEntry(c.Pos(), info.dictParam, ix, info.dictInfo.dictLen)
						}
					}
					typed(m.List[i].Type(), dt)
					m.List[i] = dt
				}
			}

		}
		return m
	}
	edit(info.fun)
	ir.CurFunc = savef
}

// findDictType looks for type t in the typeparams or derived types in the generic
// function info.gfInfo. This will indicate the dictionary entry with the
// correct concrete type for the associated instantiated function.
func findDictType(info *instInfo, t *types.Type) int {
	for i, dt := range info.dictInfo.shapeParams {
		if dt == t {
			return i
		}
	}
	for i, dt := range info.dictInfo.derivedTypes {
		if types.IdenticalStrict(dt, t) {
			return i + len(info.dictInfo.shapeParams)
		}
	}
	return -1
}

// convertUsingDictionary converts instantiated value v (type v.Type()) to an interface
// type dst, by returning a new set of nodes that make use of a dictionary entry. in is the
// instantiated node of the CONVIFACE node or XDOT node (for a bound method call) that is causing the
// conversion.
func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v ir.Node, in ir.Node, dst *types.Type) ir.Node {
	assert(v.Type().HasShape() || (in.Type().HasShape() && !in.Type().IsEmptyInterface()))
	assert(dst.IsInterface())

	if v.Type().IsInterface() {
		// Converting from an interface. The shape-ness of the source doesn't really matter, as
		// we'll be using the concrete type from the first interface word.
		if dst.IsEmptyInterface() {
			// Converting I2E. OCONVIFACE does that for us, and doesn't depend
			// on what the empty interface was instantiated with. No dictionary entry needed.
			v = ir.NewConvExpr(pos, ir.OCONVIFACE, dst, v)
			v.SetTypecheck(1)
			return v
		}
		if !in.Type().HasShape() {
			// Regular OCONVIFACE works if the destination isn't parameterized.
			v = ir.NewConvExpr(pos, ir.OCONVIFACE, dst, v)
			v.SetTypecheck(1)
			return v
		}

		// We get the destination interface type from the dictionary and the concrete
		// type from the argument's itab. Call runtime.convI2I to get the new itab.
		tmp := typecheck.Temp(v.Type())
		as := ir.NewAssignStmt(pos, tmp, v)
		as.SetTypecheck(1)
		itab := ir.NewUnaryExpr(pos, ir.OITAB, tmp)
		typed(types.Types[types.TUINTPTR].PtrTo(), itab)
		idata := ir.NewUnaryExpr(pos, ir.OIDATA, tmp)
		typed(types.Types[types.TUNSAFEPTR], idata)

		fn := typecheck.LookupRuntime("convI2I")
		fn.SetTypecheck(1)
		types.CalcSize(fn.Type())
		call := ir.NewCallExpr(pos, ir.OCALLFUNC, fn, nil)
		typed(types.Types[types.TUINT8].PtrTo(), call)
		ix := findDictType(info, in.Type())
		assert(ix >= 0)
		inter := getDictionaryType(info, dictParam, pos, ix)
		call.Args = []ir.Node{inter, itab}
		i := ir.NewBinaryExpr(pos, ir.OEFACE, call, idata)
		typed(dst, i)
		i.PtrInit().Append(as)
		return i
	}

	var rt ir.Node
	if !dst.IsEmptyInterface() {
		// We should have an itab entry in the dictionary. Using this itab
		// will be more efficient than converting to an empty interface first
		// and then type asserting to dst.
		ix := -1
		for i, ic := range info.dictInfo.itabConvs {
			if ic == in {
				ix = info.dictInfo.startItabConv + i
				break
			}
		}
		assert(ix >= 0)
		rt = getDictionaryEntry(pos, dictParam, ix, info.dictInfo.dictLen)
	} else {
		ix := findDictType(info, v.Type())
		assert(ix >= 0)
		// Load the actual runtime._type of the type parameter from the dictionary.
		rt = getDictionaryType(info, dictParam, pos, ix)
	}

	// Figure out what the data field of the interface will be.
	data := ir.NewConvExpr(pos, ir.OCONVIDATA, nil, v)
	typed(types.Types[types.TUNSAFEPTR], data)

	// Build an interface from the type and data parts.
	var i ir.Node = ir.NewBinaryExpr(pos, ir.OEFACE, rt, data)
	typed(dst, i)
	return i
}

func (subst *subster) namelist(l []*ir.Name) []*ir.Name {
	s := make([]*ir.Name, len(l))
	for i, n := range l {
		s[i] = subst.localvar(n)
	}
	return s
}

func (subst *subster) list(l []ir.Node) []ir.Node {
	s := make([]ir.Node, len(l))
	for i, n := range l {
		s[i] = subst.node(n)
	}
	return s
}

// fields sets the Nname field for the Field nodes inside a type signature, based
// on the corresponding in/out parameters in dcl. It depends on the in and out
// parameters being in order in dcl.
func (subst *subster) fields(class ir.Class, oldfields []*types.Field, dcl []*ir.Name) []*types.Field {
	// Find the starting index in dcl of declarations of the class (either
	// PPARAM or PPARAMOUT).
	var i int
	for i = range dcl {
		if dcl[i].Class == class {
			break
		}
	}

	// Create newfields nodes that are copies of the oldfields nodes, but
	// with substitution for any type params, and with Nname set to be the node in
	// Dcl for the corresponding PPARAM or PPARAMOUT.
	newfields := make([]*types.Field, len(oldfields))
	for j := range oldfields {
		newfields[j] = oldfields[j].Copy()
		newfields[j].Type = subst.ts.Typ(oldfields[j].Type)
		// A PPARAM field will be missing from dcl if its name is
		// unspecified or specified as "_". So, we compare the dcl sym
		// with the field sym (or sym of the field's Nname node). (Unnamed
		// results still have a name like ~r2 in their Nname node.) If
		// they don't match, this dcl (if there is one left) must apply to
		// a later field.
		if i < len(dcl) && (dcl[i].Sym() == oldfields[j].Sym ||
			(oldfields[j].Nname != nil && dcl[i].Sym() == oldfields[j].Nname.Sym())) {
			newfields[j].Nname = dcl[i]
			i++
		}
	}
	return newfields
}

// deref does a single deref of type t, if it is a pointer type.
func deref(t *types.Type) *types.Type {
	if t.IsPtr() {
		return t.Elem()
	}
	return t
}

// markTypeUsed marks type t as used in order to help avoid dead-code elimination of
// needed methods.
func markTypeUsed(t *types.Type, lsym *obj.LSym) {
	if t.IsInterface() {
		return
	}
	// TODO: This is somewhat overkill, we really only need it
	// for types that are put into interfaces.
	// Note: this relocation is also used in cmd/link/internal/ld/dwarf.go
	reflectdata.MarkTypeUsedInInterface(t, lsym)
}

// getDictionarySym returns the dictionary for the named generic function gf, which
// is instantiated with the type arguments targs.
func (g *genInst) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) *types.Sym {
	if len(targs) == 0 {
		base.Fatalf("%s should have type arguments", gf.Sym().Name)
	}

	// Enforce that only concrete types can make it to here.
	for _, t := range targs {
		if t.HasShape() {
			panic(fmt.Sprintf("shape %+v in dictionary for %s", t, gf.Sym().Name))
		}
	}

	// Get a symbol representing the dictionary.
	sym := typecheck.MakeDictSym(gf.Sym(), targs, isMeth)

	// Initialize the dictionary, if we haven't yet already.
	lsym := sym.Linksym()
	if len(lsym.P) > 0 {
		// We already started creating this dictionary and its lsym.
		return sym
	}

	infoPrint("=== Creating dictionary %v\n", sym.Name)
	off := 0
	// Emit an entry for each targ (concrete type or gcshape).
	for _, t := range targs {
		infoPrint(" * %v\n", t)
		s := reflectdata.TypeLinksym(t)
		off = objw.SymPtr(lsym, off, s, 0)
		markTypeUsed(t, lsym)
	}

	instInfo := g.getInstantiation(gf, targs, isMeth)
	info := instInfo.dictInfo

	subst := typecheck.Tsubster{
		Tparams: info.shapeParams,
		Targs:   targs,
	}
	// Emit an entry for each derived type (after substituting targs)
	for _, t := range info.derivedTypes {
		ts := subst.Typ(t)
		infoPrint(" - %v\n", ts)
		s := reflectdata.TypeLinksym(ts)
		off = objw.SymPtr(lsym, off, s, 0)
		markTypeUsed(ts, lsym)
	}
	// Emit an entry for each subdictionary (after substituting targs)
	for _, subDictInfo := range info.subDictCalls {
		var sym *types.Sym
		n := subDictInfo.callNode
		switch n.Op() {
		case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH:
			call := n.(*ir.CallExpr)
			if call.X.Op() == ir.OXDOT || call.X.Op() == ir.ODOTMETH {
				var nameNode *ir.Name
				se := call.X.(*ir.SelectorExpr)
				if se.X.Type().IsShape() {
					// This is a method call enabled by a type bound.
					tparam := se.X.Type()
					if call.X.Op() == ir.ODOTMETH {
						// We need this extra check for method expressions,
						// which don't add in the implicit XDOTs.
						tmpse := ir.NewSelectorExpr(src.NoXPos, ir.OXDOT, se.X, se.Sel)
						tmpse = typecheck.AddImplicitDots(tmpse)
						tparam = tmpse.X.Type()
					}
					if !tparam.IsShape() {
						// The method expression is not
						// really on a typeparam.
						break
					}
					ix := -1
					for i, shape := range info.shapeParams {
						if shape == tparam {
							ix = i
							break
						}
					}
					assert(ix >= 0)
					recvType := targs[ix]
					if recvType.IsInterface() || len(recvType.RParams()) == 0 {
						// No sub-dictionary entry is
						// actually needed, since the
						// type arg is not an
						// instantiated type that
						// will have generic methods.
						break
					}
					// This is a method call for an
					// instantiated type, so we need a
					// sub-dictionary.
					targs := recvType.RParams()
					genRecvType := recvType.OrigType()
					nameNode = typecheck.Lookdot1(call.X, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name)
					sym = g.getDictionarySym(nameNode, targs, true)
				} else {
					// This is the case of a normal
					// method call on a generic type.
					assert(subDictInfo.savedXNode == se)
					sym = g.getSymForMethodCall(se, &subst)
				}
			} else {
				inst, ok := call.X.(*ir.InstExpr)
				if ok {
					// Code hasn't been transformed yet
					assert(subDictInfo.savedXNode == inst)
				}
				// If !ok, then the generic method/function call has
				// already been transformed to a shape instantiation
				// call. Either way, use the SelectorExpr/InstExpr
				// node saved in info.
				cex := subDictInfo.savedXNode
				if se, ok := cex.(*ir.SelectorExpr); ok {
					sym = g.getSymForMethodCall(se, &subst)
				} else {
					inst := cex.(*ir.InstExpr)
					nameNode := inst.X.(*ir.Name)
					subtargs := typecheck.TypesOf(inst.Targs)
					for i, t := range subtargs {
						subtargs[i] = subst.Typ(t)
					}
					sym = g.getDictionarySym(nameNode, subtargs, false)
				}
			}

		case ir.OFUNCINST:
			inst := n.(*ir.InstExpr)
			nameNode := inst.X.(*ir.Name)
			subtargs := typecheck.TypesOf(inst.Targs)
			for i, t := range subtargs {
				subtargs[i] = subst.Typ(t)
			}
			sym = g.getDictionarySym(nameNode, subtargs, false)

		case ir.OXDOT, ir.OMETHEXPR, ir.OMETHVALUE:
			sym = g.getSymForMethodCall(n.(*ir.SelectorExpr), &subst)

		default:
			assert(false)
		}

		if sym == nil {
			// Unused sub-dictionary entry, just emit 0.
			off = objw.Uintptr(lsym, off, 0)
			infoPrint(" - Unused subdict entry\n")
		} else {
			off = objw.SymPtr(lsym, off, sym.Linksym(), 0)
			infoPrint(" - Subdict %v\n", sym.Name)
		}
	}

	g.instantiateMethods()
	delay := &delayInfo{
		gf:     gf,
		targs:  targs,
		sym:    sym,
		off:    off,
		isMeth: isMeth,
	}
	g.dictSymsToFinalize = append(g.dictSymsToFinalize, delay)
	return sym
}

// getSymForMethodCall gets the dictionary sym for a method call, method value, or method
// expression that has selector se. subst gives the substitution from shape types to
// concrete types.
func (g *genInst) getSymForMethodCall(se *ir.SelectorExpr, subst *typecheck.Tsubster) *types.Sym {
	// For everything except method expressions, 'recvType = deref(se.X.Type)' would
	// also give the receiver type. For method expressions with embedded types, we
	// need to look at the type of the selection to get the final receiver type.
	recvType := deref(se.Selection.Type.Recv().Type)
	genRecvType := recvType.OrigType()
	nameNode := typecheck.Lookdot1(se, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name)
	subtargs := recvType.RParams()
	s2targs := make([]*types.Type, len(subtargs))
	for i, t := range subtargs {
		s2targs[i] = subst.Typ(t)
	}
	return g.getDictionarySym(nameNode, s2targs, true)
}

// finalizeSyms finishes up all dictionaries on g.dictSymsToFinalize, by writing out
// any needed LSyms for itabs. The itab lsyms create wrappers which need various
// dictionaries and method instantiations to be complete, so, to avoid recursive
// dependencies, we finalize the itab lsyms only after all dictionaries syms and
// instantiations have been created.
// Also handles writing method expression closures into the dictionaries.
func (g *genInst) finalizeSyms() {
Outer:
	for _, d := range g.dictSymsToFinalize {
		infoPrint("=== Finalizing dictionary %s\n", d.sym.Name)

		lsym := d.sym.Linksym()
		instInfo := g.getInstantiation(d.gf, d.targs, d.isMeth)
		info := instInfo.dictInfo

		subst := typecheck.Tsubster{
			Tparams: info.shapeParams,
			Targs:   d.targs,
		}

		// Emit an entry for each itab
		for _, n := range info.itabConvs {
			var srctype, dsttype *types.Type
			switch n.Op() {
			case ir.OXDOT, ir.OMETHVALUE:
				se := n.(*ir.SelectorExpr)
				srctype = subst.Typ(se.X.Type())
				dsttype = subst.Typ(info.shapeToBound[se.X.Type()])
			case ir.ODOTTYPE, ir.ODOTTYPE2:
				srctype = subst.Typ(n.(*ir.TypeAssertExpr).Type())
				dsttype = subst.Typ(n.(*ir.TypeAssertExpr).X.Type())
			case ir.OCONVIFACE:
				srctype = subst.Typ(n.(*ir.ConvExpr).X.Type())
				dsttype = subst.Typ(n.Type())
			case ir.OTYPE:
				srctype = subst.Typ(n.Type())
				dsttype = subst.Typ(info.type2switchType[n])
			default:
				base.Fatalf("itab entry with unknown op %s", n.Op())
			}
			if srctype.IsInterface() || dsttype.IsEmptyInterface() {
				// No itab is wanted if src type is an interface. We
				// will use a type assert instead.
				d.off = objw.Uintptr(lsym, d.off, 0)
				infoPrint(" + Unused itab entry for %v\n", srctype)
			} else {
				// Make sure all new fully-instantiated types have
				// their methods created before generating any itabs.
				g.instantiateMethods()
				itabLsym := reflectdata.ITabLsym(srctype, dsttype)
				d.off = objw.SymPtr(lsym, d.off, itabLsym, 0)
				markTypeUsed(srctype, lsym)
				infoPrint(" + Itab for (%v,%v)\n", srctype, dsttype)
			}
		}

		// Emit an entry for each method expression closure.
		// Each entry is a (captureless) closure pointing to the method on the instantiating type.
		// In other words, the entry is a runtime.funcval whose fn field is set to the method
		// in question, and has no other fields. The address of this dictionary entry can be
		// cast to a func of the appropriate type.
		// TODO: do these need to be done when finalizing, or can we do them earlier?
		for _, bf := range info.methodExprClosures {
			rcvr := d.targs[bf.idx]
			rcvr2 := deref(rcvr)
			found := false
			typecheck.CalcMethods(rcvr2) // Ensure methods on all instantiating types are computed.
			for _, f := range rcvr2.AllMethods().Slice() {
				if f.Sym.Name == bf.name {
					codePtr := ir.MethodSym(rcvr, f.Sym).Linksym()
					d.off = objw.SymPtr(lsym, d.off, codePtr, 0)
					infoPrint(" + MethodExprClosure for %v.%s\n", rcvr, bf.name)
					found = true
					break
				}
			}
			if !found {
				// We failed to find a method expression needed for this
				// dictionary. This may happen because we tried to create a
				// dictionary for an invalid instantiation.
				//
				// For example, in test/typeparam/issue54225.go, we attempt to
				// construct a dictionary for "Node[struct{}].contentLen",
				// even though "struct{}" does not implement "Value", so it
				// cannot actually be used as a type argument to "Node".
				//
				// The real issue here is we shouldn't be attempting to create
				// those dictionaries in the first place (e.g., CL 428356),
				// but that fix is scarier for backporting to Go 1.19. Too
				// many backport CLs to this code have fixed one issue while
				// introducing another.
				//
				// So as a hack, instead of calling Fatalf, we simply skip
				// calling objw.Global below, which prevents us from emitting
				// the broken dictionary. The linker's dead code elimination
				// should then naturally prune this invalid, unneeded
				// dictionary. Worst case, if the dictionary somehow *is*
				// needed by the final executable, we've just turned an ICE
				// into a link-time missing symbol failure.
				infoPrint(" ! abandoning dictionary %v; missing method expression %v.%s\n", d.sym.Name, rcvr, bf.name)
				continue Outer
			}
		}

		objw.Global(lsym, int32(d.off), obj.DUPOK|obj.RODATA)
		infoPrint("=== Finalized dictionary %s\n", d.sym.Name)
	}
	g.dictSymsToFinalize = nil
}

func (g *genInst) getDictionaryValue(pos src.XPos, gf *ir.Name, targs []*types.Type, isMeth bool) ir.Node {
	sym := g.getDictionarySym(gf, targs, isMeth)

	// Make (or reuse) a node referencing the dictionary symbol.
	var n *ir.Name
	if sym.Def != nil {
		n = sym.Def.(*ir.Name)
	} else {
		// We set the position of a static dictionary to be the position of
		// one of its uses.
		n = ir.NewNameAt(pos, sym)
		n.Curfn = ir.CurFunc
		n.SetType(types.Types[types.TUINTPTR]) // should probably be [...]uintptr, but doesn't really matter
		n.SetTypecheck(1)
		n.Class = ir.PEXTERN
		sym.Def = n
	}

	// Return the address of the dictionary.  Addr node gets position that was passed in.
	np := typecheck.NodAddrAt(pos, n)
	// Note: treat dictionary pointers as uintptrs, so they aren't pointers
	// with respect to GC. That saves on stack scanning work, write barriers, etc.
	// We can get away with it because dictionaries are global variables.
	// TODO: use a cast, or is typing directly ok?
	np.SetType(types.Types[types.TUINTPTR])
	np.SetTypecheck(1)
	return np
}

// hasShapeNodes returns true if the type of any node in targs has a shape.
func hasShapeNodes(targs []ir.Ntype) bool {
	for _, n := range targs {
		if n.Type().HasShape() {
			return true
		}
	}
	return false
}

// hasShapeTypes returns true if any type in targs has a shape.
func hasShapeTypes(targs []*types.Type) bool {
	for _, t := range targs {
		if t.HasShape() {
			return true
		}
	}
	return false
}

// getInstInfo get the dictionary format for a function instantiation- type params, derived
// types, and needed subdictionaries, itabs, and method expression closures.
func (g *genInst) getInstInfo(st *ir.Func, shapes []*types.Type, instInfo *instInfo) {
	info := instInfo.dictInfo
	info.shapeParams = shapes

	for _, t := range info.shapeParams {
		b := info.shapeToBound[t]
		if b.HasShape() {
			// If a type bound is parameterized (unusual case), then we
			// may need its derived type to do a type assert when doing a
			// bound call for a type arg that is an interface.
			addType(info, nil, b)
		}
	}

	for _, n := range st.Dcl {
		addType(info, n, n.Type())
		n.DictIndex = uint16(findDictType(instInfo, n.Type()) + 1)
	}

	if infoPrintMode {
		fmt.Printf(">>> InstInfo for %v\n", st)
		for _, t := range info.shapeParams {
			fmt.Printf("  Typeparam %v\n", t)
		}
	}

	// Map to remember when we have seen an instantiated function value or method
	// expression/value as part of a call, so we can determine when we encounter
	// an uncalled function value or method expression/value.
	callMap := make(map[ir.Node]bool)

	var visitFunc func(ir.Node)
	visitFunc = func(n ir.Node) {
		switch n.Op() {
		case ir.OFUNCINST:
			if !callMap[n] && hasShapeNodes(n.(*ir.InstExpr).Targs) {
				infoPrint("  Closure&subdictionary required at generic function value %v\n", n.(*ir.InstExpr).X)
				info.subDictCalls = append(info.subDictCalls, subDictInfo{callNode: n, savedXNode: nil})
			}
		case ir.OMETHEXPR, ir.OMETHVALUE:
			if !callMap[n] && !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) &&
				len(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) > 0 &&
				hasShapeTypes(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) {
				if n.(*ir.SelectorExpr).X.Op() == ir.OTYPE {
					infoPrint("  Closure&subdictionary required at generic meth expr %v\n", n)
				} else {
					infoPrint("  Closure&subdictionary required at generic meth value %v\n", n)
				}
				info.subDictCalls = append(info.subDictCalls, subDictInfo{callNode: n, savedXNode: nil})
			}
		case ir.OCALL:
			ce := n.(*ir.CallExpr)
			if ce.X.Op() == ir.OFUNCINST {
				callMap[ce.X] = true
				if hasShapeNodes(ce.X.(*ir.InstExpr).Targs) {
					infoPrint("  Subdictionary at generic function/method call: %v - %v\n", ce.X.(*ir.InstExpr).X, n)
					// Save the instExpr node for the function call,
					// since we will lose this information when the
					// generic function call is transformed to a call
					// on the shape instantiation.
					info.subDictCalls = append(info.subDictCalls, subDictInfo{callNode: n, savedXNode: ce.X})
				}
			}
			// Note: this XDOT code is not actually needed as long as we
			// continue to disable type parameters on RHS of type
			// declarations (#45639).
			if ce.X.Op() == ir.OXDOT {
				callMap[ce.X] = true
				if isBoundMethod(info, ce.X.(*ir.SelectorExpr)) {
					infoPrint("  Optional subdictionary at generic bound call: %v\n", n)
					info.subDictCalls = append(info.subDictCalls, subDictInfo{callNode: n, savedXNode: nil})
				}
			}
		case ir.OCALLMETH:
			ce := n.(*ir.CallExpr)
			if ce.X.Op() == ir.ODOTMETH &&
				len(deref(ce.X.(*ir.SelectorExpr).X.Type()).RParams()) > 0 {
				callMap[ce.X] = true
				if hasShapeTypes(deref(ce.X.(*ir.SelectorExpr).X.Type()).RParams()) {
					infoPrint("  Subdictionary at generic method call: %v\n", n)
					// Save the selector for the method call, since we
					// will eventually lose this information when the
					// generic method call is transformed into a
					// function call on the method shape instantiation.
					info.subDictCalls = append(info.subDictCalls, subDictInfo{callNode: n, savedXNode: ce.X})
				}
			}
		case ir.OCONVIFACE:
			if n.Type().IsInterface() && !n.Type().IsEmptyInterface() &&
				(n.Type().HasShape() || n.(*ir.ConvExpr).X.Type().HasShape()) {
				infoPrint("  Itab for interface conv: %v\n", n)
				info.itabConvs = append(info.itabConvs, n)
			}
		case ir.OXDOT:
			se := n.(*ir.SelectorExpr)
			if se.X.Op() == ir.OTYPE && se.X.Type().IsShape() {
				// Method expression.
				addMethodExprClosure(info, se)
				break
			}
			if isBoundMethod(info, se) {
				if callMap[n] {
					// Method value called directly. Use method expression closure.
					addMethodExprClosure(info, se)
					break
				}
				// Method value not called directly. Still doing the old way.
				infoPrint("  Itab for bound call: %v\n", n)
				info.itabConvs = append(info.itabConvs, n)
			}

		case ir.ODOTTYPE, ir.ODOTTYPE2:
			if !n.(*ir.TypeAssertExpr).Type().IsInterface() && !n.(*ir.TypeAssertExpr).X.Type().IsEmptyInterface() {
				infoPrint("  Itab for dot type: %v\n", n)
				info.itabConvs = append(info.itabConvs, n)
			}
		case ir.OCLOSURE:
			// Visit the closure body and add all relevant entries to the
			// dictionary of the outer function (closure will just use
			// the dictionary of the outer function).
			cfunc := n.(*ir.ClosureExpr).Func
			for _, n1 := range cfunc.Body {
				ir.Visit(n1, visitFunc)
			}
			for _, n := range cfunc.Dcl {
				n.DictIndex = uint16(findDictType(instInfo, n.Type()) + 1)
			}
		case ir.OSWITCH:
			ss := n.(*ir.SwitchStmt)
			if ss.Tag != nil && ss.Tag.Op() == ir.OTYPESW &&
				!ss.Tag.(*ir.TypeSwitchGuard).X.Type().IsEmptyInterface() {
				for _, cc := range ss.Cases {
					for _, c := range cc.List {
						if c.Op() == ir.OTYPE && c.Type().HasShape() {
							// Type switch from a non-empty interface - might need an itab.
							infoPrint("  Itab for type switch: %v\n", c)
							info.itabConvs = append(info.itabConvs, c)
							if info.type2switchType == nil {
								info.type2switchType = map[ir.Node]*types.Type{}
							}
							info.type2switchType[c] = ss.Tag.(*ir.TypeSwitchGuard).X.Type()
						}
					}
				}
			}
		}
		addType(info, n, n.Type())
	}

	for _, stmt := range st.Body {
		ir.Visit(stmt, visitFunc)
	}
	if infoPrintMode {
		for _, t := range info.derivedTypes {
			fmt.Printf("  Derived type %v\n", t)
		}
		fmt.Printf(">>> Done Instinfo\n")
	}
	info.startSubDict = len(info.shapeParams) + len(info.derivedTypes)
	info.startItabConv = len(info.shapeParams) + len(info.derivedTypes) + len(info.subDictCalls)
	info.startMethodExprClosures = len(info.shapeParams) + len(info.derivedTypes) + len(info.subDictCalls) + len(info.itabConvs)
	info.dictLen = len(info.shapeParams) + len(info.derivedTypes) + len(info.subDictCalls) + len(info.itabConvs) + len(info.methodExprClosures)
}

// isBoundMethod returns true if the selection indicated by se is a bound method of
// se.X. se.X must be a shape type (i.e. substituted directly from a type param). If
// isBoundMethod returns false, then the selection must be a field access of a
// structural type.
func isBoundMethod(info *dictInfo, se *ir.SelectorExpr) bool {
	bound := info.shapeToBound[se.X.Type()]
	return typecheck.Lookdot1(se, se.Sel, bound, bound.AllMethods(), 1) != nil
}

func shapeIndex(info *dictInfo, t *types.Type) int {
	for i, s := range info.shapeParams {
		if s == t {
			return i
		}
	}
	base.Fatalf("can't find type %v in shape params", t)
	return -1
}

// addMethodExprClosure adds the T.M method expression to the list of bound method expressions
// used in the generic body.
// isBoundMethod must have returned true on the same arguments.
func addMethodExprClosure(info *dictInfo, se *ir.SelectorExpr) {
	idx := shapeIndex(info, se.X.Type())
	name := se.Sel.Name
	for _, b := range info.methodExprClosures {
		if idx == b.idx && name == b.name {
			return
		}
	}
	infoPrint("  Method expression closure for %v.%s\n", info.shapeParams[idx], name)
	info.methodExprClosures = append(info.methodExprClosures, methodExprClosure{idx: idx, name: name})
}

// findMethodExprClosure finds the entry in the dictionary to use for the T.M
// method expression encoded in se.
// isBoundMethod must have returned true on the same arguments.
func findMethodExprClosure(info *dictInfo, se *ir.SelectorExpr) int {
	idx := shapeIndex(info, se.X.Type())
	name := se.Sel.Name
	for i, b := range info.methodExprClosures {
		if idx == b.idx && name == b.name {
			return i
		}
	}
	base.Fatalf("can't find method expression closure for %s %s", se.X.Type(), name)
	return -1
}

// addType adds t to info.derivedTypes if it is parameterized type (which is not
// just a simple shape) that is different from any existing type on
// info.derivedTypes.
func addType(info *dictInfo, n ir.Node, t *types.Type) {
	if t == nil || !t.HasShape() {
		return
	}
	if t.IsShape() {
		return
	}
	if t.Kind() == types.TFUNC && n != nil &&
		(t.Recv() != nil || n.Op() == ir.ONAME && n.Name().Class == ir.PFUNC) {
		// Don't use the type of a named generic function or method,
		// since that is parameterized by other typeparams.
		// (They all come from arguments of a FUNCINST node.)
		return
	}
	if doubleCheck && !parameterizedBy(t, info.shapeParams) {
		base.Fatalf("adding type with invalid parameters %+v", t)
	}
	if t.Kind() == types.TSTRUCT && t.IsFuncArgStruct() {
		// Multiple return values are not a relevant new type (?).
		return
	}
	// Ignore a derived type we've already added.
	for _, et := range info.derivedTypes {
		if types.IdenticalStrict(t, et) {
			return
		}
	}
	info.derivedTypes = append(info.derivedTypes, t)
}

// parameterizedBy returns true if t is parameterized by (at most) params.
func parameterizedBy(t *types.Type, params []*types.Type) bool {
	return parameterizedBy1(t, params, map[*types.Type]bool{})
}
func parameterizedBy1(t *types.Type, params []*types.Type, visited map[*types.Type]bool) bool {
	if visited[t] {
		return true
	}
	visited[t] = true

	if t.Sym() != nil && len(t.RParams()) > 0 {
		// This defined type is instantiated. Check the instantiating types.
		for _, r := range t.RParams() {
			if !parameterizedBy1(r, params, visited) {
				return false
			}
		}
		return true
	}
	if t.IsShape() {
		// Check if t is one of the allowed parameters in scope.
		for _, p := range params {
			if p == t {
				return true
			}
		}
		// Couldn't find t in the list of allowed parameters.
		return false

	}
	switch t.Kind() {
	case types.TARRAY, types.TPTR, types.TSLICE, types.TCHAN:
		return parameterizedBy1(t.Elem(), params, visited)

	case types.TMAP:
		return parameterizedBy1(t.Key(), params, visited) && parameterizedBy1(t.Elem(), params, visited)

	case types.TFUNC:
		return parameterizedBy1(t.TParams(), params, visited) && parameterizedBy1(t.Recvs(), params, visited) && parameterizedBy1(t.Params(), params, visited) && parameterizedBy1(t.Results(), params, visited)

	case types.TSTRUCT:
		for _, f := range t.Fields().Slice() {
			if !parameterizedBy1(f.Type, params, visited) {
				return false
			}
		}
		return true

	case types.TINTER:
		for _, f := range t.Methods().Slice() {
			if !parameterizedBy1(f.Type, params, visited) {
				return false
			}
		}
		return true

	case types.TINT, types.TINT8, types.TINT16, types.TINT32, types.TINT64,
		types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64,
		types.TUINTPTR, types.TBOOL, types.TSTRING, types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128, types.TUNSAFEPTR:
		return true

	case types.TUNION:
		for i := 0; i < t.NumTerms(); i++ {
			tt, _ := t.Term(i)
			if !parameterizedBy1(tt, params, visited) {
				return false
			}
		}
		return true

	default:
		base.Fatalf("bad type kind %+v", t)
		return true
	}
}

// startClosures starts creation of a closure that has the function type typ. It
// creates all the formal params and results according to the type typ. On return,
// the body and closure variables of the closure must still be filled in, and
// ir.UseClosure() called.
func startClosure(pos src.XPos, outer *ir.Func, typ *types.Type) (*ir.Func, []*types.Field, []*types.Field) {
	// Make a new internal function.
	fn := ir.NewClosureFunc(pos, outer != nil)
	ir.NameClosure(fn.OClosure, outer)

	// Build formal argument and return lists.
	var formalParams []*types.Field  // arguments of closure
	var formalResults []*types.Field // returns of closure
	for i := 0; i < typ.NumParams(); i++ {
		t := typ.Params().Field(i).Type
		arg := ir.NewNameAt(pos, closureSym(outer, "a", i))
		arg.Class = ir.PPARAM
		typed(t, arg)
		arg.Curfn = fn
		fn.Dcl = append(fn.Dcl, arg)
		f := types.NewField(pos, arg.Sym(), t)
		f.Nname = arg
		f.SetIsDDD(typ.Params().Field(i).IsDDD())
		formalParams = append(formalParams, f)
	}
	for i := 0; i < typ.NumResults(); i++ {
		t := typ.Results().Field(i).Type
		result := ir.NewNameAt(pos, closureSym(outer, "r", i)) // TODO: names not needed?
		result.Class = ir.PPARAMOUT
		typed(t, result)
		result.Curfn = fn
		fn.Dcl = append(fn.Dcl, result)
		f := types.NewField(pos, result.Sym(), t)
		f.Nname = result
		formalResults = append(formalResults, f)
	}

	// Build an internal function with the right signature.
	closureType := types.NewSignature(typ.Pkg(), nil, nil, formalParams, formalResults)
	typed(closureType, fn.Nname)
	typed(typ, fn.OClosure)
	fn.SetTypecheck(1)
	return fn, formalParams, formalResults

}

// closureSym returns outer.Sym().Pkg.LookupNum(prefix, n).
// If outer is nil, then types.LocalPkg is used instead.
func closureSym(outer *ir.Func, prefix string, n int) *types.Sym {
	pkg := types.LocalPkg
	if outer != nil {
		pkg = outer.Sym().Pkg
	}
	return pkg.LookupNum(prefix, n)
}

// assertToBound returns a new node that converts a node rcvr with interface type to
// the 'dst' interface type.
func assertToBound(info *instInfo, dictVar *ir.Name, pos src.XPos, rcvr ir.Node, dst *types.Type) ir.Node {
	if !dst.HasShape() {
		return typed(dst, ir.NewTypeAssertExpr(pos, rcvr, nil))
	}

	ix := findDictType(info, dst)
	assert(ix >= 0)
	rt := getDictionaryType(info, dictVar, pos, ix)
	return typed(dst, ir.NewDynamicTypeAssertExpr(pos, ir.ODYNAMICDOTTYPE, rcvr, rt))
}

Youez - 2016 - github.com/yon3zu
LinuXploit