blob: f0a942e1727556eeea69f66bc384d4834774e9d5 [file] [log] [blame]
/* $VER: vbcc (alias.c) $Revision: 1.6 $ */
/* 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,type *t,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)){
type *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)){
Var *v=vilist[i];
if(!is_const(v->vtyp)||!v->clist||(v->storage_class!=STATIC&&v->storage_class!=EXTERN))
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)){
Var *v=vilist[j];
if(v->clist&&is_const(v->vtyp)&&(v->storage_class==STATIC||v->storage_class==EXTERN)){
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,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 0
void calc_pt(flowgraph *fg)
{
flowgraph *g;
flowlist *in;
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;
}
}
}
}
#endif
int p_typ(Var *v)
/* Liefert den Typ, auf den Variable zeigen kann. Falls nicht eindeutig */
/* wird CHAR zurueckgegeben, da ein char * auf alles zeigen kann. */
{
type *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,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;
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)){
type *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(IC *p,bvtype *result)
/* Initialisiert den Bitvektor result mit allen Variablen, die durch das */
/* IC p geaendert werden koennten. */
{
int i,j,t,t2;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);
}
}
if(p->code==CALL){
function_info *fi;
if((p->q1.flags&(VAR|DREFOBJ))==VAR&&(fi=p->q1.v->fi)&&(fi->flags&ALL_MODS)&&!(disable&65536)){
/* we can get the set from the function_info */
for(i=0;i<fi->change_cnt;i++){
if(v=fi->change_list[i].v){
if(v->inr==inr&&v->index>=0){
if(v->index>=vcount) ierror(0);
alias_propagate(result,v->index,v->vtyp->flags&NQ,1);
}else
propagate_pointers(result,v,v->vtyp->flags&NQ,-1);
}else{
for(j=0;j<vcount-rcount;j++){
v=vilist[j];
if(v->nesting==0||v->storage_class==EXTERN||(v->flags&USEDASADR)){
t=v->vtyp->flags&NQ;
if(t==(fi->change_list[i].flags&NQ)||!ISSCALAR(t)){
BSET(result,j);
if(j<rcount) BSET(result,j+vcount-rcount);
}
}
if(j<rcount){
t=p_typ(vilist[j]);
if(t==CHAR||!ISSCALAR(t)||t==fi->change_list[i].flags)
BSET(result,j+vcount-rcount);
}
}
}
}
}else{
bvunite(result,av_drefs,vsize);
bvunite(result,av_address,vsize);
bvunite(result,av_globals,vsize);
bvunite(result,av_statics,vsize);
}
}
if((p->z.flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
bvunite(result,av_drefs,vsize);
}
}
void ic_uses(IC *p,bvtype *result)
/* Initialisiert den Bitvektor result mit allen Variablen, die durch das */
/* IC p benutzt werden koennten. */
{
int i,j,t,t2,c;Var *v;type *tp;
memset(result,0,vsize);
c=p->code;
if(c!=ADDRESS){
if((p->q1.flags&(VAR|VARADR))==VAR&&c!=ADDRESS&&(c!=CALL||(p->q1.flags&DREFOBJ))){
v=p->q1.v;
i=v->index;
if(i<0||i>=vcount) ierror(0);
t=q1typ(p);
if(p->q1.flags&DREFOBJ){
if(i>=rcount) ierror(0);
alias_propagate(result,i+vcount-rcount,t,0);
}
alias_propagate(result,i,t,0);
}
if((p->q2.flags&(VAR|VARADR))==VAR){
v=p->q2.v;
i=v->index;
if(i<0||i>=vcount) ierror(0);
t=q2typ(p);
if(p->q2.flags&DREFOBJ){
if(i>=rcount) ierror(0);
alias_propagate(result,i+vcount-rcount,t,0);
}
alias_propagate(result,i,t,0);
}
}
if((p->z.flags&(VAR|VARADR|DREFOBJ))==(VAR|DREFOBJ)){
v=p->z.v;
i=v->index;
if(i>=vcount) {pric2(stdout,p);ierror(0);}
t=(ztyp(p)&NQ);
alias_propagate(result,i,t,0);
}
if(p->code==CALL){
function_info *fi;
if((p->q1.flags&(VAR|DREFOBJ))==VAR&&(fi=p->q1.v->fi)&&(fi->flags&ALL_USES)&&!(disable&65536)){
/* we can get the set from the function_info */
for(i=0;i<fi->use_cnt;i++){
if(v=fi->use_list[i].v){
if(v->inr==inr&&v->index>=0)
alias_propagate(result,v->index,v->vtyp->flags&NQ,0);
else
propagate_pointers(result,v,v->vtyp->flags&NQ,-1);
}else{
for(j=0;j<vcount-rcount;j++){
v=vilist[j];
if(v->nesting==0||v->storage_class==EXTERN||(v->flags&USEDASADR)){
t=v->vtyp->flags&NQ;
if(t==(fi->use_list[i].flags&NQ)||!ISSCALAR(t))
BSET(result,j);
}
if(j<rcount){
t=p_typ(vilist[j]);
if(t==CHAR||!ISSCALAR(t)||t==fi->use_list[i].flags)
BSET(result,j+vcount-rcount);
}
}
}
}
}else{
bvunite(result,av_drefs,vsize);
bvunite(result,av_address,vsize);
bvunite(result,av_globals,vsize);
bvunite(result,av_statics,vsize);
}
}
if((p->q1.flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
bvunite(result,av_drefs,vsize);
}
if((p->q2.flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
bvunite(result,av_drefs,vsize);
}
}
void free_alias(flowgraph *fg)
/* Gibt alle use/change-Listen der ICs im Flussgraphen frei. */
{
IC *p;flowgraph *g;
if(DEBUG&1024) printf("freeing alias info\n");
for(g=fg;g;g=g->normalout){
for(p=g->start;p;p=p->next){
if(p->code==LABEL&&(p->use_cnt>0||p->change_cnt>0)) ierror(0);
if(p->use_cnt>0) {free(p->use_list);p->use_cnt=0;}
if(p->change_cnt>0) {free(p->change_list);p->change_cnt=0;}
if(p==g->end) break;
}
}
have_alias=0;
}
void create_alias(flowgraph *fg)
/* Initialisiert jedes IC mit einer Liste aller Variablen, die dadurch */
/* benutzt und veraendert werden koennten. Z.Z. wird bis auf Typ-basierte */
/* Optimierungen der worst-case angenommen. */
{
bvtype *vars=mymalloc(vsize);
IC *p;flowgraph *g;
flowlist *in;
bvtype **ppt;
int i,cnt,all_preds,changed;
unsigned long heapsize;
if(DEBUG&1024) printf("creating alias info\n");
ptsize=0;
changed=1;
while(changed){
if(DEBUG&1024) printf("create_alias pass\n");
changed=0;
if(have_alias)
free_alias(fg);
heapsize=0;
for(g=fg;g;g=g->normalout){
if((optflags&1024)&&!noaliasopt){
/* 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 */
gpt=clone_pt(g->in->graph->pt);
for(in=g->in->next;in;in=in->next){
ppt=in->graph->pt;
if(!ppt)
continue;
for(i=0;i<vcount;i++){
if(gpt[i]){
if(!ppt[i])
undef_pt(gpt,i);
else
bvunite(gpt[i],ppt[i],vsize);
}
}
}
}else
gpt=new_pt();
}else{
gpt=0;
}
for(p=g->start;p;p=p->next){
int da; /* always consider a direct write, even if variable is const-qualified */
ic_uses(p,vars);
for(i=0,cnt=0;i<vcount;i++)
if(BTST(vars,i)) cnt++;
p->use_cnt=cnt;
if(cnt==0){
p->use_list=0;
}else{
p->use_list=mymalloc(cnt*VLS);
heapsize+=cnt*VLS;
for(cnt=0,i=0;i<vcount;i++){
if(BTST(vars,i)){
p->use_list[cnt].v=vilist[i];
if(i>=vcount-rcount) p->use_list[cnt].flags=DREFOBJ;
else p->use_list[cnt].flags=0;
cnt++;
}
}
}
ic_changes(p,vars);
if((p->z.flags&(VAR|DREFOBJ))==VAR)
da=p->z.v->index;
else
da=0;
for(i=0,cnt=0;i<vcount;i++)
if(BTST(vars,i)&&(i>=vcount-rcount||i==da||!is_const(vilist[i]->vtyp))) cnt++;
p->change_cnt=cnt;
if(cnt==0){
p->change_list=0;
}else{
p->change_list=mymalloc(cnt*VLS);
heapsize+=cnt*VLS;
for(cnt=0,i=0;i<vcount;i++){
if(BTST(vars,i)&&(i>=vcount-rcount||i==da||!is_const(vilist[i]->vtyp))){
p->change_list[cnt].v=vilist[i];
if(i>=vcount-rcount) p->change_list[cnt].flags=DREFOBJ;
else p->change_list[cnt].flags=0;
cnt++;
}
}
}
if(p->code==CALL){
if((p->q1.flags&(VAR|DREFOBJ))==(VAR|DREFOBJ)){
int i=p->q1.v->index;
if(i<0||i>=vcount) ierror(0);
if(gpt&&gpt[i]){
int j,cnt;
for(cnt=0,j=0;j<vcount-rcount;j++){
if(BTST(gpt[i],j)&&ISFUNC(vilist[j]->vtyp->flags))
cnt++;
}
if(cnt){
if(p->call_cnt) free(p->call_list);
p->call_cnt=cnt;
p->call_list=mymalloc(sizeof(*p->call_list)*cnt);
for(cnt=0,j=0;j<vcount-rcount;j++){
if(BTST(gpt[i],j)&&ISFUNC(vilist[j]->vtyp->flags)){
p->call_list[cnt].v=vilist[j];
p->call_list[cnt].flags=0;
cnt++;
}
}
if(cnt==1&&all_preds){
if(DEBUG&1024) {printf("replacing indirect call by single target:\n");pric2(stdout,p);}
p->q1.flags=VAR;
p->q1.val.vmax=l2zm(0L);
p->q1.v=p->call_list[0].v;
}
}
}
}
}
if((optflags&1024)&&!noaliasopt)
trans_pt(gpt,p);
if(p==g->end) break;
}
if((optflags&1024)&&!noaliasopt){
if(!changed){
if(!equal_pt(gpt,g->pt)){
changed=1;
free_pt(g->pt);
g->pt=gpt;
}else{
free_pt(gpt);
}
}else{
free_pt(g->pt);
g->pt=gpt;
}
}
}
if(DEBUG&16384) printf("create_alias heapsize=%lu\n",heapsize);
have_alias=1;
}
if(DEBUG&16384) printf("points-to heapsize=%lu\n",ptsize);
if((optflags&1024)&&!noaliasopt){
for(g=fg;g;g=g->normalout){
free_pt(g->pt);
g->pt=0;
}
}
free(vars);
}
#if 1
void update_alias(Var *old,Var *new)
/* Aendert alle use/changes von (old) auf (new). Wird aufgerufen, wenn */
/* copy-propagation eine Variable neu zu einem DREFOBJ macht. */
{
IC *p;int i;
if(DEBUG&1024) printf("update-alias\n");
for(p=first_ic;p;p=p->next){
for(i=0;i<p->use_cnt;i++){
if(p->use_list[i].v==old&&(p->use_list[i].flags&DREFOBJ)){
p->use_cnt++;
p->use_list=myrealloc(p->use_list,p->use_cnt*VLS);
p->use_list[p->use_cnt-1].v=new;
p->use_list[p->use_cnt-1].flags=DREFOBJ;
break;
}
}
for(i=0;i<p->change_cnt;i++){
if(p->change_list[i].v==new||(p->change_list[i].v==old&&(p->change_list[i].flags&DREFOBJ))){
p->change_cnt++;
p->change_list=myrealloc(p->change_list,p->change_cnt*VLS);
p->change_list[p->change_cnt-1].v=new;
p->change_list[p->change_cnt-1].flags=DREFOBJ;
break;
}
}
}
}
#endif