changeset 416:a6ed0575d731

ARM goto code, Parallel assignment
author kono
date Sun, 24 Oct 2004 21:07:46 +0900
parents bdf900926f32
children 98888da30b35
files .gdbinit Changes mc-code-arm.c mc-code-powerpc.c mc-codegen.c
diffstat 5 files changed, 154 insertions(+), 67 deletions(-) [+]
line wrap: on
line diff
--- a/.gdbinit	Sat Oct 23 23:26:33 2004 +0900
+++ b/.gdbinit	Sun Oct 24 21:07:46 2004 +0900
@@ -1,6 +1,6 @@
 tb main
-# run  -s test/arg.c
-run  -s mc-parse.c
+run  -s test/arg.c
+# run  -s mc-parse.c
 # run  -s mc-codegen.c
 # run  -s nkf203/nkf.c
 # run  -s -ob01.s mc-switch.c
--- a/Changes	Sat Oct 23 23:26:33 2004 +0900
+++ b/Changes	Sun Oct 24 21:07:46 2004 +0900
@@ -6174,3 +6174,65 @@
 なので、RET_LREGにしないで、lmove してしまうのが良い。
 
 align がおかしい
+
+Sat Oct 23 23:33:11 JST 2004
+
+struct を使った interface をregister にmapするかどうか。まぁ、
+難しいけどね。
+
+やっぱりarmのbitfieldを合わせるのは止めた方がいいんじゃない?
+long long 以外は、型を大きくして対応できる。long long のはみ出し
+は、ちょっと対処できない。
+      a:8 =>  a0:4<<4+a1:4
+      a:8 = hoge =>    a0:4 = hoge<<4, a1:4 = hoge;
+というように分解する?
+
+Sun Oct 24 14:19:13 JST 2004
+
+code_frame_pointer と code_environment は同じなんですけど...
+
+巨大な構造体を並列代入すると、
+
+自分自身が重なっている
+   |----------|
+       |----------|
+
+では、
+   |----------|
+            --copy-> |----------|
+     他のものを代入
+            <-copy--
+       |----------|
+ってことになる。
+
+これは、ちょっと手間が大きい。
+   |--|---|---|
+       |--|---|---|
+と分割する(分割が細かくならない?)
+   |---|--|---|
+       |---|--|---|
+
+分割はだめだね。自分自身しか重なってないのだったらoverappable copy
+する。
+   |----------|----------|----------|
+       |----------|----------|----------|
+
+circular dependency はrecursive callする必要はないね。
+
+なんか、構造体が一度、スタックにあげられてから戻されているみたい
+
+RSTRUCT って、本当にいるの?
+
+なんか、「まだ、emit_copy が間違っている!」
+
+PowerPC は、code のレジスタに割り当てられた分のスタック上の引数
+を割り当てているな。なので、
+## code carg6(int i, int j,int k,int l,struct arg args0)
+##     goto carg3(args0,args0,i,j,k,l);
+で、args0 のcopyが余計に出るね。 しかもずれ方が変。
+
+無害ではあるんだが...
+
+でも、それでバグを見つけたわけか。
+
+だいぶ、enbug しちゃったよ...
--- a/mc-code-arm.c	Sat Oct 23 23:26:33 2004 +0900
+++ b/mc-code-arm.c	Sun Oct 24 21:07:46 2004 +0900
@@ -60,10 +60,11 @@
 static int output_mode = TEXT_EMIT_MODE;
 static int register_save_return_label;
 
-// static int r1_offset_label;
+static int r1_offset_label;
 static int lvar_offset_label;
 static int    max_func_args = 0;
 static int arg_on_register = 0;
+static int max_func_arg_label = 0;
 
 
 static int freg,ireg,lreg;
@@ -102,10 +103,11 @@
 
 #define PTRC_REG 3              /* mark for pointer cache */
 
-#define FREG_VAR_BASE 7
+#define FREG_VAR_BASE 4
 #define FREG_VAR_MIN  4
-#define MIN_TMP_FREG 1
-#define MAX_TMP_FREG 4
+#define FREG_VAR_MAX  7
+#define MIN_TMP_FREG 0
+#define MAX_TMP_FREG 3
 
 int MAX_REGISTER=17;             /* ARMのレジスタを10個まで使う*/
 int MAX_FREGISTER=8;
