changeset 128:d497c39add36 args-works

arg.c works (?)
author kono
date Thu, 03 Apr 2003 03:04:16 +0900
parents eb4d8975926c
children 948977254fa6
files Changes mc-code-ia32.c mc-code-powerpc.c mc-codegen.c mc-parse.c
diffstat 5 files changed, 115 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/Changes	Tue Apr 01 10:31:40 2003 +0900
+++ b/Changes	Thu Apr 03 03:04:16 2003 +0900
@@ -2674,7 +2674,7 @@
 に入っている。だよね。
 
                  * gotoを呼び出した関数のr1 ! r1(goto前のr1)
-   #             *          r30 <---------------r1_offset---------------> r1
+   #             *                           r30<--r1_offset-------------> r1
 r+ +----------+--+----------+----------------+-----------+----------+----+
     cousin arg xx  reg save !callee arg      !code local  caller arg  xx
                    r20-r29     lvar>0         lvar<0      lvar>0x1000 000
@@ -2688,3 +2688,36 @@
 
 それで、code segment から関数呼出しするときは? (ってことは、
 それようのテストも必要なわけか...)
+
+Wed Apr  2 17:40:32 JST 2003
+
+register 変数が既に使われていても、わざわざsaveする必要はない。
+戻って来ないから。register を使ったことにするには、used_max_register_var
+を設定してやれば良い。
+
+Interl版で goto が動かなくなったのは、arg_offset が、register 変数分
+も取るようになったから。save することを考えると、その方が良い。実際、
+function call があるとsaveされてしまう。ということは、別に r20-r29
+である必要はないってことか。通常のinput register varで良い。とすると、
+register変数をsaveする必要もないね。
+ただ、input regsiter var は、function callの前には saveする必要が
+ある。でも、これは、やっぱり手遅れか。ってことは、やっぱり、
+r20-r29が良いってことか。
+
+jump() では、呼出し引数は、-arg_size つまり、局所変数と
+同じ扱いになっている。ってことは、
+
+                 * gotoを呼び出した関数のr1 ! r1(goto前のr1)
+   #             *                           r30<----r1_offset---------> r1
+r+ +----------+--+----------+----------------+-----------+----------+----+
+    cousin arg xx  reg save !callee arg      !code local  caller arg  xx
+                   r20-r29     lvar >0        lvar<0      lvar>0x1000 000
+                   f20-f31  <-my_func_args--><--disp-----><-max_func_arg->
+                              *size_of_int                  *size_of_int
+
+                  r1 <----------------------r30 (return continuation)
+
+で、callee arg は保存されたまま、code local だけ変わるってことだね。
+
+return continuation で、構造体を返そうと思うと難しい。そもそも、
+浮動小数点が、ちゃんと返るのか?
--- a/mc-code-ia32.c	Tue Apr 01 10:31:40 2003 +0900
+++ b/mc-code-ia32.c	Thu Apr 03 03:04:16 2003 +0900
@@ -35,13 +35,13 @@
 int MAX_CODE_INPUT_DREGISTER_VAR = 0;
 
 /*
-                                           -16  -8 local2
-                                           -12  -4 local1
-                                            -8  8  arg3
-                                            -4  4  arg2
-                                             0  0  arg1
-         local2     -20 4                    0    (%edi)
-         local1 <-- -16 0 local variable     0    (%esi)
+                                           -28  -8 local2
+                                           -24  -4 local1
+                                           -20  8  arg3
+                                           -16  4  arg2
+                                           -12  0  arg1
+         local2     -20 4                   -8    (%edi)
+         local1 <-- -16 0 local variable    -4    (%esi)
         %edi        -12  <- disp_offset          %ebp
         %esi         -8
         %ebx         -4
@@ -1392,20 +1392,31 @@
 void
 leave(int control, char *name)
 {
+    int sz;
+
+    disp &= -size_of_int;
     if (control)
         code_set_return_register(1);
     if (retcont) {
 	if (control)
 	    jmp(retlabel);
 	fwddef(retcont);
-	use_register(creg,REG_EAX,0);
-	printf("\tmovl %s,%s\n",reg_name[REG_ESI],register_name(creg,0));
-	/* printf("\tleave\n"); */
+        if (cadr(fnptr->ty)==FLOAT||cadr(fnptr->ty)==DOUBLE) {
+	    printf("\tfldl %d(%%ebp)\n",-size_of_double);
+        } else if (cadr(fnptr->ty)>0&&(
+            car(cadr(fnptr->ty))==STRUCT ||
+            car(cadr(fnptr->ty))==UNION)) {
+            sz = size(cadr(fnptr->ty));
+            printf("\tlea %d(%%ebp),%s\n",-sz,register_name(dreg,0));
+            printf("\tmovl %d(%%ebp),%s\n",disp-size_of_int,
+		register_name(creg,0));
+            emit_copy(dreg,creg,sz,0,1,1);
+        } else if (cadr(fnptr->ty)!=VOID) {
+	    use_register(creg,REG_EAX,0);
+	    printf("\tmovl %s,%s\n",reg_name[REG_ESI],register_name(creg,0));
+        }
     }
     fwddef(retlabel);
