Mercurial > hg > CbC > old > device
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;