changeset 557:c3053086f790

a little partial evaluation.
author kono
date Sat, 07 Jan 2006 02:00:06 +0900
parents ef225b589888
children 528fed826f17
files Changes mc-codegen.c mc-codegen.h mc-inline.c
diffstat 4 files changed, 260 insertions(+), 109 deletions(-) [+]
line wrap: on
line diff
--- 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 解析しないと。
+
+
+
--- 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
--- 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-* */
 
--- 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;
 }