cc1.om (26492B)
1 struct compiler { 2 // Allocator 3 a: *alloc; 4 5 err: *file; 6 7 // Parser 8 p: *parser; 9 10 // Context 11 filename: *byte; 12 lineno: int; 13 colno: int; 14 15 // Assembler 16 s: *assembler; 17 18 // Namespace 19 decls: *decl; 20 21 // C Output 22 do_cout: int; 23 cout: *file; 24 25 // Call graph 26 call_out: *file; 27 28 // Entry points 29 start: *label; 30 kstart: *label; 31 32 // Usage stack 33 used_top: *decl; 34 35 lex_action: **byte; 36 lex_action_len: int; 37 lex_action_cap: int; 38 nfa_id: int; 39 dfa_id: int; 40 dfa_cache: *rbnode; 41 42 mach: *machine; 43 } 44 45 struct machine { 46 id: int; 47 emit_builtin: func(c: *compiler); 48 output_ir: func(c: *compiler, d: *decl); 49 } 50 51 struct parser { 52 a: *alloc; 53 c: *compiler; 54 err: *file; 55 } 56 57 func cshow_context(c: *compiler) { 58 fputs(c.err, "on "); 59 if (c.filename) { 60 fputs(c.err, c.filename); 61 } 62 fputs(c.err, ":"); 63 fputd(c.err, c.lineno); 64 fputs(c.err, ":"); 65 fputd(c.err, c.colno); 66 fputs(c.err, "\n"); 67 } 68 69 func cdie(c: *compiler, msg: *byte) { 70 cshow_context(c); 71 fputs(c.err, "cdie: "); 72 fputs(c.err, msg); 73 fputs(c.err, "\n"); 74 exit(1); 75 } 76 77 func setup_parser(c: *compiler, err: *file): *parser { 78 var p: *parser; 79 p = alloc(c.a, sizeof(*p)) as *parser; 80 p.a = c.a; 81 p.c = c; 82 p.err = err; 83 return p; 84 } 85 86 func comp_setup(a: *alloc, err: *file): *compiler { 87 var c: *compiler; 88 89 c = alloc(a, sizeof(*c)) as *compiler; 90 91 c.a = a; 92 93 c.err = err; 94 95 c.p = setup_parser(c, err); 96 97 c.filename = nil; 98 c.lineno = 0; 99 c.colno = 0; 100 101 c.s = setup_assembler(a); 102 103 c.decls = nil; 104 105 c.do_cout = 0; 106 c.cout = nil; 107 108 c.start = nil; 109 c.kstart = nil; 110 111 c.used_top = nil; 112 113 return c; 114 } 115 116 func open_coutput(c: *compiler, filename: *byte) { 117 var fd: int; 118 119 if (c.cout) { 120 die("multiple output files"); 121 } 122 123 fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, (6 << 6) + (6 << 3) + 6); 124 if (fd < 0) { 125 die("open_coutput: failed to open output"); 126 } 127 128 c.cout = fopen(fd, c.a); 129 c.cout.noflush = 1; 130 } 131 132 func compile(c: *compiler, p: *node) { 133 var n: *node; 134 var d: *decl; 135 var v: *decl; 136 var kind: int; 137 138 // Process enum and struct declarations 139 n = p; 140 loop { 141 if (!n) { 142 break; 143 } 144 145 kind = n.a.kind; 146 if (kind == N_STRUCT) { 147 defstruct(c, n.a); 148 } else if (kind == N_UNION) { 149 defunion(c, n.a); 150 } else if (kind == N_ENUM) { 151 defenum(c, n.a); 152 } else if (kind != N_FUNC && kind != N_FUNCDECL && kind != N_LEXER && kind != N_GRAMMAR) { 153 cdie(c, "invalid decl"); 154 } 155 156 n = n.b; 157 } 158 159 // Process function declarations 160 n = p; 161 loop { 162 if (!n) { 163 break; 164 } 165 166 kind = n.a.kind; 167 if (kind == N_FUNCDECL) { 168 defextern(c, n.a); 169 } else if (kind == N_FUNC) { 170 defun(c, n.a); 171 } else if (kind == N_LEXER) { 172 lexer_compile(c, n.a, nil); 173 } else if (kind == N_GRAMMAR) { 174 lalr_compiler(c, n.a, nil); 175 } 176 177 n = n.b; 178 } 179 180 // Allocate structs 181 d = first_decl(c); 182 loop { 183 if (!d) { 184 break; 185 } 186 187 if (d.struct_defined) { 188 layout_struct(c, d); 189 } 190 191 d = next_decl(c, d); 192 } 193 194 // Typecheck functions and translate to ir 195 d = first_decl(c); 196 loop { 197 if (!d) { 198 break; 199 } 200 201 if d.func_defined && d.func_def { 202 typecheck_stmt(c, d, d.func_def.b); 203 d.func_ir = func_to_ir(c, d.func_def); 204 } 205 206 d = next_decl(c, d); 207 } 208 209 // Check usage 210 d = find(c, "_start", nil, 0); 211 if (d && d.func_defined) { 212 c.start = d.func_label; 213 mark_func_used(c, nil, d); 214 } 215 216 d = find(c, "_kstart", nil, 0); 217 if (d && d.func_defined) { 218 c.kstart = d.func_label; 219 mark_func_used(c, nil, d); 220 } 221 222 check_usage(c); 223 224 d = find(c, "_isr0", nil, 0); 225 if d && d.func_used { 226 v = find(c, "_isr", nil, 0); 227 if (v && v.func_defined) { 228 mark_func_used(c, d, v); 229 } 230 } 231 232 d = find(c, "_ssr0", nil, 0); 233 if d && d.func_used { 234 v = find(c, "_ssr", nil, 0); 235 if (v && v.func_defined) { 236 mark_func_used(c, d, v); 237 } 238 } 239 240 check_usage(c); 241 242 if c.call_out { 243 fflush(c.call_out); 244 } 245 246 // Do optimization passes 247 d = first_decl(c); 248 loop { 249 if (!d) { 250 break; 251 } 252 253 if d.func_used && d.func_defined && d.func_ir { 254 ir_optimize(d.func_ir); 255 } 256 257 d = next_decl(c, d); 258 } 259 260 // Compile the ir to output 261 d = first_decl(c); 262 loop { 263 if (!d) { 264 break; 265 } 266 267 if d.func_used && d.func_defined && d.func_ir { 268 c.mach.output_ir(c, d); 269 } 270 271 d = next_decl(c, d); 272 } 273 } 274 275 func mark_func_used(c: *compiler, d: *decl, v: *decl) { 276 var edge: *decl; 277 278 if d { 279 // name uses member 280 edge = find(c, d.name, v.name, 1); 281 if c.call_out && !edge.used_forward { 282 fputs(c.call_out, d.name); 283 fputs(c.call_out, " -> "); 284 fputs(c.call_out, v.name); 285 fputs(c.call_out, "\n"); 286 } 287 edge.used_forward = 1; 288 // member uses name 289 edge = find(c, v.name, d.name, 1); 290 edge.used_backward = 1; 291 } 292 293 if v.func_used { 294 return; 295 } 296 297 v.func_used = 1; 298 v.used_next = c.used_top; 299 c.used_top = v; 300 } 301 302 func mark_ir_expr(c: *compiler, d: *decl, op: *irop) { 303 var v: *decl; 304 var kind: int; 305 306 if op.kind == IOP_FUNC { 307 v = find(c, op.s, nil, 0); 308 if !v || !v.func_defined { 309 return; 310 } 311 312 mark_func_used(c, d, v); 313 } 314 315 if op.a { 316 mark_ir_expr(c, d, op.a); 317 } 318 319 if op.b { 320 mark_ir_expr(c, d, op.b); 321 } 322 } 323 324 func mark_ir_used(c: *compiler, d: *decl) { 325 var ic: *irfunc; 326 var ib: *irblock; 327 var i: int; 328 var j: int; 329 330 ic = d.func_ir; 331 332 i = 0; 333 loop { 334 if i == ic.blocks_len { 335 break; 336 } 337 338 ib = ic.blocks[i]; 339 340 j = 0; 341 loop { 342 if j == ib.ops_len { 343 break; 344 } 345 346 mark_ir_expr(c, d, ib.ops[j]); 347 348 j = j + 1; 349 } 350 351 i = i + 1; 352 } 353 } 354 355 func check_usage(c: *compiler) { 356 var d: *decl; 357 358 loop { 359 d = c.used_top; 360 if !d { 361 break; 362 } 363 c.used_top = d.used_next; 364 365 if d.func_ir { 366 mark_ir_used(c, d); 367 } 368 } 369 } 370 371 func defextern(c: *compiler, n: *node): *decl { 372 var d: *decl; 373 var name: *byte; 374 var t: *type; 375 376 c.filename = n.filename; 377 c.lineno = n.lineno; 378 c.colno = n.colno; 379 380 name = n.a.s; 381 382 t = prototype(c, n.b); 383 384 d = find(c, name, nil, 1); 385 386 // TODO This is a quick hack but it's short. 387 // Mark functions in syscall.om as coming from stdlib 388 // This changes the behavior of ircout to link to libc 389 // for these functions. 390 if strcmp(n.filename, "syscall.om") == 0 { 391 d.func_stdlib = 1; 392 } 393 394 if d.func_defined { 395 unify(c, d.func_type, t); 396 return d; 397 } 398 399 d.func_defined = 1; 400 d.func_type = t; 401 402 return d; 403 } 404 405 func defun(c: *compiler, funcdef: *node) { 406 var d: *decl; 407 var name: *byte; 408 var v: *decl; 409 var t: *type; 410 var n: *node; 411 412 d = defextern(c, funcdef.a); 413 414 if d.func_defined == 2 { 415 die("duplicate function"); 416 } 417 d.func_defined = 2; 418 419 d.func_def = funcdef; 420 421 n = funcdef.a.b.a; 422 loop { 423 if (!n) { 424 break; 425 } 426 427 c.filename = n.filename; 428 c.lineno = n.lineno; 429 c.colno = n.colno; 430 c.s.filename = n.filename; 431 c.s.lineno = n.lineno; 432 433 name = n.a.a.s; 434 t = prototype(c, n.a.b); 435 436 v = find(c, d.name, name, 1); 437 if (v.var_defined) { 438 cdie(c, "duplicate argument"); 439 } 440 441 v.var_defined = 1; 442 v.var_type = t; 443 444 n = n.b; 445 } 446 447 hoist_locals(c, d, funcdef.b); 448 } 449 450 func defstruct(c: *compiler, n: *node) { 451 var name: *byte; 452 var d: *decl; 453 454 name = n.a.s; 455 456 c.filename = n.filename; 457 c.lineno = n.lineno; 458 c.colno = n.colno; 459 460 if (!strcmp(name, "int") || !strcmp(name, "byte") || !strcmp(name, "func")) { 461 cdie(c, "reserved word"); 462 } 463 464 d = find(c, name, nil, 1); 465 466 if (d.struct_defined) { 467 cdie(c, "duplicate struct"); 468 } 469 470 d.struct_defined = 1; 471 d.struct_def = n; 472 d.struct_type = prototype(c, n.a); 473 } 474 475 func defunion(c: *compiler, n: *node) { 476 var name: *byte; 477 var d: *decl; 478 479 name = n.a.s; 480 481 c.filename = n.filename; 482 c.lineno = n.lineno; 483 c.colno = n.colno; 484 485 if (!strcmp(name, "int") || !strcmp(name, "byte") || !strcmp(name, "func")) { 486 cdie(c, "reserved word"); 487 } 488 489 d = find(c, name, nil, 1); 490 491 if (d.struct_defined) { 492 cdie(c, "duplicate struct"); 493 } 494 495 d.struct_defined = 1; 496 d.struct_def = n; 497 d.struct_type = prototype(c, n.a); 498 } 499 500 func define_enum_tag(c: *compiler, name: *byte, value: int) { 501 var d: *decl; 502 503 d = find(c, name, nil, 1); 504 505 if d.enum_defined { 506 cdie(c, "duplicate enum"); 507 } 508 509 d.enum_defined = 1; 510 d.enum_value = value; 511 } 512 513 func define_ir_func(c: *compiler, ic: *irfunc, t: *type) { 514 var d: *decl; 515 516 d = find(c, ic.name, nil, 1); 517 518 if d.func_defined == 2 { 519 cdie(c, "duplicate func"); 520 } 521 522 if d.func_defined { 523 unify(c, d.func_type, t); 524 } 525 526 d.func_defined = 2; 527 d.func_type = t; 528 d.func_ir = ic; 529 } 530 531 func defenum(c: *compiler, n: *node) { 532 var i: int; 533 var name: *byte; 534 535 n = n.a; 536 i = 0; 537 loop { 538 if (!n) { 539 break; 540 } 541 542 c.filename = n.a.filename; 543 c.lineno = n.a.lineno; 544 c.colno = n.a.colno; 545 546 name = n.a.a.s; 547 548 if (n.a.b) { 549 i = n.a.b.n; 550 } 551 552 define_enum_tag(c, name, i); 553 554 i = i + 1; 555 n = n.b; 556 } 557 } 558 559 func layout_struct(c: *compiler, d: *decl) { 560 var m: *node; 561 var offset: int; 562 var name: *byte; 563 var md: *decl; 564 var t: *type; 565 566 if (d.struct_layout_done) { 567 if (d.struct_layout_done == 2) { 568 cdie(c, "circular struct definition"); 569 } 570 571 return; 572 } 573 574 d.struct_layout_done = 2; 575 576 m = d.struct_def.b; 577 578 offset = 0; 579 loop { 580 if (!m) { 581 break; 582 } 583 584 c.filename = m.a.filename; 585 c.lineno = m.a.lineno; 586 c.colno = m.a.colno; 587 588 name = m.a.a.s; 589 t = prototype(c, m.a.b); 590 591 md = find(c, d.name, name, 1); 592 593 if (d.member_defined) { 594 cdie(c, "duplicate member"); 595 } 596 597 md.member_defined = 1; 598 md.member_type = t; 599 md.member_offset = offset; 600 601 offset = offset + type_sizeof(c, t); 602 603 m = m.b; 604 } 605 606 d.struct_size = offset; 607 d.struct_layout_done = 1; 608 } 609 610 func layout_union(c: *compiler, d: *decl) { 611 var m: *node; 612 var size: int; 613 var member_size: int; 614 var name: *byte; 615 var md: *decl; 616 var t: *type; 617 618 if (d.struct_layout_done) { 619 if (d.struct_layout_done == 2) { 620 cdie(c, "circular struct definition"); 621 } 622 623 return; 624 } 625 626 d.struct_layout_done = 2; 627 628 m = d.struct_def.b; 629 630 size = 0; 631 loop { 632 if (!m) { 633 break; 634 } 635 636 c.filename = m.a.filename; 637 c.lineno = m.a.lineno; 638 c.colno = m.a.colno; 639 640 name = m.a.a.s; 641 t = prototype(c, m.a.b); 642 643 md = find(c, d.name, name, 1); 644 645 if (d.member_defined) { 646 cdie(c, "duplicate member"); 647 } 648 649 md.member_defined = 1; 650 md.member_type = t; 651 md.member_offset = 0; 652 653 member_size = type_sizeof(c, t); 654 if member_size > size { 655 size = member_size; 656 } 657 658 m = m.b; 659 } 660 661 d.struct_size = size; 662 d.struct_layout_done = 1; 663 } 664 665 func typecheck_expr(c: *compiler, d: *decl, n: *node, rhs: int) { 666 var v: *decl; 667 var kind: int; 668 669 c.filename = n.filename; 670 c.lineno = n.lineno; 671 c.colno = n.colno; 672 673 kind = n.kind; 674 if (kind == N_STR) { 675 if (!rhs) { 676 cdie(c, "str is not an lexpr"); 677 } 678 679 n.t = mktype1(c, TY_PTR, mktype0(c, TY_BYTE)); 680 } else if (kind == N_NIL) { 681 if (!rhs) { 682 cdie(c, "nil is not an lexpr"); 683 } 684 685 n.t = mktype0(c, TY_NIL); 686 } else if (kind == N_NUM) { 687 if (!rhs) { 688 cdie(c, "num is not an lexpr"); 689 } 690 691 n.t = mktype0(c, TY_INT); 692 } else if (kind == N_CHAR) { 693 if (!rhs) { 694 cdie(c, "char is not an lexpr"); 695 } 696 697 n.t = mktype0(c, TY_INT); 698 } else if (kind == N_EXPRLIST) { 699 if (!rhs) { 700 cdie(c, "call is not an lexpr"); 701 } 702 703 if (n.b) { 704 typecheck_expr(c, d, n.b, 1); 705 } 706 707 typecheck_expr(c, d, n.a, 1); 708 709 if (n.b) { 710 n.t = mktype2(c, TY_ARG, n.a.t, n.b.t); 711 } else { 712 n.t = mktype1(c, TY_ARG, n.a.t); 713 } 714 } else if (kind == N_CALL) { 715 if (!rhs) { 716 cdie(c, "call is not an lexpr"); 717 } 718 719 if (n.b) { 720 typecheck_expr(c, d, n.b, 1); 721 } 722 723 if (n.a.kind == N_IDENT) { 724 v = find(c, n.a.s, nil, 0); 725 if (v && v.enum_defined) { 726 cdie(c, "type error"); 727 } 728 729 v = find(c, d.name, n.a.s, 0); 730 if (v && v.var_defined) { 731 n.a.t = v.var_type; 732 } else if !strcmp(n.a.s, "_include") { 733 v = find(c, n.a.s, nil, 0); 734 if (!v || !v.func_defined) { 735 cdie(c, "no such function"); 736 } 737 n.a.t = v.func_type; 738 } else { 739 v = find(c, n.a.s, nil, 0); 740 if (!v || !v.func_defined) { 741 cdie(c, "no such function"); 742 } 743 n.a.t = v.func_type; 744 } 745 } else { 746 typecheck_expr(c, d, n.a, 1); 747 } 748 749 if (n.a.t.kind != TY_FUNC) { 750 cdie(c, "calling not a function"); 751 } 752 753 if (n.b) { 754 unify(c, n.a.t.arg, n.b.t); 755 } else { 756 unify(c, n.a.t.arg, nil); 757 } 758 759 n.t = n.a.t.val; 760 } else if (kind == N_DOT) { 761 typecheck_expr(c, d, n.a, 0); 762 763 if (n.a.t.kind == TY_PTR) { 764 if (n.a.t.val.kind != TY_STRUCT && n.a.t.val.kind != TY_UNION) { 765 cdie(c, "dot not a struct"); 766 } 767 768 v = find(c, n.a.t.val.st.name, n.b.s, 0); 769 } else { 770 if (n.a.t.kind != TY_STRUCT && n.a.t.kind != TY_UNION) { 771 cdie(c, "dot not a struct"); 772 } 773 774 v = find(c, n.a.t.st.name, n.b.s, 0); 775 } 776 777 if (!v || !v.member_defined) { 778 cdie(c, "no such member"); 779 } 780 781 n.t = v.member_type; 782 } else if (kind == N_IDENT) { 783 v = find(c, n.s, nil, 0); 784 if (v && v.enum_defined) { 785 n.t = mktype0(c, TY_INT); 786 return; 787 } 788 789 v = find(c, d.name, n.s, 0); 790 if (v && v.var_defined) { 791 n.t = v.var_type; 792 return; 793 } 794 795 v = find(c, n.s, nil, 0); 796 if (v && v.func_defined) { 797 n.t = v.func_type; 798 return; 799 } 800 801 fputs(nil, n.s); 802 cdie(c, "no such variable"); 803 } else if (kind == N_ASSIGN) { 804 if (!rhs) { 805 cdie(c, "assign is not an lexpr"); 806 } 807 808 typecheck_expr(c, d, n.b, 1); 809 typecheck_expr(c, d, n.a, 0); 810 811 unify(c, n.a.t, n.b.t); 812 813 n.t = n.a.t; 814 } else if (kind == N_SIZEOF) { 815 if (!rhs) { 816 cdie(c, "sizeof is not an lexpr"); 817 } 818 819 typecheck_expr(c, d, n.a, 0); 820 821 n.t = mktype0(c, TY_INT); 822 } else if (kind == N_REF) { 823 if (!rhs) { 824 cdie(c, "ref is not an lexpr"); 825 } 826 827 typecheck_expr(c, d, n.a, 0); 828 829 n.t = mktype1(c, TY_PTR, n.a.t); 830 } else if (kind == N_DEREF) { 831 typecheck_expr(c, d, n.a, 1); 832 833 if (n.a.t.kind != TY_PTR) { 834 cdie(c, "deref not a pointer"); 835 } 836 837 n.t = n.a.t.val; 838 } else if (kind == N_INDEX) { 839 typecheck_expr(c, d, n.a, 1); 840 typecheck_expr(c, d, n.b, 1); 841 842 if (n.a.t.kind != TY_PTR) { 843 cdie(c, "not a pointer"); 844 } 845 846 if (!type_isint(n.b.t)) { 847 cdie(c, "index: not an int"); 848 } 849 850 n.t = n.a.t.val; 851 } else if (kind == N_LT) { 852 if (!rhs) { 853 cdie(c, "not lexpr"); 854 } 855 856 typecheck_expr(c, d, n.b, 1); 857 typecheck_expr(c, d, n.a, 1); 858 859 unify(c, n.a.t, n.b.t); 860 861 if (!type_isprim(n.a.t)) { 862 cdie(c, "lt: not an int"); 863 } 864 865 n.t = n.a.t; 866 } else if (kind == N_GT) { 867 if (!rhs) { 868 cdie(c, "not lexpr"); 869 } 870 871 typecheck_expr(c, d, n.b, 1); 872 typecheck_expr(c, d, n.a, 1); 873 874 unify(c, n.a.t, n.b.t); 875 876 if (!type_isprim(n.a.t)) { 877 cdie(c, "gt: not an int"); 878 } 879 880 n.t = n.a.t; 881 } else if (kind == N_LE) { 882 if (!rhs) { 883 cdie(c, "not lexpr"); 884 } 885 886 typecheck_expr(c, d, n.b, 1); 887 typecheck_expr(c, d, n.a, 1); 888 889 unify(c, n.a.t, n.b.t); 890 891 if (!type_isprim(n.a.t)) { 892 cdie(c, "le: not an int"); 893 } 894 895 n.t = n.a.t; 896 } else if (kind == N_GE) { 897 if (!rhs) { 898 cdie(c, "not lexpr"); 899 } 900 901 typecheck_expr(c, d, n.b, 1); 902 typecheck_expr(c, d, n.a, 1); 903 904 unify(c, n.a.t, n.b.t); 905 906 if (!type_isprim(n.a.t)) { 907 cdie(c, "ge: not an int"); 908 } 909 910 n.t = n.a.t; 911 } else if (kind == N_EQ) { 912 if (!rhs) { 913 cdie(c, "not lexpr"); 914 } 915 916 typecheck_expr(c, d, n.b, 1); 917 typecheck_expr(c, d, n.a, 1); 918 919 unify(c, n.a.t, n.b.t); 920 921 if (!type_isprim(n.a.t)) { 922 cdie(c, "eq: not an int"); 923 } 924 925 n.t = n.a.t; 926 } else if (kind == N_NE) { 927 if (!rhs) { 928 cdie(c, "not lexpr"); 929 } 930 931 typecheck_expr(c, d, n.b, 1); 932 typecheck_expr(c, d, n.a, 1); 933 934 unify(c, n.a.t, n.b.t); 935 936 if (!type_isprim(n.a.t)) { 937 cdie(c, "ne: not an int"); 938 } 939 940 n.t = n.a.t; 941 } else if (kind == N_BNOT) { 942 if (!rhs) { 943 cdie(c, "not lexpr"); 944 } 945 946 typecheck_expr(c, d, n.a, 1); 947 948 if (!type_isprim(n.a.t)) { 949 cdie(c, "not an prim"); 950 } 951 952 n.t = mktype0(c, TY_INT); 953 } else if (kind == N_BOR) { 954 if (!rhs) { 955 cdie(c, "not lexpr"); 956 } 957 958 typecheck_expr(c, d, n.a, 1); 959 typecheck_expr(c, d, n.b, 1); 960 961 if (!type_isprim(n.a.t)) { 962 cdie(c, "not an prim"); 963 } 964 965 if (!type_isprim(n.b.t)) { 966 cdie(c, "not an prim"); 967 } 968 969 n.t = mktype0(c, TY_INT); 970 } else if (kind == N_BAND) { 971 if (!rhs) { 972 cdie(c, "not lexpr"); 973 } 974 975 typecheck_expr(c, d, n.a, 1); 976 typecheck_expr(c, d, n.b, 1); 977 978 if (!type_isprim(n.a.t)) { 979 cdie(c, "not an prim"); 980 } 981 982 if (!type_isprim(n.b.t)) { 983 cdie(c, "not an prim"); 984 } 985 986 n.t = mktype0(c, TY_INT); 987 } else if (kind == N_POS) { 988 if (!rhs) { 989 cdie(c, "not lexpr"); 990 } 991 992 typecheck_expr(c, d, n.a, 1); 993 994 if (!type_isint(n.a.t)) { 995 cdie(c, "pos: not an int"); 996 } 997 998 n.t = n.a.t; 999 } else if (kind == N_NEG) { 1000 if (!rhs) { 1001 cdie(c, "not lexpr"); 1002 } 1003 1004 typecheck_expr(c, d, n.a, 1); 1005 1006 if (!type_isint(n.a.t)) { 1007 cdie(c, "neg: not an int"); 1008 } 1009 1010 n.t = n.a.t; 1011 } else if (kind == N_NOT) { 1012 if (!rhs) { 1013 cdie(c, "not lexpr"); 1014 } 1015 1016 typecheck_expr(c, d, n.a, 1); 1017 1018 if (!type_isint(n.a.t)) { 1019 cdie(c, "not: not an int"); 1020 } 1021 1022 n.t = n.a.t; 1023 } else if (kind == N_ADD) { 1024 if (!rhs) { 1025 cdie(c, "not lexpr"); 1026 } 1027 1028 typecheck_expr(c, d, n.b, 1); 1029 typecheck_expr(c, d, n.a, 1); 1030 1031 unify(c, n.a.t, n.b.t); 1032 1033 if (!type_isint(n.a.t)) { 1034 cdie(c, "add: not an int"); 1035 } 1036 1037 n.t = n.a.t; 1038 } else if (kind == N_SUB) { 1039 if (!rhs) { 1040 cdie(c, "not lexpr"); 1041 } 1042 1043 typecheck_expr(c, d, n.b, 1); 1044 typecheck_expr(c, d, n.a, 1); 1045 1046 unify(c, n.a.t, n.b.t); 1047 1048 if (!type_isint(n.a.t)) { 1049 cdie(c, "sub: not an int"); 1050 } 1051 1052 n.t = n.a.t; 1053 } else if (kind == N_MUL) { 1054 if (!rhs) { 1055 cdie(c, "not lexpr"); 1056 } 1057 1058 typecheck_expr(c, d, n.b, 1); 1059 typecheck_expr(c, d, n.a, 1); 1060 1061 unify(c, n.a.t, n.b.t); 1062 1063 if (!type_isint(n.a.t)) { 1064 cdie(c, "mul: not an int"); 1065 } 1066 1067 n.t = n.a.t; 1068 } else if (kind == N_DIV) { 1069 if (!rhs) { 1070 cdie(c, "not lexpr"); 1071 } 1072 1073 typecheck_expr(c, d, n.b, 1); 1074 typecheck_expr(c, d, n.a, 1); 1075 1076 unify(c, n.a.t, n.b.t); 1077 1078 if (!type_isint(n.a.t)) { 1079 cdie(c, "div: not an int"); 1080 } 1081 1082 n.t = n.a.t; 1083 } else if (kind == N_MOD) { 1084 if (!rhs) { 1085 cdie(c, "not lexpr"); 1086 } 1087 1088 typecheck_expr(c, d, n.b, 1); 1089 typecheck_expr(c, d, n.a, 1); 1090 1091 unify(c, n.a.t, n.b.t); 1092 1093 if (!type_isint(n.a.t)) { 1094 cdie(c, "mod: not an int"); 1095 } 1096 1097 n.t = n.a.t; 1098 } else if (kind == N_LSH) { 1099 if (!rhs) { 1100 cdie(c, "not lexpr"); 1101 } 1102 1103 typecheck_expr(c, d, n.b, 1); 1104 typecheck_expr(c, d, n.a, 1); 1105 1106 unify(c, n.a.t, n.b.t); 1107 1108 if (!type_isint(n.a.t)) { 1109 cdie(c, "lsh: not an int"); 1110 } 1111 1112 n.t = n.a.t; 1113 } else if (kind == N_RSH) { 1114 if (!rhs) { 1115 cdie(c, "not lexpr"); 1116 } 1117 1118 typecheck_expr(c, d, n.b, 1); 1119 typecheck_expr(c, d, n.a, 1); 1120 1121 unify(c, n.a.t, n.b.t); 1122 1123 if (!type_isint(n.a.t)) { 1124 cdie(c, "rsh: not an int"); 1125 } 1126 1127 n.t = n.a.t; 1128 } else if (kind == N_AND) { 1129 if (!rhs) { 1130 cdie(c, "not lexpr"); 1131 } 1132 1133 typecheck_expr(c, d, n.b, 1); 1134 typecheck_expr(c, d, n.a, 1); 1135 1136 unify(c, n.a.t, n.b.t); 1137 1138 if (!type_isint(n.a.t)) { 1139 cdie(c, "and: not an int"); 1140 } 1141 1142 n.t = n.a.t; 1143 } else if (kind == N_OR) { 1144 if (!rhs) { 1145 cdie(c, "not lexpr"); 1146 } 1147 1148 typecheck_expr(c, d, n.b, 1); 1149 typecheck_expr(c, d, n.a, 1); 1150 1151 unify(c, n.a.t, n.b.t); 1152 1153 if (!type_isint(n.a.t)) { 1154 cdie(c, "or: not an int"); 1155 } 1156 1157 n.t = n.a.t; 1158 } else if (kind == N_XOR) { 1159 if (!rhs) { 1160 cdie(c, "not lexpr"); 1161 } 1162 1163 typecheck_expr(c, d, n.b, 1); 1164 typecheck_expr(c, d, n.a, 1); 1165 1166 unify(c, n.a.t, n.b.t); 1167 1168 if (!type_isint(n.a.t)) { 1169 cdie(c, "xor: not an int"); 1170 } 1171 1172 n.t = n.a.t; 1173 } else if (kind == N_CAST) { 1174 if (!rhs) { 1175 cdie(c, "not lexpr"); 1176 } 1177 1178 typecheck_expr(c, d, n.a, 1); 1179 if (!type_isprim(n.a.t)) { 1180 cdie(c, "not a primitive"); 1181 } 1182 1183 n.t = prototype(c, n.b); 1184 } else { 1185 cdie(c, "not an expression"); 1186 } 1187 } 1188 1189 func typecheck_stmt(c: *compiler, d: *decl, n: *node) { 1190 var v: *decl; 1191 var kind: int; 1192 1193 if (!n) { 1194 return; 1195 } 1196 1197 c.filename = n.filename; 1198 c.lineno = n.lineno; 1199 c.colno = n.colno; 1200 1201 kind = n.kind; 1202 if (kind == N_CONDLIST) { 1203 loop { 1204 if (!n) { 1205 break; 1206 } 1207 1208 if (n.a.a) { 1209 typecheck_expr(c, d, n.a.a, 1); 1210 } 1211 1212 typecheck_stmt(c, d, n.a.b); 1213 1214 n = n.b; 1215 } 1216 } else if (kind == N_STMTLIST) { 1217 loop { 1218 if (!n) { 1219 break; 1220 } 1221 typecheck_stmt(c, d, n.a); 1222 n = n.b; 1223 } 1224 } else if (kind == N_LOOP) { 1225 typecheck_stmt(c, d, n.a); 1226 } else if (kind == N_BREAK) { 1227 } else if (kind == N_CONTINUE) { 1228 } else if (kind == N_RETURN) { 1229 if (n.a) { 1230 if (d.func_type.val.kind == TY_VOID) { 1231 cdie(c, "returning a value in a void function"); 1232 } 1233 call_check(c, n.a); 1234 typecheck_expr(c, d, n.a, 1); 1235 unify(c, n.a.t, d.func_type.val); 1236 } else { 1237 if (d.func_type.val.kind != TY_VOID) { 1238 cdie(c, "returning void in a non void function"); 1239 } 1240 } 1241 } else if (kind == N_LABEL) { 1242 v = find(c, d.name, n.a.s, 0); 1243 } else if (kind == N_GOTO) { 1244 v = find(c, d.name, n.a.s, 0); 1245 if (!v || !v.goto_defined) { 1246 cdie(c, "label not defined"); 1247 } 1248 } else if (kind != N_VARDECL) { 1249 call_check(c, n); 1250 typecheck_expr(c, d, n, 1); 1251 } 1252 } 1253 1254 func hoist_locals(c: *compiler, d: *decl, n: *node) { 1255 var kind: int; 1256 var name: *byte; 1257 var t: *type; 1258 var v: *decl; 1259 1260 if (!n) { 1261 return; 1262 } 1263 1264 kind = n.kind; 1265 if (kind == N_CONDLIST) { 1266 loop { 1267 if (!n) { 1268 return; 1269 } 1270 1271 hoist_locals(c, d, n.a.b); 1272 1273 n = n.b; 1274 } 1275 } else if (kind == N_STMTLIST) { 1276 loop { 1277 if (!n) { 1278 return; 1279 } 1280 1281 hoist_locals(c, d, n.a); 1282 1283 n = n.b; 1284 } 1285 } else if (kind == N_LOOP) { 1286 hoist_locals(c, d, n.a); 1287 return; 1288 } else if (kind == N_LABEL) { 1289 name = n.a.s; 1290 v = find(c, d.name, name, 1); 1291 1292 if (v.goto_defined) { 1293 cdie(c, "duplicate goto"); 1294 } 1295 v.goto_defined = 1; 1296 1297 return; 1298 } else if (kind != N_VARDECL) { 1299 return; 1300 } 1301 1302 name = n.a.s; 1303 t = prototype(c, n.b); 1304 1305 n.t = t; 1306 1307 v = find(c, d.name, name, 1); 1308 1309 if (v.var_defined) { 1310 cdie(c, "duplicate variable"); 1311 } 1312 1313 v.var_type = t; 1314 v.var_defined = 1; 1315 } 1316 1317 func gather_include(c: *compiler, filename: *byte, slen: *int): *byte { 1318 var fd: int; 1319 var blob: *byte; 1320 1321 fd = open(filename, O_RDONLY, 0); 1322 if fd < 0 { 1323 cdie(c, "gather_include: failed to open include"); 1324 } 1325 1326 blob = readall(fd, slen, c.a); 1327 1328 close(fd); 1329 1330 return blob; 1331 } 1332 1333 func call_check(c: *compiler, n: *node): int { 1334 var result: int; 1335 var ret: int; 1336 1337 result = 0; 1338 1339 if !n { 1340 return result; 1341 } 1342 1343 if n.kind == N_CALL { 1344 result = call_check(c, n.a); 1345 n = n.b; 1346 loop { 1347 if !n { 1348 break; 1349 } 1350 ret = call_check(c, n.a); 1351 if result && ret { 1352 cdie(c, "multiple calls in call"); 1353 } 1354 result = result | ret; 1355 n = n.b; 1356 } 1357 result = 1; 1358 } else if n.kind == N_BOR || n.kind == N_BAND { 1359 // Side effects okay in both positions 1360 result = call_check(c, n.a); 1361 result = result | call_check(c, n.b); 1362 } else if n.kind == N_ASSIGN || n.kind == N_INDEX || n.kind == N_LT 1363 || n.kind == N_LE || n.kind == N_GT || n.kind == N_GE 1364 || n.kind == N_EQ || n.kind == N_NE || n.kind == N_BNOT 1365 || n.kind == N_ADD || n.kind == N_SUB || n.kind == N_MUL 1366 || n.kind == N_DIV || n.kind == N_MOD || n.kind == N_LSH 1367 || n.kind == N_RSH || n.kind == N_AND || n.kind == N_OR 1368 || n.kind == N_XOR { 1369 // Possible side effects in both positions 1370 result = call_check(c, n.a); 1371 ret = call_check(c, n.b); 1372 if result && ret { 1373 cdie(c, "multiple calls in expression"); 1374 } 1375 result = result | ret; 1376 } else if n.kind == N_REF || n.kind == N_DEREF || n.kind == N_POS 1377 || n.kind == N_NEG || n.kind == N_NOT || n.kind == N_CAST 1378 || n.kind == N_DOT { 1379 // Possible side effect in the first position 1380 result = call_check(c, n.a); 1381 } else if n.kind == N_STR || n.kind == N_NUM || n.kind == N_CHAR 1382 || n.kind == N_IDENT || n.kind == N_SIZEOF || n.kind == N_NIL { 1383 // No side effects 1384 } else { 1385 show_node(nil, n); 1386 fputd(nil, n.kind); 1387 die("invalid expr"); 1388 } 1389 1390 return result; 1391 } 1392 1393 func open_call_out(c: *compiler, filename: *byte) { 1394 var fd: int; 1395 1396 fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, (6 << 6) + (6 << 3) + 6); 1397 if (fd < 0) { 1398 die("open_call_out: failed to open output"); 1399 } 1400 1401 c.call_out = fopen(fd, c.a); 1402 c.call_out.noflush = 1; 1403 } 1404 1405 func open_lines_out(c: *compiler, filename: *byte) { 1406 var fd: int; 1407 1408 fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, (6 << 6) + (6 << 3) + 6); 1409 if (fd < 0) { 1410 die("open_lines_out: failed to open output"); 1411 } 1412 1413 c.s.lines_out = fopen(fd, c.a); 1414 c.s.lines_out.noflush = 1; 1415 } 1416 1417 struct name_node { 1418 next: *name_node; 1419 name: *byte; 1420 } 1421 1422 func main(argc: int, argv: **byte, envp: **byte) { 1423 var a: alloc; 1424 var c: *compiler; 1425 var p: *node; 1426 var i: int; 1427 var show: int; 1428 var out_filename: *byte; 1429 var cout_filename: *byte; 1430 var err: *file; 1431 var input: *name_node; 1432 var tmp: *name_node; 1433 var link: **name_node; 1434 var sem: *lex_sem; 1435 var _aarch64: machine; 1436 var _x86_64: machine; 1437 var _riscv64: machine; 1438 1439 link = &input; 1440 1441 setup_alloc(&a); 1442 1443 err = fopen(2, &a); 1444 1445 c = comp_setup(&a, err); 1446 1447 _aarch64.id = 0xb7; 1448 _aarch64.emit_builtin = aarch64_builtin; 1449 _aarch64.output_ir = aarch64_output_ir; 1450 1451 _x86_64.id = 0x3e; 1452 _x86_64.emit_builtin = x86_64_builtin; 1453 _x86_64.output_ir = x86_64_output_ir; 1454 1455 _riscv64.id = 0xf3; 1456 _riscv64.emit_builtin = riscv64_builtin; 1457 _riscv64.output_ir = riscv64_output_ir; 1458 1459 if get_machine() == 0xb7 { 1460 c.mach = &_aarch64; 1461 } else if get_machine() == 0x3e { 1462 c.mach = &_x86_64; 1463 } else if get_machine() == 0xf3 { 1464 c.mach = &_riscv64; 1465 } 1466 1467 i = 1; 1468 loop { 1469 if (i >= argc) { 1470 break; 1471 } 1472 1473 if (!strcmp(argv[i], "-o")) { 1474 i = i + 1; 1475 if (i >= argc) { 1476 die("invalid -o at end of argument list"); 1477 } 1478 out_filename = argv[i]; 1479 i = i + 1; 1480 continue; 1481 } 1482 1483 if (!strcmp(argv[i], "-fdump")) { 1484 i = i + 1; 1485 show = 1; 1486 continue; 1487 } 1488 1489 if (!strcmp(argv[i], "-m")) { 1490 i = i + 1; 1491 if (i >= argc) { 1492 die("invalid -m at end of argument list"); 1493 } 1494 if (!strcmp(argv[i], "aarch64")) { 1495 c.mach = &_aarch64; 1496 i = i + 1; 1497 } else if (!strcmp(argv[i], "x86_64")) { 1498 c.mach = &_x86_64; 1499 i = i + 1; 1500 } else if (!strcmp(argv[i], "riscv64")) { 1501 c.mach = &_riscv64; 1502 i = i + 1; 1503 } else { 1504 die("unknown machine"); 1505 } 1506 continue; 1507 } 1508 1509 if (!strcmp(argv[i], "-C")) { 1510 i = i + 1; 1511 if (i >= argc) { 1512 die("invalid -o at end of argument list"); 1513 } 1514 cout_filename = argv[i]; 1515 i = i + 1; 1516 continue; 1517 } 1518 1519 if (!strcmp(argv[i], "-G")) { 1520 i = i + 1; 1521 if (i >= argc) { 1522 die("invalid -G at end of argument list"); 1523 } 1524 open_call_out(c, argv[i]); 1525 i = i + 1; 1526 continue; 1527 } 1528 1529 if (!strcmp(argv[i], "-n")) { 1530 i = i + 1; 1531 if (i >= argc) { 1532 die("invalid -n at end of argument list"); 1533 } 1534 open_lines_out(c, argv[i]); 1535 i = i + 1; 1536 continue; 1537 } 1538 1539 if (argv[i][0] == '-' as byte) { 1540 die("invalid argument"); 1541 } 1542 1543 tmp = alloc(&a, sizeof(*tmp)) as *name_node; 1544 tmp.next = nil; 1545 tmp.name = argv[i]; 1546 *link = tmp; 1547 link = &tmp.next; 1548 1549 i = i + 1; 1550 } 1551 1552 tmp = input; 1553 loop { 1554 if !tmp { 1555 break; 1556 } 1557 sem = dolalr(c, tmp.name, err); 1558 p = concat_program(p, sem.n); 1559 tmp = tmp.next; 1560 } 1561 1562 if show { 1563 show_node(err, p); 1564 fflush(err); 1565 return; 1566 } 1567 1568 if !c.mach { 1569 die("machine not set"); 1570 } 1571 1572 compile(c, p); 1573 1574 if cout_filename { 1575 open_coutput(c, cout_filename); 1576 ircout(c); 1577 } 1578 1579 if out_filename { 1580 c.mach.emit_builtin(c); 1581 1582 open_output(c.s, out_filename); 1583 writeout(c.s, c.mach.id, c.start, c.kstart); 1584 } 1585 }