changeset 450:eaf9e2746c83 simple-exp-in-parallel-assign

parallel assign for simple expr. (too complex solution) statement expression (GNU extension fix) non_lazy function reference in PowerPC
author kono
date Sun, 28 Nov 2004 03:28:38 +0900
parents c55363eff5e5
children 656ec59cd79f
files .gdbinit Changes Makefile.linuxzaurus Makefile.mips mc-code-arm.c mc-code-ia32.c mc-code-mips.c mc-code-powerpc.c mc-code.h mc-codegen.c mc-codegen.h mc-parse.c mc.h test/scope.c
diffstat 14 files changed, 438 insertions(+), 220 deletions(-) [+]
line wrap: on
line diff
--- a/.gdbinit	Thu Nov 25 16:56:26 2004 +0900
+++ b/.gdbinit	Sun Nov 28 03:28:38 2004 +0900
@@ -1,5 +1,5 @@
 tb main
-run  -s test/inline.c
+# run  -s test/inline.c
 # run  -s mc-parse.c
 # run  -s mc-codegen.c
 # run  -s nkf203/nkf.c
@@ -9,6 +9,7 @@
 # run  -s test/basic.c
 # run -s test/code-gen-all.c
 # run -s test/tmp7.c
+run -s test/tmp1.c
 define regs 
 printf "pc =%08x lr =%08x r0 =%08x r1 =%08x r3= %08x r4= %08x\n",$pc,$lr,$r0,$r1,$r3,$r4
 printf "r10=%08x r11=%08x r12=%08x r13=%08x r14=%08x r15=%08x\n",$r10,$r11,$r12,$r13,$r14,$r15
--- a/Changes	Thu Nov 25 16:56:26 2004 +0900
+++ b/Changes	Sun Nov 28 03:28:38 2004 +0900
@@ -6828,3 +6828,78 @@
 
 progress でなんとかすると、やっぱり、全部 save されちゃうね。
 toplogical sort しないとだめか。
+
+singleton が良い。multi ならば、どうせsaveするんだから。
+list5 はやらないとだめ。
+
+
+#define CHECK_HEAP(b) ({int _k=(int)(b);if(_k>heapsize)error(-1);_k;})
+#define car(e) (heap[(int)(CHECK_HEAP(e))])
+
+は、いいんだけどさ、これのコンパイルが間違っているみたいね。
+
+っていうか、expr() 中で docomp が実行されてコード生成されちゃうから
+まずよな。何とか、する方法としては... (うーん、思い付かないな。
+だめなんじゃないの?)
+
+単独のサブルーチンを生成して、そこへの関数呼び出しにすれば?
+code 生成系を足さないとできないか。
+	b hoge
+    haga:
+	fuga
+	st value
+	ret
+    hoge:
+	bl haga
+	value 
+まあ、いいんだけど、大半の場合は、必要ないんだよね。
+
+あぁ、これだと、({   goto exit0;  }) みたいなのがだめだ。
+	b L1
+    L2:
+	fuga
+	st value
+	j L3
+    L1:
+	.........
+	b L2
+    L3:
+	value 
+ですかぁ? はぁ。
+
+Sat Nov 27 08:51:01 JST 2004
+
+({}) で、init_vars がnestする可能性があるのを忘れてました。
+
+register stack が異なるので破綻しているみたい。
+
+    ## 	if (car(ns)==sc) {
+    ## (heap[(int)(({int _k=(int)(ns);if(_k>heapsize)error(-1);_k;}))])
+	    b	L_2215
+    L_2216:
+    # 3764: gexpr_init: creg=r11 freg=f14
+	    lwz r11,lo16(-16)(r30)
+	   ....
+    L_2215:
+	    lwz r11,lo16(28+L_2206)(r30)
+	    b	L_2216
+
+どうしようかなぁ。
+
+Sun Nov 28 02:41:11 JST 2004
+
+> L_code_postinc$non_lazy_ptr:
+>       .indirect_symbol _code_postinc
+>       .long   0
+
+なんだけど、PowerPC で、
+     関数として使われている is_function && sc==EXTRN1
+           binding helper 必要
+           non_lazy は不要
+と、
+     大域変数としてい使われている
+           binding helper 不要
+           non_lazy のみ必要
+を区別する必要があるみたいね。これは parse.c で追加する必要がある。
+
+もっとも、.long 0 が余計に出力されるだけだが。
--- a/Makefile.linuxzaurus	Thu Nov 25 16:56:26 2004 +0900
+++ b/Makefile.linuxzaurus	Sun Nov 28 03:28:38 2004 +0900
@@ -103,11 +103,11 @@
 	make check-code$(MK) TARGET=test/fact-a
 	make check-code$(MK) TARGET=test/fact
 	make check-code$(MK) TARGET=test/goto
-#	make check-code$(MK) TARGET=test/test1
-#	make check-code$(MK) TARGET=test/tmp1
+	make check-code$(MK) TARGET=test/test1
+	make check-code$(MK) TARGET=test/tmp1
 	make check-code$(MK) TARGET=test/tmp2
 	make check-code$(MK) TARGET=test/tmp4
-#	make check-code$(MK) TARGET=test/tmp6
+	make check-code$(MK) TARGET=test/tmp6
 	make check-code$(MK) TARGET=test/scope
 
 check-nkf:
