changeset 313:f73b93de216a alloca

alloca done for ia32, powerpc, mips
author kono
date Tue, 15 Jun 2004 00:11:26 +0900
parents a93e619cf772
children 2e1012a8852a
files Changes mc-code-ia32.c mc-code-mips.c mc-code-powerpc.c mc-code.h mc-codegen.c mc-parse.c mc.h stdio.h test/tmp8.c
diffstat 10 files changed, 289 insertions(+), 87 deletions(-) [+]
line wrap: on
line diff
--- a/Changes	Sat Jun 12 15:58:56 2004 +0900
+++ b/Changes	Tue Jun 15 00:11:26 2004 +0900
@@ -4899,3 +4899,47 @@
      sizeof(typeof(hoge));
      ((typeof (hoge)) fuga)
 みたいな感じ。
+
+なんか g() で、register_save が出ちゃってるね。
+
+Sun Jun 13 12:20:39 JST 2004
+
+ia32 の alloca は、関数の引数に呼び出されるのはまずい。あと、
+stack の途中も、まずい。じゃぁ、どうするの?
+      a = alloca(3)+3;
+      f(i,alloca(3),j);
+みたいなのでも破綻しちゃうのね。
+
+powerpc でも結構奥が深いな。関数呼び出し時の引数は、
+r1 相対でつまないとだめ。そうだよね。というか、
+最初から r1 相対で積めよ。
+
+        lwz r2,0(r1)
+        neg r0,r0
+        stwux r2,r1,r0
+        addi r2,r1,208
+        addi r0,r2,15
+        srwi r0,r0,4
+        slwi r0,r0,4
+        stw r0,208(r30) <=== 最初のlocal 変数のアドレス。
+        b L26
+L25:
+        li r0,0
+        stw r0,208(r30)
+L26:
+
+ってわけか。
+
+うーん、
+      int i;
+      goto f(alloca(100),&i);
+なのってあるよね。だとすれば、local 変数はつぶさない方が
+いいのか。その方が簡単か。そうすると絶対に local 変数と
+goto の引数は重ならないから parallel assignment の必要
+ないし。なんで、最初からそうしなかったんだろう?
+
+しかし、そうするにはどこ直せば良いんだろう? max-func-arg?
+
+Mon Jun 14 20:48:13 JST 2004
+
+PowerPC の alloca は動いたけど...
--- a/mc-code-ia32.c	Sat Jun 12 15:58:56 2004 +0900
+++ b/mc-code-ia32.c	Tue Jun 15 00:11:26 2004 +0900
@@ -63,6 +63,7 @@
 
 static int  reg_sp;   /* REGister Stack-Pointer */
 static int reg_stack[MAX_MAX];  /* 実際のレジスタの領域 */
+int stack_depth = 0;
 
 /* floating point registers */
 
@@ -227,6 +228,7 @@
 #define __externsion__\n\
 #define __flexarr\n\
 #define wchar_t int\n\
+#define __GNUC__ 2\n\
 ";
 
 void
@@ -471,6 +473,7 @@
     if (freg_sp>0) error(-1);
     reg_sp = 0;
     freg_sp = 0;
+    stack_depth = 0;
     text_mode();
     gexpr_code_init();
     register_usage("gexpr_init");
@@ -599,6 +602,7 @@
 	if (reg_sp>=MAX_MAX) error(-1);
 	reg_stack[reg_sp++] =  -1;
 	printf("\tpushl %s\n",register_name(creg,0));
+	stack_depth += SIZE_OF_INT;
 	/* creg is used soon, don't regv[creg]=0 */
     } else {
 	reg_stack[reg_sp++] = creg;     /* push するかわりにレジスタを使う */
@@ -622,6 +626,7 @@
 }
 	printf("\tpopl %s\n",register_name(dreg,0));
 	regv[dreg]=1;
+	stack_depth -= SIZE_OF_INT;
 	return dreg;
     } else if (xreg<= -REG_LVAR_OFFSET) {
 	code_rlvar(xreg+REG_LVAR_OFFSET,dreg);
@@ -1096,6 +1101,7 @@
 	regv[xreg]=1;
     } else
 	free_register(xreg);
+    stack_depth += length*SIZE_OF_INT;
     return length/SIZE_OF_INT;
 }
 
@@ -1105,6 +1111,8 @@
     int e2,e3,e4,nargs,t,ret_type;
     NMTBL *n=0;
     int save,saved;
