Mercurial > hg > CbC > old > device
changeset 258:22949117768f
Complex function argments. Struct is done. Long long is odd.
author | kono |
---|---|
date | Sat, 15 May 2004 20:07:24 +0900 |
parents | e2f5671c413d |
children | 18837238e306 |
files | Changes mc-code-ia32.c mc-code-powerpc.c mc-codegen.c mc-parse.c test/tmp7.c |
diffstat | 6 files changed, 236 insertions(+), 110 deletions(-) [+] |
line wrap: on
line diff
--- a/Changes Sat May 15 12:05:17 2004 +0900 +++ b/Changes Sat May 15 20:07:24 2004 +0900 @@ -4209,3 +4209,19 @@ でも、やっぱり、意外に複雑だよ。struct をどうするかとかさ。 +struct は、call memmove するんだけど、そいつを先にやるわけには +いかない。先にやると、その間のfunction callが壊してしまう。 +後に持って良くと、input register が壊れるので、やっぱり、 +特別扱いする必要がある。ってことは... + complex function argument + struct copy + simple arguments +っていう順番でやれば良いってことか.... うーん。 + +(うーん、でもなぁ。やるの?) + +function argument の計算で、long long register が破壊されるのは、 +なんか方法が悪いんじゃないの? 本来、lreg は値渡しできるべきだよね。 +まぁねぇ。 + +
--- a/mc-code-ia32.c Sat May 15 12:05:17 2004 +0900 +++ b/mc-code-ia32.c Sat May 15 20:07:24 2004 +0900 @@ -971,30 +971,32 @@ register_name(to,0)); break; default: - if (-MAX_COPY_LEN<length && length <0) { - for(;length<=4;length+=4,offset-=4) - emit_copy(from,to,4,offset,0,det); - for(;length<=2;length+=2,offset-=2) - emit_copy(from,to,2,offset,0,det); - if(length>0) - emit_copy(from,to,length,offset,0,det); - break; - } else if (length <=MAX_COPY_LEN) { - for(;length>=4;length-=4,offset+=4) - emit_copy(from,to,4,offset,0,det); - for(;length>=2;length-=2,offset+=2) - emit_copy(from,to,2,offset,0,det); - if(length>0) - emit_copy(from,to,length,offset,0,det); - break; - } + if (length <0) { + 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) + emit_copy(from,to,-2,offset-2,0,det); + if(length<0) + emit_copy(from,to,length,offset-1,0,det); + break; + } + } else if (length <=MAX_COPY_LEN) { + for(;length>=4;length-=4,offset+=4) + emit_copy(from,to,4,offset,0,det); + for(;length>=2;length-=2,offset+=2) + emit_copy(from,to,2,offset,0,det); + if(length>0) + emit_copy(from,to,length,offset,0,det); + break; + } +/* if (det) { -/* call bcopy g_expr(list3(FUNCTION,,); break; + } */ - } use_register(from,REG_ESI,1); use_register(to, REG_EDI,1); use_register(dreg,REG_ECX,0); @@ -1004,14 +1006,14 @@ printf("\taddl $%d,%%edi\n",-length); printf("\tstd\n\trep\n\tmovsl\n"); if(length%4) { - emit_copy(from,to,length,offset+length/4,0,det); + emit_copy(from,to,length,offset+length/SIZE_OF_INT,0,det); } } else { printf("\tmovl $%d,%%ecx\n",length/4); fix = (length/4)*4; printf("\tcld\n\trep\n\tmovsl\n"); if(length%4) { - emit_copy(from,to,length,offset+length/4,0,det); + emit_copy(from,to,length,offset+length/SIZE_OF_INT,0,det); } } }
--- a/mc-code-powerpc.c Sat May 15 12:05:17 2004 +0900 +++ b/mc-code-powerpc.c Sat May 15 20:07:24 2004 +0900 @@ -127,6 +127,8 @@ "f30","f31" }; +#define round4(i) ((i+3)&~3) + #define register_name(i) reg_name[i] #define fregister_name(i) reg_name[i] #define lregister_name_low(i) reg_name[regv_l(i)] @@ -1405,14 +1407,16 @@ printf("\tstw %s,%d(%s)\n",drn,offset,trn); break; default: - if (-MAX_COPY_LEN<length && length <0) { - for(;length<=4;length+=4,offset-=4) - emit_copy(from,to,4,offset,0,det); - for(;length<=2;length+=2,offset-=2) - emit_copy(from,to,2,offset,0,det); - if(length>0) - emit_copy(from,to,length,offset,0,det); - break; + if (length <0) { + 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) + emit_copy(from,to,-2,offset-2,0,det); + if(length<0) + emit_copy(from,to,length,offset-1,0,det); + break; + } } else if (length <=MAX_COPY_LEN) { for(;length>=4;length-=4,offset+=4) emit_copy(from,to,4,offset,0,det); @@ -1466,22 +1470,20 @@ if (length<MAX_COPY_LEN) { sreg = get_register(); if (!sreg) error(-1); srn = register_name(sreg); - code_lvar(cadr(arg),sreg); - for(count=0;length<MAX_COPY_LEN;count++,length-=SIZE_OF_INT) { - if (length==0) { - free_register(sreg); - free_register(dreg); - return count; - } else { - printf("\tlwz %s,%d(%s)\n",drn,length-SIZE_OF_INT,crn); - printf("\tstwu %s,%d(%s)\n",drn,-SIZE_OF_INT,srn); - } + code_lvar(cadr(arg),dreg); + for(count=0;count<length;count+=SIZE_OF_INT) { + printf("\tlwz %s,%d(%s)\n",srn,count,crn); + printf("\tstwu %s,%d(%s)\n",srn,count,drn); } + free_register(sreg); + free_register(dreg); + return length/SIZE_OF_INT; + } else { + code_lvar(cadr(arg),dreg); + /* downward direction copy */ + emit_copy(creg,dreg,length,0,0,1); } - code_lvar(cadr(arg),dreg); - /* downward direction copy */ - emit_copy(creg,dreg,length,0,0,1); - if (dreg) free_register(dreg); + free_register(dreg); return length/SIZE_OF_INT; } @@ -1648,10 +1650,10 @@ e3==LDIV||e3==LUDIV||e3==LMOD||e3==LUMOD; } -int -simple_args(int e3) +static int +simple_arg(int e3) { - return !contains_in_list_p(e3,not_simple_p); + return !contains_p(e3,not_simple_p); } int @@ -1697,6 +1699,89 @@ if (mode) use_reg(reg); } +static void +compute_complex_arg(int e3,int reg_arg_list,int arg) { + int t=caddr(e3); + int e4 = car(e3); + reg_arg_list = list2(arg,reg_arg_list); + g_expr_u(assign_expr0(arg,e4,t,t)); + if (car(arg)==REGISTER||car(arg)==DREGISTER|| + car(arg)==FREGISTER||car(arg)==LREGISTER) + use_input_reg(cadr(arg),1); + car(e3) = arg; +} + +static void +increment_function_arg(int e3,int *pnargs,int *preg_arg,int *pfreg_arg) { + int nargs=0,reg_arg=0,freg_arg=0; + int t=caddr(e3); + if(scalar(t)) { + nargs ++ ; reg_arg++; + } else if (t==LONGLONG||t==ULONGLONG) { + nargs ++ ; reg_arg++; + nargs ++ ; reg_arg++; + } else if (t==DOUBLE||t==FLOAT) { + if (*preg_arg<MAX_INPUT_REGISTER_VAR) { + reg_arg += 2; + } + freg_arg++; + nargs += size(t)/SIZE_OF_INT; + } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) { + nargs += round4(size(t))/SIZE_OF_INT; + } else { + error(TYERR); + nargs ++ ; + } + *pnargs += nargs; + *preg_arg += reg_arg; + *pfreg_arg += freg_arg; +} + +#define AS_SAVE 1 +#define AS_ARG 0 + +static int +get_input_arg(int t,int mode,int nargs,int reg_arg,int freg_arg) +{ + if(scalar(t)) { + if (mode==AS_SAVE) { + return get_register_var(0); + } else if (reg_arg>=MAX_INPUT_REGISTER_VAR) { + return list2(LVAR,caller_arg_offset_v(nargs)); + } else + return get_input_register_var(reg_arg,0,0); + } else if (t==LONGLONG||t==ULONGLONG) { + if (mode==AS_SAVE) { + return get_lregister_var(0); + } else if (reg_arg>=MAX_INPUT_REGISTER_VAR) { + return list2(LVAR,caller_arg_offset_v(nargs)); + } else + return get_input_lregister_var(reg_arg,0,0); + } else if (t==FLOAT) { + if (mode==AS_SAVE) { + return get_dregister_var(0,0); + } else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) { + return list2(LVAR,caller_arg_offset_v(nargs)); + } else + return get_input_dregister_var(freg_arg,0,0,0); + } else if (t==DOUBLE) { + if (mode==AS_SAVE) { + return get_dregister_var(0,1); + } else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) { + return list2(LVAR,caller_arg_offset_v(nargs)); + } else + return get_input_dregister_var(freg_arg,0,0,1); + } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) { + if (mode==AS_SAVE) { + return get_register_var(0); + } else + return list2(LVAR,caller_arg_offset_v(nargs)); + } else { + error(-1); + return get_register_var(0); + } +} + int function(int e1) { @@ -1707,6 +1792,9 @@ NMTBL *fn = 0; int jmp = 0; char *jrn; + int complex_; + int pnargs,preg_arg,pfreg_arg; + int stargs; special_lvar = -1; ret_type = cadr(cadddr(e1)); @@ -1734,6 +1822,42 @@ code_register(creg,cadr(jmp)); /* g_expr(assign_expr0(jmp,e2,INT,INT)); functions are lvalue */ } + /* first we execute complex argument to avoid interaction with + input variables */ + stargs = 0; + complex_ = 0; + nargs = reg_arg = freg_arg = arg_assign = 0; + for (e3 = e1 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) { + t=caddr(e3); + if ((e5= !simple_arg(car(e3)))) { + if (complex_) { + arg = get_input_arg(caddr(complex_),AS_SAVE, + pnargs,preg_arg,pfreg_arg); + compute_complex_arg(complex_,reg_arg_list,arg); + } + pnargs=nargs;preg_arg=reg_arg;pfreg_arg=freg_arg; + complex_ = e3; + } + if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) { + // The struct should be pushed after complex arguments. + if (e5) { // compute address only, complex_ is me now. Clear it. + complex_ = 0; + e4 = car(e3); + if (car(e4)!=RSTRUCT) error(-1); + if (!simple_arg(cadr(e4))) { + // Calculate complex struct address here. + // If simple, leave it. + arg = get_register_var(0); + g_expr_u(assign_expr0(arg,list2(ADDRESS,car(e3)),INT,INT)); + car(e3)=arg; + reg_arg_list = list2(arg,reg_arg_list); + if (car(arg)==REGISTER) use_input_reg(cadr(arg),1); + } + } + stargs = list4(e3,stargs,nargs,reg_arg); + } + increment_function_arg(e3,&nargs,®_arg,&freg_arg); + } /* now all input register vars are free */ code_save_stacks(); @@ -1741,71 +1865,48 @@ set_freg(FREG_FREGISTER,0); set_ireg(CREG_REGISTER,0); + if (complex_) { + arg = get_input_arg(caddr(complex_),AS_ARG,pnargs,preg_arg,pfreg_arg); + compute_complex_arg(complex_,reg_arg_list,arg); + } + for(stargs=reverse0(stargs);stargs;stargs = cadr(stargs)) { + e3 = car(stargs); + e4 = car(e3); + t = caddr(e3); + arg = get_input_arg(t,AS_ARG,caddr(stargs),cadddr(stargs),0); + struct_push(e4,t,arg); + } + nargs = reg_arg = freg_arg = arg_assign = 0; - for (e3 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) { + for (e3 = e1; e3; + increment_function_arg(e3,&nargs,®_arg,&freg_arg), + e3 = cadr(e3)) { + if (!(e4=car(e3))) continue; t=caddr(e3); - e4 = car(e3); + arg = get_input_arg(t,AS_ARG,nargs,reg_arg,freg_arg); if(scalar(t)) { - if (reg_arg>=MAX_INPUT_REGISTER_VAR) { - arg = list2(LVAR,caller_arg_offset_v(nargs)); - } else if (!simple_args(e3) && cadr(e3)) { - arg = get_register_var(0); - arg_assign = list2( - assign_expr0(get_input_register_var(reg_arg,0,0), - arg,t,t), - arg_assign); - } else { - arg = get_input_register_var(reg_arg,0,0); - } reg_arg_list = list2(arg,reg_arg_list); /* protect from input register free */ if (car(arg)==REGISTER) use_input_reg(cadr(arg),1); g_expr_u(assign_expr0(arg,e4,t,t)); - nargs ++ ; reg_arg++; continue; } else if (t==LONGLONG||t==ULONGLONG) { if (reg_arg>=MAX_INPUT_REGISTER_VAR) { - arg = list2(LVAR,caller_arg_offset_v(nargs)); } else if (reg_arg+1>=MAX_INPUT_REGISTER_VAR) { // half register, half memory case // put whole long long anyway - arg = list2(LVAR,caller_arg_offset_v(nargs)); arg_assign = list2( assign_expr0(r0=get_input_register_var(reg_arg,0,0), arg,INT,INT), arg_assign); use_input_reg(cadr(r0),1); - } else if (!simple_args(e3) && cadr(e3)) { - arg = get_lregister_var(0); - if (car(arg)==LREGISTER) { - // r0=get_input_lregiste... is not preserved - // we cannot mark r0 used, it consumes unused register - // but get_input_register is preserved. - arg_assign = list2( - assign_expr0(get_input_register_var(reg_arg,0,0), - list2(REGISTER,regv_h(cadr(arg))),INT,INT), - list2( - assign_expr0(get_input_register_var(reg_arg+1,0,0), - list2(REGISTER,regv_l(cadr(arg))),INT,INT), - arg_assign)); - } else { - arg_assign = list2( - assign_expr0(get_input_register_var(reg_arg,0,0), - list2(LVAR,cadr(arg)+SIZE_OF_INT),INT,INT), - list2( - assign_expr0(get_input_register_var(reg_arg+1,0,0), - list2(LVAR,cadr(arg)),INT,INT), - arg_assign)); - } } else { - arg = get_input_lregister_var(reg_arg,0,0); - use_input_reg(cadr(arg),1); + if (car(arg)==LREGISTER) + use_input_reg(cadr(arg),1); } reg_arg_list = list2(arg,reg_arg_list); g_expr_u(assign_expr0(arg,e4,t,t)); - nargs ++ ; reg_arg++; - nargs ++ ; reg_arg++; continue; } else if (t==DOUBLE||t==FLOAT) { if (reg_arg<MAX_INPUT_REGISTER_VAR) { @@ -1839,7 +1940,6 @@ list2(LVAR,special_lvar+SIZE_OF_INT), INT,INT), arg_assign); } - reg_arg += 2; } if (dots && freg_arg>=4 && freg_arg<MAX_INPUT_DREGISTER_VAR) { /* oh my god! @@ -1851,32 +1951,16 @@ get_input_dregister_var(freg_arg,0,0,1),t,t), arg_assign); } - if (freg_arg>=MAX_INPUT_DREGISTER_VAR) { - arg = list2(LVAR,caller_arg_offset_v(nargs)); - } else if (!simple_args(e3) && cadr(e3)) { - arg = get_dregister_var(0,1); - arg_assign = list2( - assign_expr0(get_input_dregister_var(freg_arg,0,0,1), - arg,t,t), - arg_assign); - } else { - arg = get_input_dregister_var(freg_arg,0,0,1); - } reg_arg_list = list2(arg,reg_arg_list); if (car(arg)==DREGISTER) use_input_reg(cadr(arg),1); /* protect from input register free */ g_expr_u(assign_expr0(arg,e4,t,t)); /* XXX */ - freg_arg++; - nargs += size(t)/SIZE_OF_INT; continue; } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) { - arg = list2(LVAR,caller_arg_offset_v(nargs)); - nargs += struct_push(e4,t,arg); continue; } else { error(TYERR); } - ++nargs; } if (max_func_args<nargs) max_func_args=nargs; for(;arg_assign;arg_assign=cadr(arg_assign)) {
--- a/mc-codegen.c Sat May 15 12:05:17 2004 +0900 +++ b/mc-codegen.c Sat May 15 20:07:24 2004 +0900 @@ -1131,7 +1131,7 @@ void sassign(int e1) { - int e2,e3,e4,sz,xreg,det; + int e2,e3,e4,sz,xreg,det,offset; /* structure assignment */ e2 = cadr(e1); /* pointer variable to the struct */ @@ -1146,12 +1146,12 @@ /* しかし、わかる場合もある */ if (car(e4)==RSTRUCT) e4=cadr(e4); if (is_same_type(e2,e4)) { - if(cadr(e2)<cadr(e4)) sz=-sz; - det=1; + if(cadr(e2)<cadr(e4)) { offset=sz; sz=-sz;} + det=1; } else { - det = 0; + det = 0; offset=0; } - emit_copy(xreg,USE_CREG,sz,0,1,det); + emit_copy(xreg,USE_CREG,sz,offset,1,det); emit_pop_free(xreg); return; }
--- a/mc-parse.c Sat May 15 12:05:17 2004 +0900 +++ b/mc-parse.c Sat May 15 20:07:24 2004 +0900 @@ -1022,6 +1022,9 @@ if (endian) n->dsp += size_of_int-size_of_short; } args += size_of_int; + } else if(type>0&&(type==UNION||type==STRUCT)) { + n->dsp = args; + args += ((sz+(size_of_int-1))&~size_of_int); } else { /* if (n->dsp==0) (argument list in ADECL is useless, type list can be found in type ) */
--- a/test/tmp7.c Sat May 15 12:05:17 2004 +0900 +++ b/test/tmp7.c Sat May 15 20:07:24 2004 +0900 @@ -3,6 +3,7 @@ int k=3; struct aa { int a[100]; } aaa,bbb; +struct bb { int b[2]; } aaa1,bbb1; void tmp(void); @@ -38,6 +39,19 @@ printf("main2 a1.a[55] %d\n",a1.a[55]); } +struct bb +main5(struct aa a1,struct bb a2) +{ + printf("main5 a1.a[99] %d\n",a1.a[99]); + printf("main5 a1.a[55] %d\n",a1.a[55]); + printf("main5 a2.b[0] %d\n",a2.b[0]); + printf("main5 a2.b[1] %d\n",a2.b[1]); + a2.b[0]=333; + a2.b[1]=555; + return a2; +} + + void main1(struct aa a1) { @@ -101,6 +115,13 @@ p = p+i; /* 47 ./a.out */ printf("%d %s\n",i,p-i+3); + aaa1.b[0]=33; + aaa1.b[1]=55; + bbb1 = main5(aaa,aaa1); + printf("main5-2 %d\n", + main5(bbb,bbb1).b[0]); + printf("main5-1 %d\n", + main5(bbb,main5(aaa,aaa1)).b[0]); return 0; }