--- a/Makefile.mips	Thu Nov 25 16:56:26 2004 +0900
+++ b/Makefile.mips	Sun Nov 28 03:28:38 2004 +0900
@@ -103,11 +103,11 @@
 	make check-code$(MK) TARGET=test/fact-a
 	make check-code$(MK) TARGET=test/fact
 	make check-code$(MK) TARGET=test/goto
-#	make check-code$(MK) TARGET=test/test1
-#	make check-code$(MK) TARGET=test/tmp1
+	make check-code$(MK) TARGET=test/test1
+	make check-code$(MK) TARGET=test/tmp1
 	make check-code$(MK) TARGET=test/tmp2
 	make check-code$(MK) TARGET=test/tmp4
-#	make check-code$(MK) TARGET=test/tmp6
+	make check-code$(MK) TARGET=test/tmp6
 	make check-code$(MK) TARGET=test/scope
 
 check-nkf:
--- a/mc-code-arm.c	Thu Nov 25 16:56:26 2004 +0900
+++ b/mc-code-arm.c	Sun Nov 28 03:28:38 2004 +0900
@@ -293,7 +293,6 @@
 static int code_l2(long long ll);
 #endif
 
-static void code_save_stacks();
 static void code_save_input_registers(int dots);
 static void    set_ireg(int,int);
 #if FLOAT_CODE
@@ -2244,7 +2243,7 @@
 	case DPOSTINC : case DPREINC : case DASSOP :
 	case DOP+LT : case DOP+LE : case DOP+GT : case DOP+GE :
 	case DOP+EQ : case DOP+NEQ:
-	case RBIT_FIELD: case BASS: case BASSOP:
+	case RBIT_FIELD: case BASS: case BASSOP: case LCALL:
 	return 1;
     }
     return 0;
@@ -3408,6 +3407,18 @@
     set_freg(FREG_FREGISTER,0);
 }
 
+void
+code_label_call(int l)
+{
+        printf("\tbl\tL_%d\n",l);
+}
+
+void
+code_ret()
+{
+	printf("\tmov\tpc, lr\n");
+	control=0;
+}
 
 void
 leave(int control0, char *name)
--- a/mc-code-ia32.c	Thu Nov 25 16:56:26 2004 +0900
+++ b/mc-code-ia32.c	Sun Nov 28 03:28:38 2004 +0900
@@ -184,7 +184,6 @@
 static int code_d2(double d);
 static void code_save_fstacks();
 #endif
-static void code_save_stacks();
 static void jcond(int l, char cond);
 #if LONGLONG_CODE
 static int code_l1(long long d);
@@ -1892,6 +1891,19 @@
 }
 
 void
+code_label_call(int l)
+{
+        printf("\tcall\tL_%d\n",l);
+}
+
+void
+code_ret()
+{
+        printf("\tret\n");
+        control=0;
+}
+
+void
 leave(int control, char *name)
 {
     int sz;
@@ -3755,7 +3767,7 @@
         case DPOSTINC : case DPREINC : case DASSOP :
         case DOP+LT : case DOP+LE : case DOP+GT : case DOP+GE :
         case DOP+EQ : case DOP+NEQ:
-        case RBIT_FIELD: case BASS: case BASSOP:
+        case RBIT_FIELD: case BASS: case BASSOP: case LCALL:
         return 1;
     }
     return 0;
--- a/mc-code-mips.c	Thu Nov 25 16:56:26 2004 +0900
+++ b/mc-code-mips.c	Sun Nov 28 03:28:38 2004 +0900
@@ -279,7 +279,6 @@
 static void    set_lreg(int,int);
 #endif
 
-static void code_save_stacks();
 static void code_save_input_registers(int dots);
 static void    set_ireg(int,int);
 static void    set_dreg(int,int);
@@ -310,7 +309,8 @@
      $4-$7  input register
      r18-r24 saved register variable (input register for code segment)
      $25    jump register
-     $31    stack pointer
+     $31    return address
+     $sp    stack pointer
      $fp    frame pointer
 
      $f0       return value etc.
@@ -1834,13 +1834,17 @@
 int
 not_simple_p(int e3)
 {
-    return (e3==FUNCTION||e3==CONV||e3==RSTRUCT||e3==STASS||e3==ALLOCA||
-	e3==LDIV||e3==LUDIV||e3==LMOD||e3==LUMOD||
-		e3==LLSHIFT||e3==LULSHIFT||e3==LRSHIFT||e3==LURSHIFT||
-	e3==DDIV||e3==DADD||e3==DSUB||e3==DMUL||e3==DMINUS||
-            e3== DPOSTINC || e3==DPREINC || e3==DASSOP ||
-            e3== DOP+LT || e3== DOP+LE || e3== DOP+GT ||
-            e3== DOP+GE || e3== DOP+EQ || e3== DOP+NEQ);
+    switch(e3) {
+    case FUNCTION: case CONV: case RSTRUCT: case STASS: case ALLOCA: 
+	case LDIV: case LUDIV: case LMOD: case LUMOD: 
+		case LLSHIFT: case LULSHIFT: case LRSHIFT: case LURSHIFT: 
+	case DDIV: case DADD: case DSUB: case DMUL: case DMINUS: 
+            case  DPOSTINC :  case DPREINC :  case DASSOP : 
+            case  DOP+LT :  case  DOP+LE :  case  DOP+GT : 
+            case  DOP+GE :  case  DOP+EQ :  case  DOP+NEQ:
+    return 1;
+    }
+    return 0;
 }
 
 int
