Mercurial > hg > CbC > old > device
changeset 57:3d7f199e99d0
struct handling
author | kono |
---|---|
date | Wed, 19 Feb 2003 17:19:55 +0900 |
parents | 5aa4528b6983 |
children | 727c280bdd25 |
files | Idea mc-nop-386.c test/arg.c |
diffstat | 3 files changed, 81 insertions(+), 23 deletions(-) [+] |
line wrap: on
line diff
--- a/Idea Wed Feb 19 12:15:05 2003 +0900 +++ b/Idea Wed Feb 19 17:19:55 2003 +0900 @@ -1610,3 +1610,12 @@ post processing する時にoverrapしてないという保証がない。 +Wed Feb 19 15:38:55 JST 2003 + +自分自身とのoverrrapを見てないので、 + struct a a,int i + int i,struct a a +みたいな時に自分自身を壊してしまう。なので、emit_copy +が、ちゃんと方向を見て壊さないように処理する必要がある。 + +call bcop でいいじゃん。まね。
--- a/mc-nop-386.c Wed Feb 19 12:15:05 2003 +0900 +++ b/mc-nop-386.c Wed Feb 19 17:19:55 2003 +0900 @@ -59,7 +59,7 @@ static void tosop(int op,int reg); static void edx_cleanup(); static void use_register(int virt, int real, int move); -static void emit_copy(int from,int to,int length,int offset,int value); +static void emit_copy(int from,int to,int length,int offset,int value,int det); static int is_same_type(int s,int t); extern int error(int n); @@ -677,9 +677,6 @@ use_register(creg,REG_EAX,1); fwddef(e3); return; - case RSTRUCT: - g_expr(e2); - return; case SASS: sassign(e1); return; @@ -689,6 +686,9 @@ case ASSOP: case CASSOP: assop(e1); return; + case RSTRUCT: + g_expr(e2); + return; case COMMA: g_expr(e2); g_expr(caddr(e1)); @@ -858,45 +858,64 @@ #define MAX_COPY_LEN 20 void -emit_copy(int from,int to,int length,int offset,int value) +emit_copy(int from,int to,int length,int offset,int value,int det) { int fix = 0; - if (length<=0) return; + /* length <0 means upward direction copy */ switch (length) { case 0: break; - case 1: + case 1: case -1: printf("\tmovb %d(%s),%s\n",offset,register_name(from,0), reg_name_l[rname[dreg]] ); printf("\tmovb %s,%d(%s)\n",reg_name_l[rname[dreg]] ,offset,register_name(to,0)); break; - case 2: + case 2: case -2: printf("\tmovw %d(%s),%s\n",offset,register_name(from,0), reg_name_w[rname[dreg]] ); printf("\tmovw %s,%d(%s)\n",reg_name_w[rname[dreg]] ,offset,register_name(to,0)); break; - case 4: + case 4: case -4: printf("\tmovl %d(%s),%s\n",offset,register_name(from,0), register_name(dreg,0)); printf("\tmovl %s,%d(%s)\n",register_name(dreg,0), offset,register_name(to,0)); break; default: - if (length <=MAX_COPY_LEN) { + if (-MAX_COPY_LEN<length && length <0) { + for(;length<=4;length+=4,offset-=4) + emit_copy(from,to,4,offset,0,det); + for(;length<=2;length+=2,offset-=2) + emit_copy(from,to,2,offset,0,det); + if(length>0) + emit_copy(from,to,length,offset,0,det); + break; + } else if (length <=MAX_COPY_LEN) { for(;length>=4;length-=4,offset+=4) - emit_copy(from,to,4,offset,0); + emit_copy(from,to,4,offset,0,det); for(;length>=2;length-=2,offset+=2) - emit_copy(from,to,2,offset,0); + emit_copy(from,to,2,offset,0,det); if(length>0) - emit_copy(from,to,length,offset,0); + emit_copy(from,to,length,offset,0,det); break; } use_register(from,REG_ESI,1); use_register(to, REG_EDI,1); use_register(dreg,REG_ECX,0); - printf("\tmovl $%d,%%ecx\n",length/4); - fix = (length/4)*4; - printf("\tcld\n\trep\n\tmovsl\n"); - if(length%4) { - emit_copy(from,to,length,offset+length/4,0); + if (length<0) { + printf("\tmovl $%d,%%ecx\n",-length/4); + printf("\taddl $%d,%%esi\n",-length); + printf("\taddl $%d,%%edi\n",-length); + printf("\tstd\n\trep\n\tmovsl\n"); + if(length%4) { + emit_copy(from,to,length,offset+length/4,0,det); + } + } else { + printf("\tmovl $%d,%%ecx\n",length/4); + fix = (length/4)*4; + printf("\tcld\n\trep\n\tmovsl\n"); + if(length%4) { + emit_copy(from,to,length,offset+length/4,0,det); + } } } if (value) { + /* creg must point top of the destination data */ /* this code is necessary for the value of assignment or function call */ /* otherwise we don't need this */ if (fix) printf("\tsubl $%d,%s\n",fix,register_name(to,0)); @@ -945,7 +964,8 @@ else printf("\tmovl %%esp,%s\n",register_name(xreg,0)); regv[xreg]=1; - emit_copy(creg,xreg,length,0,0); + /* downward direction copy */ + emit_copy(creg,xreg,length,0,0,1); /* we have value in creg, it may be changed */ if (save) { if(creg==xreg) { @@ -1038,7 +1058,7 @@ /* source (after) list2(tag,disp) */ /* source list list3(e,cdr,sz) */ -#define DEBUG_PARALLEL_ASSIGN 0 +#define DEBUG_PARALLEL_ASSIGN 1 int overrap(int t,int sz,int source) @@ -1188,7 +1208,7 @@ { return ( e1==CONST || e1==FNAME || e1==LVAR || e1==REGISTER || - e1==GVAR || RGVAR || RLVAR || CRLVAR || CRGVAR + e1==GVAR || e1==RGVAR || e1==RLVAR || e1==CRLVAR || e1==CRGVAR ); } @@ -1372,7 +1392,7 @@ void sassign(int e1) { - int e2,e3,e4,sz,xreg; + int e2,e3,e4,sz,xreg,det; /* structure assignment */ e2 = cadr(e1); /* pointer variable to the struct */ @@ -1383,7 +1403,16 @@ emit_push(); g_expr(e2); xreg = emit_pop(0); - emit_copy(xreg,creg,sz,0,1); + /* 一般的にはコピーのオーバラップの状況は実行時にしかわからない */ + /* しかし、わかる場合もある */ + if (car(e4)==RSTRUCT) e4=cadr(e4); + if (is_same_type(e2,e4)) { + if(cadr(e2)<cadr(e4)) sz=-sz; + det=1; + } else { + det = 0; + } + emit_copy(xreg,creg,sz,0,1,det); emit_pop_free(xreg); return; }
--- a/test/arg.c Wed Feb 19 12:15:05 2003 +0900 +++ b/test/arg.c Wed Feb 19 17:19:55 2003 +0900 @@ -31,6 +31,26 @@ } +code carg3(struct arg args0,struct arg args1,int i, int j,int k,int l) +{ + goto carg4(args0,args1,j,k,l,i); +} + +code carg4(struct arg args0,struct arg args1,int i, int j,int k,int l) +{ + goto carg5(args1,args0,j,k,l,i); +} + +code carg5(struct arg args0,struct arg args1,int i, int j,int k,int l) +{ + goto carg6(i,j,k,l,args0); +} + +code carg6(int i, int j,int k,int l,struct arg args0) +{ + goto carg3(args0,args0,i,j,k,l); +} + int main1(int n) { goto carg1(0,1,2,3,4,return,environment);