PulkoMandy | 17fc759 | 2022-07-28 18:27:54 +0200 | [diff] [blame] | 1 | #include "minicomp.h" |
| 2 | |
| 3 | #define clone_type clone_typ |
| 4 | #define free_type freetyp |
| 5 | #define new_icode new_IC |
| 6 | #define add_icode add_IC |
| 7 | #define free_all_icode() free_IC(first_ic) |
| 8 | #define get_first_icode() first_ic |
| 9 | typedef struct IC icode; |
| 10 | |
| 11 | static int errors; |
| 12 | var *store_locals; |
| 13 | |
| 14 | struct rpair rp; |
| 15 | |
| 16 | char *copyright="minicomp/vbcc (c) in 2002 Volker Barthelmann"; |
| 17 | char *inname,*outname; |
| 18 | struct struct_declaration *first_sd; |
| 19 | struct Var *first_ext,*merk_varf; |
| 20 | char **target_macros; |
| 21 | |
| 22 | FILE *out; |
| 23 | |
| 24 | void raus(void) |
| 25 | { |
| 26 | var *v; |
| 27 | for(v=first_var[0];v;v=v->next) |
| 28 | if(v->type->flags!=FUNCTION){ |
| 29 | gen_align(out,falign(v->type)); |
| 30 | gen_var_head(out,v->vbccvar); |
| 31 | gen_ds(out,szof(v->type),v->type); |
| 32 | } |
| 33 | |
| 34 | cleanup_cg(out); |
| 35 | |
| 36 | if(errors>0) |
| 37 | exit(EXIT_FAILURE); |
| 38 | else |
| 39 | exit(EXIT_SUCCESS); |
| 40 | } |
| 41 | |
| 42 | main(int argc,char **argv) |
| 43 | { |
| 44 | int i,j,flag; |
| 45 | type *nt; |
| 46 | |
| 47 | for(i=1;i<argc;i++){ |
| 48 | if(*argv[i]!='-'){ |
| 49 | if(inname) |
| 50 | error(18,"multiple input files"); |
| 51 | inname=argv[i]; |
| 52 | }else{ |
| 53 | flag=0; |
| 54 | if((!strcmp("-o",argv[i]))&&i<argc-1){ |
| 55 | flag=1; |
| 56 | outname=argv[++i]; |
| 57 | continue; |
| 58 | } |
| 59 | if(!strncmp("-debug=",argv[i],7)){ |
| 60 | flag=1; |
| 61 | sscanf(argv[i]+7,"%d",&j); |
| 62 | DEBUG=j; |
| 63 | continue; |
| 64 | } |
| 65 | if(!strncmp("-unroll-size=",argv[i],13)){ |
| 66 | flag=1; |
| 67 | sscanf(argv[i]+13,"%d",&j); |
| 68 | unroll_size=j; |
| 69 | continue; |
| 70 | } |
| 71 | if(!strncmp("-inline-size=",argv[i],13)){ |
| 72 | flag=1; |
| 73 | sscanf(argv[i]+13,"%d",&j); |
| 74 | inline_size=j; |
| 75 | continue; |
| 76 | } |
| 77 | if(!strncmp("-maxoptpasses=",argv[i],14)){ |
| 78 | flag=1; |
| 79 | sscanf(argv[i]+14,"%d",&j); |
| 80 | maxoptpasses=j; |
| 81 | continue; |
| 82 | } |
| 83 | for(j=0;j<MAXGF&&flag==0;j++){ |
| 84 | size_t l; |
| 85 | if(!g_flags_name[j]) continue; |
| 86 | l=strlen(g_flags_name[j]); |
| 87 | if(l>0&&!strncmp(argv[i]+1,g_flags_name[j],l)){ |
| 88 | flag=1; |
| 89 | if((g_flags[j]&(USEDFLAG|FUNCFLAG))==USEDFLAG){error(19,"multiple option");break;} |
| 90 | g_flags[j]|=USEDFLAG; |
| 91 | if(g_flags[j]&STRINGFLAG){ |
| 92 | if(argv[i][l+1]!='='){error(21,"string expected");} |
| 93 | if(argv[i][l+2]||i>=argc-1) |
| 94 | g_flags_val[j].p=&argv[i][l+2]; |
| 95 | else |
| 96 | g_flags_val[j].p=&argv[++i][0]; |
| 97 | } |
| 98 | if(g_flags[j]&VALFLAG){ |
| 99 | if(argv[i][l+1]!='='){error(20,"value expected");} |
| 100 | if(argv[i][l+2]||i>=argc-1) |
| 101 | g_flags_val[j].l=atol(&argv[i][l+2]); |
| 102 | else |
| 103 | g_flags_val[j].l=atol(&argv[++i][0]); |
| 104 | } |
| 105 | if(g_flags[j]&FUNCFLAG) g_flags_val[j].f(&argv[i][l+1]); |
| 106 | } |
| 107 | } |
| 108 | if(!flag) error(23,"unknown option"); |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | if(!inname) |
| 113 | error(22,"no input file"); |
| 114 | infile=fopen(inname,"r"); |
| 115 | if(!infile) |
| 116 | error(18,"could not open output file"); |
| 117 | if(!outname) |
| 118 | error(23,"no output file"); |
| 119 | out=fopen(outname,"w"); |
| 120 | if(!out){ |
| 121 | error(24,"could not open input file"); |
| 122 | } |
| 123 | nt=new_type(FUNCTION); |
| 124 | nt->next=new_type(INT); |
| 125 | add_var("readInt",clone_type(nt)); |
| 126 | add_var("writeInt",clone_type(nt)); |
| 127 | add_var("writeChar",clone_type(nt)); |
| 128 | add_var("readChar",clone_type(nt)); |
| 129 | add_var("writeReal",nt); |
| 130 | nt=new_type(FUNCTION); |
| 131 | nt->next=new_type(REAL); |
| 132 | add_var("readReal",nt); |
| 133 | |
| 134 | stackalign=l2zm(0L); |
| 135 | if(!init_cg()) exit(EXIT_FAILURE); |
| 136 | if(zmeqto(stackalign,l2zm(0L))) |
| 137 | stackalign=maxalign; |
| 138 | for(i=0;i<EMIT_BUF_DEPTH;i++) |
| 139 | emit_buffer[i]=mymalloc(EMIT_BUF_LEN); |
| 140 | emit_p=emit_buffer[0]; |
| 141 | |
| 142 | multiple_ccs=0; |
| 143 | optflags=-1; |
| 144 | maxoptpasses=100; |
| 145 | |
| 146 | yyparse(); |
| 147 | |
| 148 | raus(); |
| 149 | } |
| 150 | |
| 151 | yyerror(char *s) |
| 152 | { |
| 153 | error(1,s); |
| 154 | } |
| 155 | |
| 156 | void error(int n,...) |
| 157 | { |
| 158 | if(n==170||n==172) return; |
| 159 | errors++; |
| 160 | fprintf(stderr,"error %d\n",n); |
| 161 | raus(); |
| 162 | } |
| 163 | |
| 164 | void *getmem(size_t s) |
| 165 | { |
| 166 | void *p=malloc(s); |
| 167 | if(!p){ |
| 168 | error(2,"out of memory"); |
| 169 | } |
| 170 | return p; |
| 171 | } |
| 172 | |
| 173 | #define LABELNESTING 1024 |
| 174 | static int labelstack[LABELNESTING],labelidx; |
| 175 | |
| 176 | void push_int(int l) |
| 177 | { |
| 178 | labelstack[labelidx++]=l; |
| 179 | } |
| 180 | |
| 181 | int pop_int() |
| 182 | { |
| 183 | return labelstack[--labelidx]; |
| 184 | } |
| 185 | |
| 186 | #define NAMENESTING 1024 |
| 187 | static char *namestack[NAMENESTING],nameidx; |
| 188 | |
| 189 | void push_ptr(void *ptr) |
| 190 | { |
| 191 | namestack[nameidx++]=ptr; |
| 192 | } |
| 193 | |
| 194 | void *pop_ptr() |
| 195 | { |
| 196 | return namestack[--nameidx]; |
| 197 | } |
| 198 | |
| 199 | |
| 200 | char *typename[]={" ","int","real","array","function"}; |
| 201 | |
| 202 | |
| 203 | type *new_type(int t) |
| 204 | { |
| 205 | type *new=new_typ(); |
| 206 | new->flags=t; |
| 207 | new->next=0; |
| 208 | return new; |
| 209 | } |
| 210 | |
| 211 | type *new_array(type *t,node *p) |
| 212 | { |
| 213 | type *new=new_typ(); |
| 214 | simplify_tree(p); |
| 215 | if(p->flags!=NNUMBER) |
| 216 | error(3,"array size not a constant"); |
| 217 | if(p->type->flags!=INT) |
| 218 | error(4,"array size not an integer"); |
| 219 | new->flags=ARRAY; |
| 220 | new->next=t; |
| 221 | new->size=l2zm((long)p->ivalue); |
| 222 | free_tree(p); |
| 223 | return new; |
| 224 | } |
| 225 | |
| 226 | int nesting; |
| 227 | int local_offset,parm_offset,framesize; |
| 228 | |
| 229 | #define MAXNESTING 128 |
| 230 | var *first_var[128]; |
| 231 | |
| 232 | void free_varlist(var *v) |
| 233 | { |
| 234 | var *m; |
| 235 | while(v){ |
| 236 | free_var(v->vbccvar); |
| 237 | m=v->next; |
| 238 | free(v); |
| 239 | v=m; |
| 240 | } |
| 241 | } |
| 242 | |
| 243 | void enter_block() |
| 244 | { |
| 245 | nesting++; |
| 246 | first_var[nesting]=0; |
| 247 | push_int(local_offset); |
| 248 | } |
| 249 | |
| 250 | void leave_block() |
| 251 | { |
| 252 | if(first_var[nesting]){ |
| 253 | var *p=first_var[nesting]; |
| 254 | while(p->next) |
| 255 | p=p->next; |
| 256 | p->next=store_locals; |
| 257 | p->vbccvar->next=merk_varf; |
| 258 | store_locals=first_var[nesting]; |
| 259 | merk_varf=store_locals->vbccvar; |
| 260 | } |
| 261 | nesting--; |
| 262 | local_offset=pop_int(); |
| 263 | } |
| 264 | |
| 265 | void gen_func(var *v,icode *first,int framesize) |
| 266 | { |
| 267 | pric(stdout,get_first_icode()); |
| 268 | vl1=first_var[0]?first_var[0]->vbccvar:0; |
| 269 | vl2=first_var[1]?first_var[1]->vbccvar:0; |
| 270 | vl3=merk_varf; |
| 271 | optimize(optflags,v->vbccvar); |
| 272 | memset(regs_modified,0,RSIZE); |
| 273 | pric(stdout,get_first_icode()); |
| 274 | gen_code(out,get_first_icode(),v->vbccvar,max_offset); |
| 275 | } |
| 276 | |
| 277 | void enter_func(char *name,type *p) |
| 278 | { |
| 279 | type *t=new_type(FUNCTION); |
| 280 | var *v; |
| 281 | t->next=p; |
| 282 | t->exact=getmem(sizeof(*t->exact)); |
| 283 | t->exact->count=0; |
| 284 | v=add_var(name,t); |
| 285 | local_offset=parm_offset=framesize=0; |
| 286 | push_ptr(v); |
| 287 | enter_block(); |
| 288 | } |
| 289 | |
| 290 | void leave_func() |
| 291 | { |
| 292 | icode *p,*merk; |
| 293 | leave_block(); |
| 294 | gen_func(pop_ptr(),get_first_icode(),framesize); |
| 295 | free_all_icode(); |
| 296 | first_ic=last_ic=0; |
| 297 | free_varlist(store_locals); |
| 298 | merk_varf=0; |
| 299 | store_locals=0; |
| 300 | } |
| 301 | |
| 302 | var *find_var(char *p,int minnest) |
| 303 | { |
| 304 | var *v; |
| 305 | int i; |
| 306 | |
| 307 | for(i=nesting;i>=minnest;i--){ |
| 308 | for(v=first_var[i];v;v=v->next) |
| 309 | if(!strcmp(v->name,p)) |
| 310 | return v; |
| 311 | } |
| 312 | return 0; |
| 313 | } |
| 314 | |
| 315 | var *add_var(char *name,type *t) |
| 316 | { |
| 317 | var *new=getmem(sizeof(*new)); |
| 318 | struct Var *vv; |
| 319 | /*FIXME: add vbccvar */ |
| 320 | if(find_var(name,nesting)) |
| 321 | error(5,"var %s already defined",name); |
| 322 | new->nesting=nesting; |
| 323 | new->name=add_string(name); |
| 324 | new->type=t; |
| 325 | if(*name==0){ |
| 326 | new->next=store_locals; |
| 327 | }else{ |
| 328 | new->next=first_var[nesting]; |
| 329 | } |
| 330 | if(nesting==1){ |
| 331 | /* parameter */ |
| 332 | new->offset=parm_offset; |
| 333 | parm_offset+=szof(t); |
| 334 | } |
| 335 | if(nesting>1){ |
| 336 | /* local variable */ |
| 337 | new->offset=local_offset; |
| 338 | local_offset+=szof(t); |
| 339 | if(local_offset>framesize) |
| 340 | framesize=local_offset; |
| 341 | } |
| 342 | /* attach vbcc variable */ |
| 343 | vv=new_var(); |
| 344 | vv->vtyp=clone_typ(new->type); |
| 345 | vv->identifier=add_string(name); |
| 346 | vv->nesting=(*name!=0?nesting:2); |
| 347 | vv->storage_class=(vv->nesting==0?EXTERN:AUTO); |
| 348 | if(nesting==1) |
| 349 | vv->offset=zmsub(l2zm(0L),zmadd(maxalign,l2zm(new->offset))); |
| 350 | else |
| 351 | vv->offset=l2zm((long)local_offset); |
| 352 | new->vbccvar=vv; |
| 353 | |
| 354 | if(*name==0){ |
| 355 | store_locals=new; |
| 356 | vv->next=merk_varf; |
| 357 | merk_varf=vv; |
| 358 | }else{ |
| 359 | vv->next=first_var[nesting]?first_var[nesting]->vbccvar:0; |
| 360 | first_var[nesting]=new; |
| 361 | } |
| 362 | return new; |
| 363 | } |
| 364 | |
| 365 | var *new_temp(int tflags) |
| 366 | { |
| 367 | char tname[16]; |
| 368 | static int itmps,rtmps,ptmps; |
| 369 | if(tflags==INT) |
| 370 | sprintf(tname,"\0 itmp%d",++itmps); |
| 371 | else if(tflags==REAL) |
| 372 | sprintf(tname,"\0 rtmp%d",++rtmps); |
| 373 | else if(tflags==POINTER) |
| 374 | sprintf(tname,"\0 rtmp%d",++ptmps); |
| 375 | else |
| 376 | error(16,"internal"); |
| 377 | return add_var(tname,new_type(tflags)); |
| 378 | } |
| 379 | |
| 380 | struct Var *add_tmp_var(struct Typ *t) |
| 381 | { |
| 382 | |
| 383 | return new_temp(t->flags)->vbccvar; |
| 384 | } |
| 385 | |
| 386 | char *add_string(char *s) |
| 387 | { |
| 388 | char *new=getmem(strlen(s)+1); |
| 389 | strcpy(new,s); |
| 390 | return new; |
| 391 | } |
| 392 | |
| 393 | char *nodename[]={ |
| 394 | "var","number","add","mul","sub","div","index","equals", |
| 395 | "lt","gt","leq","geq","neq","and","or", |
| 396 | "int2real","real2int","assign","call","argument" |
| 397 | }; |
| 398 | |
| 399 | node *number_node(void) |
| 400 | { |
| 401 | node *new=getmem(sizeof(*new)); |
| 402 | new->flags=NNUMBER; |
| 403 | if(strstr(tkname,".")){ |
| 404 | double rval; |
| 405 | sscanf(tkname,"%lf",&rval); |
| 406 | new->rvalue=rval; |
| 407 | new->type=new_type(REAL); |
| 408 | new->left=new->right=0; |
| 409 | }else{ |
| 410 | new->ivalue=atoi(tkname); |
| 411 | new->type=new_type(INT); |
| 412 | new->left=new->right=0; |
| 413 | } |
| 414 | return new; |
| 415 | } |
| 416 | |
| 417 | node *var_node(void) |
| 418 | { |
| 419 | var *v=find_var(tkname,0); |
| 420 | node *new; |
| 421 | if(!v){ |
| 422 | error(6,"unknown identifier: %s",tkname); |
| 423 | } |
| 424 | new=getmem(sizeof(*new)); |
| 425 | new->flags=NVARIABLE; |
| 426 | new->var=v; |
| 427 | new->type=clone_type(v->type); |
| 428 | new->left=new->right=0; |
| 429 | return new; |
| 430 | } |
| 431 | |
| 432 | |
| 433 | node *binary_node(enum nodeflags flags,node *left,node *right) |
| 434 | { |
| 435 | node *new=getmem(sizeof(*new)); |
| 436 | new->flags=flags; |
| 437 | new->left=left; |
| 438 | new->right=right; |
| 439 | new->type=0; |
| 440 | if(!left||(flags!=NCALL&&!right)) |
| 441 | error(7,"internal error"); |
| 442 | if(flags==NINDEX){ |
| 443 | if(left->type->flags!=ARRAY) |
| 444 | error(8,"operand of [] must be array"); |
| 445 | new->type=clone_type(left->type->next); |
| 446 | }else if(flags==NARG){ |
| 447 | /* nothing to do? */ |
| 448 | }else if(flags==NCALL){ |
| 449 | if(left->type->flags!=FUNCTION) |
| 450 | error(9,"only functions can be called"); |
| 451 | new->type=clone_type(left->type->next); |
| 452 | }else{ |
| 453 | if(left->type->flags==ARRAY||right->type->flags==ARRAY) |
| 454 | error(10,"both operands must be real or int"); |
| 455 | if(left->type->flags==REAL||right->type->flags==REAL){ |
| 456 | new->type=new_type(REAL); |
| 457 | if(left->type->flags==INT){ |
| 458 | new->left=conv_tree(left,REAL); |
| 459 | } |
| 460 | if(right->type->flags==INT){ |
| 461 | new->right=conv_tree(right,REAL); |
| 462 | } |
| 463 | }else |
| 464 | new->type=new_type(INT); |
| 465 | } |
| 466 | return new; |
| 467 | } |
| 468 | |
| 469 | void print_tree(node *p) |
| 470 | { |
| 471 | printf("%s(",nodename[p->flags]); |
| 472 | if(p->left) |
| 473 | print_tree(p->left); |
| 474 | if(p->right){ |
| 475 | printf(","); |
| 476 | print_tree(p->right); |
| 477 | } |
| 478 | if(p->flags==NNUMBER){ |
| 479 | if(p->type->flags==INT) |
| 480 | printf("%d[int]",p->ivalue); |
| 481 | else |
| 482 | printf("%g[real]",p->rvalue); |
| 483 | } |
| 484 | if(p->flags==NVARIABLE) |
| 485 | printf("%s[%s]",p->var->name,typename[p->var->type->flags]); |
| 486 | printf(")"); |
| 487 | } |
| 488 | |
| 489 | node *conv_tree(node *p,int tflags) |
| 490 | { |
| 491 | node *new; |
| 492 | if(p->type->flags==tflags) |
| 493 | return p; |
| 494 | new=getmem(sizeof(*new)); |
| 495 | if(tflags==REAL) |
| 496 | new->flags=NI2R; |
| 497 | else |
| 498 | new->flags=NR2I; |
| 499 | new->type=new_type(p->type->flags); |
| 500 | new->left=p; |
| 501 | new->right=0; |
| 502 | return new; |
| 503 | } |
| 504 | |
| 505 | void free_tree(node *p) |
| 506 | { |
| 507 | if(p->left) |
| 508 | free_tree(p->left); |
| 509 | if(p->right) |
| 510 | free_tree(p->right); |
| 511 | if(p->type) |
| 512 | free_type(p->type); |
| 513 | free(p); |
| 514 | } |
| 515 | |
| 516 | |
| 517 | static void const_node(node *p,int val) |
| 518 | { |
| 519 | p->flags=NNUMBER; |
| 520 | p->ivalue=val; |
| 521 | if(p->left) |
| 522 | free_tree(p->left); |
| 523 | if(p->right) |
| 524 | free_tree(p->right); |
| 525 | p->left=p->right=0; |
| 526 | } |
| 527 | |
| 528 | void simplify_tree(node *p) |
| 529 | { |
| 530 | if(p->left) |
| 531 | simplify_tree(p->left); |
| 532 | if(p->right) |
| 533 | simplify_tree(p->right); |
| 534 | if(p->type&&p->type->flags==INT&&p->left&&p->left->flags==NNUMBER&&p->right&&p->right->flags==NNUMBER){ |
| 535 | switch(p->flags){ |
| 536 | case NADD: const_node(p,p->left->ivalue+p->right->ivalue); break; |
| 537 | case NMUL: const_node(p,p->left->ivalue*p->right->ivalue); break; |
| 538 | case NSUB: const_node(p,p->left->ivalue-p->right->ivalue); break; |
| 539 | case NDIV: |
| 540 | if(p->right->ivalue!=0) |
| 541 | const_node(p,p->left->ivalue/p->right->ivalue); break; |
| 542 | } |
| 543 | } |
| 544 | } |
| 545 | |
| 546 | void assign_statement(node *left,node *right) |
| 547 | { |
| 548 | if(left->type->flags==ARRAY||right->type->flags==ARRAY) |
| 549 | error(11,"array type in assignment"); |
| 550 | if(left->type->flags==FUNCTION||right->type->flags==FUNCTION) |
| 551 | error(12,"function type in assignment"); |
| 552 | |
| 553 | right=conv_tree(right,left->type->flags); |
| 554 | simplify_tree(left); |
| 555 | simplify_tree(right); |
| 556 | if(left->flags==NINDEX){ |
| 557 | icode *n1,*n2,*n3; |
| 558 | n1=new_icode(); |
| 559 | n1->code=MULT; |
| 560 | n1->typf=INT; |
| 561 | n1->q1=*gen_tree(left->right); |
| 562 | n1->q2.flags=KONST; |
| 563 | n1->q2.val.vint=zm2zi(sizetab[INT]); |
| 564 | n1->z.flags=VAR; |
| 565 | n1->z.v=new_temp(INT)->vbccvar; |
| 566 | n1->z.val.vmax=l2zm(0L); |
| 567 | n2=new_icode(); |
| 568 | n2->code=ADDI2P; |
| 569 | n2->typf=INT; |
| 570 | n2->typf2=POINTER; |
| 571 | n2->q1=*gen_tree(left->left); |
| 572 | n2->q2=n1->z; |
| 573 | n2->z.flags=VAR; |
| 574 | n2->z.v=new_temp(POINTER)->vbccvar; |
| 575 | n2->z.val.vmax=l2zm(0L); |
| 576 | n3=new_icode(); |
| 577 | n3->code=ASSIGN; |
| 578 | n3->typf=left->type->flags; |
| 579 | n3->q1=*gen_tree(right); |
| 580 | n3->z=n2->z; |
| 581 | n3->z.flags|=DREFOBJ; |
| 582 | n3->z.dtyp=POINTER; |
| 583 | n3->q2.val.vmax=szof(left->type); |
| 584 | add_icode(n1); |
| 585 | add_icode(n2); |
| 586 | add_icode(n3); |
| 587 | #if 0 |
| 588 | /* leicht anderes Format */ |
| 589 | new->flags=CSTORE; |
| 590 | new->op1=*gen_tree(right); |
| 591 | new->op2=*gen_tree(left->left); |
| 592 | new->dest=*gen_tree(left->right); |
| 593 | #endif |
| 594 | }else{ |
| 595 | icode *new=new_icode(); |
| 596 | new->code=ASSIGN; |
| 597 | new->q1=*gen_tree(right); |
| 598 | new->z=*gen_tree(left); |
| 599 | new->q2.val.vmax=szof(left->type); |
| 600 | new->typf=left->type->flags; |
| 601 | add_icode(new); |
| 602 | } |
| 603 | free_tree(left); |
| 604 | free_tree(right); |
| 605 | } |
| 606 | |
| 607 | void return_statement(node *p) |
| 608 | { |
| 609 | icode *new=new_icode(); |
| 610 | p=conv_tree(p,INT); /*FIXME*/ |
| 611 | simplify_tree(p); |
| 612 | new->code=SETRETURN; |
| 613 | new->typf=p->type->flags; |
| 614 | new->q1=*gen_tree(p); |
| 615 | new->z.reg=freturn(p->type); |
| 616 | add_icode(new); |
| 617 | free_tree(p); |
| 618 | } |
| 619 | |
| 620 | void while_statement(node *p) |
| 621 | { |
| 622 | int loop=++label,exit=++label; |
| 623 | simplify_tree(p); |
| 624 | gen_cond(p,loop,exit); |
| 625 | gen_label(loop); |
| 626 | last_ic->flags|=LOOP_COND_TRUE; |
| 627 | push_ptr(p); |
| 628 | push_int(loop); |
| 629 | push_int(exit); |
| 630 | #if 0 |
| 631 | gen_label(loop); |
| 632 | gen_cond(p,start,exit); |
| 633 | free_tree(p); |
| 634 | gen_label(start); |
| 635 | push_int(loop); |
| 636 | push_int(exit); |
| 637 | #endif |
| 638 | } |
| 639 | |
| 640 | void while_end() |
| 641 | { |
| 642 | int loop,exit; |
| 643 | node *p; |
| 644 | exit=pop_int(); |
| 645 | loop=pop_int(); |
| 646 | p=pop_ptr(); |
| 647 | gen_cond(p,loop,exit); |
| 648 | gen_label(exit); |
| 649 | #if 0 |
| 650 | new=new_icode(); |
| 651 | new->code=BRA; |
| 652 | new->typf=loop; |
| 653 | add_icode(new); |
| 654 | gen_label(exit); |
| 655 | #endif |
| 656 | } |
| 657 | |
| 658 | void if_statement(node *p) |
| 659 | { |
| 660 | int true=++label,false=++label; |
| 661 | simplify_tree(p); |
| 662 | gen_cond(p,true,false); |
| 663 | free_tree(p); |
| 664 | gen_label(true); |
| 665 | push_int(false); |
| 666 | } |
| 667 | |
| 668 | void if_end() |
| 669 | { |
| 670 | gen_label(pop_int()); |
| 671 | } |
| 672 | |
| 673 | void if_else() |
| 674 | { |
| 675 | int endlabel=++label; |
| 676 | icode *new=new_icode(); |
| 677 | new->code=BRA; |
| 678 | new->typf=++label; |
| 679 | add_icode(new); |
| 680 | gen_label(pop_int()); |
| 681 | push_int(label); |
| 682 | } |
| 683 | |
| 684 | int label; |
| 685 | |
| 686 | operand *gen_tree(node *p) |
| 687 | { |
| 688 | icode *new; |
| 689 | static operand op; |
| 690 | |
| 691 | if(p->flags==NVARIABLE){ |
| 692 | if(p->var->type->flags==ARRAY){ |
| 693 | if(p->var->nesting==0){ |
| 694 | op.flags=VAR|VARADR; |
| 695 | op.v=p->var->vbccvar; |
| 696 | op.val.vmax=l2zm(0L); |
| 697 | return &op; |
| 698 | }else{ |
| 699 | icode *new=new_icode(); |
| 700 | new->flags=ADDRESS; |
| 701 | new->q1.flags=VAR; |
| 702 | new->q1.v=p->var->vbccvar; |
| 703 | new->q1.val.vmax=l2zm(0L); |
| 704 | new->z.flags=VAR; |
| 705 | new->z.v=new_temp(POINTER)->vbccvar; |
| 706 | new->z.val.vmax=l2zm(0L); |
| 707 | add_icode(new); |
| 708 | return &new->z; |
| 709 | } |
| 710 | }else{ |
| 711 | op.flags=VAR; |
| 712 | op.v=p->var->vbccvar; |
| 713 | op.val.vmax=l2zm(0L); |
| 714 | return &op; |
| 715 | } |
| 716 | } |
| 717 | |
| 718 | if(p->flags==NNUMBER){ |
| 719 | op.flags=KONST; |
| 720 | if(p->type->flags==INT) |
| 721 | op.val.vint=p->ivalue; |
| 722 | else |
| 723 | op.val.vdouble=zld2zd(d2zld(p->rvalue)); |
| 724 | return &op; |
| 725 | } |
| 726 | |
| 727 | if(p->flags==NADD||p->flags==NMUL||p->flags==NSUB||p->flags==NDIV||p->flags==NI2R||p->flags==NR2I){ |
| 728 | int ttyp=p->type->flags; |
| 729 | new=new_icode(); |
| 730 | switch(p->flags){ |
| 731 | case NADD: new->code=ADD;break; |
| 732 | case NMUL: new->code=MULT;break; |
| 733 | case NSUB: new->code=SUB;break; |
| 734 | case NDIV: new->code=DIV;break; |
| 735 | case NI2R: new->code=CONVERT;ttyp=REAL;new->typf2=INT;break; |
| 736 | case NR2I: new->code=CONVERT;ttyp=INT;new->typf2=REAL;break; |
| 737 | } |
| 738 | new->q1=*gen_tree(p->left); |
| 739 | if(p->right) |
| 740 | new->q2=*gen_tree(p->right); |
| 741 | new->z.flags=VAR; |
| 742 | new->z.v=new_temp(ttyp)->vbccvar; |
| 743 | new->z.val.vmax=l2zm(0L); |
| 744 | new->typf=ttyp; |
| 745 | add_icode(new); |
| 746 | return &new->z; |
| 747 | } |
| 748 | |
| 749 | if(p->flags==NINDEX){ |
| 750 | if(p->type->flags==ARRAY){ |
| 751 | icode *merk,*new=new_icode(); |
| 752 | new->flags=MULT; |
| 753 | new->typf=INT; |
| 754 | new->q1=*gen_tree(p->right); |
| 755 | new->q2.flags=KONST; |
| 756 | new->q2.val.vint=szof(p->type); |
| 757 | new->z.flags=VAR; |
| 758 | new->z.v=new_temp(INT)->vbccvar; |
| 759 | new->z.val.vmax=l2zm(0L); |
| 760 | add_icode(new); |
| 761 | merk=new; |
| 762 | new=new_icode(); |
| 763 | new->flags=ADDI2P; |
| 764 | new->typf=INT; |
| 765 | new->typf2=POINTER; |
| 766 | new->q1=*gen_tree(p->left); |
| 767 | new->q2=merk->z; |
| 768 | new->z.flags=VAR; |
| 769 | new->z.v=new_temp(POINTER)->vbccvar; |
| 770 | new->z.val.vmax=l2zm(0L); |
| 771 | op=new->z; |
| 772 | add_icode(new); |
| 773 | return &new->z; |
| 774 | }else{ |
| 775 | icode *merk,*new=new_icode(); |
| 776 | new->code=MULT; |
| 777 | new->typf=INT; |
| 778 | new->q1=*gen_tree(p->right); |
| 779 | new->q2.flags=KONST; |
| 780 | new->q2.val.vint=zm2zi(sizetab[INT]); |
| 781 | new->z.flags=VAR; |
| 782 | new->z.v=new_temp(INT)->vbccvar; |
| 783 | new->z.val.vmax=l2zm(0L); |
| 784 | add_icode(new); |
| 785 | merk=new; |
| 786 | new=new_icode(); |
| 787 | new->code=ADDI2P; |
| 788 | new->q1=*gen_tree(p->left); |
| 789 | new->q2=merk->z; |
| 790 | new->typf=INT; |
| 791 | new->typf2=POINTER; |
| 792 | new->z.flags=VAR; |
| 793 | new->z.v=new_temp(POINTER)->vbccvar; |
| 794 | new->z.val.vmax=l2zm(0L); |
| 795 | op=new->z; |
| 796 | op.flags|=DREFOBJ; |
| 797 | op.dtyp=POINTER; |
| 798 | add_icode(new); |
| 799 | return &op; |
| 800 | } |
| 801 | } |
| 802 | |
| 803 | if(p->flags==NCALL){ |
| 804 | icode *new=new_icode(); |
| 805 | new->code=CALL; |
| 806 | new->typf=FUNKT; |
| 807 | if(p->right) |
| 808 | new->q2.val.vmax=l2zm(push_arg(p->right)); |
| 809 | else |
| 810 | new->q2.val.vmax=l2zm(0L); |
| 811 | new->q1=*gen_tree(p->left); |
| 812 | add_icode(new); |
| 813 | new=new_icode(); |
| 814 | new->code=GETRETURN; |
| 815 | new->z.flags=VAR; |
| 816 | new->typf=p->type->flags; |
| 817 | new->z.v=new_temp(p->type->flags)->vbccvar; |
| 818 | new->z.val.vmax=l2zm(0L); |
| 819 | new->q1.reg=freturn(p->type); |
| 820 | add_icode(new); |
| 821 | return &new->z; |
| 822 | } |
| 823 | |
| 824 | error(13,"operation not yet supported"); |
| 825 | } |
| 826 | |
| 827 | void gen_label(int l) |
| 828 | { |
| 829 | icode *new=new_icode(); |
| 830 | new->code=LABEL; |
| 831 | new->typf=l; |
| 832 | add_icode(new); |
| 833 | } |
| 834 | |
| 835 | void gen_cond(node *p,int true_label,int false_label) |
| 836 | { |
| 837 | icode *new; |
| 838 | if(p->flags==NAND){ |
| 839 | int tmp=++label; |
| 840 | gen_cond(p->left,tmp,false_label); |
| 841 | gen_label(tmp); |
| 842 | gen_cond(p->right,true_label,false_label); |
| 843 | return; |
| 844 | } |
| 845 | if(p->flags==NOR){ |
| 846 | int tmp=++label; |
| 847 | gen_cond(p->left,true_label,tmp); |
| 848 | gen_label(tmp); |
| 849 | gen_cond(p->right,true_label,false_label); |
| 850 | return; |
| 851 | } |
| 852 | new=new_icode(); |
| 853 | new->code=COMPARE; |
| 854 | new->typf=p->type->flags; |
| 855 | new->q1=*gen_tree(p->left); |
| 856 | new->q2=*gen_tree(p->right); |
| 857 | add_icode(new); |
| 858 | new=new_icode(); |
| 859 | switch(p->flags){ |
| 860 | case NEQUALS: new->code=BEQ;break; |
| 861 | case NNEQ: new->code=BNE;break; |
| 862 | case NLT: new->code=BLT;break; |
| 863 | case NGT: new->code=BGT;break; |
| 864 | case NLEQ: new->code=BLE;break; |
| 865 | case NGEQ: new->code=BGE;break; |
| 866 | default: error(14,"internal"); |
| 867 | } |
| 868 | new->typf=true_label; |
| 869 | add_icode(new); |
| 870 | |
| 871 | new=new_icode(); |
| 872 | new->code=BRA; |
| 873 | new->typf=false_label; |
| 874 | add_icode(new); |
| 875 | } |
| 876 | |
| 877 | int push_arg(node *p) |
| 878 | { |
| 879 | if(p->flags==NARG){ |
| 880 | int s; |
| 881 | s=push_arg(p->right); |
| 882 | return s+push_arg(p->left); |
| 883 | }else{ |
| 884 | icode *new=new_icode(); |
| 885 | if(p->type->flags==ARRAY) |
| 886 | error(15,"arrays cannot be passed"); |
| 887 | new->code=PUSH; |
| 888 | new->q2.val.vmax=szof(p->type); |
| 889 | new->z.val.vmax=new->q2.val.vmax; |
| 890 | new->typf=p->type->flags; |
| 891 | new->q1=*gen_tree(p); |
| 892 | add_icode(new); |
| 893 | return szof(p->type); |
| 894 | } |
| 895 | } |
| 896 | |
| 897 | void free_var(struct Var *v) |
| 898 | { |
| 899 | free(v); |
| 900 | /*FIXME*/ |
| 901 | } |
| 902 | |
| 903 | void add_IC(icode *new) |
| 904 | { |
| 905 | if(last_ic&&new->code==ASSIGN&&new->q1.flags==VAR&&last_ic->z.flags==VAR&& |
| 906 | new->q1.v==last_ic->z.v&&zmeqto(new->q1.val.vmax,last_ic->z.val.vmax)&& |
| 907 | *new->q1.v->identifier==0){ |
| 908 | last_ic->z=new->z; |
| 909 | free(new); |
| 910 | return; |
| 911 | } |
| 912 | insert_IC(last_ic,new); |
| 913 | } |