# HG changeset patch # User kono # Date 1136566806 -32400 # Node ID c3053086f790181430e938cb41577b087f18c15f # Parent ef225b589888ccbdcacc169a7aa442f64a06c509 a little partial evaluation. diff -r ef225b589888 -r c3053086f790 Changes --- a/Changes Fri Jan 06 21:19:13 2006 +0900 +++ b/Changes Sat Jan 07 02:00:06 2006 +0900 @@ -7949,3 +7949,17 @@ PowerPC の math.h のinlcude がうまくいきません。 +Sat Jan 7 01:33:01 JST 2006 + +switch(c) で c が定数の場合は、別に作らないとだめか。 +式を持ち歩けば良いんだよね。今はレジスタを持ち歩いている +わけだけど。 + +pexpr で処理するのは、statementにcontrolがあるかどうかを +判断しなければならないので難しい。 + +inline は const をいれない状態だと、ほとんど部分計算は +ないね。flow 解析しないと。 + + + diff -r ef225b589888 -r c3053086f790 mc-codegen.c --- a/mc-codegen.c Fri Jan 06 21:19:13 2006 +0900 +++ b/mc-codegen.c Sat Jan 07 02:00:06 2006 +0900 @@ -1228,6 +1228,43 @@ return 0; } +extern int +reference(int e1) +{ + switch(car(e1)) { + case GVAR : + case CRGVAR : + case CURGVAR : + case DRGVAR : + case FRGVAR : + case LRGVAR : + case LURGVAR : + case RGVAR: + case SRGVAR : + case SURGVAR: + return list3(GVAR,cadr(e1),caddr(e1)); + case LVAR : + case CRLVAR : + case CURLVAR : + case DRLVAR : + case FRLVAR : + case LRLVAR: + case LURLVAR: + case RLVAR: + case SRLVAR : + case SURLVAR : + return list3(LVAR,cadr(e1),caddr(e1)); + case FREGISTER : + case REGISTER: + case LREGISTER: + case DREGISTER: + return e1; + break; + default: error(-1); + } + return e1; +} + static int is_memory0(int e1,int *global) { @@ -4041,6 +4078,75 @@ return(list3(op+us,e1,e2)); } +/* + arugment type of binary operator + */ +extern int +type_of_bop(int op) +{ + int us; + if (op>0) { + switch(op%200) { + case UMUL: case UDIV: case UMOD: + case URSHIFT: case ULSHIFT: + case ULT: case UCMP: case UCMPGE: case UGE: case UGT: case ULE: + us = 1; break; + case MUL: case DIV: case MOD: case ADD: case SUB: case CMP: + case RSHIFT: case LSHIFT: + case GT: case GE: case LT: case LE: case EQ: case NEQ: + case BAND: case EOR: case BOR: + case CMPGE: case CMPEQ: case CMPNEQ: + us = 0; break; + default: + return 0; + } + switch((op/200)*200 + us) { + case SOP: return SHORT; + case SOP+US: return USHORT; + case COP: return CHAR; + case COP+US: return UCHAR; + case DOP: return DOUBLE; + case FOP: return FLOAT; + case LOP: return LONGLONG; + case LOP+US: return ULONGLONG; + case US: return UNSIGNED; + case 0: return INT; + } + } + return 0; +} + +/* + type of result of conversion operator + */ +extern int +type_of_conv(int op) +{ + switch(op) { + case LL2D: case ULL2D: case F2D: case I2D: case U2D: + return DOUBLE; + case LL2F: case ULL2F: case D2F: case I2F: case U2F: + return FLOAT; + case LL2I: case ULL2I: case D2I: case F2I: + case I2C: case I2S: + return INT; + case D2LL: case F2LL: case I2LL: case U2LL: + return LONGLONG; + case D2ULL: case F2ULL: case I2ULL: case U2ULL: + return ULONGLONG; + case LL2U: case ULL2U: case D2U: case F2U: + case U2UC: case U2US: + return UNSIGNED; + } + return 0; +} + +extern int +op_of(int op) +{ + return (op%200); +} + /* coarse for function/code segments arguments */ extern int diff -r ef225b589888 -r c3053086f790 mc-codegen.h --- a/mc-codegen.h Fri Jan 06 21:19:13 2006 +0900 +++ b/mc-codegen.h Sat Jan 07 02:00:06 2006 +0900 @@ -80,6 +80,10 @@ /* used by mc-inline */ extern void checkjmp(int l); // generate delayed jump, l = current label +extern int reference(int e1); // recover lvalue from rvalue of memory or register +extern int type_of_bop(int op); +extern int type_of_conv(int op); +extern int op_of(int op); /* used by mc-code-* */ diff -r ef225b589888 -r c3053086f790 mc-inline.c --- a/mc-inline.c Fri Jan 06 21:19:13 2006 +0900 +++ b/mc-inline.c Sat Jan 07 02:00:06 2006 +0900 @@ -367,7 +367,7 @@ */ static int -p_vartable(int e,int adisp,int ldisp) +p_vartable(int adisp,int ldisp) { int i; int pvartable = getfree(adisp-ldisp); // have to be local heap @@ -449,22 +449,24 @@ static int p_conv(int e1,int e2) { + int t; + if (is_const(e2) && (t=type_of_conv(e1))) { + return correct_type(e2,t); + } return list3(CONV,pexpr(e2),e1); } static int pbinop(int op,int e1,int e2) { - // we should call binop here, but we don't know the type... - int e = pexpr(e1); - return list3(op,e,pexpr(e2)); -} - -static int -prexpr(int op,int e1,int e2) -{ - int e = pexpr(e1); - return list3(op,e,pexpr(e2)); + e1 = pexpr(e1); + e2 = pexpr(e2); + if (is_const(e1)&&is_const(e2)) { + int t; + if((t= type_of_bop(op))) + return binop(op_of(op),e1,e2,t,t); + } + return list3(op,e1,e2); } static int @@ -871,6 +873,7 @@ return paddress(e1); case MINUS: if ((e3 = pexpr(e2))==e2) return e1; + if ((e3 = pexpr(e2))==e2) return e1; if (car(e3)==CONST) return list2(CONST,-cadr(e3)); return list2(car(e1),e3); #if LONGLONG_CODE @@ -904,7 +907,7 @@ case PREINC: case UPREINC: if ((e3 = pexpr(e2))==e2) return e1; - if (car(e3)==CONST) return list2(CONST,cadr(e3)+1); + if (car(e3)==CONST) return list2(CONST,cadr(e3)+caddr(e1)); return list4(car(e1),e3,caddr(e1),cadddr(e1)); case POSTINC: case UPOSTINC: @@ -965,6 +968,21 @@ case LADD: case LSUB: case LBAND: case LEOR: case LBOR: case LCMP: #endif return pbinop(car(e1),e2,caddr(e1)); +// relational operator + case GT: case UGT: case GE: case UGE: case LT: + case ULT: case LE: case ULE: + case LOP+GT: case LOP+UGT: case LOP+GE: case LOP+UGE: case LOP+LT: + case LOP+ULT: case LOP+LE: case LOP+ULE: + case DOP+GT: case DOP+GE: case DOP+LT: case DOP+LE: + case FOP+GT: case FOP+GE: case FOP+LT: case FOP+LE: + case FOP+EQ: case FOP+NEQ: + case EQ: case NEQ: case DOP+EQ: case DOP+NEQ: + case LOP+EQ: case LOP+NEQ: + return pbinop(car(e1),e2,caddr(e1)); + case LAND: + return pland(car(e1),cadr(e1),caddr(e1)); + case LOR: + return plor(car(e1),cadr(e1),caddr(e1)); case LCOND: case DCOND: case FCOND: case COND: case UCOND: case LUCOND: e2 = pexpr(e2); if (car(e2)==CONST) return @@ -1001,21 +1019,6 @@ case ENVIRONMENT: case LCALL: return e1; -// relational operator - case GT: case UGT: case GE: case UGE: case LT: - case ULT: case LE: case ULE: - case LOP+GT: case LOP+UGT: case LOP+GE: case LOP+UGE: case LOP+LT: - case LOP+ULT: case LOP+LE: case LOP+ULE: - case DOP+GT: case DOP+GE: case DOP+LT: case DOP+LE: - case FOP+GT: case FOP+GE: case FOP+LT: case FOP+LE: - case FOP+EQ: case FOP+NEQ: - case EQ: case NEQ: case DOP+EQ: case DOP+NEQ: - case LOP+EQ: case LOP+NEQ: - return prexpr(car(e1),cadr(e1),caddr(e1)); - case LAND: - return pland(car(e1),cadr(e1),caddr(e1)); - case LOR: - return plor(car(e1),cadr(e1),caddr(e1)); #if BIT_FIELD_CODE case RBIT_FIELD: return prbit_field(e1); @@ -1057,9 +1060,103 @@ return VOID; } -#define round4(i) ((i+(SIZE_OF_INT-1))&~(SIZE_OF_INT-1)) +static int +replace_inline_parameter(NMTBL *anptr,int t,int e4,int narg,int evals) +{ + int arg; + if (has_attr(anptr,KONST) && !has_attr(anptr,HAS_ADDRESS)) { + if (is_memory(e4)) { + heap[pdisp+narg]=reference(e4); + return evals; + } else if (is_const(e4)) { + heap[pdisp+narg]=e4; + return evals; + } + } + arg = heap[pdisp+narg]=list3(LVAR,new_lvar(size(t)),0); + inline_lvars = glist2(arg,inline_lvars); + evals=list2(assign_expr0(arg,e4,anptr->ty,t),evals); + return evals; +} + +/* + setup parameter replacement of inline call + */ + +static void +enter_inline(NMTBL *n, int e) +{ + int e1 = attr_value(n,INLINE); + int arg_disp = cadr(e1); // number of arguments + int narg,e3,e4, e5, fargtype; + int evals = 0; + int t; + NMTBL *anptr; + + fnptr = n; // st_return see this + pvartable = p_vartable(arg_disp, /* number of arg */ + caddr(e1) /* number of local parameter */); + + /* function arguments type */ + fargtype = n->dsp; // we cannot do destruct reverse here -// extern int lreg_count; + /* inline function arguments */ + narg = 0; + if (!fargtype) { + goto no_args; // wrong number of arguments + } + for (e3 = e5 = reverse0(caddr(e)); e3; e3 = cadr(e3)) { + anptr = (NMTBL*)caddr(fargtype); + if (!anptr) break; // should not happen? + t=caddr(e3); // type + e4 = car(e3); + evals = replace_inline_parameter(anptr,t,e4,narg,evals); + narg ++; + fargtype = cadr(fargtype); + } + caddr(e) = reverse0(e5); // make it normal + if (eval_order==NORMAL) evals = reverse0(evals); + for(;evals;evals=cadr(evals)) { + g_expr_u(car(evals)); + } +no_args: + return; +} + +/* + pass local static variable list to our parents + clean up and free used inline parameters + */ + +static void +leave_inline(int e1) +{ + NMTBL *n; + NMTBL *local_statics = (NMTBL*)cadddr(e1); // local static list + + if (retcont) error(STERR); // inline can't handle return/environment + + if (local_statics && local_statics != &null_nptr) { + // append our local static variables to the parent list + n = local_statics; + while(n->next != &null_nptr) n=n->next; + n->next = local_static_list; local_static_list = local_statics; + cadddr(e1) = 0; // prevent duplicate initialize + } + while(inline_lvars) { + int e; + int l = car(inline_lvars); + switch(car(l)) { + case LVAR: free_lvar(cadr(l)); break; + case REGISTER: case DREGISTER: + case FREGISTER: case LREGISTER: + free_register(cadr(l)); + } + e = cadr(inline_lvars); + free_glist2(inline_lvars); + inline_lvars = e; + } +} extern int gen_inline(int e) @@ -1077,17 +1174,11 @@ int slfree; // int slreg_count=lreg_count; - int narg,arg; NMTBL *n = (NMTBL*)cadr(cadr(e)); int e1 = attr_value(n,INLINE); int parse = car(e1); // inline parse tree - int arg_disp = cadr(e1); // number of arguments - NMTBL *local_statics = (NMTBL*)cadddr(e1); // local static list - int e2,e3,t,e4,e5,dots; + int dots; int ret_type = function_type(cadddr(e),&dots); - int fargtype; - int evals = 0; - NMTBL *anptr; checkret(); checkjmp(-1); @@ -1112,86 +1203,26 @@ inline_lvars = 0; retlabel = fwdlabel(); - enter_scope(); // to make label scope happy - - fnptr = n; // st_return see this - pvartable = p_vartable(e,arg_disp,caddr(e1)); - - /* function arguments type */ - fargtype = n->dsp; // we cannot do destruct reverse here + enter_inline(n,e); - /* inline function arguments */ - narg = 0; - if (!fargtype) { - goto no_args; // wrong number of arguments - } - for (e3 = e5 = reverse0(caddr(e)); e3; e3 = cadr(e3)) { - anptr = (NMTBL*)caddr(fargtype); - if (!anptr) break; // should not happen? - t=caddr(e3); // type - e4 = car(e3); - if ((has_attr(anptr,KONST) && !has_attr(anptr,HAS_ADDRESS)&& - (is_const(e4) || (0 && is_memory(e4))))) { - if (is_memory(e4)) - heap[pdisp+narg]=rvalue_t(e4,t); - else - heap[pdisp+narg]=e4; - } else { - arg = heap[pdisp+narg]=list3(LVAR,new_lvar(size(t)),0); - inline_lvars = glist2(arg,inline_lvars); - // should contain correct argument variable name - // if (anptr) printf("## var %s\n",anptr->nm); - // else printf("## var 0\n"); - if (eval_order==REVERSE) { - evals=list2(assign_expr0(arg,e4,anptr->ty,t),evals); - } else - g_expr_u(assign_expr0(arg,e4,anptr->ty,t)); - } - narg ++; - fargtype = cadr(fargtype); - } - caddr(e) = reverse0(e5); // make it normal - if (eval_order==REVERSE) { - for(;evals;evals=cadr(evals)) { - g_expr_u(car(evals)); - } - } -no_args: - e2 = pexpr(parse); + // partial evaluation of parse tree + // constant propergation, etc. + parse = pexpr(parse); pdisp = sdisp; pvartable = svartable; + // generate code if necessary if (ret_type!=VOID) - g_expr0(e2); + g_expr0(parse); else - g_expr_u(e2); + g_expr_u(parse); + checkret(); fwddef(retlabel); control=1; - if (retcont) error(STERR); // inline can't handle return/environment + leave_inline(e1); - leave_scope(); - if (local_statics && local_statics != &null_nptr) { - // append our local static variables to the parent list - n = local_statics; - while(n->next != &null_nptr) n=n->next; - n->next = local_static_list; local_static_list = local_statics; - cadddr(e1) = 0; // prevent duplicate initialize - } - while(inline_lvars) { - int e; - int l = car(inline_lvars); - switch(car(l)) { - case LVAR: free_lvar(cadr(l)); break; - case REGISTER: case DREGISTER: - case FREGISTER: case LREGISTER: - free_register(cadr(l)); - } - e = cadr(inline_lvars); - free_glist2(inline_lvars); - inline_lvars = e; - } fnptr = sfnptr; retlabel = sretlabel; retcont = sretcont; @@ -1201,10 +1232,6 @@ inline_lvars = sinline_lvars; lfree=slfree; -// if (slreg_count!=lreg_count && lreg_count>0) { -// printf("## lreg_count %d != %d\n", slreg_count,lreg_count); -// } - return ret_type; }