changeset 46:b1c8ac8c308d

fix cascading struct retrun. Now it should be compatible with gcc calling sequence.
author kono
date Sat, 15 Feb 2003 17:54:30 +0900
parents b9266c88495c
children f6b5e4f1a962
files Idea mc-nop-386.c mc-parse.c test/tmp11.c test/tmp7.c
diffstat 5 files changed, 158 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- a/Idea	Thu Feb 13 22:14:21 2003 +0900
+++ b/Idea	Sat Feb 15 17:54:30 2003 +0900
@@ -1506,3 +1506,22 @@
         int number;
     }
 virtual/real は、どうする。
+
+Sat Feb 15 14:00:03 JST 2003
+
+fdecl_struct を構文的に引数が出現するときに行うと、int *f(int
+a) などで、* の評価が終る前に、int aが評価されしまう。*obj 
+のobj を評価し終らないとfのタイプが確定しない。int*f()[] み
+たいな場合があるから。(?) なので、gcc と、そろえるためには、
+arg の先頭で fdecl_struct を行う方法ではだめで、fdecl 中であ
+とから修正する方が良い。
+
+fix しようにも引数リストなんて、存在しないじゃん!
+
+varargs を実装するのはめんどくさかろう...
+
+rvalue(expr(),type) では、expr() のtypeをrvalueに引き渡せな
+い。でも、type を大域変数にすると、rvalueを異なるタイプで呼
+び出すときにtypeを変更する必要がある。このrvalueのtype の扱
+いは、かなりはまったことがあるので、rvalue(int e,int type)の
+方が良いことは確かなんだが... 
--- a/mc-nop-386.c	Thu Feb 13 22:14:21 2003 +0900
+++ b/mc-nop-386.c	Sat Feb 15 17:54:30 2003 +0900
@@ -913,22 +913,30 @@
     if (register_full()) {
 	/* this is wrong assumption */
 	save = 1;
-	for(lreg=0;lreg!=creg&&lreg!=dreg;lreg++);
+	for(lreg=0;lreg==creg||lreg==dreg;lreg++);
 	printf("\tpushl %s\n",register_name(lreg,0));
-	xreg = lreg;
+	xreg = lreg; regv[xreg]=0;
     } else {
 	save=0;
 	xreg = get_register();
     }
-    printf("\tmovl %%esp,%s\n",register_name(xreg,0));
+    if (save) 
+	printf("\tlea %d(%%esp),%s\n",size_of_int,register_name(xreg,0));
+    else
+	printf("\tmovl %%esp,%s\n",register_name(xreg,0));
     regv[xreg]=1;
     emit_copy(creg,xreg,length,0);
-    /* we have value in creg */
+    /* we have value in creg, it may be changed */
     if (save) {
-	printf("\tpopl %s\n",register_name(lreg,0));
+	if(creg==xreg) {
+	    creg = get_register();   /* creg is freed in emit_copy */
+	    printf("\tmovl %s,%s\n",register_name(xreg,0),register_name(creg,0));
+	    regv[creg]=1;
+	}
+	printf("\tpopl %s\n",register_name(xreg,0));
+	regv[xreg]=1;
     } else
 	free_register(xreg);
-    regv[xreg]=0;
     return length/size_of_int;
 }
 
--- a/mc-parse.c	Thu Feb 13 22:14:21 2003 +0900
+++ b/mc-parse.c	Sat Feb 15 17:54:30 2003 +0900
@@ -75,6 +75,7 @@
 static void reverse(int t1);
 int reverse0(int t1);
 static int rvalue(int e);
+static int rvalue_t(int e,int type);
 int scalar(int t);
 static int sdecl(int s);
 static int skipspc(void);
@@ -90,9 +91,11 @@
 static void local_define();
 static void local_undef();
 static int macro_eval(int macrop,char *body,int history);
-static char * append(int lists);
+static char * mappend(int lists);
 static NMTBL *free_nptr();
 static void replace_return_struct(int func,int left);
+static void fdecl_struct(int type);
+static int append3(int p,int a1,int a2);
 
 extern void display_ntable(NMTBL *n, char *s);
 extern void closing(void);
@@ -131,6 +134,7 @@
 extern void exit(int l);
 
 static int struct_return  = 0;
+static int arglist = 0;
 
 int
 main(int argc, char **argv)
@@ -572,26 +576,13 @@
     reg_var=0;
     n->dsp=0;
     smode = mode;
-    /* if(mode!=GDECL && mode!=ADECL) 
-	 error(DCERR);  */
     mode=ADECL;
