Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
718 | jacekm | 1 | /* |
2 | ** Small-C Compiler -- Part 3 -- Expression Analyzer. |
||
3 | ** Copyright 1982, 1983, 1985, 1988 J. E. Hendrix |
||
4 | ** Copyright 1998 H T Walheim |
||
5 | ** All rights reserved. |
||
6 | */ |
||
7 | |||
8 | #include |
||
9 | #include "cc.h" |
||
10 | |||
11 | #define ST 0 /* is[ST] - symbol table address, else 0 */ |
||
12 | #define TI 1 /* is[TI] - type of indirect obj to fetch, else 0 */ |
||
13 | #define TA 2 /* is[TA] - type of address, else 0 */ |
||
14 | #define TC 3 /* is[TC] - type of constant (INT or UINT), else 0 */ |
||
15 | #define CV 4 /* is[CV] - value of constant (+ auxiliary uses) */ |
||
16 | #define OP 5 /* is[OP] - code of highest/last binary operator */ |
||
17 | #define SA 6 /* is[SA] - stage address of "op 0" code, else 0 */ |
||
18 | |||
19 | extern char |
||
20 | *litq, *glbptr, *lptr, ssname[NAMESIZE], quote[2]; |
||
21 | extern int |
||
22 | ch, csp, litlab, litptr, nch, op[16], op2[16], |
||
23 | opindex, opsize, *snext; |
||
24 | |||
25 | /***************** lead-in functions *******************/ |
||
26 | |||
27 | constexpr(val) int *val; { |
||
28 | int constant; |
||
29 | int *before, *start; |
||
30 | setstage(&before, &start); |
||
31 | expression(&constant, val); |
||
32 | clearstage(before, 0); /* scratch generated code */ |
||
33 | if(constant == 0) error("must be constant expression"); |
||
34 | return constant; |
||
35 | } |
||
36 | |||
37 | null_is (is) |
||
38 | int is[7]; |
||
39 | { |
||
40 | int i; |
||
41 | |||
42 | for (i = 0; i < 7; ++i) |
||
43 | { |
||
44 | is[i] = 0; /* <-- */ |
||
45 | } |
||
46 | } |
||
47 | |||
48 | |||
49 | expression(con, val) int *con, *val; |
||
50 | { |
||
51 | int i; |
||
52 | int is[7]; |
||
53 | |||
54 | null_is (is); |
||
55 | |||
56 | if(level1(is)) fetch(is); |
||
57 | *con = is[TC]; |
||
58 | *val = is[CV]; |
||
59 | } |
||
60 | |||
61 | test(label, parens) int label, parens; { |
||
62 | int is[7]; |
||
63 | int *before, *start; |
||
64 | |||
65 | null_is (is); |
||
66 | |||
67 | if(parens) need("("); |
||
68 | while(1) { |
||
69 | setstage(&before, &start); |
||
70 | if(level1(is)) fetch(is); |
||
71 | if(match(",")) clearstage(before, start); |
||
72 | else break; |
||
73 | } |
||
74 | if(parens) need(")"); |
||
75 | if(is[TC]) { /* constant expression */ |
||
76 | clearstage(before, 0); |
||
77 | if(is[CV]) return; |
||
78 | gen(JMPm, label); |
||
79 | return; |
||
80 | } |
||
81 | if(is[SA]) { /* stage address of "oper 0" code */ |
||
82 | switch(is[OP]) { /* operator code */ |
||
83 | case EQ12: |
||
84 | case LE12u: zerojump(EQ10f, label, is); break; |
||
85 | case NE12: |
||
86 | case GT12u: zerojump(NE10f, label, is); break; |
||
87 | case GT12: zerojump(GT10f, label, is); break; |
||
88 | case GE12: zerojump(GE10f, label, is); break; |
||
89 | case GE12u: clearstage(is[SA], 0); break; |
||
90 | case LT12: zerojump(LT10f, label, is); break; |
||
91 | case LT12u: zerojump(JMPm, label, is); break; |
||
92 | case LE12: zerojump(LE10f, label, is); break; |
||
93 | default: gen(NE10f, label); break; |
||
94 | } |
||
95 | } |
||
96 | else gen(NE10f, label); |
||
97 | clearstage(before, start); |
||
98 | } |
||
99 | |||
100 | /* |
||
101 | ** test primary register against zero and jump if false |
||
102 | */ |
||
103 | zerojump(oper, label, is) int oper, label, is[]; { |
||
104 | clearstage(is[SA], 0); /* purge conventional code */ |
||
105 | gen(oper, label); |
||
106 | } |
||
107 | |||
108 | /***************** precedence levels ******************/ |
||
109 | #ifdef _MSC_VER |
||
110 | level2(); |
||
111 | level3(); |
||
112 | level4(); |
||
113 | level5(); |
||
114 | level6(); |
||
115 | level7(); |
||
116 | level8(); |
||
117 | level9(); |
||
118 | level10(); |
||
119 | level11(); |
||
120 | level12(); |
||
121 | level13(); |
||
122 | #endif |
||
123 | |||
124 | level1(is) int is[]; { |
||
125 | int k, is2[7], is3[2], oper, oper2; |
||
126 | |||
127 | null_is (is2); |
||
128 | null_is (is3); |
||
129 | |||
130 | k = down1(level2, is); |
||
131 | if(is[TC]) |
||
132 | { |
||
133 | #ifdef INT32 |
||
134 | gen(GETd1n, is[CV]); |
||
135 | #else |
||
136 | gen(GETw1n, is[CV]); |
||
137 | #endif |
||
138 | } |
||
139 | if(match("|=")) {oper = oper2 = OR12;} |
||
140 | else if(match("^=")) {oper = oper2 = XOR12;} |
||
141 | else if(match("&=")) {oper = oper2 = AND12;} |
||
142 | else if(match("+=")) {oper = oper2 = ADD12;} |
||
143 | else if(match("-=")) {oper = oper2 = SUB12;} |
||
144 | else if(match("*=")) {oper = MUL12; oper2 = MUL12u;} |
||
145 | else if(match("/=")) {oper = DIV12; oper2 = DIV12u;} |
||
146 | else if(match("%=")) {oper = MOD12; oper2 = MOD12u;} |
||
147 | else if(match(">>=")) {oper = oper2 = ASR12;} |
||
148 | else if(match("<<=")) {oper = oper2 = ASL12;} |
||
149 | else if(match("=")) {oper = oper2 = 0;} |
||
150 | else return k; |
||
151 | /* have an assignment operator */ |
||
152 | if(k == 0) { |
||
153 | needlval(); |
||
154 | return 0; |
||
155 | } |
||
156 | is3[ST] = is[ST]; |
||
157 | is3[TI] = is[TI]; |
||
158 | if(is[TI]) { /* indirect target */ |
||
159 | if(oper) { /* ?= */ |
||
160 | gen(PUSH1, 0); /* save address */ |
||
161 | fetch(is); /* fetch left side */ |
||
162 | } |
||
163 | down2(oper, oper2, level1, is, is2); /* parse right side */ |
||
164 | if(oper) gen(POP2, 0); /* retrieve address */ |
||
165 | } |
||
166 | else { /* direct target */ |
||
167 | if(oper) { /* ?= */ |
||
168 | fetch(is); /* fetch left side */ |
||
169 | down2(oper, oper2, level1, is, is2); /* parse right side */ |
||
170 | } |
||
171 | else { /* = */ |
||
172 | if(level1(is2)) fetch(is2); /* parse right side */ |
||
173 | } |
||
174 | } |
||
175 | store(is3); /* store result */ |
||
176 | return 0; |
||
177 | } |
||
178 | |||
179 | level2(is1) int is1[]; { |
||
180 | int is2[7], is3[7], k, flab, endlab, *before, *after; |
||
181 | |||
182 | null_is (is2); |
||
183 | null_is (is3); |
||
184 | |||
185 | k = down1(level3, is1); /* expression 1 */ |
||
186 | if(match("?") == 0) return k; |
||
187 | dropout(k, NE10f, flab = getlabel(), is1); |
||
188 | if(down1(level2, is2)) fetch(is2); /* expression 2 */ |
||
189 | else if(is2[TC]) |
||
190 | { |
||
191 | #ifdef INT32 |
||
192 | gen(GETd1n, is2[CV]); |
||
193 | #else |
||
194 | gen(GETw1n, is2[CV]); |
||
195 | #endif |
||
196 | } |
||
197 | need(":"); |
||
198 | gen(JMPm, endlab = getlabel()); |
||
199 | gen(LABm, flab); |
||
200 | if(down1(level2, is3)) fetch(is3); /* expression 3 */ |
||
201 | else if(is3[TC]) |
||
202 | { |
||
203 | #ifdef INT32 |
||
204 | gen(GETd1n, is3[CV]); |
||
205 | #else |
||
206 | gen(GETw1n, is3[CV]); |
||
207 | #endif |
||
208 | } |
||
209 | gen(LABm, endlab); |
||
210 | |||
211 | is1[TC] = is1[CV] = 0; |
||
212 | if(is2[TC] && is3[TC]) { /* expr1 ? const2 : const3 */ |
||
213 | is1[TA] = is1[TI] = is1[SA] = 0; |
||
214 | } |
||
215 | else if(is3[TC]) { /* expr1 ? var2 : const3 */ |
||
216 | is1[TA] = is2[TA]; |
||
217 | is1[TI] = is2[TI]; |
||
218 | is1[SA] = is2[SA]; |
||
219 | } |
||
220 | else if((is2[TC]) /* expr1 ? const2 : var3 */ |
||
221 | || (is2[TA] == is3[TA])) { /* expr1 ? same2 : same3 */ |
||
222 | is1[TA] = is3[TA]; |
||
223 | is1[TI] = is3[TI]; |
||
224 | is1[SA] = is3[SA]; |
||
225 | } |
||
226 | else error("mismatched expressions"); |
||
227 | return 0; |
||
228 | } |
||
229 | |||
230 | level3 (is) int is[]; {return skim("||", EQ10f, 1, 0, level4, is);} |
||
231 | level4 (is) int is[]; {return skim("&&", NE10f, 0, 1, level5, is);} |
||
232 | level5 (is) int is[]; {return down("|", 0, level6, is);} |
||
233 | level6 (is) int is[]; {return down("^", 1, level7, is);} |
||
234 | level7 (is) int is[]; {return down("&", 2, level8, is);} |
||
235 | level8 (is) int is[]; {return down("== !=", 3, level9, is);} |
||
236 | level9 (is) int is[]; {return down("<= >= < >", 5, level10, is);} |
||
237 | level10(is) int is[]; {return down(">> <<", 9, level11, is);} |
||
238 | level11(is) int is[]; {return down("+ -", 11, level12, is);} |
||
239 | level12(is) int is[]; {return down("* / %", 13, level13, is);} |
||
240 | |||
241 | level13(is) int is[]; { |
||
242 | int k; |
||
243 | char *ptr; |
||
244 | if(match("++")) { /* ++lval */ |
||
245 | if(level13(is) == 0) { |
||
246 | needlval(); |
||
247 | return 0; |
||
248 | } |
||
249 | step(rINC1, is, 0); |
||
250 | return 0; |
||
251 | } |
||
252 | else if(match("--")) { /* --lval */ |
||
253 | if(level13(is) == 0) { |
||
254 | needlval(); |
||
255 | return 0; |
||
256 | } |
||
257 | step(rDEC1, is, 0); |
||
258 | return 0; |
||
259 | } |
||
260 | else if(match("~")) { /* ~ */ |
||
261 | if(level13(is)) fetch(is); |
||
262 | gen(COM1, 0); |
||
263 | is[CV] = ~ is[CV]; |
||
264 | return (is[SA] = 0); |
||
265 | } |
||
266 | else if(match("!")) { /* ! */ |
||
267 | if(level13(is)) fetch(is); |
||
268 | gen(LNEG1, 0); |
||
269 | is[CV] = ! is[CV]; |
||
270 | return (is[SA] = 0); |
||
271 | } |
||
272 | else if(match("-")) { /* unary - */ |
||
273 | if(level13(is)) fetch(is); |
||
274 | gen(ANEG1, 0); |
||
275 | is[CV] = -is[CV]; |
||
276 | return (is[SA] = 0); |
||
277 | } |
||
278 | else if(match("*")) { /* unary * */ |
||
279 | if(level13(is)) fetch(is); |
||
280 | if(ptr = is[ST]) is[TI] = ptr[TYPE]; |
||
281 | else is[TI] = INT; |
||
282 | is[SA] = /* no (op 0) stage address */ |
||
283 | is[TA] = /* not an address */ |
||
284 | is[TC] = 0; /* not a constant */ |
||
285 | is[CV] = 1; /* omit fetch() on func call */ |
||
286 | return 1; |
||
287 | } |
||
288 | else if(amatch("sizeof", 6)) { /* sizeof() */ |
||
289 | int sz, p; char *ptr, sname[NAMESIZE]; |
||
290 | if(match("(")) p = 1; |
||
291 | else p = 0; |
||
292 | sz = 0; |
||
293 | if (amatch("unsigned", 8)) sz = INTSIZE; |
||
294 | if (amatch("int", 3)) sz = INTSIZE; |
||
295 | else if(amatch("char", 4)) sz = 1; |
||
296 | if(sz) {if(match("*")) sz = PTRSIZE;} |
||
297 | else if(symname(sname) |
||
298 | && ((ptr = findloc(sname)) || |
||
299 | (ptr = findglb(sname))) |
||
300 | && ptr[IDENT] != FUNCTION |
||
301 | && ptr[IDENT] != LABEL) sz = getint(ptr+SIZE, INTSIZE); |
||
302 | else if(sz == 0) error("must be object or type"); |
||
303 | if(p) need(")"); |
||
304 | is[TC] = INT; |
||
305 | is[CV] = sz; |
||
306 | is[TA] = is[TI] = is[ST] = 0; |
||
307 | return 0; |
||
308 | } |
||
309 | else if(match("&")) { /* unary & */ |
||
310 | if(level13(is) == 0) { |
||
311 | error("illegal address"); |
||
312 | return 0; |
||
313 | } |
||
314 | ptr = is[ST]; |
||
315 | is[TA] = ptr[TYPE]; |
||
316 | if(is[TI]) return 0; |
||
317 | gen(POINT1m, ptr); |
||
318 | is[TI] = ptr[TYPE]; |
||
319 | return 0; |
||
320 | } |
||
321 | else { |
||
322 | k = level14(is); |
||
323 | if(match("++")) { /* lval++ */ |
||
324 | if(k == 0) { |
||
325 | needlval(); |
||
326 | return 0; |
||
327 | } |
||
328 | step(rINC1, is, rDEC1); |
||
329 | return 0; |
||
330 | } |
||
331 | else if(match("--")) { /* lval-- */ |
||
332 | if(k == 0) { |
||
333 | needlval(); |
||
334 | return 0; |
||
335 | } |
||
336 | step(rDEC1, is, rINC1); |
||
337 | return 0; |
||
338 | } |
||
339 | else return k; |
||
340 | } |
||
341 | } |
||
342 | |||
343 | level14(is) int *is; { |
||
344 | int k, consta, val; |
||
345 | char *ptr, *before, *start; |
||
346 | k = primary(is); |
||
347 | ptr = is[ST]; |
||
348 | blanks(); |
||
349 | if(ch == '[' || ch == '(') { |
||
350 | int is2[7]; /* allocate only if needed */ |
||
351 | |||
352 | null_is (is2); |
||
353 | |||
354 | while(1) { |
||
355 | if(match("[")) { /* [subscript] */ |
||
356 | if(ptr == 0) { |
||
357 | error("can't subscript"); |
||
358 | skip(); |
||
359 | need("]"); |
||
360 | return 0; |
||
361 | } |
||
362 | if(is[TA]) {if(k) fetch(is);} |
||
363 | else {error("can't subscript"); k = 0;} |
||
364 | setstage(&before, &start); |
||
365 | is2[TC] = 0; |
||
366 | down2(0, 0, level1, is2, is2); |
||
367 | need("]"); |
||
368 | if(is2[TC]) { |
||
369 | clearstage(before, 0); |
||
370 | if(is2[CV]) |
||
371 | { /* only add if non-zero */ |
||
372 | if(ptr[TYPE] >> 2 == BPD) |
||
373 | { |
||
374 | #ifdef INT32 |
||
375 | gen(GETd2n, is2[CV] << LBPD); |
||
376 | #else |
||
377 | gen(GETw2n, is2[CV] << LBPD); |
||
378 | #endif |
||
379 | } |
||
380 | else if(ptr[TYPE] >> 2 == BPW) |
||
381 | { |
||
382 | #ifdef INT32 |
||
383 | gen(GETd2n, is2[CV] << LBPW); |
||
384 | #else |
||
385 | gen(GETw2n, is2[CV] << LBPW); |
||
386 | #endif |
||
387 | } |
||
388 | else |
||
389 | { |
||
390 | #ifdef INT32 |
||
391 | gen(GETd2n, is2[CV]); |
||
392 | #else |
||
393 | gen(GETw2n, is2[CV]); |
||
394 | #endif |
||
395 | } |
||
396 | gen(ADD12, 0); |
||
397 | } |
||
398 | } |
||
399 | else |
||
400 | { |
||
401 | if(ptr[TYPE] >> 2 == BPD) |
||
402 | { |
||
403 | gen(DBL1, 0); |
||
404 | gen(DBL1, 0); |
||
405 | } |
||
406 | else if(ptr[TYPE] >> 2 == BPW) |
||
407 | { |
||
408 | gen(DBL1, 0); |
||
409 | } |
||
410 | gen(ADD12, 0); |
||
411 | } |
||
412 | is[TA] = 0; |
||
413 | is[TI] = ptr[TYPE]; |
||
414 | k = 1; |
||
415 | } |
||
416 | else if(match("(")) { /* function(...) */ |
||
417 | if(ptr == 0) callfunc(0); |
||
418 | else if(ptr[IDENT] != FUNCTION) { |
||
419 | if(k && !is[CV]) fetch(is); |
||
420 | callfunc(0); |
||
421 | } |
||
422 | else callfunc(ptr); |
||
423 | k = is[ST] = is[TC] = is[CV] = 0; |
||
424 | } |
||
425 | else return k; |
||
426 | } |
||
427 | } |
||
428 | if(ptr && ptr[IDENT] == FUNCTION) { |
||
429 | gen(POINT1m, ptr); |
||
430 | is[ST] = 0; |
||
431 | return 0; |
||
432 | } |
||
433 | return k; |
||
434 | } |
||
435 | |||
436 | primary(is) int *is; { |
||
437 | char *ptr, sname[NAMESIZE]; |
||
438 | int k; |
||
439 | if(match("(")) { /* (subexpression) */ |
||
440 | do k = level1(is); while(match(",")); |
||
441 | need(")"); |
||
442 | return k; |
||
443 | } |
||
444 | putint(0, is, 7 << LBPW); /* clear "is" array */ |
||
445 | if(symname(sname)) { /* is legal symbol */ |
||
446 | if(ptr = findloc(sname)) { /* is local */ |
||
447 | if(ptr[IDENT] == LABEL) { |
||
448 | experr(); |
||
449 | return 0; |
||
450 | } |
||
451 | gen(POINT1s, getint(ptr+OFFSET, INTSIZE)); |
||
452 | is[ST] = ptr; |
||
453 | is[TI] = ptr[TYPE]; |
||
454 | if(ptr[IDENT] == ARRAY) { |
||
455 | is[TA] = ptr[TYPE]; |
||
456 | return 0; |
||
457 | } |
||
458 | if(ptr[IDENT] == POINTER) { |
||
459 | is[TI] = UINT; |
||
460 | is[TA] = ptr[TYPE]; |
||
461 | } |
||
462 | return 1; |
||
463 | } |
||
464 | if(ptr = findglb(sname)) { /* is global */ |
||
465 | is[ST] = ptr; |
||
466 | if(ptr[IDENT] != FUNCTION) { |
||
467 | if(ptr[IDENT] == ARRAY) { |
||
468 | gen(POINT1m, ptr); |
||
469 | is[TI] = |
||
470 | is[TA] = ptr[TYPE]; |
||
471 | return 0; |
||
472 | } |
||
473 | if(ptr[IDENT] == POINTER) |
||
474 | is[TA] = ptr[TYPE]; |
||
475 | return 1; |
||
476 | } |
||
477 | } |
||
478 | else is[ST] = addsym(sname, FUNCTION, INT, 0, 0, &glbptr, AUTOEXT); |
||
479 | return 0; |
||
480 | } |
||
481 | if(constant(is) == 0) experr(); |
||
482 | return 0; |
||
483 | } |
||
484 | |||
485 | experr() { |
||
486 | error("invalid expression"); |
||
487 | #ifdef INT32 |
||
488 | gen(GETd1n, 0); |
||
489 | #else |
||
490 | gen(GETw1n, 0); |
||
491 | #endif |
||
492 | skip(); |
||
493 | } |
||
494 | |||
495 | /* attempt at right to left - do it later */ |
||
496 | #ifdef LATER |
||
497 | pushargs (ptr, nargs) |
||
498 | char *ptr; |
||
499 | int nargs; |
||
500 | { |
||
501 | if (streq(lptr, ")") != 0) |
||
502 | return; |
||
503 | |||
504 | if(endst()) |
||
505 | return; |
||
506 | |||
507 | if(ptr) |
||
508 | { |
||
509 | expression(&consta, &val); |
||
510 | gen(PUSH1, 0); |
||
511 | } |
||
512 | else |
||
513 | { |
||
514 | gen(PUSH1, 0); |
||
515 | expression(&consta, &val); |
||
516 | gen(SWAP1s, 0); /* don't push addr */ |
||
517 | } |
||
518 | nargs = nargs + INTSIZE; /* count args*BPW */ |
||
519 | |||
520 | if(match(",") == 0) break; |
||
521 | |||
522 | } |
||
523 | #endif |
||
524 | |||
525 | callfunc(ptr) |
||
526 | char *ptr; /* symbol table entry or 0 */ |
||
527 | { |
||
528 | int nargs, consta, val; |
||
529 | |||
530 | nargs = 0; |
||
531 | blanks(); /* already saw open paren */ |
||
532 | |||
533 | while(streq(lptr, ")") == 0) |
||
534 | { |
||
535 | if(endst()) |
||
536 | break; |
||
537 | if(ptr) |
||
538 | { |
||
539 | expression(&consta, &val); |
||
540 | gen(PUSH1, 0); |
||
541 | } |
||
542 | else |
||
543 | { |
||
544 | gen(PUSH1, 0); |
||
545 | expression(&consta, &val); |
||
546 | gen(SWAP1s, 0); /* don't push addr */ |
||
547 | } |
||
548 | nargs = nargs + INTSIZE; /* count args*BPW */ |
||
549 | |||
550 | if(match(",") == 0) break; |
||
551 | } |
||
552 | need(")"); |
||
553 | if(ptr && (streq(ptr + NAME, "CCARGC") == 0)) /* accessing ... like va_args */ |
||
554 | #ifdef INT32 |
||
555 | gen(ARGCNTn, nargs >> LBPD); /* to get start of frame */ |
||
556 | #else |
||
557 | gen(ARGCNTn, nargs >> LBPW); /* to get start of frame */ |
||
558 | #endif |
||
559 | |||
560 | if(ptr) |
||
561 | gen(CALLm, ptr); |
||
562 | else |
||
563 | gen(CALL1, 0); |
||
564 | gen(ADDSP, csp + nargs); |
||
565 | } |
||
566 | |||
567 | /* |
||
568 | ** true if is2's operand should be doubled |
||
569 | */ |
||
570 | fdouble (oper, is1, is2) |
||
571 | int oper, is1[], is2[]; |
||
572 | { |
||
573 | ////////////////////////////////////////////////////// |
||
574 | // This is a 'magic' function, its usage and function |
||
575 | // are not so obvious |
||
576 | // |
||
577 | // Purpose: when indexing an address we must know |
||
578 | // what we are pointing at so that the indexsize is |
||
579 | // proper, e,g, |
||
580 | // charptr++, should multiply index by a 1 |
||
581 | // shortptr++, should multiply index by a 2 |
||
582 | // intptr++, should multiply index by a 4 |
||
583 | // |
||
584 | // Algorithm: |
||
585 | // IF |
||
586 | // operation is ADD12 or SUB12 |
||
587 | // AND |
||
588 | // is1 is an address (pointer, array or via & operator |
||
589 | // AND |
||
590 | // is2 is NOT an address (pointer, array or via & operator |
||
591 | // THEN |
||
592 | // return the multiplication factor based on s1 (or true) |
||
593 | // ELSE |
||
594 | // return 0 (or false) |
||
595 | // |
||
596 | // Usage: The return value is used as a 'boolean' |
||
597 | // for nonconstant values, indicating that runtime code |
||
598 | // is necessary to do the necessary multiplication |
||
599 | // For contant value the return value is used to do a compile-time |
||
600 | // multiplication (shift actually) |
||
601 | // |
||
602 | |||
603 | if ((oper == ADD12 || oper == SUB12) |
||
604 | && (is2[TA] == 0)) |
||
605 | { |
||
606 | switch (is1[TA]>>2) |
||
607 | { |
||
608 | default: |
||
609 | case 1: // char |
||
610 | return (0); |
||
611 | case 2: // short |
||
612 | return (1); |
||
613 | case 4: // int |
||
614 | return (2); |
||
615 | } |
||
616 | } |
||
617 | |||
618 | return (0); |
||
619 | |||
620 | |||
621 | |||
622 | /* |
||
623 | - original code - |
||
624 | if((oper != ADD12 && oper != SUB12) |
||
625 | || (is1[TA] >> 2 != BPW) |
||
626 | || (is2[TA])) |
||
627 | |||
628 | return 0; |
||
629 | |||
630 | |||
631 | return 1; |
||
632 | */ |
||
633 | } |
||
634 | |||
635 | |||
636 | step (oper, is, oper2) int oper, is[], oper2; { |
||
637 | fetch(is); |
||
638 | gen(oper, is[TA] ? (is[TA] >> 2) : 1); |
||
639 | store(is); |
||
640 | if(oper2) gen(oper2, is[TA] ? (is[TA] >> 2) : 1); |
||
641 | } |
||
642 | |||
643 | store(is) |
||
644 | int is[]; |
||
645 | { |
||
646 | char *ptr; |
||
647 | |||
648 | if(is[TI]) |
||
649 | { /* putstk */ |
||
650 | if(is[TI] >> 2 == 1) |
||
651 | { |
||
652 | gen(PUTbp1, 0); |
||
653 | } |
||
654 | else if(is[TI] >> 2 == 2) |
||
655 | { |
||
656 | gen(PUTwp1, 0); |
||
657 | } |
||
658 | else |
||
659 | { |
||
660 | gen(PUTdp1, 0); |
||
661 | } |
||
662 | } |
||
663 | else |
||
664 | { /* putmem */ |
||
665 | ptr = is[ST]; |
||
666 | if(ptr[IDENT] == POINTER) |
||
667 | { |
||
668 | #ifdef INT32 /* int and ptr-size are ALWAYS the same */ |
||
669 | gen(PUTdm1, ptr); |
||
670 | #else |
||
671 | gen(PUTwm1, ptr); |
||
672 | #endif |
||
673 | } |
||
674 | else if (ptr[TYPE] >> 2 == 1) |
||
675 | { |
||
676 | gen(PUTbm1, ptr); |
||
677 | } |
||
678 | else if (ptr[TYPE] >> 2 == BPW) |
||
679 | { |
||
680 | gen(PUTwm1, ptr); |
||
681 | } |
||
682 | else |
||
683 | { |
||
684 | gen(PUTdm1, ptr); |
||
685 | } |
||
686 | } |
||
687 | } |
||
688 | |||
689 | fetch(is) |
||
690 | int is[]; |
||
691 | { |
||
692 | char *ptr; |
||
693 | |||
694 | ptr = is[ST]; |
||
695 | if(is[TI]) /* indirect */ |
||
696 | { |
||
697 | if(is[TI] >> 2 == BPD) /* pointer to DWORD */ |
||
698 | { |
||
699 | gen(GETd1p, 0); |
||
700 | } |
||
701 | else if(is[TI] >> 2 == BPW) /* pointer to WORD */ |
||
702 | { |
||
703 | /* if INT32 must make distinction between signed/unsigned <-- */ |
||
704 | gen(GETw1p, 0); |
||
705 | } |
||
706 | else |
||
707 | { |
||
708 | if(ptr[TYPE] & UNSIGNED) |
||
709 | gen(GETb1pu, 0); |
||
710 | else |
||
711 | gen(GETb1p, 0); |
||
712 | } |
||
713 | } |
||
714 | else |
||
715 | { /* direct */ |
||
716 | |||
717 | if(ptr[IDENT] == POINTER) |
||
718 | { |
||
719 | #ifdef INT32 |
||
720 | gen(GETd1m, ptr); |
||
721 | #else |
||
722 | gen(GETw1m, ptr); |
||
723 | #endif |
||
724 | } |
||
725 | else if (ptr[TYPE] >> 2 == BPD) |
||
726 | { |
||
727 | gen(GETd1m, ptr); |
||
728 | } |
||
729 | else if (ptr[TYPE] >> 2 == BPW) |
||
730 | { |
||
731 | gen(GETw1m, ptr); |
||
732 | } |
||
733 | else |
||
734 | { |
||
735 | if(ptr[TYPE] & UNSIGNED) |
||
736 | gen(GETb1mu, ptr); |
||
737 | else |
||
738 | gen(GETb1m, ptr); |
||
739 | } |
||
740 | } |
||
741 | } |
||
742 | |||
743 | constant(is) |
||
744 | int is[]; |
||
745 | { |
||
746 | int offset; |
||
747 | |||
748 | if (is[TC] = number(is + CV)) |
||
749 | { |
||
750 | #ifdef INT32 |
||
751 | gen(GETd1n, is[CV]); |
||
752 | #else |
||
753 | gen(GETw1n, is[CV]); |
||
754 | #endif |
||
755 | } |
||
756 | else if(is[TC] = chrcon(is + CV)) |
||
757 | { |
||
758 | #ifdef INT32 |
||
759 | gen(GETd1n, is[CV]); |
||
760 | #else |
||
761 | gen(GETw1n, is[CV]); |
||
762 | #endif |
||
763 | } |
||
764 | else if(string(&offset)) |
||
765 | { |
||
766 | gen(POINT1l, offset); |
||
767 | } |
||
768 | else |
||
769 | { |
||
770 | return 0; |
||
771 | } |
||
772 | return 1; |
||
773 | } |
||
774 | |||
775 | number(value) int *value; { |
||
776 | int k, minus; |
||
777 | k = minus = 0; |
||
778 | while(1) { |
||
779 | if(match("+")) ; |
||
780 | else if(match("-")) minus = 1; |
||
781 | else break; |
||
782 | } |
||
783 | if(isdigit(ch) == 0) return 0; |
||
784 | if(ch == '0') { |
||
785 | while(ch == '0') inbyte(); |
||
786 | if(toupper(ch) == 'X') { |
||
787 | inbyte(); |
||
788 | while(isxdigit(ch)) { |
||
789 | if(isdigit(ch)) |
||
790 | k = k*16 + (inbyte() - '0'); |
||
791 | else k = k*16 + 10 + (toupper(inbyte()) - 'A'); |
||
792 | } |
||
793 | } |
||
794 | else while (ch >= '0' && ch <= '7') |
||
795 | k = k*8 + (inbyte() - '0'); |
||
796 | } |
||
797 | else while (isdigit(ch)) k = k*10 + (inbyte() - '0'); |
||
798 | if(minus) { |
||
799 | *value = -k; |
||
800 | return (INT); |
||
801 | } |
||
802 | if((*value = k) < 0) return (UINT); |
||
803 | else return (INT); |
||
804 | } |
||
805 | |||
806 | chrcon(value) |
||
807 | int *value; |
||
808 | { |
||
809 | int k; |
||
810 | |||
811 | k = 0; |
||
812 | if(match("'") == 0) |
||
813 | return 0; |
||
814 | while(ch != '\'') |
||
815 | k = (k << 8) + (litchar() & 255); |
||
816 | gch(); |
||
817 | *value = k; |
||
818 | return (INT); |
||
819 | } |
||
820 | |||
821 | string(offset) int *offset; { |
||
822 | char c; |
||
823 | if(match(quote) == 0) return 0; |
||
824 | *offset = litptr; |
||
825 | while (ch != '"') { |
||
826 | if(ch == 0) break; |
||
827 | stowlit(litchar(), 1); |
||
828 | } |
||
829 | gch(); |
||
830 | litq[litptr++] = 0; |
||
831 | return 1; |
||
832 | } |
||
833 | |||
834 | stowlit(value, size) int value, size; { |
||
835 | if((litptr+size) >= LITMAX) { |
||
836 | error("literal queue overflow"); |
||
837 | exit(ERRCODE); |
||
838 | } |
||
839 | putint(value, litq+litptr, size); |
||
840 | litptr += size; |
||
841 | } |
||
842 | |||
843 | litchar() { |
||
844 | int i, oct; |
||
845 | if(ch != '\\' || nch == 0) return gch(); |
||
846 | gch(); |
||
847 | switch(ch) { |
||
848 | case 'n': gch(); return NEWLINE; |
||
849 | case 't': gch(); return 9; /* HT */ |
||
850 | case 'b': gch(); return 8; /* BS */ |
||
851 | case 'f': gch(); return 12; /* FF */ |
||
852 | } |
||
853 | i = 3; |
||
854 | oct = 0; |
||
855 | while((i--) > 0 && ch >= '0' && ch <= '7') |
||
856 | oct = (oct << 3) + gch() - '0'; |
||
857 | if(i == 2) return gch(); |
||
858 | else return oct; |
||
859 | } |
||
860 | |||
861 | /***************** pipeline functions ******************/ |
||
862 | |||
863 | /* |
||
864 | ** skim over terms adjoining || and && operators |
||
865 | */ |
||
866 | skim(opstr, tcode, dropval, endval, level, is) |
||
867 | char *opstr; |
||
868 | int tcode, dropval, endval, (*level)(), is[]; { |
||
869 | int k, droplab, endlab; |
||
870 | droplab = 0; |
||
871 | while(1) { |
||
872 | k = down1(level, is); |
||
873 | if(nextop(opstr)) { |
||
874 | bump(opsize); |
||
875 | if(droplab == 0) droplab = getlabel(); |
||
876 | dropout(k, tcode, droplab, is); |
||
877 | } |
||
878 | else if(droplab) { |
||
879 | dropout(k, tcode, droplab, is); |
||
880 | #ifdef INT32 |
||
881 | gen(GETd1n, endval); |
||
882 | #else |
||
883 | gen(GETw1n, endval); |
||
884 | #endif |
||
885 | gen(JMPm, endlab = getlabel()); |
||
886 | gen(LABm, droplab); |
||
887 | #ifdef INT32 |
||
888 | gen(GETd1n, dropval); |
||
889 | #else |
||
890 | gen(GETw1n, dropval); |
||
891 | #endif |
||
892 | gen(LABm, endlab); |
||
893 | is[TI] = is[TA] = is[TC] = is[CV] = is[SA] = 0; |
||
894 | return 0; |
||
895 | } |
||
896 | else return k; |
||
897 | } |
||
898 | } |
||
899 | |||
900 | /* |
||
901 | ** test for early dropout from || or && sequences |
||
902 | */ |
||
903 | dropout(k, tcode, exit1, is) |
||
904 | int k, tcode, exit1, is[]; { |
||
905 | if(k) fetch(is); |
||
906 | else if(is[TC]) |
||
907 | { |
||
908 | #ifdef INT32 |
||
909 | gen(GETd1n, is[CV]); |
||
910 | #else |
||
911 | gen(GETw1n, is[CV]); |
||
912 | #endif |
||
913 | } |
||
914 | gen(tcode, exit1); /* jumps on false */ |
||
915 | } |
||
916 | |||
917 | /* |
||
918 | ** drop to a lower level |
||
919 | */ |
||
920 | down(opstr, opoff, level, is) |
||
921 | char *opstr; int opoff, (*level)(), is[]; { |
||
922 | int k; |
||
923 | k = down1(level, is); |
||
924 | if(nextop(opstr) == 0) return k; |
||
925 | if(k) fetch(is); |
||
926 | while(1) { |
||
927 | if(nextop(opstr)) { |
||
928 | int is2[7]; /* allocate only if needed */ |
||
929 | |||
930 | null_is (is2); |
||
931 | |||
932 | bump(opsize); |
||
933 | opindex += opoff; |
||
934 | down2(op[opindex], op2[opindex], level, is, is2); |
||
935 | } |
||
936 | else return 0; |
||
937 | } |
||
938 | } |
||
939 | |||
940 | /* |
||
941 | ** unary drop to a lower level |
||
942 | */ |
||
943 | down1(level, is) int (*level)(), is[]; { |
||
944 | int k, *before, *start; |
||
945 | setstage(&before, &start); |
||
946 | k = (*level)(is); |
||
947 | if(is[TC]) clearstage(before, 0); /* load constant later */ |
||
948 | return k; |
||
949 | } |
||
950 | |||
951 | /* |
||
952 | ** binary drop to a lower level |
||
953 | */ |
||
954 | down2(oper, oper2, level, is, is2) |
||
955 | int oper, oper2, (*level)(), is[], is2[]; { |
||
956 | int *before, *start; |
||
957 | char *ptr; |
||
958 | int value; |
||
959 | setstage(&before, &start); |
||
960 | is[SA] = 0; /* not "... op 0" syntax */ |
||
961 | if(is[TC]) { /* consant op unknown */ |
||
962 | if(down1(level, is2)) fetch(is2); |
||
963 | if(is[CV] == 0) is[SA] = snext; |
||
964 | gen(GETw2n, is[CV] << fdouble(oper, is2, is)); |
||
965 | } |
||
966 | else { /* variable op unknown */ |
||
967 | gen(PUSH1, 0); /* at start in the buffer */ |
||
968 | if(down1(level, is2)) fetch(is2); |
||
969 | if(is2[TC]) { /* variable op constant */ |
||
970 | if(is2[CV] == 0) is[SA] = start; |
||
971 | #ifdef INT32 |
||
972 | csp += BPD; /* adjust stack and */ |
||
973 | #else |
||
974 | csp += BPW; /* adjust stack and */ |
||
975 | #endif |
||
976 | clearstage(before, 0); /* discard the PUSH */ |
||
977 | if(oper == ADD12) { /* commutative */ |
||
978 | #ifdef INT32 |
||
979 | gen(GETd2n, is2[CV] << fdouble(oper, is, is2)); |
||
980 | #else |
||
981 | gen(GETw2n, is2[CV] << fdouble(oper, is, is2)); |
||
982 | #endif |
||
983 | } |
||
984 | else { /* non-commutative */ |
||
985 | gen(MOVE21, 0); |
||
986 | #ifdef INT32 |
||
987 | gen(GETd1n, is2[CV] << fdouble(oper, is, is2)); |
||
988 | #else |
||
989 | gen(GETw1n, is2[CV] << fdouble(oper, is, is2)); |
||
990 | #endif |
||
991 | } |
||
992 | } |
||
993 | else { /* variable op variable */ |
||
994 | gen(POP2, 0); |
||
995 | if(value = fdouble(oper, is, is2)) |
||
996 | { |
||
997 | gen(DBL1, 0); // index size 2 |
||
998 | if (value > 1) |
||
999 | gen(DBL1, 0); // .. or even 4 |
||
1000 | } |
||
1001 | if(value = fdouble(oper, is2, is)) |
||
1002 | { |
||
1003 | gen(DBL2, 0); |
||
1004 | if (value > 1) |
||
1005 | gen(DBL2, 0); |
||
1006 | } |
||
1007 | } |
||
1008 | } |
||
1009 | if(oper) { |
||
1010 | if(nosign(is) || nosign(is2)) oper = oper2; |
||
1011 | if(is[TC] = is[TC] & is2[TC]) { /* constant result */ |
||
1012 | is[CV] = calc(is[CV], oper, is2[CV]); |
||
1013 | clearstage(before, 0); |
||
1014 | if(is2[TC] == UINT) is[TC] = UINT; |
||
1015 | } |
||
1016 | else { /* variable result */ |
||
1017 | gen(oper, 0); |
||
1018 | if(oper == SUB12 |
||
1019 | && is [TA] >> 2 == BPW |
||
1020 | && is2[TA] >> 2 == BPW) { /* difference of two word addresses */ |
||
1021 | gen(SWAP12, 0); |
||
1022 | gen(GETw1n, 1); |
||
1023 | gen(ASR12, 0); /* div by 2 */ |
||
1024 | } |
||
1025 | is[OP] = oper; /* identify the operator */ |
||
1026 | } |
||
1027 | if(oper == SUB12 || oper == ADD12) { |
||
1028 | if(is[TA] && is2[TA]) /* addr +/- addr */ |
||
1029 | is[TA] = 0; |
||
1030 | else if(is2[TA]) { /* value +/- addr */ |
||
1031 | is[ST] = is2[ST]; |
||
1032 | is[TI] = is2[TI]; |
||
1033 | is[TA] = is2[TA]; |
||
1034 | } |
||
1035 | } |
||
1036 | if(is[ST] == 0 || ((ptr = is2[ST]) && (ptr[TYPE] & UNSIGNED))) |
||
1037 | is[ST] = is2[ST]; |
||
1038 | } |
||
1039 | } |
||
1040 | |||
1041 | /* |
||
1042 | ** unsigned operand? |
||
1043 | */ |
||
1044 | nosign(is) int is[]; { |
||
1045 | char *ptr; |
||
1046 | if(is[TA] |
||
1047 | || is[TC] == UINT |
||
1048 | || ((ptr = is[ST]) && (ptr[TYPE] & UNSIGNED)) |
||
1049 | ) return 1; |
||
1050 | return 0; |
||
1051 | } |
||
1052 | |||
1053 | /* |
||
1054 | ** calcualte signed constant result |
||
1055 | */ |
||
1056 | calc(left, oper, right) int left, oper, right; { |
||
1057 | switch(oper) { |
||
1058 | case ADD12: return (left + right); |
||
1059 | case SUB12: return (left - right); |
||
1060 | case MUL12: return (left * right); |
||
1061 | case DIV12: return (left / right); |
||
1062 | case MOD12: return (left % right); |
||
1063 | case EQ12: return (left == right); |
||
1064 | case NE12: return (left != right); |
||
1065 | case LE12: return (left <= right); |
||
1066 | case GE12: return (left >= right); |
||
1067 | case LT12: return (left < right); |
||
1068 | case GT12: return (left > right); |
||
1069 | case AND12: return (left & right); |
||
1070 | case OR12: return (left | right); |
||
1071 | case XOR12: return (left ^ right); |
||
1072 | case ASR12: return (left >> right); |
||
1073 | case ASL12: return (left << right); |
||
1074 | } |
||
1075 | return (calc2(left, oper, right)); |
||
1076 | } |
||
1077 | |||
1078 | /* |
||
1079 | ** calcualte unsigned constant result |
||
1080 | */ |
||
1081 | calc2(left, oper, right) unsigned left, right; int oper; { |
||
1082 | switch(oper) { |
||
1083 | case MUL12u: return (left * right); |
||
1084 | case DIV12u: return (left / right); |
||
1085 | case MOD12u: return (left % right); |
||
1086 | case LE12u: return (left <= right); |
||
1087 | case GE12u: return (left >= right); |
||
1088 | case LT12u: return (left < right); |
||
1089 | case GT12u: return (left > right); |
||
1090 | } |
||
1091 | return (0); |
||
1092 | }>=>><>>=>><>><>><>><>><>><>=>><>>=>-->><>><>><>><>><>",><",>>=>="))><="))>-->> |
||
1093 |