@@ -3053,6 +3057,18 @@
     set_freg(FREG_FREGISTER,0);
 }
 
+void
+code_label_call(int l)
+{
+    printf("\tjal       L_%d\n",l);
+}
+
+void
+code_ret()
+{
+    printf("\tj       $31\n");
+    control=1;
+}
 
 void
 leave(int control, char *name)
@@ -3110,7 +3126,7 @@
     if (max_reg_var+max_freg_var)
 	code_register_restore(max_reg_var,max_freg_var,-arg_offset-SIZE_OF_INT*2);
     printf("\tmove    $sp,$13\n");
-    printf("\tj       $31\n");
+    code_ret();
 
 //  leave part end
 
--- a/mc-code-powerpc.c	Thu Nov 25 16:56:26 2004 +0900
+++ b/mc-code-powerpc.c	Sun Nov 28 03:28:38 2004 +0900
@@ -245,7 +245,6 @@
 static int code_l2(long long ll);
 #endif
 
-static void code_save_stacks();
 static void code_save_input_registers(int dots);
 static void    set_ireg(int,int);
 static void    set_freg(int,int);
@@ -1777,9 +1776,13 @@
 int
 not_simple_p(int e3)
 {
-    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;
+    switch (e3) {
+    case FUNCTION: case CONV: case LCALL: case STASS:  
+	case LLSHIFT: case LULSHIFT: case LRSHIFT: case LURSHIFT: 
+	case LDIV: case LUDIV: case LMOD: case LUMOD: case LASSOP: case ALLOCA:
+    return 1;
+    }
+    return 0;
 }
 
 static int
@@ -2818,6 +2821,18 @@
 }
 
 void
+code_label_call(int l)
+{
+	printf("\tbl\tL_%d\n",l);
+}
+
+void
+code_ret()
+{
+	printf("\tblr\n");
+}
+
+void
 leave(int control, char *name)
 {
     int retcont1=0,sz;
@@ -2868,7 +2883,7 @@
 	printf("\tmtlr r0\n");
 	printf("\tlmw r%d,%d(r1)\n",
 		    REG_VAR_BASE-max_reg_var,reg_save);
-	printf("\tblr\n");
+	code_ret();
     }
 
     disp &= -SIZE_OF_INT;
