changeset 258:22949117768f

Complex function argments. Struct is done. Long long is odd.
author kono
date Sat, 15 May 2004 20:07:24 +0900
parents e2f5671c413d
children 18837238e306
files Changes mc-code-ia32.c mc-code-powerpc.c mc-codegen.c mc-parse.c test/tmp7.c
diffstat 6 files changed, 236 insertions(+), 110 deletions(-) [+]
line wrap: on
line diff
--- a/Changes	Sat May 15 12:05:17 2004 +0900
+++ b/Changes	Sat May 15 20:07:24 2004 +0900
@@ -4209,3 +4209,19 @@
 
 でも、やっぱり、意外に複雑だよ。struct をどうするかとかさ。
 
+struct は、call memmove するんだけど、そいつを先にやるわけには
+いかない。先にやると、その間のfunction callが壊してしまう。
+後に持って良くと、input register が壊れるので、やっぱり、
+特別扱いする必要がある。ってことは...
+    complex function argument
+    struct copy
+    simple arguments
+っていう順番でやれば良いってことか.... うーん。
+
+(うーん、でもなぁ。やるの?)
+
+function argument の計算で、long long register が破壊されるのは、
+なんか方法が悪いんじゃないの? 本来、lreg は値渡しできるべきだよね。
+まぁねぇ。
+
+
--- a/mc-code-ia32.c	Sat May 15 12:05:17 2004 +0900
+++ b/mc-code-ia32.c	Sat May 15 20:07:24 2004 +0900
@@ -971,30 +971,32 @@
 	    register_name(to,0));
 	break;
     default:
-	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,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;
-	}
+        if (length <0) {
+            if (length > -MAX_COPY_LEN) {
+                for(;length<=-4;length+=4,offset-=4)
+                    emit_copy(from,to,-4,offset-4,0,det);
+                for(;length<=-2;length+=2,offset-=2)
+                    emit_copy(from,to,-2,offset-2,0,det);
+                if(length<0)
+                    emit_copy(from,to,length,offset-1,0,det);
+                break;
+            }
+        } else if (length <=MAX_COPY_LEN) {
+            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;
+        }
+/*
 	if (det) {
-/*
    call bcopy
 	    g_expr(list3(FUNCTION,,);
 	    break;
+	}
  */
-	}
 	use_register(from,REG_ESI,1);
 	use_register(to,  REG_EDI,1);
 	use_register(dreg,REG_ECX,0);
@@ -1004,14 +1006,14 @@
 	    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);
+		emit_copy(from,to,length,offset+length/SIZE_OF_INT,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);
+		emit_copy(from,to,length,offset+length/SIZE_OF_INT,0,det);
 	    }
 	}
     }
--- a/mc-code-powerpc.c	Sat May 15 12:05:17 2004 +0900
+++ b/mc-code-powerpc.c	Sat May 15 20:07:24 2004 +0900
@@ -127,6 +127,8 @@
     "f30","f31"
 }; 
 
+#define round4(i)   ((i+3)&~3)
+
 #define register_name(i)  reg_name[i]
 #define fregister_name(i) reg_name[i]
 #define lregister_name_low(i) reg_name[regv_l(i)]
@@ -1405,14 +1407,16 @@
 	printf("\tstw %s,%d(%s)\n",drn,offset,trn);
 	break;
     default:
