blob: 4e76920fea1916c3c51e9fe5e42356ff85eac11d [file] [log] [blame]
PulkoMandy17fc7592022-07-28 18:27:54 +02001/* $VER: vbcc (ic.c) $Revision: 1.65 $ */
2
3#include "vbc.h"
4#include "opt.h"
5
6#define RNOSAVE 32 /* register does not have to be saved across call */
7#define RHALF 64 /* half of a register pair was already allocated */
8
9static char FILE_[]=__FILE__;
10
11static IC *first_pushed;
12static unsigned int opushed;
13static int volatile_convert;
14
15int do_arith(np,IC *,np,obj *);
16static obj *postop_obj;
17static int postop_type;
18np gen_libcall(char *fname,np arg1,type *t1,np arg2,type *t2);
19
20static void handle_reglist(regargs_list *,obj *);
21
22static void fix_pushic(IC **pushic,IC *new)
23{
24 IC *p=last_ic;
25 while(p&&p->code==FREEREG) p=p->prev;
26 if(new==*pushic&&new!=p){
27 if(DEBUG&1){
28 printf("pushic converted to:\n");
29 pric2(stdout,p);
30 }
31 *pushic=p;
32 }
33}
34
35#if HAVE_LIBCALLS
36/* avoid calling use_libcall with illegal operands */
37static char *use_libcall_wrap(int c,int t,int t2)
38{
39 if(optflags&2)
40 return 0;
41
42 if(c==PMULT) c=MULT;
43 if((c>=OR&&c<=AND)||(c>=LSHIFT&&c<=KOMPLEMENT)||c==COMPARE||c==CONVERT||c==MINUS||c==TEST)
44 return use_libcall(c,t,t2);
45 return 0;
46}
47#endif
48
49void gen_test(obj *o,int t,int branch,int label)
50/* Generiert ein test o, branch label und passt auf, dass */
51/* kein TEST const generiert wird. */
52{
53 IC *new;
54 if(o->flags&KONST){
55 eval_const(&o->val,t);
56 if(zldeqto(vldouble,d2zld(0.0))&&zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))){
57 if(branch==BEQ) branch=BRA; else branch=0;
58 }else{
59 if(branch==BNE) branch=BRA; else branch=0;
60 }
61 }else{
62#if HAVE_LIBCALLS
63 static node n={TEST},nn={REINTERPRET};
64 static type nt,it={INT};
65 char *libname;
66 n.left=&nn;
67 n.ntyp=&it;
68 nn.ntyp=&nt;
69 nt.flags=t;
70 n.o=nn.o=*o;
71 if(libname=use_libcall_wrap(TEST,t,0)){
72 new=new_IC();
73 new->code=TEST;
74 new->q2.flags=new->z.flags=0;
75 new->typf=INT;
76 new->q1=gen_libcall(libname,&nn,&nt,0,0)->o;
77 add_IC(new);
78 }else{
79#endif
80 new=new_IC();
81 new->code=TEST;
82 new->q2.flags=new->z.flags=0;
83 new->typf=t;
84 new->q1=*o;
85 add_IC(new);
86#if HAVE_LIBCALLS
87 }
88#endif
89 }
90 if(branch){
91 new=new_IC();
92 new->code=branch;
93 new->typf=label;
94 add_IC(new);
95 }
96}
97
98/* remove a freereg if a scratch register is needed more than once */
99static void keep_reg(int r)
100{
101 IC *n;
102 if(nocode) return;
103 n=last_ic;
104 while(n){
105 if(n->code==CALL&&regscratch[r]){
106 IC *ret;
107 regs[r]=1;
108 savescratch(MOVEFROMREG,n->prev,0,&n->q1);
109 ret=n->next;
110 while(ret->code==ALLOCREG||ret->code==FREEREG)
111 ret=ret->next;
112 if(ret->code==GETRETURN){
113 if((ret->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&ret->z.reg==r)
114 ret->z.flags&=~REG;
115 }else
116 ret=ret->prev;
117 savescratch(MOVETOREG,ret,0,&n->q1);
118 }
119 if(n->code==FREEREG&&n->q1.reg==r){
120 remove_IC(n);
121 if(!nocode)
122 regs[r]=1;
123 break;
124 }
125 n=n->prev;
126 }
127}
128
129/* Generate code to insert a bitfield */
130void insert_bitfield(obj *dest,obj *src,obj *val,int bfs,int bfo,int t,int isclear)
131{
132 /*FIXME: shortcut beachten? */
133 IC *new;
134 obj tmp1,tmp2,tmp3;
135 int vmerk;
136 bfo=bflayout(bfo,bfs,t);
137 if((dest->flags&REG)&&!regs[dest->reg])
138 keep_reg(dest->reg);
139 new=new_IC();
140 new->code=AND;
141 new->typf=t;
142 new->q1=*src;
143 new->q1.flags&=~SCRATCH;
144 new->q2.flags=KONST;
145 gval.vmax=zmsub(zmlshift(l2zm(1L),l2zm((int)bfs)),l2zm(1L));
146 eval_const(&gval,MAXINT);
147 insert_const(&new->q2.val,t);
148 get_scratch(&new->z,t,0,0);
149 tmp1=new->z;
150 if((new->q1.flags&(KONST|DREFOBJ))==KONST){
151 calc(AND,new->typf,&new->q1.val,&new->q2.val,&new->q1.val,0);
152 new->code=ASSIGN;
153 new->q2.flags=0;
154 new->q2.val.vmax=sizetab[new->typf&NQ];
155 }
156 *val=tmp1;
157 vmerk=val->flags;
158 tmp1.flags&=~SCRATCH;
159 add_IC(new);
160 if(bfo!=0){
161 new=new_IC();
162 new->code=LSHIFT;
163 new->typf=t;
164 new->typf2=INT;
165 new->q1=tmp1;
166 new->q2.flags=KONST;
167 new->q2.val.vint=zm2zi(l2zm((long)bfo));
168 get_scratch(&new->z,t,0,0);
169 tmp3=new->z;
170 add_IC(new);
171 }else{
172 tmp3=tmp1;
173 }
174 if(!isclear){
175 new=new_IC();
176 new->code=AND;
177 new->typf=t;
178 new->q1=*dest;
179 new->q1.flags&=~SCRATCH;
180 new->q2.flags=KONST;
181 gval.vmax=zmkompl(zmlshift(zmsub(zmlshift(l2zm(1L),l2zm((int)bfs)),l2zm(1L)),l2zm((long)bfo)));
182 eval_const(&gval,MAXINT);
183 insert_const(&new->q2.val,t);
184 get_scratch(&new->z,t,0,0);
185 tmp2=new->z;
186 add_IC(new);
187 }
188 new=new_IC();
189 new->code=OR;
190 new->typf=t;
191 if(isclear)
192 new->q1=*dest;
193 else
194 new->q1=tmp2;
195 new->q2=tmp3;
196 new->z=*dest;
197 add_IC(new);
198 if(dest->flags&(REG|SCRATCH)) free_reg(dest->reg);
199 val->flags=vmerk;
200}
201
202void inline_memcpy(np z,np q,zmax size)
203/* fuegt ein ASSIGN-IC ein, das memcpy(z,q,size) entspricht */
204{
205 IC *new=new_IC();
206 if(!ISPOINTER(z->ntyp->flags)) {error(39);return;}
207 if(!ISPOINTER(q->ntyp->flags)) {error(39);return;}
208
209 if(z->flags==ADDRESS||z->flags==ADDRESSA||z->flags==ADDRESSS){
210 gen_IC(z,0,0);
211 new->z=z->left->o;
212 if(z->flags!=ADDRESSS&&z->left->flags==IDENTIFIER&&is_vlength(z->left->ntyp)){
213 /* variable length array */
214 new->z.flags|=DREFOBJ;
215 new->z.dtyp=POINTER_TYPE(z->ntyp->next);
216 }
217 }else{
218 gen_IC(z,0,0);
219 if(z->o.flags&DREFOBJ){
220 IC *n2=new_IC();
221 n2->code=ASSIGN;
222 n2->typf=q->ntyp->flags;
223 n2->q1=z->o;
224 get_scratch(&n2->z,z->ntyp->flags,z->ntyp->next->flags,z->ntyp);
225 n2->q2.flags=0;
226 n2->q2.val.vmax=sizetab[POINTER_TYPE(z->ntyp->next)];
227 new->z=n2->z;
228 add_IC(n2);
229 }else{
230 new->z=z->o;
231 }
232 if(new->z.flags&VARADR){
233 new->z.flags&=~VARADR;
234 }else{
235 new->z.flags|=DREFOBJ;
236 new->z.dtyp=POINTER_TYPE(z->ntyp->next);
237 }
238 }
239 if(z->ntyp->next->flags&VOLATILE){
240 if(new->z.flags&DREFOBJ)
241 new->z.dtyp|=PVOLATILE;
242 }
243 if(q->flags==ADDRESS||q->flags==ADDRESSA||q->flags==ADDRESSS){
244 gen_IC(q,0,0);
245 new->q1=q->left->o;
246 if(q->flags!=ADDRESSS&&q->left->flags==IDENTIFIER&&is_vlength(q->left->ntyp)){
247 /* variable length array */
248 new->q1.flags|=DREFOBJ;
249 new->q1.dtyp=POINTER_TYPE(q->ntyp->next);
250 }
251 }else{
252 gen_IC(q,0,0);
253 if(q->o.flags&DREFOBJ){
254 IC *n2=new_IC();
255 n2->code=ASSIGN;
256 n2->typf=q->ntyp->flags;
257 n2->q1=q->o;
258 get_scratch(&n2->z,q->ntyp->flags,q->ntyp->next->flags,q->ntyp);
259 n2->q2.flags=0;
260 n2->q2.val.vmax=sizetab[POINTER_TYPE(q->ntyp->next)];
261
262 new->q1=n2->z;
263 add_IC(n2);
264 }else{
265 new->q1=q->o;
266 }
267 if(new->q1.flags&VARADR){
268 new->q1.flags&=~VARADR;
269 }else{
270 new->q1.flags|=DREFOBJ;
271 new->q1.dtyp=POINTER_TYPE(q->ntyp->next);
272 }
273 }
274 if(q->ntyp->next->flags&VOLATILE){
275 if(new->q1.flags&DREFOBJ)
276 new->q1.dtyp|=PVOLATILE;
277 }
278 new->code=ASSIGN;
279 new->typf=UNSIGNED|CHAR;
280 new->q2.flags=0;
281 new->q2.val.vmax=size;
282
283 if(!zmeqto(size,Z0))
284 add_IC(new);
285}
286
287void add_IC(IC *new)
288/* fuegt ein IC ein */
289{
290 int code;
291 if(!new) return;
292 if(nocode) {
293#ifdef HAVE_MISRA
294/* removed */
295#endif
296 /*free(new);*/ /* building a list to free later would be nice... */
297 return;
298 }
299 new->next=0;
300 new->q1.am=new->q2.am=new->z.am=0;
301 new->line=line; new->file=filename;
302 code=new->code;
303 if(code>=BEQ&&code<=BRA) new->q1.flags=new->q2.flags=new->z.flags=0;
304 if(code==ALLOCREG||code==FREEREG||code==SAVEREGS||code==RESTOREREGS) new->typf=0;
305 if(DEBUG&64){ pric(stdout,first_ic);printf("new\n");pric2(stdout,new);printf("-\n");}
306 if(new->q1.flags&VAR){
307 if(!new->q1.v)
308 ierror(0);
309 new->q1.v->flags|=USEDASSOURCE;
310 if(code==ADDRESS||(new->q1.flags&VARADR))
311 if(!is_vlength(new->q1.v->vtyp))
312 new->q1.v->flags|=USEDASADR;
313 new->q1.v->priority+=currentpri;
314 }
315 if(new->q2.flags&VAR){
316 if(!new->q2.v) ierror(0);
317 new->q2.v->flags|=USEDASSOURCE;
318 if(code==ADDRESS||(new->q2.flags&VARADR))
319 if(!is_vlength(new->q2.v->vtyp))
320 new->q2.v->flags|=USEDASADR;
321 new->q2.v->priority+=currentpri;
322 }
323 if(new->z.flags&VAR){
324 if(!new->z.v) ierror(0);
325 if(new->z.flags&DREFOBJ)
326 new->z.v->flags|=USEDASSOURCE;
327 else
328 new->z.v->flags|=USEDASDEST;
329 new->z.v->priority+=currentpri;
330 }
331 if(block_vla[nesting]){
332 /* special handling for blocks with variable-length arrays */
333 llist *p;
334 if(new->code==LABEL){
335 p=mymalloc(LSIZE);
336 p->label=new->typf;
337 p->next=vladeflabels[nesting];
338 vladeflabels[nesting]=p;
339 }else if(0&&new->code==BRA&&!(new->flags&LOOP_COND_TRUE)){
340 p=mymalloc(LSIZE);
341 p->label=new->typf;
342 p->next=vlajmplabels[nesting];
343 vlajmplabels[nesting]=p;
344 p=vladeflabels[nesting];
345 while(p){
346 if(p->label==new->typf)
347 break;
348 p=p->next;
349 }
350 if(!p){
351 /* label not declared in this block so far;
352 re-adjust stack, but store the position - label may be
353 declared later in the same block and adjustement must be
354 removed */
355 vlaadjust_list *vl;
356 IC *first;
357 first=last_ic;
358 freevl();
359 first=first->next;
360 vl=mymalloc(sizeof(*vl));
361 vl->branch=new;
362 vl->first=first;
363 vl->next=vlaadjusts[nesting];
364 vlaadjusts[nesting]=vl;
365 }
366 }
367 }
368 if(/*(c_flags_val[0].l&2)&&*/code==LABEL){
369 /* entfernt Spruenge zu direkt folgenden Labels */
370 IC *p=last_ic;
371 while(p){
372 if(p->typf==new->typf&&p->code>=BEQ&&p->code<=BRA){
373 IC *n;
374 if(p->code!=BRA){
375 IC *cmp=p->prev;
376 while(cmp&&cmp->code==FREEREG) cmp=cmp->prev;
377 if(cmp->code==TEST){
378 if(is_volatile_obj(&cmp->q1))
379 break;
380 else{
381 if(DEBUG&1) printf("preceding test removed\n");
382 remove_IC(cmp);
383 }
384 }else if(cmp->code==COMPARE){
385 if(is_volatile_obj(&cmp->q1)||is_volatile_obj(&cmp->q2))
386 break;
387 else{
388 if(DEBUG&1) printf("preceding compare removed\n");
389 remove_IC(cmp);
390 }
391 }else
392 break;
393 }
394 if(vlaadjusts[nesting]){
395 /* remove it from vlaadjusts-lists, if necessary */
396 vlaadjust_list *vl=vlaadjusts[nesting];
397 while(vl){
398 if(vl->branch==p){
399 IC *np=vl->branch->prev;
400 while(np!=vl->first->prev){
401 if(!np) ierror(0);
402 np->code=NOP;
403 np->q1.flags=np->q2.flags=np->z.flags=0;
404 np=np->prev;
405 }
406 vl->branch=0;
407 }
408 vl=vl->next;
409 }
410 }
411 if(DEBUG&1) printf("%s l%d deleted\n",ename[p->code],p->typf);
412 n=p->next;
413 remove_IC(p);
414 p=n;
415 }else{
416 if(p->code!=LABEL) break;
417 p=p->prev;
418 }
419 }
420 }
421 if(last_ic){
422 if(code==ASSIGN){
423 if((last_ic->z.flags&(REG|SCRATCH|DREFOBJ))==(REG|SCRATCH)&&(new->q1.flags==last_ic->z.flags)&&last_ic->z.reg==new->q1.reg/*&&last_ic->code!=CALL*/){
424 if(USEQ2ASZ||!(last_ic->q2.flags&REG)||!(new->z.flags&REG)||last_ic->q2.reg!=new->z.reg){
425 if(USEQ2ASZ||!(last_ic->q2.flags&VAR)||!(new->z.flags&VAR)||last_ic->q2.v!=new->z.v){
426 /* verbindet op a,b->reg,move reg->c zu op a,b->c */
427 /* hier fehlt aber noch Registerfreigabe */
428 last_ic->z=new->z;
429 if(DEBUG&1) printf("move and op combined\n");
430 if((new->q1.flags&(SCRATCH|REG))==(SCRATCH|REG)&&(new->q1.reg!=new->z.reg||!(new->z.flags&REG)))
431 free_reg(new->q1.reg);
432 free(new);
433 return;
434 }
435 }
436 }
437 if((last_ic->z.flags&(VAR|SCRATCH|DREFOBJ))==(VAR|SCRATCH)&&(new->q1.flags==last_ic->z.flags)&&last_ic->z.v==new->q1.v/*&&last_ic->code!=CALL*/){
438 if(USEQ2ASZ||!(last_ic->q2.flags&REG)||!(new->z.flags&REG)||last_ic->q2.reg!=new->z.reg){
439 if(USEQ2ASZ||!(last_ic->q2.flags&VAR)||!(new->z.flags&VAR)||last_ic->q2.v!=new->z.v){
440 /* verbindet op a,b->scratch,move scratch->c zu op a,b->c */
441 /* hier fehlt aber noch Registerfreigabe */
442 last_ic->z=new->z;
443 if(DEBUG&1) printf("move and op combined(2)\n");
444/* if((new->q1.flags&(SCRATCH|REG))==(SCRATCH|REG)&&(new->q1.reg!=new->z.reg||!(new->z.flags&REG)))
445 free_reg(new->q1.reg);*/
446 free(new);
447 return;
448 }
449 }
450 }
451
452 }
453 if(last_ic->code==BRA){
454 if(!dontdelete&&code!=LABEL&&code!=ALLOCREG&&code!=FREEREG){
455 /* loescht alles nach bra bis ein Label kommt */
456 /* momentan noch nicht perfekt, da es bei alloc/freereg stoppt */
457 free(new);
458#ifdef HAVE_MISRA
459/* removed */
460#endif
461 if(DEBUG&1) printf("Unreachable Statement deleted\n");
462 return;
463 }
464 if(last_ic->prev&&code==LABEL){
465 /* ersetzt bcc l1;bra l2;l1 durch b!cc l2 */
466 if(last_ic->prev->code>=BEQ&&last_ic->prev->code<=BGT&&new->typf==last_ic->prev->typf){
467 if(last_ic->next) pric2(stdout,last_ic->next);
468 if(DEBUG&1) printf("%s l%d;%s l%d; substituted\n",ename[last_ic->prev->code],last_ic->prev->typf,ename[last_ic->code],last_ic->typf);
469 if(last_ic->prev->code&1)
470 last_ic->prev->code--;
471 else
472 last_ic->prev->code++;
473 last_ic->prev->typf=last_ic->typf;
474 last_ic=last_ic->prev;
475 free(last_ic->next);
476 last_ic->next=new;new->prev=last_ic;
477 last_ic=new;
478 return;
479 }
480 }
481 }
482/* }*/
483 new->prev=last_ic;
484 last_ic->next=new;
485 last_ic=new;
486 }else{
487 last_ic=new;first_ic=new;new->prev=0;
488 }
489 ic_count++;
490
491#if HAVE_POF2OPT
492 if(((new->code==MULT)||((new->code==DIV||new->code==MOD)&&(new->typf&UNSIGNED)))&&(new->q2.flags&KONST)&&ISINT(new->typf)){
493 /* ersetzt mul etc. mit Zweierpotenzen */
494 long ln;
495 eval_const(&new->q2.val,new->typf);
496 if(zmleq(l2zm(0L),vmax)&&zumleq(ul2zum(0UL),vumax)){
497 if(ln=get_pof2(vumax)){
498 if(new->code==MOD){
499 vmax=zmsub(vmax,l2zm(1L));
500 new->code=AND;
501 }else{
502 if(new->code==DIV) new->code=RSHIFT; else new->code=LSHIFT;
503 vmax=l2zm(ln-1);
504 }
505 gval.vmax=vmax;
506 eval_const(&gval,MAXINT);
507 insert_const(&new->q2.val,new->typf);
508 new->typf2=new->typf;
509 }
510 }
511 }
512#endif
513
514 /* Merken, on Fliesskomma benutzt wurde */
515 if(code!=LABEL&&(code<BEQ||code>BRA)){
516 if(ISFLOAT(new->typf)) float_used=1;
517 if(code==CONVERT&&ISFLOAT(new->typf2)) float_used=1;
518 }
519 if((new->q1.flags&(SCRATCH|REG))==(SCRATCH|REG)&&(!(new->z.flags&REG)||new->q1.reg!=new->z.reg))
520 free_reg(new->q1.reg);
521 if((new->q2.flags&(SCRATCH|REG))==(SCRATCH|REG)&&(!(new->z.flags&REG)||new->q2.reg!=new->z.reg))
522 free_reg(new->q2.reg);
523}
524
525np gen_libcall(char *fname,np arg1,type *t1,np arg2,type *t2)
526/* generate call to a library function (emulate operation) */
527{
528 np new;
529 argument_list *al=0,*t;
530 new=new_node();
531 new->flags=CALL;
532 new->right=0;
533 new->left=new_node();
534 new->left->flags=IDENTIFIER;
535 new->left->left=new->left->right=0;
536 new->left->identifier=add_identifier(fname,strlen(fname));
537 new->left->ntyp=0;
538 new->left->sidefx=0;
539 new->left->val.vmax=l2zm(0L);
540 new->alist=0;
541 if(arg1){
542 al=mymalloc(sizeof(*al));
543 if(postop_obj){
544 al->arg=new_node();
545 al->arg->o=*postop_obj;
546 al->arg->ntyp=new_typ();
547 al->arg->ntyp->flags=postop_type;
548 al->arg->flags=REINTERPRET;
549 }else
550 al->arg=arg1;
551 al->next=0;
552 if(t1){
553 np cnv=new_node();
554 cnv->flags=CAST;
555 cnv->left=arg1;
556 cnv->right=0;
557 cnv->ntyp=t1;
558 al->arg=cnv;
559 }
560 }
561 if(arg2){
562 t=mymalloc(sizeof(*t));
563 t->arg=arg2;
564 t->next=0;
565 al->next=t;
566 if(t2){
567 np cnv=new_node();
568 cnv->flags=CAST;
569 cnv->left=arg2;
570 cnv->right=0;
571 cnv->ntyp=t2;
572 t->arg=cnv;
573 }
574 }
575 new->alist=al;
576 /* Kann man type_expr nochmal auf die Argumente anwenden? */
577 if(t1||t2)
578 no_cast_free=1;
579 if(!type_expression(new,0))
580 ierror(0);
581 no_cast_free=0;
582 gen_IC(new,0,0);
583 return new;
584}
585
586
587void gen_IC(np p,int ltrue,int lfalse)
588/* Erzeugt eine IC-Liste aus einer expression */
589{
590 IC *new; regargs_list *rl;
591 if(!p) return;
592
593 if(p->flags==STRING){
594 Var *v=0;
595 if(merge_strings){
596 for(v=first_var[0];v;v=v->next){
597 if(v->vtyp->flags==ARRAY&&(v->vtyp->next->flags&STRINGCONST)&&zmleq(p->ntyp->size,v->vtyp->size)){
598 zmax i;const_list *cl1=p->cl,*cl2=v->clist;
599 for(i=Z0;!zmleq(p->ntyp->size,i)&&cl1&&cl2;cl1=cl1->next,cl2=cl2->next,i=zmadd(i,Z1)){
600 if(!zumeqto(zuc2zum(cl1->other->val.vuchar),zuc2zum(cl2->other->val.vuchar)))
601 break;
602 }
603 if(zmleq(p->ntyp->size,i)) break;
604 }
605 }
606 }
607 if(!v){
608 p->o.v=add_var(empty,clone_typ(p->ntyp),STATIC,p->cl);
609 p->o.v->flags|=DEFINED;
610 }else
611 p->o.v=v;
612 p->o.flags=VAR;
613 p->o.reg=0;
614 p->o.val=p->val;
615 return;
616 }
617 if(p->flags==LITERAL){
618 int sc;
619 if(nesting==0||(is_const(p->ntyp)&&zmeqto(p->val.vmax,l2zm(0L))))
620 sc=STATIC;
621 else
622 sc=AUTO;
623 p->o.v=add_var(empty,clone_typ(p->ntyp),sc,p->cl);
624 p->o.v->flags|=DEFINED;
625 p->o.flags=VAR;
626 p->o.reg=0;
627 p->o.val.vmax=l2zm(0L);
628 if(sc==AUTO)
629 init_local_compound(p->o.v);
630 return;
631 }
632 if(p->flags==IDENTIFIER){
633/* p->o.v=find_var(p->identifier,0);*/
634 p->o.flags=VAR;
635 p->o.reg=0;
636 p->o.val=p->val;
637 return;
638 }
639 if(p->flags==CEXPR||p->flags==PCEXPR){
640 if(p->left){
641 if(p->left->flags==POSTINC) p->left->flags=PREINC;
642 if(p->left->flags==POSTDEC) p->left->flags=PREDEC;
643 gen_IC(p->left,0,0);
644 if((p->left->o.flags&(SCRATCH|REG))==(SCRATCH|REG)) free_reg(p->left->o.reg);
645 }
646 if(p->right){
647 if(p->right->flags==POSTINC) p->right->flags=PREINC;
648 if(p->right->flags==POSTDEC) p->right->flags=PREDEC;
649 gen_IC(p->right,0,0);
650 if((p->right->o.flags&(SCRATCH|REG))==(SCRATCH|REG)) free_reg(p->right->o.reg);
651 }
652 p->o.flags=KONST;
653 p->o.val=p->val;
654 p->o.reg=0;
655 return;
656 }
657 if(p->flags==KOMMA){
658 if(p->left->sidefx){
659 gen_IC(p->left,0,0);
660 if((p->left->o.flags&(SCRATCH|REG))==(SCRATCH|REG)) free_reg(p->left->o.reg);
661 }else if(!(p->left->ntyp->flags&VOLATILE))
662 error(129);
663 gen_IC(p->right,0,0);
664 p->o=p->right->o;
665 return;
666 }
667 if(p->flags==REINTERPRET){
668 if(p->left){
669 gen_IC(p->left,0,0);
670 p->o=p->left->o;
671 }
672 /* if no left, do nothing, use just object */
673 return;
674 }
675 if(p->flags==CAST){
676 gen_IC(p->left,0,0);
677 if((p->ntyp->flags&NQ)==VOID){
678 if((p->left->o.flags&(SCRATCH|REG))==(SCRATCH|REG)) free_reg(p->left->o.reg);
679 p->o.flags=0;
680 }else{
681 if(ISPOINTER(p->ntyp->flags)&&(p->ntyp->next->flags&VOLATILE))
682 volatile_convert=1;
683 convert(p->left,p->ntyp->flags);
684 if(volatile_convert){
685 if((p->left->o.flags&VAR)&&p->left->o.v->vtyp->next)
686 p->left->o.v->vtyp->next->flags|=VOLATILE;
687 volatile_convert=0;
688 }
689 p->o=p->left->o;
690 }
691 return;
692 }
693 if(p->flags==FIRSTELEMENT){
694 gen_IC(p->left,0,0);
695 p->o=p->left->o;
696 return;
697 }
698
699#if HAVE_POF2OPT
700 if(((p->flags==MULT||p->flags==PMULT)||((p->flags==DIV||p->flags==MOD)&&(p->ntyp->flags&UNSIGNED)))&&(p->right->flags==CEXPR||p->right->flags==PCEXPR)&&ISINT(p->ntyp->flags)){
701 /* ersetzt mul etc. mit Zweierpotenzen */
702 long ln;
703 eval_constn(p->right);
704 if(zmleq(l2zm(0L),vmax)&&zumleq(ul2zum(0UL),vumax)){
705 if(ln=get_pof2(vumax)){
706 if(p->flags==MOD){
707 vmax=zmsub(vmax,l2zm(1L));
708 p->flags=AND;
709 }else{
710 if(p->flags==DIV) p->flags=RSHIFT; else p->flags=LSHIFT;
711 vmax=l2zm(ln-1);
712 }
713 gval.vmax=vmax;
714 eval_const(&gval,MAXINT);
715 insert_constn(p->right);
716 }
717 }
718 }
719#endif
720
721#if HAVE_LIBCALLS
722 if(!(optflags&2)){
723 char *libname;
724 if(libname=use_libcall_wrap(p->flags,p->ntyp->flags,0)){
725 np lc;type *t1,*t2;
726 if(p->flags==LSHIFT||p->flags==RSHIFT){
727 t1=clone_typ(p->ntyp);
728 t2=new_typ();
729 t2->flags=INT;
730 }else{
731 if(p->right){
732 t1=arith_typ(p->left->ntyp,p->right->ntyp);
733 t2=clone_typ(t1);
734 }else{
735 t1=arith_typ(p->left->ntyp,p->left->ntyp);
736 t2=0;
737 }
738 }
739 lc=gen_libcall(libname,p->left,t1,p->right,t2);
740 *p=*lc;
741 free(lc);
742 return;
743 }
744 }
745#endif
746 new=new_IC();
747 new->typf=p->ntyp->flags;
748 new->q1.reg=new->q2.reg=new->z.reg=0;
749 new->q1.flags=new->q2.flags=new->z.flags=0;
750 if((p->flags>=LSHIFT&&p->flags<=MOD)||(p->flags>=OR&&p->flags<=AND)||p->flags==PMULT){
751 do_arith(p,new,0,0);
752 return;
753 }
754 if(p->flags==CONTENT){
755 gen_IC(p->left,0,0);
756 if(p->left->o.flags&VARADR){
757 free(new);
758 p->o=p->left->o;
759 p->o.flags&=~VARADR;
760 return;
761 }
762 if(!(p->left->o.flags&DREFOBJ)){
763 free(new);
764 p->o=p->left->o;
765 p->o.flags|=DREFOBJ;
766 p->o.dtyp=p->left->ntyp->flags;
767 }else{
768 if((p->left->o.flags&SCRATCH)&&p->left->o.dtyp==POINTER_TYPE(p->ntyp)){
769 new->z=p->left->o;
770 new->z.flags&=~DREFOBJ;
771 }else{
772 get_scratch(&new->z,p->left->ntyp->flags,p->ntyp->flags,p->left->ntyp);
773 }
774 new->code=ASSIGN;new->typf=POINTER_TYPE(p->ntyp);
775 new->q1=p->left->o;
776 new->q2.val.vmax=sizetab[new->typf&NQ];
777 p->o=new->z;
778 add_IC(new);
779 p->o.flags|=DREFOBJ;
780 p->o.dtyp=POINTER_TYPE(p->ntyp);
781 }
782 if(p->left->ntyp->next->flags&VOLATILE) p->o.dtyp|=PVOLATILE;
783 return;
784 }
785 if(p->flags==ASSIGN){
786 if(p->left->flags==BITFIELD){
787 gen_IC(p->right,0,0);
788 gen_IC(p->left->left,0,0);
789 convert(p->right,p->ntyp->flags);
790 insert_bitfield(&p->left->left->o,&p->right->o,&p->o,p->left->bfs,p->left->bfo,p->ntyp->flags&NU,0);
791 return;
792 }
793 new->code=ASSIGN;
794 gen_IC(p->right,0,0);
795 gen_IC(p->left,0,0);
796 convert(p->right,p->ntyp->flags);
797 new->q1=p->right->o;
798 new->z=p->left->o;
799 new->q2.val.vmax=szof(p->left->ntyp);
800 p->o=new->z;
801 if(!ISSCALAR(p->ntyp->flags))
802 new->typf2=zm2l(falign(p->ntyp));
803 add_IC(new);
804 return;
805 }
806 if(p->flags==ASSIGNOP){
807 /* das hier ist nicht besonders schoen */
808 obj o,q;IC *n;int f;char *libname;
809 np lc;
810 if(p->right->right==0){
811 /* sowas wie a+=0 wurde wegoptimiert */
812 free(new);
813 p->o=p->left->o;
814 return;
815 }
816#if HAVE_LIBCALLS
817 if(libname=use_libcall_wrap(p->right->flags,p->right->ntyp->flags,(p->right->flags==LSHIFT||p->right->flags==RSHIFT)?INT:0)){
818 type *t1,*t2;
819 np a1;
820 gen_IC(p->left,0,0);
821 a1=new_node();
822 a1->o=p->left->o;
823 a1->flags=REINTERPRET;
824 a1->o.flags&=~SCRATCH;
825 a1->ntyp=clone_typ(p->left->ntyp);
826 t1=clone_typ(p->right->ntyp);
827 if(p->right->flags==LSHIFT||p->right->flags==RSHIFT){
828 t2=new_typ();
829 t2->flags=INT;
830 }else
831 t2=clone_typ(t1);
832 lc=gen_libcall(libname,a1/*p->right->left*/,t1,p->right->right,t2);
833 /**p->right=*lc;*/
834 o=p->left->o;
835 free(a1);
836 /*p->left=0;*/
837 /*free(lc);*/
838 }else
839#endif
840 {
841 lc=0;
842 f=do_arith(p->right,new,p->left,&o);
843 if(!f) ierror(0);
844 if(f>1) ierror(0);
845 }
846 if((o.flags&(SCRATCH|REG))==(SCRATCH|REG)&&!regs[o.reg])
847 keep_reg(o.reg);
848 if(lc)
849 convert(lc,p->ntyp->flags);
850 else
851 convert(p->right,p->ntyp->flags);
852 if(p->left&&p->left->flags==BITFIELD){
853 if(lc) ierror(0);
854 insert_bitfield(&p->left->left->o,&p->right->o,&p->o,p->left->bfs,p->left->bfo,p->ntyp->flags&NU,0);
855 if((p->right->o.flags&(REG|SCRATCH))==(REG|SCRATCH)&&regs[p->right->o.reg])
856 free_reg(p->right->o.reg);
857 return;
858 }
859 new=new_IC();
860 new->typf=p->ntyp->flags;
861 new->q2.flags=0;
862 new->code=ASSIGN;
863 if(lc){
864 new->q1=lc->o;
865 /*free(lc);*/
866 }else
867 new->q1=p->right->o;
868 new->z=o;
869 new->q2.val.vmax=szof(p->ntyp);
870 p->o=new->z;
871 add_IC(new);
872 return;
873 }
874 if(p->flags==MINUS||p->flags==KOMPLEMENT){
875 new->code=p->flags;
876 gen_IC(p->left,0,0);
877 convert(p->left,p->ntyp->flags);
878 if((p->left->o.flags&(SCRATCH|REG))==(SCRATCH|REG)&&regok(p->left->o.reg,p->ntyp->flags,0)){
879 new->z=p->left->o;
880 new->z.flags&=~DREFOBJ;
881 }else{
882 get_scratch(&new->z,p->ntyp->flags,0,p->ntyp);
883 }
884 new->q1=p->left->o;
885 p->o=new->z;
886 add_IC(new);
887 return;
888 }
889 if(p->flags==ADDRESS||p->flags==ADDRESSA||p->flags==ADDRESSS){
890 if(p->flags!=ADDRESSS&&p->left->flags==IDENTIFIER&&is_vlength(p->left->ntyp)){
891 gen_IC(p->left,0,0);
892 if(!(p->left->o.flags&VAR))
893 ierror(0);
894 free(new);
895 p->o=p->left->o;
896 return;
897 }
898 new->code=ADDRESS;
899 new->typf=p->left->ntyp->flags;
900 new->typf2=POINTER_TYPE(p->left->ntyp);
901 gen_IC(p->left,0,0);
902 if(p->left->o.flags&VAR) p->left->o.v->flags|=(USEDASSOURCE|USEDASDEST);
903 if(p->left->o.flags&DREFOBJ){
904 free(new);
905 p->o=p->left->o;
906 p->o.flags&=~DREFOBJ;
907 return;
908 }
909 if((p->left->o.flags&VAR)&&!(p->left->o.flags&VARADR)
910 &&(p->left->o.v->storage_class==EXTERN||p->left->o.v->storage_class==STATIC)){
911 free(new);
912 p->o=p->left->o;
913 p->o.flags|=VARADR;
914 return;
915 }
916 new->q1=p->left->o;
917 get_scratch(&new->z,POINTER_TYPE(p->ntyp->next),p->ntyp->next->flags,0);
918 p->o=new->z;
919 add_IC(new);
920 return;
921 }
922 if(p->flags==LAND||p->flags==LOR){
923 int l1,l2,l3,l4;
924/* printf("%s true=%d false=%d\n",ename[p->flags],ltrue,lfalse);*/
925
926 if(ISVECTOR(p->ntyp->flags)){
927 do_arith(p,new,0,0);
928 return;
929 }
930
931 l1=++label;
932 if(!ltrue) {l2=++label;l3=++label;l4=++label;}
933 if(!ltrue){
934 if(p->flags==LAND)
935 gen_IC(p->left,l1,l3);
936 else
937 gen_IC(p->left,l3,l1);
938 }else{
939 if(p->flags==LAND)
940 gen_IC(p->left,l1,lfalse);
941 else
942 gen_IC(p->left,ltrue,l1);
943 }
944 if(p->left->o.flags!=0){
945 if(p->flags==LAND)
946 gen_test(&p->left->o,p->left->ntyp->flags,BEQ,((!ltrue)?l3:lfalse));
947 else
948 gen_test(&p->left->o,p->left->ntyp->flags,BNE,((!ltrue)?l3:ltrue));
949 }
950 gen_label(l1);
951 if(!ltrue){
952 if(p->flags==LAND)
953 gen_IC(p->right,l2,l3);
954 else
955 gen_IC(p->right,l3,l2);
956 }else
957 gen_IC(p->right,ltrue,lfalse);
958 if(p->right->o.flags!=0){
959 if(p->flags==LAND)
960 gen_test(&p->right->o,p->right->ntyp->flags,BEQ,((!ltrue)?l3:lfalse));
961 else
962 gen_test(&p->right->o,p->right->ntyp->flags,BNE,((!ltrue)?l3:ltrue));
963 }
964 if(!ltrue){
965 gen_label(l2);
966 if(p->flags==LAND) gen_cond(&p->o,0,l3,l4); else gen_cond(&p->o,1,l3,l4);
967 }else{
968 new=new_IC();
969 new->code=BRA;
970 if(p->flags==LAND) new->typf=ltrue; else new->typf=lfalse;
971 add_IC(new);
972 }
973 if(ltrue) p->o.flags=0;
974 return;
975 }
976 if(p->flags==NEGATION){
977 int l1,l2,l3;
978 if(ISVECTOR(p->ntyp->flags)){
979 gen_IC(p->left,0,0);
980 if((p->left->o.flags&(SCRATCH|REG))==(SCRATCH|REG)&&regok(p->left->o.reg,p->ntyp->flags,0)){
981 new->z=p->left->o;
982 new->z.flags&=~DREFOBJ;
983 }else{
984 get_scratch(&new->z,p->left->ntyp->flags,0,p->left->ntyp);
985 }
986 new->typf=p->left->ntyp->flags;
987 new->q1=p->left->o;
988 p->o=new->z;
989 new->code=NEGATION;
990 add_IC(new);
991 return;
992 }
993 if(!ltrue) {l1=++label;l2=++label;l3=++label;}
994 if(ltrue)
995 gen_IC(p->left,lfalse,ltrue);
996 else
997 gen_IC(p->left,l1,l3);
998 if(!p->left->o.flags){
999 free(new);p->o.flags=0;
1000 }else{
1001 gen_test(&p->left->o,p->left->ntyp->flags,BNE,((!ltrue)?l1:lfalse));
1002 }
1003 if(ltrue){
1004 new=new_IC();
1005 new->code=BRA;
1006 if(!ltrue) new->typf=l2; else new->typf=ltrue;
1007 add_IC(new);
1008 p->o.flags=0;
1009 }else{
1010 gen_label(l3);
1011 gen_cond(&p->o,0,l1,l2);
1012 }
1013 return;
1014 }
1015 if(p->flags>=EQUAL&&p->flags<=GREATEREQ){
1016 int l1,l2,l3,tl,tr;
1017 type *at=0;
1018 char *libname;
1019 if(ISVECTOR(p->ntyp->flags)){
1020 do_arith(p,new,0,0);
1021 return;
1022 }
1023 if(!ltrue) {l1=++label;l2=++label;l3=++label;}
1024 if(p->left->flags==CEXPR){
1025 /* Konstanten nach rechts */
1026 np merk;merk=p->left;p->left=p->right;p->right=merk;
1027 if(p->flags==LESS) p->flags=GREATER;
1028 else if(p->flags==LESSEQ) p->flags=GREATEREQ;
1029 else if(p->flags==GREATER) p->flags=LESS;
1030 else if(p->flags==GREATEREQ) p->flags=LESSEQ;
1031 }
1032#if HAVE_LIBCALLS
1033 at=arith_typ(p->left->ntyp,p->right->ntyp);
1034 if(libname=use_libcall_wrap(COMPARE,at->flags,0)){
1035 new->q1=gen_libcall(libname,p->left,at,p->right,clone_typ(at))->o;
1036 new->code=COMPARE;
1037 new->typf=LIBCALL_CMPTYPE;
1038 new->q2.flags=KONST;
1039 gval.vmax=Z0;
1040 eval_const(&gval,MAXINT);
1041 insert_const(&new->q2.val,LIBCALL_CMPTYPE);
1042 }else{
1043#endif
1044 new->code=COMPARE;
1045 tl=p->left->ntyp->flags&NU;tr=p->right->ntyp->flags&NU;
1046 if(p->right->flags==CEXPR&&ISINT(tr)&&ISINT(tl)&&zm2l(sizetab[tl&NQ])<=zm2l(sizetab[tr&NQ])&&((tl&NQ)>=INT||shortcut(COMPARE,tl))){
1047 int negativ;
1048 eval_constn(p->right);
1049 if(zmleq(vmax,l2zm(0L))) negativ=1; else negativ=0;
1050 if((tl&UNSIGNED)||(tr&UNSIGNED)) negativ=0;
1051 if((!negativ||zmleq(t_min(tl),vmax))&&(negativ||zumleq(vumax,t_max(tl)))){
1052 if((tl&UNSIGNED)||!(tr&UNSIGNED)||p->flags==EQUAL||p->flags==INEQUAL){
1053 convert(p->right,tl);
1054 tr=tl;
1055 }
1056 }
1057 }
1058 if(ISARITH(tl)&&(tl!=tr||!shortcut(COMPARE,tl))){
1059 type *t;
1060 t=arith_typ(p->left->ntyp,p->right->ntyp);
1061 new->typf=t->flags;
1062 freetyp(t);
1063 }else{
1064 new->typf=p->left->ntyp->flags;
1065 }
1066 gen_IC(p->left,0,0);
1067 convert(p->left,new->typf);
1068 gen_IC(p->right,0,0);
1069 convert(p->right,new->typf);
1070 new->q1=p->left->o;
1071 new->q2=p->right->o;
1072 new->z.flags=0;
1073 if(p->flags==EQUAL||p->flags==INEQUAL){
1074 /* generate TEST, if possible */
1075 if(new->q2.flags&KONST){
1076 eval_const(&new->q2.val,new->typf);
1077 if(zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))&&zldeqto(vldouble,d2zld(0.0))){
1078 new->code=TEST;
1079 new->q2.flags=0;
1080 }
1081 }
1082 }
1083#if HAVE_LIBCALLS
1084 }
1085#endif
1086 freetyp(at);
1087 add_IC(new);
1088 new=new_IC();
1089 if(p->flags==EQUAL) new->code=BEQ;
1090 if(p->flags==INEQUAL) new->code=BNE;
1091 if(p->flags==LESS) new->code=BLT;
1092 if(p->flags==LESSEQ) new->code=BLE;
1093 if(p->flags==GREATER) new->code=BGT;
1094 if(p->flags==GREATEREQ) new->code=BGE;
1095 if(ltrue) new->typf=ltrue; else new->typf=l1;
1096 add_IC(new);
1097 if(ltrue){
1098 new=new_IC();
1099 new->code=BRA;
1100 new->typf=lfalse;
1101 add_IC(new);
1102 p->o.flags=0;
1103 }else{
1104 gen_label(l3);
1105 gen_cond(&p->o,1,l1,l2);
1106 }
1107 return;
1108 }
1109 if(p->flags==CALL){
1110 int r=0,radrpush=0;
1111 obj *op,cfunc,ret_obj;
1112 zmax sz;
1113 int mregs[MAXR+1];
1114 IC *callic;
1115#ifdef ORDERED_PUSH
1116 IC *merk_fp,*lp;
1117 unsigned int merk_opushed=opushed;
1118#endif
1119 if(p->left->flags==ADDRESS&&p->left->left->flags==IDENTIFIER){
1120 Var *v;
1121 gen_IC(p->left,0,0); r=1;
1122 v=p->left->o.v;
1123 if(v->fi&&v->fi->first_ic&&!cross_module&&(c_flags_val[0].l&4096)){
1124 /* function call inlining */
1125 argument_list *al;
1126 Var *vp,**argl1,**argl2;
1127 IC *ip;int lc;
1128 int arg_cnt=0,i;
1129 if(DEBUG&1024){
1130 printf("inlining call to <%s>\n",v->identifier);
1131 for(vp=v->fi->vars;vp;vp=vp->next)
1132 printf("%s(%ld)/%p\n",vp->identifier,zm2l(vp->offset),(void*)vp);
1133 }
1134 for(vp=v->fi->vars;vp;vp=vp->next){
1135 /*FIXME: zmeqto hier ok? siehe cross_module_inline */
1136 if((zmeqto(vp->offset,l2zm(0L))||vp->reg)&&*vp->identifier&&(vp->storage_class==AUTO||vp->storage_class==REGISTER)) arg_cnt++;
1137 }
1138
1139 /* Argumente in die ersten Parametervariablen kopieren */
1140 argl1=mymalloc(arg_cnt*sizeof(Var *));
1141 argl2=mymalloc(arg_cnt*sizeof(Var *));
1142
1143 al=p->alist;vp=v->fi->vars;i=0;
1144 while(al){
1145 /*FIXME: zmeqto hier ok? siehe cross_module_inline */
1146 while(vp&&(!*vp->identifier||(!zmeqto(vp->offset,l2zm(0L))&&!vp->reg)||(vp->storage_class!=REGISTER&&vp->storage_class!=AUTO))) vp=vp->next;
1147 if(!vp){ error(39); break; }
1148 if(i>=arg_cnt) ierror(0);
1149 if(DEBUG&1024) printf("arg: %s(%ld)\n",vp->identifier,zm2l(vp->offset));
1150 argl1[i]=vp;
1151 argl2[i]=add_var(empty,clone_typ(vp->vtyp),vp->storage_class,0);
1152 if(!al->arg) ierror(0);
1153 gen_IC(al->arg,0,0);
1154 convert(al->arg,vp->vtyp->flags);
1155 new=new_IC();
1156 new->code=ASSIGN;
1157 new->q1=al->arg->o;
1158 new->q2.flags=0;
1159 new->q2.val.vmax=szof(vp->vtyp);
1160 new->z.flags=VAR;
1161 new->z.val.vmax=l2zm(0L);
1162 new->z.v=argl2[i];
1163 new->typf=vp->vtyp->flags;
1164 new->typf2=falign(vp->vtyp);
1165 add_IC(new);
1166 i++;
1167 al=al->next;
1168 vp=vp->next;
1169 }
1170 if(i<arg_cnt){ error(83); arg_cnt=i;}
1171
1172 /* Kopien der Variablen erzeugen */
1173 for(vp=v->fi->vars;vp;vp=vp->next){
1174 vp->inline_copy=0;
1175 }
1176 for(i=0;i<arg_cnt;i++){
1177 if(argl1[i]){
1178 if(!argl2[i]) ierror(0);
1179 argl1[i]->inline_copy=argl2[i];
1180 }
1181 }
1182
1183 /* Rueckgabewert */
1184 if((p->ntyp->flags&NQ)!=VOID){
1185 p->o.flags=SCRATCH|VAR;
1186 p->o.reg=0;p->o.val.vmax=l2zm(0L);
1187 p->o.v=add_var(empty,clone_typ(p->ntyp),AUTO,0);
1188 }else{
1189 p->o.flags=0;
1190 }
1191
1192 free(argl1);
1193 free(argl2);
1194
1195 /* Code einfuegen und Labels umschreiben */
1196 ip=v->fi->first_ic;lc=0;
1197 while(ip){
1198 Var *iv;
1199 int c;
1200 new=new_IC();
1201 *new=*ip;
1202 ip->copy=new;
1203 c=ip->code;
1204 /* evtl. ist ein IC praktisch ein SETRETURN, falls das */
1205 /* Rueckgabeziel ueber Parameterzeiger angespr. wird */
1206 if(ip->z.flags&VAR){
1207 iv=ip->z.v;
1208 if(iv->storage_class==AUTO||iv->storage_class==REGISTER){
1209 if(!*iv->identifier&&zmeqto(iv->offset,l2zm(0L))){
1210 new->z=p->o;
1211 }else{
1212 if(!iv->inline_copy){
1213 iv->inline_copy=add_var(empty,clone_typ(iv->vtyp),iv->storage_class,0);
1214 iv->inline_copy->reg=iv->reg;
1215 }
1216 new->z.v=iv->inline_copy;
1217 }/*else if(iv->inline_copy) ierror(0);*/
1218 }
1219 }
1220 /* Kopien aller auto/register Variablen erzeugen */
1221 if(ip->q1.flags&VAR){
1222 iv=ip->q1.v;
1223 if(iv->storage_class==AUTO||iv->storage_class==REGISTER){
1224 if(!iv->inline_copy){
1225 iv->inline_copy=add_var(empty,clone_typ(iv->vtyp),iv->storage_class,0);
1226 iv->inline_copy->reg=iv->reg;
1227 }
1228 new->q1.v=iv->inline_copy;
1229 }/*else if(iv->inline_copy) ierror(0);*/
1230 }
1231 if(ip->q2.flags&VAR){
1232 iv=ip->q2.v;
1233 if(iv->storage_class==AUTO||iv->storage_class==REGISTER){
1234 if(!iv->inline_copy){
1235 iv->inline_copy=add_var(empty,clone_typ(iv->vtyp),iv->storage_class,0);
1236 iv->inline_copy->reg=iv->reg;
1237 }
1238 new->q2.v=iv->inline_copy;
1239 }/*else if(iv->inline_copy) ierror(0);*/
1240 }
1241 if(c==CALL){
1242 int i;
1243 function_calls+=currentpri;
1244 new->arg_list=mymalloc(sizeof(*new->arg_list)*new->arg_cnt);
1245 for(i=0;i<new->arg_cnt;i++) new->arg_list[i]=ip->arg_list[i]->copy;
1246 }
1247 if(c==LABEL||(c>=BEQ&&c<=BRA)){
1248 if(new->typf>lc) lc=new->typf;
1249 new->typf+=label;
1250 }
1251 if(c==SETRETURN){
1252 new->code=ASSIGN;
1253 new->z=p->o;
1254 }
1255 add_IC(new);
1256 ip=ip->next;
1257 }
1258 label+=lc;
1259 return;
1260 }
1261 /* einige spezielle Inline-Funktionen; das setzt voraus, dass */
1262 /* diese in den Headerfiles passend deklariert werden */
1263 if(v->storage_class==EXTERN){
1264 if((optflags&2)&&(!strcmp(v->identifier,"strlen")||!strcmp(v->identifier,"__asm_strlen"))&&p->alist&&p->alist->arg){
1265 np n=p->alist->arg;
1266 if(n->flags==ADDRESSA&&n->left->flags==STRING&&zmeqto(n->left->val.vmax,l2zm(0L))){
1267 const_list *cl;zumax len=ul2zum(0UL);
1268 cl=n->left->cl;
1269 while(cl){
1270 if(zmeqto(l2zm(0L),zc2zm(cl->other->val.vchar))) break;
1271 len=zumadd(len,ul2zum(1UL));
1272 cl=cl->next;
1273 }
1274 p->o.val.vumax=len;
1275 eval_const(&p->o.val,UNSIGNED|MAXINT);
1276 insert_constn(p);
1277 insert_const(&p->o.val,p->ntyp->flags);
1278 p->flags=CEXPR;
1279 p->o.flags=KONST;
1280 return;
1281 }
1282 }
1283
1284 if(inline_memcpy_sz>0&&(optflags&2)){
1285 if((!strcmp(v->identifier,"strcpy")||!strcmp(v->identifier,"__asm_strcpy"))&&p->alist&&p->alist->next&&p->alist->next->arg){
1286 np n=p->alist->next->arg;
1287 if(n->flags==ADDRESSA&&n->left->flags==STRING&&zmeqto(n->left->val.vmax,l2zm(0L))){
1288 const_list *cl;zmax len=l2zm(0L);
1289 cl=n->left->cl;
1290 while(cl){
1291 len=zmadd(len,l2zm(1L));
1292 if(zmeqto(zc2zm(cl->other->val.vchar),l2zm(0L))) break;
1293 cl=cl->next;
1294 }
1295 if(zmleq(len,l2zm((long)inline_memcpy_sz))){
1296 inline_memcpy(p->alist->arg,n,len);
1297 p->o=p->alist->arg->o;
1298 return;
1299 }
1300 }
1301 }
1302 if(!strcmp(v->identifier,"memcpy")||!strcmp(v->identifier,"__asm_memcpy")){
1303 if(p->alist&&p->alist->next&&p->alist->next->next
1304 &&p->alist->next->next->arg
1305 &&p->alist->next->next->arg->flags==CEXPR){
1306 eval_constn(p->alist->next->next->arg);
1307 if(zmleq(vmax,l2zm((long)inline_memcpy_sz))){
1308 inline_memcpy(p->alist->arg,p->alist->next->arg,vmax);
1309 p->o=p->alist->arg->o;
1310 return;
1311 }
1312 }
1313 }
1314 }
1315 }
1316 }
1317 rl=0;
1318 if(!(optflags&2)){
1319 int r;
1320 for(r=1;r<=MAXR;r++){mregs[r]=regs[r];regs[r]&=~(RNOSAVE|RHALF);}
1321 }else{
1322 gen_IC(p->left,0,0);
1323 }
1324#ifdef ORDERED_PUSH
1325 merk_fp=first_pushed;
1326 first_pushed=0;
1327 lp=last_ic;
1328#endif
1329#ifdef HAVE_REGPARMS
1330 if(!ffreturn(p->ntyp)&&(p->ntyp->flags&NQ)!=VOID){
1331 IC *new2;static type ptyp={0};
1332 treg_handle reg_handle=empty_reg_handle;
1333 int reg;
1334 ptyp.next=p->ntyp;
1335 ptyp.flags=POINTER_TYPE(p->ntyp);
1336 reg=reg_parm(&reg_handle,&ptyp,0,p->left->ntyp->next);
1337 if(reg){
1338 new2=new_IC();
1339 new2->code=ADDRESS;
1340 new2->typf=p->ntyp->flags;
1341 new2->typf2=POINTER_TYPE(p->ntyp);
1342 new2->q1.flags=VAR;
1343 new2->q1.v=add_var(empty,clone_typ(p->ntyp),AUTO,0);
1344 new2->q1.val.vmax=l2zm(0L);
1345 op=&new2->q1;
1346 new2->q2.flags=0;
1347 get_scratch(&new2->z,POINTER_TYPE(p->ntyp),p->ntyp->flags,0);
1348 ret_obj=new2->z;
1349 add_IC(new2);
1350 sz=push_args(p->alist,p->left->ntyp->next->exact,0,&rl,&reg_handle,&ret_obj,p->ntyp,reg,p->left->ntyp);
1351 if(optflags&2)
1352 handle_reglist(rl,&ret_obj);
1353 }else{
1354 sz=push_args(p->alist,p->left->ntyp->next->exact,0,&rl,&reg_handle,0,p->ntyp,reg,p->left->ntyp);
1355 radrpush=1;
1356 if(optflags&2)
1357 handle_reglist(rl,0);
1358 }
1359 }else{
1360 treg_handle reg_handle=empty_reg_handle;
1361 sz=push_args(p->alist,p->left->ntyp->next->exact,0,&rl,&reg_handle,0,0,-1,p->left->ntyp);
1362 if(optflags&2)
1363 handle_reglist(rl,0);
1364 }
1365#else
1366 sz=push_args(p->alist,p->left->ntyp->next->exact,0,&rl);
1367 if(optflags&2)
1368 handle_reglist(rl,0);
1369#endif
1370 if(!r&&!(optflags&2)) gen_IC(p->left,0,0);
1371 if(!(p->left->o.flags&DREFOBJ)){
1372 free(new);
1373 p->o=p->left->o;
1374 if(p->o.flags&VARADR){
1375 p->o.flags&=~VARADR;
1376 }else{
1377 p->o.flags|=DREFOBJ;
1378 p->o.dtyp=p->left->ntyp->flags;
1379 }
1380 }else{
1381 if(p->left->o.flags&VARADR){
1382 free(new);
1383 p->o=p->left->o;
1384 p->o.flags&=~VARADR;
1385 }else{
1386 if((p->left->o.flags&SCRATCH)&&p->ntyp->flags==p->left->ntyp->flags){
1387 new->z=p->left->o;
1388 new->z.flags&=~DREFOBJ;
1389 }else{
1390 get_scratch(&new->z,p->left->ntyp->flags,FUNKT,p->left->ntyp);
1391 }
1392 new->code=ASSIGN;
1393 new->typf=p->left->ntyp->flags;
1394 new->q1=p->left->o;
1395 new->q2.val.vmax=sizetab[new->typf&NQ];
1396 new->q2.flags=0;
1397 p->o=new->z;
1398 add_IC(new);
1399 p->o.flags|=DREFOBJ;
1400 p->o.dtyp=p->left->ntyp->flags;
1401 }
1402 }
1403/* p->left->o.flags-=DREFOBJ|VARADR; Was sollte das?? */
1404
1405#if 0
1406 if(optflags&2){
1407 while(rl){
1408 regargs_list *m;
1409 new=new_IC();
1410 new->code=NOP;
1411 new->q1.flags=VAR;
1412 new->q1.v=rl->v;
1413 new->q1.val.vmax=l2zm(0L);
1414 new->typf=0;
1415 new->q2.flags=new->z.flags=0;
1416 add_IC(new);
1417 m=rl->next;free(rl);rl=m;
1418 }
1419 }
1420#endif
1421
1422 /* gegebenenfalls Adresse des Ziels auf den Stack */
1423#ifdef HAVE_REGPARMS
1424 if(radrpush)
1425#else
1426 if(!ffreturn(p->ntyp)&&(p->ntyp->flags&NQ)!=VOID)
1427#endif
1428 {
1429#if defined(ORDERED_PUSH) && defined(HAVE_REGPARMS)
1430 ierror(0);
1431#endif
1432 new=new_IC();
1433 new->code=ADDRESS;
1434 new->typf=p->ntyp->flags;
1435 new->typf2=POINTER_TYPE(p->ntyp);
1436 new->q1.flags=VAR;
1437 new->q1.v=add_var(empty,clone_typ(p->ntyp),AUTO,0);
1438 new->q1.val.vmax=l2zm(0L);
1439 op=&new->q1;
1440 new->q2.flags=0;
1441 get_scratch(&new->z,POINTER_TYPE(p->ntyp),p->ntyp->flags,0);
1442 ret_obj=new->z;
1443 add_IC(new);
1444 new=new_IC();
1445 new->code=PUSH;
1446 new->typf=POINTER_TYPE(p->ntyp);
1447 new->q1=ret_obj;
1448 new->q2.flags=new->z.flags=0;
1449 new->q2.val.vmax=sizetab[new->typf&NQ];
1450 new->z.val.vmax=new->q2.val.vmax;
1451 add_IC(new);
1452 sz=zmadd(sz,sizetab[new->typf&NQ]);
1453 }
1454
1455 /* Scratchregister evtl. sichern */
1456 cfunc=p->o;
1457 if(!nocode)
1458 savescratch(MOVEFROMREG,last_ic,0,&cfunc);
1459 function_calls+=currentpri;
1460 new=new_IC();
1461 new->code=CALL;
1462 callic=new;
1463 if(p->alist){
1464 /* insert list of argument ICs */
1465 int i=0;
1466 argument_list *a=p->alist;
1467 while(a){i++;a=a->next;}
1468 new->arg_cnt=i;
1469 new->arg_list=mymalloc(sizeof(*new->arg_list)*i);
1470 for(a=p->alist,i=0;a;a=a->next,i++) new->arg_list[i]=a->pushic;
1471 }else{
1472 new->arg_cnt=0;
1473 new->arg_list=0;
1474 }
1475 new->typf=FUNKT;
1476 new->q1=p->o;
1477 new->q2.flags=new->z.flags=0;
1478 new->q2.val.vmax=sz; /* Groesse der Parameter auf dem Stack */
1479 add_IC(new);
1480
1481 //pric2(stdout,new);
1482
1483 if(optflags&2){
1484 while(rl){
1485 regargs_list *m;
1486 new=new_IC();
1487 new->code=NOP;
1488 new->q1.flags=VAR;
1489 new->q1.v=rl->v;
1490 new->q1.val.vmax=l2zm(0L);
1491 new->typf=0;
1492 new->q2.flags=new->z.flags=0;
1493 add_IC(new);
1494 m=rl->next;free(rl);rl=m;
1495 }
1496 }
1497
1498 r=0;
1499 if((p->ntyp->flags&NQ)!=VOID){
1500 new=new_IC();
1501 new->code=GETRETURN;
1502 new->q1.flags=new->q2.flags=0;
1503 new->q1.reg=ffreturn(p->ntyp);
1504 new->q2.val.vmax=szof(p->ntyp);
1505 new->typf=p->ntyp->flags;
1506 if(ffreturn(p->ntyp)){
1507 int t=p->ntyp->flags&NQ;
1508 if(ISSTRUCT(t)||ISUNION(t)){
1509 new->z.v=add_var(empty,clone_typ(p->ntyp),AUTO,0);
1510 new->z.flags=VAR;
1511 new->z.val.vmax=l2zm(0L);
1512 }else{
1513 if(optflags&2){
1514 get_scratch(&new->z,p->ntyp->flags,0,p->ntyp);
1515 }else{
1516 /* Suche geeignetes Register, um Rueckgabewert zu speichern. */
1517 regargs_list *l2;
1518 int r;
1519 r=new->q1.reg;
1520 if(regs[r]||!regok(r,p->ntyp->flags,0)||(reg_pair(r,&rp)&&(regs[rp.r1]||regs[rp.r2]))){
1521 r=0;
1522 }else{
1523 for(l2=rl;l2;l2=l2->next){
1524 if(l2->v&&abs(l2->reg)==r) {r=0;break;}
1525 }
1526 }
1527 if(r==0){
1528 for(r=1;r<=MAXR;r++){
1529 if(!regs[r]&&regok(r,p->ntyp->flags,0)&&(!reg_pair(r,&rp)||(!regs[rp.r1]&&!regs[rp.r2]))){
1530 for(l2=rl;l2;l2=l2->next){
1531 if(l2->v&&abs(l2->reg)==r) break;
1532 }
1533 if(l2) continue;
1534 break;
1535 }
1536 }
1537 }
1538 if(r>=1&&r<=MAXR){
1539 alloc_hardreg(r);
1540 new->z.flags=(REG|SCRATCH);
1541 new->z.reg=r;
1542 }else{
1543 get_scratch(&new->z,p->ntyp->flags,0,p->ntyp);
1544 }
1545 }
1546 }
1547 } else
1548 new->z=*op;
1549 if((new->z.flags&(REG|DREFOBJ))==REG) r=new->z.reg;
1550 p->o=new->z;
1551 add_IC(new);
1552 }else{
1553 p->o.flags=0;
1554 }
1555 /* Scratchregister evtl. wiederherstellen */
1556 if(!nocode)
1557 savescratch(MOVETOREG,last_ic,r,&cfunc);
1558 if(!(optflags&2)){
1559 int r;
1560 for(r=1;r<=MAXR;r++){
1561 if(regs[r])
1562 regs[r]|=(mregs[r]&RNOSAVE);
1563 }
1564 }
1565 /* Evtl. gespeicherte Registerargumente wiederherstellen. */
1566 while(rl){
1567 regargs_list *m;
1568 if(rl->v){
1569 int r;
1570 for(r=MAXR;r>=1;r--){
1571 if(regs[r]&&reg_pair(r,&rp)&&(rp.r1==abs(rl->reg)||rp.r2==abs(rl->reg)))
1572 break;
1573 }
1574 if(r<=1) r=abs(rl->reg);
1575 new=new_IC();
1576 new->code=MOVETOREG;
1577 new->typf=0;
1578 new->q1.flags=VAR|DONTREGISTERIZE;
1579 new->q1.v=rl->v;
1580 new->q1.val.vmax=l2zm(0L);
1581 new->z.flags=REG;
1582 if(rl->rsaved)
1583 new->z.reg=rl->rsaved;
1584 else
1585 new->z.reg=abs(r);
1586 new->q2.flags=0;
1587 new->q2.val.vmax=regsize[r];
1588 add_IC(new);
1589 if(rl->rsaved)
1590 free_reg(abs(rl->reg));
1591 }else{
1592 free_reg(abs(rl->reg));
1593 }
1594 m=rl->next;free(rl);rl=m;
1595 }
1596#ifdef ORDERED_PUSH
1597 /* If arguments have been pushed nested we have to copy them and */
1598 /* push them later. */
1599 if(merk_fp&&opushed!=merk_opushed){
1600 IC *p,*m=0,*np;
1601 if(!lp) ierror(0);
1602 for(p=merk_fp;p;){
1603 np=p->next;
1604 if(p->code==PUSH){
1605 new=new_IC();
1606 *new=*p;
1607 /* be careful about the address because of arg_list! */
1608 if(p->prev) p->prev->next=new;
1609 new->prev=p->prev;
1610 if(p->next) p->next->prev=new;
1611 new->next=p->next;
1612 if(p==last_ic) last_ic=new;
1613 if(p==first_ic) first_ic=new;
1614 if(new->q1.flags&&!(p->flags&ORDERED_PUSH_COPY)){
1615 new->code=ASSIGN;
1616 new->z.flags=VAR;
1617 new->z.val.vmax=l2zm(0L);
1618 /* typ allocated in push_args and not used there */
1619 /* if(!p->ityp) ierror(0);*/
1620 new->z.v=add_tmp_var(clone_typ(p->ityp)); /*FIXME??*/
1621 p->q1=new->z;
1622 /* p->ityp=0;*/
1623 }else{
1624 remove_IC(new);
1625 }
1626 p->next=p->prev=0;
1627 p->flags|=ORDERED_PUSH_COPY;
1628 add_IC(p);
1629 if(!m&&!nocode) m=p;
1630 }
1631 if(p==lp) break;
1632 p=np;
1633 }
1634 if(!m) ierror(0);
1635 first_pushed=m;
1636 }else
1637 first_pushed=merk_fp;
1638#endif
1639 return;
1640 }
1641 if(p->flags>=PREINC&&p->flags<=POSTDEC){
1642 obj o;
1643#if HAVE_LIBCALLS
1644 char *libname;
1645 node tn={ADD},one={CEXPR};
1646#endif
1647 gen_IC(p->left,0,0);
1648 if((p->flags==POSTINC||p->flags==POSTDEC)){
1649 /*new=new_IC();*/
1650 new->code=ASSIGN;
1651 new->typf=p->ntyp->flags;
1652 new->q2.val.vmax=sizetab[p->ntyp->flags&NQ];
1653 new->q1=p->left->o;
1654 postop_obj=&new->q1;
1655 postop_type=new->typf;
1656 new->q1.flags&=~SCRATCH;
1657 get_scratch(&new->z,p->left->ntyp->flags,0,p->left->ntyp);
1658 new->q2.flags=0;
1659 o=new->z;
1660 add_IC(new);
1661 new=new_IC();
1662 }else
1663 o=p->left->o;
1664#if HAVE_LIBCALLS
1665 if(p->flags==PREDEC||p->flags==POSTDEC)
1666 tn.flags=SUB;
1667 tn.left=p->left;
1668 tn.right=&one;
1669 tn.ntyp=p->ntyp;
1670 one.flags=CEXPR;
1671 one.ntyp=p->ntyp;
1672 gval.vmax=l2zm(1L);
1673 eval_const(&gval,MAXINT);
1674 insert_const(&one.val,p->ntyp->flags&NU);
1675 if(libname=use_libcall_wrap(tn.flags,tn.ntyp->flags,0)){
1676 np lc;
1677 lc=gen_libcall(libname,p->left,0,&one,0);
1678 new=new_IC();
1679 new->code=ASSIGN;
1680 new->typf=p->ntyp->flags;
1681 new->q2.val.vmax=sizetab[p->ntyp->flags&NQ];
1682 new->q1=lc->o;
1683 new->q1.flags&=~SCRATCH;
1684 new->z=p->left->o;
1685 add_IC(new);
1686 new=new_IC();
1687 free(lc);
1688 }else
1689#endif
1690 if(ISPOINTER(p->left->ntyp->flags)){
1691 if(p->flags==PREINC||p->flags==POSTINC)
1692 new->code=ADDI2P;
1693 else
1694 new->code=SUBIFP;
1695 vmax=szof(p->left->ntyp->next);
1696 new->q2.val.vint=zm2zi(vmax);
1697 new->typf=INT;
1698 new->typf2=p->left->ntyp->flags;
1699 new->q1=p->left->o;
1700 new->z=p->left->o;
1701 new->q2.flags=KONST;
1702 add_IC(new);
1703 }else{
1704 if(p->flags==PREINC||p->flags==POSTINC)
1705 new->code=ADD;
1706 else
1707 new->code=SUB;
1708 new->typf=p->ntyp->flags;
1709 new->q1=p->left->o;
1710 new->z=p->left->o;
1711 new->q2.flags=KONST;
1712 gval.vint=zm2zi(l2zm(1L));
1713 eval_const(&gval,INT);
1714 insert_const(&new->q2.val,new->typf);
1715 add_IC(new);
1716 }
1717 if(p->left->flags==BITFIELD){
1718 insert_bitfield(&p->left->left->o,&new->z,&p->o,p->left->bfs,p->left->bfo,p->ntyp->flags,0);
1719 if(p->flags!=POSTINC&&p->flags!=POSTDEC){
1720 o=p->o;
1721 }else{
1722 if((p->o.flags&(REG|SCRATCH))==(REG|SCRATCH))
1723 free_reg(p->o.reg);
1724 }
1725 }
1726 if(p->flags==POSTINC||p->flags==POSTDEC||p->left->flags==BITFIELD){
1727 if((p->left->o.flags&(SCRATCH|REG))==(SCRATCH|REG))
1728 free_reg(p->left->o.reg);
1729 }
1730
1731 postop_obj=0;
1732 p->o=o;
1733 return;
1734 }
1735 if(p->flags==COND){
1736 int ltrue,lfalse,lout;
1737 ltrue=++label;lfalse=++label;lout=++label;
1738 gen_IC(p->left,ltrue,lfalse);
1739 if(!p->left->o.flags){
1740 free(new);
1741 }else{
1742 if(p->left->flags!=CEXPR){
1743 gen_test(&p->left->o,p->left->ntyp->flags,BEQ,lfalse);
1744 }else{
1745 eval_constn(p->left);
1746 if(zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))&&zldeqto(vldouble,d2zld(0.0))){
1747 gen_IC(p->right->right,0,0);
1748 p->o=p->right->right->o;
1749 }else{
1750 gen_IC(p->right->left,0,0);
1751 p->o=p->right->left->o;
1752 }
1753 return;
1754 }
1755 }
1756 gen_label(ltrue);
1757 gen_IC(p->right->left,0,0);
1758 if((p->ntyp->flags&NQ)!=VOID){
1759 convert(p->right->left,p->ntyp->flags);
1760 if((p->right->left->o.flags&(SCRATCH|DREFOBJ))==SCRATCH){
1761 p->o=p->right->left->o;
1762 }else{
1763 get_scratch(&p->o,p->ntyp->flags,0,p->ntyp);
1764 new=new_IC();
1765 new->code=ASSIGN;
1766 new->q1=p->right->left->o;
1767 new->z=p->o;
1768 new->q2.flags=0;
1769 new->q2.val.vmax=szof(p->ntyp);
1770 new->typf=p->ntyp->flags;
1771 p->o=new->z;
1772 add_IC(new);
1773 }
1774 }else
1775 p->o.flags=0;
1776 new=new_IC();
1777 new->code=BRA;
1778 new->typf=lout;
1779 add_IC(new);
1780 gen_label(lfalse);
1781 gen_IC(p->right->right,0,0);
1782 if((p->ntyp->flags&NQ)!=VOID){
1783 convert(p->right->right,p->ntyp->flags);
1784 new=new_IC();
1785 new->code=ASSIGN;
1786 new->q1=p->right->right->o;
1787 new->z=p->o;
1788 new->q2.flags=0;
1789 new->q2.val.vmax=szof(p->ntyp);
1790 new->typf=p->ntyp->flags;
1791 add_IC(new);
1792 }
1793 gen_label(lout);
1794 return;
1795 }
1796 if(p->flags==BITFIELD){
1797 int lsc,rsc,bfo;
1798 obj tmp;
1799 bfo=bflayout(p->bfo,p->bfs,p->ntyp->flags);
1800 lsc=zm2l(zmmult(sizetab[p->ntyp->flags&NQ],char_bit))-p->bfs-bfo;
1801 rsc=lsc+bfo;
1802 gen_IC(p->left,0,0);
1803 new->code=LSHIFT;
1804 new->typf=p->ntyp->flags;
1805 new->typf2=INT;
1806 new->q1=p->left->o;
1807 new->q2.flags=KONST;
1808 new->q2.val.vint=zm2zi(l2zm((long)lsc));
1809 get_scratch(&new->z,new->typf,0,0);
1810 tmp=new->z;
1811 add_IC(new);
1812 new=new_IC();
1813 new->code=RSHIFT;
1814 new->typf=p->ntyp->flags;
1815 new->typf2=INT;
1816 new->q1=tmp;
1817 new->q2.flags=KONST;
1818 new->q2.val.vint=zm2zi(l2zm((long)rsc));
1819 new->z=tmp;
1820 p->o=new->z;
1821 add_IC(new);
1822 return;
1823 }
1824 printf("Operation: %d=%s\n",p->flags,ename[p->flags]);
1825 ierror(0);
1826 free(new);
1827 p->o.flags=0;
1828}
1829
1830static void handle_reglist(regargs_list *nrl,obj *radr)
1831{
1832 IC *new;
1833 /* Letztes Argument; jetzt in Register laden. */
1834#ifdef HAVE_REGPARMS
1835 int didradr=0;
1836#endif
1837 while(nrl){
1838 new=new_IC();
1839 new->code=ASSIGN;
1840 new->typf=nrl->v->vtyp->flags/*|VOLATILE*/;
1841 new->q1.flags=VAR;
1842 new->q1.v=nrl->v;
1843 new->q1.val.vmax=l2zm(0L);
1844 new->q2.flags=0;
1845 new->q2.val.vmax=szof(nrl->v->vtyp);
1846 new->z.flags=VAR;
1847 new->z.val.vmax=l2zm(0L);
1848 new->z.v=add_var(empty,clone_typ(nrl->v->vtyp),AUTO,0);
1849 new->z.v->reg=nrl->reg;
1850 new->z.v->vtyp->flags|=VOLATILE;
1851 nrl->v=new->z.v;
1852 add_IC(new);
1853
1854#ifdef HAVE_REGPARMS
1855 if(radr&&!didradr){
1856 didradr=1;
1857 }else{
1858#endif
1859 nrl->al->pushic=new;
1860 fix_pushic(&nrl->al->pushic,new);
1861#ifdef HAVE_REGPARMS
1862 }
1863#endif
1864 nrl=nrl->next;
1865 }
1866}
1867
1868#ifdef HAVE_REGPARMS
1869zmax push_args(argument_list *al,struct_declaration *sd,int n,regargs_list **rl,treg_handle *reg_handle,obj *radr,type *rtype,int rreg,type *fkt)
1870#else
1871zmax push_args(argument_list *al,struct_declaration *sd,int n,regargs_list **rl)
1872#endif
1873/* Legt die Argumente eines Funktionsaufrufs in umgekehrter Reihenfolge */
1874/* auf den Stack. Es wird Integer-Erweiterung vorgenommen und float wird */
1875/* nach double konvertiert, falls kein Prototype da ist. */
1876{
1877 int t,reg,regpush,evaluated=0;type *ft;
1878 IC *new;regargs_list *nrl;zmax sz,rsz,of;obj *arg;
1879#ifdef HAVE_REGPARMS
1880 int stdreg;
1881 if(!al&&!radr) return(0);
1882 if(radr){
1883 stdreg=rreg;
1884 }else{
1885 if(n<sd->count){
1886 stdreg=reg_parm(reg_handle,(*sd->sl)[n].styp,0,fkt->next);
1887 }else{
1888 if(sd->count)
1889 stdreg=reg_parm(reg_handle,al->arg->ntyp,1,fkt->next);
1890 else{
1891 if(short_push&&ISINT(al->arg->ntyp->flags)){
1892 static type t;
1893 t.flags=int_erw(al->arg->ntyp->flags);
1894 stdreg=reg_parm(reg_handle,&t,0,fkt->next);
1895 }else{
1896 stdreg=reg_parm(reg_handle,al->arg->ntyp,0,fkt->next);
1897 }
1898 }
1899 }
1900 }
1901 reg=stdreg;
1902#else
1903 if(!al) return(0);
1904 reg=0;
1905#endif
1906#ifdef HAVE_REGPARMS
1907 if(!radr){
1908#endif
1909 if(!al->arg) ierror(0);
1910 if(!sd) ierror(0);
1911 if(n<sd->count){
1912 ft=clone_typ((*sd->sl)[n].styp);sz=szof(ft);
1913 t=ft->flags;
1914 reg=(*sd->sl)[n].reg;
1915 }else{
1916 ft=clone_typ(al->arg->ntyp);sz=szof(ft);
1917 t=ft->flags;
1918 }
1919 if(ISINT(t)){
1920 if(n>=sd->count||!short_push)
1921 t=int_erw(t);
1922 ft->flags=t;
1923 sz=sizetab[t&NQ];
1924 }
1925 if((t&NQ)==FLOAT&&n>=sd->count) {t=DOUBLE;ft->flags=t;sz=sizetab[t&NQ];}
1926#ifdef HAVE_REGPARMS
1927 }else{
1928 ft=new_typ();
1929 ft->flags=t=POINTER_TYPE(rtype);
1930 ft->next=clone_typ(rtype);
1931 sz=sizetab[t&NQ];
1932 }
1933#endif
1934 if(reg<0) {reg=-reg;regpush=1;} else regpush=0;
1935 rsz=sz;
1936 sz=zmmult(zmdiv(zmadd(sz,zmsub(stackalign,l2zm(1L))),stackalign),stackalign);
1937#ifdef ORDERED_PUSH
1938 if(reg==0||regpush){
1939 new=new_IC();
1940#ifdef HAVE_REGPARMS
1941 if(!radr&&!evaluated){
1942#endif
1943 gen_IC(al->arg,0,0);
1944 convert(al->arg,t);
1945 evaluated=1;
1946 new->q1=al->arg->o;
1947 al->pushic=new;
1948#ifdef HAVE_REGPARMS
1949 }else
1950 new->q1=*radr;
1951#endif
1952 /* Parameteruebergabe ueber Stack. */
1953 new->code=PUSH;
1954 new->typf=t;
1955 new->ityp=ft;
1956 new->q2.flags=new->z.flags=0;
1957 new->q2.val.vmax=sz;
1958 new->z.val.vmax=rsz;
1959 if(regpush){
1960 if(c_flags[26]&USEDFLAG){
1961 new->q1.am=new->q2.am=new->z.am=0;
1962 new->line=line; new->file=filename;
1963 insert_IC(last_ic,new);
1964 }else{
1965 new->q1.flags=0;
1966 add_IC(new);
1967 if(al) fix_pushic(&al->pushic,new);
1968 }
1969 }else{
1970 add_IC(new);
1971 if(al) fix_pushic(&al->pushic,new);
1972 }
1973 opushed++;
1974 if(!first_pushed&&!nocode) first_pushed=new;
1975 if(al&&!al->next&&!regpush) return sz;
1976 }
1977#endif
1978#ifdef HAVE_REGPARMS
1979 if(radr){
1980 if(al) of=push_args(al,sd,0,rl,reg_handle,0,0,0,fkt); else of=l2zm(0L);
1981 }else{
1982 if(al->next) of=push_args(al->next,sd,n+1,rl,reg_handle,0,0,0,fkt); else of=l2zm(0L);
1983 }
1984#else
1985 if(al->next) of=push_args(al->next,sd,n+1,rl); else of=l2zm(0L);
1986#endif
1987#ifdef ORDERED_PUSH
1988 if(reg==0) return zmadd(of,sz);
1989#endif
1990
1991 if(regpush) of=zmadd(of,sz);
1992
1993#ifdef HAVE_REGPARMS
1994 if(radr){
1995 arg=radr;
1996 }else{
1997 if(!evaluated){
1998 gen_IC(al->arg,0,0);
1999 convert(al->arg,t);
2000 evaluated=1;
2001 }
2002 arg=&al->arg->o;
2003 }
2004#else
2005 if(!evaluated){
2006 gen_IC(al->arg,0,0);
2007 convert(al->arg,t);
2008 evaluated=1;
2009 }
2010 arg=&al->arg->o;
2011#endif
2012#ifndef ORDERED_PUSH
2013 if(reg==0||regpush){
2014 /* Parameteruebergabe ueber Stack. */
2015 new=new_IC();
2016 new->code=PUSH;
2017 new->typf=t;
2018 new->q1=*arg;
2019 if(regpush&&!(c_flags[26]&USEDFLAG)) new->q1.flags=0;
2020 new->q2.flags=new->z.flags=0;
2021 new->q2.val.vmax=sz;
2022 new->z.val.vmax=rsz;
2023 add_IC(new);
2024 al->pushic=new;
2025 fix_pushic(&al->pushic,new);
2026 if(!regpush) return(zmadd(of,sz));
2027 }
2028#endif
2029 if(reg){
2030 /* Parameteruebergabe in Register. */
2031 Var *v=0; type *t2;
2032 int rsaved=0;
2033 if(optflags&2){
2034 /* Version fuer Optimizer. */
2035 t2=new_typ();
2036 t2->flags=t;
2037 if(ISPOINTER(t)){
2038 t2->next=new_typ();
2039 t2->next->flags=VOID;
2040 }
2041 v=add_var(empty,t2,AUTO,0);
2042 new=new_IC();
2043 new->code=ASSIGN;
2044 new->typf=t;
2045 new->q1=*arg;
2046 new->q2.flags=0;
2047 new->q2.val.vmax=sizetab[t&NQ];
2048 new->z.flags=VAR;
2049 new->z.v=v;
2050 new->z.val.vmax=l2zm(0L);
2051 add_IC(new);
2052 nrl=mymalloc(sizeof(*nrl));
2053 nrl->next=*rl;
2054 nrl->reg=reg;
2055 nrl->v=v;
2056 nrl->al=al;
2057 *rl=nrl;
2058 return of;
2059 }else{
2060 /* Nicht-optimierende Version. */
2061
2062 if(DEBUG&16){
2063 printf("reg[%s]=%d ",regnames[reg],regs[reg]);
2064 if(reg_pair(reg,&rp))
2065 printf("reg[%s]=%d reg[%s]=%d ",regnames[rp.r1],regs[rp.r1],regnames[rp.r2],regs[rp.r2]);
2066 printf("\n");
2067 }
2068 if(reg_pair(reg,&rp)&&(arg->flags&(REG|SCRATCH))==(REG|SCRATCH)&&(arg->reg==rp.r1||arg->reg==rp.r2)){
2069 /* rx->reg_pair(rx,ry): make a copy */
2070 new=new_IC();
2071 new->code=ASSIGN;
2072 new->typf=t;
2073 new->q1=*arg;
2074 new->q2.flags=0;
2075 new->q2.val.vmax=sizetab[t&NQ];
2076 scratch_var(&new->z,t,0);
2077 add_IC(new);
2078 *arg=new->z;
2079 free_reg(arg->reg);
2080 }
2081 if(!regs[reg]&&(!reg_pair(reg,&rp)||(!regs[rp.r1]&&!regs[rp.r2]))&&!nocode){
2082 new=new_IC();
2083 new->code=ALLOCREG;
2084 new->typf=0;
2085 new->q1.flags=REG;
2086 new->q1.reg=reg;
2087 new->q2.flags=new->z.flags=0;
2088 add_IC(new);
2089 regs[reg]=(1|RNOSAVE);regused[reg]++;
2090 if(DEBUG&16) printf("allocated %s (1)\n",regnames[reg]);
2091 if(reg_pair(reg,&rp)){
2092 regs[rp.r1]=1|RNOSAVE;regused[rp.r1]++;
2093 regs[rp.r2]=1|RNOSAVE;regused[rp.r2]++;
2094 }
2095 }else if(!regs[reg]&&reg_pair(reg,&rp)&&(regs[rp.r1]||regs[rp.r2])&&!nocode){
2096 int r=0;
2097 regargs_list *p;
2098
2099 new=new_IC();
2100 new->code=ALLOCREG;
2101 new->typf=0;
2102 new->q1.flags=REG;
2103 new->q2.flags=new->z.flags=0;
2104 if(regs[rp.r1]){
2105 new->q1.reg=rp.r2;
2106 r=rp.r1;
2107 regs[r]|=RHALF;
2108 }else{
2109 new->q1.reg=rp.r1;
2110 r=rp.r2;
2111 regs[r]|=RHALF;
2112 }
2113 regs[new->q1.reg]=(1|RNOSAVE);regused[new->q1.reg]++;
2114 regs[reg]=(1|RNOSAVE);regused[reg]++;
2115 add_IC(new);
2116 if(DEBUG&16) printf("allocated %s (half)\n",regnames[new->q1.reg]);
2117 rsaved=r;
2118 /* Testen, ob Quellregister gesichert wurde. Unschoen. */
2119 for(p=*rl;p;p=p->next){
2120 int ri;
2121 if(p->v&&(ri=abs(p->reg))){
2122 if(ri==r) break;
2123 if(reg_pair(ri,&rp)&&(rp.r1==r||rp.r2==r)) break;
2124 }
2125 }
2126
2127 if(r&&!p){
2128 t2=clone_typ(regtype[r]);
2129 v=add_var(empty,t2,AUTO,0);
2130 v->flags|=USEDASADR;
2131 new=new_IC();
2132 new->code=MOVEFROMREG;
2133 new->typf=0;
2134 new->q1.flags=REG;
2135 new->q1.reg=r;
2136 new->q2.flags=0;
2137 new->q2.val.vmax=regsize[r];
2138 new->z.flags=VAR|DONTREGISTERIZE;
2139 new->z.v=v;
2140 new->z.val.vmax=l2zm(0L);
2141 add_IC(new);
2142 }
2143 }else{
2144 if((arg->flags&(REG|SCRATCH))!=(REG|SCRATCH)||arg->reg!=reg){
2145 int r=0;
2146 regargs_list *p;
2147
2148 /* register pairs */
2149 if(reg_pair(reg,&rp)){
2150 if(regs[reg]||regs[rp.r1]||regs[rp.r2])
2151 r=reg;
2152 }else{
2153 for(r=MAXR;r>=1;r--){
2154 if(regs[r]&&reg_pair(r,&rp)&&(rp.r1==reg||rp.r2==reg))
2155 break;
2156 }
2157 if(r<1) r=reg;
2158 }
2159
2160
2161 /* Testen, ob Quellregister gesichert wurde. Unschoen. */
2162 for(p=*rl;p;p=p->next){
2163 int ri;
2164 if(p->v&&(ri=abs(p->reg))){
2165 if(ri==r||(reg_pair(r,&rp)&&(rp.r1==ri||rp.r2==ri))) {break;}
2166 if(reg_pair(ri,&rp)&&(rp.r1==r||rp.r2==r)) {break;}
2167 }
2168 }
2169
2170 if(r&&!p){
2171 t2=clone_typ(regtype[r]);
2172 v=add_var(empty,t2,AUTO,0);
2173 v->flags|=USEDASADR;
2174 new=new_IC();
2175 new->code=MOVEFROMREG;
2176 new->typf=0;
2177 new->q1.flags=REG;
2178 new->q1.reg=r;
2179 new->q2.flags=0;
2180 new->q2.val.vmax=regsize[r];
2181 new->z.flags=VAR|DONTREGISTERIZE;
2182 new->z.v=v;
2183 new->z.val.vmax=l2zm(0L);
2184 add_IC(new);
2185 }
2186 }else{
2187 regs[reg]|=RNOSAVE;
2188 }
2189 }
2190 new=new_IC();
2191#ifdef HAVE_REGPARMS
2192 if(!radr){
2193 al->pushic=new;
2194 }
2195#else
2196 al->pushic=new;
2197#endif
2198 new->code=ASSIGN;
2199 new->typf=t;
2200 new->q1=*arg;
2201 /* Testen, ob Quellregister gesichert wurde. Unschoen. */
2202 if((new->q1.flags&REG)){
2203 regargs_list *p;
2204 for(p=*rl;p;p=p->next){
2205 int r;
2206 if(p->v&&(r=abs(p->reg))){
2207 if(new->q1.reg==r||(reg_pair(new->q1.reg,&rp)&&(rp.r1==r||rp.r2==r))) {new->q1.v=p->v;new->q1.val.vmax=l2zm(0L);break;}
2208 /*FIXME: andersrum bei LITTLEENDIAN?? */
2209 if(reg_pair(r,&rp)&&rp.r1==new->q1.reg) {new->q1.v=p->v;new->q1.val.vmax=l2zm(0L);break;}
2210 if(reg_pair(r,&rp)&&rp.r2==new->q1.reg) {new->q1.v=p->v;new->q1.val.vmax=regsize[rp.r1];break;}
2211
2212 }
2213 }
2214 if(p&&new->q1.v){
2215 if(!(new->q1.flags&DREFOBJ)&&must_convert(new->typf,regtype[new->q1.reg]->flags,0)){
2216 new->code=CONVERT;
2217 new->typf2=regtype[new->q1.reg]->flags;
2218 }
2219 new->q1.flags&=~REG;
2220 new->q1.flags|=VAR;
2221 /*new->q1.val.vmax=l2zm(0L);*/
2222 }
2223 }
2224 new->q2.flags=new->z.flags=0;
2225 new->q2.val.vmax=sizetab[t&NQ];
2226 new->z.flags=REG;
2227 new->z.reg=reg;
2228 add_IC(new);
2229 if(al) fix_pushic(&al->pushic,new);
2230 nrl=mymalloc(sizeof(*nrl));
2231 nrl->next=*rl;
2232 nrl->reg=reg;
2233 nrl->v=v;
2234 nrl->rsaved=rsaved; /* if only part of a pair was saved */
2235 rsaved=0;
2236 *rl=nrl;
2237 return of;
2238 }
2239 }
2240}
2241
2242void convert(np p,int f)
2243/* konvertiert das Objekt in p->o in bestimmten Typ */
2244/* wenn volatile_convert gesetzt ist, wird immer IC erzeugt */
2245{
2246 IC *new;
2247 int o=p->ntyp->flags;
2248 int to,tn,mc,dr;
2249 static node n,nn;
2250 static type nt;
2251 char *libname;
2252 if((f&NQ)==VOID) return;
2253
2254 if(p->flags==CEXPR||p->flags==PCEXPR){
2255#ifdef HAVE_MISRA
2256/* removed */
2257/* removed */
2258#endif
2259 eval_constn(p);
2260 p->ntyp->flags=f;
2261 insert_constn(p);
2262 p->o.val=p->val;
2263 return;
2264 }
2265 if((AVOID_FLOAT_TO_UNSIGNED&&ISFLOAT(o)&&(f&UNSIGNED))||
2266 (AVOID_UNSIGNED_TO_FLOAT&&ISFLOAT(f)&&(o&UNSIGNED))){
2267 union atyps val;
2268 int l1,l2,it;
2269 Var *tmp;
2270 np t;
2271 type *ttyp;
2272 if(f&UNSIGNED)
2273 it=f&NQ;
2274 else
2275 it=o&NQ;
2276 ttyp=clone_typ(p->ntyp);
2277 ttyp->flags=f;
2278 tmp=add_tmp_var(ttyp);
2279 new=new_IC();
2280 new->code=COMPARE;
2281 new->typf=o;
2282 new->q1=p->o;
2283 new->q1.flags&=~SCRATCH;
2284 new->q2.flags=KONST;
2285 new->q2.val.vumax=t_max[it];
2286 eval_const(&new->q2.val,MAXINT|UNSIGNED);
2287 insert_const(&new->q2.val,o);
2288 val=new->q2.val;
2289 add_IC(new);
2290 new=new_IC();
2291 new->code=BLE;
2292 l1=++label;
2293 new->typf=l1;
2294 add_IC(new);
2295 new=new_IC();
2296 new->code=SUB;
2297 new->typf=o;
2298 new->q1=p->o;
2299 new->q1.flags&=~SCRATCH;
2300 new->q2.flags=KONST;
2301 new->q2.val=val;
2302 new->z.flags=VAR;
2303 get_scratch(&new->z,o,0,0);
2304 t=new_node();
2305 t->ntyp=clone_typ(p->ntyp);
2306 t->ntyp->flags&=~UNSIGNED;
2307 t->o=new->z;
2308 add_IC(new);
2309 convert(t,f&NQ);
2310 new=new_IC();
2311 new->code=ADD;
2312 new->typf=f;
2313 new->q1=t->o;
2314 new->q1.flags&=~SCRATCH;
2315 freetyp(t->ntyp);
2316 free(t);
2317 new->q2.flags=KONST;
2318 new->q2.val.vumax=t_max[it];
2319 eval_const(&new->q2.val,MAXINT|UNSIGNED);
2320 insert_const(&new->q2.val,f);
2321 new->z.flags=VAR;
2322 new->z.v=tmp;
2323 new->z.val.vmax=l2zm(0L);
2324 add_IC(new);
2325 new=new_IC();
2326 new->code=BRA;
2327 l2=++label;
2328 new->typf=l2;
2329 add_IC(new);
2330 new=new_IC();
2331 new->code=LABEL;
2332 new->typf=l1;
2333 add_IC(new);
2334 p->ntyp->flags&=~UNSIGNED;
2335 convert(p,f&NQ);
2336 new=new_IC();
2337 new->code=ASSIGN;
2338 new->typf=f;
2339 new->q1=p->o;
2340 new->z.flags=VAR;
2341 new->z.v=tmp;
2342 new->z.val.vmax=l2zm(0L);
2343 new->q2.val.vmax=sizetab[f&NQ];
2344 p->o=new->z;
2345 p->ntyp->flags=f;
2346 add_IC(new);
2347 new=new_IC();
2348 new->code=LABEL;
2349 new->typf=l2;
2350 add_IC(new);
2351 return;
2352 }
2353 if(ISVECTOR(f)&&ISSCALAR(o)){
2354 o=VECTYPE(f);
2355 convert(p,o);
2356 }
2357 if(!volatile_convert&&((o&(NU&~UNSIGNED))==(f&(NU&~UNSIGNED))||(!(mc=must_convert(o,f,const_expr))&&(const_expr||!(optflags&2))))){
2358 p->ntyp->flags=f;
2359 if(!ISPOINTER(f)&&!ISARRAY(f)){freetyp(p->ntyp->next);p->ntyp->next=0;}
2360 return;
2361 }
2362 /* do not create direct converts between float and small types
2363 if the backend does not like that */
2364 if(ISFLOAT(o)&&ISINT(f)&&(f&NQ)<MIN_FLOAT_TO_INT_TYPE)
2365 tn=MIN_FLOAT_TO_INT_TYPE|(f&UNSIGNED);
2366 else
2367 tn=f;
2368 libname=0;
2369 if(ISFLOAT(f)&&ISINT(o)&&(o&NQ)<MIN_INT_TO_FLOAT_TYPE){
2370#if HAVE_LIBCALLS
2371 if((libname=use_libcall_wrap(CONVERT,tn,o))&&mc){
2372 to=o;
2373 libname=use_libcall_wrap(CONVERT,tn,MIN_INT_TO_FLOAT_TYPE|(o&UNSIGNED));
2374 if(!libname) ierror(0);
2375 }else
2376#endif
2377 {
2378 to=MIN_INT_TO_FLOAT_TYPE|(o&UNSIGNED);
2379 convert(p,to);
2380 }
2381 }else{
2382 to=o;
2383 }
2384#if HAVE_LIBCALLS
2385 n.flags=CONVERT;
2386 n.ntyp=&nt;
2387 nt.flags=f;
2388 n.left=&nn;
2389 nn.ntyp=p->ntyp;
2390 if((libname||(libname=use_libcall_wrap(CONVERT,tn,to)))&&mc){
2391 node *n=new_node();
2392 n->flags=REINTERPRET;
2393 n->o=p->o;
2394 n->ntyp=p->ntyp;
2395 p->o=gen_libcall(libname,n,p->ntyp,0,0)->o;
2396 }else{
2397#endif
2398 new=new_IC();
2399 new->q1=p->o;
2400 new->q2.flags=0;
2401 new->code=CONVERT;
2402 new->typf2=to;
2403 new->typf=tn;
2404 if((p->o.flags&(SCRATCH|REG))!=(SCRATCH|REG)||!regok(p->o.reg,tn,0)){
2405 get_scratch(&new->z,tn,0,0);
2406 }else{
2407 new->z=p->o;new->z.flags&=~DREFOBJ;
2408 }
2409 p->o=new->z;
2410 /* hmm... */
2411 if(!mc&&libname){
2412 new->code=ASSIGN;
2413 new->q2.val.vmax=sizetab[tn&NQ];
2414 }
2415 add_IC(new);
2416#if HAVE_LIBCALLS
2417 }
2418#endif
2419 if(f!=tn){
2420 p->ntyp->flags=tn;
2421 convert(p,f);
2422 }
2423}
2424
2425void alloc_hardreg(int r)
2426/* Belegt Register r. */
2427{
2428 IC *new;
2429 if(nocode) return;
2430 if(DEBUG&16) printf("allocated %s\n",regnames[r]);
2431 regs[r]=1;regused[r]++;
2432 new=new_IC();
2433 new->code=ALLOCREG;
2434 new->typf=0;
2435 new->q1.flags=REG;
2436 new->q1.reg=r;
2437 new->q2.flags=new->z.flags=0;
2438 add_IC(new);
2439 if(reg_pair(r,&rp)){
2440 regs[rp.r1]=1;regused[rp.r1]++;
2441 regs[rp.r2]=1;regused[rp.r2]++;
2442 }
2443}
2444
2445int allocreg(int f,int mode)
2446/* Fordert Register fuer Typ f an. */
2447{
2448 int i,r=0,prio=-1;
2449 if(nocode) return(1);
2450 for(i=1;i<=MAXR;i++){
2451 if(!regs[i]&&reg_prio[i]>prio&&regok(i,f,mode)&&(!reg_pair(i,&rp)||(!regs[rp.r1]&&!regs[rp.r2]))){
2452 r=i;
2453 prio=reg_prio[i];
2454 }
2455 }
2456 if(r){
2457 if(DEBUG&16) printf("alloc %s\n",regnames[r]);
2458 alloc_hardreg(r);
2459 return r;
2460 }
2461 if(DEBUG&1) printf("Couldn't allocate register for type %d\n",f);
2462 return 0;
2463}
2464void free_reg(int r)
2465/* Gibt Register r frei */
2466{
2467 IC *new;
2468 if(!r||nocode) return;
2469 if(regs[r]==0&&!cross_module)
2470 {printf("Register %d(%s):\n",r,regnames[r]);ierror(0);}
2471 if(DEBUG&16) printf("freed %s\n",regnames[r]);
2472 new=new_IC();
2473 new->code=FREEREG;
2474 new->typf=0;
2475 new->q1.flags=REG;
2476 new->q1.reg=r;
2477 new->q2.flags=new->z.flags=0;
2478 regs[r]=0;
2479 if(reg_pair(r,&rp)){
2480 if(regs[rp.r1]&RHALF){
2481 if(DEBUG&16) printf("keep %s\n",regnames[rp.r1]);
2482 regs[rp.r1]&=~RHALF;
2483 new->q1.reg=rp.r2;
2484 }else
2485 regs[rp.r1]=0;
2486 if(regs[rp.r2]&RHALF){
2487 if(DEBUG&16) printf("keep %s\n",regnames[rp.r2]);
2488 regs[rp.r2]&=~RHALF;
2489 new->q1.reg=rp.r1;
2490 }else
2491 regs[rp.r2]=0;
2492 }
2493 add_IC(new);
2494}
2495void gen_label(int l)
2496/* Erzeugt ein Label */
2497{
2498 IC *new;
2499 new=new_IC();
2500 new->code=LABEL;
2501 new->typf=l;
2502 new->q1.flags=new->q2.flags=new->z.flags=0;
2503 add_IC(new);
2504}
2505void gen_cond(obj *p,int m,int l1,int l2)
2506/* Generiert code, der 0 oder 1 in Register schreibt. Schreibt obj nach p. */
2507{
2508 IC *new;
2509 obj omerk;
2510 new=new_IC();
2511 new->code=ASSIGN;
2512 new->typf=INT;
2513 new->q1.flags=KONST;
2514 new->q2.flags=0;
2515 new->q2.val.vmax=sizetab[INT];
2516 if(!m) vmax=l2zm(1L); else vmax=l2zm(0L);
2517 new->q1.val.vint=zm2zi(vmax);
2518 get_scratch(&new->z,INT,0,0);
2519 omerk=new->z;
2520 add_IC(new);
2521 new=new_IC();
2522 new->code=BRA;
2523 new->typf=l2;
2524 add_IC(new);
2525 gen_label(l1);
2526 new=new_IC();
2527 new->code=ASSIGN;
2528 new->typf=INT;
2529 new->q1.flags=KONST;
2530 new->q2.flags=0;
2531 new->q2.val.vmax=sizetab[INT];
2532 if(!m) vmax=l2zm(0L); else vmax=l2zm(1L);
2533 new->q1.val.vint=zm2zi(vmax);
2534 new->z=omerk;
2535/* new->z.reg=r;
2536 new->z.flags=SCRATCH|REG;*/
2537 add_IC(new);
2538 gen_label(l2);
2539 *p=omerk;
2540}
2541void scratch_var(obj *o,int t,type *typ)
2542/* liefert eine temporaere Variable */
2543/* nicht effizient, aber wer hat schon so wenig Register... */
2544{
2545 type *nt;
2546 if(!ISSCALAR(t)&&!ISVECTOR(t)){
2547 if(!typ) ierror(0);
2548 nt=clone_typ(typ);
2549 }else{
2550 nt=new_typ();
2551 nt->flags=t;
2552 if(ISPOINTER(t)){
2553 nt->next=new_typ();
2554 nt->next->flags=VOID;
2555 }
2556 }
2557 o->flags=SCRATCH|VAR;o->reg=0;
2558 o->v=add_var(empty,nt,AUTO,0);
2559 o->val.vmax=l2zm(0L);
2560}
2561void get_scratch(obj *o,int t1,int t2,type *typ)
2562/* liefert ein Scratchregister oder eine Scratchvariable */
2563{
2564 if(!(optflags&2)&&(o->reg=allocreg(t1,t2))){
2565 o->flags=SCRATCH|REG;
2566 }else{
2567 scratch_var(o,t1,typ);
2568 }
2569}
2570int do_arith(np p,IC *new,np dest,obj *o)
2571/* erzeugt IC new fuer einen arithmetischen Knoten und speichert das */
2572/* Resultat vom Unterknoten dest in o (fuer a op= b) */
2573/* liefert 0, wenn dest nicht gefunden */
2574{
2575 int f=0,mflags;
2576 new->code=p->flags;
2577 if(new->code==PMULT) new->code=MULT;
2578 gen_IC(p->left,0,0);
2579 if(dest&&p->left==dest){
2580 *o=p->left->o;f++;
2581 if(p->left->flags==BITFIELD){
2582 *o=p->left->left->o;
2583 if((o->flags&(REG|SCRATCH))==(REG|SCRATCH))
2584 keep_reg(o->reg);
2585 }
2586 }
2587 gen_IC(p->right,0,0);
2588 if(dest&&p->right==dest) {*o=p->right->o;f++;}
2589 if(dest){
2590 mflags=dest->o.flags;
2591 if(p->left->flags!=BITFIELD)
2592 dest->o.flags&=(~SCRATCH);
2593 }
2594
2595 if(ISPOINTER(p->left->ntyp->flags)&&ISPOINTER(p->right->ntyp->flags)){
2596 /* Subtrahieren zweier Pointer */
2597 int dt=PTRDIFF_T(p->left->ntyp->flags);
2598 if(p->flags!=SUB) ierror(0);
2599 new->typf=dt;
2600 new->typf2=p->left->ntyp->flags;
2601 new->code=SUBPFP;
2602 new->q1=p->left->o;
2603 new->q2=p->right->o;
2604 if(!dest&&(p->left->o.flags&(SCRATCH|REG))==(SCRATCH|REG)&&regok(p->left->o.reg,dt,0)){
2605 new->z=p->left->o;
2606 new->z.flags&=~DREFOBJ;
2607 }else{
2608 if(USEQ2ASZ&&(p->right->o.flags&(SCRATCH|REG))==(SCRATCH|REG)&&regok(p->right->o.reg,dt,0)){
2609 new->z=p->right->o;
2610 new->z.flags&=(~DREFOBJ);
2611 }else{
2612 get_scratch(&new->z,dt,0,0);
2613 }
2614 }
2615 p->o=new->z;
2616 add_IC(new);
2617 if(!zmleq(szof(p->left->ntyp->next),l2zm(1L))){
2618 long ln;
2619 new=new_IC();
2620 new->q1=p->o;
2621 new->q2.flags=KONST;
2622 gval.vmax=szof(p->left->ntyp->next);
2623 eval_const(&gval,MAXINT);
2624 if(ln=get_pof2(vumax)){
2625 /* Division immer ohne Rest, daher shift möglich */
2626 /* TODO: Haben wir Targets ohne arith. shift right? */
2627 gval.vmax=l2zm(ln-1);
2628 eval_const(&gval,MAXINT);
2629 insert_const(&new->q2.val,INT);
2630 new->typf2=INT;
2631 new->code=RSHIFT;
2632 }else{
2633 insert_const(&new->q2.val,dt);
2634 new->code=DIV;
2635 }
2636 new->z=p->o;
2637 new->typf=dt;
2638 add_IC(new);
2639 }
2640 if(dest) dest->o.flags=mflags;
2641 return f;
2642 }
2643 if((p->flags==ADD||p->flags==SUB)&&(ISPOINTER(p->left->ntyp->flags)||ISPOINTER(p->right->ntyp->flags))){
2644 /* Addieren und Subtrahieren eines Integers zu einem Pointer */
2645 if(p->flags==ADD){
2646 new->code=ADDI2P;
2647 if(!ISPOINTER(p->left->ntyp->flags)){
2648 np tmp=p->left;
2649 p->left=p->right;
2650 p->right=tmp;
2651 }
2652 }else
2653 new->code=SUBIFP;
2654 new->typf=p->right->ntyp->flags;
2655 new->typf2=p->ntyp->flags;
2656 new->q1=p->left->o;
2657 /* kleinere Typen als MINADDI2P erst in diesen wandeln */
2658 if(new->typf&UNSIGNED){
2659 if((new->typf&NQ)<(MINADDUI2P&NQ)){convert(p->right,MINADDUI2P);new->typf=MINADDUI2P;}
2660 }else{
2661 if((new->typf&NQ)<MINADDI2P){convert(p->right,MINADDI2P);new->typf=MINADDI2P;}
2662 }
2663 /* groessere Typen als MAXADDI2P erst in diesen wandeln */
2664 if(new->typf&UNSIGNED){
2665 if((new->typf&NQ)>(MAXADDI2P&NQ)){convert(p->right,MAXADDUI2P);new->typf=MAXADDUI2P;}
2666 }else{
2667 if((new->typf&NQ)>MAXADDI2P){convert(p->right,MAXADDI2P);new->typf=MAXADDI2P;}
2668 }
2669 if((p->left->o.flags&VARADR)&&(p->right->o.flags&KONST)){
2670 eval_const(&p->right->o.val,p->right->ntyp->flags);
2671 p->o=p->left->o;
2672 p->o.val.vmax=zmadd(vmax,p->left->o.val.vmax);
2673 free(new);
2674 return f;
2675 }
2676 new->q2=p->right->o;
2677 if(!dest&&(p->left->o.flags&(SCRATCH|REG))==(SCRATCH|REG)&&regok(new->q1.reg,POINTER_TYPE(p->left->ntyp->next),p->left->ntyp->next->flags)){
2678 new->z=p->left->o;
2679 new->z.flags&=(~DREFOBJ);
2680 }else{
2681 /*get_scratch(&new->z,POINTER_TYPE(p->left->ntyp->next),p->left->ntyp->next->flags,0);*/
2682 get_scratch(&new->z,p->ntyp->flags,p->ntyp->next->flags,0);
2683 }
2684 p->o=new->z;
2685 add_IC(new);
2686 if(dest) dest->o.flags=mflags;
2687 return f;
2688 }
2689 if(!ISVECTOR(p->ntyp->flags)||!ISVECTOR(p->left->ntyp->flags))
2690 convert(p->left,p->ntyp->flags);
2691 if(p->flags==LSHIFT||p->flags==RSHIFT){
2692 if(shortcut(p->flags,p->left->ntyp->flags&NU)){
2693 convert(p->right,p->right->ntyp->flags);
2694 new->typf2=p->right->ntyp->flags;
2695 }else{
2696 convert(p->right,INT);
2697 new->typf2=INT;
2698 }
2699#if 0
2700 type *st;
2701 st=clone_typ(p->right->ntyp);
2702 /*st->flags=int_erw(st->flags);*/
2703 st->flags=INT;
2704 convert(p->right,st->flags);
2705 new->typf2=st->flags;
2706 freetyp(st);
2707#endif
2708 }else{
2709 if(!ISVECTOR(p->ntyp->flags)||!ISVECTOR(p->right->ntyp->flags))
2710 convert(p->right,p->ntyp->flags);
2711 }
2712 new->q1=p->left->o;
2713 new->q2=p->right->o;
2714 if(ISVECTOR(p->ntyp->flags)){
2715 new->typf=p->left->ntyp->flags;
2716 new->typf2=p->ntyp->flags;
2717 }else
2718 new->typf=p->ntyp->flags;
2719 /* Bei dest!=0, d.h. ASSIGNOP, darf q1 nicht als Ziel benuzt werden! */
2720 if(!dest&&(new->q1.flags&(SCRATCH|REG))==(SCRATCH|REG)&&regok(new->q1.reg,p->ntyp->flags,0)){
2721 new->z=new->q1;
2722 new->z.flags&=~DREFOBJ;
2723 }else{
2724 if((new->q2.flags&SCRATCH)&&regok(new->q2.reg,p->ntyp->flags,0)){
2725 if((p->flags>=OR&&p->flags<=AND)||p->flags==ADD||p->flags==MULT||p->flags==PMULT){
2726 /* bei kommutativen Operatoren vertauschen */
2727 new->z=new->q2;
2728 new->q2=new->q1;
2729 new->q1=new->z;
2730 new->z.flags&=~DREFOBJ;
2731 }else{
2732 if(USEQ2ASZ){
2733 new->z=new->q2;
2734 new->z.flags&=~DREFOBJ;
2735 }else{
2736 get_scratch(&new->z,new->typf,0,0);
2737 }
2738 }
2739 }else{
2740 get_scratch(&new->z,new->typf,0,0);
2741 }
2742 }
2743 p->o=new->z;
2744 add_IC(new);
2745 if(dest){
2746 dest->o.flags=mflags;
2747 /*
2748 if((dest->o.flags&REG)&&!regs[dest->o.reg])
2749 keep_reg(dest->o.reg);
2750 */
2751 }
2752
2753 return f;
2754}
2755void savescratch(int code,IC *p,int dontsave,obj *o)
2756/* speichert Scratchregister bzw. stellt sie wieder her (je nach code */
2757/* entweder MOVEFROMREG oder MOVETOREG) */
2758{
2759 int i,s,e,b,ds1,ds2;IC *new;
2760 if(code==MOVETOREG){ s=1;e=MAXR+1;b=1;} else {s=MAXR;e=0;b=-1;}
2761 if(reg_pair(dontsave,&rp)){
2762 ds1=rp.r1;
2763 ds2=rp.r2;
2764 }else
2765 ds1=ds2=0;
2766 for(i=s;i!=e;i+=b){
2767 int mustsave=0;
2768 if((o->flags&(VAR|DREFOBJ))==VAR&&o->v->fi&&(o->v->fi->flags&ALL_REGS))
2769 mustsave=BTST(o->v->fi->regs_modified,i);
2770 else
2771 mustsave=regscratch[i];
2772 if(regsa[i]) mustsave=0;
2773 if(mustsave) simple_scratch[i]=1;
2774 if(regs[i]&&!(regs[i]&RNOSAVE)&&mustsave&&i!=dontsave&&i!=ds1&&i!=ds2&&!reg_pair(i,&rp)){
2775 if(!regsbuf[i]){
2776 type *t;
2777 if(code!=MOVEFROMREG) continue;
2778 t=clone_typ(regtype[i]);
2779 regsbuf[i]=add_var(empty,t,AUTO,0);
2780 regsbuf[i]->flags|=USEDASADR;
2781 regbnesting[i]=nesting;
2782 }
2783 new=new_IC();
2784 new->typf=new->q2.flags=0;
2785 new->line=0;new->file=0;
2786 new->code=code;
2787 if(code==MOVEFROMREG){
2788 new->q1.flags=REG;new->q1.reg=i;
2789 new->z.flags=VAR|DONTREGISTERIZE;new->z.v=regsbuf[i];
2790 new->z.val.vmax=l2zm(0L);
2791 }else{
2792 new->z.flags=REG;new->z.reg=i;
2793 new->q1.flags=VAR|DONTREGISTERIZE;new->q1.v=regsbuf[i];
2794 new->q1.val.vmax=l2zm(0L);
2795 }
2796 new->use_cnt=new->change_cnt=0;
2797 new->use_list=new->change_list=0;
2798 insert_IC(p,new);
2799 }
2800 }
2801}
2802