@@ -3150,7 +3165,7 @@
     }
     init = 0;
     for(n = global_list;n!=&null_nptr;n = n->next) {
-	if (is_code(n)||is_function(n)) continue;
+//	if (is_code(n)||is_function(n)) continue;
 	if (n->sc==EXTRN1) {
 	    if(init==0) {
 		printf(".data\n");
--- a/mc-code.h	Thu Nov 25 16:56:26 2004 +0900
+++ b/mc-code.h	Sun Nov 28 03:28:38 2004 +0900
@@ -41,11 +41,14 @@
 extern void code_enter(char *name);
 extern void code_enter1(int args);
 extern void code_leave(char *name);
+extern void code_label_call(int i);
+extern void code_ret();
 extern void enter(char *name);
 extern void enter1();
 extern void leave(int control, char *name);
 extern void jmp(int l);
 extern int not_simple_p(int l);
+extern void code_save_stacks();
 
 extern int get_register_var(NMTBL *n);
 extern int get_dregister_var(NMTBL *n,int d);
--- a/mc-codegen.c	Thu Nov 25 16:56:26 2004 +0900
+++ b/mc-codegen.c	Sun Nov 28 03:28:38 2004 +0900
@@ -475,6 +475,11 @@
     case ENVIRONMENT:
 	code_environment(USE_CREG);
 	return ADDRESS;
+    case LCALL:
+	code_save_stacks();
+	gen_jmp(e2);
+	fwddef(caddr(e1));
+	return VOID;
 #if BIT_FIELD_CODE
     case RBIT_FIELD:
 	return bit_field(e2,caddr(e1) /* type */);
@@ -853,29 +858,43 @@
 
 static int is_memory(int e1);
 
+/* overlap 
+      return list of overlapped target
+ */
+
 static int
-overlap(int t,int sz,int source)
+overlap(int t,int sz,int target)
 {
     int s,s0,s1;
     int t0=cadr(t);
     int t1=t0+sz;
-    for(;source;source=cadr(source)) {
-	s=car(source); s0=cadr(s); 
-	switch(car(s)) {
-	case REGISTER: case DREGISTER: case FREGISTER: case LREGISTER:
-	    if (code_register_overlap(s,t)) return s;
-	}
-	if (is_same_type(s,t)) {
-	    s1=s0+caddr(source);
+    int source;
+    int result=0;
+    if (!is_memory(t)) error(-1);
+    for(;target;target=cadr(target)) {
+	for(source=caddddr(target);source;source=cadr(source)) {
+	    s=car(source); s0=cadr(s); 
+	    switch(car(s)) {
+	    case REGISTER: case DREGISTER: case FREGISTER: case LREGISTER:
+		if (code_register_overlap(s,t)) {
+		    result = list2(target,result);
+		}
+		break;
+	    default:
+		if (is_same_type(s,t)) {
+		    s1=s0+caddr(source);
 #if DEBUG_PARALLEL_ASSIGN>1 
 printf("# overlap source %d t0 %d t1 %d\n",car(car(t)),t0,t1);
 printf("# overlap target %d s0 %d s1 %d\n",car(car(source)),s0,s1);
 printf("# overlap   equal = %d\n",((t0<=s0&&s0<t1)||(t0<s1&&s1<=t1)));
 #endif
-	    if((t0<=s0&&s0<t1)||(t0<s1&&s1<=t1)) return s;
+		    if((t0<=s0&&s0<t1)||(t0<s1&&s1<=t1))
+			result = list2(target,result);
+		}
+	    }
 	}
     }
-    return 0;
+    return result;
 }
 
 static void
@@ -904,76 +923,78 @@
 	// e1=list3(REGISTER,e1,0);
 	*use=list3(t,*use,e1);
 	g_expr_u(assign_expr0(e1,s,ty,ty));
-	*target = append4(*target,t,ty,e1);
+	*target = append5(*target,t,ty,e1,list3(e1,0,sz));
 #if FLOAT_CODE
     } else if (ty==DOUBLE && sz==size_of_double && (e1=get_dregister_var(0,1))!=-1) {
 	// e1=list3(DREGISTER,e1,0);
 	*use=list3(t,*use,e1);
 	g_expr_u(assign_expr0(e1,s,ty,ty));
-	*target = append4(*target,t,ty,e1);
+	*target = append5(*target,t,ty,e1,list3(e1,0,sz));
     } else if (ty==FLOAT && sz==size_of_float && (e1=get_dregister_var(0,0))!=-1) {
 	// e1=list3(FREGISTER,e1,0);
 	*use=list3(t,*use,e1);
 	g_expr_u(assign_expr0(e1,s,ty,ty));
-	*target = append4(*target,t,ty,e1);
+	*target = append5(*target,t,ty,e1,list3(e1,0,sz));
 #endif
 #if LONGLONG_CODE
     } else if ((ty==LONGLONG||ty==ULONGLONG)&&(e1=get_lregister_var(0))!=-1) {
 	// e1=list3(LREGISTER,e1,0);
 	*use=list3(t,*use,e1);
 	g_expr_u(assign_expr0(e1,s,ty,ty));
-	*target = append4(*target,t,ty,e1);
+	*target = append5(*target,t,ty,e1,list3(e1,0,sz));
 #endif
     } else {
 	g_expr_u(assign_expr0((e1=list3(LVAR,new_lvar(sz),0)),s,ty,ty));
-	*target = append4(*target,t,ty,e1);
+	*target = append5(*target,t,ty,e1,list3(e1,0,sz));
 	*use=list3(t,*use,e1);
     }
 }
 
 static int
-circular_dependency(int t,int s,int *target,int *source)
+circular_dependency(int t,int clist,int target,int history)
 {
-    int target0=*target;
-    int t1,sz,ty,s1;
-    while(target0) {
-	if (cadddr(target0)==s) {
-	    t1=car(target0); 
-	    s=cadddr(target0);
-	    sz=size(ty=caddr(target0)); 
-	    if(t==t1) {
+    int t1,h,sz,ty,s,clist1,t2;
+
+    for(;clist;clist=cadr(clist)) {          /* conflict list */
+loop:
+	t1 = car(clist);
+	for(h=history;h;h=cadr(h)) {
+	    if (t1==car(h)) {
 #if DEBUG_PARALLEL_ASSIGN
-printf("# circular dependency %d ty %d+%d sz %d\n",car(t1),ty,cadr(t1),sz);
+printf("# circular dependency %d ty %d+%d\n",car(t1),ty,cadr(t1));
 #endif
-		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 */
-		s = s1; target0 = *target;
-		continue;
+		return t1;
 	    }
 	}
-	target0=cadr(target0);
+	for(s=caddddr(t1);s;s=cadr(s)) {    /* dependent memory sources */
+	    sz=caddr(s);
+	    if ((clist1=overlap(car(s),sz,target))) {
+		if (!cadr(t1)&&!cadr(s)) {
+		    history = list2(t,history);
+		    t = t1;
+		    clist = clist1; 
+		    goto loop;  // tail recursion
+		} else {
+		    if ((t2=circular_dependency(t1,
+				clist1,target,list2(t,history)))) {
+			return t2;
+		    }
+		}
+	    }
+	}
     }
     return 0;
 }
 
-static void remove_a(int source,int s);  // remove all child
+// static void remove_a(int source,int s);  // remove all child
 
 static void
-parallel_assign(int *target,int *source,int *processing,int *use)
+parallel_assign(int *target,int *processing,int *use)
 {
     int t,s,sz,ty,target0,s1,progress;
     while(*target) {
-	target0=*target;
 	progress = 0;
-	while(target0) {
+	for(target0=*target;target0; target0=cadr(target0)) {
 	    t=car(target0); s=cadddr(target0);
 	    sz=size(ty=caddr(target0)); 
 	    if(car(t)==car(s) && cadr(t)==cadr(s)) {
@@ -981,27 +1002,30 @@
 #if DEBUG_PARALLEL_ASSIGN
 printf("# remove same %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz);
 #endif
-		remove_target(target,t,use); remove_a((int)source,s);
+		remove_target(target,t,use);
 		progress = 1;
-	    } else if (!(s1=overlap(t,sz,*source))) {
+	    } else if (!(s1=overlap(t,sz,*target)) || 
+		    (cadr(s1)==0 && car(car(s1))==t)) {
 		/* 重なってないので安心して書き込める */
 #if DEBUG_PARALLEL_ASSIGN
+if (s1 && cadr(s1)==0)
+printf("# singleton %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz);
+else
 printf("# normal assign %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz);
 #endif
 		g_expr_u(assign_expr0(t,s,ty,ty));
-		remove_target(target,t,use); remove_a((int)source,s);
+		remove_target(target,t,use);
 		progress = 1;
-	    } else {
-		if(circular_dependency(t,s1,target,source)) {
+	    } else if((t=circular_dependency(target0,s1,*target,0))) {
+		remove_target(target,car(t),use);
+		sz=size(ty=caddr(t)); 
+		save_target(car(t),cadddr(t),target,use,sz,ty);
+		progress = 1;
 #if DEBUG_PARALLEL_ASSIGN
-    printf("# saving %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz);
+    printf("# saving %d ty %d+%d sz %d\n",car(car(t)),ty,cadr(car(t)),sz);
 #endif
-		    remove_target(target,t,use); remove_a((int)source,s);
-		    save_target(t,s,target,use,sz,ty);
-		    progress = 1;
-		}
+		break;
 	    }
-	    target0=cadr(target0);
 	}
 	if (!progress) {
 	    // can't performe parallel assign
@@ -1012,7 +1036,7 @@
 #if DEBUG_PARALLEL_ASSIGN
 printf("# can't progress save any %d ty %d+%d sz %d\n",car(s),ty,cadr(t),sz);
 #endif
-	    remove_target(target,t,use); remove_a((int)source,s);
+	    remove_target(target,t,use);
 	    save_target(t,s,target,use,sz,ty);
 	}
     }
@@ -1031,6 +1055,8 @@
     }
 }
 
+/*
+
 static int
 remove_1(int source,int e)
 {
@@ -1046,6 +1072,9 @@
 {
     contains_p1(source,s,remove_1);
 }
+*/
+
+// #define SAVE_ALL_NON_MEMORY
 
 #ifdef SAVE_ALL_NON_MEMORY
 static int
@@ -1154,29 +1183,29 @@
     int t0,s0,r,reg;
     NMTBL *code0 = 0;
     int target = 0;
-    int source = 0;
     int processing = 0;
     int use = 0;
 
     /* e1 = list4(FUNCTION,code_segment,arglist,ftype); */
 
     /* まず、サイズを計算しながら、target を決まった形に落す。 */
+    /*    list5(target,next,ty,source,source_dependency)       */
 
     arg_size = 0; regs = 0;
     fregs = 0;
     for (e3 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) {	
 	e2 = car(e3); sz = size(ty=caddr(e3)); 
 	if (scalar(ty) && (r = get_input_register_var(regs,0,1))) {
-	    target=list4(r,target,ty,e2); regs++;
+	    target=list5(r,target,ty,e2,0); regs++;
 	} else if (ty==FLOAT  && (r = get_input_dregister_var(fregs,0,1,0))) {
-	    target=list4(r, target,ty,e2); fregs++;
+	    target=list5(r, target,ty,e2,0); fregs++;
 	} else if (ty==DOUBLE && (r = get_input_dregister_var(fregs,0,1,1))) {
-	    target=list4(r, target,ty,e2); fregs++;
+	    target=list5(r, target,ty,e2,0); fregs++;
 	} else if ((ty==LONGLONG||ty==ULONGLONG) && (r = get_input_lregister_var(fregs,0,1))) {
-	    target=list4(r, target,ty,e2); regs+=2;
+	    target=list5(r, target,ty,e2,0); regs+=2;
 	} else {
 	    while(car(e2)==RSTRUCT) e2=cadr(e2);
-	    target=list4(list3(LVAR,0,0), target,ty,e2);
+	    target=list5(list3(LVAR,0,0), target,ty,e2,0);
 	}
         /* keep arg space for register variables */
         arg_size += sz;
@@ -1213,19 +1242,15 @@
 	    g_expr_u(assign_expr0((e4=list3(LVAR,new_lvar(sz),0)),s0,ty,ty));
 	    use=list3(ty,use,e1);
 	    cadddr(e2)=e4;
+	    caddddr(e2)=list3(e4,0,sz);
 	    s0=e4;
         } else if (is_same_type(t0,s0)) {
             if(cadr(t0)==cadr(s0)) {
-#if DEBUG_PARALLEL_ASSIGN
-printf("# remove same memory %d ty %d+%d sz %d\n",car(t0),ty,cadr(t0),sz);
-#endif
-                /* we should check size also (but currently useless) */
-                remove0(&target,t0);
-                /* still we keep source to avoid overwrite */
 		if(is_memory(s0)) {
-		    source=list3(s0,source,sz);
+		    caddddr(e2)=list3(s0,0,sz);
 		    continue;
-		}
+		} else
+		    error(-1);
 	    }
         }
 	if(is_memory(s0)) {
@@ -1237,37 +1262,40 @@
 printf("# division sz %d\n",sz);
 #endif
 		caddr(e2) = UNSIGNED;
-		source=list3( cadddr(e2), source,4);
+		caddddr(e2) = list3(
+			cadddr(e2)=list3(LVAR,cadr(s0),0),
+				0, size_of_int);
 #if DEBUG_PARALLEL_ASSIGN
-printf("# div 0 source %d ty %d+%d sz %d\n",car(car(source)),ty,cadr(car(source)),4);
+printf("# div 0 source %d ty %d+%d sz %d\n",car(s0),ty,cadr(s0),size_of_int);
 #endif
-		for(e4=4;e4<sz;) {
-		    cadr(e2) = list4(car(e2),cadr(e2),caddr(e2),cadddr(e2));
+		for(e4=size_of_int;e4<sz;) {
+		    cadr(e2) = list5(car(e2),cadr(e2),
+			caddr(e2),cadddr(e2),caddddr(e2));
 		    switch(sz-e4) {
 		    case 1: caddr(e2) = UCHAR; r = 1; break;
 		    case 2:
-		    case 3: caddr(e2) = USHORT; r = 2; break;
-		    default: caddr(e2) = UNSIGNED; r = 4;
+		    case 3: caddr(e2) = USHORT; r = size_of_short; break;
+		    default: caddr(e2) = UNSIGNED; r = size_of_int;
 		    }
-		    if (e4==4) e3=cadr(e2);
+		    if (e4==size_of_int) e3=cadr(e2);
 		    car(e2) =  list3(LVAR,cadr(t0)+e4,0);
-		    cadddr(e2) = list3(LVAR,cadr(s0)+e4,0);
-		    source=list3( cadddr(e2), source,r);
+		    caddddr(e2) = list3(
+			cadddr(e2) = list3(LVAR,cadr(s0)+e4,0),0, r);
 		    e4 += r;
 #if DEBUG_PARALLEL_ASSIGN
-printf("# div 1 source %d ty %d+%d sz %d\n",car(car(source)),ty,cadr(car(source)),r);
+printf("# div 1 source %d ty %d+%d sz %d\n",car(s0),ty,cadr(s0),r);
 #endif
 		}
 		e2 = e3;
 		continue;
 	    }
-	    source=list3(s0,source,sz);
+	    caddddr(e2)=list3(s0,0,sz);
 #if DEBUG_PARALLEL_ASSIGN
-printf("# source %d ty %d+%d sz %d\n",car(car(source)),ty,cadr(car(source)),sz);
+printf("# source %d ty %d+%d sz %d\n",car(s0),ty,cadr(s0),sz);
 #endif
 	} else {
 	    /* check used sources in rather complex source */
-	    source = contains_p1(source,s0,check_source);
+	    caddddr(e2)=contains_p1(0,s0,check_source);
 	}
     }
     /* compute jump address */
@@ -1287,7 +1315,7 @@
     }
 
     /* 並列代入を実行 */
-    parallel_assign(&target,&source,&processing,&use);
+    parallel_assign(&target,&processing,&use);
     while (use) {
 	reg = car(caddr(use));
 	if (reg==REGISTER||reg==FREGISTER||reg==DREGISTER||reg==LREGISTER)
@@ -2249,6 +2277,19 @@
     return code_csvalue();
 }
 
+extern void
+gen_ret()
+{
+    if (chk) return;
+    code_ret();
+}
+
+extern void
+gen_label_call(int l)
+{
+    if (chk) return;
+    code_label_call(l);
+}
 
 extern int
 fwdlabel(void)
--- a/mc-codegen.h	Thu Nov 25 16:56:26 2004 +0900
+++ b/mc-codegen.h	Sun Nov 28 03:28:38 2004 +0900
@@ -71,6 +71,8 @@
 extern void parallel_rassign(int assigns);
 extern void replace_return_struct(int func,int left);
 extern void ret(void);
+extern void gen_ret(void);
+extern void gen_label_call(int l);
 
 /* used by mc-cod-* */
 
--- a/mc-parse.c	Thu Nov 25 16:56:26 2004 +0900
+++ b/mc-parse.c	Sun Nov 28 03:28:38 2004 +0900
@@ -1857,12 +1857,13 @@
 static void
 dofor(void)
 {
-    int sbreak,scontinue,l,e,slfree,dflag=0;
-    int slimit;
-
-    sbreak=blabel;
-    scontinue=clabel;
-    slimit = lfree_type_limit;
+    int l,e,slfree,dflag=0;
+    int sbreak=blabel;
+    int slimit = lfree_type_limit;
+    int sinit_vars = init_vars; 
+    int scontinue=clabel;
+    init_vars = 0;
+
     blabel=fwdlabel();
     conv->for_();
     getsym(0);
@@ -1924,6 +1925,7 @@
     fwddef(blabel);
     clabel=scontinue;
     blabel=sbreak;
+    init_vars=sinit_vars;
 }
 
 /*
@@ -1933,6 +1935,7 @@
 docomp(int use)
 {
     int slimit = lfree_type_limit ;
+    int sinit_vars = init_vars;
     conv->lc_();
     local_decl();
     emit_init_vars();
@@ -1940,6 +1943,7 @@
     while(sym!=RC) statement(use); 
     conv->rc_();
     lfree_type_limit = slimit; 
+    init_vars = sinit_vars;
     leave_scope();
     getsym(0);
 }
@@ -2963,8 +2967,23 @@
 	    return correct_type(e1,t);
 	} else if (sym==LC) {
 	    // statement in expression  (GNU extension)
+	    //
+	    // if COMMA expr is not gexpred by !control, 
+            // l2 is not defined and generates undefined error.
+	    // cntl may prevent this.
+	    int l,b,l2,cntl=control;
+	    if (cntl) {
+		gen_jmp(l=fwdlabel());
+	    } else l = 0;
+	    b = backdef();
 	    docomp(1);
-	    e1 = lastexp; lastexp = 0;
+	    if (cntl) {
+		gen_jmp(l2=fwdlabel());
+	    } else l2 = 0;
+	    e1 = list3(COMMA,list3(LCALL,b,l2),lastexp);
+	    lastexp = 0;
+	    if (l) fwddef(l);
+	    control=cntl;
 	} else {
 	    e1=expr0();
 	    conv->rpar_();
@@ -4196,6 +4215,17 @@
 }
 
 extern int
+append5(int p,int a1,int a2,int a3,int a4)
+{
+    int p1;
+    if(!p) return list5(a1,0,a2,a3,a4);
+    p1=p;
+    while(cadr(p)) p = cadr(p);
+    cadr(p) = list5(a1,0,a2,a3,a4);
+    return p1;
+}
+
+extern int
 append4(int p,int a1,int a2,int a3)
 {
     int p1;
--- a/mc.h	Thu Nov 25 16:56:26 2004 +0900
+++ b/mc.h	Sun Nov 28 03:28:38 2004 +0900
@@ -138,26 +138,27 @@
 #define LCONST  (LOP+CONST)
 #define STRING 	8
 #define FNAME  	9
-#define LABEL  	10
+#define LCALL  	10
+#define LABEL  	11
 
-#define NULLARY_ARGS(i) (i==RETURN||i==ENVIRONMENT||i==REGISTER||i==DREGISTER||i==FREGISTER||i==LREGISTER||(GVAR<=(i%SOP)&&(i%SOP)<=LABEL))
+#define NULLARY_ARGS(i) (i==RETURN||i==ENVIRONMENT||i==LCALL||i==REGISTER||i==DREGISTER||i==FREGISTER||i==LREGISTER||(GVAR<=(i%SOP)&&(i%SOP)<=LABEL))
 
 /* unary  argments */
 
-#define ADDRESS	11
-#define MINUS  	12
-#define LNOT   	13
-#define BNOT   	14
-#define INC    	15
-#define POSTINC	16
-#define UPOSTINC       	17
-#define PREINC 	18
-#define UPREINC	19
-#define POSTDEC	20
-#define UPOSTDEC       	21
-#define PREDEC 	22
-#define UPREDEC	23
-#define DEC    	24
+#define ADDRESS	12
+#define MINUS  	13
+#define LNOT   	14
+#define BNOT   	15
+#define INC    	16
+#define POSTINC	17
+#define UPOSTINC       	18
+#define PREINC 	19
+#define UPREINC	20
+#define POSTDEC	21
+#define UPOSTDEC       	22
+#define PREDEC 	23
+#define UPREDEC	24
+#define DEC    	25
 #define CPOSTINC (COP+POSTINC)
 #define CUPOSTINC (COP+UPOSTINC)
 #define CPREINC (COP+PREINC)
@@ -182,9 +183,9 @@
 #define LPREINC (LOP+PREINC)
 #define LUPOSTINC       (LOP+UPOSTINC)
 #define LUPREINC        (LOP+UPREINC)
-#define INDIRECT       	25
-#define RINDIRECT      	26
-#define URINDIRECT     	27
+#define INDIRECT       	26
+#define RINDIRECT      	27
+#define URINDIRECT     	28
 #define CRINDIRECT      (COP+RINDIRECT)
 #define CURINDIRECT     (COP+URINDIRECT)
 #define SRINDIRECT      (SOP+RINDIRECT)
@@ -193,58 +194,58 @@
 #define DRINDIRECT      (DOP+RINDIRECT)
 #define LRINDIRECT      (LOP+RINDIRECT)
 #define LURINDIRECT     (LOP+URINDIRECT)
-#define RSTRUCT	28
-#define ALLOCA 	29
-#define BIT_FIELD 	30
-#define RBIT_FIELD 	31
-#define BPREINC 	32
-#define BPOSTINC 	33
-#define CONV   	34
+#define RSTRUCT	29
+#define ALLOCA 	30
+#define BIT_FIELD 	31
+#define RBIT_FIELD 	32
+#define BPREINC 	33
+#define BPOSTINC 	34
+#define CONV   	35
 
 #define UNARY_ARGS(i) (ADDRESS<=(i%SOP)&&(i%SOP)<=CONV)
 
 /* binary  argments */
 
-#define MUL    	35
-#define UMUL   	36
-#define DIV    	37
-#define UDIV   	38
-#define MOD    	39
-#define UMOD   	40
-#define ADD    	41
-#define SUB    	42
-#define CMP    	43      
-#define RSHIFT 	44
-#define URSHIFT	45
-#define LSHIFT 	46
-#define ULSHIFT	47
-#define GT     	48
-#define UGT    	49
-#define GE     	50
-#define UGE    	51
-#define LT     	52
-#define ULT    	53
-#define LE     	54
-#define ULE    	55
-#define EQ     	56
-#define NEQ    	57
-#define BAND   	58
-#define EOR    	59
-#define BOR    	60
-#define LAND   	61
-#define LOR    	62
-#define ASS    	63
-#define UCMP   	64
-#define UCMPGE 	65
-#define CMPGE  	66
-#define CMPEQ  	67
-#define CMPNEQ 	68
-#define ASSOP  	69
-#define COMMA  	70
+#define MUL    	36
+#define UMUL   	37
+#define DIV    	38
+#define UDIV   	39
+#define MOD    	40
+#define UMOD   	41
+#define ADD    	42
+#define SUB    	43
+#define CMP    	44      
+#define RSHIFT 	45
+#define URSHIFT	46
+#define LSHIFT 	47
+#define ULSHIFT	48
+#define GT     	49
+#define UGT    	50
+#define GE     	51
+#define UGE    	52
+#define LT     	53
+#define ULT    	54
+#define LE     	55
+#define ULE    	56
+#define EQ     	57
+#define NEQ    	58
+#define BAND   	59
+#define EOR    	60
+#define BOR    	61
+#define LAND   	62
+#define LOR    	63
+#define ASS    	64
+#define UCMP   	65
+#define UCMPGE 	66
+#define CMPGE  	67
+#define CMPEQ  	68
+#define CMPNEQ 	69
+#define ASSOP  	70
+#define COMMA  	71
 
-#define CASS   	71
-#define CASSOP 	72
-#define CUASSOP	73
+#define CASS   	72
+#define CASSOP 	73
+#define CUASSOP	74
 
 #define SASS    (SOP+CASS)
 #define SASSOP (SOP+CASSOP)
@@ -300,18 +301,18 @@
 #define LEOR    (LOP+EOR)
 #define LBOR    (LOP+BOR)
 
-#define BASS   	74
-#define BASSOP 	75
-#define BFD_REPL 	76
+#define BASS   	75
+#define BASSOP 	76
+#define BFD_REPL 	77
 
-#define STASS  	77
+#define STASS  	78
 
 
 #define BINARY_ARGS(i) (MUL<=(i%SOP)&&(i%SOP)<=STASS)
 
 /* tarnary  argments */
 
-#define COND   	78
+#define COND   	79
 #define SCOND   (SOP+COND)
 #define DCOND   (DOP+COND)
 #define FCOND   (FOP+COND)
@@ -321,35 +322,35 @@
 
 /* not appeared as tags */
 
-#define LPAR   	79
-#define RPAR   	80
-#define LBRA   	81
-#define RBRA   	82
-#define LC     	83
-#define RC     	84
-#define COLON  	85
-#define SM     	86
-#define PERIOD 	87
-#define ARROW  	88
-#define CNAME  	89
+#define LPAR   	80
+#define RPAR   	81
+#define LBRA   	82
+#define RBRA   	83
+#define LC     	84
+#define RC     	85
+#define COLON  	86
+#define SM     	87
+#define PERIOD 	88
+#define ARROW  	89
+#define CNAME  	90
 
-#define I2C  	90
-#define I2S  	91
-#define I2I    	92
-#define I2U    	93
-#define I2D    	94
-#define I2F    	95
-#define I2LL   	96
-#define I2ULL  	97
+#define I2C  	91
+#define I2S  	92
+#define I2I    	93
+#define I2U    	94
+#define I2D    	95
+#define I2F    	96
+#define I2LL   	97
+#define I2ULL  	98
 
-#define U2UC  	98
-#define U2US  	99
-#define U2I    	100
-#define U2U    	101
-#define U2D    	102
-#define U2F    	103
-#define U2LL   	104
-#define U2ULL  	105
+#define U2UC  	99
+#define U2US  	100
+#define U2I    	101
+#define U2U    	102
+#define U2D    	103
+#define U2F    	104
+#define U2LL   	105
+#define U2ULL  	106
 
 
 #define D2I     (DOP+I2I)
@@ -444,24 +445,33 @@
 extern int list2(int e1, int e2);
 extern int list3(int e1, int e2, int e3);
 extern int list4(int e1, int e2, int e3,int e4);
+extern int list5(int e1, int e2, int e3,int e4,int e5);
 extern int length(int e1);
 extern int nth(int n,int e1);
 extern int reverse0(int t1);
 extern int append4(int p,int a1,int a2,int a3);
+extern int append5(int p,int a1,int a2,int a3,int a4);
 extern int insert_ascend(int p,int e,int eq());
 
 extern void free_nptr(NMTBL *n);
 extern NMTBL *get_nptr();
 
-#define car(e) (heap[(int)(e)])
-
-#define cadr(e) (heap[((int)(e))+1])
+#if 1
+extern int heapsize;
+#define CHECK_HEAP(b) ({int _k=(int)(b);if(_k>heapsize)error(-1);_k;})
+#else
+#define CHECK_HEAP(b)  (b)
+#endif
 
-#define caddr(e) (heap[((int)(e))+2])
+#define car(e) (heap[(int)(CHECK_HEAP(e))])
+
+#define cadr(e) (heap[((int)(CHECK_HEAP(e)))+1])
 
-#define cadddr(e) (heap[((int)(e))+3])
+#define caddr(e) (heap[((int)(CHECK_HEAP(e)))+2])
 
-#define caddddr(e) (heap[((int)(e))+4])
+#define cadddr(e) (heap[((int)(CHECK_HEAP(e)))+3])
+
+#define caddddr(e) (heap[((int)(CHECK_HEAP(e)))+4])
 
 #if FLOAT_CODE
 #define dcadr(e) (*(double*)&heap[((int)(e))+1])
--- a/test/scope.c	Thu Nov 25 16:56:26 2004 +0900
+++ b/test/scope.c	Sun Nov 28 03:28:38 2004 +0900
@@ -40,6 +40,8 @@
 	    goto exit1;
 	} else
 	    goto *exit;
+	/* not reached */
+	i = ({ int k=3; k; });
 exit1:
 	printf("#0043:inner %d %d %0x\n",i,k,&&exit1==exit);
     }