@@ -117,11 +119,11 @@
 #define LREG_OFFSET (REAL_MAX_REGISTER+REAL_MAX_FREGISTER)
 
 int MAX_INPUT_REGISTER_VAR = 4;
-int MAX_CODE_INPUT_REGISTER_VAR = 9-MIN_TMP_REG;
 int MAX_INPUT_DREGISTER_VAR = 4;
 int MAX_INPUT_FREGISTER_VAR = 4;
-int MAX_CODE_INPUT_DREGISTER_VAR = 3-MIN_TMP_FREG;
-int MAX_CODE_INPUT_FREGISTER_VAR = 7-MIN_TMP_FREG;
+int MAX_CODE_INPUT_REGISTER_VAR = 4;
+int MAX_CODE_INPUT_DREGISTER_VAR = 6;
+int MAX_CODE_INPUT_FREGISTER_VAR = 6;
 
 #define LREG_V 3    /* mark for virtual long long/double register */
 #define REGS_MAX (REAL_MAX_REGISTER+REAL_MAX_FREGISTER+REAL_MAX_LREGISTER+LREG_V)
@@ -317,23 +319,23 @@
 
 register_save is done by callee
 
-                 * gotoを呼び出した関数のr1 ! r1(goto前のr1)
-   #             *             $fp <-----------------r1_offset---------> $sp
-r+ +----------+-------------+--------+-------+-----------+----------+----+
-    cousin arg!  callee arg !reg_save!reg_arg!code local  caller arg  xx
-                    (arg4..)  lvar>0 (arg0.3) lvar<0      lvar>0x1000 000
-                  <-----------my_func_args--><--disp-----><-max_func_arg->
+                     (prev $sp)
+                            <---lvar_offset-->
+   #                       $fp <--------------------r1_offset---------> $sp
+r+ +----------+-------------+--------+-------+-----------+---------------+
+    cousin arg!  callee arg !reg_save!reg_arg!local       caller arg 
+              (arg4..)lvar>0         (arg0.3) lvar<0      lvar>0x1000 000
+               <--------------my_func_args--><--disp-----><-max_func_arg->
                               *SIZE_OF_INT                  *SIZE_OF_INT
                  prev $sp=$fp                 $fp                        $sp
 
-
-                      <-------r1_offset------------------------------>
-                                      <------------lvar_offset------->
-                                                              <-arg_offset->
- r+  +-----------+----+---------------+----------+-------------+----+
-       callee arg xxx  register save   local      caller arg     xxx
-                 ($r31)($fp) reg_save   disp          max_func_args*SIZE_OF_INT
-        lvar>0                         lvar<0          lvar>0x1000 0000
+                                         (prev $sp)
+                                      <------r1_offset----------------> $sp
+                 (prev $fp)           $fp
+ r+  +-----------+--------------------+----------+-----------------------+
+       callee arg      register save   local      caller arg   
+                                        disp          max_func_args*SIZE_OF_INT
+                                       lvar<0          lvar>0x1000 0000
                       prev $sp=$fp                                   $sp=$fp
  */
 
@@ -344,7 +346,6 @@
 
 #define func_disp_offset 8
 #define code_disp_offset 0
-#define jump_offset 0
 
 #define CODE_LVAR(l) ((l)+code_disp_offset)
 #define CODE_CALLER_ARG(l) ((l)+arg_offset1)