+    int stack_depth_save = stack_depth;
+
     ret_type = cadr(cadddr(e1));
     if (ret_type==CHAR) ret_type=INT;
 
@@ -1135,6 +1143,7 @@
 		g_expr(e4);
 		printf("\tpushl %s\n",register_name(creg,0));
 	    }
+	    stack_depth += SIZE_OF_INT;
 	} else if (t==LONGLONG||t==ULONGLONG) {
 	    if (car(e4)==LREGISTER) {
 		printf("\tpushl %s\n\tpushl %s\n",l_edx(cadr(e4)),l_eax(cadr(e4)));
@@ -1143,17 +1152,20 @@
 		printf("\tpushl %%edx\n\tpushl %%eax\n");
 	    }
 	    ++nargs;
+	    stack_depth += SIZE_OF_INT*2;
 	} else if (t==DOUBLE) {
 	    g_expr(e4);
 	    printf("\tleal\t-8(%%esp),%%esp\n\tfstpl\t(%%esp)\n");
 	    nargs += SIZE_OF_DOUBLE/SIZE_OF_INT;
 	    fregv[freg]=0;
+	    stack_depth += SIZE_OF_DOUBLE;
 	    continue;
 	} else if (t==FLOAT) {
 	    g_expr(e4);
 	    printf("\tleal\t-4(%%esp),%%esp\n\tfstps\t(%%esp)\n");
 	    nargs += SIZE_OF_FLOAT/SIZE_OF_INT;
 	    fregv[freg]=0;
+	    stack_depth += SIZE_OF_FLOAT;
 	    continue;
 	} else if (car(t)==STRUCT||car(t)==UNION) {
 	    nargs += struct_push(e4,t);
@@ -1202,10 +1214,36 @@
 	use_register(creg,REG_EAX,0);
 	fregv[freg]=0; regv[creg]=1;
     }
+    stack_depth = stack_depth_save;
     return ret_type;
 }
 
 void