-	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;
+	if (length <0) {
+	    if (length > -MAX_COPY_LEN) {
+		for(;length<=-4;length+=4,offset-=4)
+		    emit_copy(from,to,-4,offset-4,0,det);
+		for(;length<=-2;length+=2,offset-=2)
+		    emit_copy(from,to,-2,offset-2,0,det);
+		if(length<0)
+		    emit_copy(from,to,length,offset-1,0,det);
+		break;
+	    }
 	} else if (length <=MAX_COPY_LEN) {
 	    for(;length>=4;length-=4,offset+=4)
 		emit_copy(from,to,4,offset,0,det);
@@ -1466,22 +1470,20 @@
     if (length<MAX_COPY_LEN) {
 	sreg = get_register(); if (!sreg) error(-1);
 	srn = register_name(sreg);
-	code_lvar(cadr(arg),sreg);
-	for(count=0;length<MAX_COPY_LEN;count++,length-=SIZE_OF_INT) {
-	    if (length==0) {
-		free_register(sreg);
-		free_register(dreg);
-		return count;
-	    } else {
-		printf("\tlwz %s,%d(%s)\n",drn,length-SIZE_OF_INT,crn);
-		printf("\tstwu %s,%d(%s)\n",drn,-SIZE_OF_INT,srn);
-	    }
+	code_lvar(cadr(arg),dreg);
+	for(count=0;count<length;count+=SIZE_OF_INT) {
+	    printf("\tlwz %s,%d(%s)\n",srn,count,crn);
+	    printf("\tstwu %s,%d(%s)\n",srn,count,drn);
 	}
+	free_register(sreg);
+	free_register(dreg);
+	return length/SIZE_OF_INT;
+    } else {
+	code_lvar(cadr(arg),dreg);
+	/* downward direction copy */
+	emit_copy(creg,dreg,length,0,0,1);
     }
-    code_lvar(cadr(arg),dreg);
-    /* downward direction copy */
-    emit_copy(creg,dreg,length,0,0,1);
-    if (dreg) free_register(dreg);
+    free_register(dreg);
     return length/SIZE_OF_INT;
 }
 
@@ -1648,10 +1650,10 @@
 	e3==LDIV||e3==LUDIV||e3==LMOD||e3==LUMOD;
 }
 
-int
-simple_args(int e3)
+static int
+simple_arg(int e3)
 {
-    return !contains_in_list_p(e3,not_simple_p);
+    return !contains_p(e3,not_simple_p);
 }
 
 int
@@ -1697,6 +1699,89 @@
     if (mode) use_reg(reg);
 }
 
+static void
+compute_complex_arg(int e3,int reg_arg_list,int arg) {
+    int t=caddr(e3);
+    int e4 = car(e3);
+    reg_arg_list = list2(arg,reg_arg_list);
+    g_expr_u(assign_expr0(arg,e4,t,t));
+    if (car(arg)==REGISTER||car(arg)==DREGISTER||
+	car(arg)==FREGISTER||car(arg)==LREGISTER)
+	use_input_reg(cadr(arg),1);
+    car(e3) = arg;
+}
+
+static void
+increment_function_arg(int e3,int *pnargs,int *preg_arg,int *pfreg_arg) {
+    int nargs=0,reg_arg=0,freg_arg=0;
+    int t=caddr(e3);
+    if(scalar(t)) {
+	nargs ++ ; reg_arg++;
+    } else if (t==LONGLONG||t==ULONGLONG) {
+	nargs ++ ; reg_arg++;
+	nargs ++ ; reg_arg++;
+    } else if (t==DOUBLE||t==FLOAT) {
+	if (*preg_arg<MAX_INPUT_REGISTER_VAR) {
+	    reg_arg += 2;
+	}
+	freg_arg++;
+	nargs += size(t)/SIZE_OF_INT;
+    } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
+	nargs += round4(size(t))/SIZE_OF_INT;
+    } else {
+	error(TYERR);
+	nargs ++ ;
+    }
+    *pnargs += nargs;
+    *preg_arg += reg_arg;
+    *pfreg_arg += freg_arg;
+}
+
+#define AS_SAVE 1
+#define AS_ARG  0
+
+static int
+get_input_arg(int t,int mode,int nargs,int reg_arg,int freg_arg) 
+{
+    if(scalar(t)) {
+	if (mode==AS_SAVE) {
+	    return get_register_var(0);
+	} else if (reg_arg>=MAX_INPUT_REGISTER_VAR) {
+	    return list2(LVAR,caller_arg_offset_v(nargs));
+	} else 
+	    return get_input_register_var(reg_arg,0,0);
+    } else if (t==LONGLONG||t==ULONGLONG) {
+	if (mode==AS_SAVE) {
+	    return get_lregister_var(0);
+	} else if (reg_arg>=MAX_INPUT_REGISTER_VAR)  {
+	    return list2(LVAR,caller_arg_offset_v(nargs));
+	} else
+	    return get_input_lregister_var(reg_arg,0,0);
+    } else if (t==FLOAT) {
+	if (mode==AS_SAVE) {
+	    return get_dregister_var(0,0);
+	} else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) {
+	    return list2(LVAR,caller_arg_offset_v(nargs));
+	} else
+	    return get_input_dregister_var(freg_arg,0,0,0);
+    } else if (t==DOUBLE) {
+	if (mode==AS_SAVE) {
+	    return get_dregister_var(0,1);
+	} else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) {
+	    return list2(LVAR,caller_arg_offset_v(nargs));
+	} else
+	    return get_input_dregister_var(freg_arg,0,0,1);
+    } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
+	if (mode==AS_SAVE) {
+	    return get_register_var(0);
+	} else
+	    return list2(LVAR,caller_arg_offset_v(nargs));
+    } else {
+	error(-1);
+	return get_register_var(0);
+    }
+}
+
 int
 function(int e1)
 {
@@ -1707,6 +1792,9 @@
     NMTBL *fn = 0;
     int jmp = 0;
     char *jrn;
+    int complex_;
+    int pnargs,preg_arg,pfreg_arg;
+    int stargs;
 
     special_lvar = -1;
     ret_type = cadr(cadddr(e1));
@@ -1734,6 +1822,42 @@
 	code_register(creg,cadr(jmp));
         /* g_expr(assign_expr0(jmp,e2,INT,INT)); functions are lvalue */
     }
