PulkoMandy | 17fc759 | 2022-07-28 18:27:54 +0200 | [diff] [blame] | 1 | /* $VER: vbcc (alias.c) $Revision: 1.6 $ */ |
| 2 | /* Listen benutzter/veraenderter Variablen und Behandlung von Decknamen. */ |
| 3 | |
| 4 | #include "opt.h" |
| 5 | |
| 6 | static char FILE_[]=__FILE__; |
| 7 | |
| 8 | static bvtype **gpt; |
| 9 | |
| 10 | static 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 */ |
| 15 | void 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 */ |
| 31 | void 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 */ |
| 71 | void 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 */ |
| 117 | void 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 | |
| 129 | void 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 | |
| 142 | void 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 */ |
| 154 | bvtype **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 | |
| 172 | void 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 */ |
| 187 | void 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 | |
| 215 | void 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 | |
| 299 | bvtype **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 */ |
| 319 | int 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 |
| 337 | void 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 |
| 396 | int 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 */ |
| 411 | static 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 | } |
| 428 | void 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 | |
| 480 | void 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 | } |
| 542 | void 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 | } |
| 620 | void 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 | } |
| 635 | void 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 |
| 795 | void 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 |