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