Mercurial > hg > CbC > old > device
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 + ); +} +