-    args= 0;
+    args = 0;
+    arglist = 0;
     for(;;) {	
 	if(sym==IDENT && nptr->sc!=TYPE) {
 	    rplacad(n->ty,glist2(INT,cadr(n->ty)));
-	    if (stmode==REGISTER && reg_var < MAX_REGISTER_VAR) {
-		nptr->ty = INT;
-		nptr->sc = REGISTER;
-		if ((nptr->dsp = get_register_var())<0)
-		    error(-1);
-		use_register_var(nptr->dsp); /* it has now value in it */
-		reg_var++;
-	    } else {
-		nptr->ty = INT;
-		nptr->sc = LVAR;
-		nptr->dsp = args ;
-		args += size_of_int;
-	    }
+	    def(nptr);
 	    getsym();
 	    if(sym==RPAR) break;
 	} else {
@@ -739,6 +730,7 @@
 	nsc = TYPE;
 	break;
     case ADECL:
+	arglist = list2((int)n,arglist);
 	if (stmode==REGISTER && reg_var <MAX_REGISTER_VAR) {
 	    if (type!=CHAR && !scalar(type)) 
 		error(TYERR);
@@ -748,7 +740,7 @@
 		if ((n->dsp = get_register_var())<0) {
 		    error(-1);
 		} 
-		use_register_var(nptr->dsp); /* it has now value in it */
+		use_register_var(n->dsp); /* it has now value in it */
 	    } 
 	    return n;
 	}
@@ -988,9 +980,9 @@
     code_enter(n->nm);
     fnptr=n;
     disp = -args;
-    args = 0;
     reg_var=0;
     mode=ADECL;
+    args = 0;
     stmode=REGISTER;
     while (sym!=LC) { /* argument declaration !ANSI */
 	decl(); getsym();
@@ -1023,9 +1015,6 @@
 void
 fdecl(NMTBL *n)
 {
-    NMTBL str_ret;
-    int t;
-
     enter(n->nm);
     fnptr=n;
     retlabel=fwdlabel();
@@ -1035,28 +1024,12 @@
     reg_var=0;
     fcheck(n);
     mode=ADECL;
-    if (sym!=LC) args=0;
+    if (sym!=LC) { args=0; arglist = 0; }
     while (sym!=LC) { /* argument declaration !ANSI */
 	stmode=0;
 	decl(); getsym();
     }
-    t=car(fnptr->ty);
-    if (!scalar(t) && (car(t)==STRUCT||car(t)==UNION)) {
-	/* extra argument for struct return */
-	/* this extra dummy arguments are set at calling sequence */
-	str_ret.nm = "str_ret"; str_ret.sc = EMPTY;
-	str_ret.dsp = 0; str_ret.ty = 0;
-	type=list2(POINTER,t);
-	if ((t=size(t))==-1) error(TYERR);
-	else {
-	    def(&str_ret);
-	    struct_return = list3(list2(LVAR,str_ret.dsp),t,type);
-	}
-	/* type is no longer valid */
-    } else {
-	struct_return = 0;
-    }
-    args=0;
+    fdecl_struct(fnptr->ty);
     disp=0;
     init_vars=0;
     /* local variable declaration */
@@ -1078,6 +1051,44 @@
     control=0;
 }
 
+static NMTBL str_ret;
+
+void
+fdecl_struct(int fntype)
+{
+    int type_save,mode_save,t,sz;
+    NMTBL *n;
+
+    t = car(fntype);
+    if (!scalar(t) && (car(t)==STRUCT||car(t)==UNION)) {
+	mode_save = mode;
+	mode=ADECL;
+	type_save = type;
+	/* extra argument for struct return */
+	/* this extra dummy arguments are set at calling sequence */
+	str_ret.nm = "str_ret"; str_ret.sc = EMPTY;
+	str_ret.dsp = 0; str_ret.ty = 0;
+	type=list2(POINTER,t);
+	/* fix all arguments's offset */
+	sz = size(type);
+	for(t=arglist;t;t=cadr(t)) {
+	    n=(NMTBL *)car(t);
+	    n->dsp += sz;
+	}
+	arglist = reverse0(arglist);
+	if ((t=size(car(fntype)))==-1) error(TYERR);
+	else {
+	    args = 0;
+	    def(&str_ret);
+	    struct_return = list3(list2(LVAR,str_ret.dsp),t,type);
+	}
+	type = type_save;
+	mode = mode_save;
+    } else {
+	struct_return = 0;
+    }
+}
+
 void
 fcheck(NMTBL *n)
 {
@@ -1413,10 +1424,16 @@
 	e = expr();
 	if ((car(type)==STRUCT || car(type)==UNION)&&
 		size(type)==cadr(struct_return)) {
-	    e = rvalue(e);
-	    type = caddr(struct_return);
-	    e1 = rvalue(cadr(struct_return));
-	    gexpr(list4(SASS,rvalue(car(struct_return)),e,e1));
+	    if(car(e)==RSTRUCT && car(cadr(e))==FUNCTION) {
+		replace_return_struct(cadr(e),
+		    rvalue_t(car(struct_return),caddr(struct_return)));
+		gexpr(cadr(e));
+	    } else {
+		e = rvalue(e);
+		type = caddr(struct_return);
+		e1 = rvalue_t(cadr(struct_return),INT); /* size */
+		gexpr(list4(SASS,rvalue(car(struct_return)),e,e1));
+	    }
 	} else {
 	    error(TYERR); /* should check compatible */
 	}
@@ -1431,8 +1448,9 @@
 
 void
 replace_return_struct(int func,int left) {
-    int e = caddr(func); /* arg lists */
-    e = car(e);          /* return_struct arg */
+    int e = caddr(func);      /* arg lists */
+    while(cadr(e)) e=cadr(e); /* find first arg */
+    e = car(e);               /* return_struct arg */
     rplacad(e,left);
 }
 
@@ -1527,6 +1545,7 @@
 	if(t==CHAR) {
 	    type= INT;return(list3(CASS,e1,e2));
 	} else if(!scalar(t)&&(car(t)==STRUCT||car(t)==UNION)) {
+	    if (size(t)!=size(type)) error(TYERR);
 	    type= t;
 	    if(car(e2)==RSTRUCT && car(cadr(e2))==FUNCTION) {
 		replace_return_struct(cadr(e2),e1);
@@ -2003,6 +2022,16 @@
     }
 }
 
+int
+rvalue_t(int e,int t)
+{
+    int stype = type;
+    type = t;
+    e = rvalue(e);
+    type = stype;
+    return e;
+}
+
 void
 lcheck(int e)
 {
@@ -2213,7 +2242,7 @@
 	/* this is recognized by called function declaration */
 	/* but I don't know this sequece is compatible with gcc */
 
-	arglist=list3(list2(ADDRESS,e),arglist,list2(POINTER,type));
+	append3(arglist,list2(ADDRESS,e),list2(POINTER,type));
     }
     return list3(FUNCTION,e1,arglist);
 }
@@ -2334,7 +2363,7 @@
 		macrop=macro_eval(macrop,(char *)car(nptrm->dsp),0);
 	    }
 	    macropp = macro_buf;
-	    append(reverse0(macrop));
+	    mappend(reverse0(macrop));
 	    macropp[-1] ='\n';
 	    *macropp =0;
 	    lfree = slfree;
@@ -3002,7 +3031,7 @@
     }
     evalues = reverse0(evalues);
     while(args) {
-	local_define((char *)car(args),append(reverse0(car(evalues))));
+	local_define((char *)car(args),mappend(reverse0(car(evalues))));
 /* fprintf(stderr,"%s: %s => %s\n",nptr->nm,(char *)car(args),(char *)car(msearch0((char *)car(args))->dsp)); */
 	args = cadr(args);
 	evalues = cadr(evalues);
@@ -3175,8 +3204,19 @@
     return e;
 }
 
