# HG changeset patch # User kono # Date 1084619244 -32400 # Node ID 22949117768f21343d10a50819d50cceb711b999 # Parent e2f5671c413d74f68c4edd477de038e3c5883379 Complex function argments. Struct is done. Long long is odd. diff -r e2f5671c413d -r 22949117768f Changes --- 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 は値渡しできるべきだよね。 +まぁねぇ。 + + diff -r e2f5671c413d -r 22949117768f mc-code-ia32.c --- 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_LEN0) - 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); } } } diff -r e2f5671c413d -r 22949117768f mc-code-powerpc.c --- 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_LEN0) - 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=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=4 && 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_argsdsp += 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 ) */ diff -r e2f5671c413d -r 22949117768f test/tmp7.c --- 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; }