+    /* first we execute complex argument to avoid interaction with
+       input variables */
+    stargs = 0;
+    complex_ = 0;
+    nargs = reg_arg = freg_arg = arg_assign = 0;
+    for (e3 = e1 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) {	
+	t=caddr(e3);
+	if ((e5= !simple_arg(car(e3)))) {
+	    if (complex_) {
+		arg = get_input_arg(caddr(complex_),AS_SAVE,
+					pnargs,preg_arg,pfreg_arg);
+		compute_complex_arg(complex_,reg_arg_list,arg);
+	    }
+	    pnargs=nargs;preg_arg=reg_arg;pfreg_arg=freg_arg;
+	    complex_ = e3;
+	}
+	if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
+	    // The struct should be pushed after complex arguments.
+	    if (e5) { // compute address only, complex_ is me now. Clear it.
+		complex_ = 0;
+		e4 = car(e3);
+		if (car(e4)!=RSTRUCT) error(-1);
+		if (!simple_arg(cadr(e4))) {
+		    // Calculate complex struct address here.
+		    // If simple, leave it.
+		    arg = get_register_var(0);
+		    g_expr_u(assign_expr0(arg,list2(ADDRESS,car(e3)),INT,INT));
+		    car(e3)=arg;
+		    reg_arg_list = list2(arg,reg_arg_list);
+		    if (car(arg)==REGISTER) use_input_reg(cadr(arg),1);
+		}
+	    }
+	    stargs = list4(e3,stargs,nargs,reg_arg);
+	}
+	increment_function_arg(e3,&nargs,&reg_arg,&freg_arg);
+    }
 
     /* now all input register vars are free */
     code_save_stacks();
@@ -1741,71 +1865,48 @@
     set_freg(FREG_FREGISTER,0);
     set_ireg(CREG_REGISTER,0);
 
+    if (complex_) {
+	arg = get_input_arg(caddr(complex_),AS_ARG,pnargs,preg_arg,pfreg_arg);
+	compute_complex_arg(complex_,reg_arg_list,arg);
+    }
+    for(stargs=reverse0(stargs);stargs;stargs = cadr(stargs)) {
+	e3 = car(stargs);
+	e4 = car(e3);
+	t  = caddr(e3);
+	arg = get_input_arg(t,AS_ARG,caddr(stargs),cadddr(stargs),0);
+	struct_push(e4,t,arg);
+    }
+
     nargs = reg_arg = freg_arg = arg_assign = 0;
