diff mc-codegen.c @ 681:e16b34f2b386 decl-data-tree

DECL_DATA has parse tree now.
author kono
date Mon, 01 Oct 2007 01:01:47 +0900
parents 5e71527f9fd6
children 639db8597a58
line wrap: on
line diff
--- a/mc-codegen.c	Sun Jul 29 23:09:38 2007 +0900
+++ b/mc-codegen.c	Mon Oct 01 01:01:47 2007 +0900
@@ -60,6 +60,7 @@
 static int register_to_lvar(int e);
 static void remove0(int *parent,int e) ;
 static void sassign(int e1);
+static int gen_decl_data(int e);
 
 #if FLOAT_CODE
 
@@ -292,7 +293,7 @@
     case ARRAY:
 	if (chk==2) {
 	    g_expr0(e2);
-	    t = g_expr0(caddr(e1));
+	    g_expr0(caddr(e1));
 	    code_gexpr(e1);
 	    return t;
 	}
@@ -575,7 +576,6 @@
 	code_environment(USE_CREG);
 	return ADDRESS;
     case LCALL:
-	// we cannot trust register variable either...
 	code_save_stacks();
 	gen_jmp(e2);
 	fwddef(caddr(e1));
@@ -601,6 +601,13 @@
         /*        asm    in (str) out (str) opt(str)   expr */
 	return VOID;
 #endif
+    case CAST:
+	type = cadddr(e1);
+	e2 = correct_type(e2,caddr(e1));
+	continue;
+    case DECL_DATA:
+	e1 =  gen_decl_data(e1);
+	return e1;
     case ST_DECL:         st_decl(e1);	break;
     case ST_IF:           st_if(e1);	break;
     case ST_DO:           st_do(e1);	break;