+code_alloca(int e1,int reg)
+{
+    char *crn,*drn;
+    int edx;
+  
+    g_expr(list3(BAND,list3(ADD,e1,list2(CONST,15)),list2(CONST,~15))); 
+    use_int(reg);
+    if (stack_depth>0) {
+	edx = edx_setup(-1);
+	crn = register_name(reg,0);
+	drn = register_name(edx,0);
+	printf("\tmovl %%esp,%s\n",drn);
+	printf("\tsubl %s,%%esp\n",crn);
+	printf("\tmovl %%esp,%s\n",crn);
+	emit_copy(edx,creg,stack_depth,0,1,1);
+	printf("\taddl $%d,%s\n",stack_depth,register_name(creg,0));
+	edx_cleanup();
+    } else {
+	crn = register_name(reg,0);
+	printf("\tsubl %s,%%esp\n",crn);
+	printf("\tmovl %%esp,%s\n",crn);
+    }
+}
+
+void
 code_frame_pointer(int e3) {
     use_int(e3);
     printf("\tmovl %s,%%ebp\n",register_name(e3,0));
@@ -1474,9 +1512,11 @@
 oprtc(int op,int reg,int orn)
 {
     char *crn;
+    int datareg;
     use_int(reg);
     crn = register_name(reg,0);
     orn = cadr(orn);
+    datareg=(rname[reg]<MAX_DATA_REG);
 
     switch(op) {
     case LSHIFT:
@@ -1496,13 +1536,23 @@
 	printf("\tsubl $%d,%s\n",orn,crn);
 	break;
     case BAND: 
-	printf("\tandl $%d,%s\n",orn,crn);
+	if (datareg&&(orn & ~255)==~255)
+	    printf("\tandb $%d,%s\n",orn,register_name(reg,1));
+	else if (datareg&&(orn & ~65535)==~65535)
+	    printf("\tandw $%d,%s\n",orn,register_name(reg,2));
+	else
+	    printf("\tandl $%d,%s\n",orn,crn);
 	break;
     case EOR: 
 	printf("\txorl $%d,%s\n",orn,crn);
 	break;
     case BOR:
-	printf("\torl $%d,%s\n",orn,crn);
+	if (datareg&&(orn & ~255)==0)
+	    printf("\tor $%d,%s\n",orn,register_name(reg,1));
+	else if (datareg&&(orn & ~65535)==0)
+	    printf("\tor $%d,%s\n",orn,register_name(reg,2));
+	else
+	    printf("\torl $%d,%s\n",orn,crn);
 	break;
     case MUL:
     case UMUL:
@@ -2587,6 +2637,7 @@
     // e2 (operand) is on the top of the stack
     use_longlong(reg);
     opl = 0; call=0;
+    stack_depth -= SIZE_OF_INT * 2;
 
     switch(op) {
     case LLSHIFT:
@@ -2736,9 +2787,9 @@
     switch(op) {
     case LADD: opl="addl";oph="adcl"; break;
     case LSUB: opl="subl";oph="sbbl"; break;
-    case LBAND: opl=oph="andl"; break;
     case LEOR:  opl=oph="xorl"; break;
     case LBOR:  opl=oph="orl"; break;
+    case LBAND: opl=oph="andl"; break;
     default: error(-1);
     }
     printf("\t%s $%d,%s\n\t%s $%d,%s\n",opl,vl,l_eax(reg),oph,vh,l_edx(reg));
@@ -2751,6 +2802,7 @@
 
 void emit_lpush()
 {
+    stack_depth += SIZE_OF_INT * 2;
     printf("\tpushl %%edx\n\tpushl %%eax\n");
 }
 
--- a/mc-code-mips.c	Sat Jun 12 15:58:56 2004 +0900
+++ b/mc-code-mips.c	Tue Jun 15 00:11:26 2004 +0900
@@ -445,7 +445,6 @@
     lvar_address(e2,reg);
 }
 
-
 char *init_src = "\
 #define __builtin_va_list int\n\
 #define __builtin_va_start(ap,arg) ap=(((int)(&arg))+sizeof(arg))\n\
@@ -454,12 +453,14 @@
 #define __mips__ 1\n\
 #define __LITTLE_ENDIAN__ 1\n\
 #define __STDC__ 1\n\
-#define size_t int\n\
+#define __SIZE_TYPE__ int\n\
 #define __externsion__\n\
 #define __flexarr\n\
 #define __WCHAR_TYPE__ int\n\
 #define __alignof__(type) (sizeof(type)==1?1:sizeof(type)==2?2:sizeof(type)<=4?4:8)\n\
-#define __PTRDIFF_TYPE__ int
+#define __PTRDIFF_TYPE__ int\n\
+#define __GNUC__ 2\n\
+#define alloca __builtin_alloca\n\
 ";
 
 void
@@ -2220,6 +2221,22 @@
 }
 
 void
+code_alloca(int e1,int reg)
+{
+    char *crn,*grn;
+    int g;
+  
+    g_expr(list3(BAND,list3(ADD,e1,list2(CONST,15)),list2(CONST,~15))); 
+    use_int(reg);
+    g = get_register();
+    crn = register_name(reg);
+    grn = register_name(g);
+    printf("\tsubu $sp,$sp,%s\n",crn);
+    printf("\taddu %s,$sp,$L_%d\n",crn,cprestore_label);
+    free_register(g);
+}
+
+void
 code_frame_pointer(int e3) {
     use_int(e3);
 #if R1SAVE
--- a/mc-code-powerpc.c	Sat Jun 12 15:58:56 2004 +0900
+++ b/mc-code-powerpc.c	Tue Jun 15 00:11:26 2004 +0900
@@ -11,6 +11,16 @@
     0
 };
 
+char *init_src = "\
+#define __ppc__ 1\n\
+#define __BIG_ENDIAN__ 1\n\
+#define __STDC__ 1\n\
+#define __builtin_va_list int\n\
+#define __builtin_va_start(ap,arg) ap=(((int)(&arg))+sizeof(arg))\n\
+#define __builtin_va_arg(ap,type)  (*((type *)ap)++)\n\
+#define alloca __builtin_alloca\n\
+";
+
 #define TEXT_EMIT_MODE 0
 #define DATA_EMIT_MODE 1
 #define RODATA_EMIT_MODE 2
@@ -32,6 +42,7 @@
 static int code_setup;
 static int r1_offset_label;
 static int lvar_offset_label;
+static int max_func_arg_label;
 
 static int reg_save;
 static int freg_save;
@@ -294,6 +305,11 @@
     int r1_offsetv = -disp+max_func_args*SIZE_OF_INT-reg_save+r1_offset;
     printf(".set L_%d,%d\n",lvar_offset_label,lvar_offsetv);
     printf(".set L_%d,%d\n",r1_offset_label,r1_offsetv);
+    if (max_func_arg_label) {
+	printf(".set L_%d,%d\n",max_func_arg_label,max_func_args*SIZE_OF_INT+24);
+	max_func_arg_label = 0;
+    }
+
 #if 0
 printf("# function %s\n",fnptr->nm);
     l = ARG_LVAR_OFFSET;
@@ -326,7 +342,7 @@
     } else if (l<0) {  /* local variable */
 	printf("lo16(%d+L_%d)(r30)\n",FUNC_LVAR,lvar_offset_label);
     } else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
-	printf("lo16(%d)(r30)\n",CALLER_ARG);
+	printf("lo16(%d)(r1)\n",CALLER_ARG);
     } else { /* callee's arguments */
 	printf("lo16(%d+L_%d)(r30)\n",CALLEE_ARG,r1_offset_label);
     }
