blob: f0a942e1727556eeea69f66bc384d4834774e9d5 [file] [log] [blame]
PulkoMandy17fc7592022-07-28 18:27:54 +02001/* $VER: vbcc (alias.c) $Revision: 1.6 $ */
2/* Listen benutzter/veraenderter Variablen und Behandlung von Decknamen. */
3
4#include "opt.h"
5
6static char FILE_[]=__FILE__;
7
8static bvtype **gpt;
9
10static unsigned long ptsize;
11
12#define is_restrict(i) ((i)<=vcount-rcount&&(vilist[i]->vtyp->flags&RESTRICT))
13
14/* sets points-to-info for var i to undefined */
15void undef_pt(bvtype **pt,int i)
16{
17 if(i<0||i>=vcount) ierror(0);
18 if(pt[i]) ptsize-=vsize;
19 free(pt[i]);
20 pt[i]=0;
21 if(i<rcount){
22 i+=vcount-rcount;
23 if(pt[i]) ptsize-=vsize;
24 free(pt[i]);
25 pt[i]=0;
26 }
27}
28
29/* walks through a clist and sets the corresponding bit in bv
30 for every variable whose address is contained in the clist */
31void add_clist_refs(bvtype *bv,type *t,const_list *cl)
32{
33 /*FIXME: bei Aufrufen auch auf locale, nicht USEDASDEST|USEDASADDR */
34 int i;zmax sz;
35 if(ISARRAY(t->flags)){
36 for(sz=l2zm(0L);!zmleq(t->size,sz)&&cl;sz=zmadd(sz,l2zm(1L)),cl=cl->next){
37 if(!cl->other){ierror(0);return;}
38 add_clist_refs(bv,t->next,cl->other);
39 }
40 return;
41 }
42 if(ISUNION(t->flags)){
43 add_clist_refs(bv,(*t->exact->sl)[0].styp,cl);
44 return;
45 }
46 if(ISSTRUCT(t->flags)){
47 type *st;
48 for(i=0;i<t->exact->count&&cl;i++){
49 if(!cl->other){ierror(0);return;}
50 st=(*t->exact->sl)[i].styp;
51 if(!(*t->exact->sl)[i].identifier) ierror(0);
52 if((*t->exact->sl)[i].identifier[0]){
53 add_clist_refs(bv,st,cl->other);
54 cl=cl->next;
55 }
56 }
57 return;
58 }
59 if(cl->tree&&(cl->tree->o.flags&VARADR)){
60 /* careful: variable might not have a valid index if it is not
61 used within the function optimized */
62 i=cl->tree->o.v->index;
63 if(i>=0&&i<vcount-rcount&&vilist[i]==cl->tree->o.v){
64 /*printf("add %s\n",vilist[i]->identifier);*/
65 BSET(bv,i);
66 }
67 }
68}
69
70/* copies points-to-info for one var to another */
71void copy_pt(bvtype **pt,int to,int from)
72{
73 if(to<0||to>=vcount) ierror(0);
74 if(from<0||from>=vcount) ierror(0);
75 if(!pt[from]){
76 if(from>=vcount-rcount&&pt[from-(vcount-rcount)]){
77 /* if dref check, whether from only points to initialized const */
78 int i;bvtype *new;
79 for(i=0;i<vcount;i++){
80 if(BTST(pt[from-(vcount-rcount)],i)){
81 Var *v=vilist[i];
82 if(!is_const(v->vtyp)||!v->clist||(v->storage_class!=STATIC&&v->storage_class!=EXTERN))
83 break;
84 }
85 }
86 if(i==vcount){
87 /* yes, take the points-to-info from clist */
88 if(!pt[to]||to+vcount-rcount==from){
89 new=mymalloc(vsize);
90 ptsize+=vsize;
91 }else
92 new=pt[to];
93 memset(new,0,vsize);
94 for(i=0;i<vcount;i++){
95 if(BTST(pt[from-(vcount-rcount)],i))
96 add_clist_refs(new,vilist[i]->vtyp,vilist[i]->clist);
97 }
98 if(to+vcount-rcount==from){
99 ptsize-=vsize;
100 free(pt[to]);
101 }
102 pt[to]=new;
103 return;
104 }
105 }
106 undef_pt(pt,to);
107 }else{
108 if(!pt[to]){
109 pt[to]=mymalloc(vsize);
110 ptsize+=vsize;
111 }
112 memcpy(pt[to],pt[from],vsize);
113 }
114}
115
116/* set var i points only to j in points-to-info */
117void set_pt(bvtype **pt,int i,int j)
118{
119 if(i<0||i>=vcount) ierror(0);
120 if(j<0||j>=vcount) ierror(0);
121 if(!pt[i]){
122 pt[i]=mymalloc(vsize);
123 ptsize+=vsize;
124 }
125 memset(pt[i],0,vsize);
126 BSET(pt[i],j);
127}
128
129void print_single_pt(bvtype *pt)
130{
131 int j;
132 if(pt){
133 for(j=0;j<vcount;j++){
134 if(BTST(pt,j))
135 printf(" %s<%s>(%p)\n",(j>=vcount-rcount)?"*":"",vilist[j]->identifier,(void*)vilist[j]);
136 }
137 }else{
138 printf(" (undefined)\n");
139 }
140}
141
142void print_pt(bvtype **pt)
143{
144 int i,j;
145 if(!pt) return;
146 printf("points-to:\n");
147 for(i=0;i<vcount;i++){
148 printf("%s<%s>(%p):\n",(i>=vcount-rcount)?"*":"",vilist[i]->identifier,(void*)vilist[i]);
149 print_single_pt(pt[i]);
150 }
151}
152
153/* creates new points-to-info; every var set to undefined */
154bvtype **new_pt(void)
155{
156 bvtype **pt;
157 int i;
158 pt=mymalloc(vcount*sizeof(*pt));
159 ptsize+=vcount*sizeof(*pt);
160 for(i=0;i<vcount;i++){
161 if(i<rcount&&(vilist[i]->vtyp->flags&RESTRICT)){
162 pt[i]=mymalloc(vsize);
163 ptsize+=vsize;
164 memset(pt[i],0,vsize);
165 BSET(pt[i],i+vcount-rcount);
166 }else
167 pt[i]=0;
168 }
169 return pt;
170}
171
172void free_pt(bvtype **pt)
173{
174 int i;
175 if(pt){
176 for(i=0;i<vcount;i++){
177 if(pt[i]) ptsize-=vsize;
178 free(pt[i]);
179 }
180 ptsize-=vcount*sizeof(*pt);
181 free(pt);
182 }
183}
184
185/* set points-to-info of *v to union of points-to of all vars in the
186 points-to-info of v */
187void dref_pt(bvtype **pt,int i)
188{
189 int j,d;
190 if(i<0||i>=rcount) ierror(0);
191 d=i+vcount-rcount;
192 if(!pt[i]){
193 undef_pt(pt,d);
194 return;
195 }
196 if(!pt[d]){
197 pt[d]=mymalloc(vsize);
198 ptsize+=vsize;
199 }
200 memset(pt[d],0,vsize);
201 for(j=0;j<vcount;j++){
202 if(BTST(pt[i],j)){
203 Var *v=vilist[j];
204 if(v->clist&&is_const(v->vtyp)&&(v->storage_class==STATIC||v->storage_class==EXTERN)){
205 add_clist_refs(pt[d],v->vtyp,v->clist);
206 }else if(!pt[j]){
207 undef_pt(pt,d);
208 return;
209 }else
210 bvunite(pt[d],pt[j],vsize);
211 }
212 }
213}
214
215void trans_pt(bvtype **pt,IC *p)
216{
217 int i,j,newset=-1,sv,cp;
218 if((p->code==ADDI2P||p->code==SUBIFP)&&!compare_objs(&p->q1,&p->z,ztyp(p)))
219 return;
220 if((p->z.flags&VAR)&&ISSCALAR(p->z.v->vtyp->flags)){
221 i=p->z.v->index;
222 if(i<0||i>=vcount) ierror(0);
223 if(p->z.flags&DREFOBJ){
224 if(i>=rcount) ierror(0);
225 i+=vcount-rcount;
226 }
227 if(!is_restrict(i)){
228 if(p->code==ASSIGN){
229 newset=i;sv=-1;cp=-1;
230 if(p->q1.flags&VARADR){
231 sv=p->q1.v->index;
232 set_pt(pt,i,p->q1.v->index);
233 }else if(p->q1.flags&VAR){
234 j=p->q1.v->index;
235 if(j<0||j>=vcount) ierror(0);
236 if(p->q1.flags&DREFOBJ){
237 if(j>=rcount) ierror(0);
238 j+=vcount-rcount;
239 }
240 cp=j;
241 copy_pt(pt,i,j);
242 }else{
243 if(!pt[i]){
244 pt[i]=mymalloc(vsize);
245 ptsize+=vsize;
246 }
247 memset(pt[i],0,vsize);
248 }
249 }
250 if(p->code==ADDRESS){
251 newset=i;sv=p->q1.v->index;cp=-1;
252 set_pt(pt,i,p->q1.v->index);
253 }
254 if((p->code==ADDI2P||p->code==SUBIFP)&&(p->q1.flags&VAR)){
255 newset=i;sv=-1;cp=-1;
256 if(p->q1.flags&VARADR){
257 sv=p->q1.v->index;
258 set_pt(pt,i,p->q1.v->index);
259 }else{
260 j=p->q1.v->index;
261 if(j<0||j>=vcount) ierror(0);
262 if(p->q1.flags&DREFOBJ){
263 if(j>=rcount) ierror(0);
264 j+=vcount-rcount;
265 }
266 cp=j;
267 copy_pt(pt,i,j);
268 }
269 }
270 }
271 }
272 if(newset>=0&&newset<rcount){
273 if(newset<0) ierror(0);
274 dref_pt(pt,newset);
275 }
276 for(i=0;i<p->change_cnt;i++){
277 j=p->change_list[i].v->index;
278 if(j<0||j>=vcount) ierror(0);
279 if(p->change_list[i].flags&DREFOBJ){
280 if(j>=rcount) ierror(0);
281 j+=vcount-rcount;
282 }
283 if(j!=newset&&!is_restrict(j)){
284 if(newset>=0&&pt[j]){
285 if(sv>=0){
286 if(sv>=vcount) ierror(0);
287 BSET(pt[j],sv);
288 }
289 if(cp>=0&&pt[cp]){
290 if(cp<0||cp>=vcount) ierror(0);
291 bvunite(pt[j],pt[cp],vsize);
292 }
293 }else
294 undef_pt(pt,j);
295 }
296 }
297}
298
299bvtype **clone_pt(bvtype **pt)
300{
301 int i;
302 bvtype **new;
303 if(!pt)
304 return new_pt();
305 new=mymalloc(vcount*sizeof(*new));
306 ptsize+=vcount*sizeof(*new);
307 for(i=0;i<vcount;i++){
308 if(pt[i]){
309 new[i]=mymalloc(vsize);
310 ptsize+=vsize;
311 memcpy(new[i],pt[i],vsize);
312 }else
313 new[i]=0;
314 }
315 return new;
316}
317
318/* tests if two points-to-infos are identical */
319int equal_pt(bvtype **pt1,bvtype **pt2)
320{
321 int i;
322 if(!pt1&&!pt2)
323 return 1;
324 if(!pt1||!pt2)
325 return 0;
326 for(i=0;i<vcount;i++){
327 if(!pt1[i]&&!pt2[i])
328 continue;
329 if(!pt1[i]||!pt2[i])
330 return 0;
331 if(memcmp(pt1[i],pt2[i],vsize))
332 return 0;
333 }
334 return 1;
335}
336#if 0
337void calc_pt(flowgraph *fg)
338{
339 flowgraph *g;
340 flowlist *in;
341 IC *p;
342 bvtype **pt,**ppt;
343 int i,all_preds,changed;
344
345 changed=1;
346 while(changed){
347 if(DEBUG&1024) printf("calc_pt pass\n");
348 changed=0;
349 for(g=fg;g;g=g->normalout){
350 /* do all predecessors already have points-to-info? */
351 all_preds=1;
352 for(in=g->in;in;in=in->next){
353 if(!in->graph->pt){
354 all_preds=0;
355 break;
356 }
357 }
358 if(all_preds&&g->in){
359 /* calc union of all predecessors */
360 pt=clone_pt(g->in->graph->pt);
361 for(in=g->in->next;in;in=in->next){
362 ppt=in->graph->pt;
363 for(i=0;i<vcount;i++){
364 if(pt[i]){
365 if(!ppt[i])
366 undef_pt(pt,i);
367 else
368 bvunite(pt[i],ppt[i],vsize);
369 }
370 }
371 }
372 }else
373 pt=new_pt();
374 for(p=g->start;p;p=p->next){
375 trans_pt(pt,p);
376 if(p==g->end)
377 break;
378 }
379 if(pt==g->pt) ierror(0);
380 if(!changed){
381 if(!equal_pt(pt,g->pt)){
382 changed=1;
383 free_pt(g->pt);
384 g->pt=pt;
385 }else{
386 free_pt(pt);
387 }
388 }else{
389 free_pt(g->pt);
390 g->pt=pt;
391 }
392 }
393 }
394}
395#endif
396int p_typ(Var *v)
397/* Liefert den Typ, auf den Variable zeigen kann. Falls nicht eindeutig */
398/* wird CHAR zurueckgegeben, da ein char * auf alles zeigen kann. */
399{
400 type *t=v->vtyp;int f;
401 /* Kein Zeiger? Dann moeglicherweise Struktur, die verschiedene Zeiger */
402 /* enthalten koennte. Koennte man evtl. noch genauer pruefen. */
403 if(!ISPOINTER(t->flags)||!t->next||(v->flags&DNOTTYPESAFE)) return CHAR;
404 f=t->next->flags&NQ;
405 if(f==VOID) f=CHAR;
406 return f;
407}
408
409/* propagates information if a variable whose address may have been taken
410 is modified */
411static void propagate_pointers(bvtype *set,Var *v,int t,int i)
412{
413 int j,t2;
414 if(v->nesting==0||v->storage_class==EXTERN||(v->flags&USEDASADR)){
415 if(noaliasopt){
416 bvunite(set,av_drefs,vsize);
417 }else{
418 for(j=0;j<rcount;j++){
419 t2=p_typ(vilist[j]);
420 if(t==t2||t2==CHAR||!ISSCALAR(t)||!ISSCALAR(t2)){
421 if(!gpt||!gpt[j]||(i>=0&&BTST(gpt[j],i)))
422 BSET(set,j+vcount-rcount);
423 }
424 }
425 }
426 }
427}
428void alias_propagate(bvtype *set,int i,int t,int wr)
429{
430 int j,t2;
431 Var *v;
432 if(i<0||i>=vcount) ierror(0);
433 t&=NQ;
434 BSET(set,i);
435 if(wr&&i<rcount) BSET(set,i+vcount-rcount);
436 if(i>=vcount-rcount){
437 /* DREFOBJ */
438 if(noaliasopt||t==CHAR||!ISSCALAR(t)){
439 bvunite(set,av_drefs,vsize);
440 bvunite(set,av_address,vsize);
441 bvunite(set,av_globals,vsize);
442 }else{
443 for(j=0;j<vcount-rcount;j++){
444 v=vilist[j];
445 if(!gpt||!gpt[i-(vcount-rcount)]||BTST(gpt[i-(vcount-rcount)],j)){
446 v=vilist[j];
447 if(!v) ierror(0);
448 if(v->nesting==0||v->storage_class==EXTERN||(v->flags&USEDASADR)){
449 type *tp=v->vtyp;
450 if(!v->vtyp) ierror(0);
451 do{
452 t2=tp->flags&NQ;
453 tp=tp->next;
454 }while(ISARRAY(t2));
455 if(t==t2||!ISSCALAR(t2)){
456 BSET(set,j);
457 if(wr&&j<rcount) {BSET(set,j+vcount-rcount);continue;}
458 }
459 }
460 }
461 if(j<rcount){
462 if(i<(vcount-rcount)) ierror(0);
463 if(!gpt||
464 (!gpt[i-(vcount-rcount)]&&!is_restrict(j))||
465 (!gpt[j]&&!is_restrict(i-(vcount-rcount)))||
466 (gpt[j]&&gpt[i-(vcount-rcount)]&&bvdointersect(gpt[i-(vcount-rcount)],gpt[j],vsize))){
467 t2=p_typ(v);
468 if(t==t2||t2==CHAR||!ISSCALAR(t2))
469 BSET(set,j+vcount-rcount);
470 }
471 }
472 }
473 }
474 }else{
475 v=vilist[i];
476 propagate_pointers(set,v,t,i);
477 }
478}
479
480void ic_changes(IC *p,bvtype *result)
481/* Initialisiert den Bitvektor result mit allen Variablen, die durch das */
482/* IC p geaendert werden koennten. */
483{
484 int i,j,t,t2;Var *v;
485 memset(result,0,vsize);
486 t=(ztyp(p)&NQ);
487 if(p->z.flags&VAR){
488 v=p->z.v;
489 i=v->index;
490 /* Hilfsvariable, die waehrend diesem cse-Durchlauf eingefuehrt */
491 /* wurde. */
492 if(i<0) return;
493 if(i>=vcount) ierror(0);
494 if(p->z.flags&DREFOBJ){
495 if(i>=rcount) ierror(0);
496 alias_propagate(result,i+vcount-rcount,t,1);
497 }else{
498 alias_propagate(result,i,t,1);
499 if(i<rcount) BSET(result,i+vcount-rcount);
500 }
501 }
502 if(p->code==CALL){
503 function_info *fi;
504 if((p->q1.flags&(VAR|DREFOBJ))==VAR&&(fi=p->q1.v->fi)&&(fi->flags&ALL_MODS)&&!(disable&65536)){
505 /* we can get the set from the function_info */
506 for(i=0;i<fi->change_cnt;i++){
507 if(v=fi->change_list[i].v){
508 if(v->inr==inr&&v->index>=0){
509 if(v->index>=vcount) ierror(0);
510 alias_propagate(result,v->index,v->vtyp->flags&NQ,1);
511 }else
512 propagate_pointers(result,v,v->vtyp->flags&NQ,-1);
513 }else{
514 for(j=0;j<vcount-rcount;j++){
515 v=vilist[j];
516 if(v->nesting==0||v->storage_class==EXTERN||(v->flags&USEDASADR)){
517 t=v->vtyp->flags&NQ;
518 if(t==(fi->change_list[i].flags&NQ)||!ISSCALAR(t)){
519 BSET(result,j);
520 if(j<rcount) BSET(result,j+vcount-rcount);
521 }
522 }
523 if(j<rcount){
524 t=p_typ(vilist[j]);
525 if(t==CHAR||!ISSCALAR(t)||t==fi->change_list[i].flags)
526 BSET(result,j+vcount-rcount);
527 }
528 }
529 }
530 }
531 }else{
532 bvunite(result,av_drefs,vsize);
533 bvunite(result,av_address,vsize);
534 bvunite(result,av_globals,vsize);
535 bvunite(result,av_statics,vsize);
536 }
537 }
538 if((p->z.flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
539 bvunite(result,av_drefs,vsize);
540 }
541}
542void ic_uses(IC *p,bvtype *result)
543/* Initialisiert den Bitvektor result mit allen Variablen, die durch das */
544/* IC p benutzt werden koennten. */
545{
546 int i,j,t,t2,c;Var *v;type *tp;
547 memset(result,0,vsize);
548 c=p->code;
549 if(c!=ADDRESS){
550 if((p->q1.flags&(VAR|VARADR))==VAR&&c!=ADDRESS&&(c!=CALL||(p->q1.flags&DREFOBJ))){
551 v=p->q1.v;
552 i=v->index;
553 if(i<0||i>=vcount) ierror(0);
554 t=q1typ(p);
555 if(p->q1.flags&DREFOBJ){
556 if(i>=rcount) ierror(0);
557 alias_propagate(result,i+vcount-rcount,t,0);
558 }
559 alias_propagate(result,i,t,0);
560 }
561 if((p->q2.flags&(VAR|VARADR))==VAR){
562 v=p->q2.v;
563 i=v->index;
564 if(i<0||i>=vcount) ierror(0);
565 t=q2typ(p);
566 if(p->q2.flags&DREFOBJ){
567 if(i>=rcount) ierror(0);
568 alias_propagate(result,i+vcount-rcount,t,0);
569 }
570 alias_propagate(result,i,t,0);
571 }
572 }
573 if((p->z.flags&(VAR|VARADR|DREFOBJ))==(VAR|DREFOBJ)){
574 v=p->z.v;
575 i=v->index;
576 if(i>=vcount) {pric2(stdout,p);ierror(0);}
577 t=(ztyp(p)&NQ);
578 alias_propagate(result,i,t,0);
579 }
580 if(p->code==CALL){
581 function_info *fi;
582 if((p->q1.flags&(VAR|DREFOBJ))==VAR&&(fi=p->q1.v->fi)&&(fi->flags&ALL_USES)&&!(disable&65536)){
583 /* we can get the set from the function_info */
584 for(i=0;i<fi->use_cnt;i++){
585 if(v=fi->use_list[i].v){
586 if(v->inr==inr&&v->index>=0)
587 alias_propagate(result,v->index,v->vtyp->flags&NQ,0);
588 else
589 propagate_pointers(result,v,v->vtyp->flags&NQ,-1);
590 }else{
591 for(j=0;j<vcount-rcount;j++){
592 v=vilist[j];
593 if(v->nesting==0||v->storage_class==EXTERN||(v->flags&USEDASADR)){
594 t=v->vtyp->flags&NQ;
595 if(t==(fi->use_list[i].flags&NQ)||!ISSCALAR(t))
596 BSET(result,j);
597 }
598 if(j<rcount){
599 t=p_typ(vilist[j]);
600 if(t==CHAR||!ISSCALAR(t)||t==fi->use_list[i].flags)
601 BSET(result,j+vcount-rcount);
602 }
603 }
604 }
605 }
606 }else{
607 bvunite(result,av_drefs,vsize);
608 bvunite(result,av_address,vsize);
609 bvunite(result,av_globals,vsize);
610 bvunite(result,av_statics,vsize);
611 }
612 }
613 if((p->q1.flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
614 bvunite(result,av_drefs,vsize);
615 }
616 if((p->q2.flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
617 bvunite(result,av_drefs,vsize);
618 }
619}
620void free_alias(flowgraph *fg)
621/* Gibt alle use/change-Listen der ICs im Flussgraphen frei. */
622{
623 IC *p;flowgraph *g;
624 if(DEBUG&1024) printf("freeing alias info\n");
625 for(g=fg;g;g=g->normalout){
626 for(p=g->start;p;p=p->next){
627 if(p->code==LABEL&&(p->use_cnt>0||p->change_cnt>0)) ierror(0);
628 if(p->use_cnt>0) {free(p->use_list);p->use_cnt=0;}
629 if(p->change_cnt>0) {free(p->change_list);p->change_cnt=0;}
630 if(p==g->end) break;
631 }
632 }
633 have_alias=0;
634}
635void create_alias(flowgraph *fg)
636/* Initialisiert jedes IC mit einer Liste aller Variablen, die dadurch */
637/* benutzt und veraendert werden koennten. Z.Z. wird bis auf Typ-basierte */
638/* Optimierungen der worst-case angenommen. */
639{
640 bvtype *vars=mymalloc(vsize);
641 IC *p;flowgraph *g;
642 flowlist *in;
643 bvtype **ppt;
644 int i,cnt,all_preds,changed;
645 unsigned long heapsize;
646 if(DEBUG&1024) printf("creating alias info\n");
647
648 ptsize=0;
649
650 changed=1;
651 while(changed){
652 if(DEBUG&1024) printf("create_alias pass\n");
653 changed=0;
654 if(have_alias)
655 free_alias(fg);
656 heapsize=0;
657 for(g=fg;g;g=g->normalout){
658 if((optflags&1024)&&!noaliasopt){
659 /* do all predecessors already have points-to-info? */
660 all_preds=1;
661 for(in=g->in;in;in=in->next){
662 if(!in->graph->pt){
663 all_preds=0;
664 break;
665 }
666 }
667 if(/*all_preds&&*/g->in){
668 /* calc union of all predecessors */
669 gpt=clone_pt(g->in->graph->pt);
670 for(in=g->in->next;in;in=in->next){
671 ppt=in->graph->pt;
672 if(!ppt)
673 continue;
674 for(i=0;i<vcount;i++){
675 if(gpt[i]){
676 if(!ppt[i])
677 undef_pt(gpt,i);
678 else
679 bvunite(gpt[i],ppt[i],vsize);
680 }
681 }
682 }
683 }else
684 gpt=new_pt();
685 }else{
686 gpt=0;
687 }
688 for(p=g->start;p;p=p->next){
689 int da; /* always consider a direct write, even if variable is const-qualified */
690 ic_uses(p,vars);
691 for(i=0,cnt=0;i<vcount;i++)
692 if(BTST(vars,i)) cnt++;
693 p->use_cnt=cnt;
694 if(cnt==0){
695 p->use_list=0;
696 }else{
697 p->use_list=mymalloc(cnt*VLS);
698 heapsize+=cnt*VLS;
699 for(cnt=0,i=0;i<vcount;i++){
700 if(BTST(vars,i)){
701 p->use_list[cnt].v=vilist[i];
702 if(i>=vcount-rcount) p->use_list[cnt].flags=DREFOBJ;
703 else p->use_list[cnt].flags=0;
704 cnt++;
705 }
706 }
707 }
708 ic_changes(p,vars);
709 if((p->z.flags&(VAR|DREFOBJ))==VAR)
710 da=p->z.v->index;
711 else
712 da=0;
713 for(i=0,cnt=0;i<vcount;i++)
714 if(BTST(vars,i)&&(i>=vcount-rcount||i==da||!is_const(vilist[i]->vtyp))) cnt++;
715 p->change_cnt=cnt;
716 if(cnt==0){
717 p->change_list=0;
718 }else{
719 p->change_list=mymalloc(cnt*VLS);
720 heapsize+=cnt*VLS;
721 for(cnt=0,i=0;i<vcount;i++){
722 if(BTST(vars,i)&&(i>=vcount-rcount||i==da||!is_const(vilist[i]->vtyp))){
723 p->change_list[cnt].v=vilist[i];
724 if(i>=vcount-rcount) p->change_list[cnt].flags=DREFOBJ;
725 else p->change_list[cnt].flags=0;
726 cnt++;
727 }
728 }
729 }
730
731 if(p->code==CALL){
732 if((p->q1.flags&(VAR|DREFOBJ))==(VAR|DREFOBJ)){
733 int i=p->q1.v->index;
734 if(i<0||i>=vcount) ierror(0);
735 if(gpt&&gpt[i]){
736 int j,cnt;
737 for(cnt=0,j=0;j<vcount-rcount;j++){
738 if(BTST(gpt[i],j)&&ISFUNC(vilist[j]->vtyp->flags))
739 cnt++;
740 }
741 if(cnt){
742 if(p->call_cnt) free(p->call_list);
743 p->call_cnt=cnt;
744 p->call_list=mymalloc(sizeof(*p->call_list)*cnt);
745 for(cnt=0,j=0;j<vcount-rcount;j++){
746 if(BTST(gpt[i],j)&&ISFUNC(vilist[j]->vtyp->flags)){
747 p->call_list[cnt].v=vilist[j];
748 p->call_list[cnt].flags=0;
749 cnt++;
750 }
751 }
752 if(cnt==1&&all_preds){
753 if(DEBUG&1024) {printf("replacing indirect call by single target:\n");pric2(stdout,p);}
754 p->q1.flags=VAR;
755 p->q1.val.vmax=l2zm(0L);
756 p->q1.v=p->call_list[0].v;
757 }
758 }
759 }
760 }
761 }
762
763 if((optflags&1024)&&!noaliasopt)
764 trans_pt(gpt,p);
765 if(p==g->end) break;
766 }
767 if((optflags&1024)&&!noaliasopt){
768 if(!changed){
769 if(!equal_pt(gpt,g->pt)){
770 changed=1;
771 free_pt(g->pt);
772 g->pt=gpt;
773 }else{
774 free_pt(gpt);
775 }
776 }else{
777 free_pt(g->pt);
778 g->pt=gpt;
779 }
780 }
781 }
782 if(DEBUG&16384) printf("create_alias heapsize=%lu\n",heapsize);
783 have_alias=1;
784 }
785 if(DEBUG&16384) printf("points-to heapsize=%lu\n",ptsize);
786 if((optflags&1024)&&!noaliasopt){
787 for(g=fg;g;g=g->normalout){
788 free_pt(g->pt);
789 g->pt=0;
790 }
791 }
792 free(vars);
793}
794#if 1
795void update_alias(Var *old,Var *new)
796/* Aendert alle use/changes von (old) auf (new). Wird aufgerufen, wenn */
797/* copy-propagation eine Variable neu zu einem DREFOBJ macht. */
798{
799 IC *p;int i;
800 if(DEBUG&1024) printf("update-alias\n");
801 for(p=first_ic;p;p=p->next){
802 for(i=0;i<p->use_cnt;i++){
803 if(p->use_list[i].v==old&&(p->use_list[i].flags&DREFOBJ)){
804 p->use_cnt++;
805 p->use_list=myrealloc(p->use_list,p->use_cnt*VLS);
806 p->use_list[p->use_cnt-1].v=new;
807 p->use_list[p->use_cnt-1].flags=DREFOBJ;
808 break;
809 }
810 }
811 for(i=0;i<p->change_cnt;i++){
812 if(p->change_list[i].v==new||(p->change_list[i].v==old&&(p->change_list[i].flags&DREFOBJ))){
813 p->change_cnt++;
814 p->change_list=myrealloc(p->change_list,p->change_cnt*VLS);
815 p->change_list[p->change_cnt-1].v=new;
816 p->change_list[p->change_cnt-1].flags=DREFOBJ;
817 break;
818 }
819 }
820 }
821}
822#endif