@@ -2823,30 +2830,31 @@
 contains_p(int e,int (*p)(int))
 {
     while(e) {
-	if (!car(e)) return 0;
-	if (p(car(e))) return 1;
-	if (LIST_ARGS(car(e))){
+	int e1 = car(e);
+	if (!e1) return 0;
+	if (p(e1)) return 1;
+	if (LIST_ARGS(e1)){
         /* list arguments */
 	    return contains_in_list_p(caddr(e),p);
-	} else if (UNARY_ARGS(car(e))) {
+	} else if (UNARY_ARGS(e1)) {
         /* unary operators */
 	    e = cadr(e);
 	    continue;
-	} else if (BINARY_ARGS(car(e))) {
+	} else if (BINARY_ARGS(e1)) {
         /* biary operators */
 	    if (contains_p(cadr(e),p)) return 1;
 	    e = caddr(e);
 	    continue;
-	} else if (TERNARY_ARGS(car(e))) {
+	} else if (TERNARY_ARGS(e1)) {
         /* tarary operators */
 	    if (contains_p(cadr(e), p)) return 1;
 	    if (contains_p(caddr(e),p)) return 1;
 	    e = cadddr(e);
 	    continue;
-	} else if (NULLARY_ARGS(car(e))) {
+	} else if (NULLARY_ARGS(e1)) {
         /* nullary operators */
 	    return 0;
-	} else if (IS_STATEMENT(car(e))) {
+	} else if (IS_STATEMENT(e1)) {
 	    return 1;  // may contain anything
 	} else {
 	    // if (lsrc)fprintf(stderr,"Unknown Tree ID %d\n",car(e));
@@ -2873,30 +2881,31 @@
 contains_p1(int arg,int e,int (*p)(int,int))
 {
     while(e) {
-	if (!car(e)) return arg;
-	if (LIST_ARGS(car(e))){
+	int e1 = car(e);
+	if (!e1) return arg;
+	if (LIST_ARGS(e1)){
         /* list arguments */
 	    return contains_in_list_p1(arg,caddr(e),p);
-	} else if (UNARY_ARGS(car(e))) {
+	} else if (UNARY_ARGS(e1)) {
         /* unary operators */
 	    e = cadr(e);
 	    continue;
-	} else if (BINARY_ARGS(car(e))) {
+	} else if (BINARY_ARGS(e1)) {
         /* biary operators */
 	    arg=contains_p1(arg,cadr(e),p);
 	    e = caddr(e);
 	    continue;
-	} else if (TERNARY_ARGS(car(e))) {
+	} else if (TERNARY_ARGS(e1)) {
         /* tarary operators */
 	    arg=contains_p1(arg,cadr(e), p);
 	    arg=contains_p1(arg,caddr(e),p);
 	    e = cadddr(e);
 	    continue;
-	} else if (NULLARY_ARGS(car(e))) {
+	} else if (NULLARY_ARGS(e1)) {
         /* nullary operators */
 	    arg=p(arg,e);
 	    return arg;
-	} else if (IS_STATEMENT(car(e))) {
+	} else if (IS_STATEMENT(e1)) {
 	    return arg;
 	} else {
 	    // if (lsrc)fprintf(stderr,"Unknown Tree ID %d\n",car(e));
@@ -3433,7 +3442,7 @@
 	return;
     }
     while(e) {
-	gexpr(car(e),0);
+	g_expr_u(car(e));
 	e = cadr(e);
     }
 }
@@ -3523,6 +3532,160 @@
     error(INERR);
 }
 
+static int gen_decl_data0(NMTBL *nptr0,int target_type,int init,int offset);
+
+extern int
+gen_delayed_decl_data(NMTBL *n,int offset)
+{
+    int offset0=0;
+    int e;
+    int t,sz,offset1=0;
+    int init = decl_str_init;
+
+    decl_str_init = 0;
+    sz = size(n->ty);
+    /*
+         decl_str_init
+            output delayed decl data
+         list4(offset,next,expression,list2(type0,type1));
+     */
+    while (init) {
+        offset= car(init);
+        e=caddr(init);
+        t=car(cadddr(init));
+        if (offset!=offset0) {
+            // make space
+            assign_data(list2(CONST,offset-offset0),EMPTY,n,offset0);
+        }
+        type=cadr(cadddr(init));
+	offset0 = gen_decl_data0(n,t,e,offset);
+        init = cadr(init);
+    }
+    offset = offset0;
+    if ((sz=(offset1+sz-offset))>0)
+        assign_data(list2(CONST,sz),EMPTY,n,offset0);
+    decl_str_init = 0;
+    local_nptr = 0;
+    return offset;
+}
+
+static int
+gen_decl_data_array(NMTBL *nptr0,int init,int target_type,int offset)
+{
+    int type0 = cadr(target_type);  /* array item type */
+    int e;
+
+    for(; init; init = cadr(init)) {
+        // unordered data with tag or array offset
+        if (car(init)!=DECL_DATA_ARRAY) {
+                error(-1);
+        }
+        e = pexpr(caddr(init));
+        offset = gen_decl_data0(nptr0,type0,e,offset);
+    }
+    return offset;
+}
+
+static int
+gen_decl_data_field(NMTBL *nptr0,int init,int target_type,int offset)
+{
+    int type0 = target_type;  /* list of fields */
+    int e,t,type1,foffset;
+    NMTBL *n;
+
+    for(; init; init = cadr(init)) {
+        // unordered data with tag or array offset
+        if (car(init)!=DECL_DATA_FIELD) {
+                error(-1);
+        }
+        n = (NMTBL*)cadddr(init);
+        type1 = search_struct_type(type0,n->nm,&foffset);
+        e = caddr(init);
+        if (car(e)!=DECL_DATA) error(-1);
+        t = caddr(e);
+        decl_str_init=insert_ascend(decl_str_init,
+            glist4(offset+foffset,0,e,glist2(type1,t)),str_init_eq);
+    }
+    return offset;
+}
+
+static int
+gen_decl_data_list(NMTBL *nptr0,int init,int target_type,int offset)
+{
+    int type0 = caddr(target_type);  /* list of fields */
+    int e;
+
+    for(; init; init = cadr(init)) {
+        // ordered data
+        if (car(init)!=DECL_DATA_LIST) {
+                error(-1);
+        }
+        e = caddr(init);
+        offset = gen_decl_data0(nptr0,car(type0),e,offset);
+        type0 = cadr(type0);
+    }
+    return offset;
+}
+
+
+static int
+gen_decl_data0(NMTBL *nptr0,int target_type,int init,int offset)
+{
+    int e,t;
+    if (car(init)==DECL_DATA) {
+        switch( car(e=cadr(init))) {
+        case DECL_DATA_LIST:
+            offset = gen_decl_data_list(nptr0,e,target_type,offset);
+            break;
+        case DECL_DATA_FIELD:
+            offset = gen_decl_data_field(nptr0,e,target_type,offset);
+            break;
+        case DECL_DATA_ARRAY:
+            offset = gen_decl_data_array(nptr0,e,target_type,offset);
+            break;
+        default:
+            t = caddr(init);       // type of source
+	    e = rvalue_t(e,t);
+	    offset=assign_data(e,t,nptr0,offset);
+        }
+    } else {
+        error(-1);
+    }
+    if (decl_str_init) {
+	offset = gen_delayed_decl_data(nptr0,offset);
+    }
+    return offset;
+}
+
+static int
+gen_decl_data(int e)
+{
+    NMTBL *nptr0;
+    int t = caddr(e);
+    int e1,sz;
+    int offset = 0;
+    int sinit_vars = init_vars;
+    init_vars = 0;
+
+    nptr0 = get_nptr(); 
+    nptr0->nm = "";
+    nptr0->sc = LVAR;
+    nptr0->attr = 0;
+    type = nptr0->ty = t;
+    sz = size(type);
+    nptr0->dsp = new_lvar_align(sz,16);
+
+    e1 = list3(RSTRUCT,list3(
+	nptr0->sc,nptr0->dsp,(int)nptr0),sz);
+
+    gen_decl_data0(nptr0,t,e,offset);
+
+    if (init_vars) emit_init_vars();
+    g_expr0(e1);
+    init_vars = sinit_vars;
+    return type;
+}
+
 //
 // local variable initialization
 //
@@ -3532,6 +3695,7 @@
 {
     int ass,sz,bfd;
 
+    if (inmode) error(-1);
 #if STRUCT_ALIGN
     if (t!=-99) {
 	int strtype=0;
@@ -3550,10 +3714,20 @@
 	    error(TYERR);
 	}
     }
-    if(mode==GDECL) {
+    switch (mode) {
+    case GDECL:
 	if (!is_const(e)) error(INERR);
  	emit_data(e,t,n);
-    } else if(mode==LDECL || (mode==STADECL&&local_nptr&&(n=local_nptr))) {
+	break;
+    case STADECL:
+	if (!local_nptr) {
+	    if (!is_const(e)) error(INERR);
+	    else emit_data(e,t,n);
+	    break;
+	}
+	n = local_nptr;
+    case LDECL:
+    case STAT:               // inline case
 	if (t==EMPTY) {
 	    /* empty space in partial initialization */
 	    return offset+cadr(e);
@@ -3569,16 +3743,15 @@
     (n->sc==REGISTER||n->sc==DREGISTER||n->sc==FREGISTER||n->sc==LREGISTER)?
 		list3(n->sc,n->dsp,(int)n):
 		list3(n->sc,n->dsp+offset,(int)n),
-	e,t,type);
+	    e,t,type);
 	init_vars = list2(ass,init_vars);
-    } else if(mode==STADECL) {
-	if (!is_const(e)) error(INERR);
-	else emit_data(e,t,n);
-    } else if(mode==SFDINIT) {
+	break;
+    case SFDINIT:
 // if (lsrc)printf("## %d sfdinit c0(e)=%d type=%d t=%d offset=%d\n",lineno,car(e),type,t,offset);
 	decl_str_init=insert_ascend(decl_str_init,
 		glist4(offset,0,e,glist2(t,type)),str_init_eq);
-    } else {
+	break;
+    default:
 	error(DCERR);
 	return offset;
     }
@@ -3605,8 +3778,6 @@
     int offset0=0;
     int e;
     int t,sz,offset1=0;
-    int smode=mode;
-    mode = STADECL;
     sz = size(n->ty);
     /*
          decl_str_init
@@ -3631,14 +3802,15 @@
         assign_data(list2(CONST,sz),EMPTY,n,offset0);
     decl_str_init = 0;
     local_nptr = 0;
-    mode=smode;
 }
 
 extern void
 data_closing(NMTBL *n)
 {
     if (!chk) {
+	int smode = mode; mode = STADECL;
 	if (decl_str_init) flush_delayed_decl_data(n);
+	mode = smode;
 	emit_data_closing(n);
     }
 }
@@ -3779,22 +3951,29 @@
     }
 }
 
-static void
-compatible(int t1, int t2)
+extern int
+type_compatible(int t1, int t2)
 {
     t1 = type_value(t1);
     t2 = type_value(t2);
     if(integral(t1)) {
-	    if(t1!=t2) error(TYERR);
+	    if(t1!=t2) return 0;
     }
     else if(t1<0 || t2<0) {
-	if(t1!=t2) error(TYERR);
+	if(t1!=t2) return 0;
     } else if(car(t1)!=car(t2))
-	    error(TYERR);
+	    return 0;
     else if((car(t1)==STRUCT || car(t1)==UNION) && cadr(t1)!=cadr(t2))
-	    error(TYERR);
+	    return 0;
     else if(car(t1)==POINTER || car(t1)==ARRAY ||car(t1)==FUNCTION)
-	    compatible(cadr(t1),cadr(t2));
+	    return type_compatible(cadr(t1),cadr(t2));
+    return 1;
+}
+
+static void
+compatible(int t1, int t2)
+{
+    if (!type_compatible(t1,t2)) error(TYERR);
 }
 
 extern int
@@ -4070,7 +4249,7 @@
 {
     int dsp = 0;
     int type0;
-    int e1 = 0;
+    int e1;
 
     if (inmode || chk) {
 	e1 = list4(ind?ARROW:PERIOD,e,(int)nptr,type);
@@ -4086,7 +4265,7 @@
     /* type = list4(s,disp,fields,tag_nptr); */
     /* print_fields(caddr(type),"strop"); */
     type = search_struct_type(type,nptr->nm,&dsp);
-    if (!type) { error(TYERR); type=INT; return e; }
+    if (!type) { error(UFLDERR); type=INT; return e; }
     if (inmode || chk) {
 	// bitfield will be checked after parse
 	return e1;