#include "minicomp.h" #define clone_type clone_typ #define free_type freetyp #define new_icode new_IC #define add_icode add_IC #define free_all_icode() free_IC(first_ic) #define get_first_icode() first_ic typedef struct IC icode; static int errors; var *store_locals; struct rpair rp; char *copyright="minicomp/vbcc (c) in 2002 Volker Barthelmann"; char *inname,*outname; struct struct_declaration *first_sd; struct Var *first_ext,*merk_varf; char **target_macros; FILE *out; void raus(void) { var *v; for(v=first_var[0];v;v=v->next) if(v->type->flags!=FUNCTION){ gen_align(out,falign(v->type)); gen_var_head(out,v->vbccvar); gen_ds(out,szof(v->type),v->type); } cleanup_cg(out); if(errors>0) exit(EXIT_FAILURE); else exit(EXIT_SUCCESS); } main(int argc,char **argv) { int i,j,flag; type *nt; for(i=1;i0&&!strncmp(argv[i]+1,g_flags_name[j],l)){ flag=1; if((g_flags[j]&(USEDFLAG|FUNCFLAG))==USEDFLAG){error(19,"multiple option");break;} g_flags[j]|=USEDFLAG; if(g_flags[j]&STRINGFLAG){ if(argv[i][l+1]!='='){error(21,"string expected");} if(argv[i][l+2]||i>=argc-1) g_flags_val[j].p=&argv[i][l+2]; else g_flags_val[j].p=&argv[++i][0]; } if(g_flags[j]&VALFLAG){ if(argv[i][l+1]!='='){error(20,"value expected");} if(argv[i][l+2]||i>=argc-1) g_flags_val[j].l=atol(&argv[i][l+2]); else g_flags_val[j].l=atol(&argv[++i][0]); } if(g_flags[j]&FUNCFLAG) g_flags_val[j].f(&argv[i][l+1]); } } if(!flag) error(23,"unknown option"); } } if(!inname) error(22,"no input file"); infile=fopen(inname,"r"); if(!infile) error(18,"could not open output file"); if(!outname) error(23,"no output file"); out=fopen(outname,"w"); if(!out){ error(24,"could not open input file"); } nt=new_type(FUNCTION); nt->next=new_type(INT); add_var("readInt",clone_type(nt)); add_var("writeInt",clone_type(nt)); add_var("writeChar",clone_type(nt)); add_var("readChar",clone_type(nt)); add_var("writeReal",nt); nt=new_type(FUNCTION); nt->next=new_type(REAL); add_var("readReal",nt); stackalign=l2zm(0L); if(!init_cg()) exit(EXIT_FAILURE); if(zmeqto(stackalign,l2zm(0L))) stackalign=maxalign; for(i=0;iflags=t; new->next=0; return new; } type *new_array(type *t,node *p) { type *new=new_typ(); simplify_tree(p); if(p->flags!=NNUMBER) error(3,"array size not a constant"); if(p->type->flags!=INT) error(4,"array size not an integer"); new->flags=ARRAY; new->next=t; new->size=l2zm((long)p->ivalue); free_tree(p); return new; } int nesting; int local_offset,parm_offset,framesize; #define MAXNESTING 128 var *first_var[128]; void free_varlist(var *v) { var *m; while(v){ free_var(v->vbccvar); m=v->next; free(v); v=m; } } void enter_block() { nesting++; first_var[nesting]=0; push_int(local_offset); } void leave_block() { if(first_var[nesting]){ var *p=first_var[nesting]; while(p->next) p=p->next; p->next=store_locals; p->vbccvar->next=merk_varf; store_locals=first_var[nesting]; merk_varf=store_locals->vbccvar; } nesting--; local_offset=pop_int(); } void gen_func(var *v,icode *first,int framesize) { pric(stdout,get_first_icode()); vl1=first_var[0]?first_var[0]->vbccvar:0; vl2=first_var[1]?first_var[1]->vbccvar:0; vl3=merk_varf; optimize(optflags,v->vbccvar); memset(regs_modified,0,RSIZE); pric(stdout,get_first_icode()); gen_code(out,get_first_icode(),v->vbccvar,max_offset); } void enter_func(char *name,type *p) { type *t=new_type(FUNCTION); var *v; t->next=p; t->exact=getmem(sizeof(*t->exact)); t->exact->count=0; v=add_var(name,t); local_offset=parm_offset=framesize=0; push_ptr(v); enter_block(); } void leave_func() { icode *p,*merk; leave_block(); gen_func(pop_ptr(),get_first_icode(),framesize); free_all_icode(); first_ic=last_ic=0; free_varlist(store_locals); merk_varf=0; store_locals=0; } var *find_var(char *p,int minnest) { var *v; int i; for(i=nesting;i>=minnest;i--){ for(v=first_var[i];v;v=v->next) if(!strcmp(v->name,p)) return v; } return 0; } var *add_var(char *name,type *t) { var *new=getmem(sizeof(*new)); struct Var *vv; /*FIXME: add vbccvar */ if(find_var(name,nesting)) error(5,"var %s already defined",name); new->nesting=nesting; new->name=add_string(name); new->type=t; if(*name==0){ new->next=store_locals; }else{ new->next=first_var[nesting]; } if(nesting==1){ /* parameter */ new->offset=parm_offset; parm_offset+=szof(t); } if(nesting>1){ /* local variable */ new->offset=local_offset; local_offset+=szof(t); if(local_offset>framesize) framesize=local_offset; } /* attach vbcc variable */ vv=new_var(); vv->vtyp=clone_typ(new->type); vv->identifier=add_string(name); vv->nesting=(*name!=0?nesting:2); vv->storage_class=(vv->nesting==0?EXTERN:AUTO); if(nesting==1) vv->offset=zmsub(l2zm(0L),zmadd(maxalign,l2zm(new->offset))); else vv->offset=l2zm((long)local_offset); new->vbccvar=vv; if(*name==0){ store_locals=new; vv->next=merk_varf; merk_varf=vv; }else{ vv->next=first_var[nesting]?first_var[nesting]->vbccvar:0; first_var[nesting]=new; } return new; } var *new_temp(int tflags) { char tname[16]; static int itmps,rtmps,ptmps; if(tflags==INT) sprintf(tname,"\0 itmp%d",++itmps); else if(tflags==REAL) sprintf(tname,"\0 rtmp%d",++rtmps); else if(tflags==POINTER) sprintf(tname,"\0 rtmp%d",++ptmps); else error(16,"internal"); return add_var(tname,new_type(tflags)); } struct Var *add_tmp_var(struct Typ *t) { return new_temp(t->flags)->vbccvar; } char *add_string(char *s) { char *new=getmem(strlen(s)+1); strcpy(new,s); return new; } char *nodename[]={ "var","number","add","mul","sub","div","index","equals", "lt","gt","leq","geq","neq","and","or", "int2real","real2int","assign","call","argument" }; node *number_node(void) { node *new=getmem(sizeof(*new)); new->flags=NNUMBER; if(strstr(tkname,".")){ double rval; sscanf(tkname,"%lf",&rval); new->rvalue=rval; new->type=new_type(REAL); new->left=new->right=0; }else{ new->ivalue=atoi(tkname); new->type=new_type(INT); new->left=new->right=0; } return new; } node *var_node(void) { var *v=find_var(tkname,0); node *new; if(!v){ error(6,"unknown identifier: %s",tkname); } new=getmem(sizeof(*new)); new->flags=NVARIABLE; new->var=v; new->type=clone_type(v->type); new->left=new->right=0; return new; } node *binary_node(enum nodeflags flags,node *left,node *right) { node *new=getmem(sizeof(*new)); new->flags=flags; new->left=left; new->right=right; new->type=0; if(!left||(flags!=NCALL&&!right)) error(7,"internal error"); if(flags==NINDEX){ if(left->type->flags!=ARRAY) error(8,"operand of [] must be array"); new->type=clone_type(left->type->next); }else if(flags==NARG){ /* nothing to do? */ }else if(flags==NCALL){ if(left->type->flags!=FUNCTION) error(9,"only functions can be called"); new->type=clone_type(left->type->next); }else{ if(left->type->flags==ARRAY||right->type->flags==ARRAY) error(10,"both operands must be real or int"); if(left->type->flags==REAL||right->type->flags==REAL){ new->type=new_type(REAL); if(left->type->flags==INT){ new->left=conv_tree(left,REAL); } if(right->type->flags==INT){ new->right=conv_tree(right,REAL); } }else new->type=new_type(INT); } return new; } void print_tree(node *p) { printf("%s(",nodename[p->flags]); if(p->left) print_tree(p->left); if(p->right){ printf(","); print_tree(p->right); } if(p->flags==NNUMBER){ if(p->type->flags==INT) printf("%d[int]",p->ivalue); else printf("%g[real]",p->rvalue); } if(p->flags==NVARIABLE) printf("%s[%s]",p->var->name,typename[p->var->type->flags]); printf(")"); } node *conv_tree(node *p,int tflags) { node *new; if(p->type->flags==tflags) return p; new=getmem(sizeof(*new)); if(tflags==REAL) new->flags=NI2R; else new->flags=NR2I; new->type=new_type(p->type->flags); new->left=p; new->right=0; return new; } void free_tree(node *p) { if(p->left) free_tree(p->left); if(p->right) free_tree(p->right); if(p->type) free_type(p->type); free(p); } static void const_node(node *p,int val) { p->flags=NNUMBER; p->ivalue=val; if(p->left) free_tree(p->left); if(p->right) free_tree(p->right); p->left=p->right=0; } void simplify_tree(node *p) { if(p->left) simplify_tree(p->left); if(p->right) simplify_tree(p->right); if(p->type&&p->type->flags==INT&&p->left&&p->left->flags==NNUMBER&&p->right&&p->right->flags==NNUMBER){ switch(p->flags){ case NADD: const_node(p,p->left->ivalue+p->right->ivalue); break; case NMUL: const_node(p,p->left->ivalue*p->right->ivalue); break; case NSUB: const_node(p,p->left->ivalue-p->right->ivalue); break; case NDIV: if(p->right->ivalue!=0) const_node(p,p->left->ivalue/p->right->ivalue); break; } } } void assign_statement(node *left,node *right) { if(left->type->flags==ARRAY||right->type->flags==ARRAY) error(11,"array type in assignment"); if(left->type->flags==FUNCTION||right->type->flags==FUNCTION) error(12,"function type in assignment"); right=conv_tree(right,left->type->flags); simplify_tree(left); simplify_tree(right); if(left->flags==NINDEX){ icode *n1,*n2,*n3; n1=new_icode(); n1->code=MULT; n1->typf=INT; n1->q1=*gen_tree(left->right); n1->q2.flags=KONST; n1->q2.val.vint=zm2zi(sizetab[INT]); n1->z.flags=VAR; n1->z.v=new_temp(INT)->vbccvar; n1->z.val.vmax=l2zm(0L); n2=new_icode(); n2->code=ADDI2P; n2->typf=INT; n2->typf2=POINTER; n2->q1=*gen_tree(left->left); n2->q2=n1->z; n2->z.flags=VAR; n2->z.v=new_temp(POINTER)->vbccvar; n2->z.val.vmax=l2zm(0L); n3=new_icode(); n3->code=ASSIGN; n3->typf=left->type->flags; n3->q1=*gen_tree(right); n3->z=n2->z; n3->z.flags|=DREFOBJ; n3->z.dtyp=POINTER; n3->q2.val.vmax=szof(left->type); add_icode(n1); add_icode(n2); add_icode(n3); #if 0 /* leicht anderes Format */ new->flags=CSTORE; new->op1=*gen_tree(right); new->op2=*gen_tree(left->left); new->dest=*gen_tree(left->right); #endif }else{ icode *new=new_icode(); new->code=ASSIGN; new->q1=*gen_tree(right); new->z=*gen_tree(left); new->q2.val.vmax=szof(left->type); new->typf=left->type->flags; add_icode(new); } free_tree(left); free_tree(right); } void return_statement(node *p) { icode *new=new_icode(); p=conv_tree(p,INT); /*FIXME*/ simplify_tree(p); new->code=SETRETURN; new->typf=p->type->flags; new->q1=*gen_tree(p); new->z.reg=freturn(p->type); add_icode(new); free_tree(p); } void while_statement(node *p) { int loop=++label,exit=++label; simplify_tree(p); gen_cond(p,loop,exit); gen_label(loop); last_ic->flags|=LOOP_COND_TRUE; push_ptr(p); push_int(loop); push_int(exit); #if 0 gen_label(loop); gen_cond(p,start,exit); free_tree(p); gen_label(start); push_int(loop); push_int(exit); #endif } void while_end() { int loop,exit; node *p; exit=pop_int(); loop=pop_int(); p=pop_ptr(); gen_cond(p,loop,exit); gen_label(exit); #if 0 new=new_icode(); new->code=BRA; new->typf=loop; add_icode(new); gen_label(exit); #endif } void if_statement(node *p) { int true=++label,false=++label; simplify_tree(p); gen_cond(p,true,false); free_tree(p); gen_label(true); push_int(false); } void if_end() { gen_label(pop_int()); } void if_else() { int endlabel=++label; icode *new=new_icode(); new->code=BRA; new->typf=++label; add_icode(new); gen_label(pop_int()); push_int(label); } int label; operand *gen_tree(node *p) { icode *new; static operand op; if(p->flags==NVARIABLE){ if(p->var->type->flags==ARRAY){ if(p->var->nesting==0){ op.flags=VAR|VARADR; op.v=p->var->vbccvar; op.val.vmax=l2zm(0L); return &op; }else{ icode *new=new_icode(); new->flags=ADDRESS; new->q1.flags=VAR; new->q1.v=p->var->vbccvar; new->q1.val.vmax=l2zm(0L); new->z.flags=VAR; new->z.v=new_temp(POINTER)->vbccvar; new->z.val.vmax=l2zm(0L); add_icode(new); return &new->z; } }else{ op.flags=VAR; op.v=p->var->vbccvar; op.val.vmax=l2zm(0L); return &op; } } if(p->flags==NNUMBER){ op.flags=KONST; if(p->type->flags==INT) op.val.vint=p->ivalue; else op.val.vdouble=zld2zd(d2zld(p->rvalue)); return &op; } if(p->flags==NADD||p->flags==NMUL||p->flags==NSUB||p->flags==NDIV||p->flags==NI2R||p->flags==NR2I){ int ttyp=p->type->flags; new=new_icode(); switch(p->flags){ case NADD: new->code=ADD;break; case NMUL: new->code=MULT;break; case NSUB: new->code=SUB;break; case NDIV: new->code=DIV;break; case NI2R: new->code=CONVERT;ttyp=REAL;new->typf2=INT;break; case NR2I: new->code=CONVERT;ttyp=INT;new->typf2=REAL;break; } new->q1=*gen_tree(p->left); if(p->right) new->q2=*gen_tree(p->right); new->z.flags=VAR; new->z.v=new_temp(ttyp)->vbccvar; new->z.val.vmax=l2zm(0L); new->typf=ttyp; add_icode(new); return &new->z; } if(p->flags==NINDEX){ if(p->type->flags==ARRAY){ icode *merk,*new=new_icode(); new->flags=MULT; new->typf=INT; new->q1=*gen_tree(p->right); new->q2.flags=KONST; new->q2.val.vint=szof(p->type); new->z.flags=VAR; new->z.v=new_temp(INT)->vbccvar; new->z.val.vmax=l2zm(0L); add_icode(new); merk=new; new=new_icode(); new->flags=ADDI2P; new->typf=INT; new->typf2=POINTER; new->q1=*gen_tree(p->left); new->q2=merk->z; new->z.flags=VAR; new->z.v=new_temp(POINTER)->vbccvar; new->z.val.vmax=l2zm(0L); op=new->z; add_icode(new); return &new->z; }else{ icode *merk,*new=new_icode(); new->code=MULT; new->typf=INT; new->q1=*gen_tree(p->right); new->q2.flags=KONST; new->q2.val.vint=zm2zi(sizetab[INT]); new->z.flags=VAR; new->z.v=new_temp(INT)->vbccvar; new->z.val.vmax=l2zm(0L); add_icode(new); merk=new; new=new_icode(); new->code=ADDI2P; new->q1=*gen_tree(p->left); new->q2=merk->z; new->typf=INT; new->typf2=POINTER; new->z.flags=VAR; new->z.v=new_temp(POINTER)->vbccvar; new->z.val.vmax=l2zm(0L); op=new->z; op.flags|=DREFOBJ; op.dtyp=POINTER; add_icode(new); return &op; } } if(p->flags==NCALL){ icode *new=new_icode(); new->code=CALL; new->typf=FUNKT; if(p->right) new->q2.val.vmax=l2zm(push_arg(p->right)); else new->q2.val.vmax=l2zm(0L); new->q1=*gen_tree(p->left); add_icode(new); new=new_icode(); new->code=GETRETURN; new->z.flags=VAR; new->typf=p->type->flags; new->z.v=new_temp(p->type->flags)->vbccvar; new->z.val.vmax=l2zm(0L); new->q1.reg=freturn(p->type); add_icode(new); return &new->z; } error(13,"operation not yet supported"); } void gen_label(int l) { icode *new=new_icode(); new->code=LABEL; new->typf=l; add_icode(new); } void gen_cond(node *p,int true_label,int false_label) { icode *new; if(p->flags==NAND){ int tmp=++label; gen_cond(p->left,tmp,false_label); gen_label(tmp); gen_cond(p->right,true_label,false_label); return; } if(p->flags==NOR){ int tmp=++label; gen_cond(p->left,true_label,tmp); gen_label(tmp); gen_cond(p->right,true_label,false_label); return; } new=new_icode(); new->code=COMPARE; new->typf=p->type->flags; new->q1=*gen_tree(p->left); new->q2=*gen_tree(p->right); add_icode(new); new=new_icode(); switch(p->flags){ case NEQUALS: new->code=BEQ;break; case NNEQ: new->code=BNE;break; case NLT: new->code=BLT;break; case NGT: new->code=BGT;break; case NLEQ: new->code=BLE;break; case NGEQ: new->code=BGE;break; default: error(14,"internal"); } new->typf=true_label; add_icode(new); new=new_icode(); new->code=BRA; new->typf=false_label; add_icode(new); } int push_arg(node *p) { if(p->flags==NARG){ int s; s=push_arg(p->right); return s+push_arg(p->left); }else{ icode *new=new_icode(); if(p->type->flags==ARRAY) error(15,"arrays cannot be passed"); new->code=PUSH; new->q2.val.vmax=szof(p->type); new->z.val.vmax=new->q2.val.vmax; new->typf=p->type->flags; new->q1=*gen_tree(p); add_icode(new); return szof(p->type); } } void free_var(struct Var *v) { free(v); /*FIXME*/ } void add_IC(icode *new) { if(last_ic&&new->code==ASSIGN&&new->q1.flags==VAR&&last_ic->z.flags==VAR&& new->q1.v==last_ic->z.v&&zmeqto(new->q1.val.vmax,last_ic->z.val.vmax)&& *new->q1.v->identifier==0){ last_ic->z=new->z; free(new); return; } insert_IC(last_ic,new); }