Left: | ||
Right: |
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 #include <u.h> | 5 #include <u.h> |
6 #include <libc.h> | 6 #include <libc.h> |
7 #include "go.h" | 7 #include "go.h" |
8 | 8 |
9 static Node* walkprint(Node*, NodeList**, int); | 9 static Node* walkprint(Node*, NodeList**, int); |
10 static Node* mapfn(char*, Type*); | 10 static Node* mapfn(char*, Type*); |
11 static Node* mapfndel(char*, Type*); | 11 static Node* mapfndel(char*, Type*); |
12 static Node* ascompatee1(int, Node*, Node*, NodeList**); | 12 static Node* ascompatee1(int, Node*, Node*, NodeList**); |
13 static NodeList* ascompatee(int, NodeList*, NodeList*, NodeList**); | 13 static NodeList* ascompatee(int, NodeList*, NodeList*, NodeList**); |
14 static NodeList* ascompatet(int, NodeList*, Type**, int, NodeList**); | 14 static NodeList* ascompatet(int, NodeList*, Type**, int, NodeList**); |
15 static NodeList* ascompatte(int, Node*, int, Type**, NodeList*, int, Node List**); | 15 static NodeList* ascompatte(int, Node*, int, Type**, NodeList*, int, Node List**); |
16 static Node* convas(Node*, NodeList**); | 16 static Node* convas(Node*, NodeList**); |
17 static void heapmoves(void); | 17 static void heapmoves(void); |
18 static NodeList* paramstoheap(Type **argin, int out); | 18 static NodeList* paramstoheap(Type **argin, int out); |
19 static NodeList* reorder1(NodeList*); | 19 static NodeList* reorder1(NodeList*); |
20 static NodeList* reorder3(NodeList*); | 20 static NodeList* reorder3(NodeList*); |
21 static Node* addstr(Node*, NodeList**); | 21 static Node* addstr(Node*, NodeList**); |
22 static Node* appendslice(Node*, NodeList**); | 22 static Node* appendslice(Node*, NodeList**); |
23 static Node* append(Node*, NodeList**); | 23 static Node* append(Node*, NodeList**); |
24 static Node* sliceany(Node*, NodeList**); | 24 static Node* sliceany(Node*, NodeList**); |
25 static void walkcompare(Node**, NodeList**); | 25 static void walkcompare(Node**, NodeList**); |
26 static void walkrotate(Node**); | 26 static void walkrotate(Node**); |
27 static void walkdiv(Node**, NodeList**); | |
27 static int bounded(Node*, int64); | 28 static int bounded(Node*, int64); |
28 static Mpint mpzero; | 29 static Mpint mpzero; |
29 | 30 |
30 // can this code branch reach the end | 31 // can this code branch reach the end |
31 // without an unconditional RETURN | 32 // without an unconditional RETURN |
32 // this is hard, so it is conservative | 33 // this is hard, so it is conservative |
33 static int | 34 static int |
34 walkret(NodeList *l) | 35 walkret(NodeList *l) |
35 { | 36 { |
36 Node *n; | 37 Node *n; |
(...skipping 846 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
883 n->right = nod(OCOM, n->right, N); | 884 n->right = nod(OCOM, n->right, N); |
884 typecheck(&n->right, Erv); | 885 typecheck(&n->right, Erv); |
885 } | 886 } |
886 n->left = safeexpr(n->left, init); | 887 n->left = safeexpr(n->left, init); |
887 walkexpr(&n->left, init); | 888 walkexpr(&n->left, init); |
888 l = n->left; | 889 l = n->left; |
889 walkexpr(&n->right, init); | 890 walkexpr(&n->right, init); |
890 | 891 |
891 /* | 892 /* |
892 * on 32-bit arch, rewrite 64-bit ops into l = l op r. | 893 * on 32-bit arch, rewrite 64-bit ops into l = l op r. |
893 * on 386, rewrite float ops into l = l op r. | 894 * on 386, rewrite float ops into l = l op r. |
dfc
2012/11/11 22:51:52
should this be 386/arm ?
remyoudompheng
2012/11/12 06:55:23
I don't know.
| |
894 * everywhere, rewrite map ops into l = l op r. | 895 * everywhere, rewrite map ops into l = l op r. |
895 * everywhere, rewrite string += into l = l op r. | 896 * everywhere, rewrite string += into l = l op r. |
896 » » * everywhere, rewrite complex /= into l = l op r. | 897 » » * everywhere, rewrite integer/complex /= into l = l op r. |
897 * TODO(rsc): Maybe this rewrite should be done always? | 898 * TODO(rsc): Maybe this rewrite should be done always? |
898 */ | 899 */ |
899 et = n->left->type->etype; | 900 et = n->left->type->etype; |
900 if((widthptr == 4 && (et == TUINT64 || et == TINT64)) || | 901 if((widthptr == 4 && (et == TUINT64 || et == TINT64)) || |
901 (thechar == '8' && isfloat[et]) || | 902 (thechar == '8' && isfloat[et]) || |
902 l->op == OINDEXMAP || | 903 l->op == OINDEXMAP || |
903 et == TSTRING || | 904 et == TSTRING || |
904 » » (iscomplex[et] && n->etype == ODIV)) { | 905 » » (!isfloat[et] && n->etype == ODIV) || |
906 » » n->etype == OMOD) { | |
905 l = safeexpr(n->left, init); | 907 l = safeexpr(n->left, init); |
906 a = l; | 908 a = l; |
907 if(a->op == OINDEXMAP) { | 909 if(a->op == OINDEXMAP) { |
908 // map index has "lhs" bit set in a->etype. | 910 // map index has "lhs" bit set in a->etype. |
909 // make a copy so we can clear it on the rhs. | 911 // make a copy so we can clear it on the rhs. |
910 a = nod(OXXX, N, N); | 912 a = nod(OXXX, N, N); |
911 *a = *l; | 913 *a = *l; |
912 a->etype = 0; | 914 a->etype = 0; |
913 } | 915 } |
914 r = nod(OAS, l, nod(n->etype, a, n->right)); | 916 r = nod(OAS, l, nod(n->etype, a, n->right)); |
(...skipping 23 matching lines...) Expand all Loading... | |
938 */ | 940 */ |
939 et = n->left->type->etype; | 941 et = n->left->type->etype; |
940 if(iscomplex[et] && n->op == ODIV) { | 942 if(iscomplex[et] && n->op == ODIV) { |
941 t = n->type; | 943 t = n->type; |
942 n = mkcall("complex128div", types[TCOMPLEX128], init, | 944 n = mkcall("complex128div", types[TCOMPLEX128], init, |
943 conv(n->left, types[TCOMPLEX128]), | 945 conv(n->left, types[TCOMPLEX128]), |
944 conv(n->right, types[TCOMPLEX128])); | 946 conv(n->right, types[TCOMPLEX128])); |
945 n = conv(n, t); | 947 n = conv(n, t); |
946 goto ret; | 948 goto ret; |
947 } | 949 } |
950 // Nothing to do for float divisions. | |
951 if(isfloat[et]) | |
952 goto ret; | |
953 // Try rewriting as shifts or magic multiplies. | |
954 walkdiv(&n, init); | |
955 switch(n->op) { | |
956 default: | |
957 goto ret; | |
958 case OMOD: | |
959 case ODIV: | |
960 break; | |
961 } | |
dfc
2012/11/11 22:51:52
why not move the block into this switch then push
remyoudompheng
2012/11/12 06:55:23
It made the diff smaller. but it's weird indeed.
| |
948 /* | 962 /* |
949 * rewrite div and mod into function calls | 963 * rewrite div and mod into function calls |
950 * on 32-bit architectures. | 964 * on 32-bit architectures. |
951 */ | 965 */ |
952 if(widthptr > 4 || (et != TUINT64 && et != TINT64)) | 966 if(widthptr > 4 || (et != TUINT64 && et != TINT64)) |
953 goto ret; | 967 goto ret; |
954 if(et == TINT64) | 968 if(et == TINT64) |
955 strcpy(namebuf, "int64"); | 969 strcpy(namebuf, "int64"); |
956 else | 970 else |
957 strcpy(namebuf, "uint64"); | 971 strcpy(namebuf, "uint64"); |
(...skipping 1898 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2856 ········ | 2870 ········ |
2857 // Remove rotate 0 and rotate w. | 2871 // Remove rotate 0 and rotate w. |
2858 s = mpgetfix(n->right->val.u.xval); | 2872 s = mpgetfix(n->right->val.u.xval); |
2859 if(s == 0 || s == w) | 2873 if(s == 0 || s == w) |
2860 n = n->left; | 2874 n = n->left; |
2861 | 2875 |
2862 *np = n; | 2876 *np = n; |
2863 return; | 2877 return; |
2864 } | 2878 } |
2865 | 2879 |
2880 static void | |
2881 walkdiv(Node **np, NodeList **init) | |
2882 { | |
2883 Node *n, *nl, *nr, *nc; | |
2884 Node *n1, *n2, *n3, *n4; | |
2885 int pow; // if >= 0, nr is 1<<n | |
2886 int s; // 1 if nr is negative. | |
2887 int w; | |
2888 Type *twide; | |
2889 Magic m; | |
2890 | |
2891 n = *np; | |
2892 if(n->right->op != OLITERAL) | |
2893 return; | |
2894 // nr is a constant. | |
2895 nl = cheapexpr(n->left, init); | |
2896 nr = n->right; | |
2897 | |
2898 // special cases of mod/div | |
2899 // by a constant | |
dfc
2012/11/11 22:51:52
nit: maybe move this comment to like 2908
remyoudompheng
2012/11/12 06:55:23
Makes a good description for the function.
| |
2900 w = nl->type->width*8; | |
2901 s = 0; | |
2902 pow = powtwo(nr); | |
2903 if(pow >= 1000) { | |
2904 // negative power of 2 | |
2905 s = 1; | |
2906 pow -= 1000; | |
2907 } | |
2908 | |
2909 if(pow+1 >= w) { | |
2910 // just sign bit | |
dfc
2012/11/11 22:51:52
i know this came from 6g, but can the comment be i
remyoudompheng
2012/11/12 06:55:23
i'm not even sure what it means. We could add a sp
| |
2911 return; | |
2912 } | |
2913 if(pow < 0) { | |
2914 goto divbymul; | |
2915 } | |
2916 | |
2917 switch(pow) { | |
2918 case 0: | |
2919 if(n->op == OMOD) { | |
2920 // nl % 1 is zero. | |
2921 nodconst(n, n->type, 0); | |
2922 } else if(s) { | |
2923 // divide by -1 | |
2924 n->op = OMINUS; | |
2925 n->right = N; | |
2926 } else { | |
2927 // divide by 1 | |
2928 n = nl; | |
2929 } | |
2930 break; | |
2931 default: | |
2932 if(issigned[n->type->etype]) { | |
2933 if(n->op == OMOD) { | |
2934 goto longmod; | |
2935 } else { | |
2936 // arithmetic right shift does not give the corr ect rounding. | |
2937 // if nl >= 0, nl >> n == nl / nr | |
2938 // if nl < 0, we want to add 2^n-1 first. | |
2939 nc = nod(OXXX, N, N); | |
2940 nodconst(nc, types[simtype[TUINT]], w-1); | |
2941 n1 = nod(ORSH, nl, nc); // n1 = -1 iff nl < 0. | |
2942 if(pow == 1) { | |
2943 // nl+1 is nl-(-1) | |
2944 n->left = nod(OSUB, nl, n1); | |
2945 } else { | |
2946 // Do a logical right right on -1 to kee p pow bits. | |
2947 nc = nod(OXXX, N, N); | |
2948 nodconst(nc, types[simtype[TUINT]], w-po w); | |
2949 n2 = nod(ORSH, conv(n1, tounsigned(nl->t ype)), nc); | |
2950 n->left = nod(OADD, nl, conv(n2, nl->typ e)); | |
2951 } | |
2952 // n = (nl + 2^pow-1) >> pow | |
2953 n->op = ORSH; | |
2954 nc = nod(OXXX, N, N); | |
2955 nodconst(nc, types[simtype[TUINT]], pow); | |
2956 n->right = nc; | |
2957 n->typecheck = 0; | |
2958 } | |
2959 if(s) | |
2960 n = nod(OMINUS, n, N); | |
2961 break; | |
2962 } | |
2963 nc = nod(OXXX, N, N); | |
2964 if(n->op == OMOD) { | |
2965 // n = nl & (nr-1) | |
2966 n->op = OAND; | |
2967 nodconst(nc, nl->type, mpgetfix(nr->val.u.xval)-1); | |
2968 } else { | |
2969 // n = nl >> pow | |
2970 n->op = ORSH; | |
2971 nodconst(nc, types[simtype[TUINT]], pow); | |
2972 } | |
2973 n->typecheck = 0; | |
2974 n->right = nc; | |
2975 break; | |
2976 } | |
2977 goto ret; | |
2978 | |
2979 divbymul: | |
2980 if(n->op == OMOD) | |
2981 goto longmod; | |
2982 | |
2983 // try to do division by multiply by (2^w)/d | |
2984 // see hacker's delight chapter 10 | |
2985 // TODO: support 64-bit magic multiply here. | |
2986 m.w = w; | |
2987 if(issigned[nl->type->etype]) { | |
2988 m.sd = mpgetfix(nr->val.u.xval); | |
2989 smagic(&m); | |
2990 } else { | |
2991 m.ud = mpgetfix(nr->val.u.xval); | |
2992 umagic(&m); | |
2993 } | |
2994 if(m.bad) | |
2995 return; | |
2996 | |
2997 // Select a Go type with (at least) twice the width. | |
2998 switch(simtype[nl->type->etype]) { | |
2999 default: | |
3000 return; | |
3001 case TUINT8: | |
3002 case TUINT16: | |
3003 twide = types[TUINT32]; | |
3004 break; | |
3005 case TUINT32: | |
3006 twide = types[TUINT64]; | |
3007 break; | |
3008 case TINT8: | |
3009 case TINT16: | |
3010 twide = types[TINT32]; | |
3011 break; | |
3012 case TINT32: | |
3013 twide = types[TINT64]; | |
3014 break; | |
3015 } | |
3016 | |
3017 switch(simtype[nl->type->etype]) { | |
3018 default: | |
3019 return; | |
3020 | |
3021 case TUINT8: | |
3022 case TUINT16: | |
3023 case TUINT32: | |
3024 // n1 = nl * magic. | |
3025 nc = nod(OXXX, N, N); | |
3026 nodconst(nc, twide, m.um); | |
3027 n1 = nod(OMUL, conv(nl, twide), nc); | |
3028 if(m.ua) { | |
3029 // add numerator. | |
3030 // n2 = (n1>>w + nl) | |
3031 nc = nod(OXXX, N, N); | |
3032 nodconst(nc, types[TUINT], w); | |
3033 n2 = nod(ORSH, n1, nc); | |
3034 n3 = nod(OADD, n2, conv(nl, twide)); | |
3035 | |
3036 // shift by m.s | |
3037 nc = nod(OXXX, N, N); | |
3038 nodconst(nc, types[TUINT], m.s); | |
3039 n = conv(nod(ORSH, n3, nc), nl->type); | |
3040 } else { | |
3041 // n = (n1>>w) >> m.s | |
3042 nc = nod(OXXX, N, N); | |
3043 nodconst(nc, types[TUINT], w+m.s); | |
3044 n = conv(nod(ORSH, n1, nc), nl->type); | |
3045 } | |
3046 break; | |
3047 | |
3048 case TINT8: | |
3049 case TINT16: | |
3050 case TINT32: | |
3051 // n1 = nl * magic. | |
3052 nc = nod(OXXX, N, N); | |
3053 nodconst(nc, twide, m.sm); | |
3054 n1 = nod(OMUL, conv(nl, twide), nc); | |
3055 // take the high part with an arithmetic shift. | |
3056 nc = nod(OXXX, N, N); | |
3057 nodconst(nc, types[TUINT], w); | |
3058 n2 = conv(nod(ORSH, n1, nc), nl->type); | |
3059 if(m.sm < 0) { | |
3060 // add the numerator. | |
3061 n2 = nod(OADD, n2, nl); | |
3062 } | |
3063 // shift by m.s | |
3064 nc = nod(OXXX, N, N); | |
3065 nodconst(nc, types[TUINT], m.s); | |
3066 n3 = conv(nod(ORSH, n2, nc), nl->type); | |
3067 // add 1 iff n1 is negative. | |
3068 nc = nod(OXXX, N, N); | |
3069 nodconst(nc, types[TUINT], w-1); | |
3070 n4 = nod(ORSH, nl, nc); // n4 = -1 iff n1 is negative.a | |
3071 n = nod(OSUB, n3, n4); | |
3072 // apply sign. | |
3073 if(m.sd < 0) | |
3074 n = nod(OMINUS, n, N); | |
3075 break; | |
3076 } | |
3077 goto ret; | |
3078 | |
3079 longmod: | |
3080 // rewrite as A%B = A - (A/B*B). | |
3081 n1 = nod(ODIV, nl, nr); | |
3082 n2 = nod(OMUL, n1, nr); | |
3083 n = nod(OSUB, nl, n2); | |
3084 goto ret; | |
3085 | |
3086 ret: | |
3087 typecheck(&n, Erv); | |
3088 walkexpr(&n, init); | |
3089 *np = n; | |
3090 } | |
3091 | |
2866 // return 1 if integer n must be in range [0, max), 0 otherwise | 3092 // return 1 if integer n must be in range [0, max), 0 otherwise |
2867 static int | 3093 static int |
2868 bounded(Node *n, int64 max) | 3094 bounded(Node *n, int64 max) |
2869 { | 3095 { |
2870 int64 v; | 3096 int64 v; |
2871 int32 bits; | 3097 int32 bits; |
2872 int sign; | 3098 int sign; |
2873 | 3099 |
2874 if(n->type == T || !isint[n->type->etype]) | 3100 if(n->type == T || !isint[n->type->etype]) |
2875 return 0; | 3101 return 0; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2961 yyerror("tracked field must be in named struct type"); | 3187 yyerror("tracked field must be in named struct type"); |
2962 if(!exportname(field->sym->name)) | 3188 if(!exportname(field->sym->name)) |
2963 yyerror("tracked field must be exported (upper case)"); | 3189 yyerror("tracked field must be exported (upper case)"); |
2964 | 3190 |
2965 l = typ(0); | 3191 l = typ(0); |
2966 l->type = field; | 3192 l->type = field; |
2967 l->down = curfn->paramfld; | 3193 l->down = curfn->paramfld; |
2968 curfn->paramfld = l; | 3194 curfn->paramfld = l; |
2969 } | 3195 } |
2970 | 3196 |
OLD | NEW |