-    /* use_register(creg,REG_EAX,0); too late */
-    /* if(disp) printf("\taddl $%d,%%esp\n",-disp);  */
-    disp &= -size_of_int;
 
     printf("\tlea %d(%%ebp),%%esp\n",disp_offset);
     printf("\tpopl %%edi\n");
--- a/mc-code-powerpc.c	Tue Apr 01 10:31:40 2003 +0900
+++ b/mc-code-powerpc.c	Thu Apr 03 03:04:16 2003 +0900
@@ -140,7 +140,7 @@
 code segment stack frame
 
                  * gotoを呼び出した関数のr1 ! r1(goto前のr1)
-   #             *          r30 <---------------r1_offset---------------> r1
+   #             *                           r30 <---r1_offset---------> r1
 r+ +----------+--+----------+----------------+-----------+----------+----+
     cousin arg xx  reg save !callee arg      !code local  caller arg  xx
                    r20-r29     lvar>0         lvar<0      lvar>0x1000 000
@@ -920,14 +920,20 @@
     printf("\tla %s,lo16(L_%d-L_%d)(%s)\n",crn,retcont,code_base,crn);
 }
 
+#define R1SAVE 1
 
 void
 code_environment(int creg) {
     /* save frame pointer */
-    printf("\tmr %s,r30\n",register_name(creg));
+#if R1SAVE
+    printf("\tlwz %s,0(r1)\n",register_name(creg));
+#else
+    int l = 0;
+    printf("\tla %s,",register_name(creg));
+    printf("lo16(%d+L_%d)(r30)\n",FUNC_LVAR,lvar_offset_label);
+#endif
 }
 
