Mercurial > hg > CbC > old > device
annotate mc-codegen.c @ 458:0bc9f3273aa7
*** empty log message ***
author | kono |
---|---|
date | Wed, 01 Dec 2004 23:14:50 +0900 (2004-12-01) |
parents | b8f95294eb77 |
children | 2a49dfe59540 |
rev | line source |
---|---|
326 | 1 /* Micro-C Generic Code Generation Part */ |
61 | 2 /* $Id$ */ |
3 | |
327 | 4 #include <stdio.h> |
61 | 5 #include "mc.h" |
327 | 6 #include "mc-parse.h" |
61 | 7 #include "mc-codegen.h" |
8 #include "mc-code.h" | |
454 | 9 #include "mc-switch.h" |
453 | 10 #include "mc-inline.h" |
61 | 11 |
83 | 12 int use; /* generated value will be used */ |
327 | 13 char *init_src; |
14 int size_of_int; | |
15 int size_of_short; | |
16 int size_of_float; | |
17 int size_of_double; | |
18 int size_of_longlong; | |
19 int bit_of_byte; | |
20 int endian; | |
397 | 21 int disp_align; |
81 | 22 |
327 | 23 static void assign(int e1); |
440 | 24 #if ASM_CODE |
327 | 25 static void gen_asm(int asm0,int in,int out,int opt,int e); |
440 | 26 #endif |
327 | 27 static void compatible(int t1, int t2); |
28 static int contains(int e,int type); | |
29 static int contains_in_list(int e,int type); | |
30 static int contains_in_list_p(int e,int (*p)(int)); | |
31 static void iassop(int e1); | |
105 | 32 static int is_same_type(int e1,int e2); |
33 static void jump(int e1, int env); | |
34 static void machinop(int e1); | |
327 | 35 static int register_to_lvar(int e); |
36 static void remove0(int *parent,int e) ; | |
105 | 37 static void sassign(int e1); |
61 | 38 |
195 | 39 #if FLOAT_CODE |
40 | |
41 /* floating point */ | |
42 | |
43 static void dassop(int e1); | |
44 static void dmachinop(int e1,int d); | |
45 static void dassign(int e1); | |
46 | |
47 #endif | |
48 #if LONGLONG_CODE | |
49 static void lassop(int e1); | |
50 static void lmachinop(int e1); | |
51 static void lassign(int e1); | |
52 #endif | |
53 | |
329 | 54 #if BIT_FIELD_CODE |
331 | 55 static int bit_field_repl(int e1,int e2,int t); |
329 | 56 static int bit_field(int e1,int t); |
57 static int bassign(int e1,int e2,int t); | |
331 | 58 static int bassop(int e1,int e2,int op,int t,int post); |
329 | 59 #endif |
60 | |
327 | 61 extern void |
102 | 62 codegen_init() |
63 { | |
327 | 64 /* called only once */ |
102 | 65 code_init(); |
66 } | |
67 | |
327 | 68 extern void |
69 codegen_reinit() | |
70 { | |
71 /* called for each file */ | |
72 emit_reinit(); | |
73 } | |
74 | |
75 extern void | |
76 codegen_decl_init() | |
77 { | |
78 /* called before each declaration */ | |
79 emit_init(); | |
80 init_free_lvar_list(); | |
81 } | |
82 | |
83 extern void | |
137 | 84 arg_register(NMTBL *fnptr) |
85 { | |
86 code_arg_register(fnptr); | |
87 } | |
88 | |
327 | 89 extern int |
83 | 90 gexpr(int e1,int use0) |
61 | 91 { |
94 | 92 if (chk) return INT; |
61 | 93 gexpr_init(); |
83 | 94 use = use0; |
94 | 95 return g_expr0(e1); |
61 | 96 } |
97 | |
327 | 98 /* gexpr for value unused */ |
99 | |
100 extern int | |
83 | 101 g_expr_u(int e1) |
102 { | |
94 | 103 int t; |
83 | 104 int suse = use; use=0; |
94 | 105 t=g_expr0(e1); |
147 | 106 code_gexpr(e1); |
107 | |
83 | 108 use=suse; |
94 | 109 return t; |
83 | 110 } |
111 | |
327 | 112 /* gexpr for value used */ |
113 | |
114 extern int | |
61 | 115 g_expr(int e1) |
116 { | |
94 | 117 int t; |
83 | 118 int suse = use; use=1; |
94 | 119 t=g_expr0(e1); |
147 | 120 code_gexpr(e1); |
121 | |
83 | 122 use=suse; |
94 | 123 return t; |
83 | 124 } |
125 | |
327 | 126 /* gexpr for used flag untouched */ |
127 | |
128 extern int | |
83 | 129 g_expr0(int e1) |
130 { | |
453 | 131 int e2,e3,t,d,t1; |
132 NMTBL *n; | |
133 | |
455 | 134 if (inmode) { |
453 | 135 return (parse = list3(ST_COMP,parse,e1)); |
136 } | |
456 | 137 if (!control && !IS_STATEMENT(car(e1))) return VOID; |
453 | 138 |
139 for(;e1;e1=e2) { | |
147 | 140 code_gexpr(e1); |
141 | |
61 | 142 e2 = cadr(e1); |
143 switch (car(e1)){ | |
144 case GVAR: | |
221 | 145 code_gvar(e1,USE_CREG); |
94 | 146 return ADDRESS; |
61 | 147 case RGVAR: |
221 | 148 code_rgvar(e1,USE_CREG); |
94 | 149 return INT; |
61 | 150 case CRGVAR: |
221 | 151 code_crgvar(e1,USE_CREG,1,1); |
94 | 152 return CHAR; |
162 | 153 case CURGVAR: |
221 | 154 code_crgvar(e1,USE_CREG,0,1); |
165 | 155 return UCHAR; |
156 case SRGVAR: | |
221 | 157 code_crgvar(e1,USE_CREG,1,size_of_short); |
165 | 158 return CHAR; |
159 case SURGVAR: | |
221 | 160 code_crgvar(e1,USE_CREG,0,size_of_short); |
162 | 161 return UCHAR; |
61 | 162 case LVAR: |
221 | 163 code_lvar(e2,USE_CREG); |
94 | 164 return ADDRESS; |
61 | 165 case REGISTER: |
221 | 166 code_register(e2,USE_CREG); |
94 | 167 return INT; |
195 | 168 #if FLOAT_CODE |
94 | 169 case DREGISTER: |
221 | 170 code_dregister(e2,USE_CREG,1); |
94 | 171 return DOUBLE; |
137 | 172 case FREGISTER: |
221 | 173 code_dregister(e2,USE_CREG,0); |
137 | 174 return FLOAT; |
195 | 175 #endif |
219 | 176 #if LONGLONG_CODE |
177 case LREGISTER: | |
221 | 178 code_lregister(e2,USE_CREG); |
219 | 179 return LONGLONG; |
180 #endif | |
61 | 181 case RLVAR: |
221 | 182 code_rlvar(e2,USE_CREG); |
94 | 183 return INT; |
61 | 184 case CRLVAR: |
221 | 185 code_crlvar(e2,USE_CREG,1,1); |
94 | 186 return CHAR; |
162 | 187 case CURLVAR: |
221 | 188 code_crlvar(e2,USE_CREG,0,1); |
165 | 189 return UCHAR; |
190 case SRLVAR: | |
221 | 191 code_crlvar(e2,USE_CREG,1,size_of_short); |
165 | 192 return CHAR; |
193 case SURLVAR: | |
221 | 194 code_crlvar(e2,USE_CREG,0,size_of_short); |
162 | 195 return UCHAR; |
195 | 196 #if FLOAT_CODE |
81 | 197 case FRLVAR: |
221 | 198 code_drlvar(e2,0,USE_CREG); |
94 | 199 return FLOAT; |
81 | 200 case FRGVAR: |
221 | 201 code_drgvar(e1,0,USE_CREG); |
94 | 202 return FLOAT; |
81 | 203 case DRLVAR: |
221 | 204 code_drlvar(e2,1,USE_CREG); |
94 | 205 return DOUBLE; |
81 | 206 case DRGVAR: |
221 | 207 code_drgvar(e1,1,USE_CREG); |
94 | 208 return DOUBLE; |
195 | 209 #endif |
202 | 210 #if LONGLONG_CODE |
211 case LRLVAR: | |
221 | 212 code_lrlvar(e2,USE_CREG); |
202 | 213 return LONGLONG; |
214 case LRGVAR: | |
221 | 215 code_lrgvar(e1,USE_CREG); |
202 | 216 return LONGLONG; |
217 case LURLVAR: | |
221 | 218 code_lrlvar(e2,USE_CREG); |
202 | 219 return ULONGLONG; |
220 case LURGVAR: | |
221 | 221 code_lrgvar(e1,USE_CREG); |
202 | 222 return ULONGLONG; |
223 #endif | |
61 | 224 case FNAME: |
221 | 225 code_fname((NMTBL *)(e2),USE_CREG); |
94 | 226 return ADDRESS; |
363 | 227 case LABEL: |
228 code_label_value(e2,USE_CREG); | |
229 return ADDRESS; | |
61 | 230 case CONST: /* ���������ͤ�0�Ǥ����̤ʽ����Ϥ��ʤ� */ |
221 | 231 code_const(e2,USE_CREG); |
94 | 232 return INT; |
195 | 233 #if FLOAT_CODE |
81 | 234 case DCONST: |
221 | 235 code_dconst(e1,USE_CREG,1); |
94 | 236 return DOUBLE; |
133 | 237 case FCONST: |
221 | 238 code_dconst(e1,USE_CREG,0); |
133 | 239 return FLOAT; |
195 | 240 #endif |
206 | 241 #if LONGLONG_CODE |
202 | 242 case LCONST: |
221 | 243 code_lconst(e1,USE_CREG); |
202 | 244 return LONGLONG; |
245 #endif | |
61 | 246 case STRING: |
221 | 247 code_string(e1,USE_CREG); |
94 | 248 return ADDRESS; |
61 | 249 case FUNCTION: |
94 | 250 t = function(e1); |
251 return t; | |
61 | 252 case CODE: |
253 jump(e2,caddr(e1)); | |
94 | 254 return VOID; |
455 | 255 case INLINE: |
256 return g_expr0(pexpr(e1)); | |
61 | 257 case INDIRECT: |
94 | 258 return g_expr0(e2); |
196 | 259 case RINDIRECT: |
355 | 260 code_rindirect(e2,USE_CREG,caddr(e1),1,0); return INT; |
196 | 261 case URINDIRECT: |
355 | 262 code_rindirect(e2,USE_CREG,caddr(e1),0,0); return UNSIGNED; |
196 | 263 case CRINDIRECT: |
355 | 264 code_rindirect(e2,USE_CREG,caddr(e1),1,1); return CHAR; |
196 | 265 case CURINDIRECT: |
355 | 266 code_rindirect(e2,USE_CREG,caddr(e1),0,1); return UCHAR; |
196 | 267 case SRINDIRECT: |
355 | 268 code_rindirect(e2,USE_CREG,caddr(e1),1,size_of_short); return SHORT; |
245 | 269 case SURINDIRECT: |
355 | 270 code_rindirect(e2,USE_CREG,caddr(e1),0,size_of_short); return USHORT; |
195 | 271 #if FLOAT_CODE |
197 | 272 case FRINDIRECT: |
221 | 273 return code_drindirect(e2,USE_CREG,caddr(e1),0); |
196 | 274 case DRINDIRECT: |
221 | 275 return code_drindirect(e2,USE_CREG,caddr(e1),1); |
195 | 276 #endif |
196 | 277 #if LONGLONG_CODE |
278 case LRINDIRECT: | |
221 | 279 return code_lrindirect(e2,USE_CREG,caddr(e1),0); |
196 | 280 case LURINDIRECT: |
221 | 281 return code_lrindirect(e2,USE_CREG,caddr(e1),1); |
196 | 282 #endif |
61 | 283 case ADDRESS: |
138 | 284 if (car(e2)==REGISTER||car(e2)==DREGISTER||car(e2)==FREGISTER) |
285 return register_to_lvar(e2); /* too late? */ | |
105 | 286 else |
287 return g_expr0(e2); | |
61 | 288 case MINUS: /* �쥸�������Ф���negl��¹Ԥ���м¸���ǽ */ |
221 | 289 g_expr0(e2); code_neg(USE_CREG); |
94 | 290 return INT; |
212 | 291 #if LONGLONG_CODE |
292 case LMINUS: | |
221 | 293 g_expr0(e2); code_lneg(USE_CREG); |
212 | 294 return LONGLONG; |
295 #endif | |
195 | 296 #if FLOAT_CODE |
81 | 297 case DMINUS: |
221 | 298 g_expr0(e2); code_dneg(USE_CREG,1); |
94 | 299 return DOUBLE; |
133 | 300 case FMINUS: |
221 | 301 g_expr0(e2); code_dneg(USE_CREG,0); |
133 | 302 return FLOAT; |
195 | 303 #endif |
108 | 304 case CONV: |
305 g_expr0(e2); | |
306 switch(caddr(e1)) { | |
353 | 307 case I2C: code_i2c(USE_CREG); return INT; |
308 case I2S: code_i2s(USE_CREG); return INT; | |
309 case U2UC: code_u2uc(USE_CREG); return UNSIGNED; | |
310 case U2US: code_u2us(USE_CREG); return UNSIGNED; | |
195 | 311 #if FLOAT_CODE |
221 | 312 case I2D: code_i2d(USE_CREG); return DOUBLE; |
313 case D2I: code_d2i(USE_CREG); return INT; | |
314 case U2D: code_u2d(USE_CREG); return DOUBLE; | |
315 case F2U: code_f2u(USE_CREG); return UNSIGNED; | |
316 case I2F: code_i2f(USE_CREG); return FLOAT; | |
317 case F2I: code_f2i(USE_CREG); return INT; | |
318 case U2F: code_u2f(USE_CREG); return FLOAT; | |
319 case D2U: code_d2u(USE_CREG); return UNSIGNED; | |
320 case D2F: code_d2f(USE_CREG); return FLOAT; | |
321 case F2D: code_f2d(USE_CREG); return DOUBLE; | |
195 | 322 #endif |
323 #if LONGLONG_CODE | |
221 | 324 case I2LL: code_i2ll(USE_CREG); return LONGLONG; |
325 case I2ULL: code_i2ull(USE_CREG); return ULONGLONG; | |
326 case U2LL: code_u2ll(USE_CREG); return LONGLONG; | |
327 case U2ULL: code_u2ull(USE_CREG); return ULONGLONG; | |
328 case LL2I: code_ll2i(USE_CREG); return INT; | |
329 case LL2U: code_ll2u(USE_CREG); return UNSIGNED; | |
330 case ULL2I: code_ull2i(USE_CREG); return INT; | |
331 case ULL2U: code_ull2u(USE_CREG); return UNSIGNED; | |
195 | 332 #if FLOAT_CODE |
221 | 333 case D2LL: code_d2ll(USE_CREG); return LONGLONG; |
334 case D2ULL: code_d2ull(USE_CREG); return ULONGLONG; | |
335 case F2LL: code_f2ll(USE_CREG); return LONGLONG; | |
336 case F2ULL: code_f2ull(USE_CREG); return ULONGLONG; | |
337 case LL2D: code_ll2d(USE_CREG); return DOUBLE; | |
338 case LL2F: code_ll2f(USE_CREG); return FLOAT; | |
339 case ULL2D: code_ull2d(USE_CREG); return DOUBLE; | |
340 case ULL2F: code_ull2f(USE_CREG); return FLOAT; | |
195 | 341 #endif |
342 #endif | |
343 | |
108 | 344 default: |
345 error(-1); return INT; | |
346 } | |
61 | 347 case BNOT: /* ~ */ |
221 | 348 g_expr0(e2); code_not(USE_CREG); |
94 | 349 return INT; |
61 | 350 case LNOT: /* ! */ |
221 | 351 g_expr0(e2); code_lnot(USE_CREG); |
94 | 352 return INT; |
61 | 353 case PREINC: |
221 | 354 code_preinc(e1,e2,caddr(e1),1,cadddr(e1),USE_CREG); |
168 | 355 return INT; |
356 case UPREINC: | |
221 | 357 code_preinc(e1,e2,caddr(e1),0,cadddr(e1),USE_CREG); |
94 | 358 return INT; |
61 | 359 case POSTINC: |
221 | 360 code_postinc(e1,e2,caddr(e1),1,cadddr(e1),USE_CREG); |
168 | 361 return INT; |
362 case UPOSTINC: | |
221 | 363 code_postinc(e1,e2,caddr(e1),0,cadddr(e1),USE_CREG); |
94 | 364 return INT; |
195 | 365 #if FLOAT_CODE |
147 | 366 case DPREINC: /* ++d */ |
221 | 367 code_dpreinc(e1,e2,1,USE_CREG); |
94 | 368 return DOUBLE; |
147 | 369 case DPOSTINC: /* d++ */ |
221 | 370 code_dpostinc(e1,e2,1,USE_CREG); |
94 | 371 return DOUBLE; |
147 | 372 case FPREINC: /* ++f */ |
221 | 373 code_dpreinc(e1,e2,0,USE_CREG); |
94 | 374 return FLOAT; |
147 | 375 case FPOSTINC: /* f++ */ |
221 | 376 code_dpostinc(e1,e2,0,USE_CREG); |
94 | 377 return FLOAT; |
195 | 378 #endif |
379 #if LONGLONG_CODE | |
380 case LPREINC: /* ++d */ | |
221 | 381 code_lpreinc(e1,e2,USE_CREG); |
219 | 382 return LONGLONG; |
195 | 383 case LPOSTINC: /* d++ */ |
221 | 384 code_lpostinc(e1,e2,USE_CREG); |
219 | 385 return LONGLONG; |
386 case LUPREINC: /* ++d */ | |
221 | 387 code_lpreinc(e1,e2,USE_CREG); |
219 | 388 return ULONGLONG; |
389 case LUPOSTINC: /* d++ */ | |
221 | 390 code_lpostinc(e1,e2,USE_CREG); |
219 | 391 return ULONGLONG; |
195 | 392 #endif |
61 | 393 case MUL: case UMUL: |
394 case DIV: case UDIV: | |
395 case MOD: case UMOD: | |
396 case LSHIFT: case ULSHIFT: case RSHIFT: case URSHIFT: | |
246 | 397 case ADD: case SUB: case BAND: case EOR: case BOR: case CMP: case CMPGE: |
278 | 398 case UCMP: case CMPEQ: case CMPNEQ: case UCMPGE: |
61 | 399 machinop(e1); |
94 | 400 return INT; |
195 | 401 #if FLOAT_CODE |
81 | 402 case DMUL: case DDIV: |
403 case DADD: case DSUB: | |
250 | 404 case DCMP: case DCMPGE: case DCMPEQ: case DCMPNEQ: |
133 | 405 dmachinop(e1,1); |
94 | 406 return DOUBLE; |
133 | 407 case FMUL: case FDIV: |
408 case FADD: case FSUB: | |
250 | 409 case FCMP: case FCMPGE: case FCMPEQ: case FCMPNEQ: |
133 | 410 dmachinop(e1,0); |
411 return FLOAT; | |
195 | 412 #endif |
413 #if LONGLONG_CODE | |
414 case LMUL: case LUMUL: | |
415 case LDIV: case LUDIV: | |
416 case LMOD: case LUMOD: | |
417 case LLSHIFT: case LULSHIFT: case LRSHIFT: case LURSHIFT: | |
418 case LADD: case LSUB: case LBAND: case LEOR: case LBOR: case LCMP: | |
419 lmachinop(e1); | |
420 return INT; | |
421 #endif | |
222 | 422 case LCOND: |
423 case DCOND: | |
424 case FCOND: | |
195 | 425 case COND: /* a?0:1 should consider non-brach instruction */ |
426 d = (car(e1)==LCOND?LONGLONG: | |
427 car(e1)==COND?INT:car(e1)==DCOND?DOUBLE:FLOAT); | |
108 | 428 e2=fwdlabel(); |
355 | 429 if (caddr(e1)) { |
430 b_expr(cadr(e1),0,e2,0); | |
431 g_expr0(caddr(e1)); | |
388 | 432 } else { // gcc extenstion a?:DEF |
355 | 433 bexpr(cadr(e1),0,e2); // value used |
434 } | |
221 | 435 t = code_get_fixed_creg(USE_CREG,d); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
436 gen_jmp(e3=fwdlabel()); |
108 | 437 fwddef(e2); |
191 | 438 t1=g_expr0(cadddr(e1)); |
187 | 439 code_set_fixed_creg(t,1,d); |
61 | 440 fwddef(e3); |
191 | 441 return t1; |
164 | 442 case STASS: |
61 | 443 sassign(e1); |
94 | 444 return RSTRUCT; |
165 | 445 case ASS: case CASS: case SASS: |
61 | 446 assign(e1); |
94 | 447 return INT; |
343 | 448 case SASSOP: case SUASSOP: |
162 | 449 case ASSOP: case CASSOP: case CUASSOP: |
327 | 450 iassop(e1); |
94 | 451 return INT; |
195 | 452 #if FLOAT_CODE |
453 case FASS: case DASS: | |
454 dassign(e1); | |
455 return DOUBLE; | |
81 | 456 case DASSOP: case FASSOP: |
457 dassop(e1); | |
94 | 458 return DOUBLE; |
195 | 459 #endif |
460 #if LONGLONG_CODE | |
461 case LASS: | |
462 lassign(e1); | |
463 return LONGLONG; | |
464 case LASSOP: case LUASSOP: | |
465 lassop(e1); | |
466 return LONGLONG ; | |
467 #endif | |
61 | 468 case RSTRUCT: |
83 | 469 g_expr0(e2); |
94 | 470 return RSTRUCT; |
313 | 471 case ALLOCA: |
472 code_alloca(e2,USE_CREG); | |
473 return list2(POINTER,CHAR); | |
456 | 474 case BUILTINP: |
475 /* Too late. Should be evaluated in pexpr. */ | |
476 code_const(is_const(e2),USE_CREG); | |
477 return INT; | |
61 | 478 case COMMA: |
83 | 479 g_expr_u(e2); |
94 | 480 return g_expr0(caddr(e1)); |
61 | 481 case RETURN: |
482 n = (NMTBL *)e2; | |
483 if (retcont==0) | |
484 retcont=fwdlabel(); | |
221 | 485 code_return(USE_CREG); |
94 | 486 return VOID; |
61 | 487 case ENVIRONMENT: |
221 | 488 code_environment(USE_CREG); |
94 | 489 return ADDRESS; |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
490 case LCALL: |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
491 code_save_stacks(); |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
492 gen_jmp(e2); |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
493 fwddef(caddr(e1)); |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
494 return VOID; |
329 | 495 #if BIT_FIELD_CODE |
496 case RBIT_FIELD: | |
497 return bit_field(e2,caddr(e1) /* type */); | |
498 case BASS: | |
499 return bassign(e2,caddr(e1),cadr(cadddr(e1))/* type */); | |
331 | 500 case BPREINC: |
501 return bassop(e2,list2(CONST,caddr(e1)),ADD, | |
338 | 502 cadddr(e1)/* type */,0); |
331 | 503 case BPOSTINC: |
504 return bassop(e2,list2(CONST,caddr(e1)),ADD, | |
338 | 505 cadddr(e1)/* type */,1); |
329 | 506 case BASSOP: |
507 return bassop(e2,caddr(e1),car(cadddr(e1)),/* op */ | |
331 | 508 cadr(cadddr(e1))/* type */,0); |
329 | 509 #endif |
316 | 510 #if ASM_CODE |
511 case ASM: | |
327 | 512 gen_asm(car(e2),cadr(e2),caddr(e2),cadddr(e2),caddr(e1)); |
316 | 513 /* asm in (str) out (str) opt(str) expr */ |
514 return VOID; | |
515 #endif | |
453 | 516 case ST_DECL: st_decl(e1); break; |
517 case ST_IF: st_if(e1); break; | |
518 case ST_DO: st_do(e1); break; | |
519 case ST_WHILE: st_while(e1); break; | |
520 case ST_FOR: st_for(e1); break; | |
521 case ST_SWITCH: st_switch(e1); break; | |
522 case ST_COMP: st_comp(e1); break; | |
523 case ST_BREAK: st_break(e1); break; | |
524 case ST_CONTINUE: st_continue(e1); break; | |
525 case ST_CASE: st_case(e1); break; | |
526 case ST_DEFAULT: st_default(e1); break; | |
527 case ST_RETURN: st_return(e1); break; | |
528 case ST_GOTO: st_goto(e1); break; | |
529 case ST_ASM: st_asm(e1); break; | |
530 case ST_LABEL: st_label(e1); break; | |
531 case ST_COMMENT: st_comment(e1); break; | |
61 | 532 default: |
221 | 533 code_bool(e1,USE_CREG); /* type? */ |
94 | 534 return INT; |
61 | 535 } |
453 | 536 } |
537 return VOID; | |
61 | 538 } |
539 | |
327 | 540 static int |
94 | 541 rop_dual(op) |
542 { | |
232 | 543 // x op y => y dual(op) x |
195 | 544 switch(op) { |
545 case GT: return LT; | |
546 case UGT: return ULT; | |
547 case GE: return LE; | |
548 case UGE: return ULE; | |
549 case LT: return GT; | |
550 case ULT: return UGT; | |
551 case LE: return GE; | |
552 case ULE: return UGE; | |
553 case DOP+GT: return DOP+LT; | |
554 case DOP+GE: return DOP+LE; | |
555 case DOP+LT: return DOP+GT; | |
556 case DOP+LE: return DOP+GE; | |
557 case FOP+GT: return FOP+LT; | |
558 case FOP+GE: return FOP+LE; | |
559 case FOP+LT: return FOP+GT; | |
560 case FOP+LE: return FOP+GE; | |
561 | |
562 case LOP+GT: return LOP+LT; | |
563 case LOP+GE: return LOP+LE; | |
564 case LOP+LT: return LOP+GT; | |
565 case LOP+LE: return LOP+GE; | |
566 case LOP+UGT: return FOP+ULT; | |
567 case LOP+UGE: return FOP+ULE; | |
568 case LOP+ULT: return FOP+UGT; | |
569 case LOP+ULE: return FOP+UGE; | |
570 } | |
94 | 571 return op; |
572 } | |
573 | |
327 | 574 /* bexpr for value unused */ |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
575 /* l1 ... label for branch */ |
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
576 /* return 0 if l1 is not used, otherwise return l1 */ |
327 | 577 |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
578 extern int |
289 | 579 bexpr_u(int e1, char cond, int l1) |
61 | 580 { |
94 | 581 int op = car(e1); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
582 if (chk) return l1; |
292 | 583 // gexpr_init(); |
342 | 584 switch(op) { |
441 | 585 case GT: case UGT: case GE: case UGE: case LT: |
342 | 586 case ULT: case LE: case ULE: |
587 case DOP+GT: case DOP+GE: case DOP+LT: case DOP+LE: | |
588 case FOP+GT: case FOP+GE: case FOP+LT: case FOP+LE: | |
589 case FOP+EQ: case FOP+NEQ: | |
590 case EQ: case NEQ: case DOP+EQ: case DOP+NEQ: | |
441 | 591 switch(car(cadr(e1))) { |
592 case CONST: case DCONST: case FCONST: case LCONST: | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
593 return b_expr(list3(rop_dual(op),caddr(e1),cadr(e1)),cond,l1,0); |
342 | 594 } |
595 } | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
596 return b_expr(e1,cond,l1,0); |
61 | 597 } |
598 | |
327 | 599 /* bexpr for value used */ |
600 | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
601 extern int |
289 | 602 bexpr(int e1, char cond, int l1) |
603 { | |
604 int uses = use; use=1; | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
605 l1 = bexpr_u(e1, cond, l1); |
289 | 606 use = uses; |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
607 return l1; |
289 | 608 } |
609 | |
327 | 610 /* branch expression generator */ |
611 /* if (cond?e1:!e1) goto l1 */ | |
612 /* 1 or 0 is return for code_bool */ | |
613 | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
614 extern int |
61 | 615 b_expr(int e1, char cond, int l1,int err) |
616 { | |
94 | 617 int e2,l2,t; |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
618 if (!control) return l1; |
127 | 619 l2 = 0; |
61 | 620 e2=cadr(e1); |
621 switch(car(e1)) { | |
622 case LNOT: | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
623 return b_expr(e2,!cond,l1,0); |
280 | 624 case GT: case GE: case LT: case LE: |
625 case EQ: case NEQ: | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
626 return rexpr(e1,l1,cond,INT); |
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
627 return l1; |
280 | 628 case UGT: case UGE: case ULT: case ULE: |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
629 return rexpr(e1,l1,cond,UNSIGNED); |
195 | 630 #if FLOAT_CODE |
82 | 631 case DOP+GT: |
194 | 632 case DOP+GE: |
633 case DOP+EQ: | |
634 case DOP+NEQ: | |
635 case FOP+GT: | |
636 case FOP+GE: | |
637 case FOP+EQ: | |
638 case FOP+NEQ: | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
639 return drexpr(cadr(e1),caddr(e1),l1,car(e1),cond); |
194 | 640 case FOP+LT: |
231 | 641 case FOP+LE: |
82 | 642 case DOP+LT: |
643 case DOP+LE: | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
644 return drexpr(caddr(e1),cadr(e1),l1,rop_dual(car(e1)),cond); |
195 | 645 #endif |
646 #if LONGLONG_CODE | |
647 case LOP+GT: | |
648 case LOP+GE: | |
649 case LOP+EQ: | |
650 case LOP+NEQ: | |
210 | 651 case LOP+UGT: |
652 case LOP+UGE: | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
653 return lrexpr(cadr(e1),caddr(e1),l1,car(e1),cond); |
232 | 654 case LOP+LT: |
655 case LOP+LE: | |
210 | 656 case LOP+ULT: |
657 case LOP+ULE: | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
658 return lrexpr(caddr(e1),cadr(e1),l1,rop_dual(car(e1)),cond); |
195 | 659 #endif |
61 | 660 case LAND: |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
661 l2=bexpr(e2,0,cond?(l2=fwdlabel()):l1); |
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
662 l1=bexpr_u(caddr(e1),cond,l1); |
61 | 663 if(cond) fwddef(l2); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
664 return l1; |
61 | 665 case LOR: |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
666 l2=bexpr(e2,1,cond?l1:(l2=fwdlabel())); |
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
667 l1=bexpr_u(caddr(e1),cond,l1); |
61 | 668 if(!cond) fwddef(l2); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
669 return l1; |
167 | 670 case CRGVAR: case CURGVAR: |
287 | 671 code_cmp_crgvar(e1,USE_CREG,1,l1,cond); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
672 return l1; |
167 | 673 case SRGVAR: case SURGVAR: |
287 | 674 code_cmp_crgvar(e1,USE_CREG,size_of_short,l1,cond); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
675 return l1; |
167 | 676 case CRLVAR: case CURLVAR: |
287 | 677 code_cmp_crlvar(e2,USE_CREG,1,l1,cond); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
678 return l1; |
167 | 679 case SRLVAR: case SURLVAR: |
287 | 680 code_cmp_crlvar(e2,USE_CREG,size_of_short,l1,cond); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
681 return l1; |
61 | 682 case RGVAR: |
287 | 683 code_cmp_rgvar(e1,USE_CREG,l1,cond); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
684 return l1; |
61 | 685 case RLVAR: |
287 | 686 code_cmp_rlvar(e2,USE_CREG,l1,cond); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
687 return l1; |
195 | 688 #if FLOATC_DOE |
81 | 689 case DRLVAR: |
287 | 690 code_cmp_drlvar(e2,USE_CREG,1,l1,cond); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
691 return l1; |
138 | 692 case FRLVAR: |
287 | 693 code_cmp_drlvar(e2,USE_CREG,0,l1,cond); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
694 return l1; |
81 | 695 case DRGVAR: |
287 | 696 code_cmp_drgvar(e2,USE_CREG,1,l1,cond); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
697 return l1; |
138 | 698 case FRGVAR: |
287 | 699 code_cmp_drgvar(e2,USE_CREG,0,l1,cond); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
700 return l1; |
138 | 701 case FREGISTER: |
287 | 702 code_cmp_dregister(e2,0,l1,cond); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
703 return l1; |
94 | 704 case DREGISTER: |
287 | 705 code_cmp_dregister(e2,1,l1,cond); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
706 return l1; |
81 | 707 case DCONST: |
138 | 708 case FCONST: |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
709 if(control&&((dcadr(e2)!=0.0)^cond)) { |
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
710 gen_jmp(l1); return l1; |
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
711 else return 0; |
195 | 712 #endif |
713 #if LONGLONG_DOE | |
714 case LRLVAR: | |
287 | 715 code_cmp_lrlvar(e2,1,l1,cond); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
716 return l1; |
195 | 717 case LRGVAR: |
287 | 718 code_cmp_lrgvar(e2,1,l1,cond); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
719 return l1; |
195 | 720 case LREGISTER: |
287 | 721 code_cmp_lregister(e2,1,l1,cond); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
722 return l1; |
195 | 723 case LCONST: |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
724 if(control&&((lcadr(e2)!=0)^cond)) { |
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
725 gen_jmp(l1); return l1; |
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
726 else return 0; |
195 | 727 #endif |
728 case REGISTER: | |
287 | 729 code_cmp_register(e2,l1,cond); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
730 return l1; |
195 | 731 case CONST: |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
732 if(control&&((cond&&e2)||(!cond&&!e2))) { |
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
733 gen_jmp(l1); return l1; |
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
734 } else return 0; |
61 | 735 default: |
736 if(err) { | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
737 error(-1); return l1; /* recursive g_expr/b_expr */ |
94 | 738 } |
739 t=g_expr(e1); | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
740 if (!use) return l1; |
195 | 741 if (0) ; |
742 #if FLOAT_CODE | |
743 else if(t==FLOAT) | |
287 | 744 code_cmp_dregister(USE_CREG,0,l1,cond); |
138 | 745 else if(t==DOUBLE) |
287 | 746 code_cmp_dregister(USE_CREG,1,l1,cond); |
195 | 747 #endif |
748 #if LONGLONG_CODE | |
749 else if(t==LONGLONG||t==ULONGLONG) | |
287 | 750 code_cmp_lregister(USE_CREG,l1,cond); |
195 | 751 #endif |
94 | 752 else |
287 | 753 code_cmp_register(USE_CREG,l1,cond); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
754 return l1; |
61 | 755 } |
756 } | |
757 | |
327 | 758 extern int |
456 | 759 is_const(int e) |
760 { | |
761 switch(car(e)) { | |
762 case CONST: case LCONST: case FCONST: case DCONST: | |
763 // case ADDRESS: what happen? | |
764 // case POINTER: | |
765 return 1; | |
766 default: | |
767 return 0; | |
768 } | |
769 } | |
770 | |
771 extern int | |
126 | 772 is_code(NMTBL *fnptr) |
773 { | |
774 int type = fnptr->ty; | |
775 return type==CODE|| (type>0 && car(type)==CODE); | |
776 } | |
777 | |
327 | 778 extern int |
126 | 779 is_function(NMTBL *fnptr) |
780 { | |
781 int type = fnptr->ty; | |
782 return type==FUNCTION || (type>0 && car(type)==FUNCTION); | |
783 } | |
784 | |
327 | 785 extern int |
453 | 786 is_inline(NMTBL *f) |
787 { | |
788 return (f && attr_value(f,INLINE)); | |
789 } | |
790 | |
791 extern int | |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
792 function_type(int e1,int *dots) |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
793 { |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
794 int ret_type,t; |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
795 ret_type = cadr(e1); |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
796 if (ret_type==CHAR) ret_type=INT; |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
797 |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
798 /* check argments type is DOTS? */ |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
799 t = caddr(e1); |
313 | 800 if (/* t==0 || */ t==DOTS) *dots = 1; |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
801 else { |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
802 *dots = 0; |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
803 for(;t;t = cadr(t)) { |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
804 if (car(t)==DOTS) *dots = 1; |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
805 } |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
806 } |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
807 |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
808 return ret_type; |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
809 } |
61 | 810 |
105 | 811 static int |
812 register_to_lvar(int e) | |
813 { | |
814 error(REG_ERR); | |
815 return 0; | |
816 #if 0 | |
817 ����ǥ쥸��������LVAR���ѹ����Ƥ⡢�֤˹��ʤ��� | |
818 | |
819 NMTBL *n = (NMTBL*)caddr(e); | |
820 int reg = cadr(e); | |
821 int tag = car(e); | |
822 int lvar; | |
823 int t; | |
824 if (!n||n==&null_nptr) error(REG_ERR); | |
342 | 825 switch(tag) { |
826 case REGISTER: | |
827 n->dsp = new_lvar(size_of_int); t = INT; break; | |
828 case DREGISTER: | |
829 n->dsp = new_lvar(size_of_double); t = DOUBLE; break; | |
830 case FREGISTER: | |
831 n->dsp = new_lvar(size_of_float); t = DOUBLE; break; | |
832 case LREGISTER: | |
833 n->dsp = new_lvar(size_of_longlong); t = LONGLONG; break; | |
834 default: | |
835 error(-1); | |
836 } | |
105 | 837 n->sc = LVAR; |
445 | 838 lvar = list3(LVAR,n->dsp,(int)n); |
839 g_expr_u(assign_expr0(list3(LVAR,n->dsp,(int)n),list3(tag,reg,(int)n),t,t)); | |
195 | 840 if (tag==REGISTER||tag==DREGISTER||tag==FREGISTER||tag==LREGISTER) { |
105 | 841 free_register(reg); |
842 return g_expr0(lvar); | |
843 #endif | |
844 } | |
845 | |
277 | 846 // parallel assignment of registers. |
847 // | |
848 // target = list3(target_regnum,next,source_regnum); | |
849 | |
327 | 850 extern void |
277 | 851 parallel_rassign(int assigns) |
852 { | |
368 | 853 int free,tmp,remains,t0,t2,src; |
277 | 854 tmp = 0; |
855 for(;;) { | |
856 remains = 0; | |
857 // find free target | |
858 for(free=assigns;free;free=cadr(free)) { | |
859 if (!caddr(free)) continue; // already done | |
369 | 860 if (car(free)==caddr(free)) { |
861 caddr(free)=0; | |
862 continue; | |
863 } | |
277 | 864 remains++; |
865 t0 = car(free); // target register | |
866 // check target is free | |
867 for(src=assigns;src;src=cadr(src)) { | |
868 if ((t2=caddr(src)) && t0==t2) break; // target is in source | |
869 } | |
870 if (src==0) { | |
871 break; // free is a free target | |
872 } | |
873 } | |
874 if (remains==0) { | |
370 | 875 if (tmp) free_lvar(tmp); |
277 | 876 return; |
877 } | |
878 if (free) { // free target | |
368 | 879 if (t0!=caddr(free)) { |
880 if (caddr(free)>=0) { | |
881 code_assign_register(t0,0,caddr(free)); | |
882 } else { | |
883 code_rlvar(caddr(free),t0); | |
884 } | |
885 } | |
886 caddr(free)=0; // mark it done | |
277 | 887 } else { // no free target |
888 for(free=assigns;free;free=cadr(free)) { | |
889 if (caddr(free)) break; // not yet done | |
890 } | |
891 if (!free) error(-1); | |
892 tmp = new_lvar(size_of_int); | |
368 | 893 if (tmp>0) error(-1); |
277 | 894 code_assign_lvar(tmp,caddr(free),0); |
368 | 895 caddr(free) = tmp; |
277 | 896 } |
897 } | |
898 } | |
899 | |
61 | 900 /* goto arguments list */ |
901 /* target list4(list2(tag,disp),cdr,ty,source_expr) */ | |
902 /* source expr=listn(tag,...) */ | |
903 /* source (after) list2(tag,disp) */ | |
904 /* source list list3(e,cdr,sz) */ | |
905 | |
451 | 906 #define DEBUG_PARALLEL_ASSIGN 0 |
449 | 907 |
908 static int is_memory(int e1); | |
61 | 909 |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
910 /* overlap |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
911 return list of overlapped target |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
912 */ |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
913 |
327 | 914 static int |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
915 overlap(int t,int sz,int target) |
61 | 916 { |
917 int s,s0,s1; | |
918 int t0=cadr(t); | |
919 int t1=t0+sz; | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
920 int source; |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
921 int result=0; |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
922 if (!is_memory(t)) error(-1); |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
923 for(;target;target=cadr(target)) { |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
924 for(source=caddddr(target);source;source=cadr(source)) { |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
925 s=car(source); s0=cadr(s); |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
926 switch(car(s)) { |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
927 case REGISTER: case DREGISTER: case FREGISTER: case LREGISTER: |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
928 if (code_register_overlap(s,t)) { |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
929 result = list2(target,result); |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
930 } |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
931 break; |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
932 default: |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
933 if (is_same_type(s,t)) { |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
934 s1=s0+caddr(source); |
61 | 935 #if DEBUG_PARALLEL_ASSIGN>1 |
344 | 936 printf("# overlap source %d t0 %d t1 %d\n",car(car(t)),t0,t1); |
937 printf("# overlap target %d s0 %d s1 %d\n",car(car(source)),s0,s1); | |
938 printf("# overlap equal = %d\n",((t0<=s0&&s0<t1)||(t0<s1&&s1<=t1))); | |
61 | 939 #endif |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
940 if((t0<=s0&&s0<t1)||(t0<s1&&s1<=t1)) |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
941 result = list2(target,result); |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
942 } |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
943 } |
61 | 944 } |
945 } | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
946 return result; |
61 | 947 } |
948 | |
327 | 949 static void |
61 | 950 remove_target(int *target,int t,int *use) |
951 { | |
952 int use0=*use; | |
147 | 953 int reg; |
61 | 954 while(use0) { |
955 if (car(use0)==t) { | |
147 | 956 reg = car(caddr(use0)); |
345 | 957 if (reg==REGISTER||reg==FREGISTER||reg==DREGISTER||reg==LREGISTER) |
99 | 958 free_register(cadr(caddr(use0))); |
61 | 959 break; |
960 } | |
961 use0 = cadr(use0); | |
962 } | |
963 remove0(target,t); | |
964 } | |
965 | |
327 | 966 static void |
61 | 967 save_target(int t,int s,int *target,int *use,int sz,int ty) |
968 { | |
969 int e1; | |
970 /*�������쥸����(or �����å�)���������*/ | |
417 | 971 if (scalar(ty) && sz==size_of_int && (e1=get_register_var(0))!=-1) { |
972 // e1=list3(REGISTER,e1,0); | |
61 | 973 *use=list3(t,*use,e1); |
99 | 974 g_expr_u(assign_expr0(e1,s,ty,ty)); |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
975 *target = append5(*target,t,ty,e1,list3(e1,0,sz)); |
195 | 976 #if FLOAT_CODE |
417 | 977 } else if (ty==DOUBLE && sz==size_of_double && (e1=get_dregister_var(0,1))!=-1) { |
978 // e1=list3(DREGISTER,e1,0); | |
99 | 979 *use=list3(t,*use,e1); |
83 | 980 g_expr_u(assign_expr0(e1,s,ty,ty)); |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
981 *target = append5(*target,t,ty,e1,list3(e1,0,sz)); |
417 | 982 } else if (ty==FLOAT && sz==size_of_float && (e1=get_dregister_var(0,0))!=-1) { |
983 // e1=list3(FREGISTER,e1,0); | |
138 | 984 *use=list3(t,*use,e1); |
985 g_expr_u(assign_expr0(e1,s,ty,ty)); | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
986 *target = append5(*target,t,ty,e1,list3(e1,0,sz)); |
195 | 987 #endif |
205 | 988 #if LONGLONG_CODE |
417 | 989 } else if ((ty==LONGLONG||ty==ULONGLONG)&&(e1=get_lregister_var(0))!=-1) { |
990 // e1=list3(LREGISTER,e1,0); | |
205 | 991 *use=list3(t,*use,e1); |
992 g_expr_u(assign_expr0(e1,s,ty,ty)); | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
993 *target = append5(*target,t,ty,e1,list3(e1,0,sz)); |
205 | 994 #endif |
61 | 995 } else { |
445 | 996 g_expr_u(assign_expr0((e1=list3(LVAR,new_lvar(sz),0)),s,ty,ty)); |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
997 *target = append5(*target,t,ty,e1,list3(e1,0,sz)); |
117 | 998 *use=list3(t,*use,e1); |
61 | 999 } |
1000 } | |
1001 | |
327 | 1002 static int |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1003 circular_dependency(int t,int clist,int target,int history) |
61 | 1004 { |
451 | 1005 int t1,h,sz,s,clist1,t2; |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1006 |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1007 for(;clist;clist=cadr(clist)) { /* conflict list */ |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1008 loop: |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1009 t1 = car(clist); |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1010 for(h=history;h;h=cadr(h)) { |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1011 if (t1==car(h)) { |
61 | 1012 #if DEBUG_PARALLEL_ASSIGN |
451 | 1013 printf("# circular dependency %d ty %d\n",car(t1),cadr(t1)); |
61 | 1014 #endif |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1015 return t1; |
61 | 1016 } |
1017 } | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1018 for(s=caddddr(t1);s;s=cadr(s)) { /* dependent memory sources */ |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1019 sz=caddr(s); |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1020 if ((clist1=overlap(car(s),sz,target))) { |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1021 if (!cadr(t1)&&!cadr(s)) { |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1022 history = list2(t,history); |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1023 t = t1; |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1024 clist = clist1; |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1025 goto loop; // tail recursion |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1026 } else { |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1027 if ((t2=circular_dependency(t1, |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1028 clist1,target,list2(t,history)))) { |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1029 return t2; |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1030 } |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1031 } |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1032 } |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1033 } |
61 | 1034 } |
1035 return 0; | |
1036 } | |
1037 | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1038 // static void remove_a(int source,int s); // remove all child |
449 | 1039 |
327 | 1040 static void |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1041 parallel_assign(int *target,int *processing,int *use) |
61 | 1042 { |
449 | 1043 int t,s,sz,ty,target0,s1,progress; |
61 | 1044 while(*target) { |
449 | 1045 progress = 0; |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1046 for(target0=*target;target0; target0=cadr(target0)) { |
61 | 1047 t=car(target0); s=cadddr(target0); |
1048 sz=size(ty=caddr(target0)); | |
1049 if(car(t)==car(s) && cadr(t)==cadr(s)) { | |
1050 /*�����褬��ʬ����*/ | |
1051 #if DEBUG_PARALLEL_ASSIGN | |
1052 printf("# remove same %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz); | |
1053 #endif | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1054 remove_target(target,t,use); |
449 | 1055 progress = 1; |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1056 } else if (!(s1=overlap(t,sz,*target)) || |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1057 (cadr(s1)==0 && car(car(s1))==t)) { |
61 | 1058 /* �ŤʤäƤʤ��Τǰ¿����ƽ���� */ |
1059 #if DEBUG_PARALLEL_ASSIGN | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1060 if (s1 && cadr(s1)==0) |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1061 printf("# singleton %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz); |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1062 else |
61 | 1063 printf("# normal assign %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz); |
1064 #endif | |
83 | 1065 g_expr_u(assign_expr0(t,s,ty,ty)); |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1066 remove_target(target,t,use); |
449 | 1067 progress = 1; |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1068 } else if((t=circular_dependency(target0,s1,*target,0))) { |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1069 remove_target(target,car(t),use); |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1070 sz=size(ty=caddr(t)); |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1071 save_target(car(t),cadddr(t),target,use,sz,ty); |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1072 progress = 1; |
61 | 1073 #if DEBUG_PARALLEL_ASSIGN |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1074 printf("# saving %d ty %d+%d sz %d\n",car(car(t)),ty,cadr(car(t)),sz); |
61 | 1075 #endif |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1076 break; |
61 | 1077 } |
1078 } | |
449 | 1079 if (!progress) { |
1080 // can't performe parallel assign | |
1081 // error(-1); | |
1082 target0 = *target; | |
1083 t=car(target0); s=cadddr(target0); | |
1084 sz=size(ty=caddr(target0)); | |
1085 #if DEBUG_PARALLEL_ASSIGN | |
1086 printf("# can't progress save any %d ty %d+%d sz %d\n",car(s),ty,cadr(t),sz); | |
1087 #endif | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1088 remove_target(target,t,use); |
449 | 1089 save_target(t,s,target,use,sz,ty); |
1090 } | |
61 | 1091 } |
1092 } | |
1093 | |
327 | 1094 static void |
61 | 1095 remove0(int *parent,int e) |
1096 { | |
1097 int list; | |
1098 while ((list=*parent)) { | |
1099 if (car(list)==e) { | |
1100 *parent= cadr(list); return; | |
1101 } else { | |
1102 parent=&cadr(list); | |
1103 } | |
1104 } | |
1105 } | |
1106 | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1107 /* |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1108 |
449 | 1109 static int |
1110 remove_1(int source,int e) | |
61 | 1111 { |
449 | 1112 int sz; |
1113 if ((sz=is_memory(e))) { | |
1114 remove0((int*)source,e); | |
61 | 1115 } |
449 | 1116 return source; |
61 | 1117 } |
449 | 1118 |
1119 static void | |
1120 remove_a(int source,int s) | |
1121 { | |
1122 contains_p1(source,s,remove_1); | |
1123 } | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1124 */ |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1125 |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1126 // #define SAVE_ALL_NON_MEMORY |
449 | 1127 |
1128 #ifdef SAVE_ALL_NON_MEMORY | |
327 | 1129 static int |
61 | 1130 is_simple(int e1) |
1131 { | |
342 | 1132 switch(e1) { |
344 | 1133 case CONST: case FNAME: case LVAR: case REGISTER: case DREGISTER: |
342 | 1134 case FREGISTER: case LREGISTER: |
1135 case GVAR: case RGVAR: case RLVAR: case CRLVAR: case CRGVAR: | |
1136 case DRLVAR: case FRLVAR: case LRLVAR: | |
1137 case CURLVAR: case SURLVAR: case CURGVAR: case SURGVAR: | |
1138 return 1; | |
1139 } | |
1140 return 0; | |
61 | 1141 } |
449 | 1142 #endif |
344 | 1143 |
327 | 1144 static int |
61 | 1145 is_same_type(int e1,int e2) |
1146 { | |
1147 int ce1=car(e1); | |
1148 int ce2=car(e2); | |
342 | 1149 if (ce1==LVAR) { |
1150 switch(ce2) { | |
1151 case RLVAR: case CRLVAR: case FRLVAR: case DRLVAR: | |
416 | 1152 case SRLVAR: case SURLVAR: case CURLVAR: case LVAR: |
342 | 1153 return 1; |
1154 } | |
1155 } else if (ce2==LVAR) { | |
1156 switch(ce1) { | |
1157 case RLVAR: case CRLVAR: case FRLVAR: case DRLVAR: | |
416 | 1158 case SRLVAR: case SURLVAR: case CURLVAR: case LRLVAR: case LVAR: |
342 | 1159 return 1; |
1160 } | |
1161 } else if (ce1==GVAR) { | |
367 | 1162 return 0; |
1163 #if 0 | |
342 | 1164 switch(ce2) { |
1165 case RGVAR: case CRGVAR: case FRGVAR: case DRGVAR: | |
1166 case SRGVAR: case SURGVAR: case CURGVAR: | |
1167 return 1; | |
1168 } | |
367 | 1169 #endif |
342 | 1170 } else if (ce2==GVAR) { |
367 | 1171 return 0; |
1172 #if 0 | |
342 | 1173 switch(ce1) { |
1174 case RGVAR: case CRGVAR: case FRGVAR: case DRGVAR: | |
1175 case SRGVAR: case SURGVAR: case CURGVAR: case LRGVAR: | |
1176 return 1; | |
1177 } | |
367 | 1178 #endif |
342 | 1179 } |
1180 return 0; | |
61 | 1181 } |
1182 | |
327 | 1183 static int |
61 | 1184 is_memory(int e1) |
1185 { | |
344 | 1186 switch(car(e1)) { |
449 | 1187 case CRLVAR : |
1188 case CRGVAR : | |
1189 case CURGVAR : | |
342 | 1190 return 1; |
449 | 1191 case SURGVAR: |
1192 case SRGVAR : | |
1193 return size_of_short; | |
1194 case LVAR : | |
1195 case RLVAR: | |
1196 case GVAR : | |
1197 case REGISTER : | |
1198 case RGVAR: | |
1199 return size_of_int; | |
1200 case FRLVAR : | |
1201 case FRGVAR : | |
1202 case FREGISTER : | |
1203 return size_of_float; | |
1204 case DRLVAR : | |
1205 case DRGVAR : | |
1206 case DREGISTER : | |
1207 return size_of_double; | |
1208 case LRGVAR : | |
1209 case LRLVAR : | |
1210 case LREGISTER: | |
1211 return size_of_longlong; | |
342 | 1212 } |
1213 return 0; | |
61 | 1214 } |
1215 | |
449 | 1216 static int |
1217 check_source(int source,int e) | |
1218 { | |
1219 int sz; | |
1220 if ((sz=is_memory(e))) { | |
1221 source = list3(e,source,sz); | |
1222 } | |
1223 return source; | |
1224 } | |
1225 | |
434 | 1226 #define ASSIGN_STRUCT_DIVIDE 40 |
1227 | |
327 | 1228 static void |
61 | 1229 jump(int e1, int env) |
1230 { | |
99 | 1231 int e2,e3,e4,sz,arg_size,ty,regs,fregs; |
147 | 1232 int t0,s0,r,reg; |
127 | 1233 NMTBL *code0 = 0; |
61 | 1234 int target = 0; |
1235 int processing = 0; | |
1236 int use = 0; | |
1237 | |
416 | 1238 /* e1 = list4(FUNCTION,code_segment,arglist,ftype); */ |
1239 | |
1240 /* �ޤ���������������ʤ��顢target ���ޤä�������� */ | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1241 /* list5(target,next,ty,source,source_dependency) */ |
61 | 1242 |
99 | 1243 arg_size = 0; regs = 0; |
1244 fregs = 0; | |
61 | 1245 for (e3 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) { |
1246 e2 = car(e3); sz = size(ty=caddr(e3)); | |
138 | 1247 if (scalar(ty) && (r = get_input_register_var(regs,0,1))) { |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1248 target=list5(r,target,ty,e2,0); regs++; |
138 | 1249 } else if (ty==FLOAT && (r = get_input_dregister_var(fregs,0,1,0))) { |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1250 target=list5(r, target,ty,e2,0); fregs++; |
138 | 1251 } else if (ty==DOUBLE && (r = get_input_dregister_var(fregs,0,1,1))) { |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1252 target=list5(r, target,ty,e2,0); fregs++; |
345 | 1253 } else if ((ty==LONGLONG||ty==ULONGLONG) && (r = get_input_lregister_var(fregs,0,1))) { |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1254 target=list5(r, target,ty,e2,0); regs+=2; |
61 | 1255 } else { |
416 | 1256 while(car(e2)==RSTRUCT) e2=cadr(e2); |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1257 target=list5(list3(LVAR,0,0), target,ty,e2,0); |
61 | 1258 } |
128 | 1259 /* keep arg space for register variables */ |
1260 arg_size += sz; | |
61 | 1261 #if DEBUG_PARALLEL_ASSIGN |
1262 printf("# target %d ty %d+%d sz %d\n",car(car(target)),ty,cadr(car(target)),sz); | |
1263 #endif | |
1264 } | |
1265 | |
1266 /* disp �����������碌�ƽ��� */ | |
98 | 1267 if (is_code(fnptr)) { |
61 | 1268 if (-arg_size<disp) disp = -arg_size; |
1269 } else { | |
1270 if (disp_offset-arg_size<disp) disp = disp_offset-arg_size; | |
1271 } | |
1272 | |
1273 /* ʣ���ʼ�������äƷ����Ƥ��� */ | |
1274 /* ɬ�פʤ�ɽ��ѿ����Ѥ��롣 */ | |
1275 /* �ɽ��ѿ��ؤΥ��ե��åȤ�Ф��Ƥ��� */ | |
1276 | |
1277 for (e2 = target; e2; e2 = cadr(e2)) { | |
1278 t0=car(e2); s0=cadddr(e2); | |
1279 sz=size(ty=caddr(e2)); | |
1280 if(car(t0)==LVAR) { | |
1281 /* �����ǡ�����襢�ɥ쥹����� */ | |
1282 cadr(t0)=-arg_size; | |
1283 } | |
128 | 1284 arg_size-=sz; |
449 | 1285 #ifdef SAVE_ALL_NON_MEMORY |
61 | 1286 if (!is_simple(car(s0))) { |
449 | 1287 #else |
1288 if (contains_p(s0,not_simple_p)) { | |
1289 #endif | |
1290 /* complex case */ | |
445 | 1291 g_expr_u(assign_expr0((e4=list3(LVAR,new_lvar(sz),0)),s0,ty,ty)); |
117 | 1292 use=list3(ty,use,e1); |
61 | 1293 cadddr(e2)=e4; |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1294 caddddr(e2)=list3(e4,0,sz); |
61 | 1295 s0=e4; |
1296 } else if (is_same_type(t0,s0)) { | |
1297 if(cadr(t0)==cadr(s0)) { | |
434 | 1298 if(is_memory(s0)) { |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1299 caddddr(e2)=list3(s0,0,sz); |
434 | 1300 continue; |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1301 } else |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1302 error(-1); |
61 | 1303 } |
1304 } | |
1305 if(is_memory(s0)) { | |
434 | 1306 if (sz>8 && car(s0)==LVAR && car(t0)==LVAR |
1307 &&sz<ASSIGN_STRUCT_DIVIDE) { | |
1308 /* large struct generate large save/restore */ | |
1309 /* divide it to avoid large copy */ | |
1310 #if DEBUG_PARALLEL_ASSIGN | |
1311 printf("# division sz %d\n",sz); | |
1312 #endif | |
1313 caddr(e2) = UNSIGNED; | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1314 caddddr(e2) = list3( |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1315 cadddr(e2)=list3(LVAR,cadr(s0),0), |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1316 0, size_of_int); |
434 | 1317 #if DEBUG_PARALLEL_ASSIGN |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1318 printf("# div 0 source %d ty %d+%d sz %d\n",car(s0),ty,cadr(s0),size_of_int); |
434 | 1319 #endif |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1320 for(e4=size_of_int;e4<sz;) { |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1321 cadr(e2) = list5(car(e2),cadr(e2), |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1322 caddr(e2),cadddr(e2),caddddr(e2)); |
434 | 1323 switch(sz-e4) { |
1324 case 1: caddr(e2) = UCHAR; r = 1; break; | |
1325 case 2: | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1326 case 3: caddr(e2) = USHORT; r = size_of_short; break; |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1327 default: caddr(e2) = UNSIGNED; r = size_of_int; |
434 | 1328 } |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1329 if (e4==size_of_int) e3=cadr(e2); |
445 | 1330 car(e2) = list3(LVAR,cadr(t0)+e4,0); |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1331 caddddr(e2) = list3( |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1332 cadddr(e2) = list3(LVAR,cadr(s0)+e4,0),0, r); |
434 | 1333 e4 += r; |
1334 #if DEBUG_PARALLEL_ASSIGN | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1335 printf("# div 1 source %d ty %d+%d sz %d\n",car(s0),ty,cadr(s0),r); |
434 | 1336 #endif |
1337 } | |
1338 e2 = e3; | |
1339 continue; | |
1340 } | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1341 caddddr(e2)=list3(s0,0,sz); |
61 | 1342 #if DEBUG_PARALLEL_ASSIGN |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1343 printf("# source %d ty %d+%d sz %d\n",car(s0),ty,cadr(s0),sz); |
61 | 1344 #endif |
449 | 1345 } else { |
1346 /* check used sources in rather complex source */ | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1347 caddddr(e2)=contains_p1(0,s0,check_source); |
61 | 1348 } |
1349 } | |
1350 /* compute jump address */ | |
1351 e2 = cadr(e1); | |
1352 if (car(e2) == FNAME) { | |
1353 code0=(NMTBL *)cadr(e2); | |
98 | 1354 if (!is_code(code0)) { |
61 | 1355 error(TYERR); return; |
1356 } | |
1357 } else { /* indirect */ | |
1358 g_expr(e2); | |
1359 emit_push(); | |
1360 } | |
1361 if (env) { | |
1362 g_expr(env); | |
1363 emit_push(); | |
1364 } | |
1365 | |
1366 /* ����������¹� */ | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
1367 parallel_assign(&target,&processing,&use); |
61 | 1368 while (use) { |
147 | 1369 reg = car(caddr(use)); |
195 | 1370 if (reg==REGISTER||reg==FREGISTER||reg==DREGISTER||reg==LREGISTER) |
99 | 1371 free_register(cadr(caddr(use))); |
117 | 1372 else if (car(caddr(use))==LVAR) |
1373 free_lvar(cadr(caddr(use))); | |
99 | 1374 use=cadr(use); |
61 | 1375 } |
1376 if(target) error(-1); | |
1377 | |
1378 if (env) { | |
1379 /* change the frame pointer */ | |
1380 e3 = emit_pop(0); | |
1381 code_frame_pointer(e3); | |
1382 emit_pop_free(e3); | |
98 | 1383 } else if (is_function(fnptr)) { |
128 | 1384 if (car(e2) != FNAME) { |
1385 e2 = emit_pop(0); | |
1386 code_fix_frame_pointer(disp_offset); | |
1387 code_indirect_jmp(e2); | |
1388 emit_pop_free(e2); | |
1389 return; | |
1390 } | |
61 | 1391 code_fix_frame_pointer(disp_offset); |
1392 } | |
1393 | |
1394 if (car(e2) == FNAME) { | |
1395 code_jmp(code0->nm); | |
1396 } else { | |
1397 e2 = emit_pop(0); | |
1398 code_indirect_jmp(e2); | |
1399 emit_pop_free(e2); | |
1400 } | |
1401 } | |
1402 | |
327 | 1403 static void |
61 | 1404 machinop(int e1) |
1405 { | |
240 | 1406 int e2,e3,op; |
61 | 1407 |
1408 e2 = cadr(e1); | |
1409 op = car(e1); | |
1410 e3 = caddr(e1); | |
240 | 1411 if (code_const_op_p(op,e3)) { |
189 | 1412 g_expr(e2); |
240 | 1413 oprtc(op,USE_CREG,e3); |
189 | 1414 return; |
1415 } | |
61 | 1416 g_expr(e3); |
1417 emit_push(); | |
1418 g_expr(e2); | |
221 | 1419 tosop(op,USE_CREG,(e2=pop_register())); |
61 | 1420 emit_pop_free(e2); |
1421 return; | |
1422 } | |
1423 | |
195 | 1424 #if FLOAT_CODE |
327 | 1425 static void |
133 | 1426 dmachinop(int e1,int d) |
81 | 1427 { |
1428 int e2,e3,op; | |
1429 | |
1430 e2 = cadr(e1); | |
1431 op = car(e1); | |
1432 e3 = caddr(e1); | |
1433 g_expr(e3); | |
133 | 1434 emit_dpush(d); |
81 | 1435 g_expr(e2); |
221 | 1436 dtosop(car(e1),USE_CREG,(e2=emit_dpop(d))); |
138 | 1437 emit_dpop_free(e2,d); |
81 | 1438 return; |
1439 } | |
195 | 1440 #endif |
1441 | |
1442 #if LONGLONG_CODE | |
327 | 1443 static void |
195 | 1444 lmachinop(int e1) |
1445 { | |
1446 int e2,e3,op; | |
1447 | |
1448 e2 = cadr(e1); | |
1449 op = car(e1); | |
1450 e3 = caddr(e1); | |
213 | 1451 if (code_lconst_op_p(op,e3)) { |
1452 g_expr(e2); | |
221 | 1453 loprtc(op,USE_CREG,e3); |
213 | 1454 return; |
1455 } | |
195 | 1456 g_expr(e3); |
1457 emit_lpush(); | |
1458 g_expr(e2); | |
221 | 1459 ltosop(car(e1),USE_CREG,(e2=emit_lpop())); |
195 | 1460 emit_lpop_free(e2); |
1461 return; | |
1462 } | |
1463 #endif | |
81 | 1464 |
327 | 1465 static void |
61 | 1466 sassign(int e1) |
1467 { | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
256
diff
changeset
|
1468 int e2,e3,e4,sz,xreg,det,offset; |
61 | 1469 |
1470 /* structure assignment */ | |
1471 e2 = cadr(e1); /* pointer variable to the struct */ | |
1472 e3 = cadr(e2); /* offset of the variable (distination) */ | |
1473 e4 = caddr(e1); /* right value (source) */ | |
1474 sz = cadddr(e1); /* size of struct or union */ | |
416 | 1475 if (car(e4)==RSTRUCT) { |
1476 e4 = cadr(e4); | |
1477 } | |
424 | 1478 if (is_same_type(e2,e4)) { |
1479 if (cadr(e2)==cadr(e4)) { | |
1480 if (use) g_expr(e4); | |
1481 return; | |
1482 } | |
269 | 1483 } |
61 | 1484 g_expr(e4); |
1485 emit_push(); | |
1486 g_expr(e2); | |
1487 xreg = emit_pop(0); | |
1488 /* ����Ū�ˤϥ��ԡ��Υ����Х�åפξ����ϼ¹Ի��ˤ����狼��ʤ� */ | |
1489 /* ���������狼����⤢�� */ | |
1490 if (is_same_type(e2,e4)) { | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
256
diff
changeset
|
1491 if(cadr(e2)<cadr(e4)) { offset=sz; sz=-sz;} |
417 | 1492 else offset=0; |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
256
diff
changeset
|
1493 det=1; |
61 | 1494 } else { |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
256
diff
changeset
|
1495 det = 0; offset=0; |
61 | 1496 } |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
256
diff
changeset
|
1497 emit_copy(xreg,USE_CREG,sz,offset,1,det); |
61 | 1498 emit_pop_free(xreg); |
1499 return; | |
1500 } | |
1501 | |
269 | 1502 static void |
118 | 1503 assign_opt(int e5,int e2,int e4,int byte) |
1504 { | |
1505 int reg; | |
1506 /* e2=e4 */ | |
1507 if (e5==REGISTER) { | |
1508 reg = cadr(e4); | |
1509 switch(car(e2)) { | |
1510 case GVAR: code_assign_gvar(e2,reg,byte); return; | |
119 | 1511 case LVAR: code_assign_lvar(cadr(e2),reg,byte); return; |
118 | 1512 case REGISTER: code_assign_register(cadr(e2),byte,reg); return; |
1513 } | |
1514 g_expr(e2); | |
233 | 1515 code_assign(USE_CREG,byte,reg); |
118 | 1516 return; |
1517 } | |
1518 /* e2 is register now */ | |
1519 if (car(e2)!=REGISTER) error(-1); | |
1520 reg = cadr(e2); | |
1521 switch(e5) { | |
162 | 1522 case CRGVAR: |
165 | 1523 case CURGVAR: code_crgvar(e4,reg,e5==CRGVAR,1); return; |
1524 case SRGVAR: | |
1525 case SURGVAR: code_crgvar(e4,reg,e5==SRGVAR,size_of_short); return; | |
437 | 1526 case RGVAR: case URGVAR: code_rgvar(e4,reg); return; |
162 | 1527 case CRLVAR: |
165 | 1528 case CURLVAR: code_crlvar(cadr(e4),reg,e5==CRLVAR,1); return; |
1529 case SRLVAR: | |
1530 case SURLVAR: code_crlvar(cadr(e4),reg,e5==SRLVAR,size_of_short); return; | |
437 | 1531 case RLVAR: case URLVAR: code_rlvar(cadr(e4),reg); return; |
329 | 1532 case GVAR: code_gvar(e4,reg); return; |
1533 case LVAR: code_lvar(cadr(e4),reg); return; | |
1534 case CONST: code_const(cadr(e4),reg); return; | |
118 | 1535 case ADDRESS: |
1536 if (car(cadr(e4))==STRING) code_string(cadr(e4),reg); | |
1537 else code_gvar(cadr(e4),reg); | |
1538 return; | |
329 | 1539 case FNAME: code_fname((NMTBL*)cadr(e4),reg); return; |
1540 case STRING: code_string(e4,reg); return; | |
135 | 1541 default: error(-1); |
118 | 1542 } |
1543 } | |
1544 | |
327 | 1545 static void |
61 | 1546 assign(int e1) |
1547 { | |
118 | 1548 int e2,e4,byte,e5; |
61 | 1549 |
166 | 1550 byte=(car(e1) == CASS)?1:(car(e1) == SASS)?size_of_short:0; |
61 | 1551 /* e2=e4 */ |
1552 e2 = cadr(e1); | |
118 | 1553 e4 = caddr(e1);e5=car(e4); |
269 | 1554 if (is_same_type(e2,e4)&&cadr(e2)==cadr(e4)) { |
1555 if (use) g_expr(e4); | |
1556 return; | |
1557 } | |
342 | 1558 if (!use) { |
1559 if (e5==REGISTER) { | |
1560 assign_opt(e5,e2,e4,byte); | |
1561 return; | |
1562 } else if (car(e2)==REGISTER) { | |
1563 switch(e5) { | |
1564 case ADDRESS: | |
1565 if (!((car(cadr(e4))==STRING) || car(cadr(e4))==GVAR)) | |
1566 break; | |
1567 case CRGVAR : case CRLVAR : case RGVAR : case RLVAR : | |
437 | 1568 case URGVAR : case URLVAR : |
342 | 1569 case CURGVAR : case CURLVAR : |
1570 case SURGVAR : case SURLVAR : | |
1571 case GVAR : case LVAR : | |
1572 case CONST : case FNAME : case STRING : | |
1573 assign_opt(e5,e2,e4,byte); | |
1574 return; | |
1575 } | |
1576 } | |
118 | 1577 } |
61 | 1578 switch(car(e2)) { |
1579 case GVAR: /* i=3 */ | |
1580 g_expr(e4); | |
221 | 1581 code_assign_gvar(e2,USE_CREG,byte); |
61 | 1582 return; |
1583 case LVAR: | |
1584 g_expr(e4); | |
221 | 1585 code_assign_lvar(cadr(e2),USE_CREG,byte); |
61 | 1586 return; |
1587 case REGISTER: | |
1588 g_expr(e4); | |
221 | 1589 code_assign_register(cadr(e2),byte,USE_CREG); |
61 | 1590 return; |
1591 } | |
1592 g_expr(e2); | |
1593 emit_push(); | |
1594 g_expr(e4); | |
1595 e2 = emit_pop(0); | |
221 | 1596 code_assign(e2,byte,USE_CREG); |
61 | 1597 emit_pop_free(e2); |
1598 return; | |
1599 } | |
1600 | |
195 | 1601 #if FLOAT_CODE |
1602 | |
269 | 1603 static void |
118 | 1604 dassign_opt(int e5,int e2,int e4,int d) |
1605 { | |
1606 int reg; | |
1607 /* e2=e4 */ | |
138 | 1608 if (e5==DREGISTER||e5==FREGISTER) { |
118 | 1609 reg = cadr(e4); |
1610 switch(car(e2)) { | |
1611 case GVAR: /* i=3 */ | |
1612 code_dassign_gvar(e2,reg,d); | |
1613 return; | |
1614 case LVAR: | |
119 | 1615 code_dassign_lvar(cadr(e2),reg,d); |
118 | 1616 return; |
1617 case DREGISTER: | |
138 | 1618 case FREGISTER: |
118 | 1619 if (reg!=cadr(e2)) |
138 | 1620 code_dassign_dregister(cadr(e2),d,reg); |
118 | 1621 return; |
135 | 1622 default: |
1623 error(-1); | |
118 | 1624 } |
1625 } | |
1626 /* e2 is register now */ | |
138 | 1627 if (car(e2)!=DREGISTER && car(e2)!=FREGISTER) error(-1); |
118 | 1628 reg = cadr(e2); |
1629 switch(e5) { | |
135 | 1630 case FRGVAR: |
118 | 1631 case DRGVAR: code_drgvar(e4,d,reg); return; |
135 | 1632 case FRLVAR: |
119 | 1633 case DRLVAR: code_drlvar(cadr(e4),d,reg); return; |
135 | 1634 case FCONST: |
264 | 1635 case DCONST: code_dconst(e4,reg,d); return; |
135 | 1636 default: |
118 | 1637 error(-1); |
1638 } | |
1639 } | |
1640 | |
327 | 1641 static void |
81 | 1642 dassign(int e1) |
1643 { | |
118 | 1644 int e2,e3,e4,d,e5; |
81 | 1645 |
1646 /* e2=e4 */ | |
1647 e2 = cadr(e1); | |
1648 e3 = cadr(e2); | |
118 | 1649 e4 = caddr(e1); e5=car(e4); |
269 | 1650 if (is_same_type(e2,e4)&&cadr(e2)==cadr(e4)) { |
1651 if (use) g_expr(e4); | |
1652 return; | |
1653 } | |
249 | 1654 if (car(e1)==DASS) d=1; |
1655 else if (car(e1)==FASS) d=0; | |
1656 else error(-1); | |
342 | 1657 if (!use) { |
1658 switch(e5) { | |
1659 case DRGVAR: case DRLVAR: case DCONST: | |
1660 if (car(e2)!=DREGISTER) break; | |
1661 dassign_opt(e5,e2,e4,d); return; | |
1662 case FRGVAR: case FRLVAR: case FCONST: | |
1663 if (car(e2)!=FREGISTER) break; | |
1664 case DREGISTER: case FREGISTER: | |
1665 dassign_opt(e5,e2,e4,d); return; | |
1666 } | |
118 | 1667 } |
81 | 1668 switch(car(e2)) { |
82 | 1669 case GVAR: |
81 | 1670 g_expr(e4); |
221 | 1671 code_dassign_gvar(e2,USE_CREG,d); |
81 | 1672 return; |
1673 case LVAR: | |
1674 g_expr(e4); | |
221 | 1675 code_dassign_lvar(cadr(e2),USE_CREG,d); |
81 | 1676 return; |
111 | 1677 case DREGISTER: |
138 | 1678 case FREGISTER: |
111 | 1679 g_expr(e4); |
221 | 1680 code_dassign_dregister(cadr(e2),d,USE_CREG); |
111 | 1681 return; |
81 | 1682 } |
1683 g_expr(e2); | |
82 | 1684 emit_push(); |
81 | 1685 g_expr(e4); |
82 | 1686 e2 = emit_pop(0); |
221 | 1687 code_dassign(e2,USE_CREG,d); |
82 | 1688 emit_pop_free(e2); |
81 | 1689 return; |
1690 } | |
1691 | |
195 | 1692 #endif |
1693 | |
1694 #if LONGLONG_CODE | |
1695 | |
327 | 1696 static void |
195 | 1697 lassign_opt(int e5,int e2,int e4) |
1698 { | |
1699 int reg; | |
1700 /* e2=e4 */ | |
1701 if (e5==LREGISTER) { | |
1702 reg = cadr(e4); | |
1703 switch(car(e2)) { | |
1704 case GVAR: /* i=3 */ | |
1705 code_lassign_gvar(e2,reg); | |
1706 return; | |
1707 case LVAR: | |
1708 code_lassign_lvar(cadr(e2),reg); | |
1709 return; | |
1710 case LREGISTER: | |
1711 if (reg!=cadr(e2)) | |
1712 code_lassign_lregister(cadr(e2),reg); | |
1713 return; | |
1714 default: | |
1715 error(-1); | |
1716 } | |
1717 } | |
1718 /* e2 is register now */ | |
1719 if (car(e2)!=LREGISTER) error(-1); | |
1720 reg = cadr(e2); | |
1721 switch(e5) { | |
437 | 1722 case LRGVAR: case LURGVAR: code_lrgvar(e4,reg); return; |
1723 case LRLVAR: case LURLVAR: code_lrlvar(cadr(e4),reg); return; | |
195 | 1724 case LCONST: code_lconst(e4,reg); return; |
1725 default: | |
1726 error(-1); | |
1727 } | |
1728 } | |
1729 | |
327 | 1730 static void |
195 | 1731 lassign(int e1) |
1732 { | |
1733 int e2,e3,e4,e5; | |
1734 | |
1735 /* e2=e4 */ | |
1736 e2 = cadr(e1); | |
1737 e3 = cadr(e2); | |
1738 e4 = caddr(e1); e5=car(e4); | |
269 | 1739 if (is_same_type(e2,e4)&&cadr(e2)==cadr(e4)) { |
1740 if (use) g_expr(e4); | |
1741 return; | |
1742 } | |
195 | 1743 if (!use && ( |
437 | 1744 (e5==LREGISTER &&(car(e2)==GVAR||car(e2)==LVAR||car(e2)==LREGISTER)) || |
1745 (car(e2)==LREGISTER&& | |
1746 (e5==LRGVAR||e5==LRLVAR||e5==LURLVAR||e5==LURGVAR||e5==LCONST)) | |
195 | 1747 )) { |
1748 lassign_opt(e5,e2,e4); | |
1749 return; | |
1750 } | |
1751 switch(car(e2)) { | |
1752 case GVAR: | |
1753 g_expr(e4); | |
221 | 1754 code_lassign_gvar(e2,USE_CREG); |
195 | 1755 return; |
1756 case LVAR: | |
1757 g_expr(e4); | |
221 | 1758 code_lassign_lvar(cadr(e2),USE_CREG); |
195 | 1759 return; |
1760 case LREGISTER: | |
437 | 1761 g_expr(e4); |
221 | 1762 code_lassign_lregister(cadr(e2),USE_CREG); |
437 | 1763 return; |
195 | 1764 } |
1765 g_expr(e2); | |
219 | 1766 emit_push(); |
195 | 1767 g_expr(e4); |
219 | 1768 e2 = emit_pop(0); |
221 | 1769 code_lassign(e2,USE_CREG); |
219 | 1770 emit_pop_free(e2); |
195 | 1771 return; |
1772 } | |
1773 | |
1774 #endif | |
1775 | |
327 | 1776 /* numerical type conversion */ |
1777 | |
440 | 1778 #if FLOAT_CODE |
327 | 1779 static int |
334 | 1780 double_value(int e2) |
327 | 1781 { |
334 | 1782 if (type>0&&car(type)==BIT_FIELD) e2=rvalue(e2); |
342 | 1783 switch(car(e2)) { |
1784 case LCONST: | |
334 | 1785 #if LONGLONG_CODE |
342 | 1786 e2 = dlist2(DCONST,(double)lcadr(e2)); break; |
334 | 1787 #endif |
342 | 1788 case CONST: |
1789 e2 = dlist2(DCONST,(double)cadr(e2)); break; | |
1790 case FCONST: | |
1791 e2 = dlist2(DCONST,dcadr(e2)); break; | |
1792 default: | |
1793 switch(type) { | |
1794 case DOUBLE: break; | |
1795 case FLOAT: e2 = list3(CONV,rvalue(e2),F2D); break; | |
1796 case UNSIGNED: e2 = list3(CONV,rvalue(e2),U2D); break; | |
1797 case LONGLONG: e2 = list3(CONV,rvalue(e2),LL2D); break; | |
1798 case ULONGLONG: e2 = list3(CONV,rvalue(e2),ULL2D); break; | |
1799 default: | |
1800 if(integral(type)) e2 = list3(CONV,rvalue(e2),I2D); | |
1801 else { error(TYERR); e2 = dlist2(DCONST,1.0); } | |
1802 } | |
1803 } | |
334 | 1804 type = DOUBLE; |
1805 return e2; | |
327 | 1806 } |
1807 | |
1808 static int | |
334 | 1809 float_value(int e2) |
327 | 1810 { |
334 | 1811 if (type>0&&car(type)==BIT_FIELD) e2=rvalue(e2); |
1812 if (0) ; | |
327 | 1813 #if LONGLONG_CODE |
334 | 1814 else if (car(e2)==LCONST) e2 = dlist2(FCONST,(double)lcadr(e2)); |
327 | 1815 #endif |
334 | 1816 else if (car(e2)==CONST) e2 = dlist2(FCONST,(double)cadr(e2)); |
1817 else if (car(e2)==DCONST) e2 = dlist2(FCONST,dcadr(e2)); | |
342 | 1818 else { |
1819 switch(type) { | |
1820 case LONGLONG: e2 = list3(CONV,rvalue(e2),LL2F); break; | |
1821 case ULONGLONG: e2 = list3(CONV,rvalue(e2),ULL2F); break; | |
1822 case FLOAT: break; | |
1823 case DOUBLE: e2 = list3(CONV,rvalue(e2),D2F); break; | |
1824 case UNSIGNED: e2 = list3(CONV,rvalue(e2),U2F); break; | |
1825 default: | |
1826 if(integral(type)) e2 = list3(CONV,rvalue(e2),I2F); | |
1827 else { error(TYERR); e2 = dlist2(DCONST,1.0); } | |
1828 } | |
1829 } | |
334 | 1830 type = FLOAT; |
1831 return e2; | |
327 | 1832 } |
440 | 1833 #endif |
327 | 1834 |
440 | 1835 #if LONGLONG_CODE |
327 | 1836 static int |
334 | 1837 longlong_value(int e2) |
327 | 1838 { |
334 | 1839 if (type>0&&car(type)==BIT_FIELD) e2=rvalue(e2); |
1840 if (0) ; | |
1841 else if (car(e2)==CONST) e2 = llist2(LCONST,(long long)cadr(e2)); | |
1842 else if (car(e2)==LCONST) ; | |
327 | 1843 #if FLOAT_CODE |
334 | 1844 else if (car(e2)==DCONST||car(e2)==FCONST) |
1845 e2 = llist2(LCONST,(long long)dcadr(e2)); | |
327 | 1846 #endif |
342 | 1847 else { |
1848 switch(type) { | |
1849 case FLOAT: e2 = list3(CONV,rvalue(e2),F2LL); break; | |
1850 case DOUBLE: e2 = list3(CONV,rvalue(e2),D2LL); break; | |
1851 case UNSIGNED: e2 = list3(CONV,rvalue(e2),U2LL); break; | |
1852 case LONGLONG: break; | |
1853 case ULONGLONG: break; | |
1854 default: | |
1855 if(integral(type)) e2 = list3(CONV,rvalue(e2),I2LL); | |
1856 else { error(TYERR); e2 = llist2(LCONST,0LL); } | |
1857 } | |
1858 } | |
334 | 1859 type = LONGLONG; |
1860 return e2; | |
327 | 1861 } |
1862 | |
1863 static int | |
334 | 1864 ulonglong_value(int e2) |
327 | 1865 { |
334 | 1866 if (type>0&&car(type)==BIT_FIELD) e2=rvalue(e2); |
1867 if (0); | |
1868 else if (car(e2)==CONST) e2 = llist2(LCONST,(unsigned long long)cadr(e2)); | |
1869 else if (car(e2)==LCONST) ; | |
327 | 1870 #if FLOAT_CODE |
334 | 1871 else if (car(e2)==DCONST||car(e2)==FCONST) |
1872 e2 = llist2(LCONST,(unsigned long long)dcadr(e2)); | |
327 | 1873 #endif |
342 | 1874 else { |
1875 switch(type) { | |
1876 case FLOAT: e2 = list3(CONV,rvalue(e2),F2ULL); break; | |
1877 case DOUBLE: e2 = list3(CONV,rvalue(e2),D2ULL); break; | |
1878 case UNSIGNED: e2 = list3(CONV,rvalue(e2),U2ULL); break; | |
1879 case LONGLONG: break; | |
1880 case ULONGLONG: break; | |
1881 default: | |
1882 if(integral(type)) e2 = list3(CONV,rvalue(e2),I2ULL); | |
1883 else { error(TYERR); e2 = llist2(LCONST,0LL); } | |
1884 } | |
1885 } | |
334 | 1886 type = ULONGLONG; |
1887 return e2; | |
327 | 1888 } |
440 | 1889 #endif |
327 | 1890 |
1891 static int | |
334 | 1892 int_value(int e2) |
327 | 1893 { |
334 | 1894 if (type>0&&car(type)==BIT_FIELD) e2=rvalue(e2); |
1895 if (0); | |
342 | 1896 else if(type>0&&car(type)==ARRAY) return e2; |
334 | 1897 else if(scalar(type)) return e2; |
327 | 1898 #if FLOAT_CODE |
334 | 1899 else if (car(e2)==DCONST||car(e2)==FCONST) e2 = list2(CONST,(int)dcadr(e2)); |
327 | 1900 #endif |
1901 #if LONGLONG_CODE | |
334 | 1902 else if (car(e2)==LCONST) e2 = list2(CONST,(int)lcadr(e2)); |
327 | 1903 #endif |
342 | 1904 else { |
1905 switch(type) { | |
1906 case FLOAT: e2 = list3(CONV,rvalue(e2),F2I); break; | |
1907 case DOUBLE: e2 = list3(CONV,rvalue(e2),D2I); break; | |
1908 case LONGLONG: e2 = list3(CONV,rvalue(e2),LL2I); break; | |
1909 case ULONGLONG: e2 = list3(CONV,rvalue(e2),ULL2I); break; | |
1910 default: | |
1911 error(TYERR); e2 = list2(CONST,1); | |
1912 } | |
1913 } | |
334 | 1914 type = INT; |
1915 return e2; | |
327 | 1916 } |
1917 | |
1918 static int | |
353 | 1919 char_value(int e2) |
1920 { | |
370 | 1921 if (type!=CHAR&&type!=INT) { |
353 | 1922 e2 = list3(CONV,int_value(rvalue(e2)),I2C); type = INT; |
1923 } | |
1924 return e2; | |
1925 } | |
1926 | |
1927 static int | |
1928 short_value(int e2) | |
1929 { | |
370 | 1930 if (type!=SHORT&&type!=INT) { |
353 | 1931 e2 = list3(CONV,int_value(rvalue(e2)),I2S); type = INT; |
1932 } | |
1933 return e2; | |
1934 } | |
1935 | |
1936 static int | |
334 | 1937 unsigned_value(int e2) |
327 | 1938 { |
334 | 1939 if (type>0&&car(type)==BIT_FIELD) e2=rvalue(e2); |
342 | 1940 else if(type>0&&car(type)==ARRAY) return e2; |
334 | 1941 if (0); |
1942 else if(scalar(type)) return e2; | |
327 | 1943 #if FLOAT_CODE |
334 | 1944 else if (car(e2)==DCONST||car(e2)==FCONST) e2 = list2(CONST,(int)dcadr(e2)); |
327 | 1945 #endif |
1946 #if LONGLONG_CODE | |
342 | 1947 else if (car(e2)==LCONST) e2 = list2(CONST,(unsigned)lcadr(e2)); |
327 | 1948 #endif |
342 | 1949 else { |
1950 switch(type) { | |
1951 case LONGLONG: e2 = list3(CONV,rvalue(e2),LL2U); break; | |
1952 case ULONGLONG: e2 = list3(CONV,rvalue(e2),ULL2U); break; | |
1953 case FLOAT: e2 = list3(CONV,rvalue(e2),F2U); break; | |
1954 case DOUBLE: e2 = list3(CONV,rvalue(e2),D2U); break; | |
1955 default: | |
1956 error(TYERR); | |
1957 } | |
1958 } | |
334 | 1959 type = UNSIGNED; |
1960 return e2; | |
327 | 1961 } |
1962 | |
353 | 1963 static int |
1964 uchar_value(int e2) | |
1965 { | |
370 | 1966 if (type!=UCHAR&&type!=UNSIGNED) { |
353 | 1967 e2 = list3(CONV,unsigned_value(rvalue(e2)),U2UC); type = UNSIGNED; |
1968 } | |
1969 return e2; | |
1970 } | |
1971 | |
1972 static int | |
1973 ushort_value(int e2) | |
1974 { | |
370 | 1975 if (type!=USHORT&&type!=UNSIGNED) { |
353 | 1976 e2 = list3(CONV,unsigned_value(rvalue(e2)),U2US); type = UNSIGNED; |
1977 } | |
1978 return e2; | |
1979 } | |
1980 | |
327 | 1981 /* assign statement */ |
1982 | |
1983 /* keep type */ | |
1984 | |
1985 extern int | |
1986 assign_expr0(int e1,int e2,int t,int type0) { | |
1987 int stype; | |
1988 stype=type; | |
1989 type = type0; | |
1990 e2 = rvalue(e2); | |
331 | 1991 e1=assign_expr(e1,e2,t); |
327 | 1992 type=stype; |
1993 return e1; | |
1994 } | |
1995 | |
1996 | |
1997 | |
1998 /* with conversion (will destroy type global variable) */ | |
1999 | |
2000 extern int | |
331 | 2001 assign_expr(int e1,int e2,int t) { |
342 | 2002 switch(t) { |
2003 case VOID: | |
2004 break; | |
2005 case CHAR:case UCHAR: | |
334 | 2006 e2=(t==UCHAR)?unsigned_value(e2):int_value(e2); |
2007 return(list3(CASS,e1,e2)); | |
342 | 2008 case SHORT:case USHORT: |
334 | 2009 e2=(t==USHORT)?unsigned_value(e2):int_value(e2); |
2010 return(list3(SASS,e1,e2)); | |
327 | 2011 #if FLOAT_CODE |
342 | 2012 case DOUBLE: |
334 | 2013 e2=double_value(e2); |
2014 return(list3(DASS,e1,e2)); | |
342 | 2015 case FLOAT: |
334 | 2016 e2=float_value(e2); |
2017 return(list3(FASS,e1,e2)); | |
327 | 2018 #endif |
2019 #if LONGLONG_CODE | |
342 | 2020 case LONGLONG: |
334 | 2021 e2=longlong_value(e2); |
2022 return(list3(LASS,e1,e2)); | |
342 | 2023 case ULONGLONG: |
334 | 2024 e2=ulonglong_value(e2); |
2025 return(list3(LASS,e1,e2)); | |
327 | 2026 #endif |
342 | 2027 default: |
2028 if(scalar(t)) { | |
2029 e2=(t==UNSIGNED)?unsigned_value(e2):int_value(e2); | |
2030 return(list3(ASS,e1,e2)); | |
2031 } | |
2032 switch(car(t)) { | |
2033 case BIT_FIELD: | |
420 | 2034 // type = list4(BIT_FIELD,type, |
426 | 2035 // list3(type /*store type*/,0 /*bit offset*/,bitsize)); |
421 | 2036 e2 = correct_type(e2,cadr(t)); /* value type */ |
342 | 2037 return(list4(BASS,e1,e2,list2(BASS,t))); |
2038 case STRUCT:case UNION: | |
2039 if (size(t)!=size(type)) error(TYERR); | |
2040 type=t; | |
2041 if(car(e2)==RSTRUCT && car(cadr(e2))==FUNCTION) { | |
2042 replace_return_struct(cadr(e2),e1); | |
2043 return cadr(e2); | |
2044 } else { | |
2045 return (list4(STASS,e1,e2,size(t))); | |
2046 } | |
2047 } | |
327 | 2048 } |
342 | 2049 error(TYERR); return list3(ASS,e1,e2); |
327 | 2050 } |
2051 | |
2052 extern int | |
2053 cond(int t,int e1,int e2,int e3) | |
2054 { | |
2055 if(car(e1)==CONST) { | |
388 | 2056 if(cadr(e1)) {type=t;return e2?e2:e1;} else return e3; |
327 | 2057 } |
2058 #if FLOAT_CODE | |
388 | 2059 if(car(e1)==DCONST) { |
2060 if(dcadr(e1)) {type=t;return e2?e2:e1;} else return e3; | |
2061 } | |
327 | 2062 if(type==DOUBLE||t==DOUBLE) { |
334 | 2063 e3=double_value(e3); |
355 | 2064 type = t; if (e2) e2=double_value(e2); |
327 | 2065 return(list4(DCOND,e1,e2,e3)); |
2066 } | |
2067 if(type==FLOAT||t==FLOAT) { | |
334 | 2068 e3=float_value(e3); |
355 | 2069 type = t; if (e2) e2=float_value(e2); |
327 | 2070 return(list4(FCOND,e1,e2,e3)); |
2071 } | |
2072 #endif | |
2073 #if LONGLONG_CODE | |
388 | 2074 if(car(e1)==LCONST) { |
2075 if(lcadr(e1)) {type=t;return e2?e2:e1;} else return e3; | |
2076 } | |
327 | 2077 if(type==LONGLONG||t==LONGLONG) { |
334 | 2078 e3=longlong_value(e3); |
355 | 2079 type = t; if (e2) e2=longlong_value(e2); |
327 | 2080 return(list4(LCOND,e1,e2,e3)); |
2081 } | |
2082 if(type==ULONGLONG||t==ULONGLONG) { | |
334 | 2083 e3=ulonglong_value(e3); |
355 | 2084 type = t; if (e2) e2=ulonglong_value(e2); |
327 | 2085 return(list4(LCOND,e1,e2,e3)); |
2086 } | |
2087 #endif | |
2088 if(type==INT||(t!=INT&&type==UNSIGNED)) | |
2089 type=t; | |
2090 /* if (t!=type) error(TYERR); */ | |
2091 return(list4(COND,e1,e2,e3)); | |
2092 } | |
2093 | |
2094 extern int | |
2095 assop(int e1,int e2,int op,int t,int no_float) | |
2096 { | |
342 | 2097 int ass,u = 0; |
327 | 2098 if(!(integral(type)||type==FLOAT||type==DOUBLE|| |
2099 type==LONGLONG||type==ULONGLONG | |
2100 )) error(TYERR); | |
342 | 2101 switch(t) { |
327 | 2102 #if FLOAT_CODE |
342 | 2103 case FLOAT: |
327 | 2104 if (no_float) error(TYERR); |
334 | 2105 e2=float_value(e2); |
327 | 2106 return(list4(FASSOP,e1,e2,op+FOP)); |
342 | 2107 case DOUBLE: |
327 | 2108 if (no_float) error(TYERR); |
334 | 2109 e2=double_value(e2); |
327 | 2110 return(list4(DASSOP,e1,e2,op+DOP)); |
2111 #endif | |
2112 #if LONGLONG_CODE | |
342 | 2113 case LONGLONG: |
334 | 2114 e2=longlong_value(e2); |
327 | 2115 return(list4(LASSOP,e1,e2,op+LOP)); |
342 | 2116 case ULONGLONG: |
334 | 2117 e2=ulonglong_value(e2); |
327 | 2118 return(list4(LASSOP,e1,e2,op+LOP+((op==MUL+AS||op==DIV+AS)?US:0))); |
2119 #endif | |
342 | 2120 case CHAR: |
2121 type= INT; ass = CASSOP; break; | |
2122 case SHORT: | |
2123 type= INT; ass = SASSOP; break; | |
2124 case INT: | |
2125 type= INT; ass = ASSOP; break; | |
2126 case UCHAR: | |
2127 type= UNSIGNED; ass = CUASSOP; u=1; break; | |
2128 case USHORT: | |
2129 type= UNSIGNED; ass = SUASSOP; u=1; break; | |
2130 case UNSIGNED: | |
2131 type= UNSIGNED; ass = ASSOP; u=1; break; | |
2132 default: | |
2133 if (t>0 && car(t)==BIT_FIELD) { | |
420 | 2134 // type = list4(BIT_FIELD,type, |
2135 // list3(type /*store type*/,0 /*bit offset*/,symval)); | |
2136 e2 = correct_type(e2,car(caddr(t))); /* store type */ | |
2137 type = cadr(t); /* value type */ | |
342 | 2138 return(list4(BASSOP,e1,e2,list2(op,t))); |
2139 } | |
327 | 2140 } |
342 | 2141 if (u) { |
2142 if (op==RSHIFT||op==LSHIFT) op=op+US; | |
2143 else { | |
2144 switch(type) { | |
2145 case UCHAR: case USHORT: case UNSIGNED: | |
2146 if (op==MUL||op==DIV||op==MOD) op=op+US; | |
2147 } | |
2148 } | |
327 | 2149 } |
2150 type=t; | |
342 | 2151 if(integral(t)) return(list4(ass,e1,e2,op)); |
327 | 2152 /* pointer += ... */ |
2153 if((op!=ADD&&op!=SUB)||car(t)!=POINTER) error(TYERR); | |
2154 e2=binop(MUL,e2,list2(CONST,size(cadr(t))),INT,UNSIGNED); | |
2155 type=t; | |
2156 | |
2157 return list4(ASSOP,e1,e2,op); | |
2158 } | |
2159 | |
2160 | |
2161 | |
2162 static void | |
2163 iassop(int e1) | |
61 | 2164 { |
165 | 2165 int e2,e3,byte,op,sign,size; |
255 | 2166 int n,t; |
61 | 2167 |
2168 /* e2 op= e3 */ | |
342 | 2169 switch(car(e1)) { |
2170 case CUASSOP: byte = 1; sign = 0; size = 1; break; | |
2171 case CASSOP: byte = 1; sign = 1; size = 1; break; | |
2172 case SUASSOP: byte = size_of_short; sign = 0; size = size_of_short; break; | |
2173 case SASSOP: byte = size_of_short; sign = 1; size = size_of_short; break; | |
2174 default: byte = 0; sign = 1; size = size_of_int; | |
162 | 2175 } |
61 | 2176 e2 = cadr(e1); |
2177 if (car(e2)==INDIRECT) e2=cadr(e2); | |
2178 e3 = caddr(e1); | |
2179 op = cadddr(e1); | |
2180 | |
285 | 2181 if (car(e2)==REGISTER) { |
2182 if (code_const_op_p(op,e3)) { | |
2183 oprtc(op,cadr(e2),e3); | |
2184 } else { | |
2185 g_expr(e3); | |
2186 code_register_assop(cadr(e2),USE_CREG,op,byte); | |
2187 } | |
2188 if (use) { | |
2189 code_register(cadr(e2),USE_CREG); | |
2190 } | |
2191 return; | |
2192 } | |
255 | 2193 if (car(e3)==CONST) { |
2194 /* e2 = e2 op e3; */ | |
2195 t = sign?INT:UNSIGNED; | |
285 | 2196 // oprtc expected |
2197 if (car(e2)==LVAR||car(e2)==GVAR) { | |
255 | 2198 g_expr(assign_expr0(e2,list3(op,rvalue_t(e2,t),e3),t,t)); |
2199 return; | |
2200 } | |
2201 /* new = &e2 */ | |
2202 /* *new = *new op e3 */ | |
445 | 2203 n = list3(LVAR,new_lvar(size_of_int),0); |
255 | 2204 g_expr_u(assign_expr0(n,list2(ADDRESS,e2),INT,INT)); |
2205 g_expr(assign_expr0(list2(INDIRECT,n),list3(op,n,e3),t,t)); | |
2206 free_lvar(cadr(n)); | |
2207 return; | |
2208 } | |
61 | 2209 g_expr(e3); |
2210 emit_push(); | |
2211 g_expr(e2); | |
221 | 2212 code_assop(op,USE_CREG,byte,sign); |
61 | 2213 return; |
2214 } | |
2215 | |
195 | 2216 #if FLOAT_CODE |
2217 | |
327 | 2218 static void |
81 | 2219 dassop(int e1) |
2220 { | |
83 | 2221 int e2,e3,op,d; |
81 | 2222 |
83 | 2223 /* e2 op= e3 */ |
2224 d = (car(e1) == DASSOP); | |
2225 e2 = cadr(e1); | |
2226 if (car(e2)==INDIRECT) e2=cadr(e2); | |
2227 e3 = caddr(e1); | |
2228 op = cadddr(e1); | |
2229 | |
2230 g_expr(e3); | |
144 | 2231 if (car(e2)==DREGISTER||car(e2)==FREGISTER) { |
273 | 2232 emit_dpush(d); |
219 | 2233 code_register_dassop(cadr(e2),op,d); |
273 | 2234 if (use) |
2235 code_dregister(cadr(e2),USE_CREG,d); | |
2236 return; | |
144 | 2237 } |
238 | 2238 emit_dpush(d); |
2239 g_expr(e2); | |
221 | 2240 code_dassop(op,USE_CREG,d); |
83 | 2241 return; |
81 | 2242 } |
61 | 2243 |
195 | 2244 #endif |
2245 | |
2246 #if LONGLONG_CODE | |
2247 | |
238 | 2248 static int |
2249 long_sign(int op) | |
2250 { | |
2251 return (op==LUDIV||op==LUMOD||op==LULSHIFT||op==LURSHIFT)?ULONGLONG:LONGLONG; | |
2252 } | |
2253 | |
327 | 2254 static void |
195 | 2255 lassop(int e1) |
2256 { | |
2257 int e2,e3,op; | |
238 | 2258 int n,t; |
195 | 2259 |
2260 /* e2 op= e3 */ | |
2261 e2 = cadr(e1); | |
2262 if (car(e2)==INDIRECT) e2=cadr(e2); | |
2263 e3 = caddr(e1); | |
2264 op = cadddr(e1); | |
2265 | |
286 | 2266 if (car(e2)==LREGISTER) { |
285 | 2267 if (code_lconst_op_p(op,e3)) { |
2268 loprtc(op,cadr(e2),e3); | |
286 | 2269 if (use) { |
2270 code_lregister(cadr(e2),USE_CREG); | |
2271 } | |
2272 return; | |
2273 } | |
2274 if (code_lassop_p) { | |
285 | 2275 g_expr(e3); |
2276 emit_lpush(); | |
2277 code_register_lassop(cadr(e2),op); | |
286 | 2278 if (use) { |
2279 code_lregister(cadr(e2),USE_CREG); | |
2280 } | |
2281 return; | |
285 | 2282 } |
2283 } | |
238 | 2284 if (!code_lassop_p||car(e3)==LCONST) { |
2285 /* e2 = e2 op e3; */ | |
2286 t = long_sign(op); | |
286 | 2287 if (car(e2)==LREGISTER||car(e2)==LVAR||car(e2)==GVAR) { |
238 | 2288 g_expr(assign_expr0(e2,list3(op,rvalue_t(e2,t),e3),t,t)); |
239 | 2289 return; |
238 | 2290 } |
2291 /* new = &e2 */ | |
2292 /* *new = *new op e3 */ | |
445 | 2293 n = list3(LVAR,new_lvar(size_of_int),0); |
239 | 2294 g_expr_u(assign_expr0(n,list2(ADDRESS,e2),INT,INT)); |
331 | 2295 g_expr(assign_expr0(list2(INDIRECT,n), |
2296 list3(op,list2(LRINDIRECT,n),e3),t,t)); | |
238 | 2297 free_lvar(cadr(n)); |
2298 return; | |
2299 } | |
2300 | |
195 | 2301 g_expr(e3); |
286 | 2302 if (car(e2)==LREGISTER) { |
2303 emit_lpush(); | |
2304 code_register_lassop(cadr(e2),op); | |
2305 if (use) | |
2306 code_lregister(cadr(e2),USE_CREG); | |
2307 return; | |
2308 } | |
238 | 2309 emit_lpush(); |
2310 g_expr(e2); | |
221 | 2311 code_lassop(op,USE_CREG); |
195 | 2312 return; |
2313 } | |
2314 | |
2315 #endif | |
2316 | |
327 | 2317 extern void |
287 | 2318 cmpdimm(int e, int csreg,int label,int cond) |
95 | 2319 { |
458 | 2320 if (!chk) { |
2321 if (car(csreg)==CONST) { | |
2322 switch(cond) { | |
2323 case 1: case 0: | |
2324 if (cond ^ (cadr(csreg)==e)) gen_jmp(label); | |
2325 break; | |
2326 case LT: | |
2327 if ((cadr(csreg)>e)) gen_jmp(label); | |
2328 break; | |
2329 } | |
2330 } else if (car(csreg)==REGISTER) { | |
2331 code_cmpdimm(e, cadr(csreg),label,cond); | |
2332 } else error(-1); | |
2333 } | |
95 | 2334 } |
2335 | |
327 | 2336 extern int |
95 | 2337 csvalue() |
2338 { | |
2339 return code_csvalue(); | |
2340 } | |
2341 | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
2342 extern void |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
2343 gen_ret() |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
2344 { |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
2345 if (chk) return; |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
2346 code_ret(); |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
2347 } |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
2348 |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
2349 extern void |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
2350 gen_label_call(int l) |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
2351 { |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
2352 if (chk) return; |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
2353 code_label_call(l); |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
2354 } |
95 | 2355 |
327 | 2356 extern int |
61 | 2357 fwdlabel(void) |
2358 { | |
2359 return labelno++; | |
2360 } | |
2361 | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
2362 static void |
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
2363 checkjmp(int l) |
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
2364 { |
442 | 2365 int p = pending_jmp; |
2366 pending_jmp = 0; | |
2367 if (p) { | |
2368 if (p!=l) { | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
2369 control=0; |
456 | 2370 if (!chk) |
2371 jmp(p); | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
2372 } |
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
2373 } |
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
2374 } |
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
2375 |
327 | 2376 extern void |
61 | 2377 fwddef(int l) |
2378 { | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
2379 if (l==0) return; |
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
2380 checkjmp(l); |
61 | 2381 control=1; |
66 | 2382 if (!chk) |
92 | 2383 code_label(l); |
61 | 2384 } |
2385 | |
327 | 2386 extern int |
61 | 2387 backdef(void) |
2388 { | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
2389 checkjmp(0); |
61 | 2390 control=1; |
66 | 2391 if (!chk) |
92 | 2392 code_label(labelno); |
61 | 2393 return labelno++; |
2394 } | |
2395 | |
327 | 2396 extern void |
61 | 2397 def_label(int cslabel, int dlabel) |
2398 { | |
2399 int fl; | |
2400 | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
2401 checkjmp(0); |
61 | 2402 fl = 0; |
2403 if (control) { | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
2404 gen_jmp(fl=fwdlabel()); |
61 | 2405 } |
2406 fwddef(cslabel); | |
2407 if (dlabel) | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
2408 gen_jmp(dlabel); |
61 | 2409 if (fl) { |
2410 fwddef(fl); | |
2411 } | |
2412 } | |
2413 | |
327 | 2414 extern void |
61 | 2415 ret(void) |
2416 { | |
456 | 2417 if (!chk) |
2418 code_set_return_register(1); | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
2419 gen_jmp(retlabel); |
61 | 2420 } |
2421 | |
327 | 2422 extern void |
66 | 2423 opening(char *filename) |
2424 { | |
2425 emit_init(); | |
2426 if (!chk) | |
2427 code_opening(filename); | |
2428 } | |
2429 | |
327 | 2430 extern void |
66 | 2431 closing() |
2432 { | |
453 | 2433 int e; |
2434 NMTBL *n; | |
2435 for(e=inline_funcs;e;e=cadr(e)) { | |
2436 n = (NMTBL*)car(e); | |
456 | 2437 if (1 || n->sc==EXTRN || n->sc==EXTRN1 || has_attr(n,FNAME)) { |
2438 // global or used as pointer | |
453 | 2439 pfdecl(n); |
456 | 2440 } |
453 | 2441 } |
66 | 2442 if (!chk) |
2443 code_closing(); | |
2444 } | |
2445 | |
327 | 2446 static int |
99 | 2447 contains_in_list(int e,int type) |
2448 { | |
2449 while(e) { | |
2450 if(contains(car(e),type)) return 1; | |
2451 e = cadr(e); | |
2452 } | |
2453 return 0; | |
2454 } | |
2455 | |
327 | 2456 static int |
99 | 2457 contains(int e,int type) |
2458 { | |
2459 while(e) { | |
2460 if (car(e)==type) return 1; | |
256
d80e6387c539
powerpc function call complex arugment pre computation.
kono
parents:
255
diff
changeset
|
2461 if (!car(e)) return 0; |
164 | 2462 if (LIST_ARGS(car(e))){ |
99 | 2463 /* list arguments */ |
2464 return contains_in_list(caddr(e),type); | |
164 | 2465 } else if (UNARY_ARGS(car(e))) { |
99 | 2466 /* unary operators */ |
2467 e = cadr(e); | |
2468 continue; | |
164 | 2469 } else if (BINARY_ARGS(car(e))) { |
99 | 2470 /* biary operators */ |
2471 if (contains(cadr(e),type)) return 1; | |
2472 e = caddr(e); | |
2473 continue; | |
164 | 2474 } else if (TARNARY_ARGS(car(e))) { |
99 | 2475 /* tarary operators */ |
2476 if (contains(cadr(e), type)) return 1; | |
2477 if (contains(caddr(e),type)) return 1; | |
2478 e = cadddr(e); | |
2479 continue; | |
164 | 2480 } else if (NULLARY_ARGS(car(e))) { |
135 | 2481 /* nullary operators */ |
2482 return 0; | |
164 | 2483 } else { |
327 | 2484 // fprintf(stderr,"Unknown Tree ID %d\n",car(e)); |
135 | 2485 error(-1); |
99 | 2486 return 0; |
2487 } | |
2488 } | |
2489 return 0; | |
2490 } | |
2491 | |
327 | 2492 static int |
223 | 2493 contains_in_list_p(int e,int (*p)(int)) |
2494 { | |
2495 while(e) { | |
2496 if(contains_p(car(e),p)) return 1; | |
2497 e = cadr(e); | |
2498 } | |
2499 return 0; | |
2500 } | |
2501 | |
327 | 2502 extern int |
223 | 2503 contains_p(int e,int (*p)(int)) |
2504 { | |
2505 while(e) { | |
256
d80e6387c539
powerpc function call complex arugment pre computation.
kono
parents:
255
diff
changeset
|
2506 if (!car(e)) return 0; |
223 | 2507 if (p(car(e))) return 1; |
2508 if (LIST_ARGS(car(e))){ | |
2509 /* list arguments */ | |
2510 return contains_in_list_p(caddr(e),p); | |
2511 } else if (UNARY_ARGS(car(e))) { | |
2512 /* unary operators */ | |
2513 e = cadr(e); | |
2514 continue; | |
2515 } else if (BINARY_ARGS(car(e))) { | |
2516 /* biary operators */ | |
2517 if (contains_p(cadr(e),p)) return 1; | |
2518 e = caddr(e); | |
2519 continue; | |
2520 } else if (TARNARY_ARGS(car(e))) { | |
2521 /* tarary operators */ | |
2522 if (contains_p(cadr(e), p)) return 1; | |
2523 if (contains_p(caddr(e),p)) return 1; | |
2524 e = cadddr(e); | |
2525 continue; | |
2526 } else if (NULLARY_ARGS(car(e))) { | |
2527 /* nullary operators */ | |
2528 return 0; | |
2529 } else { | |
327 | 2530 // fprintf(stderr,"Unknown Tree ID %d\n",car(e)); |
223 | 2531 error(-1); |
2532 return 0; | |
2533 } | |
2534 } | |
2535 return 0; | |
2536 } | |
2537 | |
449 | 2538 static int |
2539 contains_in_list_p1(int arg,int e,int (*p)(int,int)) | |
2540 { | |
2541 while(e) { | |
2542 arg=contains_p1(arg,car(e),p); | |
2543 e = cadr(e); | |
2544 } | |
2545 return arg; | |
2546 } | |
2547 | |
2548 extern int | |
2549 contains_p1(int arg,int e,int (*p)(int,int)) | |
2550 { | |
2551 while(e) { | |
2552 if (!car(e)) return arg; | |
2553 if (LIST_ARGS(car(e))){ | |
2554 /* list arguments */ | |
2555 return contains_in_list_p1(arg,caddr(e),p); | |
2556 } else if (UNARY_ARGS(car(e))) { | |
2557 /* unary operators */ | |
2558 e = cadr(e); | |
2559 continue; | |
2560 } else if (BINARY_ARGS(car(e))) { | |
2561 /* biary operators */ | |
2562 arg=contains_p1(arg,cadr(e),p); | |
2563 e = caddr(e); | |
2564 continue; | |
2565 } else if (TARNARY_ARGS(car(e))) { | |
2566 /* tarary operators */ | |
2567 arg=contains_p1(arg,cadr(e), p); | |
2568 arg=contains_p1(arg,caddr(e),p); | |
2569 e = cadddr(e); | |
2570 continue; | |
2571 } else if (NULLARY_ARGS(car(e))) { | |
2572 /* nullary operators */ | |
2573 arg=p(arg,e); | |
2574 return arg; | |
2575 } else { | |
2576 // fprintf(stderr,"Unknown Tree ID %d\n",car(e)); | |
2577 // error(-1); | |
2578 return arg; | |
2579 } | |
2580 } | |
2581 return arg; | |
2582 } | |
2583 | |
320 | 2584 #if ASM_CODE |
2585 | |
2586 | |
2587 /* | |
2588 __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (a | |
2589 ddr)); | |
2590 asm string : output constraint parameter : input constraint parameter : opt | |
2591 | |
2592 1: asm string %1,%2 will be replaced by register or value | |
2593 2: constraint gcc constraint sting | |
2594 prefix | |
2595 = overwrite by this asm for output | |
2596 & overwrite by this asm and can't be used as input register | |
2597 ignored in this compiler | |
2598 constraints | |
326 | 2599 m value expression is modified (no corresponding register) |
320 | 2600 information for compiler |
2601 r register for input or output | |
2602 input register, output register can be shared | |
2603 0-9 same operands as outout register in input constraints | |
2604 3: opt "cc", "memory" | |
2605 ignored in this compiler | |
2606 */ | |
2607 | |
2608 static void | |
327 | 2609 gen_asm(int asm0,int in,int out,int opt,int e) |
320 | 2610 { |
2611 int i,e1,n; | |
2612 int repl = 0; | |
2613 int repl0; | |
2614 int assign = 0; | |
2615 char *p; | |
2616 | |
2617 printf("# asm\n"); | |
2618 in = reverse0(in); | |
2619 out = reverse0(out); | |
2620 e = reverse0(e); | |
2621 for(i=out;i;i=cadr(i)) { | |
2622 p = (char*)cadr(car(i)); | |
2623 e1 = car(e); e = cadr(e); | |
327 | 2624 repl = code_asm_operand(p,e1,ASM_OUTPUT,repl,0,0); |
320 | 2625 if (car(car(repl))==REGISTER) { |
2626 assign = list2(assign_expr0(e1,car(repl),INT,INT),assign); | |
2627 } | |
2628 } | |
2629 repl0 = repl; | |
2630 n = length(repl0); | |
2631 for(i=in;i;i=cadr(i)) { | |
2632 p = (char*)cadr(car(i)); | |
2633 e1 = car(e); e = cadr(e); | |
327 | 2634 repl = code_asm_operand(p,e1,ASM_INPUT,repl,n,repl0); |
320 | 2635 if (car(car(repl))==REGISTER) { |
2636 g_expr_u(assign_expr0(car(repl),e1,INT,INT)); | |
2637 } | |
2638 } | |
2639 repl = reverse0(repl); | |
327 | 2640 code_asm((char*)cadr(asm0),repl); |
320 | 2641 for(i=assign;i;i=cadr(i)) { |
2642 g_expr_u(car(i)); | |
2643 } | |
327 | 2644 code_free_asm_operand(repl); |
320 | 2645 // no check for opt |
2646 } | |
2647 | |
327 | 2648 #endif |
2649 | |
426 | 2650 /* |
2651 define symbol name contents | |
2652 depending on stmode, mode | |
2653 define displacement | |
2654 */ | |
327 | 2655 |
2656 extern NMTBL * | |
445 | 2657 def(NMTBL *n,int ctmode) |
327 | 2658 { |
2659 int sz,nsc,ndsp; | |
2660 int sbit_f = bit_field_disp; | |
2661 bit_field_disp = 0; // default is 0, recover only in bit-field | |
2662 | |
2663 if (n==0) { | |
2664 n=anonymous_nptr(); | |
2665 n->nm = "_"; | |
2666 } | |
2667 nsc=ndsp=0; | |
2668 if (stmode==EXTRN||mode==GDECL) | |
2669 n->ty = type; /* must be in global table/heap */ | |
2670 if(type>0&&(car(type)==FUNCTION || car(type)==CODE)) { | |
2671 if ((mode==GDECL)) { | |
2672 fcheck(n); | |
453 | 2673 if (ctmode) set_attr(n,KONST,0); |
327 | 2674 return n; |
2675 /* function and code segment are defined using fdecl/code_decl */ | |
2676 /* in decl() */ | |
2677 } | |
2678 } | |
335 | 2679 if (mode==GSDECL||mode==LSDECL) { |
445 | 2680 /* Struct fields name lists are in the struct type or tag. */ |
2681 /* Only name in the table is used. Do not set n->ty! */ | |
2682 /* Struct field may volatile... where do I put? list2(VOLATILE,type)? */ | |
332 | 2683 if (car(type)==BIT_FIELD) { |
327 | 2684 bit_field_disp=sbit_f; // default is 0, recover only here. |
420 | 2685 // type = list4(BIT_FIELD,value type, |
2686 // list3(store type,bit offset,bit_width)); | |
440 | 2687 #if BIT_FIELD_CODE |
420 | 2688 cadr(caddr(type)) = code_bit_field_disp( |
332 | 2689 type,&disp,&bit_field_disp,&sz); |
329 | 2690 /* bit_field_disp is next bit posision */ |
440 | 2691 #else |
2692 error(-1); | |
2693 #endif | |
327 | 2694 } else { |
2695 sz = size(type); | |
2696 } | |
336 | 2697 if (n!=&null_nptr) |
2698 fields = list4(type,fields,(int)(n->nm),disp); | |
335 | 2699 } else if (mode==GUDECL||mode==LUDECL) { |
2700 if (car(type)==BIT_FIELD) { | |
420 | 2701 cadr(caddr(type)) = 0; sz = size(cadr(type)); |
335 | 2702 } else { |
2703 sz = size(type); | |
2704 } | |
2705 fields = list4(type,fields,(int)(n->nm),0); | |
327 | 2706 } else { |
2707 if (n->sc!=EMPTY && !(n->sc==EXTRN||n->sc==EXTRN1||n->sc==STATIC)) { | |
2708 /* redefined case */ | |
2709 if (mode==ADECL) { /* K&R arguments case */ | |
2710 if (n->sc==LVAR && n->ty==INT); | |
2711 else if ( n->sc==REGISTER && n->ty==INT); | |
355 | 2712 else if ( n->sc==TYPE) { |
2713 n = lsearch(n->nm,0); | |
2714 } else error(RDERR); | |
327 | 2715 } else error(RDERR); |
2716 } | |
2717 sz = size(n->ty = type); | |
2718 } | |
2719 switch(mode) { | |
2720 case GDECL: | |
2721 gen_gdecl(n->nm,gpc); | |
2722 case STADECL: | |
2723 nsc = GVAR; | |
2724 ndsp = gpc; | |
2725 if (n->dsp!=-1) /* don't set dsp if initialized static */ | |
2726 n->dsp = ndsp; /* emit_data will override this */ | |
2727 if (stmode==EXTRN) | |
2728 nsc = EXTRN; | |
2729 else if (stmode==STATIC) | |
2730 nsc = STATIC; | |
2731 n->sc = nsc; | |
2732 if (stmode==LDECL) { | |
347 | 2733 n = new_static_name(n->nm,'.'); |
350 | 2734 if (!n->next) { |
2735 n->next = local_static_list; local_static_list = n; | |
2736 } | |
348 | 2737 } else { |
350 | 2738 if (!n->next) { |
2739 n->next = global_list; global_list = n; | |
2740 } | |
327 | 2741 } |
2742 gpc +=sz; | |
453 | 2743 if (ctmode) set_attr(n,KONST,0); |
327 | 2744 return n; |
2745 case GSDECL: case LSDECL: | |
2746 disp += sz; | |
2747 return n; | |
2748 case GUDECL: case LUDECL: | |
2749 if (disp < sz) disp = sz; | |
2750 return n; | |
2751 case GTDECL: | |
2752 nsc = TYPE; | |
2753 gtypedefed=glist2((int)gnptr,gtypedefed); | |
2754 break; | |
2755 case LTDECL: | |
2756 nsc = TYPE; | |
2757 break; | |
362 | 2758 case LLDECL: |
363 | 2759 nsc = FLABEL; |
453 | 2760 if (!inmode) |
2761 ndsp = fwdlabel(); | |
362 | 2762 break; |
327 | 2763 case ADECL: |
2764 if(!integral(type)&&(car(type)==FUNCTION||car(type)==CODE)) { | |
2765 type=list2(POINTER,type); n->ty = type; | |
2766 } | |
2767 fnptr->dsp=list4(type,fnptr->dsp,(int)n,0); | |
2768 n->sc = LVAR; | |
2769 if(type==CHAR||type==UCHAR) { | |
2770 if (n->dsp==0) { | |
2771 n->dsp = args; | |
2772 if (endian) n->dsp += size_of_int-1; | |
2773 } | |
2774 args += size_of_int; | |
2775 } else if(type==SHORT||type==USHORT) { | |
2776 if (n->dsp==0) { | |
2777 n->dsp = args; | |
2778 if (endian) n->dsp += size_of_int-size_of_short; | |
2779 } | |
2780 args += size_of_int; | |
444 | 2781 #if 1 |
2782 } else if(type>0&&(car(type)==UNION||car(type)==STRUCT)) { | |
327 | 2783 n->dsp = args; |
2784 args += ((sz+(size_of_int-1))&~(size_of_int-1)); | |
343 | 2785 #endif |
327 | 2786 } else { |
2787 /* if (n->dsp==0) (argument list in ADECL is useless, type | |
2788 list can be found in type ) */ | |
2789 n->dsp = args; | |
2790 args += sz; | |
2791 } | |
2792 cadddr(fnptr->dsp)=sz; | |
2793 if(type==VOID) { | |
2794 } else { | |
2795 n->ty = type; | |
2796 } | |
453 | 2797 if (ctmode) set_attr(n,KONST,0); |
327 | 2798 return n; |
2799 case STAT: /* return (struct hoge)f() case? */ | |
2800 case LDECL: | |
453 | 2801 if (stmode==REGISTER && !inmode) { |
327 | 2802 if(scalar(type)) { |
2803 ndsp = get_register_var(n); | |
2804 #if FLOAT_CODE | |
2805 } else if (type==FLOAT) { | |
2806 ndsp = get_dregister_var(n,0); | |
2807 } else if (type==DOUBLE) { | |
2808 ndsp = get_dregister_var(n,1); | |
2809 #endif | |
2810 #if LONGLONG_CODE | |
2811 } else if (type==LONGLONG||type==ULONGLONG) { | |
2812 ndsp = get_lregister_var(n); | |
2813 #endif | |
2814 } else error(DCERR); | |
2815 nsc = car(ndsp); | |
2816 ndsp = cadr(ndsp); | |
2817 } else { | |
2818 nsc = LVAR; | |
2819 ndsp = new_lvar(sz); | |
2820 } | |
2821 n->sc = nsc; | |
2822 n->dsp = ndsp; | |
453 | 2823 if (ctmode) set_attr(n,KONST,0); |
327 | 2824 return n; |
2825 default: | |
2826 error(DCERR); | |
2827 } | |
2828 n->sc = nsc; | |
2829 n->dsp = ndsp; | |
453 | 2830 if (ctmode) set_attr(n,KONST,0); |
327 | 2831 if (stmode==EXTRN) |
2832 n->sc = EXTRN; | |
2833 return n; | |
2834 } | |
2835 | |
2836 | |
2837 extern void | |
2838 emit_init_vars(void) | |
2839 { | |
2840 if (!init_vars) return; | |
2841 init_vars = reverse0(init_vars); | |
2842 while(init_vars) { | |
2843 gexpr(car(init_vars),0); | |
2844 init_vars = cadr(init_vars); | |
2845 } | |
2846 } | |
2847 | |
2848 static int | |
2849 str_init_eq() | |
2850 { | |
2851 // error(-1); // duplicate struct field value | |
2852 return 2; // allow override keep unique | |
2853 } | |
2854 | |
340 | 2855 static void |
2856 emit_data(int e, int t, NMTBL *n) | |
2857 { | |
2858 int l; | |
2859 char *name; | |
2860 name = n->nm; | |
2861 if(mode!=GDECL && mode!=STADECL) { | |
2862 error(-1); return; | |
2863 } | |
2864 if (chk) return; | |
2865 if (n->dsp != -1) { | |
2866 n->dsp = -1; /* initialized flag */ | |
2867 emit_global(name,t); | |
2868 } | |
2869 switch(t) { | |
2870 case EMPTY: | |
2871 if(car(e)!=CONST) error(-1); | |
2872 emit_space(cadr(e)); | |
2873 return; | |
2874 case CHAR: case UCHAR: | |
2875 emit_char(cadr(e)); | |
415 | 2876 data_alignment++; |
340 | 2877 return; |
2878 case SHORT: case USHORT: | |
2879 emit_short(cadr(e)); | |
415 | 2880 data_alignment++; |
340 | 2881 return; |
2882 case INT: case UNSIGNED: case ENUM: | |
2883 emit_int(cadr(e)); | |
2884 return; | |
2885 case LONGLONG: case ULONGLONG: | |
2886 emit_longlong(e); | |
2887 return; | |
2888 case DOUBLE: | |
2889 emit_double(e); | |
2890 return; | |
2891 case FLOAT: | |
2892 emit_float(e); | |
415 | 2893 data_alignment++; |
340 | 2894 return; |
2895 default: | |
2896 if (t<0) error(-1); | |
2897 if (car(t)==BIT_FIELD) { | |
2898 return; | |
2899 } | |
2900 if (car(t)!=POINTER&&car(t)!=ARRAY) error(-1); | |
2901 switch(car(e)) { | |
2902 case CONST: | |
2903 emit_int(cadr(e)); | |
2904 return; | |
2905 case ADDRESS: | |
2906 if (car(cadr(e))==GVAR) | |
367 | 2907 emit_address(((NMTBL *)caddr(cadr(e)))->nm,cadr(cadr(e))); |
340 | 2908 else error(INERR); |
2909 return; | |
2910 case FNAME: | |
367 | 2911 emit_address(((NMTBL *)cadr(e))->nm,0); |
2912 return; | |
340 | 2913 case GVAR: |
367 | 2914 emit_address(((NMTBL *)caddr(e))->nm,0); |
340 | 2915 return; |
2916 case STRING: | |
2917 if (car(n->ty)!=ARRAY || cadr(n->ty)!=CHAR) { | |
2918 l = emit_string_label(); | |
2919 ascii((char *)cadr(e)); | |
2920 emit_label(l); | |
2921 } else | |
2922 ascii((char *)cadr(e)); | |
2923 return; | |
2924 } | |
2925 // fprintf(stderr,"# type= %d\n",t); | |
2926 } | |
2927 error(INERR); | |
2928 } | |
2929 | |
327 | 2930 extern int |
2931 assign_data(int e, int t, NMTBL *n,int offset) | |
2932 { | |
329 | 2933 int ass,sz,bfd; |
327 | 2934 |
446 | 2935 if (car(e)==ADDRESS||car(e)==GVAR) { |
2936 if (scalar(t)) { | |
2937 t = list2(POINTER,VOID); // fake | |
2938 } else { | |
2939 error(TYERR); | |
2940 } | |
2941 } | |
327 | 2942 if(mode==GDECL) { |
2943 emit_data(e,t,n); | |
2944 } else if(mode==STADECL) { | |
2945 emit_data(e,t,n); | |
2946 } else if(mode==LDECL) { | |
329 | 2947 if (t==EMPTY) { |
2948 /* empty space in partial initialization */ | |
2949 return offset+cadr(e); | |
2950 } | |
445 | 2951 /* If this is a local declared constant, we don't have to assign. |
2952 But some one may take it's address. We have to generate assign. | |
2953 */ | |
327 | 2954 ass = assign_expr0( |
2955 (n->sc==REGISTER||n->sc==DREGISTER||n->sc==FREGISTER||n->sc==LREGISTER)? | |
2956 list3(n->sc,n->dsp,(int)n): | |
445 | 2957 list3(LVAR,n->dsp+offset,0), |
327 | 2958 e,t,type); |
2959 init_vars = list2(ass,init_vars); | |
2960 } else if(mode==SFDINIT) { | |
2961 decl_str_init=insert_ascend(decl_str_init, | |
2962 list4(offset,0,e,t),str_init_eq); | |
2963 } else { | |
2964 error(DCERR); | |
2965 return offset; | |
2966 } | |
329 | 2967 if (t>0&&car(t)==BIT_FIELD) { |
2968 sz = 0; | |
420 | 2969 bfd = cadr(caddr(t)); /* bit_field_disp */ |
440 | 2970 #if BIT_FIELD_CODE |
331 | 2971 code_bit_field_disp(t,&offset,&bfd,&sz); |
440 | 2972 #endif |
329 | 2973 return offset+sz; |
2974 } | |
445 | 2975 /* constant value field */ |
453 | 2976 if (offset==0 && (has_attr(n,KONST))) { |
2977 set_attr(n,KONST,e); | |
445 | 2978 } |
327 | 2979 return offset+((t==EMPTY)?cadr(e):size(t)); |
2980 } | |
2981 | |
328 | 2982 extern void |
2983 data_closing(NMTBL *n) | |
2984 { | |
456 | 2985 if (!chk) |
2986 emit_data_closing(n); | |
328 | 2987 } |
2988 | |
353 | 2989 #define ARG_REORDER_DEBUG 0 |
328 | 2990 |
426 | 2991 /* |
2992 In K&R style, order of argment list and order of argment | |
2993 type decl are differnt. Fix them. | |
2994 */ | |
2995 | |
327 | 2996 extern int |
2997 arg_reorder(int arg,int new_arg) | |
2998 { | |
2999 /* list4(type,fnptr->dsp,(int)n,size); */ | |
3000 int i,j,sz; | |
3001 int dsp = 0; | |
3002 NMTBL *n,*n1; | |
3003 | |
353 | 3004 /* f(a,b,c) int c; short a; char* b; { } case */ |
3005 #if ARG_REORDER_DEBUG | |
3006 fprintf(stderr,"arg_reorder old:\n"); | |
3007 for(j=new_arg;j;j=cadr(j)) { | |
3008 n=(NMTBL *)caddr(j); | |
3009 fprintf(stderr,"dsp %d %s sz %d type %d\n",n->dsp,n->nm,cadddr(j),car(j)); | |
3010 } | |
3011 fprintf(stderr,"arg_reorder new:\n"); | |
3012 #endif | |
327 | 3013 for(j=arg;j;j=cadr(j)) { |
3014 n=(NMTBL *)caddr(j); | |
3015 for(i=new_arg;i;i=cadr(i)) { | |
3016 n1=(NMTBL *)caddr(i); | |
3017 if (!neqname(n1->nm,n->nm)) break; | |
3018 // if (n1==n) break; | |
3019 } | |
353 | 3020 #if ARG_REORDER_DEBUG |
3021 fprintf(stderr,"dsp %d %s %s sz %d type %d\n",dsp,n->nm,n1->nm,cadddr(i),car(i)); | |
3022 #endif | |
327 | 3023 if (!i) { |
353 | 3024 /* f(a,b,c) int c; { } case (what?!) */ |
327 | 3025 i = j; |
353 | 3026 n1 = n; |
327 | 3027 } |
3028 if(n->sc==LVAR) { | |
3029 n->dsp = dsp; | |
3030 car(j)=car(i); | |
3031 caddr(j)=caddr(i); | |
353 | 3032 n1->dsp = n->dsp; |
3033 n->ty = n1->ty; | |
3034 n->sc = n1->sc; | |
445 | 3035 n->attr = n1->attr; |
327 | 3036 cadddr(j)=sz= cadddr(i); |
3037 if (sz==1||sz==size_of_short) sz = size_of_int; | |
3038 dsp += sz; | |
3039 } | |
3040 } | |
353 | 3041 #if ARG_REORDER_DEBUG |
3042 fprintf(stderr,"arg_reorder end:\n"); | |
3043 #endif | |
327 | 3044 return arg; |
3045 } | |
3046 | |
3047 | |
3048 static NMTBL str_ret; | |
3049 | |
3050 /* | |
3051 If function has structure return value, it has an extra | |
3052 argument for where to write the structure. It have to be | |
3053 a first argument. We add it here and we have to fix all arguments' | |
3054 offset. If it is the last value, we don't have to fix, but | |
3055 gcc has a first argument convention. | |
3056 */ | |
3057 | |
3058 extern void | |
3059 fdecl_struct(int fntype) | |
3060 { | |
3061 int type_save,mode_save,t,sz; | |
3062 NMTBL *n; | |
3063 | |
3064 t = cadr(fntype); | |
3065 if (t>0 && (car(t)==STRUCT||car(t)==UNION)) { | |
3066 mode_save = mode; | |
3067 mode=ADECL; | |
3068 type_save = type; | |
3069 /* extra argument for struct return */ | |
3070 /* this extra dummy arguments are set at calling sequence */ | |
3071 str_ret.nm = "str_ret"; str_ret.sc = EMPTY; | |
3072 str_ret.dsp = 0; str_ret.ty = 0; | |
3073 type=list2(POINTER,t); | |
3074 /* fix all argument's offset */ | |
3075 sz = size(type); | |
3076 for(t=fnptr->dsp;t;t=cadr(t)) { | |
3077 n=(NMTBL *)caddr(t); | |
3078 n->dsp += sz; | |
3079 } | |
3080 fnptr->dsp = reverse0(fnptr->dsp); | |
3081 if ((sz=size(cadr(fntype)))==-1) error(TYERR); | |
3082 else { | |
3083 args = 0; | |
445 | 3084 def(&str_ret,0); |
3085 struct_return = list3(list3(LVAR,str_ret.dsp,0),sz,type); | |
327 | 3086 caddr(fnptr->ty) = glist2(POINTER,caddr(fnptr->ty)); |
3087 } | |
3088 type = type_save; | |
3089 mode = mode_save; | |
3090 } else { | |
3091 struct_return = 0; | |
3092 fnptr->dsp = reverse0(fnptr->dsp); | |
3093 } | |
3094 } | |
3095 | |
3096 extern void | |
3097 fcheck(NMTBL *n) | |
3098 { | |
3099 if(!(mode==GDECL||mode==ADECL)|| | |
3100 (car(type)!=FUNCTION&&car(type)!=CODE)) error(DCERR); | |
3101 if (n->sc==EMPTY) { | |
3102 n->sc=EXTRN; | |
3103 n->ty=type; | |
3104 } else if(is_code(n)) compatible(cadr(n->ty),cadr(type)); | |
3105 else if(is_function(n)) compatible(cadr(n->ty),cadr(type)); | |
3106 else { | |
3107 error(DCERR); | |
3108 } | |
3109 } | |
3110 | |
3111 static void | |
3112 compatible(int t1, int t2) | |
3113 { | |
3114 if(integral(t1)) { | |
3115 if(t1!=t2) error(TYERR); | |
3116 } | |
3117 else if(car(t1)!=car(t2)) | |
3118 error(TYERR); | |
3119 else if((car(t1)==STRUCT || car(t1)==UNION) && cadr(t1)!=cadr(t2)) | |
3120 error(TYERR); | |
3121 else if(car(t1)==POINTER || car(t1)==ARRAY ||car(t1)==FUNCTION) | |
3122 compatible(cadr(t1),cadr(t2)); | |
3123 } | |
3124 | |
3125 extern int | |
3126 scalar(int t) | |
3127 { | |
3128 return(integral(t)||car(t)==POINTER); | |
3129 } | |
3130 | |
3131 extern int | |
3132 integral(int t) | |
3133 { | |
3134 return(t==INT||t==SIGNED||t==CHAR||t==UNSIGNED|| | |
3135 t==UCHAR||t==SHORT||t==USHORT||t==ENUM); | |
3136 } | |
3137 | |
3138 extern void | |
3139 checkret(void) | |
3140 { | |
455 | 3141 if (inmode) error(-1); |
327 | 3142 if (cslabel==0) { |
3143 if (!control) error(-1); // no execute code in switch | |
442 | 3144 checkjmp(0); |
3145 control=0; | |
327 | 3146 jmp(cslabel=fwdlabel()); |
3147 } else if (retpending) { | |
3148 ret(); | |
3149 control=0; | |
3150 retpending=0; | |
3151 } | |
3152 if (lastexp) { | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
3153 if(!control) error(-1); |
327 | 3154 gexpr(lastexp,0); |
3155 lastexp = 0; | |
3156 } | |
3157 } | |
3158 | |
3159 | |
3160 extern void | |
3161 replace_return_struct(int func,int left) { | |
3162 int e = caddr(func); /* arg lists */ | |
3163 while(cadr(e)) e=cadr(e); /* find first arg */ | |
3164 e = car(e); /* return_struct arg */ | |
3165 cadr(e) = left; | |
3166 } | |
3167 | |
320 | 3168 |
327 | 3169 /* right value , get the value of the variable */ |
320 | 3170 |
327 | 3171 static int |
3172 indirect(int t,int e1) | |
3173 { | |
3174 int e2,e3,e4,offset; | |
3175 e2 = e1; | |
3176 offset = 0; | |
3177 e3 = cadr(e2); | |
3178 if (car(e2)==ADD) { | |
3179 e4=caddr(e2); | |
3180 if (car(e4)==CONST) { | |
3181 offset=cadr(e4); | |
3182 e1=e3; | |
3183 } | |
3184 } | |
3185 return list3(t,e1,offset); | |
3186 } | |
3187 | |
3188 extern int | |
3189 rvalue(int e) | |
3190 { | |
453 | 3191 int op,c; |
445 | 3192 NMTBL *n; |
327 | 3193 |
331 | 3194 if (e==0) error(-1); |
327 | 3195 op = 0; |
3196 switch(type) { | |
333 | 3197 case INT: break; |
3198 case UNSIGNED: break; | |
3199 case VOID: break; | |
3200 case CHAR: op=COP; type=INT; break; | |
3201 case UCHAR: op=COP+US; type=UNSIGNED; break; | |
3202 case SHORT: op=SOP; type=SIGNED; break; | |
327 | 3203 case USHORT: op=SOP+US; type=UNSIGNED; break; |
3204 case LONGLONG: op=LOP; break; | |
3205 case ULONGLONG: op=LOP+US; break; | |
333 | 3206 case FLOAT: op=FOP; break; |
327 | 3207 case DOUBLE: op=DOP; break; |
3208 case CODE: return e; | |
331 | 3209 case 0: error(-1); return e; |
327 | 3210 default: |
3211 if (integral(type)) break; | |
3212 switch(car(type)) { | |
3213 case ARRAY: | |
3214 type=list2(POINTER,cadr(type)); | |
3215 if(car(e)==INDIRECT) return cadr(e); | |
3216 return list2(ADDRESS,e); | |
3217 case STRUCT: case UNION: | |
3218 if(car(e)==RSTRUCT) return e; /* ??? */ | |
3219 return list3(RSTRUCT,e,cadr(type) /* size */); | |
3220 case FUNCTION: | |
3221 type=cadr(type); | |
3222 return e; | |
3223 case CODE: | |
3224 return e; | |
3225 case POINTER: | |
3226 break; | |
3227 case BIT_FIELD: | |
426 | 3228 e = list3(RBIT_FIELD,cadr(e),type); |
420 | 3229 /* byte rvalue, store type */ |
3230 type = cadr(type); /* value type */ | |
335 | 3231 return e; |
327 | 3232 break; |
3233 default: | |
3234 error(TYERR); | |
3235 } | |
3236 } | |
3237 switch(car(e)) { | |
3238 case GVAR: | |
445 | 3239 n = (NMTBL*)caddr(e); |
453 | 3240 if (cadr(e)==0 && (c=attr_value(n,KONST))) { |
3241 return c; | |
445 | 3242 } |
367 | 3243 return(list3(RGVAR+op,cadr(e),caddr(e))); |
327 | 3244 case LVAR: |
445 | 3245 n = (NMTBL*)caddr(e); |
453 | 3246 if (n && (c=attr_value(n,KONST))) { |
3247 return c; | |
445 | 3248 } |
3249 return(list3(RLVAR+op,cadr(e),caddr(e))); | |
327 | 3250 case INDIRECT: |
3251 return(indirect(RINDIRECT+op,cadr(e))); | |
3252 default:return(e); /* idempotent case? */ | |
3253 } | |
3254 } | |
3255 | |
3256 extern int | |
3257 rvalue_t(int e,int t) | |
3258 { | |
3259 int stype = type; | |
3260 type = t; | |
3261 e = rvalue(e); | |
3262 type = stype; | |
3263 return e; | |
3264 } | |
3265 | |
3266 extern void | |
3267 lcheck(int e) | |
3268 { | |
3269 int t; | |
342 | 3270 if(scalar(type)) return; |
3271 switch(type) { | |
3272 case DOUBLE: case FLOAT : case LONGLONG: case ULONGLONG: | |
3273 return; | |
3274 default: | |
3275 switch(car(e)) { | |
3276 case GVAR: case LVAR: case INDIRECT : | |
3277 case REGISTER : case DREGISTER : case FREGISTER : case LREGISTER: | |
3278 return; | |
3279 } | |
3280 } | |
3281 if ((t=car(type))<0 && t!=STRUCT && t!=UNION) | |
3282 error(LVERR); | |
327 | 3283 } |
3284 | |
3285 extern int | |
3286 indop(int e) | |
3287 { | |
3288 if(type!=INT&&type!=UNSIGNED) { | |
3289 if(car(type)==POINTER) | |
3290 type=cadr(type); | |
3291 else if(car(type)==CODE || car(type)==FUNCTION) | |
3292 type=type; | |
3293 else error(TYERR); | |
3294 } else | |
342 | 3295 type= CHAR; // ?! |
327 | 3296 if(car(e)==ADDRESS) |
3297 return(cadr(e)); | |
3298 return(list2(INDIRECT,e)); | |
3299 } | |
3300 | |
3301 /* filed name search */ | |
3302 | |
3303 /* type = list4(s,disp,fields,tag_nptr); */ | |
3304 | |
3305 extern int | |
3306 search_struct_type(int type,char *name,int *dsp) | |
3307 { | |
3308 int t; | |
3309 NMTBL *nptr0; | |
3310 t = caddr(type); | |
3311 if (t==0) { | |
3312 nptr0=(NMTBL*)cadddr(type); | |
3313 t = caddr(type) = caddr(nptr0->ty); | |
3314 } | |
3315 for(;t;t = cadr(t)) { | |
3316 if (neqname((char *)caddr(t),name)==0) { | |
3317 *dsp = cadddr(t); | |
3318 return car(t); | |
3319 } | |
3320 } | |
3321 return 0; | |
3322 } | |
3323 | |
3324 extern int | |
3325 strop(int e,int ind) | |
3326 { | |
3327 int dsp = 0; | |
3328 | |
3329 if (ind) e = indop(rvalue(e)); | |
3330 if (integral(type)||(car(type)!=STRUCT && car(type)!=UNION)) | |
3331 e=rvalue(e); | |
3332 /* type = list4(s,disp,fields,tag_nptr); */ | |
3333 /* print_fields(caddr(type),"strop"); */ | |
3334 type = search_struct_type(type,nptr->nm,&dsp); | |
3335 if (!type) { error(TYERR); type=INT; return e; } | |
3336 if(dsp) { | |
3337 switch(car(e)) { | |
3338 case GVAR: | |
367 | 3339 // e=list2(INDIRECT,list3(ADD,e,list2(CONST,dsp))); |
3340 e=list3(GVAR,cadr(e)+dsp,caddr(e)); | |
327 | 3341 break; |
3342 case LVAR: | |
445 | 3343 e=list3(LVAR,cadr(e) + dsp,0); /* may have attribute */ |
327 | 3344 break; |
3345 case INDIRECT: | |
3346 e=list2(INDIRECT,list3(ADD,cadr(e),list2(CONST,dsp))); | |
3347 break; | |
3348 default: | |
3349 e=list2(INDIRECT,list3(ADD,e,list2(CONST,dsp))); | |
3350 } | |
3351 } else { | |
3352 switch(car(e)) { | |
3353 case GVAR: case LVAR: case INDIRECT: | |
3354 break; | |
3355 default: | |
3356 e=list2(INDIRECT,e); | |
3357 } | |
3358 } | |
3359 if (type>0&&car(type)==BIT_FIELD) { | |
3360 // n->ty = list4(BIT_FIELD,type,bit_offset, bit_size); | |
420 | 3361 e=list3(BIT_FIELD,e,type); // ??? |
327 | 3362 } |
3363 return e; | |
3364 } | |
3365 | |
3366 #if FLOAT_CODE | |
3367 /* binary floating computation */ | |
3368 | |
3369 #define DTYPE(dop) (dop==DOP?DOUBLE:FLOAT) | |
3370 | |
3371 static int | |
3372 fdbinop(int op, int e1, int e2, int t1, int t2, int dop) | |
3373 { | |
3374 double d1,d2,d; | |
3375 int b=0; | |
3376 | |
3377 if (dop==DOP) { | |
334 | 3378 type=t1; e1=double_value(e1); |
3379 type=t2; e2=double_value(e2); | |
327 | 3380 } else { |
334 | 3381 type=t1; e1=float_value(e1); |
3382 type=t2; e2=float_value(e2); | |
327 | 3383 } |
3384 if(car(e1)==dop+CONST&&car(e2)==dop+CONST) { | |
3385 d1=dcadr(e1); | |
3386 d2=dcadr(e2); | |
3387 switch(op) { | |
3388 case ADD: d=d1+d2; break; | |
3389 case SUB: d=d1-d2; break; | |
3390 case MUL: d=d1*d2;break; | |
3391 case DIV: | |
3392 if(!d2) error(EXERR);d=d1/d2;break; | |
3393 default: | |
3394 switch(op) { | |
3395 case GT: b=(d1>d2);break; | |
3396 case GE: b=(d1>=d2);break; | |
3397 case LT: b=(d1<d2);break; | |
3398 case LE: b=(d1<=d2);break; | |
3399 case EQ: b=(d1==d2);break; | |
3400 case NEQ: b=(d1!=d2);break; | |
3401 default: error(EXERR); | |
3402 } | |
3403 type = INT; | |
3404 return list2(CONST,b); | |
3405 } | |
3406 return dlist2(dop+CONST,d); | |
3407 } | |
3408 if(car(e1)==dop+CONST) { | |
3409 if ((op==SUB||op==ADD)&&dcadr(e1)==0.0) { | |
3410 return e2; | |
3411 } else if (op==MUL&&dcadr(e1)==1.0) { | |
3412 return e2; | |
3413 } else if (op==MUL&&-dcadr(e1)==1.0) { | |
3414 return list2(dop+MINUS,e2); | |
3415 } | |
3416 } | |
3417 if(car(e2)==dop+CONST) { | |
3418 if ((op==SUB||op==ADD)&&dcadr(e2)==0.0) { | |
3419 return e1; | |
3420 } | |
3421 if ((op==DIV||op==MUL)&&dcadr(e2)==1.0) { | |
3422 return e1; | |
3423 } | |
3424 if ((op==DIV||op==MUL)&&-dcadr(e2)==1.0) { | |
3425 return list2(DMINUS,e1); | |
3426 } | |
3427 if (op==SUB) { | |
3428 op=ADD; dcadr(e2) = -dcadr(e2); | |
3429 } else if(op==DIV) { | |
3430 if(dcadr(e2)==0.0) error(EXERR); | |
3431 op=MUL; dcadr(e2)=1/dcadr(e2); | |
3432 } | |
3433 } | |
3434 if ((op==ADD||op==MUL) && ( | |
3435 car(e1)==dop+CONST || | |
3436 car(e2)==DRLVAR || car(e2)==DRGVAR || | |
3437 car(e2)==FRLVAR || car(e2)==FRGVAR | |
3438 )) { | |
3439 return(list3(op+dop,e2,e1)); | |
3440 } | |
3441 if(op==LT) { | |
3442 type=INT; | |
3443 return(list3(GT+dop,e2,e1)); | |
3444 } else if(op==LE) { | |
3445 type=INT; | |
3446 return(list3(GE+dop,e2,e1)); | |
3447 } else if(op==GT||op==GE||op==EQ||op==NEQ) { | |
3448 type=INT; | |
3449 return(list3(op+dop,e1,e2)); | |
3450 } else if(op==ADD||op==SUB||op==MUL||op==DIV) | |
3451 return(list3(op+dop,e1,e2)); | |
3452 else { | |
3453 error(-1); | |
3454 return e1; | |
3455 } | |
3456 } | |
3457 | |
3458 static int | |
3459 dbinop(int op, int e1, int e2, int t1, int t2) | |
3460 { | |
3461 return fdbinop(op, e1, e2, t1, t2,DOP); | |
3462 } | |
3463 | |
3464 static int | |
3465 fbinop(int op, int e1, int e2, int t1, int t2) | |
3466 { | |
3467 return fdbinop(op, e1, e2, t1, t2,FOP); | |
3468 } | |
3469 | |
3470 #endif | |
3471 | |
3472 #if LONGLONG_CODE | |
3473 | |
3474 static int | |
3475 lbinop(int op, int e1, int e2, int t1, int t2) | |
3476 { | |
3477 int e=0; | |
3478 long long le1, le2; | |
3479 long long le = 0; | |
436 | 3480 int us = ((t1==ULONGLONG||t1==UNSIGNED)&&(t2==ULONGLONG||t2==UNSIGNED)); |
327 | 3481 |
3482 if (us||(t1==ULONGLONG&&(op==LSHIFT||op==RSHIFT))) { | |
334 | 3483 type=t1; e1=ulonglong_value(e1); |
3484 type=t2; e2=ulonglong_value(e2); | |
327 | 3485 } else { |
334 | 3486 type=t1; e1=longlong_value(e1); |
3487 type=t2; e2=longlong_value(e2); | |
327 | 3488 } |
3489 if(car(e1)==LCONST&&car(e2)==LCONST) { | |
3490 le1=lcadr(e1); | |
3491 le2=lcadr(e2); | |
3492 switch(op) { | |
3493 case BOR: | |
3494 le=le1|le2;break; | |
3495 case EOR: | |
3496 le=le1^le2;break; | |
3497 case BAND: | |
3498 le=le1&le2;break; | |
3499 case ADD: | |
3500 le=le1+le2;break; | |
3501 case SUB: | |
436 | 3502 le=le1-le2; type=LONGLONG; break; |
327 | 3503 case MUL: |
3504 le=le1*le2;break; | |
3505 case DIV: | |
3506 if(!le2) error(EXERR); | |
3507 if (us) le=(((unsigned long long )le1)/((unsigned long long )le2)); | |
3508 else e=(le1/le2); | |
3509 case MOD: | |
3510 if(!le2) error(EXERR); | |
3511 if (us) le=(((unsigned long long )le1)%((unsigned long long )le2)); | |
3512 else e=(le1%le2); | |
3513 case RSHIFT: | |
3514 if (t1==ULONGLONG) le=(((unsigned long long)le1)<<le2); else le=le1<<le2; | |
3515 break; | |
3516 case LSHIFT: | |
3517 if (t1==ULONGLONG) le=(((unsigned long long)le1)>>le2); else le=le1>>le2; | |
3518 break; | |
3519 default: | |
3520 switch(op) { | |
3521 case EQ: | |
3522 e=(le1==le2);break; | |
3523 case NEQ: | |
3524 e=(le1!=le2);break; | |
3525 case LT: | |
3526 le=le1;le1=le2;le2=le; | |
3527 case GT: | |
3528 if (us) e=((unsigned long long)le1>(unsigned long long)le2); | |
3529 else e=(le1>le2); | |
3530 break; | |
3531 case LE: | |
3532 le=le1;le1=le2;le2=le; | |
3533 case GE: | |
3534 if (us) e=((unsigned long long)le1>=(unsigned long long)le2); | |
3535 else e=(le1>=le2); | |
3536 break; | |
3537 default: | |
3538 error(-1); return list2(CONST,0); | |
3539 } | |
3540 type = INT; | |
3541 return list2(CONST,e); | |
3542 } | |
3543 return llist2(LCONST,le); | |
3544 } | |
3545 if(op==LT) { | |
3546 type = INT; return(list3(GT+LOP+us,e2,e1)); | |
3547 } else if(op==LE) { | |
3548 type = INT; return(list3(GE+LOP+us,e2,e1)); | |
3549 } else if(op==GT||op==GE||op==LT||op==LE) { | |
3550 type = INT; return(list3(op+LOP+us,e1,e2)); | |
3551 } | |
436 | 3552 if(op==SUB) { us = 0; type=LONGLONG; } |
327 | 3553 if(op==SUB&&car(e2)==LCONST) { op=ADD; lcadr(e2)=-lcadr(e2); } |
3554 if((op==ADD||op==MUL||op==BOR||op==EOR||op==BAND)&& | |
3555 (car(e1)!=LCONST) && ( | |
3556 car(e2)==LRGVAR||car(e2)==LRLVAR|| | |
3557 car(e2)==LURGVAR||car(e2)==LURLVAR | |
3558 )) { | |
3559 e=e1;e1=e2;e2=e;e=t1;t1=t2;t2=e; | |
3560 } | |
3561 if((op==MUL||op==DIV)&&car(e2)==LCONST&&lcadr(e2)==1) return e1; | |
3562 if(op==BOR||op==EOR||op==BAND||op==ADD||op==SUB||op==EQ||op==NEQ) | |
3563 return(list3(op+LOP,e1,e2)); | |
435 | 3564 if(op==LSHIFT && car(e2)==LCONST) { |
3565 if (lcadr(e2)==0) return e1; | |
3566 else if (lcadr(e2)>63) return llist2(LCONST,0); | |
3567 } | |
3568 if(op==RSHIFT && car(e2)==LCONST) { | |
3569 if (lcadr(e2)==0) return e1; | |
3570 } | |
327 | 3571 if(op==LSHIFT||op==RSHIFT) return(list3(op+LOP+(t1==ULONGLONG),e1,e2)); |
3572 return(list3(op+LOP+us,e1,e2)); | |
3573 } | |
320 | 3574 #endif |
3575 | |
327 | 3576 /* binary integer computation */ |
3577 | |
3578 extern int | |
3579 binop(int op, int e1, int e2, int t1, int t2) | |
3580 { | |
3581 int e=0; | |
353 | 3582 int us = 0; |
327 | 3583 |
445 | 3584 if(t1>0&&car(t1)==POINTER) { |
3585 if(!(op==SUB && t2>0&&car(t2)==POINTER)) { | |
3586 type = t2; e2= int_value(e2); t2=INT; | |
3587 } | |
3588 } else if(t2>0&&car(t2)==POINTER) { | |
3589 type = t1; e1= int_value(e1); t1=INT; | |
3590 } | |
327 | 3591 #if FLOAT_CODE |
3592 else if(t1==DOUBLE||t2==DOUBLE) | |
3593 return dbinop(op,e1,e2,t1,t2); | |
3594 else if(t1==FLOAT||t2==FLOAT) | |
3595 return fbinop(op,e1,e2,t1,t2); | |
3596 #endif | |
3597 #if LONGLONG_CODE | |
3598 else if(t1==LONGLONG||t2==LONGLONG||t1==ULONGLONG||t2==ULONGLONG) | |
3599 return lbinop(op,e1,e2,t1,t2); | |
3600 #endif | |
353 | 3601 if (t1==UNSIGNED) { |
3602 if (t2==UNSIGNED || (car(e2)==CONST && cadr(e2)>0)) us = 1; | |
3603 } | |
3604 if (t2==UNSIGNED) { | |
3605 if (t1==UNSIGNED || (car(e1)==CONST && cadr(e1)>0)) us = 1; | |
3606 } | |
3607 | |
327 | 3608 if(car(e1)==CONST&&car(e2)==CONST) { |
3609 e1=cadr(e1); | |
3610 e2=cadr(e2); | |
3611 type= INT; | |
3612 switch(op) { | |
3613 case BOR: | |
3614 e=e1|e2;break; | |
3615 case EOR: | |
3616 e=e1^e2;break; | |
3617 case BAND: | |
3618 e=e1&e2;break; | |
3619 case ADD: | |
3620 if(integral(t1)) { | |
3621 if(integral(t2)) { | |
3622 e=e1+e2; | |
3623 } else { | |
3624 if(car(t2)!=POINTER) error(TYERR); | |
3625 e=size(cadr(t2))*e1+e2; | |
3626 type=t2; | |
3627 } | |
3628 } else { | |
3629 if(car(t1)!=POINTER) error(TYERR); | |
3630 e=e1+size(cadr(t1))*e2; | |
3631 type=t1; | |
3632 } | |
3633 break; | |
3634 case SUB: | |
3635 if(integral(t1)) { | |
436 | 3636 e=e1-e2; type=INT; |
327 | 3637 } else { |
3638 if(car(t1)!=POINTER) error(TYERR); | |
445 | 3639 if(integral(t2)) { |
3640 e=e1-size(cadr(t1))*e2; | |
3641 type=t1; | |
3642 } else { | |
3643 e=(e1-e2)/size(cadr(t1)); | |
3644 type=INT; | |
3645 } | |
327 | 3646 } |
3647 break; | |
3648 case MUL: | |
3649 e=e1*e2;break; | |
3650 case DIV: | |
3651 if(!e2) error(EXERR); | |
3652 if (us) e=(((unsigned)e1)/((unsigned)e2)); else e=e1/e2; | |
3653 break; | |
3654 case MOD: | |
3655 if(!e2) error(EXERR); | |
3656 if (us) e=(((unsigned)e1)%((unsigned)e2)); else e=e1%e2; | |
3657 break; | |
3658 case RSHIFT: | |
3659 if (t1==UNSIGNED) e=(((unsigned)e1)>>((unsigned)e2)); else e=e1>>e2; | |
3660 break; | |
3661 case LSHIFT: | |
3662 if (t1==UNSIGNED) e=(((unsigned)e1)<<((unsigned)e2)); else e=e1<<e2; | |
3663 break; | |
3664 case EQ: | |
3665 e=(e1==e2);break; | |
3666 case NEQ: | |
3667 e=(e1!=e2);break; | |
3668 case LT: | |
3669 e=e1;e1=e2;e2=e; | |
3670 case GT: | |
3671 if (us) e=(((unsigned)e1)>((unsigned)e2)); else e=(e1>e2); | |
3672 break; | |
3673 case LE: | |
3674 e=e1;e1=e2;e2=e; | |
3675 case GE: | |
3676 if (us) e=(((unsigned)e1)>=((unsigned)e2)); else e=(e1>=e2); | |
3677 break; | |
3678 default: error(-1); return list2(CONST,0); | |
3679 } | |
3680 return list2(CONST,e); | |
3681 } | |
441 | 3682 if(op==GT||op==GE||op==LT||op==LE) { |
3683 return(car(e1)==CONST?list3(rop_dual(op)+us,e2,e1):list3(op+us,e1,e2)); | |
327 | 3684 } else if(op==EQ||op==NEQ) { |
441 | 3685 return(car(e1)==CONST?list3(op,e2,e1):list3(op,e1,e2)); |
327 | 3686 } |
3687 if(op==SUB&&car(e2)==CONST) { op=ADD; cadr(e2)=-cadr(e2); } | |
3688 if((op==ADD||op==MUL||op==BOR||op==EOR||op==BAND)&& | |
3689 (car(e1)!=CONST&& ( | |
3690 car(e2)==RGVAR||car(e2)==RLVAR|| | |
3691 car(e2)==URGVAR||car(e2)==URLVAR|| | |
3692 car(e2)==SRGVAR||car(e2)==SRLVAR|| | |
3693 car(e2)==SURGVAR||car(e2)==SURLVAR|| | |
3694 car(e2)==CRGVAR||car(e2)==CRLVAR|| | |
3695 car(e2)==CURGVAR||car(e2)==CURLVAR | |
3696 ))) { | |
3697 e=e1;e1=e2;e2=e;e=t1;t1=t2;t2=e; | |
3698 } | |
3699 if(op==ADD) { | |
3700 if(integral(t1)) { | |
3701 if(integral(t2)) { | |
442 | 3702 // if(t1==INT) type=t2;else type=t1; |
3703 if (us) type=UNSIGNED; else type=INT; | |
327 | 3704 return(list3(ADD,e1,e2)); |
3705 } | |
3706 if(car(t2)!=POINTER) error(TYERR); | |
3707 e=binop(MUL,e1,list2(CONST,size(cadr(t2))),t1,INT); | |
3708 type=t2; | |
3709 return(list3(ADD,e,e2)); | |
3710 } | |
3711 if(car(t1)!=POINTER||!integral(t2)) error(TYERR); | |
3712 e=binop(MUL,e2,list2(CONST,size(cadr(t1))),t2,INT); | |
3713 type=t1; | |
3714 if (car(e)==CONST && cadr(e)==0) | |
3715 return(e1); | |
367 | 3716 if (car(e)==CONST) { |
444 | 3717 if(car(e1)==ADDRESS) { |
3718 if (car(cadr(e1))!=GVAR) { | |
445 | 3719 // must be lvar |
3720 if (car(cadr(e1))!=LVAR) error(-1); | |
444 | 3721 return(list2(ADDRESS, |
445 | 3722 list3(car(cadr(e1)),cadr(cadr(e1))+cadr(e), |
3723 caddr(cadr(e1))))); | |
444 | 3724 } else { |
3725 return(list2(ADDRESS, | |
3726 list3(GVAR,cadr(cadr(e1))+cadr(e),caddr(cadr(e1))))); | |
3727 } | |
367 | 3728 } else if(car(e1)==GVAR) { |
3729 return(list3(GVAR,cadr(e1)+cadr(e),caddr(e1))); | |
3730 } else if(car(e1)==LVAR) { | |
445 | 3731 return(list3(LVAR,cadr(e1)+cadr(e),0)); |
367 | 3732 } |
3733 } | |
327 | 3734 return(list3(ADD,e1,e)); |
3735 } | |
3736 if(op==SUB) { | |
3737 if(integral(t1)) { | |
3738 if(!integral(t2)) error(TYERR); | |
3739 if(t1==INT) type=t2;else type=t1; | |
436 | 3740 if (type==UNSIGNED) type=INT; |
327 | 3741 return(list3(SUB,e1,e2)); |
3742 } | |
3743 if(car(t1)!=POINTER) error(TYERR); | |
3744 if(integral(t2)) { | |
3745 e=binop(MUL,e2,list2(CONST,size(cadr(t1))),t2,INT); | |
3746 type=t1; | |
367 | 3747 if (car(e)==CONST) error(-1); |
327 | 3748 return(list3(SUB,e1,e)); |
3749 } | |
3750 if(car(t2)!=POINTER) | |
3751 error(TYERR); | |
3752 compatible(t1,t2); | |
3753 e=list3(SUB,e1,e2); | |
3754 e=binop(DIV,e,list2(CONST,size(cadr(t1))),UNSIGNED,INT); | |
3755 type= INT; | |
3756 return e; | |
3757 } | |
3758 if(!integral(t1)||!integral(t2)) error(TYERR); | |
436 | 3759 // if(t1==INT) type=t2; else type=t1; /* ??? */ |
3760 if (us) type=UNSIGNED; else type=INT; | |
327 | 3761 if((op==MUL||op==DIV)&&car(e2)==CONST&&cadr(e2)==1) return e1; |
3762 if(op==BOR||op==EOR||op==BAND) return(list3(op,e1,e2)); | |
3763 if(op==LSHIFT||op==RSHIFT) return(list3(op+(t1==UNSIGNED?US:0),e1,e2)); | |
3764 // which ops remain? | |
3765 return(list3(op+us,e1,e2)); | |
3766 } | |
3767 | |
3768 /* coarse for function/code segments arguments */ | |
3769 | |
3770 extern int | |
3771 correct_type(int e,int t) | |
3772 { | |
3773 /* e = rvalue(e); */ | |
333 | 3774 #if BIT_FIELD_CODE |
3775 if (type==BIT_FIELD) e = rvalue(e); | |
3776 #endif | |
446 | 3777 if (t==DOTS) { |
3778 if (type==FLOAT) t=DOUBLE; | |
3779 else if (type==CHAR) t=INT; | |
3780 else if (type==UCHAR) t=UNSIGNED; | |
3781 } | |
3782 if (type>0 && car(type)==ARRAY && car(e)==GVAR) { | |
3783 e=list2(ADDRESS,e); | |
3784 } | |
3785 if (t>0) { | |
3786 switch(car(t)) { | |
3787 case STRUCT: case UNION: | |
3788 if(size(t)!=size(type)) error(TYERR); | |
3789 break; | |
3790 } | |
3791 } else { | |
3792 switch(t) { | |
3793 case DOTS: return e; | |
3794 case UNSIGNED: e = unsigned_value(e); break; | |
3795 case CHAR: e = char_value(e); t = INT; break; | |
3796 case UCHAR: e = uchar_value(e); t = UNSIGNED; break; | |
3797 case SHORT: e = short_value(e); t = INT; break; | |
3798 case USHORT: e = ushort_value(e); t = UNSIGNED; break; | |
327 | 3799 #if FLOAT_CODE |
446 | 3800 case FLOAT: e = float_value(e); break; |
3801 case DOUBLE: e = double_value(e); break; | |
327 | 3802 #endif |
3803 #if LONGLONG_CODE | |
446 | 3804 case LONGLONG: e = longlong_value(e); break; |
3805 case ULONGLONG: e = ulonglong_value(e); break; | |
327 | 3806 #endif |
446 | 3807 default: |
3808 if (integral(t)) e = int_value(e); | |
3809 } | |
3810 } | |
327 | 3811 type = t; |
3812 return e; | |
3813 } | |
3814 | |
3815 | |
3816 extern int | |
3817 cexpr(int e) | |
3818 { | |
3819 if (car(e) != CONST) error(CNERR); | |
3820 return (cadr(e)); | |
3821 } | |
3822 | |
329 | 3823 #define is_long_type(type) (type==LONGLONG||type==ULONGLONG) |
3824 | |
3825 #if BIT_FIELD_CODE | |
426 | 3826 |
3827 /* | |
3828 bitfield struct { char a:1; unsigned int b:10; } | |
3829 System dependent bit alignment is defined by code_bit_field_disp. | |
3830 type of bitfield represents type of the value | |
3831 these values are stored in a stored type which can be different from | |
3832 value type. | |
3833 */ | |
3834 | |
329 | 3835 static int |
3836 bit_field(int e1,int t) | |
3837 { | |
426 | 3838 int reg; |
332 | 3839 if (car(e1)==BIT_FIELD) { |
3840 printf("# bit_field_bug\n"); | |
3841 e1 = cadr(e1); | |
3842 } | |
329 | 3843 g_expr(e1); |
426 | 3844 emit_push(); |
3845 code_bit_field(t, reg = emit_pop(0), USE_CREG); | |
3846 emit_pop_free(reg); | |
3847 return cadr(t); /* value type */ | |
329 | 3848 } |
3849 | |
3850 static int | |
3851 bit_field_repl(int e1,int e2,int t) | |
3852 { | |
365 | 3853 /* e1 = e2 */ |
3854 if ((car(e2)==CONST||car(e2)==LCONST)) { | |
3855 g_expr(e1); | |
426 | 3856 code_bit_replace_const(e2,USE_CREG,t); |
3857 return t; | |
365 | 3858 } |
335 | 3859 g_expr(e1); |
426 | 3860 emit_push(); |
335 | 3861 g_expr(e2); |
426 | 3862 code_bit_replace(e2=emit_pop(0),USE_CREG,t); |
3863 emit_pop_free(e2); | |
3864 return t; | |
329 | 3865 } |
3866 | |
3867 static int | |
338 | 3868 bassign(int e2,int e3,int t) |
329 | 3869 { |
3870 int type = cadr(t); | |
338 | 3871 /* e2 = e3 */ |
339 | 3872 if (car(e2)==BIT_FIELD) { |
3873 e2 = cadr(e2); | |
3874 } | |
426 | 3875 bit_field_repl(e2,e3,t); |
329 | 3876 return type; |
3877 } | |
3878 | |
3879 static int | |
338 | 3880 bassop(int e2,int e3,int op,int t,int post) |
329 | 3881 { |
338 | 3882 /* |
426 | 3883 n = bit_field address |
3884 code_bit_field | |
3885 if (post) n1 = value | |
3886 value op= operand | |
3887 n bit-repl value | |
3888 if (post) n1; | |
338 | 3889 */ |
426 | 3890 /* e2 = e2 op e3; */ |
3891 /* new = &e2 */ | |
3892 /* *new = *new op e3 */ | |
3893 int suse = use; | |
3894 int lo = (type==LONGLONG||type==ULONGLONG); | |
427 | 3895 int n1=0,n2=0; |
426 | 3896 int reg; |
338 | 3897 |
427 | 3898 g_expr(list2(ADDRESS,cadr(e2))); |
426 | 3899 reg = emit_push(); |
3900 code_bit_field(t, reg, USE_CREG); | |
3901 use=1; | |
3902 if (lo) { | |
440 | 3903 #if LONGLONG_CODE |
426 | 3904 if (post) { |
445 | 3905 n1 = list3(LVAR,new_lvar(size_of_longlong),0); |
426 | 3906 code_lassign_lvar(cadr(n1),USE_CREG); |
3907 } | |
427 | 3908 if (!code_lassop_p) { |
445 | 3909 n2 = list3(LVAR,new_lvar(size_of_longlong),0); |
427 | 3910 code_lassign_lvar(cadr(n2),USE_CREG); |
3911 lassign(list4(LASSOP,n2,e3,op+LOP)); | |
3912 } else { | |
3913 emit_lpush(); | |
3914 g_expr(e3); | |
3915 code_register_lassop(USE_CREG,op+LOP); | |
3916 } | |
440 | 3917 #else |
3918 error(TYERR); | |
3919 #endif | |
338 | 3920 } else { |
426 | 3921 if (post) { |
445 | 3922 n1 = list3(LVAR,new_lvar(size_of_int),0); |
426 | 3923 code_assign_lvar(cadr(n1),USE_CREG,0); |
3924 } | |
3925 emit_push(); | |
3926 g_expr(e3); | |
3927 code_register_assop((e2=emit_pop(0)),USE_CREG,op,size(type)); | |
3928 if (use) { | |
3929 code_register(e2,USE_CREG); | |
3930 } | |
3931 emit_pop_free(e2); | |
338 | 3932 } |
426 | 3933 use=post?0:suse; |
3934 code_bit_replace(e2=emit_pop(0),USE_CREG,t); | |
3935 emit_pop_free(e2); | |
3936 use = suse; | |
427 | 3937 if (post&&use) { g_expr(rvalue_t(n1,type));} |
3938 if (n1) free_lvar(cadr(n1)); | |
3939 if (n2) free_lvar(cadr(n2)); | |
3940 | |
338 | 3941 return type; |
329 | 3942 } |
3943 | |
3944 #endif | |
3945 | |
327 | 3946 /* temporal local variable free list */ |
3947 | |
3948 static int lvar_list,lvar_free_list; | |
3949 | |
3950 extern int | |
3951 new_lvar0(int sz) | |
3952 { | |
397 | 3953 switch (disp_align) { |
3954 default: | |
3955 case 0: return disp-=sz; | |
3956 case 4: | |
3957 disp-=sz; | |
409 | 3958 if (sz>=4) disp &= -4; |
397 | 3959 return disp; |
3960 } | |
327 | 3961 } |
3962 | |
3963 extern int | |
3964 new_lvar(int size) | |
3965 { | |
3966 int lvar,plvar; | |
3967 | |
3968 for (plvar = 0,lvar = lvar_free_list;lvar;lvar = cadr(lvar)) { | |
3969 if (caddr(lvar)==size) { | |
3970 if (plvar) cadr(plvar) = cadr(lvar); | |
3971 else lvar_free_list = cadr(lvar); | |
3972 break; | |
3973 } | |
3974 plvar = lvar; | |
3975 } | |
3976 if (!lvar) { | |
3977 lvar_list = glist3((lvar=new_lvar0(size)),lvar_list,size); | |
3978 } else { | |
3979 cadr(lvar) = lvar_list; lvar_list = lvar; | |
3980 lvar = car(lvar_list); | |
3981 } | |
3982 return lvar; | |
3983 } | |
3984 | |
3985 extern void | |
3986 free_lvar(int disp) | |
3987 { | |
3988 int lvar,plvar; | |
3989 | |
3990 for (plvar = 0,lvar = lvar_list;lvar;lvar = cadr(lvar)) { | |
3991 if (car(lvar)==disp) { | |
3992 if (plvar) cadr(plvar) = cadr(lvar); | |
3993 else lvar_list = cadr(lvar); | |
3994 break; | |
3995 } | |
3996 plvar = lvar; | |
3997 } | |
3998 if (!lvar) error(-1); | |
3999 cadr(lvar) = lvar_free_list; lvar_free_list = lvar; | |
4000 } | |
4001 | |
4002 extern void | |
4003 init_free_lvar_list() | |
4004 { | |
4005 int lvar; | |
4006 while((lvar=lvar_list)) { | |
4007 lvar_list=cadr(lvar_list); | |
4008 free_glist3(lvar); | |
4009 } | |
4010 while((lvar=lvar_free_list)) { | |
4011 lvar_free_list=cadr(lvar_free_list); | |
4012 free_glist3(lvar); | |
4013 } | |
4014 } | |
4015 | |
4016 extern void | |
456 | 4017 gen_comment(char *s) |
4018 { | |
4019 if (!chk) | |
4020 code_comment(s); | |
4021 } | |
4022 | |
4023 extern void | |
327 | 4024 gen_code_enter(char *name) |
4025 { | |
4026 code_enter(name); | |
4027 } | |
4028 | |
4029 extern void | |
4030 gen_code_enter1(int args) | |
4031 { | |
4032 code_enter1(args); | |
4033 } | |
4034 | |
4035 extern void | |
4036 gen_code_leave(char *name) | |
4037 { | |
4038 code_leave(name); | |
4039 } | |
4040 | |
4041 extern void | |
4042 gen_enter(char *name) | |
4043 { | |
4044 enter(name); | |
4045 } | |
4046 | |
4047 extern void | |
4048 gen_enter1() | |
4049 { | |
4050 enter1(); | |
4051 } | |
4052 | |
4053 extern void | |
4054 gen_leave(int control, char *name) | |
4055 { | |
4056 leave(control,name); | |
4057 } | |
4058 | |
4059 extern void | |
4060 gen_jmp(int l) | |
4061 { | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
4062 control=0; |
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
4063 if (!pending_jmp) { |
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
4064 pending_jmp = l; |
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
437
diff
changeset
|
4065 } |
327 | 4066 } |
4067 | |
363 | 4068 extern void |
4069 gen_indirect_goto(int e1) | |
4070 { | |
4071 g_expr(e1); | |
4072 code_indirect_jmp(USE_CREG); | |
4073 } | |
4074 | |
426 | 4075 /* |
4076 make bit mask | |
4077 MSB 1 2 3 4 .... 29 30 31 LSB | |
4078 */ | |
336 | 4079 extern int |
4080 make_mask(int from,int to) | |
4081 { | |
4082 int mask = 0; | |
4083 int bit = 1; | |
4084 int i; | |
4085 if (from<0||from>32) error(-1); | |
4086 for (i=31;from<=i;i--,bit<<=1) { | |
4087 if (i<=to) { | |
4088 mask |= bit; | |
4089 } | |
4090 } | |
4091 return mask; | |
4092 } | |
4093 | |
341 | 4094 #define MAX_PTR_CACHE 10 |
4095 | |
4096 static int ptr_cache=0; | |
4097 static int ptr_cache_last=0; | |
4098 | |
426 | 4099 /* |
4100 global name pointer cache | |
4101 */ | |
4102 | |
341 | 4103 extern void |
4104 init_ptr_cache() | |
4105 { | |
4106 int i; | |
4107 for(i=0;i<MAX_PTR_CACHE-1;i++) { | |
4108 ptr_cache=glist3(0,ptr_cache,0); | |
4109 } | |
4110 ptr_cache_last=ptr_cache; | |
4111 } | |
4112 | |
4113 extern void | |
4114 clear_ptr_cache_reg(int r) | |
4115 { | |
4116 int ptcptr=ptr_cache; | |
4117 int prev = 0; | |
4118 while(ptcptr!=ptr_cache_last) { | |
4119 if(car(ptcptr)&&caddr(ptcptr)==r) { | |
4120 free_register(r); caddr(ptcptr)=-1; car(ptcptr)=0; | |
4121 // remove me | |
4122 if (prev) cadr(prev) = cadr(ptcptr); | |
4123 else ptr_cache = cadr(ptcptr); | |
4124 // add me to the next of ptr_cache_last | |
4125 cadr(ptcptr) = cadr(ptr_cache_last); | |
4126 cadr(ptr_cache_last) = ptcptr; | |
4127 return; | |
4128 } | |
4129 ptcptr=cadr(prev=ptcptr); | |
4130 } | |
4131 } | |
4132 | |
4133 extern int | |
4134 last_ptr_cache() | |
4135 { | |
4136 int ptcptr=ptr_cache; | |
4137 int r = 0; | |
4138 while(ptcptr!=ptr_cache_last) { | |
4139 r = caddr(ptcptr); | |
4140 ptcptr=cadr(ptcptr); | |
4141 } | |
4142 return r; | |
4143 } | |
4144 | |
4145 | |
4146 extern void | |
4147 clear_ptr_cache() | |
4148 { | |
4149 int ptcptr=ptr_cache; | |
4150 while(ptcptr!=ptr_cache_last) { | |
4151 free_register(caddr(ptcptr)); caddr(ptcptr)=-1; car(ptcptr)=0; | |
4152 ptcptr=cadr(ptcptr); | |
4153 } | |
4154 ptr_cache_last = ptr_cache; | |
4155 } | |
4156 | |
4157 | |
4158 extern int | |
4159 get_ptr_cache(NMTBL *nptr) | |
4160 { | |
4161 int r; | |
4162 int ptcptr=ptr_cache; | |
4163 int g = (int)nptr; | |
4164 int prev=0,p; | |
4165 | |
4166 // linear search cache | |
4167 while(ptcptr!=ptr_cache_last) { | |
4168 if(car(ptcptr)==g) { | |
4169 if (prev) { | |
4170 // make this top | |
4171 cadr(prev)=cadr(ptcptr); | |
4172 cadr(ptcptr) = ptr_cache; | |
4173 ptr_cache = ptcptr; | |
4174 } | |
4175 return caddr(ptcptr); | |
4176 } | |
4177 ptcptr=cadr(prev=ptcptr); | |
4178 } | |
4179 if (!cadr(ptr_cache_last)) { | |
4180 // cache is full | |
4181 if (prev) { | |
4182 // remove oldest cache and it becomes the last | |
4183 free_register(caddr(prev)); caddr(ptcptr)=-1; car(ptcptr)=0; | |
4184 ptr_cache_last = prev; | |
4185 } | |
4186 else error(-1); | |
4187 } | |
430 | 4188 r = get_register(0); // some ptr cache may remove by this |
341 | 4189 caddr(p = cadr(ptr_cache_last)) = r; |
4190 car(p) = g; | |
4191 use_ptr_cache(r); | |
4192 | |
4193 cadr(ptr_cache_last) = cadr(p); | |
4194 cadr(p) = ptr_cache; | |
4195 ptr_cache = p; | |
4196 code_ptr_cache_def(r,nptr); | |
4197 return r; | |
4198 } | |
4199 | |
366 | 4200 extern int |
4201 ilog(int i) | |
4202 { | |
426 | 4203 /* number of bit (i-1) is better? */ |
366 | 4204 switch(i) { |
4205 case 2: return 1; | |
4206 case 4: return 2; | |
4207 case 8: return 3; | |
4208 case 16: return 4; | |
4209 case 32: return 5; | |
4210 case 64: return 6; | |
4211 case 128: return 7; | |
4212 case 256: return 8; | |
4213 case 512: return 9; | |
4214 case 1024: return 10; | |
4215 case 2048: return 11; | |
4216 case 4096: return 12; | |
4217 case 8192: return 13; | |
4218 case 16384: return 14; | |
4219 case 32768: return 15; | |
4220 case 65536: return 16; | |
4221 case 131072: return 17; | |
4222 case 262144: return 18; | |
4223 case 524288: return 19; | |
4224 } | |
4225 return 0; | |
4226 } | |
341 | 4227 |
61 | 4228 /* end */ |