+int
+append3(int p,int a1,int a2)
+{
+    int p1;
+    if(!p) return list3(a1,0,a2);
+    p1=p;
+    while(cadr(p)) p = cadr(p);
+    rplacad(p,list3(a1,0,a2));
+    return p1;
+}
+
 char *
-append(int lists)
+mappend(int lists)
 {
     char *p;
     char *result = macropp;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tmp11.c	Sat Feb 15 17:54:30 2003 +0900
@@ -0,0 +1,34 @@
+typedef struct nametable {
+        char *nm;
+        int sc,ty,dsp; } NMTBL;
+NMTBL *a;
+
+NMTBL *
+test2(char *n) {
+    printf("s %s\n",n);
+    return a;
+}
+
+int
+test0(int a,int b,int c) {
+    printf("a %d b %d c %d\n",a,b,c);
+    return 4;
+}
+
+int
+test1(a,b,c) 
+int a,b;int c;
+{
+    return test0(a,b,c);
+}
+
+int
+main()
+{
+    int d;
+    NMTBL *b;
+    b = test2("test");
+    d = test1(1,2,3);
+    printf("return %d\n",d);
+    return d;
+}
--- a/test/tmp7.c	Thu Feb 13 22:14:21 2003 +0900
+++ b/test/tmp7.c	Sat Feb 15 17:54:30 2003 +0900
@@ -79,7 +79,7 @@
     j = main3(bbb).a[55];
     printf("main3     bbb.a[55] in temporal copy %d==2 %d\n",j,bbb.a[53]); 
     j = main3(bbb).a[53];
-    printf("main3     bbb.a[55] in temporal copy %d==2 %d\n",j,bbb.a[53]); 
+    printf("main3     bbb.a[55] in temporal copy %d==53 %d\n",j,bbb.a[53]); 
 
     printf("%d==3\n",q.b);
 /* 3==3 */