-    for (e3 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) {	
+    for (e3 = e1; e3; 
+		increment_function_arg(e3,&nargs,&reg_arg,&freg_arg),
+		e3 = cadr(e3)) {	
+	if (!(e4=car(e3))) continue;
 	t=caddr(e3);
-	e4 = car(e3);
+	arg = get_input_arg(t,AS_ARG,nargs,reg_arg,freg_arg);
 	if(scalar(t)) {
-	    if (reg_arg>=MAX_INPUT_REGISTER_VAR) { 
-		arg = list2(LVAR,caller_arg_offset_v(nargs));
-	    } else if (!simple_args(e3) && cadr(e3)) {
-		arg = get_register_var(0); 
-		arg_assign = list2(
-		    assign_expr0(get_input_register_var(reg_arg,0,0),
-			arg,t,t),
-		    arg_assign);
-	    } else {
-		arg = get_input_register_var(reg_arg,0,0); 
-	    }
 	    reg_arg_list = list2(arg,reg_arg_list);
 	    /* protect from input register free */
 	    if (car(arg)==REGISTER)
 		use_input_reg(cadr(arg),1);
 	    g_expr_u(assign_expr0(arg,e4,t,t));
-	    nargs ++ ; reg_arg++;
 	    continue;
 	} else if (t==LONGLONG||t==ULONGLONG) {
 	    if (reg_arg>=MAX_INPUT_REGISTER_VAR) { 
-		arg = list2(LVAR,caller_arg_offset_v(nargs));
 	    } else if (reg_arg+1>=MAX_INPUT_REGISTER_VAR) { 
 		// half register, half memory case
 		// put whole long long anyway
-		arg = list2(LVAR,caller_arg_offset_v(nargs));
 		arg_assign = list2(
 		    assign_expr0(r0=get_input_register_var(reg_arg,0,0),
 			arg,INT,INT),
 		    arg_assign);
 		use_input_reg(cadr(r0),1);
-	    } else if (!simple_args(e3) && cadr(e3)) {
-		arg = get_lregister_var(0); 
-		if (car(arg)==LREGISTER) {
-		    // r0=get_input_lregiste... is not preserved
-		    // we cannot mark r0 used, it consumes unused register
-		    // but get_input_register is preserved.
-		    arg_assign = list2(
-			assign_expr0(get_input_register_var(reg_arg,0,0),
-			    list2(REGISTER,regv_h(cadr(arg))),INT,INT), 
-			list2(
-			assign_expr0(get_input_register_var(reg_arg+1,0,0),
-			    list2(REGISTER,regv_l(cadr(arg))),INT,INT), 
-			arg_assign));
-		} else {
-		    arg_assign = list2(
-			assign_expr0(get_input_register_var(reg_arg,0,0),
-			    list2(LVAR,cadr(arg)+SIZE_OF_INT),INT,INT), 
-			list2(
-			assign_expr0(get_input_register_var(reg_arg+1,0,0),
-			    list2(LVAR,cadr(arg)),INT,INT), 
-			arg_assign));
-		}
 	    } else {
-		arg = get_input_lregister_var(reg_arg,0,0); 
-		use_input_reg(cadr(arg),1);
+		if (car(arg)==LREGISTER)
+		    use_input_reg(cadr(arg),1);
 	    }
 	    reg_arg_list = list2(arg,reg_arg_list);
 	    g_expr_u(assign_expr0(arg,e4,t,t));
-	    nargs ++ ; reg_arg++;
-	    nargs ++ ; reg_arg++;
 	    continue;
 	} else if (t==DOUBLE||t==FLOAT) {
 	    if (reg_arg<MAX_INPUT_REGISTER_VAR) {
@@ -1839,7 +1940,6 @@
 			    list2(LVAR,special_lvar+SIZE_OF_INT),
 			    INT,INT), arg_assign);
 		}
-		reg_arg += 2;
 	    }
 	    if (dots && freg_arg>=4 && freg_arg<MAX_INPUT_DREGISTER_VAR) { 
 		/* oh my god! 
@@ -1851,32 +1951,16 @@
 			    get_input_dregister_var(freg_arg,0,0,1),t,t),
 		    arg_assign);
 	    }
-	    if (freg_arg>=MAX_INPUT_DREGISTER_VAR) {
-		arg = list2(LVAR,caller_arg_offset_v(nargs));
-	    } else if (!simple_args(e3) && cadr(e3)) {
-		arg = get_dregister_var(0,1); 
-		arg_assign = list2(
-		    assign_expr0(get_input_dregister_var(freg_arg,0,0,1),
-			arg,t,t),
-		    arg_assign);
-	    } else {
-		arg = get_input_dregister_var(freg_arg,0,0,1); 
-	    }
 	    reg_arg_list = list2(arg,reg_arg_list);
 	    if (car(arg)==DREGISTER)
 		use_input_reg(cadr(arg),1); /* protect from input register free */
 	    g_expr_u(assign_expr0(arg,e4,t,t)); /* XXX */
-	    freg_arg++;
-	    nargs += size(t)/SIZE_OF_INT;
 	    continue;
 	} else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