@@ -356,15 +357,29 @@
 code_offset_set(NMTBL *fnptr)
 {
     int lvar_offsetv;
-    // int code_f = (fnptr->sc==CODE);
+    int r1_offsetv;
+    int code_f = (fnptr->sc==CODE);
 
     disp &= -SIZE_OF_INT;
-    lvar_offsetv = 
-	-12 - max_reg_var*SIZE_OF_INT-max_freg_var*SIZE_OF_DOUBLE;
+
+    if (code_f) {
+	r1_offsetv = disp-max_func_args*SIZE_OF_INT;
+	printf("\t.set .L%d, %d\n",r1_offset_label,r1_offsetv);
+    } else {
+	lvar_offsetv = 
+	    -12 - max_reg_var*SIZE_OF_INT-max_freg_var*SIZE_OF_DOUBLE;
+	printf("\t.set .L%d, %d\n",lvar_offset_label,lvar_offsetv);
+    }
+    if (max_func_arg_label) {
+        printf(".set L_%d,%d\n",max_func_arg_label,max_func_args*SIZE_OF_INT);
+        max_func_arg_label = 0;
+    }
+
+
 // printf("        @ args = %d, pretend = %d, frame = %d\n",
 // 	max_func_args,0,round16(-disp));
 // printf("        @ frame_needed = 1, current_function_anonymous_args = 0\n");
-    printf("\t.set .L%d, %d\n",lvar_offset_label,lvar_offsetv);
+
 
 #if 0
 printf("# vars= %d, regs= %d/%d, args= %d, extra= %d\n",
@@ -627,7 +642,7 @@
 get_register(void)
 {    /* 使われていないレジスタを調べる */
     int i,j,reg;
-    for(i=MAX_TMP_REG;i>MIN_TMP_REG;i--) {
+    for(i=MAX_TMP_REG;i>=MIN_TMP_REG;i--) {
 	if (regs[i]) continue;  /* 使われている */
 	regs[i]=USING_REG;      /* そのレジスタを使うことを宣言し */
 	return i;   /* その場所を表す番号を返す */
@@ -662,7 +677,7 @@
         }
     }
     /* PTR_CACHE をつぶす */
-    for(i=MAX_TMP_REG;i>MIN_TMP_REG;i--) {
+    for(i=MAX_TMP_REG;i>=MIN_TMP_REG;i--) {
 	if (regs[i]==PTRC_REG) {
 	    clear_ptr_cache_reg(i);
 	} else 
@@ -709,10 +724,11 @@
       if (i!=-1) regs[i]=USING_DREG;
       return i;
     }
-    for(i=MAX_TMP_FREG+FREG_OFFSET;i>MIN_TMP_FREG+FREG_OFFSET;i--) {
-	if (regs[i]) continue;    /* 使われている */
-	regs[i]=USING_REG;      /* そのレジスタを使うことを宣言し */
-	return i;   /* その場所を表す番号を返す */
+    for(i=0;i<MAX_TMP_FREG;i++) {
+	reg = i+MIN_TMP_FREG+FREG_OFFSET;
+	if (regs[reg]) continue;    /* 使われている */
+	regs[reg]=USING_REG;      /* そのレジスタを使うことを宣言し */
+	return reg;   /* その場所を表す番号を返す */
     }
     /* search register stack */
     for(i=0;i<freg_sp;i++) {
@@ -723,11 +739,11 @@
 	    return reg;
 	}
     }
-    for(i=0;i<FREG_VAR_BASE-REG_VAR_MIN;i++) {
-        reg =FREG_VAR_BASE-i+FREG_OFFSET;
+    for(i=0;i<FREG_VAR_MAX;i++) {
+        reg =FREG_VAR_BASE+i+FREG_OFFSET;
         if (! regs[reg]) {       /* 使われていないなら */
             regs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */
-	    if (i+1>max_freg_var) max_freg_var=i+1;
+	    if (i>max_freg_var) max_freg_var=i;
 	    return reg;   /* その場所を表す番号を返す */
         }
     }
@@ -852,11 +868,11 @@
     int j;
     if (is_code) {
 	if (!(arch_mode&UseFPP)) {
-	    if(!(i<FREG_VAR_BASE-FREG_VAR_MIN)) return 0;
-	    i = FREG_VAR_BASE-i+FREG_OFFSET;
+	    if(i>MAX_CODE_INPUT_DREGISTER_VAR) return 0;
+	    i = FREG_VAR_BASE+i+FREG_OFFSET;
 	    return list3(FREGISTER,i,(int)n);
 	} else {
-	    return 0;
+	    return get_input_lregister_var(i,n,is_code);
 	}
     }
     if (d) {
@@ -1126,20 +1142,20 @@
     return list2(LVAR,new_lvar(SIZE_OF_INT));
 }
 
-#define freg_var_num(i) (FREG_VAR_BASE-i+FREG_OFFSET)
+#define freg_var_num(i) (FREG_VAR_BASE+i+FREG_OFFSET)
 
 int
 get_dregister_var(NMTBL *n,int d)
 {
     int i,j;
     if ((arch_mode&UseFPP)) {
-	for(i=0;i<FREG_VAR_BASE-FREG_VAR_MIN;i++) {
+	for(i=0;i<FREG_VAR_MAX;i++) {
 	    j = freg_var_num(i);
 	    if (! regs[j]) {       /* 使われていないなら */
 		regs[j]=USING_REG; /*そのレジスタを使うことを宣言し*/
 		if (i+1>max_freg_var) max_freg_var=i+1;
 		/* その場所を表す番号を返す */
-		return list3(d?DREGISTER:FREGISTER,j,(int)n); 
+		return list3(FREGISTER,j,(int)n); 
 	    }
 	}
     }
@@ -2201,7 +2217,7 @@
 not_simple_p(int e3)
 {
     switch(e3) {
-	case FUNCTION: case CONV: case RSTRUCT: case STASS: case ALLOCA:
+	case FUNCTION: case CONV: case STASS: case ALLOCA:
 	case DIV : case UDIV : case MOD : case UMOD :
 	case LDIV: case LUDIV: case LMOD: case LUMOD:
 	case LMUL: case LUMUL:
@@ -2658,7 +2674,9 @@
     crn = register_name(reg);
     inc_inst(2);
     printf("\trsb\tsp, %s, sp\n",crn);
-    printf("\tmov\t%s, sp\n",crn);
+    if (!max_func_arg_label) max_func_arg_label = fwdlabel();
+    code_label_value(max_func_arg_label ,REG_ip);
+    printf("\tadd\t%s, sp, ip\n",crn);
 }
 
 void
@@ -2681,7 +2699,7 @@
 code_jmp(char *s) {
     // jump to continuation means use all register variable
     max_reg_var = REG_VAR_MAX-REG_VAR_MIN;
-    max_freg_var = FREG_VAR_BASE-FREG_VAR_MIN;
+    max_freg_var = FREG_VAR_MAX-FREG_VAR_MIN;
     inc_inst(1);
     printf("\tb\t%s\n",s);
     control=0;
@@ -2691,7 +2709,7 @@
 code_indirect_jmp(int e2) {
     // jump to continuation means use all register variable
     max_reg_var = REG_VAR_MAX-REG_VAR_MIN;
-    max_freg_var = FREG_VAR_BASE-FREG_VAR_MIN;
+    max_freg_var = FREG_VAR_MAX-FREG_VAR_MIN;
     use_int(e2);
     inc_inst(1);
     printf("\tmov\tpc, %s @ indirect jump\n",register_name(e2)); // ?!
@@ -3266,11 +3284,11 @@
     if (stmode!=STATIC)
     printf("\t.globl\t%s\n",name);
     printf("\t.type\t%s,function\n",name);
-    lvar_offset_label = fwdlabel();
+    r1_offset_label = fwdlabel();
     max_func_args = 0;
     printf("%s:\n",name);
-    jmp(entry_label = fwdlabel());
-    register_save_return_label = backdef();
+    code_label_value(r1_offset_label,REG_ip);
+    printf("\tadd\tsp, ip, fp\n");
 }
 
 
@@ -3285,10 +3303,7 @@
 void
 code_leave(char *name)
 {
-    fwddef(entry_label);
     code_offset_set(fnptr);
-    code_add(REG_sp,disp,REG_fp);
-    jmp(register_save_return_label);
     local_table();
     printf("\t.size\t%s,.L%d-%s\n",name, backdef(),name);
 }
@@ -3360,10 +3375,6 @@
 	}
 #if R1SAVE
 #else
-	inc_inst(1);
-	printf("\tsub\tfp, ");
-//	printf("fp, #%d+.L%d\n",FUNC_LVAR(0),lvar_offset_label);
-	printf("fp, #%d\n",FUNC_LVAR(0));
 #endif
     }
     fwddef(retlabel);
--- a/mc-code-powerpc.c	Sat Oct 23 23:26:33 2004 +0900
+++ b/mc-code-powerpc.c	Sun Oct 24 21:07:46 2004 +0900
@@ -1571,7 +1571,7 @@
 	break;
     default:
 	if (length <0) {
-	    if (length > -MAX_COPY_LEN) {
+	    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)
@@ -1591,11 +1591,13 @@
 	}
 	clear_ptr_cache();
 	code_save_stacks();
-	printf("\tli r5,%d\n",length);
+	printf("\tli r5,%d\n",length>0?length:-length);
 	printf("\tmr r4,%s\n",frn);
 	printf("\tmr r3,%s\n",trn);
-	//if (offset)
-	//    code_add(3,offset,3);
+	if (length<0 && offset) {
+	    code_add(4,offset,4);
+	    code_add(3,offset,3);
+	}
         /* overrap must be allowed */
 	printf("\tbl L_%s$stub\n",memmove);
 	extern_define(memmove,0,FUNCTION,1);
@@ -1823,7 +1825,7 @@
 static int
 not_simple_p(int e3)
 {
-    return e3==FUNCTION||e3==CONV||e3==RSTRUCT||e3==STASS|| 
+    return e3==FUNCTION||e3==CONV/*||e3==RSTRUCT*/||e3==STASS|| 
 	e3==LLSHIFT||e3==LULSHIFT||e3==LRSHIFT||e3==LURSHIFT||
 	e3==LDIV||e3==LUDIV||e3==LMOD||e3==LUMOD||e3==LASSOP||e3==ALLOCA;
 }
--- a/mc-codegen.c	Sat Oct 23 23:26:33 2004 +0900
+++ b/mc-codegen.c	Sun Oct 24 21:07:46 2004 +0900
@@ -951,8 +951,15 @@
 		return 1;
 	    }
 	    if ((s1=overlap(t1,sz,*source))) {
+		if (s==s1) {
+#if DEBUG_PARALLEL_ASSIGN
+printf("# self dependency %d ty %d+%d sz %d\n",car(s1),ty,cadr(s1),sz);
+#endif
+		    return 1;
+		}
 		/* another overlap start over */
-		return circular_dependency(t,s1,target,source);
+		s = s1; target0 = *target;
+		continue;
 	    }
 	}
 	target0=cadr(target0);
@@ -1048,13 +1055,13 @@
     if (ce1==LVAR) {
 	switch(ce2) {
 	    case RLVAR: case CRLVAR: case FRLVAR: case DRLVAR:
-	    case SRLVAR: case SURLVAR: case CURLVAR:
+	    case SRLVAR: case SURLVAR: case CURLVAR: case LVAR:
 	    return 1;
 	}
     } else if (ce2==LVAR) {
 	switch(ce1) {
 	    case RLVAR: case CRLVAR: case FRLVAR: case DRLVAR:
-	    case SRLVAR: case SURLVAR: case CURLVAR: case LRLVAR:
+	    case SRLVAR: case SURLVAR: case CURLVAR: case LRLVAR: case LVAR:
 	    return 1;
 	}
     } else if (ce1==GVAR) {
@@ -1105,7 +1112,9 @@
     int processing = 0;
     int use = 0;
 
-    /* まず、サイズを計算しながら、決まった形に落す。 */
+    /* e1 = list4(FUNCTION,code_segment,arglist,ftype); */
+
+    /* まず、サイズを計算しながら、target を決まった形に落す。 */
 
     arg_size = 0; regs = 0;
     fregs = 0;
@@ -1120,6 +1129,7 @@
 	} else if ((ty==LONGLONG||ty==ULONGLONG) && (r = get_input_lregister_var(fregs,0,1))) {
 	    target=list4(r, target,ty,e2); regs+=2;
 	} else {
+	    while(car(e2)==RSTRUCT) e2=cadr(e2);
 	    target=list4(list2(LVAR,0), target,ty,e2);
 	}
         /* keep arg space for register variables */
@@ -1296,6 +1306,9 @@
     e3 = cadr(e2);  /* offset of the variable (distination) */
     e4 = caddr(e1); /* right value (source) */
     sz = cadddr(e1);  /* size of struct or union */
+    if (car(e4)==RSTRUCT) {
+	e4 = cadr(e4);
+    }
     if (is_same_type(e2,e4)&&cadr(e2)==cadr(e4)) {
 	if (use) g_expr(e4);
 	return;
@@ -1306,7 +1319,6 @@
     xreg = emit_pop(0);
     /* 一般的にはコピーのオーバラップの状況は実行時にしかわからない */
     /* しかし、わかる場合もある */
-    if (car(e4)==RSTRUCT) e4=cadr(e4);
     if (is_same_type(e2,e4)) {
 	if(cadr(e2)<cadr(e4)) { offset=sz; sz=-sz;}
 	det=1;