OLD | NEW |
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 /* | 5 /* |
6 * portable half of code generator. | 6 * portable half of code generator. |
7 * mainly statements and control flow. | 7 * mainly statements and control flow. |
8 */ | 8 */ |
9 | 9 |
10 #include <u.h> | 10 #include <u.h> |
(...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
799 * res = s[lo, hi]; | 799 * res = s[lo, hi]; |
800 * n->left is s | 800 * n->left is s |
801 * n->list is (cap(s)-lo(TUINT), hi-lo(TUINT)[, lo*width(TUINTPTR)]) | 801 * n->list is (cap(s)-lo(TUINT), hi-lo(TUINT)[, lo*width(TUINTPTR)]) |
802 * caller (cgen) guarantees res is an addable ONAME. | 802 * caller (cgen) guarantees res is an addable ONAME. |
803 * | 803 * |
804 * called for OSLICE, OSLICE3, OSLICEARR, OSLICE3ARR, OSLICESTR. | 804 * called for OSLICE, OSLICE3, OSLICEARR, OSLICE3ARR, OSLICESTR. |
805 */ | 805 */ |
806 void | 806 void |
807 cgen_slice(Node *n, Node *res) | 807 cgen_slice(Node *n, Node *res) |
808 { | 808 { |
809 » Node src, dst, *cap, *len, *offs, *add, *base; | 809 » Node src, dst, *cap, *len, *offs, *add, *base, *tmpcap, *tmplen, *cmp, c
on; |
| 810 » Prog *p1, *p2; |
810 | 811 |
811 cap = n->list->n; | 812 cap = n->list->n; |
812 len = n->list->next->n; | 813 len = n->list->next->n; |
813 offs = N; | 814 offs = N; |
814 if(n->list->next->next) | 815 if(n->list->next->next) |
815 offs = n->list->next->next->n; | 816 offs = n->list->next->next->n; |
816 | 817 |
817 // evaluate base pointer first, because it is the only | 818 // evaluate base pointer first, because it is the only |
818 // possibly complex expression. once that is evaluated | 819 // possibly complex expression. once that is evaluated |
819 // and stored, updating the len and cap can be done | 820 // and stored, updating the len and cap can be done |
820 // without making any calls, so without doing anything that | 821 // without making any calls, so without doing anything that |
821 // might cause preemption or garbage collection. | 822 // might cause preemption or garbage collection. |
822 // this makes the whole slice update atomic as far as the | 823 // this makes the whole slice update atomic as far as the |
823 // garbage collector can see. | 824 // garbage collector can see. |
824 ········ | 825 ········ |
825 base = temp(types[TUINTPTR]); | 826 base = temp(types[TUINTPTR]); |
| 827 tmplen = temp(types[TINT]); |
| 828 if(n->op != OSLICESTR) |
| 829 tmpcap = temp(types[TINT]); |
| 830 else |
| 831 tmpcap = tmplen; |
826 | 832 |
827 if(isnil(n->left)) { | 833 if(isnil(n->left)) { |
828 tempname(&src, n->left->type); | 834 tempname(&src, n->left->type); |
829 cgen(n->left, &src); | 835 cgen(n->left, &src); |
830 } else | 836 } else |
831 src = *n->left; | 837 src = *n->left; |
832 if(n->op == OSLICE || n->op == OSLICE3 || n->op == OSLICESTR) | 838 if(n->op == OSLICE || n->op == OSLICE3 || n->op == OSLICESTR) |
833 src.xoffset += Array_array; | 839 src.xoffset += Array_array; |
834 | 840 |
835 if(n->op == OSLICEARR || n->op == OSLICE3ARR) { | 841 if(n->op == OSLICEARR || n->op == OSLICE3ARR) { |
836 if(!isptr[n->left->type->etype]) | 842 if(!isptr[n->left->type->etype]) |
837 fatal("slicearr is supposed to work on pointer: %+N\n",
n); | 843 fatal("slicearr is supposed to work on pointer: %+N\n",
n); |
838 cgen(&src, base); | 844 cgen(&src, base); |
839 cgen_checknil(base); | 845 cgen_checknil(base); |
840 » » if(offs != N) { | 846 » } else { |
841 » » » add = nod(OADD, base, offs); | |
842 » » » typecheck(&add, Erv); | |
843 » » » cgen(add, base); | |
844 » » } | |
845 » } else if(offs == N) { | |
846 src.type = types[tptr]; | 847 src.type = types[tptr]; |
847 cgen(&src, base); | 848 cgen(&src, base); |
848 } else { | |
849 src.type = types[tptr]; | |
850 add = nod(OADDPTR, &src, offs); | |
851 typecheck(&add, Erv); | |
852 cgen(add, base); | |
853 } | 849 } |
854 ········ | 850 ········ |
855 // committed to the update | 851 // committed to the update |
856 gvardef(res); | 852 gvardef(res); |
857 | 853 |
| 854 // compute len and cap. |
| 855 // len = n-i, cap = m-i, and offs = i*width. |
| 856 // computing offs last lets the multiply overwrite i. |
| 857 cgen(len, tmplen); |
| 858 if(n->op != OSLICESTR) |
| 859 cgen(cap, tmpcap); |
| 860 |
| 861 // if new cap != 0 { base += add } |
| 862 // This avoids advancing base past the end of the underlying array/strin
g, |
| 863 // so that it cannot point at the next object in memory. |
| 864 // If cap == 0, the base doesn't matter except insofar as it is 0 or non
-zero. |
| 865 // In essence we are replacing x[i:j:k] where i == j == k |
| 866 // or x[i:j] where i == j == cap(x) with x[0:0:0]. |
| 867 if(offs != N) { |
| 868 p1 = gjmp(P); |
| 869 p2 = gjmp(P); |
| 870 patch(p1, pc); |
| 871 |
| 872 nodconst(&con, tmpcap->type, 0); |
| 873 cmp = nod(OEQ, tmpcap, &con); |
| 874 typecheck(&cmp, Erv); |
| 875 bgen(cmp, 1, -1, p2); |
| 876 |
| 877 add = nod(OADD, base, offs); |
| 878 typecheck(&add, Erv); |
| 879 cgen(add, base); |
| 880 |
| 881 patch(p2, pc); |
| 882 } |
| 883 |
858 // dst.array = src.array [ + lo *width ] | 884 // dst.array = src.array [ + lo *width ] |
859 dst = *res; | 885 dst = *res; |
860 dst.xoffset += Array_array; | 886 dst.xoffset += Array_array; |
861 dst.type = types[tptr]; | 887 dst.type = types[tptr]; |
862 ········ | |
863 cgen(base, &dst); | 888 cgen(base, &dst); |
864 | 889 |
865 // dst.len = hi [ - lo ] | 890 // dst.len = hi [ - lo ] |
866 dst = *res; | 891 dst = *res; |
867 dst.xoffset += Array_nel; | 892 dst.xoffset += Array_nel; |
868 dst.type = types[simtype[TUINT]]; | 893 dst.type = types[simtype[TUINT]]; |
869 » cgen(len, &dst); | 894 » cgen(tmplen, &dst); |
870 | 895 |
871 if(n->op != OSLICESTR) { | 896 if(n->op != OSLICESTR) { |
872 // dst.cap = cap [ - lo ] | 897 // dst.cap = cap [ - lo ] |
873 dst = *res; | 898 dst = *res; |
874 dst.xoffset += Array_cap; | 899 dst.xoffset += Array_cap; |
875 dst.type = types[simtype[TUINT]]; | 900 dst.type = types[simtype[TUINT]]; |
876 » » cgen(cap, &dst); | 901 » » cgen(tmpcap, &dst); |
877 } | 902 } |
878 } | 903 } |
879 | 904 |
880 /* | 905 /* |
881 * gather series of offsets | 906 * gather series of offsets |
882 * >=0 is direct addressed field | 907 * >=0 is direct addressed field |
883 * <0 is pointer to next field (+1) | 908 * <0 is pointer to next field (+1) |
884 */ | 909 */ |
885 int | 910 int |
886 dotoffset(Node *n, int64 *oary, Node **nn) | 911 dotoffset(Node *n, int64 *oary, Node **nn) |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
965 Node* | 990 Node* |
966 temp(Type *t) | 991 temp(Type *t) |
967 { | 992 { |
968 Node *n; | 993 Node *n; |
969 ········ | 994 ········ |
970 n = nod(OXXX, N, N); | 995 n = nod(OXXX, N, N); |
971 tempname(n, t); | 996 tempname(n, t); |
972 n->sym->def->used = 1; | 997 n->sym->def->used = 1; |
973 return n->orig; | 998 return n->orig; |
974 } | 999 } |
OLD | NEW |