@@ -353,7 +369,7 @@
 	printf("la r0,ha16(%d+L_%d)(r30)\n",FUNC_LVAR,lvar_offset_label);
     } else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
 	if (CALLER_ARG>32765)
-	    printf("la r0,ha16(%d)(r30)\n",CALLER_ARG);
+	    printf("la r0,ha16(%d)(r1)\n",CALLER_ARG);
     } else { /* callee's arguments */
 	printf("la r0,ha16(%d+L_%d)(r30)\n",CALLEE_ARG,r1_offset_label);
     }
@@ -373,7 +389,7 @@
 	if (CALLER_ARG>32765)
 	    printf("lo16(%d)(r0)\n",CALLER_ARG);
 	else
-	    printf("lo16(%d)(r30)\n",CALLER_ARG);
+	    printf("lo16(%d)(r1)\n",CALLER_ARG);
     } else { /* callee's arguments */
 	printf("lo16(%d+L_%d)(r0)\n",CALLEE_ARG,r1_offset_label);
     }
@@ -391,15 +407,6 @@
     lvar(e2);
 }
 
-char *init_src = "\
-#define __ppc__ 1\n\
-#define __BIG_ENDIAN__ 1\n\
-#define __STDC__ 1\n\
-#define __builtin_va_list int\n\
-#define __builtin_va_start(ap,arg) ap=(((int)(&arg))+sizeof(arg))\n\
-#define __builtin_va_arg(ap,type)  (*((type *)ap)++)\n\
-";
-
 void
 code_init(void)
 {
@@ -1784,7 +1791,7 @@
 {
     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==LDIV||e3==LUDIV||e3==LMOD||e3==LUMOD||e3==LASSOP||e3==ALLOCA;
 }
 
 static int
@@ -1950,6 +1957,7 @@
     }
 #else
     ret_type = function_type(cadddr(e1),&dots);
+    if (caddr(cadddr(e1))==0) dots=1;
 #endif
 
     arg_assign = 0;
@@ -2180,6 +2188,28 @@
 }
 
 void
