816 lines · 19.9 KB · C
RawDownload
/*  $VER: vbcc (alias.c) V0.8   *//*  Listen benutzter/veraenderter Variablen und Behandlung von Decknamen.   */ #include "opt.h" static char FILE_[]=__FILE__; static bvtype **gpt; static unsigned long ptsize; #define is_restrict(i) ((i)<=vcount-rcount&&(vilist[i]->vtyp->flags&RESTRICT)) /* sets points-to-info for var i to undefined */void undef_pt(bvtype **pt,int i){  if(i<0||i>=vcount) ierror(0);  if(pt[i]) ptsize-=vsize;  free(pt[i]);  pt[i]=0;  if(i<rcount){    i+=vcount-rcount;    if(pt[i]) ptsize-=vsize;    free(pt[i]);    pt[i]=0;  }} /* walks through a clist and sets the corresponding bit in bv   for every variable whose address is contained in the clist */void add_clist_refs(bvtype *bv,struct Typ *t,struct const_list *cl){  /*FIXME: bei Aufrufen auch auf locale, nicht USEDASDEST|USEDASADDR */  int i;zmax sz;  if(ISARRAY(t->flags)){    for(sz=l2zm(0L);!zmleq(t->size,sz)&&cl;sz=zmadd(sz,l2zm(1L)),cl=cl->next){      if(!cl->other){ierror(0);return;}      add_clist_refs(bv,t->next,cl->other);    }    return;  }  if(ISUNION(t->flags)){    add_clist_refs(bv,(*t->exact->sl)[0].styp,cl);    return;  }  if(ISSTRUCT(t->flags)){    struct Typ *st;    for(i=0;i<t->exact->count&&cl;i++){      if(!cl->other){ierror(0);return;}      st=(*t->exact->sl)[i].styp;      if(!(*t->exact->sl)[i].identifier) ierror(0);      if((*t->exact->sl)[i].identifier[0]){        add_clist_refs(bv,st,cl->other);        cl=cl->next;      }    }    return;  }  if(cl->tree&&(cl->tree->o.flags&VARADR)){    /* careful: variable might not have a valid index if it is not       used within the function optimized */    i=cl->tree->o.v->index;    if(i>=0&&i<vcount-rcount&&vilist[i]==cl->tree->o.v){      /*printf("add %s\n",vilist[i]->identifier);*/      BSET(bv,i);    }  }} /* copies points-to-info for one var to another */void copy_pt(bvtype **pt,int to,int from){  if(to<0||to>=vcount) ierror(0);  if(from<0||from>=vcount) ierror(0);  if(!pt[from]){    if(from>=vcount-rcount&&pt[from-(vcount-rcount)]){      /* if dref check, whether from only points to initialized const */      int i;bvtype *new;      for(i=0;i<vcount;i++){	if(BTST(pt[from-(vcount-rcount)],i)){	  struct Var *v=vilist[i];	  if(!is_const(v->vtyp)||!v->clist)	    break;	}      }      if(i==vcount){	/* yes, take the points-to-info from clist */	if(!pt[to]||to+vcount-rcount==from){	  new=mymalloc(vsize);	  ptsize+=vsize;	}else	  new=pt[to];	memset(new,0,vsize);	for(i=0;i<vcount;i++){	  if(BTST(pt[from-(vcount-rcount)],i))	    add_clist_refs(new,vilist[i]->vtyp,vilist[i]->clist);	}	if(to+vcount-rcount==from){	  ptsize-=vsize;	  free(pt[to]);	}	pt[to]=new;	return;      }    }    undef_pt(pt,to);  }else{    if(!pt[to]){      pt[to]=mymalloc(vsize);      ptsize+=vsize;    }    memcpy(pt[to],pt[from],vsize);  }} /* set var i points only to j in points-to-info */void set_pt(bvtype **pt,int i,int j){  if(i<0||i>=vcount) ierror(0);  if(j<0||j>=vcount) ierror(0);  if(!pt[i]){    pt[i]=mymalloc(vsize);    ptsize+=vsize;  }  memset(pt[i],0,vsize);  BSET(pt[i],j);} void print_single_pt(bvtype *pt){  int j;  if(pt){    for(j=0;j<vcount;j++){      if(BTST(pt,j))	printf("  %s<%s>(%p)\n",(j>=vcount-rcount)?"*":"",vilist[j]->identifier,(void*)vilist[j]);    }  }else{    printf("  (undefined)\n");  }} void print_pt(bvtype **pt){  int i,j;  if(!pt) return;  printf("points-to:\n");  for(i=0;i<vcount;i++){    printf("%s<%s>(%p):\n",(i>=vcount-rcount)?"*":"",vilist[i]->identifier,(void*)vilist[i]);    print_single_pt(pt[i]);  }} /* creates new points-to-info; every var set to undefined */bvtype **new_pt(void){  bvtype **pt;  int i;  pt=mymalloc(vcount*sizeof(*pt));  ptsize+=vcount*sizeof(*pt);  for(i=0;i<vcount;i++){    if(i<rcount&&(vilist[i]->vtyp->flags&RESTRICT)){      pt[i]=mymalloc(vsize);      ptsize+=vsize;      memset(pt[i],0,vsize);      BSET(pt[i],i+vcount-rcount);    }else      pt[i]=0;  }  return pt;} void free_pt(bvtype **pt){  int i;  if(pt){    for(i=0;i<vcount;i++){      if(pt[i]) ptsize-=vsize;      free(pt[i]);    }    ptsize-=vcount*sizeof(*pt);    free(pt);  }} /* set points-to-info of *v to union of points-to of all vars in the   points-to-info of v */void dref_pt(bvtype **pt,int i){  int j,d;  if(i<0||i>=rcount) ierror(0);  d=i+vcount-rcount;  if(!pt[i]){    undef_pt(pt,d);    return;  }  if(!pt[d]){    pt[d]=mymalloc(vsize);    ptsize+=vsize;  }  memset(pt[d],0,vsize);  for(j=0;j<vcount;j++){    if(BTST(pt[i],j)){      struct Var *v=vilist[j];      if(v->clist&&is_const(v->vtyp)){	add_clist_refs(pt[d],v->vtyp,v->clist);      }else if(!pt[j]){	undef_pt(pt,d);	return;      }else	bvunite(pt[d],pt[j],vsize);    }  }} void trans_pt(bvtype **pt,struct IC *p){  int i,j,newset=-1,sv,cp;  if((p->code==ADDI2P||p->code==SUBIFP)&&!compare_objs(&p->q1,&p->z,ztyp(p)))    return;  if((p->z.flags&VAR)&&ISSCALAR(p->z.v->vtyp->flags)){    i=p->z.v->index;    if(i<0||i>=vcount) ierror(0);    if(p->z.flags&DREFOBJ){      if(i>=rcount) ierror(0);      i+=vcount-rcount;    }    if(!is_restrict(i)){      if(p->code==ASSIGN){	newset=i;sv=-1;cp=-1;	if(p->q1.flags&VARADR){	  sv=p->q1.v->index;	  set_pt(pt,i,p->q1.v->index);	}else if(p->q1.flags&VAR){	  j=p->q1.v->index;	  if(j<0||j>=vcount) ierror(0);	  if(p->q1.flags&DREFOBJ){	    if(j>=rcount) ierror(0);	    j+=vcount-rcount;	  }	  cp=j;	  copy_pt(pt,i,j);	}else{	  if(!pt[i]){	    pt[i]=mymalloc(vsize);	    ptsize+=vsize;	  }	  memset(pt[i],0,vsize);	}      }        if(p->code==ADDRESS){	newset=i;sv=p->q1.v->index;cp=-1;	set_pt(pt,i,p->q1.v->index);      }      if((p->code==ADDI2P||p->code==SUBIFP)&&(p->q1.flags&VAR)){	newset=i;sv=-1;cp=-1;	if(p->q1.flags&VARADR){	  sv=p->q1.v->index;	  set_pt(pt,i,p->q1.v->index);	}else{	  j=p->q1.v->index;	  if(j<0||j>=vcount) ierror(0);	  if(p->q1.flags&DREFOBJ){	    if(j>=rcount) ierror(0);	    j+=vcount-rcount;	  }	  cp=j;	  copy_pt(pt,i,j);	}      }    }  }  if(newset>=0&&newset<rcount){    if(newset<0) ierror(0);    dref_pt(pt,newset);  }  for(i=0;i<p->change_cnt;i++){    j=p->change_list[i].v->index;    if(j<0||j>=vcount) ierror(0);    if(p->change_list[i].flags&DREFOBJ){      if(j>=rcount) ierror(0);      j+=vcount-rcount;    }    if(j!=newset&&!is_restrict(j)){      if(newset>=0&&pt[j]){	if(sv>=0){	  if(sv>=vcount) ierror(0);	  BSET(pt[j],sv);	}	if(cp>=0&&pt[cp]){	  if(cp<0||cp>=vcount) ierror(0);	  bvunite(pt[j],pt[cp],vsize);	}      }else	undef_pt(pt,j);    }  }} bvtype **clone_pt(bvtype **pt){  int i;  bvtype **new;  if(!pt)    return new_pt();  new=mymalloc(vcount*sizeof(*new));  ptsize+=vcount*sizeof(*new);  for(i=0;i<vcount;i++){    if(pt[i]){      new[i]=mymalloc(vsize);      ptsize+=vsize;      memcpy(new[i],pt[i],vsize);    }else      new[i]=0;  }  return new;} /* tests if two points-to-infos are identical */int equal_pt(bvtype **pt1,bvtype **pt2){  int i;  if(!pt1&&!pt2)     return 1;  if(!pt1||!pt2)    return 0;  for(i=0;i<vcount;i++){    if(!pt1[i]&&!pt2[i])      continue;    if(!pt1[i]||!pt2[i])      return 0;    if(memcmp(pt1[i],pt2[i],vsize))      return 0;  }  return 1;}#if 0void calc_pt(struct flowgraph *fg){  struct flowgraph *g;  struct flowlist *in;  struct IC *p;  bvtype **pt,**ppt;  int i,all_preds,changed;   changed=1;  while(changed){    if(DEBUG&1024) printf("calc_pt pass\n");    changed=0;    for(g=fg;g;g=g->normalout){      /* do all predecessors already have points-to-info? */      all_preds=1;      for(in=g->in;in;in=in->next){	if(!in->graph->pt){	  all_preds=0;	  break;	}      }      if(all_preds&&g->in){	/* calc union of all predecessors */	pt=clone_pt(g->in->graph->pt);	for(in=g->in->next;in;in=in->next){	  ppt=in->graph->pt;	  for(i=0;i<vcount;i++){	    if(pt[i]){	      if(!ppt[i])		undef_pt(pt,i);	      else		bvunite(pt[i],ppt[i],vsize);	    }	  }	}      }else	pt=new_pt();      for(p=g->start;p;p=p->next){	trans_pt(pt,p);	if(p==g->end)	  break;      }      if(pt==g->pt) ierror(0);      if(!changed){	if(!equal_pt(pt,g->pt)){	  changed=1;	  free_pt(g->pt);	  g->pt=pt;	}else{	  free_pt(pt);	}      }else{	free_pt(g->pt);	g->pt=pt;      }    }  }}#endifint p_typ(struct Var *v)/*  Liefert den Typ, auf den Variable zeigen kann. Falls nicht eindeutig    *//*  wird CHAR zurueckgegeben, da ein char * auf alles zeigen kann.          */{    struct Typ *t=v->vtyp;int f;    /*  Kein Zeiger? Dann moeglicherweise Struktur, die verschiedene Zeiger */    /*  enthalten koennte. Koennte man evtl. noch genauer pruefen.          */    if(!ISPOINTER(t->flags)||!t->next||(v->flags&DNOTTYPESAFE)) return CHAR;    f=t->next->flags&NQ;    if(f==VOID) f=CHAR;    return f;} /* propagates information if a variable whose address may have been taken   is modified */static void propagate_pointers(bvtype *set,struct Var *v,int t,int i){  int j,t2;  if(v->nesting==0||v->storage_class==EXTERN||(v->flags&USEDASADR)){    if(noaliasopt){      bvunite(set,av_drefs,vsize);    }else{      for(j=0;j<rcount;j++){	t2=p_typ(vilist[j]);	if(t==t2||t2==CHAR||!ISSCALAR(t)||!ISSCALAR(t2)){	  if(!gpt||!gpt[j]||(i>=0&&BTST(gpt[j],i)))	    BSET(set,j+vcount-rcount);	}	          }    }  }}void alias_propagate(bvtype *set,int i,int t,int wr){  int j,t2;  struct Var *v;  if(i<0||i>=vcount) ierror(0);  t&=NQ;  BSET(set,i);  if(wr&&i<rcount) BSET(set,i+vcount-rcount);  if(i>=vcount-rcount){    /* DREFOBJ */    if(noaliasopt||t==CHAR||!ISSCALAR(t)){      bvunite(set,av_drefs,vsize);      bvunite(set,av_address,vsize);      bvunite(set,av_globals,vsize);    }else{      for(j=0;j<vcount-rcount;j++){	v=vilist[j];	if(!gpt||!gpt[i-(vcount-rcount)]||BTST(gpt[i-(vcount-rcount)],j)){	  v=vilist[j];	  if(!v) ierror(0);	  if(v->nesting==0||v->storage_class==EXTERN||(v->flags&USEDASADR)){	    struct Typ *tp=v->vtyp;	    if(!v->vtyp) ierror(0);	    do{	      t2=tp->flags&NQ;	      tp=tp->next;	    }while(ISARRAY(t2));	    if(t==t2||!ISSCALAR(t2)){	      BSET(set,j);	      if(wr&&j<rcount) {BSET(set,j+vcount-rcount);continue;}	    }	  }	}	if(j<rcount){	  if(i<(vcount-rcount)) ierror(0);	  if(!gpt||	     (!gpt[i-(vcount-rcount)]&&!is_restrict(j))||	     (!gpt[j]&&!is_restrict(i-(vcount-rcount)))||	     (gpt[j]&&gpt[i-(vcount-rcount)]&&bvdointersect(gpt[i-(vcount-rcount)],gpt[j],vsize))){	    t2=p_typ(v);	    if(t==t2||t2==CHAR||!ISSCALAR(t2))	      BSET(set,j+vcount-rcount);	  }	}      }    }  }else{    v=vilist[i];    propagate_pointers(set,v,t,i);  }} void ic_changes(struct IC *p,bvtype *result)/*  Initialisiert den Bitvektor result mit allen Variablen, die durch das   *//*  IC p geaendert werden koennten.                                         */{    int i,j,t,t2;struct Var *v;    memset(result,0,vsize);    t=(ztyp(p)&NQ);    if(p->z.flags&VAR){        v=p->z.v;        i=v->index;        /*  Hilfsvariable, die waehrend diesem cse-Durchlauf eingefuehrt    */        /*  wurde.                                                          */        if(i<0) return;	if(i>=vcount) ierror(0);        if(p->z.flags&DREFOBJ){	  if(i>=rcount) ierror(0);	  alias_propagate(result,i+vcount-rcount,t,1);	}else{	  alias_propagate(result,i,t,1);	  if(i<rcount) BSET(result,i+vcount-rcount);	}

Lines 1–500 of 816.