xref: /inferno-os/utils/5c/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 t;
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 OASLMUL:
99 	case OASMUL:
100 		xcom(l);
101 		xcom(r);
102 		t = vlog(r);
103 		if(t >= 0) {
104 			n->op = OASASHL;
105 			r->vconst = t;
106 			r->type = types[TINT];
107 		}
108 		break;
109 
110 	case OMUL:
111 	case OLMUL:
112 		xcom(l);
113 		xcom(r);
114 		t = vlog(r);
115 		if(t >= 0) {
116 			n->op = OASHL;
117 			r->vconst = t;
118 			r->type = types[TINT];
119 		}
120 		t = vlog(l);
121 		if(t >= 0) {
122 			n->op = OASHL;
123 			n->left = r;
124 			n->right = l;
125 			r = l;
126 			l = n->left;
127 			r->vconst = t;
128 			r->type = types[TINT];
129 		}
130 		break;
131 
132 	case OASLDIV:
133 		xcom(l);
134 		xcom(r);
135 		t = vlog(r);
136 		if(t >= 0) {
137 			n->op = OASLSHR;
138 			r->vconst = t;
139 			r->type = types[TINT];
140 		}
141 		break;
142 
143 	case OLDIV:
144 		xcom(l);
145 		xcom(r);
146 		t = vlog(r);
147 		if(t >= 0) {
148 			n->op = OLSHR;
149 			r->vconst = t;
150 			r->type = types[TINT];
151 		}
152 		break;
153 
154 	case OASLMOD:
155 		xcom(l);
156 		xcom(r);
157 		t = vlog(r);
158 		if(t >= 0) {
159 			n->op = OASAND;
160 			r->vconst--;
161 		}
162 		break;
163 
164 	case OLMOD:
165 		xcom(l);
166 		xcom(r);
167 		t = vlog(r);
168 		if(t >= 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 
184 	if(l != Z)
185 		n->complex = l->complex;
186 	if(r != Z) {
187 		if(r->complex == n->complex)
188 			n->complex = r->complex+1;
189 		else
190 		if(r->complex > n->complex)
191 			n->complex = r->complex;
192 	}
193 	if(n->complex == 0)
194 		n->complex++;
195 
196 	if(com64(n))
197 		return;
198 
199 	switch(n->op) {
200 	case OFUNC:
201 		n->complex = FNX;
202 		break;
203 
204 	case OADD:
205 	case OXOR:
206 	case OAND:
207 	case OOR:
208 	case OEQ:
209 	case ONE:
210 		/*
211 		 * immediate operators, make const on right
212 		 */
213 		if(l->op == OCONST) {
214 			n->left = r;
215 			n->right = l;
216 		}
217 		break;
218 	}
219 }
220