xref: /inferno-os/utils/kc/sgen.c (revision 7ef44d652ae9e5e1f5b3465d73684e4a54de73c0)
1 #include "gc.h"
2 
3 void
4 noretval(int n)
5 {
6 
7 	if(n & 1) {
8 		gins(ANOP, Z, Z);
9 		p->to.type = D_REG;
10 		p->to.reg = REGRET;
11 	}
12 	if(n & 2) {
13 		gins(ANOP, Z, Z);
14 		p->to.type = D_FREG;
15 		p->to.reg = FREGRET;
16 	}
17 }
18 
19 /*
20  *	calculate addressability as follows
21  *		CONST ==> 20		$value
22  *		NAME ==> 10		name
23  *		REGISTER ==> 11		register
24  *		INDREG ==> 12		*[(reg)+offset]
25  *		&10 ==> 2		$name
26  *		ADD(2, 20) ==> 2	$name+offset
27  *		ADD(3, 20) ==> 3	$(reg)+offset
28  *		&12 ==> 3		$(reg)+offset
29  *		*11 ==> 11		??
30  *		*2 ==> 10		name
31  *		*3 ==> 12		*(reg)+offset
32  *	calculate complexity (number of registers)
33  */
34 void
35 xcom(Node *n)
36 {
37 	Node *l, *r;
38 	int v;
39 
40 	if(n == Z)
41 		return;
42 	l = n->left;
43 	r = n->right;
44 	n->addable = 0;
45 	n->complex = 0;
46 	switch(n->op) {
47 	case OCONST:
48 		n->addable = 20;
49 		return;
50 
51 	case OREGISTER:
52 		n->addable = 11;
53 		return;
54 
55 	case OINDREG:
56 		n->addable = 12;
57 		return;
58 
59 	case ONAME:
60 		n->addable = 10;
61 		return;
62 
63 	case OADDR:
64 		xcom(l);
65 		if(l->addable == 10)
66 			n->addable = 2;
67 		if(l->addable == 12)
68 			n->addable = 3;
69 		break;
70 
71 	case OIND:
72 		xcom(l);
73 		if(l->addable == 11)
74 			n->addable = 12;
75 		if(l->addable == 3)
76 			n->addable = 12;
77 		if(l->addable == 2)
78 			n->addable = 10;
79 		break;
80 
81 	case OADD:
82 		xcom(l);
83 		xcom(r);
84 		if(l->addable == 20) {
85 			if(r->addable == 2)
86 				n->addable = 2;
87 			if(r->addable == 3)
88 				n->addable = 3;
89 		}
90 		if(r->addable == 20) {
91 			if(l->addable == 2)
92 				n->addable = 2;
93 			if(l->addable == 3)
94 				n->addable = 3;
95 		}
96 		break;
97 
98 	case OASMUL:
99 	case OASLMUL:
100 		xcom(l);
101 		xcom(r);
102 		v = vlog(r);
103 		if(v >= 0) {
104 			n->op = OASASHL;
105 			r->vconst = v;
106 			r->type = types[TINT];
107 		}
108 		break;
109 
110 	case OMUL:
111 	case OLMUL:
112 		xcom(l);
113 		xcom(r);
114 		v = vlog(r);
115 		if(v >= 0) {
116 			n->op = OASHL;
117 			r->vconst = v;
118 			r->type = types[TINT];
119 		}
120 		v = vlog(l);
121 		if(v >= 0) {
122 			n->op = OASHL;
123 			n->left = r;
124 			n->right = l;
125 			r = l;
126 			l = n->left;
127 			r->vconst = v;
128 			r->type = types[TINT];
129 		}
130 		break;
131 
132 	case OASLDIV:
133 		xcom(l);
134 		xcom(r);
135 		v = vlog(r);
136 		if(v >= 0) {
137 			n->op = OASLSHR;
138 			r->vconst = v;
139 			r->type = types[TINT];
140 		}
141 		break;
142 
143 	case OLDIV:
144 		xcom(l);
145 		xcom(r);
146 		v = vlog(r);
147 		if(v >= 0) {
148 			n->op = OLSHR;
149 			r->vconst = v;
150 			r->type = types[TINT];
151 		}
152 		break;
153 
154 	case OASLMOD:
155 		xcom(l);
156 		xcom(r);
157 		v = vlog(r);
158 		if(v >= 0) {
159 			n->op = OASAND;
160 			r->vconst--;
161 		}
162 		break;
163 
164 	case OLMOD:
165 		xcom(l);
166 		xcom(r);
167 		v = vlog(r);
168 		if(v >= 0) {
169 			n->op = OAND;
170 			r->vconst--;
171 		}
172 		break;
173 
174 	default:
175 		if(l != Z)
176 			xcom(l);
177 		if(r != Z)
178 			xcom(r);
179 		break;
180 	}
181 	if(n->addable >= 10)
182 		return;
183 	if(l != Z)
184 		n->complex = l->complex;
185 	if(r != Z) {
186 		if(r->complex == n->complex)
187 			n->complex = r->complex+1;
188 		else
189 		if(r->complex > n->complex)
190 			n->complex = r->complex;
191 	}
192 	if(n->complex == 0)
193 		n->complex++;
194 
195 	if(com64(n))
196 		return;
197 
198 	switch(n->op) {
199 
200 	case OFUNC:
201 		n->complex = FNX;
202 		break;
203 
204 	case OEQ:
205 	case ONE:
206 	case OLE:
207 	case OLT:
208 	case OGE:
209 	case OGT:
210 	case OHI:
211 	case OHS:
212 	case OLO:
213 	case OLS:
214 		/*
215 		 * immediate operators, make const on right
216 		 */
217 		if(l->op == OCONST) {
218 			n->left = r;
219 			n->right = l;
220 			n->op = invrel[relindex(n->op)];
221 		}
222 		break;
223 
224 	case OADD:
225 	case OXOR:
226 	case OAND:
227 	case OOR:
228 		/*
229 		 * immediate operators, make const on right
230 		 */
231 		if(l->op == OCONST) {
232 			n->left = r;
233 			n->right = l;
234 		}
235 		break;
236 	}
237 }
238 
239