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);