-
 void
 code_bool(int e1) {
     char *xrn;
@@ -1449,23 +1455,33 @@
 
 void
 code_frame_pointer(int e3) {
+#if R1SAVE
+    printf("\tmr r1,%s\n",register_name(e3));
+#else
     printf("\tmr r30,%s\n",register_name(e3));
+#endif
 }
 
 
 void
 code_fix_frame_pointer(int disp_offset) {
-    printf("\tla r1,%d(r30)\n",disp_offset);
+    int l = 0;
+    printf("\tla r30,");
+    printf("lo16(%d+L_%d)(r30)\n",FUNC_LVAR,lvar_offset_label);
 }
 
 void
 code_jmp(char *s) {
+    max_reg_var = REG_VAR_BASE-REG_VAR_MIN;
+    max_freg_var = FREG_VAR_BASE-FREG_VAR_MIN;
     printf("\tb L_%s$stub\n",s);
 }
 
 
 void
 code_indirect_jmp(int e2) {
+    max_reg_var = REG_VAR_BASE-REG_VAR_MIN;
+    max_freg_var = FREG_VAR_BASE-FREG_VAR_MIN;
     printf("\tmtctr %s\n",register_name(e2));
     printf("\tbctr\n");
 }
@@ -1755,7 +1771,7 @@
 #endif
     printf("_%s:\n",name);
     code_disp_label=fwdlabel();
-    printf("\tstwu r1,lo16(L_%d)(r30)\n",code_disp_label);
+    printf("\tla r1,lo16(L_%d)(r30)\n",code_disp_label);
     printf("\tbcl 20,31,L_%d\n",code_base = fwdlabel());
     fwddef(code_base);
     printf("\tmflr r31\n");
@@ -1766,7 +1782,6 @@
 void
 code_enter1(int args)
 {
-    printf("## args %d disp %d code_arg_offset=%d code_disp_offset=%d\n",args,disp,code_arg_offset,code_disp_offset); 
     set_creg(CREG_REGISTER,0);
     set_freg(FREG_FREGISTER,0);
 }
@@ -1774,10 +1789,12 @@
 void
 code_leave(char *name)
 {
+    int r1_offsetv;
     disp&= -size_of_int;
-    printf(".set L_%d,%d\n",code_disp_label,disp+code_disp_offset);
+    r1_offsetv = -disp+max_func_args*size_of_int+code_disp_offset;
+
+    printf(".set L_%d,%d\n",code_disp_label,-r1_offsetv);
     local_table();
-    labelno++;
     free_all_register();
 }
 
@@ -1826,24 +1843,42 @@
 void
 leave(int control, char *name)
 {
+    int retcont1,sz;
+
+    if (max_freg_var>=0 && max_freg_var<=3) max_freg_var=3; 
+    reg_save = reg_save_offset();
 
     if (control) {
 	code_set_return_register(1);
     }
     if (retcont) { 
 	if (control) jmp(retlabel);
+	retcont1 = fwdlabel();
 	fwddef(retcont);
-	printf("\tmr r1,r30\n");
 	if (cadr(fnptr->ty)==FLOAT||cadr(fnptr->ty)==DOUBLE) {
 	    printf("\tfmr f1,f31\n");
+	} else if (cadr(fnptr->ty)>0&&(
+	    car(cadr(fnptr->ty))==STRUCT ||
+	    car(cadr(fnptr->ty))==UNION)) {
+	    sz = size(cadr(fnptr->ty));
+	    printf("\tli r7,%d\n",sz);
+	    printf("\tsubl r6,r7,r30\n");
+	    printf("\tlwz r3,lo16(%d)(r30)\n",(my_func_args-1)*size_of_int);
+	    emit_copy(6,3,sz,0,1,1);
 	} else if (cadr(fnptr->ty)!=VOID) {
 	    printf("\tmr r3,r29\n");
 	}
+#if !R1SAVE
+	printf("\tla r1,lo16(%d)(r30)\n",
+	    -reg_save+my_func_args*size_of_int);
+#endif
+	printf("\tb L_%d\n",retcont1);
     }
     fwddef(retlabel);
     printf("\tlwz r1,0(r1)\n");
-    if (max_freg_var>=0 && max_freg_var<=3) max_freg_var=3; 
-    reg_save = reg_save_offset();
+    if (retcont) {
+	fwddef(retcont1);
+    }
     if (max_freg_var>=0) {
 	printf("\tlmw r%d,%d(r1)\n",
 			REG_VAR_BASE-max_reg_var,reg_save);
--- a/mc-codegen.c	Tue Apr 01 10:31:40 2003 +0900
+++ b/mc-codegen.c	Thu Apr 03 03:04:16 2003 +0900
@@ -754,8 +754,9 @@
 		    target,ty,e2);
 	} else {
 	    target=list4(list2(LVAR,0), target,ty,e2);
-	    arg_size += sz;
 	}
+        /* keep arg space for register variables */
+        arg_size += sz;
 #if DEBUG_PARALLEL_ASSIGN
 printf("# target %d ty %d+%d sz %d\n",car(car(target)),ty,cadr(car(target)),sz);
 #endif
@@ -778,8 +779,8 @@
 	if(car(t0)==LVAR) {
 	    /* ここで、書込先アドレスを決める */
 	    cadr(t0)=-arg_size;
-	    arg_size-=sz;
 	}
+        arg_size-=sz;
 	if (!is_simple(car(s0))) {
 	    g_expr_u(assign_expr0((e4=list2(LVAR,new_lvar(sz))),s0,ty,ty));
 	    use=list3(ty,use,e1);
@@ -838,6 +839,13 @@
 	code_frame_pointer(e3);
 	emit_pop_free(e3);
     } else if (is_function(fnptr)) {
+	if (car(e2) != FNAME) {	
+	    e2 = emit_pop(0);
+	    code_fix_frame_pointer(disp_offset);
+	    code_indirect_jmp(e2);
+	    emit_pop_free(e2);
+	    return;
+	}
 	code_fix_frame_pointer(disp_offset);
     } 
 
--- a/mc-parse.c	Tue Apr 01 10:31:40 2003 +0900
+++ b/mc-parse.c	Thu Apr 03 03:04:16 2003 +0900
@@ -1218,7 +1218,7 @@
     NMTBL *n;
 
     t = cadr(fntype);
-    if (!scalar(t) && (car(t)==STRUCT||car(t)==UNION)) {
+    if (t>0 && (car(t)==STRUCT||car(t)==UNION)) {
 	mode_save = mode;
 	mode=ADECL;
 	type_save = type;