code.c (15519B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 #include <scc/cstd.h> 6 #include <scc/scc.h> 7 8 #include "../cc2.h" 9 #include "arch.h" 10 11 #define ADDR_LEN (INTIDENTSIZ+64) 12 13 static void binary(void), unary(void), store(void), jmp(void), ret(void), 14 branch(void), call(void), ecall(void), param(void), 15 asalloc(void), form2local(void), blit(void), vastart(void), 16 vaarg(void); 17 18 static struct opdata { 19 void (*fun)(void); 20 char *txt; 21 char letter; 22 } optbl [] = { 23 [ASLDSB] = {.fun = unary, .txt = "loadsb", .letter = 'w'}, 24 [ASLDUB] = {.fun = unary, .txt = "loadub", .letter = 'w'}, 25 [ASLDSH] = {.fun = unary, .txt = "loadsh", .letter = 'w'}, 26 [ASLDUH] = {.fun = unary, .txt = "loaduh", .letter = 'w'}, 27 [ASLDSW] = {.fun = unary, .txt = "loadsw", .letter = 'w'}, 28 [ASLDUW] = {.fun = unary, .txt = "loaduw", .letter = 'w'}, 29 [ASLDL] = {.fun = unary, .txt = "loadl", .letter = 'l'}, 30 [ASLDS] = {.fun = unary, .txt = "loads", .letter = 's'}, 31 [ASLDD] = {.fun = unary, .txt = "loadd", .letter = 'd'}, 32 33 [ASCOPYB] = {.fun = unary, .txt = "copy", .letter = 'b'}, 34 [ASCOPYH] = {.fun = unary, .txt = "copy", .letter = 'h'}, 35 [ASCOPYW] = {.fun = unary, .txt = "copy", .letter = 'w'}, 36 [ASCOPYL] = {.fun = unary, .txt = "copy", .letter = 'l'}, 37 [ASCOPYS] = {.fun = unary, .txt = "copy", .letter = 's'}, 38 [ASCOPYD] = {.fun = unary, .txt = "copy", .letter = 'd'}, 39 40 [ASSTB] = {.fun = store, .txt = "store", .letter = 'b'}, 41 [ASSTH] = {.fun = store, .txt = "store", .letter = 'h'}, 42 [ASSTW] = {.fun = store, .txt = "store", .letter = 'w'}, 43 [ASSTL] = {.fun = store, .txt = "store", .letter = 'l'}, 44 [ASSTM] = {.fun = blit}, 45 [ASSTS] = {.fun = store, .txt = "store", .letter = 's'}, 46 [ASSTD] = {.fun = store, .txt = "store", .letter = 'd'}, 47 48 [ASADDW] = {.fun = binary, .txt = "add", .letter = 'w'}, 49 [ASSUBW] = {.fun = binary, .txt = "sub", .letter = 'w'}, 50 [ASMULW] = {.fun = binary, .txt = "mul", .letter = 'w'}, 51 [ASMODW] = {.fun = binary, .txt = "rem", .letter = 'w'}, 52 [ASUMODW] = {.fun = binary, .txt = "urem", .letter = 'w'}, 53 [ASDIVW] = {.fun = binary, .txt = "div", .letter = 'w'}, 54 [ASUDIVW] = {.fun = binary, .txt = "udiv", .letter = 'w'}, 55 [ASSHLW] = {.fun = binary, .txt = "shl", .letter = 'w'}, 56 [ASSHRW] = {.fun = binary, .txt = "sar", .letter = 'w'}, 57 [ASUSHRW] = {.fun = binary, .txt = "shr", .letter = 'w'}, 58 [ASLTW] = {.fun = binary, .txt = "csltw", .letter = 'w'}, 59 [ASULTW] = {.fun = binary, .txt = "cultw", .letter = 'w'}, 60 [ASGTW] = {.fun = binary, .txt = "csgtw", .letter = 'w'}, 61 [ASUGTW] = {.fun = binary, .txt = "cugtw", .letter = 'w'}, 62 [ASLEW] = {.fun = binary, .txt = "cslew", .letter = 'w'}, 63 [ASULEW] = {.fun = binary, .txt = "culew", .letter = 'w'}, 64 [ASGEW] = {.fun = binary, .txt = "csgew", .letter = 'w'}, 65 [ASUGEW] = {.fun = binary, .txt = "cugew", .letter = 'w'}, 66 [ASEQW] = {.fun = binary, .txt = "ceqw", .letter = 'w'}, 67 [ASNEW] = {.fun = binary, .txt = "cnew", .letter = 'w'}, 68 [ASBANDW] = {.fun = binary, .txt = "and", .letter = 'w'}, 69 [ASBORW] = {.fun = binary, .txt = "or", .letter = 'w'}, 70 [ASBXORW] = {.fun = binary, .txt = "xor", .letter = 'w'}, 71 72 [ASADDL] = {.fun = binary, .txt = "add", .letter = 'l'}, 73 [ASSUBL] = {.fun = binary, .txt = "sub", .letter = 'l'}, 74 [ASMULL] = {.fun = binary, .txt = "mul", .letter = 'l'}, 75 [ASMODL] = {.fun = binary, .txt = "rem", .letter = 'l'}, 76 [ASUMODL] = {.fun = binary, .txt = "urem", .letter = 'l'}, 77 [ASDIVL] = {.fun = binary, .txt = "div", .letter = 'l'}, 78 [ASUDIVL] = {.fun = binary, .txt = "udiv", .letter = 'l'}, 79 [ASSHLL] = {.fun = binary, .txt = "shl", .letter = 'l'}, 80 [ASSHRL] = {.fun = binary, .txt = "sar", .letter = 'l'}, 81 [ASUSHRL] = {.fun = binary, .txt = "shr", .letter = 'l'}, 82 [ASLTL] = {.fun = binary, .txt = "csltl", .letter = 'w'}, 83 [ASULTL] = {.fun = binary, .txt = "cultl", .letter = 'w'}, 84 [ASGTL] = {.fun = binary, .txt = "csgtl", .letter = 'w'}, 85 [ASUGTL] = {.fun = binary, .txt = "cugtl", .letter = 'w'}, 86 [ASLEL] = {.fun = binary, .txt = "cslel", .letter = 'w'}, 87 [ASULEL] = {.fun = binary, .txt = "culel", .letter = 'w'}, 88 [ASGEL] = {.fun = binary, .txt = "csgel", .letter = 'w'}, 89 [ASUGEL] = {.fun = binary, .txt = "cugel", .letter = 'w'}, 90 [ASEQL] = {.fun = binary, .txt = "ceql", .letter = 'w'}, 91 [ASNEL] = {.fun = binary, .txt = "cnel", .letter = 'w'}, 92 [ASBANDL] = {.fun = binary, .txt = "and", .letter = 'l'}, 93 [ASBORL] = {.fun = binary, .txt = "or", .letter = 'l'}, 94 [ASBXORL] = {.fun = binary, .txt = "xor", .letter = 'l'}, 95 96 [ASADDS] = {.fun = binary, .txt = "add", .letter = 's'}, 97 [ASSUBS] = {.fun = binary, .txt = "sub", .letter = 's'}, 98 [ASMULS] = {.fun = binary, .txt = "mul", .letter = 's'}, 99 [ASDIVS] = {.fun = binary, .txt = "div", .letter = 's'}, 100 [ASLTS] = {.fun = binary, .txt = "clts", .letter = 'w'}, 101 [ASGTS] = {.fun = binary, .txt = "cgts", .letter = 'w'}, 102 [ASLES] = {.fun = binary, .txt = "cles", .letter = 'w'}, 103 [ASGES] = {.fun = binary, .txt = "cges", .letter = 'w'}, 104 [ASEQS] = {.fun = binary, .txt = "ceqs", .letter = 'w'}, 105 [ASNES] = {.fun = binary, .txt = "cnes", .letter = 'w'}, 106 107 [ASADDD] = {.fun = binary, .txt = "add", .letter = 'd'}, 108 [ASSUBD] = {.fun = binary, .txt = "sub", .letter = 'd'}, 109 [ASMULD] = {.fun = binary, .txt = "mul", .letter = 'd'}, 110 [ASDIVD] = {.fun = binary, .txt = "div", .letter = 'd'}, 111 [ASLTD] = {.fun = binary, .txt = "cltd", .letter = 'w'}, 112 [ASGTD] = {.fun = binary, .txt = "cgtd", .letter = 'w'}, 113 [ASLED] = {.fun = binary, .txt = "cled", .letter = 'w'}, 114 [ASGED] = {.fun = binary, .txt = "cged", .letter = 'w'}, 115 [ASEQD] = {.fun = binary, .txt = "ceqd", .letter = 'w'}, 116 [ASNED] = {.fun = binary, .txt = "cned", .letter = 'w'}, 117 118 [ASEXTBW] = {.fun = unary, .txt = "extsb", .letter = 'w'}, 119 [ASUEXTBW]= {.fun = unary, .txt = "extub", .letter = 'w'}, 120 [ASEXTBL] = {.fun = unary, .txt = "extsb", .letter = 'l'}, 121 [ASUEXTBL]= {.fun = unary, .txt = "extub", .letter = 'l'}, 122 [ASEXTHW] = {.fun = unary, .txt = "extsh", .letter = 'w'}, 123 [ASUEXTHW]= {.fun = unary, .txt = "extuh", .letter = 'w'}, 124 [ASEXTHL] = {.fun = unary, .txt = "extsh", .letter = 'l'}, 125 [ASUEXTHL]= {.fun = unary, .txt = "extuh", .letter = 'l'}, 126 [ASEXTWL] = {.fun = unary, .txt = "extsw", .letter = 'l'}, 127 [ASUEXTWL]= {.fun = unary, .txt = "extuw", .letter = 'l'}, 128 129 [ASSTOL] = {.fun = unary, .txt = "stosi", .letter = 'l'}, 130 [ASSTOUL] = {.fun = unary, .txt = "stoui", .letter = 'l'}, 131 [ASSTOW] = {.fun = unary, .txt = "stosi", .letter = 'w'}, 132 [ASSTOUW] = {.fun = unary, .txt = "stoui", .letter = 'w'}, 133 [ASDTOL] = {.fun = unary, .txt = "dtosi", .letter = 'l'}, 134 [ASDTOUL] = {.fun = unary, .txt = "dtoui", .letter = 'l'}, 135 [ASDTOW] = {.fun = unary, .txt = "dtosi", .letter = 'w'}, 136 [ASDTOUW] = {.fun = unary, .txt = "dtoui", .letter = 'w'}, 137 138 [ASSWTOD] = {.fun = unary, .txt = "swtof", .letter = 'd'}, 139 [ASUWTOD] = {.fun = unary, .txt = "uwtof", .letter = 'd'}, 140 [ASSWTOS] = {.fun = unary, .txt = "swtof", .letter = 's'}, 141 [ASUWTOS] = {.fun = unary, .txt = "uwtof", .letter = 's'}, 142 [ASSLTOD] = {.fun = unary, .txt = "sltof", .letter = 'd'}, 143 [ASULTOD] = {.fun = unary, .txt = "ultof", .letter = 'd'}, 144 [ASSLTOS] = {.fun = unary, .txt = "sltof", .letter = 's'}, 145 [ASULTOS] = {.fun = unary, .txt = "ultof", .letter = 's'}, 146 147 [ASEXTS] = {.fun = unary, .txt = "exts", .letter = 'd'}, 148 [ASTRUNCD] = {.fun = unary, .txt = "truncd", .letter = 's'}, 149 150 [ASNEGL] = {.fun = unary, .txt = "neg", .letter ='l'}, 151 [ASNEGW] = {.fun = unary, .txt = "neg", .letter ='w'}, 152 [ASNEGS] = {.fun = unary, .txt = "neg", .letter ='s'}, 153 [ASNEGD] = {.fun = unary, .txt = "neg", .letter ='d'}, 154 155 [ASBRANCH] = {.fun = branch}, 156 [ASJMP] = {.fun = jmp}, 157 [ASRET] = {.fun = ret}, 158 [ASCALL] = {.fun = call}, 159 [ASCALLE] = {.fun = ecall, .txt = ")"}, 160 [ASCALLEX] = {.fun = ecall, .txt = ", ...)"}, 161 [ASPAR] = {.fun = param, .txt = "%s %s, "}, 162 [ASPARE] = {.fun = param, .txt = "%s %s"}, 163 [ASALLOC] = {.fun = asalloc}, 164 [ASFORM] = {.fun = form2local}, 165 166 [ASVSTAR] = {.fun = vastart}, 167 [ASVARG] = {.fun = vaarg}, 168 }; 169 170 static char buff[ADDR_LEN]; 171 /* 172 * : is for user-defined Aggregate Types 173 * $ is for globals (represented by a pointer) 174 * % is for function-scope temporaries 175 * @ is for block labels 176 */ 177 static char 178 sigil(Symbol *sym) 179 { 180 switch (sym->kind) { 181 case SEXTRN: 182 case SGLOB: 183 case SPRIV: 184 case SLOCAL: 185 return '$'; 186 case SAUTO: 187 case STMP: 188 return '%'; 189 case SLABEL: 190 return '@'; 191 default: 192 abort(); 193 } 194 } 195 196 static char * 197 symname(Symbol *sym) 198 { 199 char c = sigil(sym); 200 201 if (sym->name) { 202 switch (sym->kind) { 203 case SEXTRN: 204 case SGLOB: 205 sprintf(buff, "%c%s", c, sym->name); 206 return buff; 207 case SLOCAL: 208 case SPRIV: 209 case SAUTO: 210 sprintf(buff, "%c%s.L%u", c, sym->name, sym->id); 211 return buff; 212 default: 213 abort(); 214 } 215 } 216 sprintf(buff, "%c.L%u", c, sym->numid); 217 218 return buff; 219 } 220 221 static void 222 emitconst(Node *np) 223 { 224 switch (np->type.size) { 225 case 1: 226 printf("%d", (int) np->u.i & 0xFF); 227 break; 228 case 2: 229 printf("%d", (int) np->u.i & 0xFFFF); 230 break; 231 case 4: 232 printf("%ld", (long) np->u.i & 0xFFFFFFFF); 233 break; 234 case 8: 235 printf("%lld", (long long) np->u.i); 236 break; 237 default: 238 abort(); 239 } 240 } 241 242 static void 243 emittree(Node *np) 244 { 245 if (!np) 246 return; 247 248 switch (np->op) { 249 case OSTRING: 250 pprint(np->u.s); 251 free(np->u.s); 252 np->u.s = NULL; 253 break; 254 case OCONST: 255 emitconst(np); 256 break; 257 case OADDR: 258 emittree(np->left); 259 break; 260 case OMEM: 261 fputs(symname(np->u.sym), stdout); 262 break; 263 default: 264 emittree(np->left); 265 printf(" %c ", np->op); 266 emittree(np->right); 267 break; 268 } 269 } 270 271 static char * 272 size2asm(Type *tp) 273 { 274 static char spec[ADDR_LEN]; 275 276 if (tp->flags & STRF) { 277 return "b"; 278 } else if (tp->flags & INTF) { 279 switch (tp->size) { 280 case 1: 281 return "b"; 282 case 2: 283 return "h"; 284 case 4: 285 return "w"; 286 case 8: 287 return "l"; 288 } 289 } else if (tp->flags & FLOATF) { 290 if (tp->size == 4) 291 return "s"; 292 else if (tp->size == 8) 293 return "d"; 294 } 295 296 abort(); 297 } 298 299 void 300 defglobal(Symbol *sym) 301 { 302 Type *tp = &sym->type; 303 304 if (sym->kind == SEXTRN) 305 return; 306 if (sym->kind == SGLOB) 307 fputs("export ", stdout); 308 if ((tp->flags & INITF) == 0) 309 fputs("common ", stdout); 310 311 printf("data %s = align %d {\n", 312 symname(sym), 313 tp->align); 314 if ((tp->flags & INITF) == 0) 315 printf("\tz\t%lu\n}\n", tp->size); 316 } 317 318 void 319 defpar(Symbol *sym) 320 { 321 if (sym->kind == SREG) 322 sym->kind = SAUTO; 323 sym->type.flags |= PARF; 324 } 325 326 void 327 defvar(Symbol *sym) 328 { 329 if (sym->kind == SREG) 330 sym->kind = SAUTO; 331 } 332 333 void 334 data(Node *np) 335 { 336 printf("\t%s\t", size2asm(&np->type)); 337 emittree(np); 338 putchar(','); 339 putchar('\n'); 340 } 341 342 static char * 343 size2stack(Type *tp) 344 { 345 static char spec[ADDR_LEN]; 346 347 if (tp->flags & INTF) { 348 switch (tp->size) { 349 case 1: 350 case 2: 351 case 4: 352 return "w"; 353 case 8: 354 return "l"; 355 } 356 } else if (tp->flags & FLOATF) { 357 if (tp->size == 4) 358 return "s"; 359 else if (tp->size == 8) 360 return "d"; 361 } else if (tp->flags & (ARRF|AGGRF)) { 362 sprintf(spec, ":.%u", tp->id); 363 return spec; 364 } else if (tp->size == 0) { 365 return "w"; 366 } 367 abort(); 368 } 369 370 void 371 deftype(Type *tp) 372 { 373 printf("type :.%u = align %d { %lu }\n", 374 tp->id, tp->align, tp->size); 375 } 376 377 static void 378 getbblocks(void) 379 { 380 Inst *i; 381 382 if (!prog) 383 return; 384 385 prog->flags |= BBENTRY; 386 for (pc = prog; pc; pc = pc->next) { 387 switch (pc->op) { 388 case ASBRANCH: 389 i = pc->from2.u.sym->u.inst; 390 i->flags |= BBENTRY; 391 case ASJMP: 392 i = pc->from1.u.sym->u.inst; 393 i->flags |= BBENTRY; 394 case ASRET: 395 if (pc->next) 396 pc->next->flags |= BBENTRY; 397 break; 398 } 399 } 400 } 401 402 void 403 writeout(void) 404 { 405 Symbol *p; 406 Type *tp; 407 char *sep; 408 int haslabel = 0; 409 410 getbblocks(); 411 412 if (curfun->kind == SGLOB) 413 fputs("export ", stdout); 414 printf("function %s %s(", size2stack(&curfun->rtype), symname(curfun)); 415 416 /* declare formal parameters */ 417 sep = ""; 418 for (p = locals; p; p = p->next) { 419 if ((p->type.flags & PARF) == 0) 420 continue; 421 printf("%s%s %s%s", 422 sep, size2stack(&p->type), 423 symname(p), 424 (p->type.flags & AGGRF) ? "" : ".val"); 425 sep = ","; 426 } 427 printf("%s)\n{\n", (curfun->type.flags&ELLIPS) ? ", ..." : ""); 428 429 /* emit assembler instructions */ 430 for (pc = prog; pc; pc = pc->next) { 431 if (pc->label) { 432 haslabel = 1; 433 printf("%s\n", symname(pc->label)); 434 } 435 if (pc->op == ASLABEL) 436 continue; 437 if (pc->flags&BBENTRY && !haslabel) 438 printf("%s\n", symname(newlabel())); 439 (*optbl[pc->op].fun)(); 440 if (!pc->label) 441 haslabel = 0; 442 } 443 444 puts("}"); 445 } 446 447 static char * 448 addr2txt(Addr *a) 449 { 450 switch (a->kind) { 451 case SCONST: 452 sprintf(buff, "%llu", (unsigned long long) a->u.i); 453 return buff; 454 case SAUTO: 455 case SLABEL: 456 case STMP: 457 case SGLOB: 458 case SEXTRN: 459 case SPRIV: 460 case SLOCAL: 461 return symname(a->u.sym); 462 default: 463 abort(); 464 } 465 } 466 467 static void 468 binary(void) 469 { 470 struct opdata *p = &optbl[pc->op]; 471 char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN]; 472 473 strcpy(to, addr2txt(&pc->to)); 474 strcpy(from1, addr2txt(&pc->from1)); 475 strcpy(from2, addr2txt(&pc->from2)); 476 printf("\t%s =%c\t%s\t%s,%s\n", to, p->letter, p->txt, from1, from2); 477 } 478 479 static void 480 blit(void) 481 { 482 Type *tp = &pc->to.u.sym->type; 483 char to[ADDR_LEN], from[ADDR_LEN]; 484 485 strcpy(to, addr2txt(&pc->to)); 486 strcpy(from, addr2txt(&pc->from1)); 487 printf("\t\tblit\t%s,%s,%lu\n", from, to, tp->size); 488 } 489 490 static void 491 store(void) 492 { 493 struct opdata *p = &optbl[pc->op]; 494 char to[ADDR_LEN], from[ADDR_LEN]; 495 496 strcpy(to, addr2txt(&pc->to)); 497 strcpy(from, addr2txt(&pc->from1)); 498 printf("\t\t%s%c\t%s,%s\n", p->txt, p->letter, from, to); 499 } 500 501 static void 502 unary(void) 503 { 504 struct opdata *p = &optbl[pc->op]; 505 char to[ADDR_LEN], from[ADDR_LEN]; 506 507 strcpy(to, addr2txt(&pc->to)); 508 strcpy(from, addr2txt(&pc->from1)); 509 printf("\t%s =%c\t%s\t%s\n", to, p->letter, p->txt, from); 510 } 511 512 static void 513 call(void) 514 { 515 char to[ADDR_LEN], from[ADDR_LEN]; 516 Symbol *sym = pc->to.u.sym; 517 518 strcpy(to, addr2txt(&pc->to)); 519 strcpy(from, addr2txt(&pc->from1)); 520 printf("\t%s =%s\tcall\t%s(", 521 to, size2stack(&sym->type), from); 522 } 523 524 static void 525 param(void) 526 { 527 Symbol *sym = pc->from2.u.sym; 528 529 printf(optbl[pc->op].txt, 530 size2stack(&sym->type), addr2txt(&pc->from1)); 531 } 532 533 static void 534 ecall(void) 535 { 536 struct opdata *p = &optbl[pc->op]; 537 538 puts(p->txt); 539 } 540 541 static void 542 ret(void) 543 { 544 if (pc->from1.kind == SNONE) 545 puts("\t\tret"); 546 else 547 printf("\t\tret\t%s\n", addr2txt(&pc->from1)); 548 } 549 550 static void 551 jmp(void) 552 { 553 printf("\t\tjmp\t%s\n", addr2txt(&pc->from1)); 554 } 555 556 static void 557 branch(void) 558 { 559 char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN]; 560 561 strcpy(to, addr2txt(&pc->to)); 562 strcpy(from1, addr2txt(&pc->from1)); 563 strcpy(from2, addr2txt(&pc->from2)); 564 printf("\t\tjnz\t%s,%s,%s\n", to, from1, from2); 565 } 566 567 static void 568 vastart(void) 569 { 570 printf("\t\tvastart %s\n", addr2txt(&pc->from1)); 571 } 572 573 static void 574 vaarg(void) 575 { 576 Symbol *sym = pc->to.u.sym; 577 Type *tp = &sym->type; 578 char to[ADDR_LEN], from[ADDR_LEN]; 579 580 strcpy(to, addr2txt(&pc->to)); 581 strcpy(from, addr2txt(&pc->from1)); 582 printf("\t\t%s =%s vaarg %s\n", to, size2asm(tp), from); 583 } 584 585 static void 586 asalloc(void) 587 { 588 Symbol *sym = pc->to.u.sym; 589 Type *tp = &sym->type; 590 extern Type ptrtype; 591 592 printf("\t%s =%s\talloc%d\t%lu\n", 593 symname(sym), size2asm(&ptrtype), tp->align+3 & ~3, tp->size); 594 } 595 596 static void 597 form2local(void) 598 { 599 Symbol *sym = pc->to.u.sym; 600 Type *tp = &sym->type; 601 char *name = symname(sym); 602 603 printf("\t\tstore%s\t%s.val,%s\n", size2asm(tp), name, name); 604 } 605 606 void 607 endinit(void) 608 { 609 puts("}"); 610 }