-	    arg = list2(LVAR,caller_arg_offset_v(nargs));
-	    nargs += struct_push(e4,t,arg);
 	    continue;
 	} else {
 	    error(TYERR);
 	}
-	++nargs;
     }
     if (max_func_args<nargs) max_func_args=nargs;
     for(;arg_assign;arg_assign=cadr(arg_assign)) {
--- a/mc-codegen.c	Sat May 15 12:05:17 2004 +0900
+++ b/mc-codegen.c	Sat May 15 20:07:24 2004 +0900
@@ -1131,7 +1131,7 @@
 void
 sassign(int e1)
 {
-    int e2,e3,e4,sz,xreg,det;
+    int e2,e3,e4,sz,xreg,det,offset;
 
     /* structure assignment */
     e2 = cadr(e1);  /* pointer variable to the struct */
@@ -1146,12 +1146,12 @@
     /* しかし、わかる場合もある */
     if (car(e4)==RSTRUCT) e4=cadr(e4);
     if (is_same_type(e2,e4)) {
-	if(cadr(e2)<cadr(e4)) sz=-sz;
-	det=1;
+	if(cadr(e2)<cadr(e4)) { offset=sz; sz=-sz;}
+	det=1;  
     } else {
-	det = 0;
+	det = 0;  offset=0;
     }
-    emit_copy(xreg,USE_CREG,sz,0,1,det);
+    emit_copy(xreg,USE_CREG,sz,offset,1,det);
     emit_pop_free(xreg);
     return;
 }
--- a/mc-parse.c	Sat May 15 12:05:17 2004 +0900
+++ b/mc-parse.c	Sat May 15 20:07:24 2004 +0900
@@ -1022,6 +1022,9 @@
 		if (endian) n->dsp += size_of_int-size_of_short;
 	    }
 	    args += size_of_int;
+	} else if(type>0&&(type==UNION||type==STRUCT)) {
+	    n->dsp = args;
+	    args += ((sz+(size_of_int-1))&~size_of_int);
 	} else {
 	    /* if (n->dsp==0) (argument list in ADECL is useless, type
                list can be found in type ) */
--- a/test/tmp7.c	Sat May 15 12:05:17 2004 +0900
+++ b/test/tmp7.c	Sat May 15 20:07:24 2004 +0900
@@ -3,6 +3,7 @@
 int k=3;
 
 struct aa { int a[100]; } aaa,bbb;
+struct bb { int b[2]; } aaa1,bbb1;
 
 void tmp(void);
 
@@ -38,6 +39,19 @@
 	printf("main2 a1.a[55] %d\n",a1.a[55]);
 }
 
+struct bb
+main5(struct aa a1,struct bb a2)
+{
+	printf("main5 a1.a[99] %d\n",a1.a[99]);
+	printf("main5 a1.a[55] %d\n",a1.a[55]);
+	printf("main5 a2.b[0] %d\n",a2.b[0]);
+	printf("main5 a2.b[1] %d\n",a2.b[1]);
+	a2.b[0]=333;
+	a2.b[1]=555;
+	return a2;
+}
+
+
 void
 main1(struct aa a1)
 {
@@ -101,6 +115,13 @@
     p = p+i;
 /* 47 ./a.out */
     printf("%d %s\n",i,p-i+3);
+    aaa1.b[0]=33;
+    aaa1.b[1]=55;
+    bbb1 = main5(aaa,aaa1);
+    printf("main5-2 %d\n",
+	main5(bbb,bbb1).b[0]);
+    printf("main5-1 %d\n",
+	main5(bbb,main5(aaa,aaa1)).b[0]);
     return 0;
 }