+code_alloca(int e1,int reg)
+{
+    char *crn,*grn;
+    int g;
+  
+    g_expr(list3(BAND,list3(ADD,e1,list2(CONST,30)),list2(CONST,~15))); 
+    use_int(reg);
+    g = get_register();
+    crn = register_name(reg);
+    grn = register_name(g);
+//    printf("\trlwinm r0,%s,0,0,27\n",crn);
+    printf("\tlwz %s,0(r1)\n",grn);
+    printf("\tneg %s,%s\n",crn,crn);
+    printf("\tstwux %s,r1,%s\n",grn,crn);
+//    printf("\tstw %s,0(r1)\n",grn);
+    if (!max_func_arg_label) max_func_arg_label = fwdlabel();
+    printf("\taddis r1,r1,ha16(L_%d)\n",max_func_arg_label);
+    printf("\taddi %s,r1,lo16(L_%d)\n",crn,max_func_arg_label);
+    free_register(g);
+}
+
+void
 code_frame_pointer(int e3) {
     use_int(e3);
 #if R1SAVE
--- a/mc-code.h	Sat Jun 12 15:58:56 2004 +0900
+++ b/mc-code.h	Tue Jun 15 00:11:26 2004 +0900
@@ -198,6 +198,7 @@
 
 #endif
 
+extern void code_alloca(int e,int reg);
 extern void code_arg_register(NMTBL *fnptr);
 
 extern int get_register(void);
--- a/mc-codegen.c	Sat Jun 12 15:58:56 2004 +0900
+++ b/mc-codegen.c	Tue Jun 15 00:11:26 2004 +0900
@@ -409,6 +409,9 @@
     case RSTRUCT:
 	g_expr0(e2);
 	return RSTRUCT;
+    case ALLOCA:
+	code_alloca(e2,USE_CREG);
+	return list2(POINTER,CHAR);
     case COMMA:
 	g_expr_u(e2);
 	return g_expr0(caddr(e1));
@@ -659,7 +662,7 @@
 
     /* check argments type is DOTS? */
     t = caddr(e1);
-    if (t==0 || t==DOTS) *dots = 1;
+    if (/* t==0 || */ t==DOTS) *dots = 1;
     else {
         *dots = 0;
         for(;t;t = cadr(t)) {
--- a/mc-parse.c	Sat Jun 12 15:58:56 2004 +0900
+++ b/mc-parse.c	Tue Jun 15 00:11:26 2004 +0900
@@ -319,6 +319,7 @@
     reserve("enum",ENUM);
     reserve("volatile",VOLATILE);
     reserve("typeof",TYPEOF);
+    reserve("__builtin_alloca",ALLOCA);
 
     gpc=glineno=0;
     gfree=ilabel=1;
@@ -689,7 +690,7 @@
 	getsym(0);
 	n=decl0();
 	checksym(RPAR);
-    } else if (sym == IDENT) {
+    } else if (sym == IDENT||sym==ALLOCA) {
 	n=nptr;
 	getsym(0);
     } else {
@@ -2855,6 +2856,14 @@
 	if(!scalar(type))
 	    error(TYERR);
 	return list2(LNOT,e);
+    case ALLOCA:
+	conv->prefix_(sym);
+	type=POINTER;
+	getsym(0);
+	checksym(LPAR);
+	e=expr0();
+	checksym(RPAR);
+	return list2(ALLOCA,rvalue(e));
     case SIZEOF:
 	conv->prefix_(sym);
 	if(getsym(0)==LPAR) {
--- a/mc.h	Sat Jun 12 15:58:56 2004 +0900
+++ b/mc.h	Tue Jun 15 00:11:26 2004 +0900
@@ -199,52 +199,53 @@
 #define LRINDIRECT	(LOP+RINDIRECT)
 #define LURINDIRECT	(LOP+URINDIRECT)
 #define RSTRUCT	27
-#define CONV	28
+#define ALLOCA	28
+#define CONV	29
 
 #define UNARY_ARGS(i) (ADDRESS<=(i%SOP)&&(i%SOP)<=CONV)
 
 /* binary  argments */
 
-#define MUL	29
-#define UMUL	30
-#define DIV	31
-#define UDIV	32
-#define MOD	33
-#define UMOD	34
-#define ADD	35
-#define SUB	36
-#define CMP    	37	
-#define RSHIFT	38
-#define URSHIFT	39
-#define LSHIFT	40
-#define ULSHIFT	41
-#define GT	42
-#define UGT	43
-#define GE	44
-#define UGE	45
-#define LT	46
-#define ULT	47
-#define LE	48
-#define ULE	49
-#define EQ	50
-#define NEQ	51
-#define BAND	52
-#define EOR	53
-#define BOR	54
-#define LAND	55
-#define LOR	56
-#define ASS	57
-#define UCMP	58
-#define UCMPGE	59
-#define CMPGE	60
-#define CMPEQ	61
-#define CMPNEQ	62
-#define ASSOP	63
-#define COMMA	64
+#define MUL	30
+#define UMUL	31
+#define DIV	32
+#define UDIV	33
+#define MOD	34
+#define UMOD	35
+#define ADD	36
+#define SUB	37
+#define CMP    	38	
+#define RSHIFT	39
+#define URSHIFT	40
+#define LSHIFT	41
+#define ULSHIFT	42
+#define GT	43
+#define UGT	44
+#define GE	45
+#define UGE	46
+#define LT	47
+#define ULT	48
+#define LE	49
+#define ULE	50
+#define EQ	51
+#define NEQ	52
+#define BAND	53
+#define EOR	54
+#define BOR	55
+#define LAND	56
+#define LOR	57
+#define ASS	58
+#define UCMP	59
+#define UCMPGE	60
+#define CMPGE	61
+#define CMPEQ	62
+#define CMPNEQ	63
+#define ASSOP	64
+#define COMMA	65
 
-#define CASS	65
-#define CASSOP	66
-#define CUASSOP	67
+#define CASS	66
+#define CASSOP	67
+#define CUASSOP	68
 
 #define SASS	(SOP+CASS)
 #define SASSOP (SOP+CASSOP)
@@ -301,13 +302,13 @@
 #define LBOR	(LOP+BOR)
 
 
-#define STASS	68
+#define STASS	69
 
 #define BINARY_ARGS(i) (MUL<=(i%SOP)&&(i%SOP)<=STASS)
 
 /* tarnary  argments */
 
-#define COND	69
+#define COND	70
 #define SCOND	(SOP+COND)
 #define DCOND	(DOP+COND)
 #define FCOND	(FOP+COND)
@@ -317,19 +318,19 @@
 
 /* not appeared as tags */
 
-#define I2I	70
-#define I2U	71
-#define I2D	72
-#define I2F	73
-#define I2LL	74
-#define I2ULL	75
+#define I2I	71
+#define I2U	72
+#define I2D	73
+#define I2F	74
+#define I2LL	75
+#define I2ULL	76
 
-#define U2I	76
-#define U2U	77
-#define U2D	78
-#define U2F	79
-#define U2LL	80
-#define U2ULL	81
+#define U2I	77
+#define U2U	78
+#define U2D	79
+#define U2F	80
+#define U2LL	81
+#define U2ULL	82
 
 #define D2I	(DOP+I2I)
 #define D2U	(DOP+I2U)
@@ -359,17 +360,17 @@
 #define ULL2LL	(LOP+U2LL)
 #define ULL2ULL	(LOP+U2ULL)
 
-#define LPAR	82
-#define RPAR	83
-#define LBRA	84
-#define RBRA	85
-#define LC	86
-#define RC	87
-#define COLON	88
-#define SM	89
-#define PERIOD	90
-#define ARROW	91
-#define CNAME	92
+#define LPAR	83
+#define RPAR	84
+#define LBRA	85
+#define RBRA	86
+#define LC	87
+#define RC	88
+#define COLON	89
+#define SM	90
+#define PERIOD	91
+#define ARROW	92
+#define CNAME	93
 
 /* tree node tags end */
 
--- a/stdio.h	Sat Jun 12 15:58:56 2004 +0900
+++ b/stdio.h	Tue Jun 15 00:11:26 2004 +0900
@@ -1,4 +1,4 @@
-#ifndef __micro_c__
+#ifndef __micro_c__aaa
 #include "/usr/include/stdio.h"
 long long strtoll(const char *, char **, int);
 #else
--- a/test/tmp8.c	Sat Jun 12 15:58:56 2004 +0900
+++ b/test/tmp8.c	Tue Jun 15 00:11:26 2004 +0900
@@ -4,12 +4,18 @@
 
 int f(int i,int j,int k,int *l);
 int g();
+int f1(int i,int j,int *l,int k);
+int g1(int k);
+void   f2();
 
 int
 main()
 {
     int a[0] ;
+   f2(1);
+   f2(0);
    printf("%d %d\n",g(),f(0,1,2,a));
+   printf("%d %d\n",g1(100),f1(0,1,a,2));
    return 0; 
 }
 
@@ -31,3 +37,42 @@
     if (i++ >20) return *l;
     return f(i,j,k,(int*)alloca(asize));
 }
+
+int
+g1(int k)
+{
+   int i;
+
+   char *p = ((char *)alloca(asize))+k;
+   p -= k;
+   for(i=0;i<100;i++) p[i]=i;
+   for(i=0;i<100;i++) k += p[i];
+   return k;
+}
+
+int
+f1(int i,int j,int *l,int k)
+{
+    // printf("f1 &i=%x &k=%x\n",&i,&k);
+    // printf("f1 i=%d j=%d *l=%0x k=%d\n",i,j,l,k);
+    *l = 3;
+    printf("f1 i=%d j=%d *l=%0x k=%d\n",i,j,*l,k);
+    if (i++ >20) return *l;
+    return f1(i,j,(int*)alloca(asize),k);
+}
+
+void
+f2(int k)
+{
+    int *l;
+    if (k==1)
+	l = alloca(asize);
+    else
+	l = 0;
+    printf("f2: %0x %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d\n",
+   // l,
+   0,
+0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40
+   );
+}
+