LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 #undef EXTERN | 5 #undef EXTERN |
6 #define EXTERN | 6 #define EXTERN |
7 #include <u.h> | 7 #include <u.h> |
8 #include <libc.h> | 8 #include <libc.h> |
9 #include "gg.h" | 9 #include "gg.h" |
10 #include "opt.h" | 10 #include "opt.h" |
(...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
760 a = optoas(op, t); | 760 a = optoas(op, t); |
761 gins(a, &n2w, &n1w); | 761 gins(a, &n2w, &n1w); |
762 cgen(&n1w, &n1b); | 762 cgen(&n1w, &n1b); |
763 cgen(&n1b, res); | 763 cgen(&n1b, res); |
764 | 764 |
765 regfree(&n1w); | 765 regfree(&n1w); |
766 regfree(&n2w); | 766 regfree(&n2w); |
767 regfree(&n1b); | 767 regfree(&n1b); |
768 regfree(&n2b); | 768 regfree(&n2b); |
769 } | 769 } |
770 | |
771 static int | |
772 regcmp(const void *va, const void *vb) | |
773 { | |
774 Node *ra, *rb; | |
775 | |
776 ra = (Node*)va; | |
777 rb = (Node*)vb; | |
778 return ra->local - rb->local; | |
779 } | |
780 | |
781 static Prog* throwpc; | |
782 | |
783 // We're only going to bother inlining if we can | |
784 // convert all the arguments to 32 bits safely. Can we? | |
785 static int | |
786 fix64(NodeList *nn, int n) | |
787 { | |
788 NodeList *l; | |
789 Node *r; | |
790 int i; | |
791 ········ | |
792 l = nn; | |
793 for(i=0; i<n; i++) { | |
794 r = l->n->right; | |
795 if(is64(r->type) && !smallintconst(r)) { | |
796 if(r->op == OCONV) | |
797 r = r->left; | |
798 if(is64(r->type)) | |
799 return 0; | |
800 } | |
801 l = l->next; | |
802 } | |
803 return 1; | |
804 } | |
805 | |
806 void | |
807 getargs(NodeList *nn, Node *reg, int n) | |
808 { | |
809 NodeList *l; | |
810 Node *r; | |
811 int i; | |
812 | |
813 throwpc = nil; | |
814 | |
815 l = nn; | |
816 for(i=0; i<n; i++) { | |
817 r = l->n->right; | |
818 if(is64(r->type)) { | |
819 if(r->op == OCONV) | |
820 r = r->left; | |
821 else if(smallintconst(r)) | |
822 r->type = types[TUINT32]; | |
823 if(is64(r->type)) | |
824 fatal("getargs"); | |
825 } | |
826 if(!smallintconst(r) && !isslice(r->type)) { | |
827 if(i < 3) // AX CX DX | |
828 nodreg(reg+i, r->type, D_AX+i); | |
829 else | |
830 reg[i].op = OXXX; | |
831 regalloc(reg+i, r->type, reg+i); | |
832 cgen(r, reg+i); | |
833 } else | |
834 reg[i] = *r; | |
835 if(reg[i].local != 0) | |
836 yyerror("local used"); | |
837 reg[i].local = l->n->left->xoffset; | |
838 l = l->next; | |
839 } | |
840 qsort((void*)reg, n, sizeof(*reg), regcmp); | |
841 for(i=0; i<n; i++) | |
842 reg[i].local = 0; | |
843 } | |
844 | |
845 void | |
846 cmpandthrow(Node *nl, Node *nr) | |
847 { | |
848 vlong cl; | |
849 Prog *p1; | |
850 int op; | |
851 Node *c, n1; | |
852 Type *t; | |
853 | |
854 op = OLE; | |
855 if(smallintconst(nl)) { | |
856 cl = mpgetfix(nl->val.u.xval); | |
857 if(cl == 0) | |
858 return; | |
859 if(smallintconst(nr)) | |
860 return; | |
861 // put the constant on the right | |
862 op = brrev(op); | |
863 c = nl; | |
864 nl = nr; | |
865 nr = c; | |
866 } | |
867 ········ | |
868 // Arguments are known not to be 64-bit, | |
869 // but they might be smaller than 32 bits. | |
870 // Check if we need to use a temporary. | |
871 // At least one of the arguments is 32 bits | |
872 // (the len or cap) so one temporary suffices. | |
873 n1.op = OXXX; | |
874 t = types[TUINT32]; | |
875 if(nl->type->width != t->width) { | |
876 regalloc(&n1, t, nl); | |
877 gmove(nl, &n1); | |
878 nl = &n1; | |
879 } else if(nr->type->width != t->width) { | |
880 regalloc(&n1, t, nr); | |
881 gmove(nr, &n1); | |
882 nr = &n1; | |
883 } | |
884 gins(optoas(OCMP, t), nl, nr); | |
885 if(n1.op != OXXX) | |
886 regfree(&n1); | |
887 if(throwpc == nil) { | |
888 p1 = gbranch(optoas(op, t), T); | |
889 throwpc = pc; | |
890 ginscall(panicslice, 0); | |
891 patch(p1, pc); | |
892 } else { | |
893 op = brcom(op); | |
894 p1 = gbranch(optoas(op, t), T); | |
895 patch(p1, throwpc); | |
896 } | |
897 } | |
898 | |
899 int | |
900 sleasy(Node *n) | |
901 { | |
902 if(n->op != ONAME) | |
903 return 0; | |
904 if(!n->addable) | |
905 return 0; | |
906 return 1; | |
907 } | |
908 | |
909 // generate inline code for | |
910 // slicearray | |
911 // sliceslice | |
912 // arraytoslice | |
913 int | |
914 cgen_inline(Node *n, Node *res) | |
915 { | |
916 Node nodes[5]; | |
917 Node n1, n2, nres, ntemp; | |
918 vlong v; | |
919 int i, narg, nochk; | |
920 | |
921 if(n->op != OCALLFUNC) | |
922 goto no; | |
923 if(!n->left->addable) | |
924 goto no; | |
925 if(n->left->sym == S) | |
926 goto no; | |
927 if(n->left->sym->pkg != runtimepkg) | |
928 goto no; | |
929 if(strcmp(n->left->sym->name, "slicearray") == 0) | |
930 goto slicearray; | |
931 if(strcmp(n->left->sym->name, "sliceslice") == 0) { | |
932 narg = 4; | |
933 goto sliceslice; | |
934 } | |
935 if(strcmp(n->left->sym->name, "sliceslice1") == 0) { | |
936 narg = 3; | |
937 goto sliceslice; | |
938 } | |
939 goto no; | |
940 | |
941 slicearray: | |
942 if(!sleasy(res)) | |
943 goto no; | |
944 if(!fix64(n->list, 5)) | |
945 goto no; | |
946 getargs(n->list, nodes, 5); | |
947 | |
948 // if(hb[3] > nel[1]) goto throw | |
949 cmpandthrow(&nodes[3], &nodes[1]); | |
950 | |
951 // if(lb[2] > hb[3]) goto throw | |
952 cmpandthrow(&nodes[2], &nodes[3]); | |
953 | |
954 // len = hb[3] - lb[2] (destroys hb) | |
955 n2 = *res; | |
956 n2.xoffset += Array_nel; | |
957 n2.type = types[TUINT32]; | |
958 | |
959 if(smallintconst(&nodes[3]) && smallintconst(&nodes[2])) { | |
960 v = mpgetfix(nodes[3].val.u.xval) - | |
961 mpgetfix(nodes[2].val.u.xval); | |
962 nodconst(&n1, types[TUINT32], v); | |
963 gins(optoas(OAS, types[TUINT32]), &n1, &n2); | |
964 } else { | |
965 regalloc(&n1, types[TUINT32], &nodes[3]); | |
966 gmove(&nodes[3], &n1); | |
967 if(!smallintconst(&nodes[2]) || mpgetfix(nodes[2].val.u.xval) !=
0) | |
968 gins(optoas(OSUB, types[TUINT32]), &nodes[2], &n1); | |
969 gins(optoas(OAS, types[TUINT32]), &n1, &n2); | |
970 regfree(&n1); | |
971 } | |
972 | |
973 // cap = nel[1] - lb[2] (destroys nel) | |
974 n2 = *res; | |
975 n2.xoffset += Array_cap; | |
976 n2.type = types[TUINT32]; | |
977 | |
978 if(smallintconst(&nodes[1]) && smallintconst(&nodes[2])) { | |
979 v = mpgetfix(nodes[1].val.u.xval) - | |
980 mpgetfix(nodes[2].val.u.xval); | |
981 nodconst(&n1, types[TUINT32], v); | |
982 gins(optoas(OAS, types[TUINT32]), &n1, &n2); | |
983 } else { | |
984 regalloc(&n1, types[TUINT32], &nodes[1]); | |
985 gmove(&nodes[1], &n1); | |
986 if(!smallintconst(&nodes[2]) || mpgetfix(nodes[2].val.u.xval) !=
0) | |
987 gins(optoas(OSUB, types[TUINT32]), &nodes[2], &n1); | |
988 gins(optoas(OAS, types[TUINT32]), &n1, &n2); | |
989 regfree(&n1); | |
990 } | |
991 | |
992 // if slice could be too big, dereference to | |
993 // catch nil array pointer. | |
994 if(nodes[0].op == OREGISTER && nodes[0].type->type->width >= unmappedzer
o) { | |
995 n2 = nodes[0]; | |
996 n2.xoffset = 0; | |
997 n2.op = OINDREG; | |
998 n2.type = types[TUINT8]; | |
999 gins(ATESTB, nodintconst(0), &n2); | |
1000 } | |
1001 | |
1002 // ary = old[0] + (lb[2] * width[4]) (destroys old) | |
1003 n2 = *res; | |
1004 n2.xoffset += Array_array; | |
1005 n2.type = types[tptr]; | |
1006 | |
1007 if(smallintconst(&nodes[2]) && smallintconst(&nodes[4])) { | |
1008 v = mpgetfix(nodes[2].val.u.xval) * | |
1009 mpgetfix(nodes[4].val.u.xval); | |
1010 if(v != 0) { | |
1011 nodconst(&n1, types[tptr], v); | |
1012 gins(optoas(OADD, types[tptr]), &n1, &nodes[0]); | |
1013 } | |
1014 } else { | |
1015 regalloc(&n1, types[tptr], &nodes[2]); | |
1016 gmove(&nodes[2], &n1); | |
1017 if(!smallintconst(&nodes[4]) || mpgetfix(nodes[4].val.u.xval) !=
1) | |
1018 gins(optoas(OMUL, types[tptr]), &nodes[4], &n1); | |
1019 gins(optoas(OADD, types[tptr]), &n1, &nodes[0]); | |
1020 regfree(&n1); | |
1021 } | |
1022 gins(optoas(OAS, types[tptr]), &nodes[0], &n2); | |
1023 | |
1024 for(i=0; i<5; i++) { | |
1025 if(nodes[i].op == OREGISTER) | |
1026 regfree(&nodes[i]); | |
1027 } | |
1028 return 1; | |
1029 | |
1030 sliceslice: | |
1031 if(!fix64(n->list, narg)) | |
1032 goto no; | |
1033 nochk = n->etype; // skip bounds checking | |
1034 ntemp.op = OXXX; | |
1035 if(!sleasy(n->list->n->right)) { | |
1036 Node *n0; | |
1037 ················ | |
1038 n0 = n->list->n->right; | |
1039 tempname(&ntemp, res->type); | |
1040 cgen(n0, &ntemp); | |
1041 n->list->n->right = &ntemp; | |
1042 getargs(n->list, nodes, narg); | |
1043 n->list->n->right = n0; | |
1044 } else | |
1045 getargs(n->list, nodes, narg); | |
1046 | |
1047 nres = *res; // result | |
1048 if(!sleasy(res)) { | |
1049 if(ntemp.op == OXXX) | |
1050 tempname(&ntemp, res->type); | |
1051 nres = ntemp; | |
1052 } | |
1053 | |
1054 if(narg == 3) { // old[lb:] | |
1055 // move width to where it would be for old[lb:hb] | |
1056 nodes[3] = nodes[2]; | |
1057 nodes[2].op = OXXX; | |
1058 ················ | |
1059 // if(lb[1] > old.nel[0]) goto throw; | |
1060 n2 = nodes[0]; | |
1061 n2.xoffset += Array_nel; | |
1062 n2.type = types[TUINT32]; | |
1063 if(!nochk) | |
1064 cmpandthrow(&nodes[1], &n2); | |
1065 | |
1066 // ret.nel = old.nel[0]-lb[1]; | |
1067 n2 = nodes[0]; | |
1068 n2.xoffset += Array_nel; | |
1069 n2.type = types[TUINT32]; | |
1070 ········ | |
1071 regalloc(&n1, types[TUINT32], N); | |
1072 gins(optoas(OAS, types[TUINT32]), &n2, &n1); | |
1073 if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) !=
0) | |
1074 gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1); | |
1075 ········ | |
1076 n2 = nres; | |
1077 n2.xoffset += Array_nel; | |
1078 n2.type = types[TUINT32]; | |
1079 gins(optoas(OAS, types[TUINT32]), &n1, &n2); | |
1080 regfree(&n1); | |
1081 } else { // old[lb:hb] | |
1082 n2 = nodes[0]; | |
1083 n2.xoffset += Array_cap; | |
1084 n2.type = types[TUINT32]; | |
1085 if (!nochk) { | |
1086 // if(hb[2] > old.cap[0]) goto throw; | |
1087 cmpandthrow(&nodes[2], &n2); | |
1088 // if(lb[1] > hb[2]) goto throw; | |
1089 cmpandthrow(&nodes[1], &nodes[2]); | |
1090 } | |
1091 | |
1092 // ret.len = hb[2]-lb[1]; (destroys hb[2]) | |
1093 n2 = nres; | |
1094 n2.xoffset += Array_nel; | |
1095 n2.type = types[TUINT32]; | |
1096 | |
1097 if(smallintconst(&nodes[2]) && smallintconst(&nodes[1])) { | |
1098 v = mpgetfix(nodes[2].val.u.xval) - | |
1099 mpgetfix(nodes[1].val.u.xval); | |
1100 nodconst(&n1, types[TUINT32], v); | |
1101 gins(optoas(OAS, types[TUINT32]), &n1, &n2); | |
1102 } else { | |
1103 regalloc(&n1, types[TUINT32], &nodes[2]); | |
1104 gmove(&nodes[2], &n1); | |
1105 if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.
xval) != 0) | |
1106 gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n
1); | |
1107 gins(optoas(OAS, types[TUINT32]), &n1, &n2); | |
1108 regfree(&n1); | |
1109 } | |
1110 } | |
1111 | |
1112 // ret.cap = old.cap[0]-lb[1]; (uses hb[2]) | |
1113 n2 = nodes[0]; | |
1114 n2.xoffset += Array_cap; | |
1115 n2.type = types[TUINT32]; | |
1116 | |
1117 regalloc(&n1, types[TUINT32], &nodes[2]); | |
1118 gins(optoas(OAS, types[TUINT32]), &n2, &n1); | |
1119 if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0) | |
1120 gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1); | |
1121 | |
1122 n2 = nres; | |
1123 n2.xoffset += Array_cap; | |
1124 n2.type = types[TUINT32]; | |
1125 gins(optoas(OAS, types[TUINT32]), &n1, &n2); | |
1126 regfree(&n1); | |
1127 | |
1128 // ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1]) | |
1129 n2 = nodes[0]; | |
1130 n2.xoffset += Array_array; | |
1131 n2.type = types[tptr]; | |
1132 | |
1133 regalloc(&n1, types[tptr], &nodes[1]); | |
1134 if(smallintconst(&nodes[1]) && smallintconst(&nodes[3])) { | |
1135 gins(optoas(OAS, types[tptr]), &n2, &n1); | |
1136 v = mpgetfix(nodes[1].val.u.xval) * | |
1137 mpgetfix(nodes[3].val.u.xval); | |
1138 if(v != 0) { | |
1139 nodconst(&n2, types[tptr], v); | |
1140 gins(optoas(OADD, types[tptr]), &n2, &n1); | |
1141 } | |
1142 } else { | |
1143 gmove(&nodes[1], &n1); | |
1144 if(!smallintconst(&nodes[3]) || mpgetfix(nodes[3].val.u.xval) !=
1) | |
1145 gins(optoas(OMUL, types[tptr]), &nodes[3], &n1); | |
1146 gins(optoas(OADD, types[tptr]), &n2, &n1); | |
1147 } | |
1148 | |
1149 n2 = nres; | |
1150 n2.xoffset += Array_array; | |
1151 n2.type = types[tptr]; | |
1152 gins(optoas(OAS, types[tptr]), &n1, &n2); | |
1153 regfree(&n1); | |
1154 | |
1155 for(i=0; i<4; i++) { | |
1156 if(nodes[i].op == OREGISTER) | |
1157 regfree(&nodes[i]); | |
1158 } | |
1159 | |
1160 if(!sleasy(res)) { | |
1161 cgen(&nres, res); | |
1162 } | |
1163 return 1; | |
1164 | |
1165 no: | |
1166 return 0; | |
1167 } | |
LEFT | RIGHT |