From bed42be34f1fda4f5ec9177c0ce6e0c4f8b02d16 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sun, 2 Feb 2020 00:23:49 -0800 Subject: 5975 --- html/apps/mu.subx.html | 14564 +++++++++++++++++++++++------------------------ 1 file changed, 7137 insertions(+), 7427 deletions(-) (limited to 'html/apps') diff --git a/html/apps/mu.subx.html b/html/apps/mu.subx.html index d915a4ea..08624b2c 100644 --- a/html/apps/mu.subx.html +++ b/html/apps/mu.subx.html @@ -458,9 +458,9 @@ if ('onhashchange' in window) { 396 55/push-ebp 397 89/<- %ebp 4/r32/esp 398 # - 399 (parse-mu *(ebp+8)) - 400 (check-mu-types) - 401 (emit-subx *(ebp+0xc)) + 399 (parse-mu *(ebp+8)) + 400 (check-mu-types) + 401 (emit-subx *(ebp+0xc)) 402 $convert-mu:end: 403 # . epilogue 404 89/<- %esp 5/r32/ebp @@ -487,701 +487,676 @@ if ('onhashchange' in window) { 425 c3/return 426 427 test-convert-function-skeleton: - 428 # empty function decl => function prologue and epilogue - 429 # fn foo { - 430 # } - 431 # => - 432 # foo: - 433 # # . prologue - 434 # 55/push-ebp - 435 # 89/<- %ebp 4/r32/esp - 436 # # . epilogue - 437 # 89/<- %esp 5/r32/ebp - 438 # 5d/pop-to-ebp - 439 # c3/return - 440 # . prologue - 441 55/push-ebp - 442 89/<- %ebp 4/r32/esp - 443 # setup - 444 (clear-stream _test-input-stream) - 445 (clear-stream $_test-input-buffered-file->buffer) - 446 (clear-stream _test-output-stream) - 447 (clear-stream $_test-output-buffered-file->buffer) - 448 # - 449 (write _test-input-stream "fn foo {\n") - 450 (write _test-input-stream "}\n") - 451 # convert - 452 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 453 (flush _test-output-buffered-file) - 454 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 460 # check output - 461 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-skeleton/0") - 462 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-skeleton/1") - 463 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-skeleton/2") - 464 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-skeleton/3") - 465 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-skeleton/4") - 466 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-skeleton/5") - 467 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-skeleton/6") - 468 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-skeleton/7") - 469 # . epilogue - 470 89/<- %esp 5/r32/ebp - 471 5d/pop-to-ebp - 472 c3/return - 473 - 474 test-convert-multiple-function-skeletons: - 475 # multiple functions correctly organized into a linked list - 476 # fn foo { - 477 # } - 478 # fn bar { - 479 # } - 480 # => - 481 # foo: - 482 # # . prologue - 483 # 55/push-ebp - 484 # 89/<- %ebp 4/r32/esp - 485 # # . epilogue - 486 # 89/<- %esp 5/r32/ebp - 487 # 5d/pop-to-ebp - 488 # c3/return - 489 # bar: - 490 # # . prologue - 491 # 55/push-ebp - 492 # 89/<- %ebp 4/r32/esp - 493 # # . epilogue - 494 # 89/<- %esp 5/r32/ebp - 495 # 5d/pop-to-ebp - 496 # c3/return - 497 # . prologue - 498 55/push-ebp - 499 89/<- %ebp 4/r32/esp - 500 # setup - 501 (clear-stream _test-input-stream) - 502 (clear-stream $_test-input-buffered-file->buffer) - 503 (clear-stream _test-output-stream) - 504 (clear-stream $_test-output-buffered-file->buffer) - 505 # - 506 (write _test-input-stream "fn foo {\n") - 507 (write _test-input-stream "}\n") - 508 (write _test-input-stream "fn bar {\n") - 509 (write _test-input-stream "}\n") - 510 # convert - 511 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 512 (flush _test-output-buffered-file) - 513 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 519 # check first function - 520 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-multiple-function-skeletons/0") - 521 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/1") - 522 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/2") - 523 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/3") - 524 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/4") - 525 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/5") - 526 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/6") - 527 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/7") - 528 # check second function - 529 (check-next-stream-line-equal _test-output-stream "bar:" "F - test-convert-multiple-function-skeletons/10") - 530 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/11") - 531 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/12") - 532 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/13") - 533 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/14") - 534 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/15") - 535 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/16") - 536 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/17") - 537 # . epilogue - 538 89/<- %esp 5/r32/ebp - 539 5d/pop-to-ebp - 540 c3/return - 541 - 542 test-convert-function-with-arg: - 543 # function with one arg - 544 # fn foo n : int { - 545 # } - 546 # => - 547 # foo: - 548 # # . prologue - 549 # 55/push-ebp - 550 # 89/<- %ebp 4/r32/esp - 551 # # . epilogue - 552 # 89/<- %esp 5/r32/ebp - 553 # 5d/pop-to-ebp - 554 # c3/return - 555 # . prologue - 556 55/push-ebp - 557 89/<- %ebp 4/r32/esp - 558 # setup - 559 (clear-stream _test-input-stream) - 560 (clear-stream $_test-input-buffered-file->buffer) - 561 (clear-stream _test-output-stream) - 562 (clear-stream $_test-output-buffered-file->buffer) - 563 # - 564 (write _test-input-stream "fn foo n : int {\n") - 565 (write _test-input-stream "}\n") - 566 # convert - 567 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 568 (flush _test-output-buffered-file) - 569 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 575 # check output - 576 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg/0") - 577 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg/1") - 578 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg/2") - 579 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg/3") - 580 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg/4") - 581 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg/5") - 582 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg/6") - 583 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg/7") - 584 # . epilogue - 585 89/<- %esp 5/r32/ebp - 586 5d/pop-to-ebp - 587 c3/return - 588 - 589 test-convert-function-with-arg-and-body: - 590 # function with one arg and one instruction in the body - 591 # fn foo n : int { - 592 # increment n - 593 # } - 594 # => - 595 # foo: - 596 # # . prologue - 597 # 55/push-ebp - 598 # 89/<- %ebp 4/r32/esp - 599 # { - 600 # ff 0/subop/increment *(ebp+8) - 601 # } - 602 # # . epilogue - 603 # 89/<- %esp 5/r32/ebp - 604 # 5d/pop-to-ebp - 605 # c3/return - 606 # . prologue - 607 55/push-ebp - 608 89/<- %ebp 4/r32/esp - 609 # setup - 610 (clear-stream _test-input-stream) - 611 (clear-stream $_test-input-buffered-file->buffer) - 612 (clear-stream _test-output-stream) - 613 (clear-stream $_test-output-buffered-file->buffer) - 614 # - 615 (write _test-input-stream "fn foo n : int {\n") - 616 (write _test-input-stream " increment n\n") - 617 (write _test-input-stream "}\n") - 618 # convert - 619 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 620 (flush _test-output-buffered-file) - 621 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 627 # check output - 628 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg-and-body/0") - 629 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg-and-body/1") - 630 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg-and-body/2") - 631 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg-and-body/3") - 632 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-arg-and-body/4") - 633 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-arg-and-body/5") - 634 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-arg-and-body/6") - 635 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg-and-body/7") - 636 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg-and-body/8") - 637 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg-and-body/9") - 638 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg-and-body/10") - 639 # . epilogue - 640 89/<- %esp 5/r32/ebp - 641 5d/pop-to-ebp - 642 c3/return - 643 - 644 test-convert-function-distinguishes-args: - 645 # function with two args refers to second one in body - 646 # fn foo a: int, b: int { - 647 # increment b - 648 # } - 649 # => - 650 # foo: - 651 # # . prologue - 652 # 55/push-ebp - 653 # 89/<- %ebp 4/r32/esp - 654 # { - 655 # ff 0/subop/increment *(ebp+0xc) - 656 # } - 657 # # . epilogue - 658 # 89/<- %esp 5/r32/ebp - 659 # 5d/pop-to-ebp - 660 # c3/return - 661 # . prologue - 662 55/push-ebp - 663 89/<- %ebp 4/r32/esp - 664 # setup - 665 (clear-stream _test-input-stream) - 666 (clear-stream $_test-input-buffered-file->buffer) - 667 (clear-stream _test-output-stream) - 668 (clear-stream $_test-output-buffered-file->buffer) - 669 # - 670 (write _test-input-stream "fn foo a: int, b: int {\n") - 671 (write _test-input-stream " increment b\n") - 672 (write _test-input-stream "}\n") - 673 # convert - 674 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 675 (flush _test-output-buffered-file) - 676 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 682 # check output - 683 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-distinguishes-args/0") - 684 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-distinguishes-args/1") - 685 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-distinguishes-args/2") - 686 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-distinguishes-args/3") - 687 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-distinguishes-args/4") - 688 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x0000000c)" "F - test-convert-function-distinguishes-args/5") - 689 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-distinguishes-args/6") - 690 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-distinguishes-args/7") - 691 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-distinguishes-args/8") - 692 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-distinguishes-args/9") - 693 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-distinguishes-args/10") - 694 # . epilogue - 695 89/<- %esp 5/r32/ebp - 696 5d/pop-to-ebp - 697 c3/return - 698 - 699 test-convert-function-returns-result: - 700 # function writes to output - 701 # fn foo a: int, b: int -> result/eax: int { - 702 # result <- copy a - 703 # result <- increment - 704 # } - 705 # => - 706 # foo: - 707 # # . prologue - 708 # 55/push-ebp - 709 # 89/<- %ebp 4/r32/esp - 710 # { - 711 # 89/-> *(ebp+8) 0/r32/eax - 712 # 40/increment-eax - 713 # } - 714 # # . epilogue - 715 # 89/<- %esp 5/r32/ebp - 716 # 5d/pop-to-ebp - 717 # c3/return - 718 # . prologue - 719 55/push-ebp - 720 89/<- %ebp 4/r32/esp - 721 # setup - 722 (clear-stream _test-input-stream) - 723 (clear-stream $_test-input-buffered-file->buffer) - 724 (clear-stream _test-output-stream) - 725 (clear-stream $_test-output-buffered-file->buffer) - 726 # - 727 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") - 728 (write _test-input-stream " result <- copy a\n") - 729 (write _test-input-stream " result <- increment\n") - 730 (write _test-input-stream "}\n") - 731 # convert - 732 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 733 (flush _test-output-buffered-file) - 734 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 740 # check output - 741 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-returns-result/0") - 742 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-returns-result/1") - 743 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-returns-result/2") - 744 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-returns-result/3") - 745 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-returns-result/4") - 746 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-returns-result/5") - 747 (check-next-stream-line-equal _test-output-stream " 40/increment-eax" "F - test-convert-function-returns-result/6") - 748 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-returns-result/7") - 749 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-returns-result/8") - 750 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-returns-result/9") - 751 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-returns-result/10") - 752 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-returns-result/11") - 753 # . epilogue - 754 89/<- %esp 5/r32/ebp - 755 5d/pop-to-ebp - 756 c3/return - 757 - 758 test-convert-function-literal-arg: - 759 # function writes to output - 760 # fn foo a: int, b: int -> result/eax: int { - 761 # result <- copy a - 762 # result <- add 1 - 763 # } - 764 # => - 765 # foo: - 766 # # . prologue - 767 # 55/push-ebp - 768 # 89/<- %ebp 4/r32/esp - 769 # { - 770 # 89/-> *(ebp+8) 0/r32/eax - 771 # 05/add-to-eax 1/imm32 - 772 # } - 773 # # . epilogue - 774 # 89/<- %esp 5/r32/ebp - 775 # 5d/pop-to-ebp - 776 # c3/return - 777 # . prologue - 778 55/push-ebp - 779 89/<- %ebp 4/r32/esp - 780 # setup - 781 (clear-stream _test-input-stream) - 782 (clear-stream $_test-input-buffered-file->buffer) - 783 (clear-stream _test-output-stream) - 784 (clear-stream $_test-output-buffered-file->buffer) - 785 # - 786 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") - 787 (write _test-input-stream " result <- copy a\n") - 788 (write _test-input-stream " result <- add 1\n") - 789 (write _test-input-stream "}\n") - 790 # convert - 791 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 792 (flush _test-output-buffered-file) - 793 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 799 # check output - 800 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-literal-arg/0") - 801 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-literal-arg/1") - 802 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-literal-arg/2") - 803 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-literal-arg/3") - 804 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-literal-arg/4") - 805 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-literal-arg/5") - 806 (check-next-stream-line-equal _test-output-stream " 05/add-to-eax 1/imm32" "F - test-convert-function-literal-arg/6") - 807 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-literal-arg/7") - 808 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-literal-arg/8") - 809 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-literal-arg/9") - 810 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-literal-arg/10") - 811 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-literal-arg/11") - 812 # . epilogue - 813 89/<- %esp 5/r32/ebp - 814 5d/pop-to-ebp - 815 c3/return - 816 - 817 test-convert-function-literal-arg-2: - 818 # function writes to output - 819 # fn foo a: int, b: int -> result/ebx: int { - 820 # result <- copy a - 821 # result <- add 1 - 822 # } - 823 # => - 824 # foo: - 825 # # . prologue - 826 # 55/push-ebp - 827 # 89/<- %ebp 4/r32/esp - 828 # { - 829 # 89/-> *(ebp+8) 3/r32/ebx - 830 # 81 0/subop/add %ebx 1/imm32 - 831 # } - 832 # # . epilogue - 833 # 89/<- %esp 5/r32/ebp - 834 # 5d/pop-to-ebp - 835 # c3/return - 836 # . prologue - 837 55/push-ebp - 838 89/<- %ebp 4/r32/esp - 839 # setup - 840 (clear-stream _test-input-stream) - 841 (clear-stream $_test-input-buffered-file->buffer) - 842 (clear-stream _test-output-stream) - 843 (clear-stream $_test-output-buffered-file->buffer) - 844 # - 845 (write _test-input-stream "fn foo a: int, b: int -> result/ebx: int {\n") - 846 (write _test-input-stream " result <- copy a\n") - 847 (write _test-input-stream " result <- add 1\n") - 848 (write _test-input-stream "}\n") - 849 # convert - 850 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 851 (flush _test-output-buffered-file) - 852 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 858 # check output - 859 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-literal-arg-2/0") - 860 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-literal-arg-2/1") - 861 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-literal-arg-2/2") - 862 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-literal-arg-2/3") - 863 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-literal-arg-2/4") - 864 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-literal-arg-2/5") - 865 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %ebx 1/imm32" "F - test-convert-function-literal-arg-2/6") - 866 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-literal-arg-2/7") - 867 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-literal-arg-2/8") - 868 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-literal-arg-2/9") - 869 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-literal-arg-2/10") - 870 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-literal-arg-2/11") - 871 # . epilogue - 872 89/<- %esp 5/r32/ebp - 873 5d/pop-to-ebp - 874 c3/return - 875 - 876 test-convert-function-call-with-literal-arg: - 877 # function writes to output - 878 # fn main -> result/ebx: int { - 879 # result <- do-add 3 4 - 880 # } - 881 # - 882 # fn do-add a: int, b: int -> result/ebx: int { - 883 # result <- copy a - 884 # result <- add b - 885 # } - 886 # => - 887 # main: - 888 # # . prologue - 889 # 55/push-ebp - 890 # 89/<- %ebp 4/r32/esp - 891 # { - 892 # (do-add 3 4) - 893 # } - 894 # # . epilogue - 895 # 89/<- %esp 5/r32/ebp - 896 # 5d/pop-to-ebp - 897 # c3/return - 898 # do-add: - 899 # # . prologue - 900 # 55/push-ebp - 901 # 89/<- %ebp 4/r32/esp - 902 # { - 903 # 8b/-> *(ebp+8) 3/r32/ebx - 904 # 03/add-to 3/r32/ebx *(ebp+0xc) - 905 # } - 906 # # . epilogue - 907 # 89/<- %esp 5/r32/ebp - 908 # 5d/pop-to-ebp - 909 # c3/return - 910 # . prologue - 911 55/push-ebp - 912 89/<- %ebp 4/r32/esp - 913 # setup - 914 (clear-stream _test-input-stream) - 915 (clear-stream $_test-input-buffered-file->buffer) - 916 (clear-stream _test-output-stream) - 917 (clear-stream $_test-output-buffered-file->buffer) - 918 # - 919 (write _test-input-stream "fn main -> result/ebx: int {\n") - 920 (write _test-input-stream " result <- do-add 3 4\n") - 921 (write _test-input-stream "}\n") - 922 (write _test-input-stream "fn do-add a: int, b: int -> result/ebx: int {\n") - 923 (write _test-input-stream " result <- copy a\n") - 924 (write _test-input-stream " result <- add b\n") - 925 (write _test-input-stream "}\n") - 926 # convert - 927 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 928 (flush _test-output-buffered-file) - 929 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 935 # check output - 936 (check-next-stream-line-equal _test-output-stream "main:" "F - test-convert-function-call-with-literal-arg/0") - 937 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/1") - 938 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/2") - 939 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/3") - 940 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/4") - 941 (check-next-stream-line-equal _test-output-stream " (do-add 3 4)" "F - test-convert-function-call-with-literal-arg/5") - 942 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/6") - 943 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/7") - 944 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/8") - 945 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/9") - 946 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/10") - 947 (check-next-stream-line-equal _test-output-stream "do-add:" "F - test-convert-function-call-with-literal-arg/11") - 948 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/12") - 949 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/13") - 950 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/14") - 951 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/15") - 952 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/16") - 953 (check-next-stream-line-equal _test-output-stream " 03/add *(ebp+0x0000000c) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/17") - 954 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/18") - 955 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/19") - 956 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/20") - 957 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/21") - 958 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/22") - 959 # . epilogue - 960 89/<- %esp 5/r32/ebp - 961 5d/pop-to-ebp - 962 c3/return - 963 - 964 test-convert-function-with-local-var-in-mem: - 965 # empty function decl => function prologue and epilogue - 966 # fn foo { - 967 # var x: int - 968 # increment x - 969 # } - 970 # => - 971 # foo: - 972 # # . prologue - 973 # 55/push-ebp - 974 # 89/<- %ebp 4/r32/esp - 975 # { - 976 # 68/push 0/imm32 - 977 # ff 0/subop/increment *(ebp-4) - 978 # 81 0/subop/add %esp 4/imm32 - 979 # } - 980 # # . epilogue - 981 # 89/<- %esp 5/r32/ebp - 982 # 5d/pop-to-ebp - 983 # c3/return - 984 # . prologue - 985 55/push-ebp - 986 89/<- %ebp 4/r32/esp - 987 # setup - 988 (clear-stream _test-input-stream) - 989 (clear-stream $_test-input-buffered-file->buffer) - 990 (clear-stream _test-output-stream) - 991 (clear-stream $_test-output-buffered-file->buffer) - 992 # - 993 (write _test-input-stream "fn foo {\n") - 994 (write _test-input-stream " var x: int\n") - 995 (write _test-input-stream " increment x\n") - 996 (write _test-input-stream "}\n") - 997 # convert - 998 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 999 (flush _test-output-buffered-file) -1000 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1006 # check output -1007 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-mem/0") -1008 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-mem/1") -1009 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-mem/2") -1010 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-mem/3") -1011 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-mem/4") -1012 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-mem/5") -1013 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-mem/6") -1014 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-in-mem/7") -1015 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-mem/8") -1016 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-mem/9") -1017 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-mem/10") -1018 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-mem/11") -1019 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-mem/12") -1020 # . epilogue -1021 89/<- %esp 5/r32/ebp -1022 5d/pop-to-ebp -1023 c3/return -1024 -1025 test-convert-function-with-local-var-in-reg: -1026 # empty function decl => function prologue and epilogue -1027 # fn foo { -1028 # var x/ecx: int <- copy 3 -1029 # x <- increment -1030 # } -1031 # => -1032 # foo: -1033 # # . prologue -1034 # 55/push-ebp -1035 # 89/<- %ebp 4/r32/esp -1036 # { -1037 # ff 6/subop/push %ecx -1038 # b9/copy-to-ecx 3/imm32 -1039 # 41/increment-ecx -1040 # 8f 0/subop/pop %ecx -1041 # } -1042 # # . epilogue -1043 # 89/<- %esp 5/r32/ebp -1044 # 5d/pop-to-ebp -1045 # c3/return -1046 # . prologue -1047 55/push-ebp -1048 89/<- %ebp 4/r32/esp -1049 # setup -1050 (clear-stream _test-input-stream) -1051 (clear-stream $_test-input-buffered-file->buffer) -1052 (clear-stream _test-output-stream) -1053 (clear-stream $_test-output-buffered-file->buffer) -1054 # -1055 (write _test-input-stream "fn foo {\n") -1056 (write _test-input-stream " var x/ecx: int <- copy 3\n") -1057 (write _test-input-stream " x <- increment\n") -1058 (write _test-input-stream "}\n") -1059 # convert -1060 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1061 (flush _test-output-buffered-file) -1062 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1068 # check output -1069 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-reg/0") -1070 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-reg/1") -1071 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-reg/2") -1072 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-reg/3") -1073 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-reg/4") -1074 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-local-var-in-reg/5") -1075 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-function-with-local-var-in-reg/6") -1076 (check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-convert-function-with-local-var-in-reg/7") -1077 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/8") -1078 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-reg/9") -1079 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-reg/10") -1080 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-reg/11") -1081 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-reg/12") -1082 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-reg/13") -1083 # . epilogue -1084 89/<- %esp 5/r32/ebp -1085 5d/pop-to-ebp -1086 c3/return -1087 -1088 test-convert-function-with-local-var-in-block: -1089 # empty function decl => function prologue and epilogue -1090 # fn foo { -1091 # { -1092 # var x: int -1093 # increment x -1094 # } -1095 # } -1096 # => -1097 # foo: -1098 # # . prologue -1099 # 55/push-ebp -1100 # 89/<- %ebp 4/r32/esp -1101 # { -1102 # { -1103 # 68/push 0/imm32 -1104 # ff 0/subop/increment *(ebp-4) -1105 # 81 0/subop/add %esp 4/imm32 -1106 # } -1107 # } -1108 # # . epilogue -1109 # 89/<- %esp 5/r32/ebp -1110 # 5d/pop-to-ebp -1111 # c3/return -1112 # . prologue -1113 55/push-ebp -1114 89/<- %ebp 4/r32/esp -1115 # setup -1116 (clear-stream _test-input-stream) -1117 (clear-stream $_test-input-buffered-file->buffer) -1118 (clear-stream _test-output-stream) -1119 (clear-stream $_test-output-buffered-file->buffer) -1120 # -1121 (write _test-input-stream "fn foo {\n") -1122 (write _test-input-stream " {\n") -1123 (write _test-input-stream " var x: int\n") -1124 (write _test-input-stream " increment x\n") -1125 (write _test-input-stream " }\n") -1126 (write _test-input-stream "}\n") -1127 # convert -1128 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1129 (flush _test-output-buffered-file) -1130 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1136 # check output -1137 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-block/0") -1138 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-block/1") -1139 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-block/2") -1140 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-block/3") -1141 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/4") -1142 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/5") -1143 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-block/6") -1144 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-block/7") -1145 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-in-block/8") -1146 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/9") -1147 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/10") -1148 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-block/11") -1149 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-block/12") -1150 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-block/13") -1151 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-block/14") -1152 # . epilogue -1153 89/<- %esp 5/r32/ebp -1154 5d/pop-to-ebp -1155 c3/return -1156 -1157 test-convert-function-with-local-var-in-named-block: -1158 # empty function decl => function prologue and epilogue -1159 # fn foo { -1160 # $bar: { -1161 # var x: int -1162 # increment x -1163 # } -1164 # } -1165 # => -1166 # foo: -1167 # # . prologue -1168 # 55/push-ebp -1169 # 89/<- %ebp 4/r32/esp -1170 # { -1171 # { -1172 # $bar:loop: -1173 # 68/push 0/imm32 -1174 # ff 0/subop/increment *(ebp-4) -1175 # 81 0/subop/add %esp 4/imm32 -1176 # } -1177 # $bar:break: -1178 # } -1179 # # . epilogue -1180 # 89/<- %esp 5/r32/ebp -1181 # 5d/pop-to-ebp -1182 # c3/return + 428 # . prologue + 429 55/push-ebp + 430 89/<- %ebp 4/r32/esp + 431 # setup + 432 (clear-stream _test-input-stream) + 433 (clear-stream $_test-input-buffered-file->buffer) + 434 (clear-stream _test-output-stream) + 435 (clear-stream $_test-output-buffered-file->buffer) + 436 # + 437 (write _test-input-stream "fn foo {\n") + 438 (write _test-input-stream "}\n") + 439 # convert + 440 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 441 (flush _test-output-buffered-file) + 442 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 448 # check output + 449 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-skeleton/0") + 450 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-skeleton/1") + 451 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-skeleton/2") + 452 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-skeleton/3") + 453 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-skeleton/4") + 454 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-skeleton/5") + 455 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-skeleton/6") + 456 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-skeleton/7") + 457 # . epilogue + 458 89/<- %esp 5/r32/ebp + 459 5d/pop-to-ebp + 460 c3/return + 461 + 462 test-convert-multiple-function-skeletons: + 463 # . prologue + 464 55/push-ebp + 465 89/<- %ebp 4/r32/esp + 466 # setup + 467 (clear-stream _test-input-stream) + 468 (clear-stream $_test-input-buffered-file->buffer) + 469 (clear-stream _test-output-stream) + 470 (clear-stream $_test-output-buffered-file->buffer) + 471 # + 472 (write _test-input-stream "fn foo {\n") + 473 (write _test-input-stream "}\n") + 474 (write _test-input-stream "fn bar {\n") + 475 (write _test-input-stream "}\n") + 476 # convert + 477 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 478 (flush _test-output-buffered-file) + 479 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 485 # check first function + 486 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-multiple-function-skeletons/0") + 487 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/1") + 488 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/2") + 489 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/3") + 490 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/4") + 491 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/5") + 492 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/6") + 493 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/7") + 494 # check second function + 495 (check-next-stream-line-equal _test-output-stream "bar:" "F - test-convert-multiple-function-skeletons/10") + 496 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/11") + 497 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/12") + 498 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/13") + 499 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/14") + 500 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/15") + 501 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/16") + 502 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/17") + 503 # . epilogue + 504 89/<- %esp 5/r32/ebp + 505 5d/pop-to-ebp + 506 c3/return + 507 + 508 test-convert-function-with-arg: + 509 # . prologue + 510 55/push-ebp + 511 89/<- %ebp 4/r32/esp + 512 # setup + 513 (clear-stream _test-input-stream) + 514 (clear-stream $_test-input-buffered-file->buffer) + 515 (clear-stream _test-output-stream) + 516 (clear-stream $_test-output-buffered-file->buffer) + 517 # + 518 (write _test-input-stream "fn foo n : int {\n") + 519 (write _test-input-stream "}\n") + 520 # convert + 521 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 522 (flush _test-output-buffered-file) + 523 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 529 # check output + 530 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg/0") + 531 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg/1") + 532 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg/2") + 533 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg/3") + 534 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg/4") + 535 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg/5") + 536 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg/6") + 537 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg/7") + 538 # . epilogue + 539 89/<- %esp 5/r32/ebp + 540 5d/pop-to-ebp + 541 c3/return + 542 + 543 test-convert-function-with-arg-and-body: + 544 # . prologue + 545 55/push-ebp + 546 89/<- %ebp 4/r32/esp + 547 # setup + 548 (clear-stream _test-input-stream) + 549 (clear-stream $_test-input-buffered-file->buffer) + 550 (clear-stream _test-output-stream) + 551 (clear-stream $_test-output-buffered-file->buffer) + 552 # + 553 (write _test-input-stream "fn foo n : int {\n") + 554 (write _test-input-stream " increment n\n") + 555 (write _test-input-stream "}\n") + 556 # convert + 557 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 558 (flush _test-output-buffered-file) + 559 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 565 # check output + 566 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg-and-body/0") + 567 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg-and-body/1") + 568 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg-and-body/2") + 569 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg-and-body/3") + 570 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-arg-and-body/4") + 571 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-arg-and-body/5") + 572 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-arg-and-body/6") + 573 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg-and-body/7") + 574 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg-and-body/8") + 575 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg-and-body/9") + 576 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg-and-body/10") + 577 # . epilogue + 578 89/<- %esp 5/r32/ebp + 579 5d/pop-to-ebp + 580 c3/return + 581 + 582 test-convert-function-distinguishes-args: + 583 # . prologue + 584 55/push-ebp + 585 89/<- %ebp 4/r32/esp + 586 # setup + 587 (clear-stream _test-input-stream) + 588 (clear-stream $_test-input-buffered-file->buffer) + 589 (clear-stream _test-output-stream) + 590 (clear-stream $_test-output-buffered-file->buffer) + 591 # + 592 (write _test-input-stream "fn foo a: int, b: int {\n") + 593 (write _test-input-stream " increment b\n") + 594 (write _test-input-stream "}\n") + 595 # convert + 596 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 597 (flush _test-output-buffered-file) + 598 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 604 # check output + 605 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-distinguishes-args/0") + 606 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-distinguishes-args/1") + 607 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-distinguishes-args/2") + 608 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-distinguishes-args/3") + 609 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-distinguishes-args/4") + 610 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x0000000c)" "F - test-convert-function-distinguishes-args/5") + 611 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-distinguishes-args/6") + 612 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-distinguishes-args/7") + 613 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-distinguishes-args/8") + 614 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-distinguishes-args/9") + 615 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-distinguishes-args/10") + 616 # . epilogue + 617 89/<- %esp 5/r32/ebp + 618 5d/pop-to-ebp + 619 c3/return + 620 + 621 test-convert-function-returns-result: + 622 # . prologue + 623 55/push-ebp + 624 89/<- %ebp 4/r32/esp + 625 # setup + 626 (clear-stream _test-input-stream) + 627 (clear-stream $_test-input-buffered-file->buffer) + 628 (clear-stream _test-output-stream) + 629 (clear-stream $_test-output-buffered-file->buffer) + 630 # + 631 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") + 632 (write _test-input-stream " result <- copy a\n") + 633 (write _test-input-stream " result <- increment\n") + 634 (write _test-input-stream "}\n") + 635 # convert + 636 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 637 (flush _test-output-buffered-file) + 638 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 644 # check output + 645 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-returns-result/0") + 646 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-returns-result/1") + 647 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-returns-result/2") + 648 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-returns-result/3") + 649 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-returns-result/4") + 650 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-returns-result/5") + 651 (check-next-stream-line-equal _test-output-stream " 40/increment-eax" "F - test-convert-function-returns-result/6") + 652 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-returns-result/7") + 653 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-returns-result/8") + 654 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-returns-result/9") + 655 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-returns-result/10") + 656 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-returns-result/11") + 657 # . epilogue + 658 89/<- %esp 5/r32/ebp + 659 5d/pop-to-ebp + 660 c3/return + 661 + 662 test-convert-function-literal-arg: + 663 # . prologue + 664 55/push-ebp + 665 89/<- %ebp 4/r32/esp + 666 # setup + 667 (clear-stream _test-input-stream) + 668 (clear-stream $_test-input-buffered-file->buffer) + 669 (clear-stream _test-output-stream) + 670 (clear-stream $_test-output-buffered-file->buffer) + 671 # + 672 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") + 673 (write _test-input-stream " result <- copy a\n") + 674 (write _test-input-stream " result <- add 1\n") + 675 (write _test-input-stream "}\n") + 676 # convert + 677 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 678 (flush _test-output-buffered-file) + 679 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 685 # check output + 686 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-literal-arg/0") + 687 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-literal-arg/1") + 688 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-literal-arg/2") + 689 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-literal-arg/3") + 690 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-literal-arg/4") + 691 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-literal-arg/5") + 692 (check-next-stream-line-equal _test-output-stream " 05/add-to-eax 1/imm32" "F - test-convert-function-literal-arg/6") + 693 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-literal-arg/7") + 694 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-literal-arg/8") + 695 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-literal-arg/9") + 696 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-literal-arg/10") + 697 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-literal-arg/11") + 698 # . epilogue + 699 89/<- %esp 5/r32/ebp + 700 5d/pop-to-ebp + 701 c3/return + 702 + 703 test-convert-function-literal-arg-2: + 704 # . prologue + 705 55/push-ebp + 706 89/<- %ebp 4/r32/esp + 707 # setup + 708 (clear-stream _test-input-stream) + 709 (clear-stream $_test-input-buffered-file->buffer) + 710 (clear-stream _test-output-stream) + 711 (clear-stream $_test-output-buffered-file->buffer) + 712 # + 713 (write _test-input-stream "fn foo a: int, b: int -> result/ebx: int {\n") + 714 (write _test-input-stream " result <- copy a\n") + 715 (write _test-input-stream " result <- add 1\n") + 716 (write _test-input-stream "}\n") + 717 # convert + 718 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 719 (flush _test-output-buffered-file) + 720 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 726 # check output + 727 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-literal-arg-2/0") + 728 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-literal-arg-2/1") + 729 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-literal-arg-2/2") + 730 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-literal-arg-2/3") + 731 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-literal-arg-2/4") + 732 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-literal-arg-2/5") + 733 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %ebx 1/imm32" "F - test-convert-function-literal-arg-2/6") + 734 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-literal-arg-2/7") + 735 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-literal-arg-2/8") + 736 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-literal-arg-2/9") + 737 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-literal-arg-2/10") + 738 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-literal-arg-2/11") + 739 # . epilogue + 740 89/<- %esp 5/r32/ebp + 741 5d/pop-to-ebp + 742 c3/return + 743 + 744 test-convert-function-call-with-literal-arg: + 745 # . prologue + 746 55/push-ebp + 747 89/<- %ebp 4/r32/esp + 748 # setup + 749 (clear-stream _test-input-stream) + 750 (clear-stream $_test-input-buffered-file->buffer) + 751 (clear-stream _test-output-stream) + 752 (clear-stream $_test-output-buffered-file->buffer) + 753 # + 754 (write _test-input-stream "fn main -> result/ebx: int {\n") + 755 (write _test-input-stream " result <- do-add 3 4\n") + 756 (write _test-input-stream "}\n") + 757 (write _test-input-stream "fn do-add a: int, b: int -> result/ebx: int {\n") + 758 (write _test-input-stream " result <- copy a\n") + 759 (write _test-input-stream " result <- add b\n") + 760 (write _test-input-stream "}\n") + 761 # convert + 762 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 763 (flush _test-output-buffered-file) + 764 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 770 # check output + 771 (check-next-stream-line-equal _test-output-stream "main:" "F - test-convert-function-call-with-literal-arg/0") + 772 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/1") + 773 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/2") + 774 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/3") + 775 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/4") + 776 (check-next-stream-line-equal _test-output-stream " (do-add 3 4)" "F - test-convert-function-call-with-literal-arg/5") + 777 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/6") + 778 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/7") + 779 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/8") + 780 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/9") + 781 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/10") + 782 (check-next-stream-line-equal _test-output-stream "do-add:" "F - test-convert-function-call-with-literal-arg/11") + 783 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/12") + 784 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/13") + 785 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/14") + 786 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/15") + 787 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/16") + 788 (check-next-stream-line-equal _test-output-stream " 03/add *(ebp+0x0000000c) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/17") + 789 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/18") + 790 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/19") + 791 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/20") + 792 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/21") + 793 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/22") + 794 # . epilogue + 795 89/<- %esp 5/r32/ebp + 796 5d/pop-to-ebp + 797 c3/return + 798 + 799 test-convert-function-with-local-var-in-mem: + 800 # . prologue + 801 55/push-ebp + 802 89/<- %ebp 4/r32/esp + 803 # setup + 804 (clear-stream _test-input-stream) + 805 (clear-stream $_test-input-buffered-file->buffer) + 806 (clear-stream _test-output-stream) + 807 (clear-stream $_test-output-buffered-file->buffer) + 808 # + 809 (write _test-input-stream "fn foo {\n") + 810 (write _test-input-stream " var x: int\n") + 811 (write _test-input-stream " increment x\n") + 812 (write _test-input-stream "}\n") + 813 # convert + 814 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 815 (flush _test-output-buffered-file) + 816 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 822 # check output + 823 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-mem/0") + 824 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-mem/1") + 825 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-mem/2") + 826 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-mem/3") + 827 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-mem/4") + 828 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-mem/5") + 829 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-mem/6") + 830 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-in-mem/7") + 831 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-mem/8") + 832 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-mem/9") + 833 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-mem/10") + 834 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-mem/11") + 835 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-mem/12") + 836 # . epilogue + 837 89/<- %esp 5/r32/ebp + 838 5d/pop-to-ebp + 839 c3/return + 840 + 841 test-convert-function-with-local-var-in-reg: + 842 # . prologue + 843 55/push-ebp + 844 89/<- %ebp 4/r32/esp + 845 # setup + 846 (clear-stream _test-input-stream) + 847 (clear-stream $_test-input-buffered-file->buffer) + 848 (clear-stream _test-output-stream) + 849 (clear-stream $_test-output-buffered-file->buffer) + 850 # + 851 (write _test-input-stream "fn foo {\n") + 852 (write _test-input-stream " var x/ecx: int <- copy 3\n") + 853 (write _test-input-stream " x <- increment\n") + 854 (write _test-input-stream "}\n") + 855 # convert + 856 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 857 (flush _test-output-buffered-file) + 858 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 864 # check output + 865 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-reg/0") + 866 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-reg/1") + 867 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-reg/2") + 868 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-reg/3") + 869 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-reg/4") + 870 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-local-var-in-reg/5") + 871 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-function-with-local-var-in-reg/6") + 872 (check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-convert-function-with-local-var-in-reg/7") + 873 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/8") + 874 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-reg/9") + 875 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-reg/10") + 876 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-reg/11") + 877 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-reg/12") + 878 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-reg/13") + 879 # . epilogue + 880 89/<- %esp 5/r32/ebp + 881 5d/pop-to-ebp + 882 c3/return + 883 + 884 test-convert-function-with-local-var-in-block: + 885 # . prologue + 886 55/push-ebp + 887 89/<- %ebp 4/r32/esp + 888 # setup + 889 (clear-stream _test-input-stream) + 890 (clear-stream $_test-input-buffered-file->buffer) + 891 (clear-stream _test-output-stream) + 892 (clear-stream $_test-output-buffered-file->buffer) + 893 # + 894 (write _test-input-stream "fn foo {\n") + 895 (write _test-input-stream " {\n") + 896 (write _test-input-stream " var x: int\n") + 897 (write _test-input-stream " increment x\n") + 898 (write _test-input-stream " }\n") + 899 (write _test-input-stream "}\n") + 900 # convert + 901 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 902 (flush _test-output-buffered-file) + 903 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 909 # check output + 910 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-block/0") + 911 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-block/1") + 912 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-block/2") + 913 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-block/3") + 914 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/4") + 915 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/5") + 916 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-block/6") + 917 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-block/7") + 918 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-in-block/8") + 919 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/9") + 920 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/10") + 921 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-block/11") + 922 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-block/12") + 923 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-block/13") + 924 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-block/14") + 925 # . epilogue + 926 89/<- %esp 5/r32/ebp + 927 5d/pop-to-ebp + 928 c3/return + 929 + 930 test-convert-function-with-local-var-in-named-block: + 931 # . prologue + 932 55/push-ebp + 933 89/<- %ebp 4/r32/esp + 934 # setup + 935 (clear-stream _test-input-stream) + 936 (clear-stream $_test-input-buffered-file->buffer) + 937 (clear-stream _test-output-stream) + 938 (clear-stream $_test-output-buffered-file->buffer) + 939 # + 940 (write _test-input-stream "fn foo {\n") + 941 (write _test-input-stream " $bar: {\n") + 942 (write _test-input-stream " var x: int\n") + 943 (write _test-input-stream " increment x\n") + 944 (write _test-input-stream " }\n") + 945 (write _test-input-stream "}\n") + 946 # convert + 947 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 948 (flush _test-output-buffered-file) + 949 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 955 # check output + 956 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-named-block/0") + 957 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-named-block/1") + 958 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-named-block/2") + 959 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-named-block/3") + 960 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/4") + 961 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/5") + 962 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-local-var-in-named-block/6") + 963 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-named-block/7") + 964 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-named-block/8") + 965 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-in-named-block/9") + 966 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/10") + 967 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-local-var-in-named-block/11") + 968 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/12") + 969 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-named-block/13") + 970 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-named-block/14") + 971 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-named-block/15") + 972 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-named-block/16") + 973 # . epilogue + 974 89/<- %esp 5/r32/ebp + 975 5d/pop-to-ebp + 976 c3/return + 977 + 978 test-convert-function-with-branches-in-block: + 979 # . prologue + 980 55/push-ebp + 981 89/<- %ebp 4/r32/esp + 982 # setup + 983 (clear-stream _test-input-stream) + 984 (clear-stream $_test-input-buffered-file->buffer) + 985 (clear-stream _test-output-stream) + 986 (clear-stream $_test-output-buffered-file->buffer) + 987 # + 988 (write _test-input-stream "fn foo x: int {\n") + 989 (write _test-input-stream " {\n") + 990 (write _test-input-stream " break-if->=\n") + 991 (write _test-input-stream " loop-if-addr<\n") + 992 (write _test-input-stream " increment x\n") + 993 (write _test-input-stream " loop\n") + 994 (write _test-input-stream " }\n") + 995 (write _test-input-stream "}\n") + 996 # convert + 997 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 998 (flush _test-output-buffered-file) + 999 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1005 # check output +1006 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-block/0") +1007 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-block/1") +1008 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-block/2") +1009 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-block/3") +1010 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/4") +1011 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/5") +1012 (check-next-stream-line-equal _test-output-stream " 0f 8d/jump-if->= break/disp32" "F - test-convert-function-with-branches-in-block/6") +1013 (check-next-stream-line-equal _test-output-stream " 0f 82/jump-if-addr< loop/disp32" "F - test-convert-function-with-branches-in-block/7") +1014 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-block/8") +1015 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-block/9") +1016 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/10") +1017 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/12") +1018 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-block/13") +1019 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-block/14") +1020 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-block/15") +1021 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-block/16") +1022 # . epilogue +1023 89/<- %esp 5/r32/ebp +1024 5d/pop-to-ebp +1025 c3/return +1026 +1027 test-convert-function-with-branches-in-named-block: +1028 # . prologue +1029 55/push-ebp +1030 89/<- %ebp 4/r32/esp +1031 # setup +1032 (clear-stream _test-input-stream) +1033 (clear-stream $_test-input-buffered-file->buffer) +1034 (clear-stream _test-output-stream) +1035 (clear-stream $_test-output-buffered-file->buffer) +1036 # +1037 (write _test-input-stream "fn foo x: int {\n") +1038 (write _test-input-stream " $bar: {\n") +1039 (write _test-input-stream " break-if->= $bar\n") +1040 (write _test-input-stream " loop-if-addr< $bar\n") +1041 (write _test-input-stream " increment x\n") +1042 (write _test-input-stream " loop\n") +1043 (write _test-input-stream " }\n") +1044 (write _test-input-stream "}\n") +1045 # convert +1046 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1047 (flush _test-output-buffered-file) +1048 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1054 # check output +1055 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-named-block/0") +1056 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-named-block/1") +1057 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-named-block/2") +1058 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-named-block/3") +1059 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/4") +1060 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/5") +1061 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-branches-in-named-block/6") +1062 (check-next-stream-line-equal _test-output-stream " 0f 8d/jump-if->= $bar:break/disp32" "F - test-convert-function-with-branches-in-named-block/7") +1063 (check-next-stream-line-equal _test-output-stream " 0f 82/jump-if-addr< $bar:loop/disp32" "F - test-convert-function-with-branches-in-named-block/8") +1064 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-named-block/9") +1065 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-named-block/10") +1066 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/11") +1067 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-branches-in-named-block/12") +1068 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/13") +1069 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-named-block/14") +1070 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-named-block/15") +1071 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-named-block/16") +1072 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-named-block/17") +1073 # . epilogue +1074 89/<- %esp 5/r32/ebp +1075 5d/pop-to-ebp +1076 c3/return +1077 +1078 test-convert-function-with-var-in-nested-block: +1079 # . prologue +1080 55/push-ebp +1081 89/<- %ebp 4/r32/esp +1082 # setup +1083 (clear-stream _test-input-stream) +1084 (clear-stream $_test-input-buffered-file->buffer) +1085 (clear-stream _test-output-stream) +1086 (clear-stream $_test-output-buffered-file->buffer) +1087 # +1088 (write _test-input-stream "fn foo x: int {\n") +1089 (write _test-input-stream " {\n") +1090 (write _test-input-stream " {\n") +1091 (write _test-input-stream " var x: int\n") +1092 (write _test-input-stream " increment x\n") +1093 (write _test-input-stream " }\n") +1094 (write _test-input-stream " }\n") +1095 (write _test-input-stream "}\n") +1096 # convert +1097 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1098 (flush _test-output-buffered-file) +1099 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1105 # check output +1106 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-var-in-nested-block/0") +1107 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-var-in-nested-block/1") +1108 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-var-in-nested-block/2") +1109 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-var-in-nested-block/3") +1110 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/4") +1111 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/5") +1112 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/6") +1113 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/7") +1114 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-var-in-nested-block/8") +1115 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-var-in-nested-block/9") +1116 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/10") +1117 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/11") +1118 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/13") +1119 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-var-in-nested-block/14") +1120 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-var-in-nested-block/15") +1121 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-var-in-nested-block/16") +1122 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-var-in-nested-block/17") +1123 # . epilogue +1124 89/<- %esp 5/r32/ebp +1125 5d/pop-to-ebp +1126 c3/return +1127 +1128 test-convert-function-with-multiple-vars-in-nested-blocks: +1129 # . prologue +1130 55/push-ebp +1131 89/<- %ebp 4/r32/esp +1132 # setup +1133 (clear-stream _test-input-stream) +1134 (clear-stream $_test-input-buffered-file->buffer) +1135 (clear-stream _test-output-stream) +1136 (clear-stream $_test-output-buffered-file->buffer) +1137 # +1138 (write _test-input-stream "fn foo x: int {\n") +1139 (write _test-input-stream " {\n") +1140 (write _test-input-stream " var x/eax: int <- copy 0\n") +1141 (write _test-input-stream " {\n") +1142 (write _test-input-stream " var y: int\n") +1143 (write _test-input-stream " x <- add y\n") +1144 (write _test-input-stream " }\n") +1145 (write _test-input-stream " }\n") +1146 (write _test-input-stream "}\n") +1147 # convert +1148 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1149 (flush _test-output-buffered-file) +1150 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1156 # check output +1157 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-var-in-nested-block/0") +1158 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-var-in-nested-block/1") +1159 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-var-in-nested-block/2") +1160 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-var-in-nested-block/3") +1161 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/4") +1162 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/5") +1163 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-with-var-in-nested-block/6") +1164 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-function-with-var-in-nested-block/7") +1165 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/8") +1166 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/9") +1167 (check-next-stream-line-equal _test-output-stream " 03/add *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-var-in-nested-block/10") +1168 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-var-in-nested-block/11") +1169 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/12") +1170 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-with-var-in-nested-block/13") +1171 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/14") +1172 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/15") +1173 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-var-in-nested-block/16") +1174 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-var-in-nested-block/17") +1175 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-var-in-nested-block/18") +1176 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-var-in-nested-block/19") +1177 # . epilogue +1178 89/<- %esp 5/r32/ebp +1179 5d/pop-to-ebp +1180 c3/return +1181 +1182 test-convert-function-with-branches-and-local-vars: 1183 # . prologue 1184 55/push-ebp 1185 89/<- %ebp 4/r32/esp @@ -1192,1563 +1167,1583 @@ if ('onhashchange' in window) { 1190 (clear-stream $_test-output-buffered-file->buffer) 1191 # 1192 (write _test-input-stream "fn foo {\n") -1193 (write _test-input-stream " $bar: {\n") +1193 (write _test-input-stream " {\n") 1194 (write _test-input-stream " var x: int\n") -1195 (write _test-input-stream " increment x\n") -1196 (write _test-input-stream " }\n") -1197 (write _test-input-stream "}\n") -1198 # convert -1199 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1200 (flush _test-output-buffered-file) -1201 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1207 # check output -1208 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-named-block/0") -1209 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-named-block/1") -1210 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-named-block/2") -1211 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-named-block/3") -1212 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/4") -1213 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/5") -1214 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-local-var-in-named-block/6") -1215 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-named-block/7") -1216 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-named-block/8") -1217 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-in-named-block/9") -1218 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/10") -1219 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-local-var-in-named-block/11") -1220 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/12") -1221 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-named-block/13") -1222 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-named-block/14") -1223 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-named-block/15") -1224 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-named-block/16") -1225 # . epilogue -1226 89/<- %esp 5/r32/ebp -1227 5d/pop-to-ebp -1228 c3/return -1229 -1230 test-convert-function-with-branches-in-block: -1231 # empty function decl => function prologue and epilogue -1232 # fn foo x: int { -1233 # { -1234 # break-if->= -1235 # loop-if-addr< -1236 # increment x -1237 # loop -1238 # } -1239 # } -1240 # => -1241 # foo: -1242 # # . prologue -1243 # 55/push-ebp -1244 # 89/<- %ebp 4/r32/esp -1245 # { -1246 # { -1247 # 0f 8d/jump-if->= break/disp32 -1248 # 0f 82/jump-if-addr< loop/disp32 -1249 # ff 0/subop/increment *(ebp+8) -1250 # e9/jump loop/disp32 -1251 # } -1252 # } -1253 # # . epilogue -1254 # 89/<- %esp 5/r32/ebp -1255 # 5d/pop-to-ebp -1256 # c3/return -1257 # . prologue -1258 55/push-ebp -1259 89/<- %ebp 4/r32/esp -1260 # setup -1261 (clear-stream _test-input-stream) -1262 (clear-stream $_test-input-buffered-file->buffer) -1263 (clear-stream _test-output-stream) -1264 (clear-stream $_test-output-buffered-file->buffer) -1265 # -1266 (write _test-input-stream "fn foo x: int {\n") -1267 (write _test-input-stream " {\n") -1268 (write _test-input-stream " break-if->=\n") -1269 (write _test-input-stream " loop-if-addr<\n") -1270 (write _test-input-stream " increment x\n") -1271 (write _test-input-stream " loop\n") -1272 (write _test-input-stream " }\n") -1273 (write _test-input-stream "}\n") -1274 # convert -1275 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1276 (flush _test-output-buffered-file) -1277 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1283 # check output -1284 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-block/0") -1285 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-block/1") -1286 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-block/2") -1287 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-block/3") -1288 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/4") -1289 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/5") -1290 (check-next-stream-line-equal _test-output-stream " 0f 8d/jump-if->= break/disp32" "F - test-convert-function-with-branches-in-block/6") -1291 (check-next-stream-line-equal _test-output-stream " 0f 82/jump-if-addr< loop/disp32" "F - test-convert-function-with-branches-in-block/7") -1292 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-block/8") -1293 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-block/9") -1294 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/10") -1295 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/12") -1296 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-block/13") -1297 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-block/14") -1298 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-block/15") -1299 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-block/16") -1300 # . epilogue -1301 89/<- %esp 5/r32/ebp -1302 5d/pop-to-ebp -1303 c3/return -1304 -1305 test-convert-function-with-branches-in-named-block: -1306 # empty function decl => function prologue and epilogue -1307 # fn foo x: int { -1308 # $bar: { -1309 # break-if->= $bar -1310 # loop-if-addr< $bar -1311 # increment x -1312 # loop -1313 # } -1314 # } -1315 # => -1316 # foo: -1317 # # . prologue -1318 # 55/push-ebp -1319 # 89/<- %ebp 4/r32/esp -1320 # { -1321 # { -1322 # $bar:loop: -1323 # 0f 8d/jump-if->= $bar:break/disp32 -1324 # 0f 82/jump-if-addr< $bar:loop/disp32 -1325 # ff 0/subop/increment *(ebp+8) -1326 # e9/jump loop/disp32 -1327 # } -1328 # $bar:break: -1329 # } -1330 # # . epilogue -1331 # 89/<- %esp 5/r32/ebp -1332 # 5d/pop-to-ebp -1333 # c3/return -1334 # . prologue -1335 55/push-ebp -1336 89/<- %ebp 4/r32/esp -1337 # setup -1338 (clear-stream _test-input-stream) -1339 (clear-stream $_test-input-buffered-file->buffer) -1340 (clear-stream _test-output-stream) -1341 (clear-stream $_test-output-buffered-file->buffer) -1342 # -1343 (write _test-input-stream "fn foo x: int {\n") -1344 (write _test-input-stream " $bar: {\n") -1345 (write _test-input-stream " break-if->= $bar\n") -1346 (write _test-input-stream " loop-if-addr< $bar\n") -1347 (write _test-input-stream " increment x\n") -1348 (write _test-input-stream " loop\n") -1349 (write _test-input-stream " }\n") -1350 (write _test-input-stream "}\n") -1351 # convert -1352 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1353 (flush _test-output-buffered-file) -1354 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1360 # check output -1361 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-named-block/0") -1362 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-named-block/1") -1363 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-named-block/2") -1364 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-named-block/3") -1365 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/4") -1366 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/5") -1367 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-branches-in-named-block/6") -1368 (check-next-stream-line-equal _test-output-stream " 0f 8d/jump-if->= $bar:break/disp32" "F - test-convert-function-with-branches-in-named-block/7") -1369 (check-next-stream-line-equal _test-output-stream " 0f 82/jump-if-addr< $bar:loop/disp32" "F - test-convert-function-with-branches-in-named-block/8") -1370 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-named-block/9") -1371 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-named-block/10") -1372 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/11") -1373 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-branches-in-named-block/12") -1374 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/13") -1375 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-named-block/14") -1376 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-named-block/15") -1377 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-named-block/16") -1378 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-named-block/17") -1379 # . epilogue -1380 89/<- %esp 5/r32/ebp -1381 5d/pop-to-ebp -1382 c3/return -1383 -1384 test-convert-function-with-var-in-nested-block: -1385 # empty function decl => function prologue and epilogue -1386 # fn foo { -1387 # { -1388 # { -1389 # var x: int -1390 # increment x -1391 # } -1392 # } -1393 # } -1394 # => -1395 # foo: -1396 # # . prologue -1397 # 55/push-ebp -1398 # 89/<- %ebp 4/r32/esp -1399 # { -1400 # { -1401 # { -1402 # 68/push 0/imm32 -1403 # ff 0/subop/increment *(ebp-4) -1404 # 81 0/subop/add %esp 4/imm32 -1405 # } -1406 # } -1407 # } -1408 # # . epilogue -1409 # 89/<- %esp 5/r32/ebp -1410 # 5d/pop-to-ebp -1411 # c3/return -1412 # . prologue -1413 55/push-ebp -1414 89/<- %ebp 4/r32/esp -1415 # setup -1416 (clear-stream _test-input-stream) -1417 (clear-stream $_test-input-buffered-file->buffer) -1418 (clear-stream _test-output-stream) -1419 (clear-stream $_test-output-buffered-file->buffer) -1420 # -1421 (write _test-input-stream "fn foo x: int {\n") -1422 (write _test-input-stream " {\n") -1423 (write _test-input-stream " {\n") -1424 (write _test-input-stream " var x: int\n") -1425 (write _test-input-stream " increment x\n") -1426 (write _test-input-stream " }\n") -1427 (write _test-input-stream " }\n") -1428 (write _test-input-stream "}\n") -1429 # convert -1430 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1431 (flush _test-output-buffered-file) -1432 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1438 # check output -1439 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-var-in-nested-block/0") -1440 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-var-in-nested-block/1") -1441 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-var-in-nested-block/2") -1442 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-var-in-nested-block/3") -1443 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/4") -1444 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/5") -1445 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/6") -1446 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/7") -1447 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-var-in-nested-block/8") -1448 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-var-in-nested-block/9") -1449 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/10") -1450 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/11") -1451 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/13") -1452 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-var-in-nested-block/14") -1453 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-var-in-nested-block/15") -1454 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-var-in-nested-block/16") -1455 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-var-in-nested-block/17") -1456 # . epilogue -1457 89/<- %esp 5/r32/ebp -1458 5d/pop-to-ebp -1459 c3/return -1460 -1461 test-convert-function-with-multiple-vars-in-nested-blocks: -1462 # empty function decl => function prologue and epilogue -1463 # fn foo { -1464 # { -1465 # var x/eax: int <- copy 0 -1466 # { -1467 # var y: int -1468 # x <- add y -1469 # } -1470 # } -1471 # } -1472 # => -1473 # foo: -1474 # # . prologue -1475 # 55/push-ebp -1476 # 89/<- %ebp 4/r32/esp -1477 # { -1478 # { -1479 # ff 6/subop/push %eax -1480 # { -1481 # 68/push 0/imm32 -1482 # ff 0/subop/increment *(ebp-8) # eax has been spilled above -1483 # 81 0/subop/add %esp 4/imm32 -1484 # } -1485 # 8f 0/subop/pop %eax -1486 # } -1487 # } -1488 # # . epilogue -1489 # 89/<- %esp 5/r32/ebp -1490 # 5d/pop-to-ebp -1491 # c3/return -1492 # . prologue -1493 55/push-ebp -1494 89/<- %ebp 4/r32/esp -1495 # setup -1496 (clear-stream _test-input-stream) -1497 (clear-stream $_test-input-buffered-file->buffer) -1498 (clear-stream _test-output-stream) -1499 (clear-stream $_test-output-buffered-file->buffer) -1500 # -1501 (write _test-input-stream "fn foo x: int {\n") -1502 (write _test-input-stream " {\n") -1503 (write _test-input-stream " var x/eax: int <- copy 0\n") -1504 (write _test-input-stream " {\n") -1505 (write _test-input-stream " var y: int\n") -1506 (write _test-input-stream " x <- add y\n") -1507 (write _test-input-stream " }\n") -1508 (write _test-input-stream " }\n") -1509 (write _test-input-stream "}\n") -1510 # convert -1511 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1512 (flush _test-output-buffered-file) -1513 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1519 # check output -1520 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-var-in-nested-block/0") -1521 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-var-in-nested-block/1") -1522 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-var-in-nested-block/2") -1523 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-var-in-nested-block/3") -1524 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/4") -1525 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/5") -1526 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-with-var-in-nested-block/6") -1527 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-function-with-var-in-nested-block/7") -1528 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/8") -1529 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/9") -1530 (check-next-stream-line-equal _test-output-stream " 03/add *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-var-in-nested-block/10") -1531 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-var-in-nested-block/11") -1532 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/12") -1533 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-with-var-in-nested-block/13") -1534 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/14") -1535 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/15") -1536 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-var-in-nested-block/16") -1537 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-var-in-nested-block/17") -1538 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-var-in-nested-block/18") -1539 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-var-in-nested-block/19") -1540 # . epilogue -1541 89/<- %esp 5/r32/ebp -1542 5d/pop-to-ebp -1543 c3/return -1544 -1545 ####################################################### -1546 # Parsing -1547 ####################################################### -1548 -1549 parse-mu: # in: (addr buffered-file) -1550 # pseudocode -1551 # var curr-function: (addr (handle function)) = Program -1552 # var line: (stream byte 512) -1553 # var word-slice: slice -1554 # while true # line loop -1555 # clear-stream(line) -1556 # read-line-buffered(in, line) -1557 # if (line->write == 0) break # end of file -1558 # word-slice = next-mu-token(line) -1559 # if slice-empty?(word-slice) # end of line -1560 # continue -1561 # else if slice-starts-with?(word-slice, "#") # comment -1562 # continue # end of line -1563 # else if slice-equal(word-slice, "fn") -1564 # var new-function: (handle function) = allocate(function) -1565 # var vars: (stack (addr var) 256) -1566 # populate-mu-function-header(in, new-function, vars) -1567 # populate-mu-function-body(in, new-function, vars) -1568 # assert(vars->top == 0) -1569 # *curr-function = new-function -1570 # curr-function = &new-function->next -1571 # else -1572 # abort() -1573 # -1574 # . prologue -1575 55/push-ebp -1576 89/<- %ebp 4/r32/esp -1577 # . save registers -1578 50/push-eax -1579 51/push-ecx -1580 52/push-edx -1581 53/push-ebx -1582 57/push-edi -1583 # var line/ecx: (stream byte 512) -1584 81 5/subop/subtract %esp 0x200/imm32 -1585 68/push 0x200/imm32/length -1586 68/push 0/imm32/read -1587 68/push 0/imm32/write -1588 89/<- %ecx 4/r32/esp -1589 # var word-slice/edx: slice -1590 68/push 0/imm32/end -1591 68/push 0/imm32/start -1592 89/<- %edx 4/r32/esp -1593 # var curr-function/edi: (addr (handle function)) = Program -1594 bf/copy-to-edi Program/imm32 -1595 # var vars/ebx: (stack (addr var) 256) -1596 81 5/subop/subtract %esp 0x400/imm32 -1597 68/push 0x400/imm32/length -1598 68/push 0/imm32/top -1599 89/<- %ebx 4/r32/esp -1600 { -1601 $parse-mu:line-loop: -1602 (clear-stream %ecx) -1603 (read-line-buffered *(ebp+8) %ecx) -1604 # if (line->write == 0) break -1605 81 7/subop/compare *ecx 0/imm32 -1606 0f 84/jump-if-= break/disp32 -1607 +-- 6 lines: #? # dump line --------------------------------------------------------------------------------------------------------------------------- -1613 (next-mu-token %ecx %edx) -1614 # if slice-empty?(word-slice) continue -1615 (slice-empty? %edx) -1616 3d/compare-eax-and 0/imm32 -1617 0f 85/jump-if-!= loop/disp32 -1618 # if (*word-slice->start == "#") continue -1619 # . eax = *word-slice->start -1620 8b/-> *edx 0/r32/eax -1621 8a/copy-byte *eax 0/r32/AL -1622 81 4/subop/and %eax 0xff/imm32 -1623 # . if (eax == '#') continue -1624 3d/compare-eax-and 0x23/imm32/hash -1625 0f 84/jump-if-= loop/disp32 -1626 # if (slice-equal?(word-slice, "fn")) parse a function -1627 { -1628 $parse-mu:fn: -1629 (slice-equal? %edx "fn") -1630 3d/compare-eax-and 0/imm32 -1631 0f 84/jump-if-= break/disp32 -1632 # var new-function/eax: (handle function) = populate-mu-function(in, new-function, vars) -1633 (allocate Heap *Function-size) # => eax -1634 (zero-out %eax *Function-size) -1635 (clear-stack %ebx) -1636 (populate-mu-function-header %ecx %eax %ebx) -1637 (populate-mu-function-body *(ebp+8) %eax %ebx) -1638 # *curr-function = new-function -1639 89/<- *edi 0/r32/eax -1640 # curr-function = &new-function->next -1641 8d/address-> *(eax+0x14) 7/r32/edi # Function-next -1642 e9/jump $parse-mu:line-loop/disp32 -1643 } -1644 # otherwise abort -1645 e9/jump $parse-mu:error1/disp32 -1646 } # end line loop -1647 $parse-mu:end: -1648 # . reclaim locals -1649 81 0/subop/add %esp 0x630/imm32 -1650 # . restore registers -1651 5f/pop-to-edi -1652 5b/pop-to-ebx -1653 5a/pop-to-edx -1654 59/pop-to-ecx -1655 58/pop-to-eax -1656 # . epilogue -1657 89/<- %esp 5/r32/ebp -1658 5d/pop-to-ebp -1659 c3/return -1660 -1661 $parse-mu:error1: -1662 # error("unexpected top-level command: " word-slice "\n") -1663 (write-buffered Stderr "unexpected top-level command: ") -1664 (write-slice-buffered Stderr %edx) -1665 (write-buffered Stderr "\n") -1666 (flush Stderr) -1667 # . syscall(exit, 1) -1668 bb/copy-to-ebx 1/imm32 -1669 b8/copy-to-eax 1/imm32/exit -1670 cd/syscall 0x80/imm8 -1671 # never gets here -1672 -1673 $parse-mu:error2: -1674 # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n") -1675 (print-int32-buffered Stderr *ebx) -1676 (write-buffered Stderr " vars not reclaimed after fn '") -1677 (write-slice-buffered Stderr *eax) # Function-name -1678 (write-buffered Stderr "'\n") -1679 (flush Stderr) -1680 # . syscall(exit, 1) -1681 bb/copy-to-ebx 1/imm32 -1682 b8/copy-to-eax 1/imm32/exit -1683 cd/syscall 0x80/imm8 -1684 # never gets here -1685 -1686 # scenarios considered: -1687 # ✗ fn foo # no block -1688 # ✓ fn foo { -1689 # ✗ fn foo { { -1690 # ✗ fn foo { } -1691 # ✗ fn foo { } { -1692 # ✗ fn foo x { -1693 # ✗ fn foo x: { -1694 # ✓ fn foo x: int { -1695 # ✓ fn foo x: int { -1696 # ✓ fn foo x: int -> y/eax: int { -1697 populate-mu-function-header: # first-line: (addr stream byte), out: (handle function), vars: (addr stack (handle var)) -1698 # pseudocode: -1699 # var name: slice -1700 # next-word(first-line, name) -1701 # assert(name not in '{' '}' '->') -1702 # out->name = slice-to-string(name) -1703 # var next-offset: int = 8 -1704 # ## inouts -1705 # while true -1706 # ## name -1707 # name = next-word(first-line) -1708 # if (name == '{') goto done -1709 # if (name == '->') break -1710 # assert(name != '}') -1711 # var v: (handle var) = parse-var-with-type(name, first-line) -1712 # assert(v->register == null) -1713 # v->stack-offset = next-offset -1714 # next-offset += size-of(v) -1715 # # v->block-depth is implicitly 0 -1716 # out->inouts = append(out->inouts, v) -1717 # push(vars, v) -1718 # ## outputs -1719 # while true -1720 # ## name -1721 # name = next-word(first-line) -1722 # assert(name not in '{' '}' '->') -1723 # var v: (handle var) = parse-var-with-type(name, first-line) -1724 # assert(v->register != null) -1725 # out->outputs = append(out->outputs, v) -1726 # done: -1727 # -1728 # . prologue -1729 55/push-ebp -1730 89/<- %ebp 4/r32/esp -1731 # . save registers -1732 50/push-eax -1733 51/push-ecx -1734 52/push-edx -1735 53/push-ebx -1736 57/push-edi -1737 # edi = out -1738 8b/-> *(ebp+0xc) 7/r32/edi -1739 # var word-slice/ecx: slice -1740 68/push 0/imm32/end -1741 68/push 0/imm32/start -1742 89/<- %ecx 4/r32/esp -1743 # var next-offset/edx = 8 -1744 ba/copy-to-edx 8/imm32 -1745 # read function name -1746 (next-word *(ebp+8) %ecx) -1747 # error checking -1748 # if (word-slice == '{') abort -1749 (slice-equal? %ecx "{") # => eax -1750 3d/compare-eax-and 0/imm32 -1751 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1752 # if (word-slice == '->') abort -1753 (slice-equal? %ecx "->") # => eax -1754 3d/compare-eax-and 0/imm32 -1755 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1756 # if (word-slice == '}') abort -1757 (slice-equal? %ecx "}") # => eax -1758 3d/compare-eax-and 0/imm32 -1759 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1760 # save function name -1761 (slice-to-string Heap %ecx) # => eax -1762 89/<- *edi 0/r32/eax # Function-name -1763 # initialize default subx-name as well -1764 89/<- *(edi+4) 0/r32/eax # Function-subx-name -1765 # save function inouts -1766 { -1767 $populate-mu-function-header:check-for-inout: -1768 (next-word *(ebp+8) %ecx) -1769 # if (word-slice == '{') goto done -1770 (slice-equal? %ecx "{") # => eax -1771 3d/compare-eax-and 0/imm32 -1772 0f 85/jump-if-!= $populate-mu-function-header:done/disp32 -1773 # if (word-slice == '->') break -1774 (slice-equal? %ecx "->") # => eax -1775 3d/compare-eax-and 0/imm32 -1776 0f 85/jump-if-!= break/disp32 -1777 # if (word-slice == '}') abort -1778 (slice-equal? %ecx "}") # => eax -1779 3d/compare-eax-and 0/imm32 -1780 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1781 # var v/ebx: (handle var) = parse-var-with-type(word-slice, first-line) -1782 (parse-var-with-type %ecx *(ebp+8)) # => eax -1783 89/<- %ebx 0/r32/eax -1784 # assert(v->register == null) -1785 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -1786 0f 85/jump-if-!= $populate-mu-function-header:error2/disp32 -1787 # v->stack-offset = next-offset -1788 89/<- *(ebx+0xc) 2/r32/edx # Var-stack-offset -1789 # next-offset += size-of(v) -1790 (size-of %ebx) # => eax -1791 01/add %edx 0/r32/eax -1792 # v->block-depth is implicitly 0 -1793 # -1794 (append-list Heap %ebx *(edi+8)) # Function-inouts => eax -1795 89/<- *(edi+8) 0/r32/eax # Function-inouts -1796 (push *(ebp+0x10) %ebx) -1797 # -1798 e9/jump loop/disp32 -1799 } -1800 # save function outputs -1801 { -1802 $parse-var-with-type:check-for-out: -1803 (next-word *(ebp+8) %ecx) -1804 # if (word-slice == '{') break -1805 (slice-equal? %ecx "{") # => eax -1806 3d/compare-eax-and 0/imm32 -1807 0f 85/jump-if-!= break/disp32 -1808 # if (word-slice == '->') abort -1809 (slice-equal? %ecx "->") # => eax -1810 3d/compare-eax-and 0/imm32 -1811 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1812 # if (word-slice == '}') abort -1813 (slice-equal? %ecx "}") # => eax -1814 3d/compare-eax-and 0/imm32 -1815 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1816 # -1817 (parse-var-with-type %ecx *(ebp+8)) # => eax -1818 89/<- %ebx 0/r32/eax -1819 # assert(var->register != null) -1820 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -1821 0f 84/jump-if-= $populate-mu-function-header:error3/disp32 -1822 (append-list Heap %ebx *(edi+0xc)) # Function-outputs => eax -1823 89/<- *(edi+0xc) 0/r32/eax # Function-outputs -1824 e9/jump loop/disp32 -1825 } -1826 $populate-mu-function-header:done: -1827 (check-no-tokens-left *(ebp+8)) -1828 $populate-mu-function-header:end: -1829 # . reclaim locals -1830 81 0/subop/add %esp 8/imm32 -1831 # . restore registers -1832 5f/pop-to-edi -1833 5b/pop-to-ebx -1834 5a/pop-to-edx -1835 59/pop-to-ecx -1836 58/pop-to-eax -1837 # . epilogue -1838 89/<- %esp 5/r32/ebp -1839 5d/pop-to-ebp -1840 c3/return -1841 -1842 $populate-mu-function-header:error1: -1843 # error("function header not in form 'fn <name> {'") -1844 (write-buffered Stderr "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '") -1845 (flush Stderr) -1846 (rewind-stream *(ebp+8)) -1847 (write-stream 2 *(ebp+8)) -1848 (write-buffered Stderr "'\n") -1849 (flush Stderr) -1850 # . syscall(exit, 1) -1851 bb/copy-to-ebx 1/imm32 -1852 b8/copy-to-eax 1/imm32/exit -1853 cd/syscall 0x80/imm8 -1854 # never gets here -1855 -1856 $populate-mu-function-header:error2: -1857 # error("function input '" var "' cannot be in a register") -1858 (write-buffered Stderr "function input '") -1859 (write-buffered Stderr *ebx) # Var-name -1860 (write-buffered Stderr "' cannot be in a register") -1861 (flush Stderr) -1862 # . syscall(exit, 1) -1863 bb/copy-to-ebx 1/imm32 -1864 b8/copy-to-eax 1/imm32/exit -1865 cd/syscall 0x80/imm8 -1866 # never gets here -1867 -1868 $populate-mu-function-header:error3: -1869 # error("function input '" var "' must be in a register") -1870 (write-buffered Stderr "function input '") -1871 (write-buffered Stderr *eax) # Var-name -1872 (write-buffered Stderr " must be in a register'") -1873 (flush Stderr) -1874 (rewind-stream *(ebp+8)) -1875 (write-stream 2 *(ebp+8)) -1876 (write-buffered Stderr "'\n") -1877 (flush Stderr) -1878 # . syscall(exit, 1) -1879 bb/copy-to-ebx 1/imm32 -1880 b8/copy-to-eax 1/imm32/exit -1881 cd/syscall 0x80/imm8 -1882 # never gets here -1883 -1884 test-function-header-with-arg: -1885 # 'foo n : int {' -1886 # . prologue -1887 55/push-ebp -1888 89/<- %ebp 4/r32/esp -1889 # setup -1890 (clear-stream _test-input-stream) -1891 (write _test-input-stream "foo n : int {\n") -1892 # var result/ecx: function -1893 2b/subtract-> *Function-size 4/r32/esp -1894 89/<- %ecx 4/r32/esp -1895 (zero-out %ecx *Function-size) -1896 # var vars/ebx: (stack (addr var) 16) -1897 81 5/subop/subtract %esp 0x10/imm32 -1898 68/push 0x10/imm32/length -1899 68/push 0/imm32/top -1900 89/<- %ebx 4/r32/esp -1901 # convert -1902 (populate-mu-function-header _test-input-stream %ecx %ebx) -1903 # check result -1904 (check-strings-equal *ecx "foo" "F - test-function-header-with-arg/name") # Function-name -1905 # edx: (handle list var) = result->inouts -1906 8b/-> *(ecx+8) 2/r32/edx # Function-inouts -1907 # ebx: (handle var) = result->inouts->value -1908 8b/-> *edx 3/r32/ebx # List-value -1909 (check-strings-equal *ebx "n" "F - test-function-header-with-arg/inout:0") # Var-name -1910 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1911 (check-ints-equal *ebx 1 "F - test-function-header-with-arg/inout:0/type:0") # Tree-left -1912 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-arg/inout:0/type:1") # Tree-right -1913 # . epilogue -1914 89/<- %esp 5/r32/ebp -1915 5d/pop-to-ebp -1916 c3/return -1917 -1918 test-function-header-with-multiple-args: -1919 # 'fn foo a: int, b: int, c: int {' -1920 # . prologue -1921 55/push-ebp -1922 89/<- %ebp 4/r32/esp -1923 # setup -1924 (clear-stream _test-input-stream) -1925 (write _test-input-stream "foo a: int, b: int c: int {\n") -1926 # result/ecx: (handle function) -1927 2b/subtract-> *Function-size 4/r32/esp -1928 89/<- %ecx 4/r32/esp -1929 (zero-out %ecx *Function-size) -1930 # var vars/ebx: (stack (addr var) 16) -1931 81 5/subop/subtract %esp 0x10/imm32 -1932 68/push 0x10/imm32/length -1933 68/push 0/imm32/top -1934 89/<- %ebx 4/r32/esp -1935 # convert -1936 (populate-mu-function-header _test-input-stream %ecx %ebx) -1937 # check result -1938 (check-strings-equal *ecx "foo") # Function-name -1939 # edx: (handle list var) = result->inouts -1940 8b/-> *(ecx+8) 2/r32/edx # Function-inouts -1941 $test-function-header-with-multiple-args:inout0: -1942 # ebx: (handle var) = result->inouts->value -1943 8b/-> *edx 3/r32/ebx # List-value -1944 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name -1945 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1946 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:0/type:0") # Tree-left -1947 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:0/type:1") # Tree-right -1948 # edx = result->inouts->next -1949 8b/-> *(edx+4) 2/r32/edx # List-next -1950 $test-function-header-with-multiple-args:inout1: -1951 # ebx = result->inouts->next->value -1952 8b/-> *edx 3/r32/ebx # List-value -1953 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args/inout:1") # Var-name -1954 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1955 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:1/type:0") # Tree-left -1956 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:1/type:1") # Tree-right -1957 # edx = result->inouts->next->next -1958 8b/-> *(edx+4) 2/r32/edx # List-next -1959 $test-function-header-with-multiple-args:inout2: -1960 # ebx = result->inouts->next->next->value -1961 8b/-> *edx 3/r32/ebx # List-value -1962 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args/inout:2") # Var-name -1963 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1964 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:2/type:0") # Tree-left -1965 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:2/type:1") # Tree-right -1966 # . epilogue -1967 89/<- %esp 5/r32/ebp -1968 5d/pop-to-ebp -1969 c3/return -1970 -1971 test-function-with-multiple-args-and-outputs: -1972 # fn foo a: int, b: int, c: int -> x: int, y: int { -1973 # . prologue -1974 55/push-ebp -1975 89/<- %ebp 4/r32/esp -1976 # setup -1977 (clear-stream _test-input-stream) -1978 (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx: int {\n") -1979 # result/ecx: (handle function) -1980 2b/subtract-> *Function-size 4/r32/esp -1981 89/<- %ecx 4/r32/esp -1982 (zero-out %ecx *Function-size) -1983 # var vars/ebx: (stack (addr var) 16) -1984 81 5/subop/subtract %esp 0x10/imm32 -1985 68/push 0x10/imm32/length -1986 68/push 0/imm32/top -1987 89/<- %ebx 4/r32/esp -1988 # convert -1989 (populate-mu-function-header _test-input-stream %ecx %ebx) -1990 # check result -1991 (check-strings-equal *ecx "foo") # Function-name -1992 # edx: (handle list var) = result->inouts -1993 8b/-> *(ecx+8) 2/r32/edx # Function-inouts -1994 # ebx: (handle var) = result->inouts->value -1995 8b/-> *edx 3/r32/ebx # List-value -1996 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0") # Var-name -1997 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1998 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0") # Tree-left -1999 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1") # Tree-right -2000 # edx = result->inouts->next -2001 8b/-> *(edx+4) 2/r32/edx # List-next -2002 # ebx = result->inouts->next->value -2003 8b/-> *edx 3/r32/ebx # List-value -2004 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1") # Var-name -2005 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2006 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0") # Tree-left -2007 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1") # Tree-right -2008 # edx = result->inouts->next->next -2009 8b/-> *(edx+4) 2/r32/edx # List-next -2010 # ebx = result->inouts->next->next->value -2011 8b/-> *edx 3/r32/ebx # List-value -2012 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2") # Var-name -2013 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2014 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0") # Tree-left -2015 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1") # Tree-right -2016 # edx: (handle list var) = result->outputs -2017 8b/-> *(ecx+0xc) 2/r32/edx # Function-outputs -2018 # ebx: (handle var) = result->outputs->value -2019 8b/-> *edx 3/r32/ebx # List-value -2020 (check-strings-equal *ebx "x" "F - test-function-header-with-multiple-args-and-outputs/output:0") # Var-name -2021 (check-strings-equal *(ebx+0x10) "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register -2022 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2023 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-left -2024 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-right -2025 # edx = result->outputs->next -2026 8b/-> *(edx+4) 2/r32/edx # List-next -2027 # ebx = result->outputs->next->value -2028 8b/-> *edx 3/r32/ebx # List-value -2029 (check-strings-equal *ebx "y" "F - test-function-header-with-multiple-args-and-outputs/output:1") # Var-name -2030 (check-strings-equal *(ebx+0x10) "edx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register -2031 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2032 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-left -2033 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-right -2034 # . epilogue -2035 89/<- %esp 5/r32/ebp -2036 5d/pop-to-ebp -2037 c3/return -2038 -2039 # format for variables with types -2040 # x: int -2041 # x: int -2042 # x: int, -2043 # ignores at most one trailing colon or comma -2044 parse-var-with-type: # name: (addr slice), first-line: (addr stream byte) -> result/eax: (handle var) -2045 # pseudocode: -2046 # var v: (handle var) = allocate(Heap, Var-size) -2047 # var s: slice -2048 # next-token-from-slice(name->start, name->end, '/', s) -2049 # var end: (addr byte) = s->end -2050 # if (slice-ends-with(s, ":")) -2051 # decrement s->end -2052 # if (slice-ends-with(s, ",")) -2053 # decrement s->end -2054 # v->name = slice-to-string(s) -2055 # ## register -2056 # next-token-from-slice(end, name->end, '/', s) -2057 # if (slice-ends-with(s, ":")) -2058 # decrement s->end -2059 # if (slice-ends-with(s, ",")) -2060 # decrement s->end -2061 # if (!slice-empty?(s)) -2062 # v->register = slice-to-string(s) -2063 # ## type -2064 # var type: (handle tree type-id) = parse-type(first-line) -2065 # v->type = type -2066 # return v -2067 # -2068 # . prologue -2069 55/push-ebp -2070 89/<- %ebp 4/r32/esp -2071 # . save registers -2072 51/push-ecx -2073 52/push-edx -2074 53/push-ebx -2075 56/push-esi -2076 57/push-edi -2077 # var result/edi: (handle var) = allocate(Heap, Var-size) -2078 (allocate Heap *Var-size) # => eax -2079 (zero-out %eax *Var-size) -2080 89/<- %edi 0/r32/eax -2081 # esi = name -2082 8b/-> *(ebp+8) 6/r32/esi -2083 # var s/ecx: slice -2084 68/push 0/imm32/end -2085 68/push 0/imm32/start -2086 89/<- %ecx 4/r32/esp -2087 $parse-var-with-type:save-name: -2088 # save v->name -2089 (next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/' -2090 # . end/edx = s->end -2091 8b/-> *(ecx+4) 2/r32/edx -2092 # . if s ends with ':', decrement s->end -2093 { -2094 8b/-> *(ecx+4) 0/r32/eax -2095 48/decrement-eax -2096 8a/copy-byte *eax 3/r32/BL -2097 81 4/subop/and %ebx 0xff/imm32 -2098 81 7/subop/compare %ebx 0x3a/imm32/colon -2099 75/jump-if-!= break/disp8 -2100 89/<- *(ecx+4) 0/r32/eax -2101 } -2102 # . if s ends with ',', decrement s->end -2103 { -2104 8b/-> *(ecx+4) 0/r32/eax -2105 48/decrement-eax -2106 8a/copy-byte *eax 3/r32/BL -2107 81 4/subop/and %ebx 0xff/imm32 -2108 81 7/subop/compare %ebx 0x2c/imm32/comma -2109 75/jump-if-!= break/disp8 -2110 89/<- *(ecx+4) 0/r32/eax -2111 } -2112 $parse-var-with-type:write-name: -2113 (slice-to-string Heap %ecx) # => eax -2114 89/<- *edi 0/r32/eax # Var-name -2115 # save v->register -2116 $parse-var-with-type:save-register: -2117 (next-token-from-slice %edx *(esi+4) 0x2f %ecx) # end, name->end, '/' -2118 # . if s ends with ':', decrement s->end -2119 { -2120 8b/-> *(ecx+4) 0/r32/eax -2121 48/decrement-eax -2122 8a/copy-byte *eax 3/r32/BL -2123 81 4/subop/and %ebx 0xff/imm32 -2124 81 7/subop/compare %ebx 0x3a/imm32/colon -2125 75/jump-if-!= break/disp8 -2126 89/<- *(ecx+4) 0/r32/eax -2127 } -2128 # . if s ends with ',', decrement s->end -2129 { -2130 8b/-> *(ecx+4) 0/r32/eax -2131 48/decrement-eax -2132 8a/copy-byte *eax 3/r32/BL -2133 81 4/subop/and %ebx 0xff/imm32 -2134 81 7/subop/compare %ebx 0x2c/imm32/comma -2135 75/jump-if-!= break/disp8 -2136 89/<- *(ecx+4) 0/r32/eax -2137 } -2138 # if (!slice-empty?(s)) v->register = slice-to-string(s) -2139 { -2140 $parse-var-with-type:write-register: -2141 # HACK: s->end can be less than s->start with all the decrements above -2142 # That's probably a sign we have the wrong algorithm for this function. -2143 8b/-> *ecx 0/r32/eax -2144 39/compare *(ecx+4) 0/r32/eax # Slice-end -2145 76/jump-if-<= break/disp8 -2146 (slice-to-string Heap %ecx) -2147 89/<- *(edi+0x10) 0/r32/eax # Var-register -2148 } -2149 $parse-var-with-type:save-type: -2150 (parse-type Heap *(ebp+0xc)) # => eax -2151 89/<- *(edi+4) 0/r32/eax # Var-type -2152 $parse-var-with-type:end: -2153 # return result -2154 89/<- %eax 7/r32/edi -2155 # . reclaim locals -2156 81 0/subop/add %esp 8/imm32 -2157 # . restore registers -2158 5f/pop-to-edi -2159 5e/pop-to-esi -2160 5b/pop-to-ebx -2161 5a/pop-to-edx -2162 59/pop-to-ecx -2163 # . epilogue -2164 89/<- %esp 5/r32/ebp -2165 5d/pop-to-ebp -2166 c3/return -2167 -2168 $parse-var-with-type:abort: -2169 # error("function header not in form 'fn <name> {'") -2170 (write-buffered Stderr "var should have form 'name: type' in '") -2171 (flush Stderr) -2172 (rewind-stream *(ebp+0xc)) -2173 (write-stream 2 *(ebp+0xc)) -2174 (write-buffered Stderr "'\n") -2175 (flush Stderr) -2176 # . syscall(exit, 1) -2177 bb/copy-to-ebx 1/imm32 -2178 b8/copy-to-eax 1/imm32/exit -2179 cd/syscall 0x80/imm8 -2180 # never gets here -2181 -2182 parse-type: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) -2183 # pseudocode: -2184 # var s: slice = next-mu-token(in) -2185 # assert s != "" -2186 # assert s != "->" -2187 # assert s != "{" -2188 # assert s != "}" -2189 # if s == ")" -2190 # return 0 -2191 # result = allocate(Tree) -2192 # zero-out(result, *Tree-size) -2193 # if s != "(" -2194 # result->left = pos-slice(Type-id, s) -2195 # return -2196 # result->left = parse-type(ad, in) -2197 # result->right = parse-type-tree(ad, in) -2198 # -2199 # . prologue -2200 55/push-ebp -2201 89/<- %ebp 4/r32/esp -2202 # . save registers -2203 51/push-ecx -2204 52/push-edx -2205 # var s/ecx: slice -2206 68/push 0/imm32 -2207 68/push 0/imm32 -2208 89/<- %ecx 4/r32/esp -2209 # s = next-mu-token(in) -2210 (next-mu-token *(ebp+0xc) %ecx) -2211 #? (write-buffered Stderr "tok: ") -2212 #? (write-slice-buffered Stderr %ecx) -2213 #? (write-buffered Stderr "$\n") -2214 #? (flush Stderr) -2215 # assert s != "" -2216 (slice-equal? %ecx "") -2217 3d/compare-eax-and 0/imm32 -2218 0f 85/jump-if-!= $parse-type:abort/disp32 -2219 # assert s != "{" -2220 (slice-equal? %ecx "{") -2221 3d/compare-eax-and 0/imm32 -2222 0f 85/jump-if-!= $parse-type:abort/disp32 -2223 # assert s != "}" -2224 (slice-equal? %ecx "}") -2225 3d/compare-eax-and 0/imm32 -2226 0f 85/jump-if-!= $parse-type:abort/disp32 -2227 # assert s != "->" -2228 (slice-equal? %ecx "->") -2229 3d/compare-eax-and 0/imm32 -2230 0f 85/jump-if-!= $parse-type:abort/disp32 -2231 # if (s == ")") return 0 -2232 (slice-equal? %ecx ")") -2233 3d/compare-eax-and 0/imm32 -2234 b8/copy-to-eax 0/imm32 -2235 0f 85/jump-if-!= $parse-type:end/disp32 -2236 # var result/edx: (handle tree type-id) -2237 (allocate *(ebp+8) *Tree-size) # => eax -2238 (zero-out %eax *Tree-size) -2239 89/<- %edx 0/r32/eax -2240 { -2241 # if (s != "(") break -2242 (slice-equal? %ecx "(") -2243 3d/compare-eax-and 0/imm32 -2244 75/jump-if-!= break/disp8 -2245 # result->left = pos-slice(Type-id, s) -2246 (pos-slice Type-id %ecx) -2247 #? (write-buffered Stderr "=> {") -2248 #? (print-int32-buffered Stderr %eax) -2249 #? (write-buffered Stderr ", 0}\n") -2250 #? (flush Stderr) -2251 89/<- *edx 0/r32/eax # Tree-left -2252 e9/jump $parse-type:return-edx/disp32 -2253 } -2254 # otherwise s == "(" -2255 # result->left = parse-type(ad, in) -2256 (parse-type *(ebp+8) *(ebp+0xc)) -2257 #? (write-buffered Stderr "=> {") -2258 #? (print-int32-buffered Stderr %eax) -2259 89/<- *edx 0/r32/eax # Tree-left -2260 # result->right = parse-type-tree(ad, in) -2261 (parse-type-tree *(ebp+8) *(ebp+0xc)) -2262 #? (write-buffered Stderr Space) -2263 #? (print-int32-buffered Stderr %eax) -2264 #? (write-buffered Stderr "}\n") -2265 #? (flush Stderr) -2266 89/<- *(edx+4) 0/r32/eax # Tree-right -2267 $parse-type:return-edx: -2268 89/<- %eax 2/r32/edx -2269 $parse-type:end: -2270 # . reclaim locals -2271 81 0/subop/add %esp 8/imm32 -2272 # . restore registers -2273 5a/pop-to-edx -2274 59/pop-to-ecx -2275 # . epilogue -2276 89/<- %esp 5/r32/ebp -2277 5d/pop-to-ebp -2278 c3/return -2279 -2280 $parse-type:abort: -2281 # error("unexpected token when parsing type: '" s "'\n") -2282 (write-buffered Stderr "unexpected token when parsing type: '") -2283 (write-slice-buffered Stderr %ecx) -2284 (write-buffered Stderr "'\n") -2285 (flush Stderr) -2286 # . syscall(exit, 1) -2287 bb/copy-to-ebx 1/imm32 -2288 b8/copy-to-eax 1/imm32/exit -2289 cd/syscall 0x80/imm8 -2290 # never gets here -2291 -2292 parse-type-tree: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) -2293 # pseudocode: -2294 # var tmp: (handle tree type-id) = parse-type(ad, in) -2295 # if tmp == 0 -2296 # return 0 -2297 # result = allocate(Tree) -2298 # zero-out(result, *Tree-size) -2299 # result->left = tmp -2300 # result->right = parse-type-tree(ad, in) -2301 # -2302 # . prologue -2303 55/push-ebp -2304 89/<- %ebp 4/r32/esp -2305 # . save registers -2306 51/push-ecx -2307 52/push-edx -2308 # var tmp/eax: (handle tree type-id) = parse-type(ad, in) -2309 (parse-type *(ebp+8) *(ebp+0xc)) -2310 # if (tmp == 0) return tmp -2311 3d/compare-eax-and 0/imm32 -2312 74/jump-if-= $parse-type-tree:end/disp8 -2313 # var tmp2/ecx = tmp -2314 89/<- %ecx 0/r32/eax -2315 # var result/edx: (handle tree type-id) -2316 (allocate *(ebp+8) *Tree-size) # => eax -2317 (zero-out %eax *Tree-size) -2318 89/<- %edx 0/r32/eax -2319 # result->left = tmp2 -2320 89/<- *edx 1/r32/ecx # Tree-left -2321 # result->right = parse-type-tree(ad, in) -2322 (parse-type-tree *(ebp+8) *(ebp+0xc)) -2323 89/<- *(edx+4) 0/r32/eax # Tree-right -2324 $parse-type-tree:return-edx: -2325 89/<- %eax 2/r32/edx -2326 $parse-type-tree:end: -2327 # . restore registers -2328 5a/pop-to-edx -2329 59/pop-to-ecx -2330 # . epilogue -2331 89/<- %esp 5/r32/ebp -2332 5d/pop-to-ebp -2333 c3/return -2334 -2335 next-mu-token: # in: (addr stream byte), out: (addr slice) -2336 # pseudocode: -2337 # start: -2338 # skip-chars-matching-whitespace(in) -2339 # if in->read >= in->write # end of in -2340 # out = {0, 0} -2341 # return -2342 # out->start = &in->data[in->read] -2343 # var curr-byte/eax: byte = in->data[in->read] -2344 # if curr->byte == ':' # comment token -2345 # ++in->read -2346 # goto start -2347 # if curr->byte == ',' # comment token -2348 # ++in->read -2349 # goto start -2350 # if curr-byte == '#' # comment -2351 # in->read = in->write # skip to end of in -2352 # goto done -2353 # if curr-byte == '"' # string literal -2354 # skip-string(in) -2355 # goto done # no metadata -2356 # if curr-byte == '(' -2357 # ++in->read -2358 # goto done -2359 # if curr-byte == ')' -2360 # ++in->read -2361 # goto done -2362 # # read a word -2363 # while true -2364 # if in->read >= in->write -2365 # break -2366 # curr-byte = in->data[in->read] -2367 # if curr-byte == ' ' -2368 # break -2369 # if curr-byte == '\r' -2370 # break -2371 # if curr-byte == '\n' -2372 # break -2373 # if curr-byte == '(' -2374 # break -2375 # if curr-byte == ')' -2376 # break -2377 # if curr-byte == ':' -2378 # break -2379 # if curr-byte == ',' -2380 # break -2381 # ++in->read -2382 # done: -2383 # out->end = &in->data[in->read] -2384 # # hack: skip a few trailing delimiters, because we don't always use -2385 # # this correct tokenizer in later tokens -2386 # while true -2387 # if in->read >= in->write -2388 # break -2389 # curr-byte = in->data[in->read] -2390 # if curr-byte == ':' -2391 # ++in->read -2392 # else if curr-byte == ',' -2393 # ++in->read -2394 # else -2395 # break -2396 # -2397 # . prologue -2398 55/push-ebp -2399 89/<- %ebp 4/r32/esp -2400 # . save registers -2401 50/push-eax -2402 51/push-ecx -2403 56/push-esi -2404 57/push-edi -2405 # esi = in -2406 8b/-> *(ebp+8) 6/r32/esi -2407 # edi = out -2408 8b/-> *(ebp+0xc) 7/r32/edi -2409 $next-mu-token:start: -2410 (skip-chars-matching-whitespace %esi) -2411 $next-mu-token:check0: -2412 # if (in->read >= in->write) return out = {0, 0} -2413 # . ecx = in->read -2414 8b/-> *(esi+4) 1/r32/ecx -2415 # . if (ecx >= in->write) return out = {0, 0} -2416 3b/compare 1/r32/ecx *esi -2417 c7 0/subop/copy *edi 0/imm32 -2418 c7 0/subop/copy *(edi+4) 0/imm32 -2419 0f 8d/jump-if->= $next-mu-token:end/disp32 -2420 # out->start = &in->data[in->read] -2421 8d/copy-address *(esi+ecx+0xc) 0/r32/eax -2422 89/<- *edi 0/r32/eax -2423 # var curr-byte/eax: byte = in->data[in->read] -2424 31/xor %eax 0/r32/eax -2425 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -2426 { -2427 $next-mu-token:check-for-colon: -2428 # if (curr-byte != ':') break -2429 3d/compare-eax-and 0x3a/imm32/colon -2430 75/jump-if-!= break/disp8 -2431 # ++in->read -2432 ff 0/subop/increment *(esi+4) -2433 # restart -2434 e9/jump $next-mu-token:start/disp32 -2435 } -2436 { -2437 $next-mu-token:check-for-comma: -2438 # if (curr-byte != ',') break -2439 3d/compare-eax-and 0x2c/imm32/comma -2440 75/jump-if-!= break/disp8 -2441 # ++in->read -2442 ff 0/subop/increment *(esi+4) -2443 # restart -2444 e9/jump $next-mu-token:start/disp32 -2445 } -2446 { -2447 $next-mu-token:check-for-comment: -2448 # if (curr-byte != '#') break -2449 3d/compare-eax-and 0x23/imm32/pound -2450 75/jump-if-!= break/disp8 -2451 # in->read = in->write # skip rest of in -2452 8b/-> *esi 0/r32/eax -2453 89/<- *(esi+4) 0/r32/eax -2454 # return -2455 e9/jump $next-mu-token:done/disp32 -2456 } -2457 { -2458 $next-mu-token:check-for-string-literal: -2459 # if (curr-byte != '"') break -2460 3d/compare-eax-and 0x22/imm32/dquote -2461 75/jump-if-!= break/disp8 -2462 (skip-string %esi) -2463 # return -2464 e9/jump $next-mu-token:done/disp32 -2465 } -2466 { -2467 $next-mu-token:check-for-open-paren: -2468 # if (curr-byte != '(') break -2469 3d/compare-eax-and 0x28/imm32/open-paren -2470 75/jump-if-!= break/disp8 -2471 # ++in->read -2472 ff 0/subop/increment *(esi+4) -2473 # return -2474 e9/jump $next-mu-token:done/disp32 -2475 } -2476 { -2477 $next-mu-token:check-for-close-paren: -2478 # if (curr-byte != ')') break -2479 3d/compare-eax-and 0x29/imm32/close-paren -2480 75/jump-if-!= break/disp8 -2481 # ++in->read -2482 ff 0/subop/increment *(esi+4) -2483 # return -2484 e9/jump $next-mu-token:done/disp32 -2485 } -2486 { -2487 $next-mu-token:regular-word-without-metadata: -2488 # if (in->read >= in->write) break -2489 # . ecx = in->read -2490 8b/-> *(esi+4) 1/r32/ecx -2491 # . if (ecx >= in->write) break -2492 3b/compare *esi 1/r32/ecx -2493 7d/jump-if->= break/disp8 -2494 # var c/eax: byte = in->data[in->read] -2495 31/xor %eax 0/r32/eax -2496 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -2497 # if (c == ' ') break -2498 3d/compare-eax-and 0x20/imm32/space -2499 74/jump-if-= break/disp8 -2500 # if (c == '\r') break -2501 3d/compare-eax-and 0xd/imm32/carriage-return -2502 74/jump-if-= break/disp8 -2503 # if (c == '\n') break -2504 3d/compare-eax-and 0xa/imm32/newline -2505 74/jump-if-= break/disp8 -2506 # if (c == '(') break -2507 3d/compare-eax-and 0x28/imm32/open-paren -2508 0f 84/jump-if-= break/disp32 -2509 # if (c == ')') break -2510 3d/compare-eax-and 0x29/imm32/close-paren -2511 0f 84/jump-if-= break/disp32 -2512 # if (c == ':') break -2513 3d/compare-eax-and 0x3a/imm32/colon -2514 0f 84/jump-if-= break/disp32 -2515 # if (c == ',') break -2516 3d/compare-eax-and 0x2c/imm32/comma -2517 0f 84/jump-if-= break/disp32 -2518 # ++in->read -2519 ff 0/subop/increment *(esi+4) -2520 # -2521 e9/jump loop/disp32 -2522 } -2523 $next-mu-token:done: -2524 # out->end = &in->data[in->read] -2525 8b/-> *(esi+4) 1/r32/ecx -2526 8d/copy-address *(esi+ecx+0xc) 0/r32/eax -2527 89/<- *(edi+4) 0/r32/eax -2528 { -2529 $next-mu-token:skip-trailing-delimiters: -2530 # if (in->read >= in->write) break -2531 # . ecx = in->read -2532 8b/-> *(esi+4) 1/r32/ecx -2533 # . if (ecx >= in->write) break -2534 3b/compare *esi 1/r32/ecx -2535 7d/jump-if->= break/disp8 -2536 # var c/eax: byte = in->data[in->read] -2537 31/xor %eax 0/r32/eax -2538 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -2539 # if (c == ':') ++in->read and loop -2540 { -2541 3d/compare-eax-and 0x3a/imm32/colon -2542 75/jump-if-!= break/disp8 -2543 # ++in->read -2544 ff 0/subop/increment *(esi+4) -2545 # -2546 eb/jump $next-mu-token:skip-trailing-delimiters/disp8 -2547 } -2548 # if (c == ',') ++in->read and loop -2549 { -2550 3d/compare-eax-and 0x2c/imm32/comma -2551 75/jump-if-!= break/disp8 -2552 # ++in->read -2553 ff 0/subop/increment *(esi+4) -2554 # -2555 eb/jump $next-mu-token:skip-trailing-delimiters/disp8 -2556 } -2557 # else break -2558 } -2559 $next-mu-token:end: -2560 # . restore registers -2561 5f/pop-to-edi -2562 5e/pop-to-esi -2563 59/pop-to-ecx -2564 58/pop-to-eax -2565 # . epilogue -2566 89/<- %esp 5/r32/ebp -2567 5d/pop-to-ebp -2568 c3/return -2569 -2570 # return the index in an array of strings matching 's' -2571 # index is denominated in elements, not bytes -2572 pos-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int -2573 # . prologue -2574 55/push-ebp -2575 89/<- %ebp 4/r32/esp -2576 # . save registers -2577 51/push-ecx -2578 52/push-edx -2579 53/push-ebx -2580 56/push-esi -2581 #? (write-buffered Stderr "pos-slice: ") -2582 #? (write-slice-buffered Stderr *(ebp+0xc)) -2583 #? (write-buffered Stderr "\n") -2584 #? (flush Stderr) -2585 # esi = arr -2586 8b/-> *(ebp+8) 6/r32/esi -2587 # var index/ecx: int = 0 -2588 b9/copy-to-ecx 0/imm32 -2589 # var curr/edx: (addr (addr array byte)) = arr->data -2590 8d/copy-address *(esi+0xc) 2/r32/edx -2591 # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write] -2592 8b/-> *esi 3/r32/ebx -2593 8d/copy-address *(esi+ebx+0xc) 3/r32/ebx -2594 { -2595 #? (write-buffered Stderr " ") -2596 #? (print-int32-buffered Stderr %ecx) -2597 #? (write-buffered Stderr "\n") -2598 #? (flush Stderr) -2599 # if (curr >= max) return -1 -2600 39/compare %edx 3/r32/ebx -2601 b8/copy-to-eax -1/imm32 -2602 73/jump-if-addr>= $pos-slice:end/disp8 -2603 # if (slice-equal?(s, *curr)) break -2604 (slice-equal? *(ebp+0xc) *edx) # => eax -2605 3d/compare-eax-and 0/imm32 -2606 75/jump-if-!= break/disp8 -2607 # ++index -2608 41/increment-ecx -2609 # curr += 4 -2610 81 0/subop/add %edx 4/imm32 -2611 # -2612 eb/jump loop/disp8 -2613 } -2614 # return index -2615 89/<- %eax 1/r32/ecx -2616 $pos-slice:end: -2617 #? (write-buffered Stderr "=> ") -2618 #? (print-int32-buffered Stderr %eax) -2619 #? (write-buffered Stderr "\n") -2620 # . restore registers -2621 5e/pop-to-esi -2622 5b/pop-to-ebx -2623 5a/pop-to-edx -2624 59/pop-to-ecx -2625 # . epilogue -2626 89/<- %esp 5/r32/ebp -2627 5d/pop-to-ebp -2628 c3/return -2629 -2630 == data -2631 -2632 Type-id: # (stream (address array byte)) -2633 0x18/imm32/write -2634 0/imm32/read -2635 0x100/imm32/length -2636 # data -2637 "literal"/imm32 # 0 -2638 "int"/imm32 # 1 -2639 "addr"/imm32 # 2 -2640 "array"/imm32 # 3 -2641 "handle"/imm32 # 4 -2642 "bool"/imm32 # 5 -2643 0/imm32 -2644 0/imm32 -2645 # 0x20 -2646 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2647 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2648 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2649 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2650 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2651 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2652 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2653 -2654 == code -2655 -2656 test-parse-var-with-type: -2657 # . prologue -2658 55/push-ebp -2659 89/<- %ebp 4/r32/esp -2660 # (eax..ecx) = "x:" -2661 b8/copy-to-eax "x:"/imm32 -2662 8b/-> *eax 1/r32/ecx -2663 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2664 05/add-to-eax 4/imm32 -2665 # var slice/ecx: slice = {eax, ecx} -2666 51/push-ecx -2667 50/push-eax -2668 89/<- %ecx 4/r32/esp -2669 # _test-input-stream contains "int" -2670 (clear-stream _test-input-stream) -2671 (write _test-input-stream "int") -2672 # -2673 (parse-var-with-type %ecx _test-input-stream) -2674 8b/-> *eax 2/r32/edx # Var-name -2675 (check-strings-equal %edx "x" "F - test-var-with-type/name") -2676 8b/-> *(eax+4) 2/r32/edx # Var-type -2677 (check-ints-equal *edx 1 "F - test-var-with-type/type") -2678 (check-ints-equal *(edx+4) 0 "F - test-var-with-type/type") -2679 # . epilogue -2680 89/<- %esp 5/r32/ebp -2681 5d/pop-to-ebp -2682 c3/return -2683 -2684 test-parse-var-with-type-and-register: -2685 # . prologue -2686 55/push-ebp -2687 89/<- %ebp 4/r32/esp -2688 # (eax..ecx) = "x/eax" -2689 b8/copy-to-eax "x/eax"/imm32 -2690 8b/-> *eax 1/r32/ecx -2691 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2692 05/add-to-eax 4/imm32 -2693 # var slice/ecx: slice = {eax, ecx} -2694 51/push-ecx -2695 50/push-eax -2696 89/<- %ecx 4/r32/esp -2697 # _test-input-stream contains ": int" -2698 (clear-stream _test-input-stream) -2699 (write _test-input-stream ": int") +1195 (write _test-input-stream " break-if->=\n") +1196 (write _test-input-stream " increment x\n") +1197 (write _test-input-stream " }\n") +1198 (write _test-input-stream "}\n") +1199 # convert +1200 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1201 (flush _test-output-buffered-file) +1202 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1208 # check output +1209 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-local-vars/0") +1210 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-local-vars/1") +1211 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-local-vars/2") +1212 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-and-local-vars/3") +1213 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/4") +1214 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/5") +1215 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-local-vars/6") +1216 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/7") +1217 (check-next-stream-line-equal _test-output-stream " 0f 8d/jump-if->= break/disp32" "F - test-convert-function-with-branches-and-local-vars/8") +1218 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-branches-and-local-vars/9") +1219 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/10") +1220 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-branches-and-local-vars/11") +1221 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/12") +1222 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/13") +1223 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-local-vars/14") +1224 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-and-local-vars/15") +1225 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-local-vars/16") +1226 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-local-vars/17") +1227 # . epilogue +1228 89/<- %esp 5/r32/ebp +1229 5d/pop-to-ebp +1230 c3/return +1231 +1232 ####################################################### +1233 # Parsing +1234 ####################################################### +1235 +1236 parse-mu: # in: (addr buffered-file) +1237 # pseudocode +1238 # var curr-function: (addr (handle function)) = Program +1239 # var line: (stream byte 512) +1240 # var word-slice: slice +1241 # while true # line loop +1242 # clear-stream(line) +1243 # read-line-buffered(in, line) +1244 # if (line->write == 0) break # end of file +1245 # word-slice = next-mu-token(line) +1246 # if slice-empty?(word-slice) # end of line +1247 # continue +1248 # else if slice-starts-with?(word-slice, "#") # comment +1249 # continue # end of line +1250 # else if slice-equal(word-slice, "fn") +1251 # var new-function: (handle function) = allocate(function) +1252 # var vars: (stack (addr var) 256) +1253 # populate-mu-function-header(in, new-function, vars) +1254 # populate-mu-function-body(in, new-function, vars) +1255 # assert(vars->top == 0) +1256 # *curr-function = new-function +1257 # curr-function = &new-function->next +1258 # else +1259 # abort() +1260 # +1261 # . prologue +1262 55/push-ebp +1263 89/<- %ebp 4/r32/esp +1264 # . save registers +1265 50/push-eax +1266 51/push-ecx +1267 52/push-edx +1268 53/push-ebx +1269 57/push-edi +1270 # var line/ecx: (stream byte 512) +1271 81 5/subop/subtract %esp 0x200/imm32 +1272 68/push 0x200/imm32/length +1273 68/push 0/imm32/read +1274 68/push 0/imm32/write +1275 89/<- %ecx 4/r32/esp +1276 # var word-slice/edx: slice +1277 68/push 0/imm32/end +1278 68/push 0/imm32/start +1279 89/<- %edx 4/r32/esp +1280 # var curr-function/edi: (addr (handle function)) = Program +1281 bf/copy-to-edi Program/imm32 +1282 # var vars/ebx: (stack (addr var) 256) +1283 81 5/subop/subtract %esp 0x400/imm32 +1284 68/push 0x400/imm32/length +1285 68/push 0/imm32/top +1286 89/<- %ebx 4/r32/esp +1287 { +1288 $parse-mu:line-loop: +1289 (clear-stream %ecx) +1290 (read-line-buffered *(ebp+8) %ecx) +1291 # if (line->write == 0) break +1292 81 7/subop/compare *ecx 0/imm32 +1293 0f 84/jump-if-= break/disp32 +1294 +-- 6 lines: #? # dump line --------------------------------------------------------------------------------------------------------------------------- +1300 (next-mu-token %ecx %edx) +1301 # if slice-empty?(word-slice) continue +1302 (slice-empty? %edx) +1303 3d/compare-eax-and 0/imm32 +1304 0f 85/jump-if-!= loop/disp32 +1305 # if (*word-slice->start == "#") continue +1306 # . eax = *word-slice->start +1307 8b/-> *edx 0/r32/eax +1308 8a/copy-byte *eax 0/r32/AL +1309 81 4/subop/and %eax 0xff/imm32 +1310 # . if (eax == '#') continue +1311 3d/compare-eax-and 0x23/imm32/hash +1312 0f 84/jump-if-= loop/disp32 +1313 # if (slice-equal?(word-slice, "fn")) parse a function +1314 { +1315 $parse-mu:fn: +1316 (slice-equal? %edx "fn") +1317 3d/compare-eax-and 0/imm32 +1318 0f 84/jump-if-= break/disp32 +1319 # var new-function/eax: (handle function) = populate-mu-function(in, new-function, vars) +1320 (allocate Heap *Function-size) # => eax +1321 (zero-out %eax *Function-size) +1322 (clear-stack %ebx) +1323 (populate-mu-function-header %ecx %eax %ebx) +1324 (populate-mu-function-body *(ebp+8) %eax %ebx) +1325 # *curr-function = new-function +1326 89/<- *edi 0/r32/eax +1327 # curr-function = &new-function->next +1328 8d/address-> *(eax+0x14) 7/r32/edi # Function-next +1329 e9/jump $parse-mu:line-loop/disp32 +1330 } +1331 # otherwise abort +1332 e9/jump $parse-mu:error1/disp32 +1333 } # end line loop +1334 $parse-mu:end: +1335 # . reclaim locals +1336 81 0/subop/add %esp 0x630/imm32 +1337 # . restore registers +1338 5f/pop-to-edi +1339 5b/pop-to-ebx +1340 5a/pop-to-edx +1341 59/pop-to-ecx +1342 58/pop-to-eax +1343 # . epilogue +1344 89/<- %esp 5/r32/ebp +1345 5d/pop-to-ebp +1346 c3/return +1347 +1348 $parse-mu:error1: +1349 # error("unexpected top-level command: " word-slice "\n") +1350 (write-buffered Stderr "unexpected top-level command: ") +1351 (write-slice-buffered Stderr %edx) +1352 (write-buffered Stderr "\n") +1353 (flush Stderr) +1354 # . syscall(exit, 1) +1355 bb/copy-to-ebx 1/imm32 +1356 b8/copy-to-eax 1/imm32/exit +1357 cd/syscall 0x80/imm8 +1358 # never gets here +1359 +1360 $parse-mu:error2: +1361 # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n") +1362 (print-int32-buffered Stderr *ebx) +1363 (write-buffered Stderr " vars not reclaimed after fn '") +1364 (write-slice-buffered Stderr *eax) # Function-name +1365 (write-buffered Stderr "'\n") +1366 (flush Stderr) +1367 # . syscall(exit, 1) +1368 bb/copy-to-ebx 1/imm32 +1369 b8/copy-to-eax 1/imm32/exit +1370 cd/syscall 0x80/imm8 +1371 # never gets here +1372 +1373 # scenarios considered: +1374 # ✗ fn foo # no block +1375 # ✓ fn foo { +1376 # ✗ fn foo { { +1377 # ✗ fn foo { } +1378 # ✗ fn foo { } { +1379 # ✗ fn foo x { +1380 # ✗ fn foo x: { +1381 # ✓ fn foo x: int { +1382 # ✓ fn foo x: int { +1383 # ✓ fn foo x: int -> y/eax: int { +1384 populate-mu-function-header: # first-line: (addr stream byte), out: (handle function), vars: (addr stack (handle var)) +1385 # pseudocode: +1386 # var name: slice +1387 # next-word(first-line, name) +1388 # assert(name not in '{' '}' '->') +1389 # out->name = slice-to-string(name) +1390 # var next-offset: int = 8 +1391 # ## inouts +1392 # while true +1393 # ## name +1394 # name = next-word(first-line) +1395 # if (name == '{') goto done +1396 # if (name == '->') break +1397 # assert(name != '}') +1398 # var v: (handle var) = parse-var-with-type(name, first-line) +1399 # assert(v->register == null) +1400 # v->stack-offset = next-offset +1401 # next-offset += size-of(v) +1402 # # v->block-depth is implicitly 0 +1403 # out->inouts = append(out->inouts, v) +1404 # push(vars, v) +1405 # ## outputs +1406 # while true +1407 # ## name +1408 # name = next-word(first-line) +1409 # assert(name not in '{' '}' '->') +1410 # var v: (handle var) = parse-var-with-type(name, first-line) +1411 # assert(v->register != null) +1412 # out->outputs = append(out->outputs, v) +1413 # done: +1414 # +1415 # . prologue +1416 55/push-ebp +1417 89/<- %ebp 4/r32/esp +1418 # . save registers +1419 50/push-eax +1420 51/push-ecx +1421 52/push-edx +1422 53/push-ebx +1423 57/push-edi +1424 # edi = out +1425 8b/-> *(ebp+0xc) 7/r32/edi +1426 # var word-slice/ecx: slice +1427 68/push 0/imm32/end +1428 68/push 0/imm32/start +1429 89/<- %ecx 4/r32/esp +1430 # var next-offset/edx = 8 +1431 ba/copy-to-edx 8/imm32 +1432 # read function name +1433 (next-word *(ebp+8) %ecx) +1434 # error checking +1435 # if (word-slice == '{') abort +1436 (slice-equal? %ecx "{") # => eax +1437 3d/compare-eax-and 0/imm32 +1438 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +1439 # if (word-slice == '->') abort +1440 (slice-equal? %ecx "->") # => eax +1441 3d/compare-eax-and 0/imm32 +1442 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +1443 # if (word-slice == '}') abort +1444 (slice-equal? %ecx "}") # => eax +1445 3d/compare-eax-and 0/imm32 +1446 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +1447 # save function name +1448 (slice-to-string Heap %ecx) # => eax +1449 89/<- *edi 0/r32/eax # Function-name +1450 # initialize default subx-name as well +1451 89/<- *(edi+4) 0/r32/eax # Function-subx-name +1452 # save function inouts +1453 { +1454 $populate-mu-function-header:check-for-inout: +1455 (next-word *(ebp+8) %ecx) +1456 # if (word-slice == '{') goto done +1457 (slice-equal? %ecx "{") # => eax +1458 3d/compare-eax-and 0/imm32 +1459 0f 85/jump-if-!= $populate-mu-function-header:done/disp32 +1460 # if (word-slice == '->') break +1461 (slice-equal? %ecx "->") # => eax +1462 3d/compare-eax-and 0/imm32 +1463 0f 85/jump-if-!= break/disp32 +1464 # if (word-slice == '}') abort +1465 (slice-equal? %ecx "}") # => eax +1466 3d/compare-eax-and 0/imm32 +1467 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +1468 # var v/ebx: (handle var) = parse-var-with-type(word-slice, first-line) +1469 (parse-var-with-type %ecx *(ebp+8)) # => eax +1470 89/<- %ebx 0/r32/eax +1471 # assert(v->register == null) +1472 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register +1473 0f 85/jump-if-!= $populate-mu-function-header:error2/disp32 +1474 # v->stack-offset = next-offset +1475 89/<- *(ebx+0xc) 2/r32/edx # Var-stack-offset +1476 # next-offset += size-of(v) +1477 (size-of %ebx) # => eax +1478 01/add %edx 0/r32/eax +1479 # v->block-depth is implicitly 0 +1480 # +1481 (append-list Heap %ebx *(edi+8)) # Function-inouts => eax +1482 89/<- *(edi+8) 0/r32/eax # Function-inouts +1483 (push *(ebp+0x10) %ebx) +1484 # +1485 e9/jump loop/disp32 +1486 } +1487 # save function outputs +1488 { +1489 $parse-var-with-type:check-for-out: +1490 (next-word *(ebp+8) %ecx) +1491 # if (word-slice == '{') break +1492 (slice-equal? %ecx "{") # => eax +1493 3d/compare-eax-and 0/imm32 +1494 0f 85/jump-if-!= break/disp32 +1495 # if (word-slice == '->') abort +1496 (slice-equal? %ecx "->") # => eax +1497 3d/compare-eax-and 0/imm32 +1498 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +1499 # if (word-slice == '}') abort +1500 (slice-equal? %ecx "}") # => eax +1501 3d/compare-eax-and 0/imm32 +1502 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +1503 # +1504 (parse-var-with-type %ecx *(ebp+8)) # => eax +1505 89/<- %ebx 0/r32/eax +1506 # assert(var->register != null) +1507 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register +1508 0f 84/jump-if-= $populate-mu-function-header:error3/disp32 +1509 (append-list Heap %ebx *(edi+0xc)) # Function-outputs => eax +1510 89/<- *(edi+0xc) 0/r32/eax # Function-outputs +1511 e9/jump loop/disp32 +1512 } +1513 $populate-mu-function-header:done: +1514 (check-no-tokens-left *(ebp+8)) +1515 $populate-mu-function-header:end: +1516 # . reclaim locals +1517 81 0/subop/add %esp 8/imm32 +1518 # . restore registers +1519 5f/pop-to-edi +1520 5b/pop-to-ebx +1521 5a/pop-to-edx +1522 59/pop-to-ecx +1523 58/pop-to-eax +1524 # . epilogue +1525 89/<- %esp 5/r32/ebp +1526 5d/pop-to-ebp +1527 c3/return +1528 +1529 $populate-mu-function-header:error1: +1530 # error("function header not in form 'fn <name> {'") +1531 (write-buffered Stderr "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '") +1532 (flush Stderr) +1533 (rewind-stream *(ebp+8)) +1534 (write-stream 2 *(ebp+8)) +1535 (write-buffered Stderr "'\n") +1536 (flush Stderr) +1537 # . syscall(exit, 1) +1538 bb/copy-to-ebx 1/imm32 +1539 b8/copy-to-eax 1/imm32/exit +1540 cd/syscall 0x80/imm8 +1541 # never gets here +1542 +1543 $populate-mu-function-header:error2: +1544 # error("function input '" var "' cannot be in a register") +1545 (write-buffered Stderr "function input '") +1546 (write-buffered Stderr *ebx) # Var-name +1547 (write-buffered Stderr "' cannot be in a register") +1548 (flush Stderr) +1549 # . syscall(exit, 1) +1550 bb/copy-to-ebx 1/imm32 +1551 b8/copy-to-eax 1/imm32/exit +1552 cd/syscall 0x80/imm8 +1553 # never gets here +1554 +1555 $populate-mu-function-header:error3: +1556 # error("function input '" var "' must be in a register") +1557 (write-buffered Stderr "function input '") +1558 (write-buffered Stderr *eax) # Var-name +1559 (write-buffered Stderr " must be in a register'") +1560 (flush Stderr) +1561 (rewind-stream *(ebp+8)) +1562 (write-stream 2 *(ebp+8)) +1563 (write-buffered Stderr "'\n") +1564 (flush Stderr) +1565 # . syscall(exit, 1) +1566 bb/copy-to-ebx 1/imm32 +1567 b8/copy-to-eax 1/imm32/exit +1568 cd/syscall 0x80/imm8 +1569 # never gets here +1570 +1571 test-function-header-with-arg: +1572 # . prologue +1573 55/push-ebp +1574 89/<- %ebp 4/r32/esp +1575 # setup +1576 (clear-stream _test-input-stream) +1577 (write _test-input-stream "foo n : int {\n") +1578 # var result/ecx: function +1579 2b/subtract-> *Function-size 4/r32/esp +1580 89/<- %ecx 4/r32/esp +1581 (zero-out %ecx *Function-size) +1582 # var vars/ebx: (stack (addr var) 16) +1583 81 5/subop/subtract %esp 0x10/imm32 +1584 68/push 0x10/imm32/length +1585 68/push 0/imm32/top +1586 89/<- %ebx 4/r32/esp +1587 # convert +1588 (populate-mu-function-header _test-input-stream %ecx %ebx) +1589 # check result +1590 (check-strings-equal *ecx "foo" "F - test-function-header-with-arg/name") # Function-name +1591 # edx: (handle list var) = result->inouts +1592 8b/-> *(ecx+8) 2/r32/edx # Function-inouts +1593 # ebx: (handle var) = result->inouts->value +1594 8b/-> *edx 3/r32/ebx # List-value +1595 (check-strings-equal *ebx "n" "F - test-function-header-with-arg/inout:0") # Var-name +1596 8b/-> *(ebx+4) 3/r32/ebx # Var-type +1597 (check-ints-equal *ebx 1 "F - test-function-header-with-arg/inout:0/type:0") # Tree-left +1598 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-arg/inout:0/type:1") # Tree-right +1599 # . epilogue +1600 89/<- %esp 5/r32/ebp +1601 5d/pop-to-ebp +1602 c3/return +1603 +1604 test-function-header-with-multiple-args: +1605 # . prologue +1606 55/push-ebp +1607 89/<- %ebp 4/r32/esp +1608 # setup +1609 (clear-stream _test-input-stream) +1610 (write _test-input-stream "foo a: int, b: int c: int {\n") +1611 # result/ecx: (handle function) +1612 2b/subtract-> *Function-size 4/r32/esp +1613 89/<- %ecx 4/r32/esp +1614 (zero-out %ecx *Function-size) +1615 # var vars/ebx: (stack (addr var) 16) +1616 81 5/subop/subtract %esp 0x10/imm32 +1617 68/push 0x10/imm32/length +1618 68/push 0/imm32/top +1619 89/<- %ebx 4/r32/esp +1620 # convert +1621 (populate-mu-function-header _test-input-stream %ecx %ebx) +1622 # check result +1623 (check-strings-equal *ecx "foo") # Function-name +1624 # edx: (handle list var) = result->inouts +1625 8b/-> *(ecx+8) 2/r32/edx # Function-inouts +1626 $test-function-header-with-multiple-args:inout0: +1627 # ebx: (handle var) = result->inouts->value +1628 8b/-> *edx 3/r32/ebx # List-value +1629 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name +1630 8b/-> *(ebx+4) 3/r32/ebx # Var-type +1631 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:0/type:0") # Tree-left +1632 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:0/type:1") # Tree-right +1633 # edx = result->inouts->next +1634 8b/-> *(edx+4) 2/r32/edx # List-next +1635 $test-function-header-with-multiple-args:inout1: +1636 # ebx = result->inouts->next->value +1637 8b/-> *edx 3/r32/ebx # List-value +1638 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args/inout:1") # Var-name +1639 8b/-> *(ebx+4) 3/r32/ebx # Var-type +1640 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:1/type:0") # Tree-left +1641 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:1/type:1") # Tree-right +1642 # edx = result->inouts->next->next +1643 8b/-> *(edx+4) 2/r32/edx # List-next +1644 $test-function-header-with-multiple-args:inout2: +1645 # ebx = result->inouts->next->next->value +1646 8b/-> *edx 3/r32/ebx # List-value +1647 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args/inout:2") # Var-name +1648 8b/-> *(ebx+4) 3/r32/ebx # Var-type +1649 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:2/type:0") # Tree-left +1650 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:2/type:1") # Tree-right +1651 # . epilogue +1652 89/<- %esp 5/r32/ebp +1653 5d/pop-to-ebp +1654 c3/return +1655 +1656 test-function-with-multiple-args-and-outputs: +1657 # . prologue +1658 55/push-ebp +1659 89/<- %ebp 4/r32/esp +1660 # setup +1661 (clear-stream _test-input-stream) +1662 (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx: int {\n") +1663 # result/ecx: (handle function) +1664 2b/subtract-> *Function-size 4/r32/esp +1665 89/<- %ecx 4/r32/esp +1666 (zero-out %ecx *Function-size) +1667 # var vars/ebx: (stack (addr var) 16) +1668 81 5/subop/subtract %esp 0x10/imm32 +1669 68/push 0x10/imm32/length +1670 68/push 0/imm32/top +1671 89/<- %ebx 4/r32/esp +1672 # convert +1673 (populate-mu-function-header _test-input-stream %ecx %ebx) +1674 # check result +1675 (check-strings-equal *ecx "foo") # Function-name +1676 # edx: (handle list var) = result->inouts +1677 8b/-> *(ecx+8) 2/r32/edx # Function-inouts +1678 # ebx: (handle var) = result->inouts->value +1679 8b/-> *edx 3/r32/ebx # List-value +1680 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0") # Var-name +1681 8b/-> *(ebx+4) 3/r32/ebx # Var-type +1682 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0") # Tree-left +1683 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1") # Tree-right +1684 # edx = result->inouts->next +1685 8b/-> *(edx+4) 2/r32/edx # List-next +1686 # ebx = result->inouts->next->value +1687 8b/-> *edx 3/r32/ebx # List-value +1688 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1") # Var-name +1689 8b/-> *(ebx+4) 3/r32/ebx # Var-type +1690 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0") # Tree-left +1691 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1") # Tree-right +1692 # edx = result->inouts->next->next +1693 8b/-> *(edx+4) 2/r32/edx # List-next +1694 # ebx = result->inouts->next->next->value +1695 8b/-> *edx 3/r32/ebx # List-value +1696 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2") # Var-name +1697 8b/-> *(ebx+4) 3/r32/ebx # Var-type +1698 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0") # Tree-left +1699 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1") # Tree-right +1700 # edx: (handle list var) = result->outputs +1701 8b/-> *(ecx+0xc) 2/r32/edx # Function-outputs +1702 # ebx: (handle var) = result->outputs->value +1703 8b/-> *edx 3/r32/ebx # List-value +1704 (check-strings-equal *ebx "x" "F - test-function-header-with-multiple-args-and-outputs/output:0") # Var-name +1705 (check-strings-equal *(ebx+0x10) "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register +1706 8b/-> *(ebx+4) 3/r32/ebx # Var-type +1707 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-left +1708 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-right +1709 # edx = result->outputs->next +1710 8b/-> *(edx+4) 2/r32/edx # List-next +1711 # ebx = result->outputs->next->value +1712 8b/-> *edx 3/r32/ebx # List-value +1713 (check-strings-equal *ebx "y" "F - test-function-header-with-multiple-args-and-outputs/output:1") # Var-name +1714 (check-strings-equal *(ebx+0x10) "edx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register +1715 8b/-> *(ebx+4) 3/r32/ebx # Var-type +1716 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-left +1717 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-right +1718 # . epilogue +1719 89/<- %esp 5/r32/ebp +1720 5d/pop-to-ebp +1721 c3/return +1722 +1723 # format for variables with types +1724 # x: int +1725 # x: int +1726 # x: int, +1727 # ignores at most one trailing colon or comma +1728 parse-var-with-type: # name: (addr slice), first-line: (addr stream byte) -> result/eax: (handle var) +1729 # pseudocode: +1730 # var v: (handle var) = allocate(Heap, Var-size) +1731 # var s: slice +1732 # next-token-from-slice(name->start, name->end, '/', s) +1733 # var end: (addr byte) = s->end +1734 # if (slice-ends-with(s, ":")) +1735 # decrement s->end +1736 # if (slice-ends-with(s, ",")) +1737 # decrement s->end +1738 # v->name = slice-to-string(s) +1739 # ## register +1740 # next-token-from-slice(end, name->end, '/', s) +1741 # if (slice-ends-with(s, ":")) +1742 # decrement s->end +1743 # if (slice-ends-with(s, ",")) +1744 # decrement s->end +1745 # if (!slice-empty?(s)) +1746 # v->register = slice-to-string(s) +1747 # ## type +1748 # var type: (handle tree type-id) = parse-type(first-line) +1749 # v->type = type +1750 # return v +1751 # +1752 # . prologue +1753 55/push-ebp +1754 89/<- %ebp 4/r32/esp +1755 # . save registers +1756 51/push-ecx +1757 52/push-edx +1758 53/push-ebx +1759 56/push-esi +1760 57/push-edi +1761 # var result/edi: (handle var) = allocate(Heap, Var-size) +1762 (allocate Heap *Var-size) # => eax +1763 (zero-out %eax *Var-size) +1764 89/<- %edi 0/r32/eax +1765 # esi = name +1766 8b/-> *(ebp+8) 6/r32/esi +1767 # var s/ecx: slice +1768 68/push 0/imm32/end +1769 68/push 0/imm32/start +1770 89/<- %ecx 4/r32/esp +1771 $parse-var-with-type:save-name: +1772 # save v->name +1773 (next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/' +1774 # . end/edx = s->end +1775 8b/-> *(ecx+4) 2/r32/edx +1776 # . if s ends with ':', decrement s->end +1777 { +1778 8b/-> *(ecx+4) 0/r32/eax +1779 48/decrement-eax +1780 8a/copy-byte *eax 3/r32/BL +1781 81 4/subop/and %ebx 0xff/imm32 +1782 81 7/subop/compare %ebx 0x3a/imm32/colon +1783 75/jump-if-!= break/disp8 +1784 89/<- *(ecx+4) 0/r32/eax +1785 } +1786 # . if s ends with ',', decrement s->end +1787 { +1788 8b/-> *(ecx+4) 0/r32/eax +1789 48/decrement-eax +1790 8a/copy-byte *eax 3/r32/BL +1791 81 4/subop/and %ebx 0xff/imm32 +1792 81 7/subop/compare %ebx 0x2c/imm32/comma +1793 75/jump-if-!= break/disp8 +1794 89/<- *(ecx+4) 0/r32/eax +1795 } +1796 $parse-var-with-type:write-name: +1797 (slice-to-string Heap %ecx) # => eax +1798 89/<- *edi 0/r32/eax # Var-name +1799 # save v->register +1800 $parse-var-with-type:save-register: +1801 (next-token-from-slice %edx *(esi+4) 0x2f %ecx) # end, name->end, '/' +1802 # . if s ends with ':', decrement s->end +1803 { +1804 8b/-> *(ecx+4) 0/r32/eax +1805 48/decrement-eax +1806 8a/copy-byte *eax 3/r32/BL +1807 81 4/subop/and %ebx 0xff/imm32 +1808 81 7/subop/compare %ebx 0x3a/imm32/colon +1809 75/jump-if-!= break/disp8 +1810 89/<- *(ecx+4) 0/r32/eax +1811 } +1812 # . if s ends with ',', decrement s->end +1813 { +1814 8b/-> *(ecx+4) 0/r32/eax +1815 48/decrement-eax +1816 8a/copy-byte *eax 3/r32/BL +1817 81 4/subop/and %ebx 0xff/imm32 +1818 81 7/subop/compare %ebx 0x2c/imm32/comma +1819 75/jump-if-!= break/disp8 +1820 89/<- *(ecx+4) 0/r32/eax +1821 } +1822 # if (!slice-empty?(s)) v->register = slice-to-string(s) +1823 { +1824 $parse-var-with-type:write-register: +1825 # HACK: s->end can be less than s->start with all the decrements above +1826 # That's probably a sign we have the wrong algorithm for this function. +1827 8b/-> *ecx 0/r32/eax +1828 39/compare *(ecx+4) 0/r32/eax # Slice-end +1829 76/jump-if-<= break/disp8 +1830 (slice-to-string Heap %ecx) +1831 89/<- *(edi+0x10) 0/r32/eax # Var-register +1832 } +1833 $parse-var-with-type:save-type: +1834 (parse-type Heap *(ebp+0xc)) # => eax +1835 89/<- *(edi+4) 0/r32/eax # Var-type +1836 $parse-var-with-type:end: +1837 # return result +1838 89/<- %eax 7/r32/edi +1839 # . reclaim locals +1840 81 0/subop/add %esp 8/imm32 +1841 # . restore registers +1842 5f/pop-to-edi +1843 5e/pop-to-esi +1844 5b/pop-to-ebx +1845 5a/pop-to-edx +1846 59/pop-to-ecx +1847 # . epilogue +1848 89/<- %esp 5/r32/ebp +1849 5d/pop-to-ebp +1850 c3/return +1851 +1852 $parse-var-with-type:abort: +1853 # error("function header not in form 'fn <name> {'") +1854 (write-buffered Stderr "var should have form 'name: type' in '") +1855 (flush Stderr) +1856 (rewind-stream *(ebp+0xc)) +1857 (write-stream 2 *(ebp+0xc)) +1858 (write-buffered Stderr "'\n") +1859 (flush Stderr) +1860 # . syscall(exit, 1) +1861 bb/copy-to-ebx 1/imm32 +1862 b8/copy-to-eax 1/imm32/exit +1863 cd/syscall 0x80/imm8 +1864 # never gets here +1865 +1866 parse-type: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) +1867 # pseudocode: +1868 # var s: slice = next-mu-token(in) +1869 # assert s != "" +1870 # assert s != "->" +1871 # assert s != "{" +1872 # assert s != "}" +1873 # if s == ")" +1874 # return 0 +1875 # result = allocate(Tree) +1876 # zero-out(result, *Tree-size) +1877 # if s != "(" +1878 # result->left = pos-slice(Type-id, s) +1879 # return +1880 # result->left = parse-type(ad, in) +1881 # result->right = parse-type-tree(ad, in) +1882 # +1883 # . prologue +1884 55/push-ebp +1885 89/<- %ebp 4/r32/esp +1886 # . save registers +1887 51/push-ecx +1888 52/push-edx +1889 # var s/ecx: slice +1890 68/push 0/imm32 +1891 68/push 0/imm32 +1892 89/<- %ecx 4/r32/esp +1893 # s = next-mu-token(in) +1894 (next-mu-token *(ebp+0xc) %ecx) +1895 #? (write-buffered Stderr "tok: ") +1896 #? (write-slice-buffered Stderr %ecx) +1897 #? (write-buffered Stderr "$\n") +1898 #? (flush Stderr) +1899 # assert s != "" +1900 (slice-equal? %ecx "") +1901 3d/compare-eax-and 0/imm32 +1902 0f 85/jump-if-!= $parse-type:abort/disp32 +1903 # assert s != "{" +1904 (slice-equal? %ecx "{") +1905 3d/compare-eax-and 0/imm32 +1906 0f 85/jump-if-!= $parse-type:abort/disp32 +1907 # assert s != "}" +1908 (slice-equal? %ecx "}") +1909 3d/compare-eax-and 0/imm32 +1910 0f 85/jump-if-!= $parse-type:abort/disp32 +1911 # assert s != "->" +1912 (slice-equal? %ecx "->") +1913 3d/compare-eax-and 0/imm32 +1914 0f 85/jump-if-!= $parse-type:abort/disp32 +1915 # if (s == ")") return 0 +1916 (slice-equal? %ecx ")") +1917 3d/compare-eax-and 0/imm32 +1918 b8/copy-to-eax 0/imm32 +1919 0f 85/jump-if-!= $parse-type:end/disp32 +1920 # var result/edx: (handle tree type-id) +1921 (allocate *(ebp+8) *Tree-size) # => eax +1922 (zero-out %eax *Tree-size) +1923 89/<- %edx 0/r32/eax +1924 { +1925 # if (s != "(") break +1926 (slice-equal? %ecx "(") +1927 3d/compare-eax-and 0/imm32 +1928 75/jump-if-!= break/disp8 +1929 # result->left = pos-slice(Type-id, s) +1930 (pos-slice Type-id %ecx) +1931 #? (write-buffered Stderr "=> {") +1932 #? (print-int32-buffered Stderr %eax) +1933 #? (write-buffered Stderr ", 0}\n") +1934 #? (flush Stderr) +1935 89/<- *edx 0/r32/eax # Tree-left +1936 e9/jump $parse-type:return-edx/disp32 +1937 } +1938 # otherwise s == "(" +1939 # result->left = parse-type(ad, in) +1940 (parse-type *(ebp+8) *(ebp+0xc)) +1941 #? (write-buffered Stderr "=> {") +1942 #? (print-int32-buffered Stderr %eax) +1943 89/<- *edx 0/r32/eax # Tree-left +1944 # result->right = parse-type-tree(ad, in) +1945 (parse-type-tree *(ebp+8) *(ebp+0xc)) +1946 #? (write-buffered Stderr Space) +1947 #? (print-int32-buffered Stderr %eax) +1948 #? (write-buffered Stderr "}\n") +1949 #? (flush Stderr) +1950 89/<- *(edx+4) 0/r32/eax # Tree-right +1951 $parse-type:return-edx: +1952 89/<- %eax 2/r32/edx +1953 $parse-type:end: +1954 # . reclaim locals +1955 81 0/subop/add %esp 8/imm32 +1956 # . restore registers +1957 5a/pop-to-edx +1958 59/pop-to-ecx +1959 # . epilogue +1960 89/<- %esp 5/r32/ebp +1961 5d/pop-to-ebp +1962 c3/return +1963 +1964 $parse-type:abort: +1965 # error("unexpected token when parsing type: '" s "'\n") +1966 (write-buffered Stderr "unexpected token when parsing type: '") +1967 (write-slice-buffered Stderr %ecx) +1968 (write-buffered Stderr "'\n") +1969 (flush Stderr) +1970 # . syscall(exit, 1) +1971 bb/copy-to-ebx 1/imm32 +1972 b8/copy-to-eax 1/imm32/exit +1973 cd/syscall 0x80/imm8 +1974 # never gets here +1975 +1976 parse-type-tree: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) +1977 # pseudocode: +1978 # var tmp: (handle tree type-id) = parse-type(ad, in) +1979 # if tmp == 0 +1980 # return 0 +1981 # result = allocate(Tree) +1982 # zero-out(result, *Tree-size) +1983 # result->left = tmp +1984 # result->right = parse-type-tree(ad, in) +1985 # +1986 # . prologue +1987 55/push-ebp +1988 89/<- %ebp 4/r32/esp +1989 # . save registers +1990 51/push-ecx +1991 52/push-edx +1992 # var tmp/eax: (handle tree type-id) = parse-type(ad, in) +1993 (parse-type *(ebp+8) *(ebp+0xc)) +1994 # if (tmp == 0) return tmp +1995 3d/compare-eax-and 0/imm32 +1996 74/jump-if-= $parse-type-tree:end/disp8 +1997 # var tmp2/ecx = tmp +1998 89/<- %ecx 0/r32/eax +1999 # var result/edx: (handle tree type-id) +2000 (allocate *(ebp+8) *Tree-size) # => eax +2001 (zero-out %eax *Tree-size) +2002 89/<- %edx 0/r32/eax +2003 # result->left = tmp2 +2004 89/<- *edx 1/r32/ecx # Tree-left +2005 # result->right = parse-type-tree(ad, in) +2006 (parse-type-tree *(ebp+8) *(ebp+0xc)) +2007 89/<- *(edx+4) 0/r32/eax # Tree-right +2008 $parse-type-tree:return-edx: +2009 89/<- %eax 2/r32/edx +2010 $parse-type-tree:end: +2011 # . restore registers +2012 5a/pop-to-edx +2013 59/pop-to-ecx +2014 # . epilogue +2015 89/<- %esp 5/r32/ebp +2016 5d/pop-to-ebp +2017 c3/return +2018 +2019 next-mu-token: # in: (addr stream byte), out: (addr slice) +2020 # pseudocode: +2021 # start: +2022 # skip-chars-matching-whitespace(in) +2023 # if in->read >= in->write # end of in +2024 # out = {0, 0} +2025 # return +2026 # out->start = &in->data[in->read] +2027 # var curr-byte/eax: byte = in->data[in->read] +2028 # if curr->byte == ':' # comment token +2029 # ++in->read +2030 # goto start +2031 # if curr->byte == ',' # comment token +2032 # ++in->read +2033 # goto start +2034 # if curr-byte == '#' # comment +2035 # in->read = in->write # skip to end of in +2036 # goto done +2037 # if curr-byte == '"' # string literal +2038 # skip-string(in) +2039 # goto done # no metadata +2040 # if curr-byte == '(' +2041 # ++in->read +2042 # goto done +2043 # if curr-byte == ')' +2044 # ++in->read +2045 # goto done +2046 # # read a word +2047 # while true +2048 # if in->read >= in->write +2049 # break +2050 # curr-byte = in->data[in->read] +2051 # if curr-byte == ' ' +2052 # break +2053 # if curr-byte == '\r' +2054 # break +2055 # if curr-byte == '\n' +2056 # break +2057 # if curr-byte == '(' +2058 # break +2059 # if curr-byte == ')' +2060 # break +2061 # if curr-byte == ':' +2062 # break +2063 # if curr-byte == ',' +2064 # break +2065 # ++in->read +2066 # done: +2067 # out->end = &in->data[in->read] +2068 # # hack: skip a few trailing delimiters, because we don't always use +2069 # # this correct tokenizer in later tokens +2070 # while true +2071 # if in->read >= in->write +2072 # break +2073 # curr-byte = in->data[in->read] +2074 # if curr-byte == ':' +2075 # ++in->read +2076 # else if curr-byte == ',' +2077 # ++in->read +2078 # else +2079 # break +2080 # +2081 # . prologue +2082 55/push-ebp +2083 89/<- %ebp 4/r32/esp +2084 # . save registers +2085 50/push-eax +2086 51/push-ecx +2087 56/push-esi +2088 57/push-edi +2089 # esi = in +2090 8b/-> *(ebp+8) 6/r32/esi +2091 # edi = out +2092 8b/-> *(ebp+0xc) 7/r32/edi +2093 $next-mu-token:start: +2094 (skip-chars-matching-whitespace %esi) +2095 $next-mu-token:check0: +2096 # if (in->read >= in->write) return out = {0, 0} +2097 # . ecx = in->read +2098 8b/-> *(esi+4) 1/r32/ecx +2099 # . if (ecx >= in->write) return out = {0, 0} +2100 3b/compare 1/r32/ecx *esi +2101 c7 0/subop/copy *edi 0/imm32 +2102 c7 0/subop/copy *(edi+4) 0/imm32 +2103 0f 8d/jump-if->= $next-mu-token:end/disp32 +2104 # out->start = &in->data[in->read] +2105 8d/copy-address *(esi+ecx+0xc) 0/r32/eax +2106 89/<- *edi 0/r32/eax +2107 # var curr-byte/eax: byte = in->data[in->read] +2108 31/xor %eax 0/r32/eax +2109 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL +2110 { +2111 $next-mu-token:check-for-colon: +2112 # if (curr-byte != ':') break +2113 3d/compare-eax-and 0x3a/imm32/colon +2114 75/jump-if-!= break/disp8 +2115 # ++in->read +2116 ff 0/subop/increment *(esi+4) +2117 # restart +2118 e9/jump $next-mu-token:start/disp32 +2119 } +2120 { +2121 $next-mu-token:check-for-comma: +2122 # if (curr-byte != ',') break +2123 3d/compare-eax-and 0x2c/imm32/comma +2124 75/jump-if-!= break/disp8 +2125 # ++in->read +2126 ff 0/subop/increment *(esi+4) +2127 # restart +2128 e9/jump $next-mu-token:start/disp32 +2129 } +2130 { +2131 $next-mu-token:check-for-comment: +2132 # if (curr-byte != '#') break +2133 3d/compare-eax-and 0x23/imm32/pound +2134 75/jump-if-!= break/disp8 +2135 # in->read = in->write # skip rest of in +2136 8b/-> *esi 0/r32/eax +2137 89/<- *(esi+4) 0/r32/eax +2138 # return +2139 e9/jump $next-mu-token:done/disp32 +2140 } +2141 { +2142 $next-mu-token:check-for-string-literal: +2143 # if (curr-byte != '"') break +2144 3d/compare-eax-and 0x22/imm32/dquote +2145 75/jump-if-!= break/disp8 +2146 (skip-string %esi) +2147 # return +2148 e9/jump $next-mu-token:done/disp32 +2149 } +2150 { +2151 $next-mu-token:check-for-open-paren: +2152 # if (curr-byte != '(') break +2153 3d/compare-eax-and 0x28/imm32/open-paren +2154 75/jump-if-!= break/disp8 +2155 # ++in->read +2156 ff 0/subop/increment *(esi+4) +2157 # return +2158 e9/jump $next-mu-token:done/disp32 +2159 } +2160 { +2161 $next-mu-token:check-for-close-paren: +2162 # if (curr-byte != ')') break +2163 3d/compare-eax-and 0x29/imm32/close-paren +2164 75/jump-if-!= break/disp8 +2165 # ++in->read +2166 ff 0/subop/increment *(esi+4) +2167 # return +2168 e9/jump $next-mu-token:done/disp32 +2169 } +2170 { +2171 $next-mu-token:regular-word-without-metadata: +2172 # if (in->read >= in->write) break +2173 # . ecx = in->read +2174 8b/-> *(esi+4) 1/r32/ecx +2175 # . if (ecx >= in->write) break +2176 3b/compare *esi 1/r32/ecx +2177 7d/jump-if->= break/disp8 +2178 # var c/eax: byte = in->data[in->read] +2179 31/xor %eax 0/r32/eax +2180 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL +2181 # if (c == ' ') break +2182 3d/compare-eax-and 0x20/imm32/space +2183 74/jump-if-= break/disp8 +2184 # if (c == '\r') break +2185 3d/compare-eax-and 0xd/imm32/carriage-return +2186 74/jump-if-= break/disp8 +2187 # if (c == '\n') break +2188 3d/compare-eax-and 0xa/imm32/newline +2189 74/jump-if-= break/disp8 +2190 # if (c == '(') break +2191 3d/compare-eax-and 0x28/imm32/open-paren +2192 0f 84/jump-if-= break/disp32 +2193 # if (c == ')') break +2194 3d/compare-eax-and 0x29/imm32/close-paren +2195 0f 84/jump-if-= break/disp32 +2196 # if (c == ':') break +2197 3d/compare-eax-and 0x3a/imm32/colon +2198 0f 84/jump-if-= break/disp32 +2199 # if (c == ',') break +2200 3d/compare-eax-and 0x2c/imm32/comma +2201 0f 84/jump-if-= break/disp32 +2202 # ++in->read +2203 ff 0/subop/increment *(esi+4) +2204 # +2205 e9/jump loop/disp32 +2206 } +2207 $next-mu-token:done: +2208 # out->end = &in->data[in->read] +2209 8b/-> *(esi+4) 1/r32/ecx +2210 8d/copy-address *(esi+ecx+0xc) 0/r32/eax +2211 89/<- *(edi+4) 0/r32/eax +2212 { +2213 $next-mu-token:skip-trailing-delimiters: +2214 # if (in->read >= in->write) break +2215 # . ecx = in->read +2216 8b/-> *(esi+4) 1/r32/ecx +2217 # . if (ecx >= in->write) break +2218 3b/compare *esi 1/r32/ecx +2219 7d/jump-if->= break/disp8 +2220 # var c/eax: byte = in->data[in->read] +2221 31/xor %eax 0/r32/eax +2222 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL +2223 # if (c == ':') ++in->read and loop +2224 { +2225 3d/compare-eax-and 0x3a/imm32/colon +2226 75/jump-if-!= break/disp8 +2227 # ++in->read +2228 ff 0/subop/increment *(esi+4) +2229 # +2230 eb/jump $next-mu-token:skip-trailing-delimiters/disp8 +2231 } +2232 # if (c == ',') ++in->read and loop +2233 { +2234 3d/compare-eax-and 0x2c/imm32/comma +2235 75/jump-if-!= break/disp8 +2236 # ++in->read +2237 ff 0/subop/increment *(esi+4) +2238 # +2239 eb/jump $next-mu-token:skip-trailing-delimiters/disp8 +2240 } +2241 # else break +2242 } +2243 $next-mu-token:end: +2244 # . restore registers +2245 5f/pop-to-edi +2246 5e/pop-to-esi +2247 59/pop-to-ecx +2248 58/pop-to-eax +2249 # . epilogue +2250 89/<- %esp 5/r32/ebp +2251 5d/pop-to-ebp +2252 c3/return +2253 +2254 # return the index in an array of strings matching 's' +2255 # index is denominated in elements, not bytes +2256 pos-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int +2257 # . prologue +2258 55/push-ebp +2259 89/<- %ebp 4/r32/esp +2260 # . save registers +2261 51/push-ecx +2262 52/push-edx +2263 53/push-ebx +2264 56/push-esi +2265 #? (write-buffered Stderr "pos-slice: ") +2266 #? (write-slice-buffered Stderr *(ebp+0xc)) +2267 #? (write-buffered Stderr "\n") +2268 #? (flush Stderr) +2269 # esi = arr +2270 8b/-> *(ebp+8) 6/r32/esi +2271 # var index/ecx: int = 0 +2272 b9/copy-to-ecx 0/imm32 +2273 # var curr/edx: (addr (addr array byte)) = arr->data +2274 8d/copy-address *(esi+0xc) 2/r32/edx +2275 # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write] +2276 8b/-> *esi 3/r32/ebx +2277 8d/copy-address *(esi+ebx+0xc) 3/r32/ebx +2278 { +2279 #? (write-buffered Stderr " ") +2280 #? (print-int32-buffered Stderr %ecx) +2281 #? (write-buffered Stderr "\n") +2282 #? (flush Stderr) +2283 # if (curr >= max) return -1 +2284 39/compare %edx 3/r32/ebx +2285 b8/copy-to-eax -1/imm32 +2286 73/jump-if-addr>= $pos-slice:end/disp8 +2287 # if (slice-equal?(s, *curr)) break +2288 (slice-equal? *(ebp+0xc) *edx) # => eax +2289 3d/compare-eax-and 0/imm32 +2290 75/jump-if-!= break/disp8 +2291 # ++index +2292 41/increment-ecx +2293 # curr += 4 +2294 81 0/subop/add %edx 4/imm32 +2295 # +2296 eb/jump loop/disp8 +2297 } +2298 # return index +2299 89/<- %eax 1/r32/ecx +2300 $pos-slice:end: +2301 #? (write-buffered Stderr "=> ") +2302 #? (print-int32-buffered Stderr %eax) +2303 #? (write-buffered Stderr "\n") +2304 # . restore registers +2305 5e/pop-to-esi +2306 5b/pop-to-ebx +2307 5a/pop-to-edx +2308 59/pop-to-ecx +2309 # . epilogue +2310 89/<- %esp 5/r32/ebp +2311 5d/pop-to-ebp +2312 c3/return +2313 +2314 == data +2315 +2316 Type-id: # (stream (address array byte)) +2317 0x18/imm32/write +2318 0/imm32/read +2319 0x100/imm32/length +2320 # data +2321 "literal"/imm32 # 0 +2322 "int"/imm32 # 1 +2323 "addr"/imm32 # 2 +2324 "array"/imm32 # 3 +2325 "handle"/imm32 # 4 +2326 "bool"/imm32 # 5 +2327 0/imm32 +2328 0/imm32 +2329 # 0x20 +2330 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2331 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2332 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2333 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2334 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2335 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2336 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2337 +2338 == code +2339 +2340 test-parse-var-with-type: +2341 # . prologue +2342 55/push-ebp +2343 89/<- %ebp 4/r32/esp +2344 # (eax..ecx) = "x:" +2345 b8/copy-to-eax "x:"/imm32 +2346 8b/-> *eax 1/r32/ecx +2347 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2348 05/add-to-eax 4/imm32 +2349 # var slice/ecx: slice = {eax, ecx} +2350 51/push-ecx +2351 50/push-eax +2352 89/<- %ecx 4/r32/esp +2353 # _test-input-stream contains "int" +2354 (clear-stream _test-input-stream) +2355 (write _test-input-stream "int") +2356 # +2357 (parse-var-with-type %ecx _test-input-stream) +2358 8b/-> *eax 2/r32/edx # Var-name +2359 (check-strings-equal %edx "x" "F - test-var-with-type/name") +2360 8b/-> *(eax+4) 2/r32/edx # Var-type +2361 (check-ints-equal *edx 1 "F - test-var-with-type/type") +2362 (check-ints-equal *(edx+4) 0 "F - test-var-with-type/type") +2363 # . epilogue +2364 89/<- %esp 5/r32/ebp +2365 5d/pop-to-ebp +2366 c3/return +2367 +2368 test-parse-var-with-type-and-register: +2369 # . prologue +2370 55/push-ebp +2371 89/<- %ebp 4/r32/esp +2372 # (eax..ecx) = "x/eax" +2373 b8/copy-to-eax "x/eax"/imm32 +2374 8b/-> *eax 1/r32/ecx +2375 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2376 05/add-to-eax 4/imm32 +2377 # var slice/ecx: slice = {eax, ecx} +2378 51/push-ecx +2379 50/push-eax +2380 89/<- %ecx 4/r32/esp +2381 # _test-input-stream contains ": int" +2382 (clear-stream _test-input-stream) +2383 (write _test-input-stream ": int") +2384 # +2385 (parse-var-with-type %ecx _test-input-stream) +2386 8b/-> *eax 2/r32/edx # Var-name +2387 (check-strings-equal %edx "x" "F - test-var-with-type-and-register/name") +2388 8b/-> *(eax+0x10) 2/r32/edx # Var-register +2389 (check-strings-equal %edx "eax" "F - test-var-with-type-and-register/register") +2390 8b/-> *(eax+4) 2/r32/edx # Var-type +2391 (check-ints-equal *edx 1 "F - test-var-with-type-and-register/type") +2392 (check-ints-equal *(edx+4) 0 "F - test-var-with-type-and-register/type") +2393 # . epilogue +2394 89/<- %esp 5/r32/ebp +2395 5d/pop-to-ebp +2396 c3/return +2397 +2398 test-parse-var-with-trailing-characters: +2399 # . prologue +2400 55/push-ebp +2401 89/<- %ebp 4/r32/esp +2402 # (eax..ecx) = "x:" +2403 b8/copy-to-eax "x:"/imm32 +2404 8b/-> *eax 1/r32/ecx +2405 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2406 05/add-to-eax 4/imm32 +2407 # var slice/ecx: slice = {eax, ecx} +2408 51/push-ecx +2409 50/push-eax +2410 89/<- %ecx 4/r32/esp +2411 # _test-input-stream contains "int," +2412 (clear-stream _test-input-stream) +2413 (write _test-input-stream "int,") +2414 # +2415 (parse-var-with-type %ecx _test-input-stream) +2416 8b/-> *eax 2/r32/edx # Var-name +2417 (check-strings-equal %edx "x" "F - test-var-with-trailing-characters/name") +2418 8b/-> *(eax+0x10) 2/r32/edx # Var-register +2419 (check-ints-equal %edx 0 "F - test-var-with-trailing-characters/register") +2420 8b/-> *(eax+4) 2/r32/edx # Var-type +2421 (check-ints-equal *edx 1 "F - test-var-with-trailing-characters/type") +2422 (check-ints-equal *(edx+4) 0 "F - test-var-with-trailing-characters/type") +2423 # . epilogue +2424 89/<- %esp 5/r32/ebp +2425 5d/pop-to-ebp +2426 c3/return +2427 +2428 test-parse-var-with-register-and-trailing-characters: +2429 # . prologue +2430 55/push-ebp +2431 89/<- %ebp 4/r32/esp +2432 # (eax..ecx) = "x/eax:" +2433 b8/copy-to-eax "x/eax:"/imm32 +2434 8b/-> *eax 1/r32/ecx +2435 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2436 05/add-to-eax 4/imm32 +2437 # var slice/ecx: slice = {eax, ecx} +2438 51/push-ecx +2439 50/push-eax +2440 89/<- %ecx 4/r32/esp +2441 # _test-input-stream contains "int," +2442 (clear-stream _test-input-stream) +2443 (write _test-input-stream "int,") +2444 # +2445 (parse-var-with-type %ecx _test-input-stream) +2446 8b/-> *eax 2/r32/edx # Var-name +2447 (check-strings-equal %edx "x" "F - test-var-with-register-and-trailing-characters/name") +2448 8b/-> *(eax+0x10) 2/r32/edx # Var-register +2449 (check-strings-equal %edx "eax" "F - test-var-with-register-and-trailing-characters/register") +2450 8b/-> *(eax+4) 2/r32/edx # Var-type +2451 (check-ints-equal *edx 1 "F - test-var-with-register-and-trailing-characters/type") +2452 (check-ints-equal *(edx+4) 0 "F - test-var-with-register-and-trailing-characters/type") +2453 # . epilogue +2454 89/<- %esp 5/r32/ebp +2455 5d/pop-to-ebp +2456 c3/return +2457 +2458 test-parse-var-with-compound-type: +2459 # . prologue +2460 55/push-ebp +2461 89/<- %ebp 4/r32/esp +2462 # (eax..ecx) = "x:" +2463 b8/copy-to-eax "x:"/imm32 +2464 8b/-> *eax 1/r32/ecx +2465 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2466 05/add-to-eax 4/imm32 +2467 # var slice/ecx: slice = {eax, ecx} +2468 51/push-ecx +2469 50/push-eax +2470 89/<- %ecx 4/r32/esp +2471 # _test-input-stream contains "(addr int)" +2472 (clear-stream _test-input-stream) +2473 (write _test-input-stream "(addr int)") +2474 # +2475 (parse-var-with-type %ecx _test-input-stream) +2476 8b/-> *eax 2/r32/edx # Var-name +2477 (check-strings-equal %edx "x" "F - test-var-with-compound-type/name") +2478 8b/-> *(eax+0x10) 2/r32/edx # Var-register +2479 (check-ints-equal %edx 0 "F - test-var-with-compound-type/register") +2480 # var type/edx: (handle tree type-id) = var->type +2481 8b/-> *(eax+4) 2/r32/edx # Var-type +2482 # type->left == atom(addr) +2483 8b/-> *edx 0/r32/eax # Atom-value +2484 (check-ints-equal *eax 2 "F - test-var-with-compound-type/type:0") # Tree-left +2485 # type->right->left == atom(int) +2486 8b/-> *(edx+4) 2/r32/edx # Tree-right +2487 8b/-> *edx 0/r32/eax # Tree-left +2488 (check-ints-equal *eax 1 "F - test-var-with-compound-type/type:1") # Atom-value +2489 # type->right->right == null +2490 (check-ints-equal *(edx+4) 0 "F - test-var-with-compound-type/type:2") # Tree-right +2491 # . epilogue +2492 89/<- %esp 5/r32/ebp +2493 5d/pop-to-ebp +2494 c3/return +2495 +2496 # identifier starts with a letter or '$' or '_' +2497 # no constraints at the moment on later letters +2498 # all we really want to do so far is exclude '{', '}' and '->' +2499 is-identifier?: # in: (addr slice) -> result/eax: boolean +2500 # . prologue +2501 55/push-ebp +2502 89/<- %ebp 4/r32/esp +2503 # if (slice-empty?(in)) return false +2504 (slice-empty? *(ebp+8)) # => eax +2505 3d/compare-eax-and 0/imm32 +2506 75/jump-if-!= $is-identifier?:false/disp8 +2507 # var c/eax: byte = *in->start +2508 8b/-> *(ebp+8) 0/r32/eax +2509 8b/-> *eax 0/r32/eax +2510 8a/copy-byte *eax 0/r32/AL +2511 81 4/subop/and %eax 0xff/imm32 +2512 # if (c == '$') return true +2513 3d/compare-eax-and 0x24/imm32/$ +2514 74/jump-if-= $is-identifier?:true/disp8 +2515 # if (c == '_') return true +2516 3d/compare-eax-and 0x5f/imm32/_ +2517 74/jump-if-= $is-identifier?:true/disp8 +2518 # drop case +2519 25/and-eax-with 0x5f/imm32 +2520 # if (c < 'A') return false +2521 3d/compare-eax-and 0x41/imm32/A +2522 7c/jump-if-< $is-identifier?:false/disp8 +2523 # if (c > 'Z') return false +2524 3d/compare-eax-and 0x5a/imm32/Z +2525 7f/jump-if-> $is-identifier?:false/disp8 +2526 # otherwise return true +2527 $is-identifier?:true: +2528 b8/copy-to-eax 1/imm32/true +2529 eb/jump $is-identifier?:end/disp8 +2530 $is-identifier?:false: +2531 b8/copy-to-eax 0/imm32/false +2532 $is-identifier?:end: +2533 # . epilogue +2534 89/<- %esp 5/r32/ebp +2535 5d/pop-to-ebp +2536 c3/return +2537 +2538 test-is-identifier-dollar: +2539 # . prologue +2540 55/push-ebp +2541 89/<- %ebp 4/r32/esp +2542 # (eax..ecx) = "$a" +2543 b8/copy-to-eax "$a"/imm32 +2544 8b/-> *eax 1/r32/ecx +2545 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2546 05/add-to-eax 4/imm32 +2547 # var slice/ecx: slice = {eax, ecx} +2548 51/push-ecx +2549 50/push-eax +2550 89/<- %ecx 4/r32/esp +2551 # +2552 (is-identifier? %ecx) +2553 (check-ints-equal %eax 1 "F - test-is-identifier-dollar") +2554 # . epilogue +2555 89/<- %esp 5/r32/ebp +2556 5d/pop-to-ebp +2557 c3/return +2558 +2559 test-is-identifier-underscore: +2560 # . prologue +2561 55/push-ebp +2562 89/<- %ebp 4/r32/esp +2563 # (eax..ecx) = "_a" +2564 b8/copy-to-eax "_a"/imm32 +2565 8b/-> *eax 1/r32/ecx +2566 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2567 05/add-to-eax 4/imm32 +2568 # var slice/ecx: slice = {eax, ecx} +2569 51/push-ecx +2570 50/push-eax +2571 89/<- %ecx 4/r32/esp +2572 # +2573 (is-identifier? %ecx) +2574 (check-ints-equal %eax 1 "F - test-is-identifier-underscore") +2575 # . epilogue +2576 89/<- %esp 5/r32/ebp +2577 5d/pop-to-ebp +2578 c3/return +2579 +2580 test-is-identifier-a: +2581 # . prologue +2582 55/push-ebp +2583 89/<- %ebp 4/r32/esp +2584 # (eax..ecx) = "a$" +2585 b8/copy-to-eax "a$"/imm32 +2586 8b/-> *eax 1/r32/ecx +2587 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2588 05/add-to-eax 4/imm32 +2589 # var slice/ecx: slice = {eax, ecx} +2590 51/push-ecx +2591 50/push-eax +2592 89/<- %ecx 4/r32/esp +2593 # +2594 (is-identifier? %ecx) +2595 (check-ints-equal %eax 1 "F - test-is-identifier-a") +2596 # . epilogue +2597 89/<- %esp 5/r32/ebp +2598 5d/pop-to-ebp +2599 c3/return +2600 +2601 test-is-identifier-z: +2602 # . prologue +2603 55/push-ebp +2604 89/<- %ebp 4/r32/esp +2605 # (eax..ecx) = "z$" +2606 b8/copy-to-eax "z$"/imm32 +2607 8b/-> *eax 1/r32/ecx +2608 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2609 05/add-to-eax 4/imm32 +2610 # var slice/ecx: slice = {eax, ecx} +2611 51/push-ecx +2612 50/push-eax +2613 89/<- %ecx 4/r32/esp +2614 # +2615 (is-identifier? %ecx) +2616 (check-ints-equal %eax 1 "F - test-is-identifier-z") +2617 # . epilogue +2618 89/<- %esp 5/r32/ebp +2619 5d/pop-to-ebp +2620 c3/return +2621 +2622 test-is-identifier-A: +2623 # . prologue +2624 55/push-ebp +2625 89/<- %ebp 4/r32/esp +2626 # (eax..ecx) = "A$" +2627 b8/copy-to-eax "A$"/imm32 +2628 8b/-> *eax 1/r32/ecx +2629 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2630 05/add-to-eax 4/imm32 +2631 # var slice/ecx: slice = {eax, ecx} +2632 51/push-ecx +2633 50/push-eax +2634 89/<- %ecx 4/r32/esp +2635 # +2636 (is-identifier? %ecx) +2637 (check-ints-equal %eax 1 "F - test-is-identifier-A") +2638 # . epilogue +2639 89/<- %esp 5/r32/ebp +2640 5d/pop-to-ebp +2641 c3/return +2642 +2643 test-is-identifier-Z: +2644 # . prologue +2645 55/push-ebp +2646 89/<- %ebp 4/r32/esp +2647 # (eax..ecx) = "Z$" +2648 b8/copy-to-eax "Z$"/imm32 +2649 8b/-> *eax 1/r32/ecx +2650 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2651 05/add-to-eax 4/imm32 +2652 # var slice/ecx: slice = {eax, ecx} +2653 51/push-ecx +2654 50/push-eax +2655 89/<- %ecx 4/r32/esp +2656 # +2657 (is-identifier? %ecx) +2658 (check-ints-equal %eax 1 "F - test-is-identifier-Z") +2659 # . epilogue +2660 89/<- %esp 5/r32/ebp +2661 5d/pop-to-ebp +2662 c3/return +2663 +2664 test-is-identifier-@: +2665 # character before 'A' is invalid +2666 # . prologue +2667 55/push-ebp +2668 89/<- %ebp 4/r32/esp +2669 # (eax..ecx) = "@a" +2670 b8/copy-to-eax "@a"/imm32 +2671 8b/-> *eax 1/r32/ecx +2672 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2673 05/add-to-eax 4/imm32 +2674 # var slice/ecx: slice = {eax, ecx} +2675 51/push-ecx +2676 50/push-eax +2677 89/<- %ecx 4/r32/esp +2678 # +2679 (is-identifier? %ecx) +2680 (check-ints-equal %eax 0 "F - test-is-identifier-@") +2681 # . epilogue +2682 89/<- %esp 5/r32/ebp +2683 5d/pop-to-ebp +2684 c3/return +2685 +2686 test-is-identifier-square-bracket: +2687 # character after 'Z' is invalid +2688 # . prologue +2689 55/push-ebp +2690 89/<- %ebp 4/r32/esp +2691 # (eax..ecx) = "[a" +2692 b8/copy-to-eax "[a"/imm32 +2693 8b/-> *eax 1/r32/ecx +2694 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2695 05/add-to-eax 4/imm32 +2696 # var slice/ecx: slice = {eax, ecx} +2697 51/push-ecx +2698 50/push-eax +2699 89/<- %ecx 4/r32/esp 2700 # -2701 (parse-var-with-type %ecx _test-input-stream) -2702 8b/-> *eax 2/r32/edx # Var-name -2703 (check-strings-equal %edx "x" "F - test-var-with-type-and-register/name") -2704 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2705 (check-strings-equal %edx "eax" "F - test-var-with-type-and-register/register") -2706 8b/-> *(eax+4) 2/r32/edx # Var-type -2707 (check-ints-equal *edx 1 "F - test-var-with-type-and-register/type") -2708 (check-ints-equal *(edx+4) 0 "F - test-var-with-type-and-register/type") -2709 # . epilogue -2710 89/<- %esp 5/r32/ebp -2711 5d/pop-to-ebp -2712 c3/return -2713 -2714 test-parse-var-with-trailing-characters: -2715 # . prologue -2716 55/push-ebp -2717 89/<- %ebp 4/r32/esp -2718 # (eax..ecx) = "x:" -2719 b8/copy-to-eax "x:"/imm32 -2720 8b/-> *eax 1/r32/ecx -2721 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2722 05/add-to-eax 4/imm32 -2723 # var slice/ecx: slice = {eax, ecx} -2724 51/push-ecx -2725 50/push-eax -2726 89/<- %ecx 4/r32/esp -2727 # _test-input-stream contains "int," -2728 (clear-stream _test-input-stream) -2729 (write _test-input-stream "int,") -2730 # -2731 (parse-var-with-type %ecx _test-input-stream) -2732 8b/-> *eax 2/r32/edx # Var-name -2733 (check-strings-equal %edx "x" "F - test-var-with-trailing-characters/name") -2734 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2735 (check-ints-equal %edx 0 "F - test-var-with-trailing-characters/register") -2736 8b/-> *(eax+4) 2/r32/edx # Var-type -2737 (check-ints-equal *edx 1 "F - test-var-with-trailing-characters/type") -2738 (check-ints-equal *(edx+4) 0 "F - test-var-with-trailing-characters/type") -2739 # . epilogue -2740 89/<- %esp 5/r32/ebp -2741 5d/pop-to-ebp -2742 c3/return -2743 -2744 test-parse-var-with-register-and-trailing-characters: -2745 # . prologue -2746 55/push-ebp -2747 89/<- %ebp 4/r32/esp -2748 # (eax..ecx) = "x/eax:" -2749 b8/copy-to-eax "x/eax:"/imm32 -2750 8b/-> *eax 1/r32/ecx -2751 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2752 05/add-to-eax 4/imm32 -2753 # var slice/ecx: slice = {eax, ecx} -2754 51/push-ecx -2755 50/push-eax -2756 89/<- %ecx 4/r32/esp -2757 # _test-input-stream contains "int," -2758 (clear-stream _test-input-stream) -2759 (write _test-input-stream "int,") -2760 # -2761 (parse-var-with-type %ecx _test-input-stream) -2762 8b/-> *eax 2/r32/edx # Var-name -2763 (check-strings-equal %edx "x" "F - test-var-with-register-and-trailing-characters/name") -2764 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2765 (check-strings-equal %edx "eax" "F - test-var-with-register-and-trailing-characters/register") -2766 8b/-> *(eax+4) 2/r32/edx # Var-type -2767 (check-ints-equal *edx 1 "F - test-var-with-register-and-trailing-characters/type") -2768 (check-ints-equal *(edx+4) 0 "F - test-var-with-register-and-trailing-characters/type") -2769 # . epilogue -2770 89/<- %esp 5/r32/ebp -2771 5d/pop-to-ebp -2772 c3/return -2773 -2774 test-parse-var-with-compound-type: +2701 (is-identifier? %ecx) +2702 (check-ints-equal %eax 0 "F - test-is-identifier-@") +2703 # . epilogue +2704 89/<- %esp 5/r32/ebp +2705 5d/pop-to-ebp +2706 c3/return +2707 +2708 test-is-identifier-backtick: +2709 # character before 'a' is invalid +2710 # . prologue +2711 55/push-ebp +2712 89/<- %ebp 4/r32/esp +2713 # (eax..ecx) = "`a" +2714 b8/copy-to-eax "`a"/imm32 +2715 8b/-> *eax 1/r32/ecx +2716 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2717 05/add-to-eax 4/imm32 +2718 # var slice/ecx: slice = {eax, ecx} +2719 51/push-ecx +2720 50/push-eax +2721 89/<- %ecx 4/r32/esp +2722 # +2723 (is-identifier? %ecx) +2724 (check-ints-equal %eax 0 "F - test-is-identifier-backtick") +2725 # . epilogue +2726 89/<- %esp 5/r32/ebp +2727 5d/pop-to-ebp +2728 c3/return +2729 +2730 test-is-identifier-curly-brace-open: +2731 # character after 'z' is invalid; also used for blocks +2732 # . prologue +2733 55/push-ebp +2734 89/<- %ebp 4/r32/esp +2735 # (eax..ecx) = "{a" +2736 b8/copy-to-eax "{a"/imm32 +2737 8b/-> *eax 1/r32/ecx +2738 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2739 05/add-to-eax 4/imm32 +2740 # var slice/ecx: slice = {eax, ecx} +2741 51/push-ecx +2742 50/push-eax +2743 89/<- %ecx 4/r32/esp +2744 # +2745 (is-identifier? %ecx) +2746 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open") +2747 # . epilogue +2748 89/<- %esp 5/r32/ebp +2749 5d/pop-to-ebp +2750 c3/return +2751 +2752 test-is-identifier-curly-brace-close: +2753 # . prologue +2754 55/push-ebp +2755 89/<- %ebp 4/r32/esp +2756 # (eax..ecx) = "}a" +2757 b8/copy-to-eax "}a"/imm32 +2758 8b/-> *eax 1/r32/ecx +2759 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2760 05/add-to-eax 4/imm32 +2761 # var slice/ecx: slice = {eax, ecx} +2762 51/push-ecx +2763 50/push-eax +2764 89/<- %ecx 4/r32/esp +2765 # +2766 (is-identifier? %ecx) +2767 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close") +2768 # . epilogue +2769 89/<- %esp 5/r32/ebp +2770 5d/pop-to-ebp +2771 c3/return +2772 +2773 test-is-identifier-hyphen: +2774 # disallow leading '-' since '->' has special meaning 2775 # . prologue 2776 55/push-ebp 2777 89/<- %ebp 4/r32/esp -2778 # (eax..ecx) = "x:" -2779 b8/copy-to-eax "x:"/imm32 +2778 # (eax..ecx) = "-a" +2779 b8/copy-to-eax "-a"/imm32 2780 8b/-> *eax 1/r32/ecx 2781 8d/copy-address *(eax+ecx+4) 1/r32/ecx 2782 05/add-to-eax 4/imm32 @@ -2756,4051 +2751,4036 @@ if ('onhashchange' in window) { 2784 51/push-ecx 2785 50/push-eax 2786 89/<- %ecx 4/r32/esp -2787 # _test-input-stream contains "(addr int)" -2788 (clear-stream _test-input-stream) -2789 (write _test-input-stream "(addr int)") -2790 # -2791 (parse-var-with-type %ecx _test-input-stream) -2792 8b/-> *eax 2/r32/edx # Var-name -2793 (check-strings-equal %edx "x" "F - test-var-with-compound-type/name") -2794 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2795 (check-ints-equal %edx 0 "F - test-var-with-compound-type/register") -2796 # var type/edx: (handle tree type-id) = var->type -2797 8b/-> *(eax+4) 2/r32/edx # Var-type -2798 # type->left == atom(addr) -2799 8b/-> *edx 0/r32/eax # Atom-value -2800 (check-ints-equal *eax 2 "F - test-var-with-compound-type/type:0") # Tree-left -2801 # type->right->left == atom(int) -2802 8b/-> *(edx+4) 2/r32/edx # Tree-right -2803 8b/-> *edx 0/r32/eax # Tree-left -2804 (check-ints-equal *eax 1 "F - test-var-with-compound-type/type:1") # Atom-value -2805 # type->right->right == null -2806 (check-ints-equal *(edx+4) 0 "F - test-var-with-compound-type/type:2") # Tree-right -2807 # . epilogue -2808 89/<- %esp 5/r32/ebp -2809 5d/pop-to-ebp -2810 c3/return -2811 -2812 # identifier starts with a letter or '$' or '_' -2813 # no constraints at the moment on later letters -2814 # all we really want to do so far is exclude '{', '}' and '->' -2815 is-identifier?: # in: (addr slice) -> result/eax: boolean -2816 # . prologue -2817 55/push-ebp -2818 89/<- %ebp 4/r32/esp -2819 # if (slice-empty?(in)) return false -2820 (slice-empty? *(ebp+8)) # => eax -2821 3d/compare-eax-and 0/imm32 -2822 75/jump-if-!= $is-identifier?:false/disp8 -2823 # var c/eax: byte = *in->start -2824 8b/-> *(ebp+8) 0/r32/eax -2825 8b/-> *eax 0/r32/eax -2826 8a/copy-byte *eax 0/r32/AL -2827 81 4/subop/and %eax 0xff/imm32 -2828 # if (c == '$') return true -2829 3d/compare-eax-and 0x24/imm32/$ -2830 74/jump-if-= $is-identifier?:true/disp8 -2831 # if (c == '_') return true -2832 3d/compare-eax-and 0x5f/imm32/_ -2833 74/jump-if-= $is-identifier?:true/disp8 -2834 # drop case -2835 25/and-eax-with 0x5f/imm32 -2836 # if (c < 'A') return false -2837 3d/compare-eax-and 0x41/imm32/A -2838 7c/jump-if-< $is-identifier?:false/disp8 -2839 # if (c > 'Z') return false -2840 3d/compare-eax-and 0x5a/imm32/Z -2841 7f/jump-if-> $is-identifier?:false/disp8 -2842 # otherwise return true -2843 $is-identifier?:true: -2844 b8/copy-to-eax 1/imm32/true -2845 eb/jump $is-identifier?:end/disp8 -2846 $is-identifier?:false: -2847 b8/copy-to-eax 0/imm32/false -2848 $is-identifier?:end: -2849 # . epilogue -2850 89/<- %esp 5/r32/ebp -2851 5d/pop-to-ebp -2852 c3/return -2853 -2854 test-is-identifier-dollar: -2855 # . prologue -2856 55/push-ebp -2857 89/<- %ebp 4/r32/esp -2858 # (eax..ecx) = "$a" -2859 b8/copy-to-eax "$a"/imm32 -2860 8b/-> *eax 1/r32/ecx -2861 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2862 05/add-to-eax 4/imm32 -2863 # var slice/ecx: slice = {eax, ecx} -2864 51/push-ecx -2865 50/push-eax -2866 89/<- %ecx 4/r32/esp -2867 # -2868 (is-identifier? %ecx) -2869 (check-ints-equal %eax 1 "F - test-is-identifier-dollar") -2870 # . epilogue -2871 89/<- %esp 5/r32/ebp -2872 5d/pop-to-ebp -2873 c3/return -2874 -2875 test-is-identifier-underscore: -2876 # . prologue -2877 55/push-ebp -2878 89/<- %ebp 4/r32/esp -2879 # (eax..ecx) = "_a" -2880 b8/copy-to-eax "_a"/imm32 -2881 8b/-> *eax 1/r32/ecx -2882 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2883 05/add-to-eax 4/imm32 -2884 # var slice/ecx: slice = {eax, ecx} -2885 51/push-ecx -2886 50/push-eax -2887 89/<- %ecx 4/r32/esp -2888 # -2889 (is-identifier? %ecx) -2890 (check-ints-equal %eax 1 "F - test-is-identifier-underscore") -2891 # . epilogue -2892 89/<- %esp 5/r32/ebp -2893 5d/pop-to-ebp -2894 c3/return -2895 -2896 test-is-identifier-a: -2897 # . prologue -2898 55/push-ebp -2899 89/<- %ebp 4/r32/esp -2900 # (eax..ecx) = "a$" -2901 b8/copy-to-eax "a$"/imm32 -2902 8b/-> *eax 1/r32/ecx -2903 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2904 05/add-to-eax 4/imm32 -2905 # var slice/ecx: slice = {eax, ecx} -2906 51/push-ecx -2907 50/push-eax -2908 89/<- %ecx 4/r32/esp -2909 # -2910 (is-identifier? %ecx) -2911 (check-ints-equal %eax 1 "F - test-is-identifier-a") -2912 # . epilogue -2913 89/<- %esp 5/r32/ebp -2914 5d/pop-to-ebp -2915 c3/return -2916 -2917 test-is-identifier-z: -2918 # . prologue -2919 55/push-ebp -2920 89/<- %ebp 4/r32/esp -2921 # (eax..ecx) = "z$" -2922 b8/copy-to-eax "z$"/imm32 -2923 8b/-> *eax 1/r32/ecx -2924 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2925 05/add-to-eax 4/imm32 -2926 # var slice/ecx: slice = {eax, ecx} -2927 51/push-ecx -2928 50/push-eax -2929 89/<- %ecx 4/r32/esp -2930 # -2931 (is-identifier? %ecx) -2932 (check-ints-equal %eax 1 "F - test-is-identifier-z") -2933 # . epilogue -2934 89/<- %esp 5/r32/ebp -2935 5d/pop-to-ebp -2936 c3/return -2937 -2938 test-is-identifier-A: -2939 # . prologue -2940 55/push-ebp -2941 89/<- %ebp 4/r32/esp -2942 # (eax..ecx) = "A$" -2943 b8/copy-to-eax "A$"/imm32 -2944 8b/-> *eax 1/r32/ecx -2945 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2946 05/add-to-eax 4/imm32 -2947 # var slice/ecx: slice = {eax, ecx} -2948 51/push-ecx -2949 50/push-eax -2950 89/<- %ecx 4/r32/esp -2951 # -2952 (is-identifier? %ecx) -2953 (check-ints-equal %eax 1 "F - test-is-identifier-A") -2954 # . epilogue -2955 89/<- %esp 5/r32/ebp -2956 5d/pop-to-ebp -2957 c3/return -2958 -2959 test-is-identifier-Z: -2960 # . prologue -2961 55/push-ebp -2962 89/<- %ebp 4/r32/esp -2963 # (eax..ecx) = "Z$" -2964 b8/copy-to-eax "Z$"/imm32 -2965 8b/-> *eax 1/r32/ecx -2966 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2967 05/add-to-eax 4/imm32 -2968 # var slice/ecx: slice = {eax, ecx} -2969 51/push-ecx -2970 50/push-eax -2971 89/<- %ecx 4/r32/esp -2972 # -2973 (is-identifier? %ecx) -2974 (check-ints-equal %eax 1 "F - test-is-identifier-Z") -2975 # . epilogue -2976 89/<- %esp 5/r32/ebp -2977 5d/pop-to-ebp -2978 c3/return -2979 -2980 test-is-identifier-@: -2981 # character before 'A' is invalid -2982 # . prologue -2983 55/push-ebp -2984 89/<- %ebp 4/r32/esp -2985 # (eax..ecx) = "@a" -2986 b8/copy-to-eax "@a"/imm32 -2987 8b/-> *eax 1/r32/ecx -2988 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2989 05/add-to-eax 4/imm32 -2990 # var slice/ecx: slice = {eax, ecx} -2991 51/push-ecx -2992 50/push-eax -2993 89/<- %ecx 4/r32/esp -2994 # -2995 (is-identifier? %ecx) -2996 (check-ints-equal %eax 0 "F - test-is-identifier-@") -2997 # . epilogue -2998 89/<- %esp 5/r32/ebp -2999 5d/pop-to-ebp -3000 c3/return -3001 -3002 test-is-identifier-square-bracket: -3003 # character after 'Z' is invalid -3004 # . prologue -3005 55/push-ebp -3006 89/<- %ebp 4/r32/esp -3007 # (eax..ecx) = "[a" -3008 b8/copy-to-eax "[a"/imm32 -3009 8b/-> *eax 1/r32/ecx -3010 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3011 05/add-to-eax 4/imm32 -3012 # var slice/ecx: slice = {eax, ecx} -3013 51/push-ecx -3014 50/push-eax -3015 89/<- %ecx 4/r32/esp -3016 # -3017 (is-identifier? %ecx) -3018 (check-ints-equal %eax 0 "F - test-is-identifier-@") -3019 # . epilogue -3020 89/<- %esp 5/r32/ebp -3021 5d/pop-to-ebp -3022 c3/return -3023 -3024 test-is-identifier-backtick: -3025 # character before 'a' is invalid -3026 # . prologue -3027 55/push-ebp -3028 89/<- %ebp 4/r32/esp -3029 # (eax..ecx) = "`a" -3030 b8/copy-to-eax "`a"/imm32 -3031 8b/-> *eax 1/r32/ecx -3032 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3033 05/add-to-eax 4/imm32 -3034 # var slice/ecx: slice = {eax, ecx} -3035 51/push-ecx -3036 50/push-eax -3037 89/<- %ecx 4/r32/esp -3038 # -3039 (is-identifier? %ecx) -3040 (check-ints-equal %eax 0 "F - test-is-identifier-backtick") -3041 # . epilogue -3042 89/<- %esp 5/r32/ebp -3043 5d/pop-to-ebp -3044 c3/return -3045 -3046 test-is-identifier-curly-brace-open: -3047 # character after 'z' is invalid; also used for blocks -3048 # . prologue -3049 55/push-ebp -3050 89/<- %ebp 4/r32/esp -3051 # (eax..ecx) = "{a" -3052 b8/copy-to-eax "{a"/imm32 -3053 8b/-> *eax 1/r32/ecx -3054 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3055 05/add-to-eax 4/imm32 -3056 # var slice/ecx: slice = {eax, ecx} -3057 51/push-ecx -3058 50/push-eax -3059 89/<- %ecx 4/r32/esp -3060 # -3061 (is-identifier? %ecx) -3062 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open") -3063 # . epilogue -3064 89/<- %esp 5/r32/ebp -3065 5d/pop-to-ebp -3066 c3/return -3067 -3068 test-is-identifier-curly-brace-close: -3069 # . prologue -3070 55/push-ebp -3071 89/<- %ebp 4/r32/esp -3072 # (eax..ecx) = "}a" -3073 b8/copy-to-eax "}a"/imm32 -3074 8b/-> *eax 1/r32/ecx -3075 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3076 05/add-to-eax 4/imm32 -3077 # var slice/ecx: slice = {eax, ecx} -3078 51/push-ecx -3079 50/push-eax -3080 89/<- %ecx 4/r32/esp -3081 # -3082 (is-identifier? %ecx) -3083 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close") -3084 # . epilogue -3085 89/<- %esp 5/r32/ebp -3086 5d/pop-to-ebp -3087 c3/return -3088 -3089 test-is-identifier-hyphen: -3090 # disallow leading '-' since '->' has special meaning -3091 # . prologue -3092 55/push-ebp -3093 89/<- %ebp 4/r32/esp -3094 # (eax..ecx) = "-a" -3095 b8/copy-to-eax "-a"/imm32 -3096 8b/-> *eax 1/r32/ecx -3097 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3098 05/add-to-eax 4/imm32 -3099 # var slice/ecx: slice = {eax, ecx} -3100 51/push-ecx -3101 50/push-eax -3102 89/<- %ecx 4/r32/esp -3103 # -3104 (is-identifier? %ecx) -3105 (check-ints-equal %eax 0 "F - test-is-identifier-hyphen") -3106 # . epilogue -3107 89/<- %esp 5/r32/ebp -3108 5d/pop-to-ebp -3109 c3/return -3110 -3111 populate-mu-function-body: # in: (addr buffered-file), out: (handle function), vars: (addr stack (handle var)) -3112 # . prologue -3113 55/push-ebp -3114 89/<- %ebp 4/r32/esp -3115 # . save registers -3116 50/push-eax -3117 56/push-esi -3118 57/push-edi -3119 # esi = in -3120 8b/-> *(ebp+8) 6/r32/esi -3121 # edi = out -3122 8b/-> *(ebp+0xc) 7/r32/edi -3123 # initialize some global state -3124 c7 0/subop/copy *Curr-block-depth 1/imm32 -3125 c7 0/subop/copy *Next-local-stack-offset -4/imm32 -3126 # var eax: (handle block) = parse-mu-block(in, vars) -3127 (parse-mu-block %esi *(ebp+0x10) %edi) # => eax -3128 # out->body = eax -3129 89/<- *(edi+0x10) 0/r32/eax # Function-body -3130 $populate-mu-function-body:end: -3131 # . restore registers -3132 5f/pop-to-edi -3133 5e/pop-to-esi -3134 58/pop-to-eax +2787 # +2788 (is-identifier? %ecx) +2789 (check-ints-equal %eax 0 "F - test-is-identifier-hyphen") +2790 # . epilogue +2791 89/<- %esp 5/r32/ebp +2792 5d/pop-to-ebp +2793 c3/return +2794 +2795 populate-mu-function-body: # in: (addr buffered-file), out: (handle function), vars: (addr stack (handle var)) +2796 # . prologue +2797 55/push-ebp +2798 89/<- %ebp 4/r32/esp +2799 # . save registers +2800 50/push-eax +2801 56/push-esi +2802 57/push-edi +2803 # esi = in +2804 8b/-> *(ebp+8) 6/r32/esi +2805 # edi = out +2806 8b/-> *(ebp+0xc) 7/r32/edi +2807 # initialize some global state +2808 c7 0/subop/copy *Curr-block-depth 1/imm32 +2809 c7 0/subop/copy *Next-local-stack-offset -4/imm32 +2810 # var eax: (handle block) = parse-mu-block(in, vars) +2811 (parse-mu-block %esi *(ebp+0x10) %edi) # => eax +2812 # out->body = eax +2813 89/<- *(edi+0x10) 0/r32/eax # Function-body +2814 $populate-mu-function-body:end: +2815 # . restore registers +2816 5f/pop-to-edi +2817 5e/pop-to-esi +2818 58/pop-to-eax +2819 # . epilogue +2820 89/<- %esp 5/r32/ebp +2821 5d/pop-to-ebp +2822 c3/return +2823 +2824 == data +2825 +2826 # Global state when parsing a function +2827 Curr-block-depth: # (addr int) +2828 0/imm32 +2829 Next-local-stack-offset: # (addr int) +2830 -4/imm32 +2831 +2832 == code +2833 +2834 # parses a block, assuming that the leading '{' has already been read by the caller +2835 parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle block) +2836 # pseudocode: +2837 # var line: (stream byte 512) +2838 # var word-slice: slice +2839 # increment *Curr-block-depth +2840 # result/eax = allocate(Heap, Stmt-size) +2841 # result->tag = 0/Block +2842 # while true # line loop +2843 # clear-stream(line) +2844 # read-line-buffered(in, line) +2845 # if (line->write == 0) break # end of file +2846 # word-slice = next-word(line) +2847 # if slice-empty?(word-slice) # end of line +2848 # continue +2849 # else if slice-starts-with?(word-slice, "#") +2850 # continue +2851 # else if slice-equal?(word-slice, "{") +2852 # assert(no-tokens-in(line)) +2853 # block = parse-mu-block(in, vars, fn) +2854 # append-to-block(result, block) +2855 # else if slice-equal?(word-slice, "}") +2856 # break +2857 # else if slice-ends-with?(word-slice, ":") +2858 # # TODO: check the rest of line +2859 # named-block = parse-mu-named-block(word-slice, in, vars, fn) +2860 # append-to-block(result, named-block) +2861 # else if slice-equal?(word-slice, "var") +2862 # var-def = parse-mu-var-def(line, vars) +2863 # append-to-block(result, var-def) +2864 # else +2865 # stmt = parse-mu-stmt(line, vars, fn) +2866 # append-to-block(result, stmt) +2867 # decrement *Curr-block-depth +2868 # return result +2869 # +2870 # . prologue +2871 55/push-ebp +2872 89/<- %ebp 4/r32/esp +2873 # . save registers +2874 51/push-ecx +2875 52/push-edx +2876 53/push-ebx +2877 57/push-edi +2878 # var line/ecx: (stream byte 512) +2879 81 5/subop/subtract %esp 0x200/imm32 +2880 68/push 0x200/imm32/length +2881 68/push 0/imm32/read +2882 68/push 0/imm32/write +2883 89/<- %ecx 4/r32/esp +2884 # var word-slice/edx: slice +2885 68/push 0/imm32/end +2886 68/push 0/imm32/start +2887 89/<- %edx 4/r32/esp +2888 # increment *Curr-block-depth +2889 ff 0/subop/increment *Curr-block-depth +2890 # edi = result +2891 (allocate Heap *Stmt-size) # => eax +2892 (zero-out %eax *Stmt-size) +2893 89/<- %edi 0/r32/eax +2894 # result->tag is implicitly block (0) +2895 { # line loop +2896 $parse-mu-block:line-loop: +2897 # line = read-line-buffered(in) +2898 (clear-stream %ecx) +2899 (read-line-buffered *(ebp+8) %ecx) +2900 #? (write-buffered Stderr "line: ") +2901 #? (write-stream-data Stderr %ecx) +2902 #? (write-buffered Stderr Newline) +2903 #? (flush Stderr) +2904 # if (line->write == 0) break +2905 81 7/subop/compare *ecx 0/imm32 +2906 0f 84/jump-if-= break/disp32 +2907 # word-slice = next-word(line) +2908 (next-word %ecx %edx) +2909 #? (write-buffered Stderr "word: ") +2910 #? (write-slice-buffered Stderr %edx) +2911 #? (write-buffered Stderr Newline) +2912 #? (flush Stderr) +2913 # if slice-empty?(word-slice) continue +2914 (slice-empty? %edx) +2915 3d/compare-eax-and 0/imm32 +2916 0f 85/jump-if-!= loop/disp32 +2917 # if (slice-starts-with?(word-slice, '#') continue +2918 # . eax = *word-slice->start +2919 8b/-> *edx 0/r32/eax +2920 8a/copy-byte *eax 0/r32/AL +2921 81 4/subop/and %eax 0xff/imm32 +2922 # . if (eax == '#') continue +2923 3d/compare-eax-and 0x23/imm32/hash +2924 0f 84/jump-if-= loop/disp32 +2925 # if slice-equal?(word-slice, "{") +2926 { +2927 $parse-mu-block:check-for-block: +2928 (slice-equal? %edx "{") +2929 3d/compare-eax-and 0/imm32 +2930 74/jump-if-= break/disp8 +2931 (check-no-tokens-left %ecx) +2932 # parse new block and append +2933 (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax +2934 (append-to-block Heap %edi %eax) +2935 e9/jump $parse-mu-block:line-loop/disp32 +2936 } +2937 # if slice-equal?(word-slice, "}") break +2938 $parse-mu-block:check-for-end: +2939 (slice-equal? %edx "}") +2940 3d/compare-eax-and 0/imm32 +2941 0f 85/jump-if-!= break/disp32 +2942 # if slice-ends-with?(word-slice, ":") parse named block and append +2943 { +2944 $parse-mu-block:check-for-named-block: +2945 # . eax = *(word-slice->end-1) +2946 8b/-> *(edx+4) 0/r32/eax +2947 48/decrement-eax +2948 8a/copy-byte *eax 0/r32/AL +2949 81 4/subop/and %eax 0xff/imm32 +2950 # . if (eax != ':') break +2951 3d/compare-eax-and 0x3a/imm32/colon +2952 0f 85/jump-if-!= break/disp32 +2953 # +2954 # TODO: error-check the rest of 'line' +2955 (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax +2956 (append-to-block Heap %edi %eax) +2957 e9/jump $parse-mu-block:line-loop/disp32 +2958 } +2959 # if slice-equal?(word-slice, "var") +2960 { +2961 $parse-mu-block:check-for-var: +2962 (slice-equal? %edx "var") +2963 3d/compare-eax-and 0/imm32 +2964 74/jump-if-= break/disp8 +2965 # +2966 (parse-mu-var-def %ecx *(ebp+0xc)) # => eax +2967 (append-to-block Heap %edi %eax) +2968 e9/jump $parse-mu-block:line-loop/disp32 +2969 } +2970 $parse-mu-block:regular-stmt: +2971 # otherwise +2972 (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10)) # => eax +2973 (append-to-block Heap %edi %eax) +2974 e9/jump loop/disp32 +2975 } # end line loop +2976 # decrement *Curr-block-depth +2977 ff 1/subop/decrement *Curr-block-depth +2978 # return result +2979 89/<- %eax 7/r32/edi +2980 $parse-mu-block:end: +2981 # . reclaim locals +2982 81 0/subop/add %esp 0x214/imm32 +2983 # . restore registers +2984 5f/pop-to-edi +2985 5b/pop-to-ebx +2986 5a/pop-to-edx +2987 59/pop-to-ecx +2988 # . epilogue +2989 89/<- %esp 5/r32/ebp +2990 5d/pop-to-ebp +2991 c3/return +2992 +2993 $parse-mu-block:abort: +2994 # error("'{' or '}' should be on its own line, but got '") +2995 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") +2996 (rewind-stream %ecx) +2997 (write-stream 2 %ecx) +2998 (write-buffered Stderr "'\n") +2999 (flush Stderr) +3000 # . syscall(exit, 1) +3001 bb/copy-to-ebx 1/imm32 +3002 b8/copy-to-eax 1/imm32/exit +3003 cd/syscall 0x80/imm8 +3004 # never gets here +3005 +3006 check-no-tokens-left: # line: (addr stream byte) +3007 # . prologue +3008 55/push-ebp +3009 89/<- %ebp 4/r32/esp +3010 # . save registers +3011 50/push-eax +3012 51/push-ecx +3013 # var s/ecx: slice +3014 68/push 0/imm32/end +3015 68/push 0/imm32/start +3016 89/<- %ecx 4/r32/esp +3017 # +3018 (next-word *(ebp+8) %ecx) +3019 # if slice-empty?(s) return +3020 (slice-empty? %ecx) +3021 3d/compare-eax-and 0/imm32 +3022 75/jump-if-!= $check-no-tokens-left:end/disp8 +3023 # if (slice-starts-with?(s, '#') return +3024 # . eax = *s->start +3025 8b/-> *edx 0/r32/eax +3026 8a/copy-byte *eax 0/r32/AL +3027 81 4/subop/and %eax 0xff/imm32 +3028 # . if (eax == '#') continue +3029 3d/compare-eax-and 0x23/imm32/hash +3030 74/jump-if-= $check-no-tokens-left:end/disp8 +3031 # abort +3032 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") +3033 (rewind-stream %ecx) +3034 (write-stream 2 %ecx) +3035 (write-buffered Stderr "'\n") +3036 (flush Stderr) +3037 # . syscall(exit, 1) +3038 bb/copy-to-ebx 1/imm32 +3039 b8/copy-to-eax 1/imm32/exit +3040 cd/syscall 0x80/imm8 +3041 # never gets here +3042 $check-no-tokens-left:end: +3043 # . reclaim locals +3044 81 0/subop/add %esp 8/imm32 +3045 # . restore registers +3046 59/pop-to-ecx +3047 58/pop-to-eax +3048 # . epilogue +3049 89/<- %esp 5/r32/ebp +3050 5d/pop-to-ebp +3051 c3/return +3052 +3053 parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) +3054 # pseudocode: +3055 # result = parse-mu-block(in, vars, fn) +3056 # result->tag = named-block +3057 # result->name = slice-to-string(name) +3058 # return result +3059 # +3060 # . prologue +3061 55/push-ebp +3062 89/<- %ebp 4/r32/esp +3063 # . save registers +3064 51/push-ecx +3065 # var s/ecx: (addr array byte) = slice-to-string(name) +3066 (slice-to-string Heap *(ebp+8)) # => eax +3067 89/<- %ecx 0/r32/eax +3068 # +3069 (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) # => eax +3070 # result->tag = named-block +3071 c7 0/subop/copy *eax 4/imm32/named-block # Stmt-tag +3072 # result->name = slice-to-string(name) +3073 89/<- *(eax+8) 1/r32/ecx # Named-block-name +3074 $parse-mu-named-block:end: +3075 # . restore registers +3076 59/pop-to-ecx +3077 # . epilogue +3078 89/<- %esp 5/r32/ebp +3079 5d/pop-to-ebp +3080 c3/return +3081 +3082 parse-mu-var-def: # line: (addr stream byte), vars: (addr stack (handle var)) -> result/eax: (handle stmt) +3083 # . prologue +3084 55/push-ebp +3085 89/<- %ebp 4/r32/esp +3086 # . save registers +3087 51/push-ecx +3088 52/push-edx +3089 # var word-slice/ecx: slice +3090 68/push 0/imm32/end +3091 68/push 0/imm32/start +3092 89/<- %ecx 4/r32/esp +3093 # var v/edx: (handle var) = parse-var-with-type(line) +3094 (next-word *(ebp+8) %ecx) +3095 (parse-var-with-type %ecx *(ebp+8)) # => eax +3096 89/<- %edx 0/r32/eax +3097 # v->stack-offset = *Next-local-stack-offset +3098 8b/-> *Next-local-stack-offset 0/r32/eax +3099 89/<- *(edx+0xc) 0/r32/eax # Var-stack-offset +3100 # *Next-local-stack-offset -= size-of(v) +3101 (size-of %edx) # => eax +3102 29/subtract-from *Next-local-stack-offset 0/r32/eax +3103 # v->block-depth = *Curr-block-depth +3104 8b/-> *Curr-block-depth 0/r32/eax +3105 89/<- *(edx+8) 0/r32/eax +3106 # +3107 (push *(ebp+0xc) %edx) +3108 # either v has no register and there's no more to this line +3109 8b/-> *(edx+0x10) 0/r32/eax # Var-register +3110 3d/compare-eax-and 0/imm32 +3111 { +3112 75/jump-if-!= break/disp8 +3113 # TODO: ensure that there's nothing else on this line +3114 (new-vardef Heap %edx) # => eax +3115 eb/jump $parse-mu-var-def:end/disp8 +3116 } +3117 # or v has a register and there's more to this line +3118 { +3119 74/jump-if-= break/disp8 +3120 # ensure that the next word is '<-' +3121 (next-word *(ebp+8) %ecx) +3122 (slice-equal? %ecx "<-") # => eax +3123 3d/compare-eax-and 0/imm32 +3124 74/jump-if-= $parse-mu-var-def:abort/disp8 +3125 # +3126 (new-regvardef Heap %edx) # => eax +3127 (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc)) +3128 } +3129 $parse-mu-var-def:end: +3130 # . reclaim locals +3131 81 0/subop/add %esp 8/imm32 +3132 # . restore registers +3133 5a/pop-to-edx +3134 59/pop-to-ecx 3135 # . epilogue 3136 89/<- %esp 5/r32/ebp 3137 5d/pop-to-ebp 3138 c3/return 3139 -3140 == data -3141 -3142 # Global state when parsing a function -3143 Curr-block-depth: # (addr int) -3144 0/imm32 -3145 Next-local-stack-offset: # (addr int) -3146 -4/imm32 -3147 -3148 == code -3149 -3150 # parses a block, assuming that the leading '{' has already been read by the caller -3151 parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle block) -3152 # pseudocode: -3153 # var line: (stream byte 512) -3154 # var word-slice: slice -3155 # increment *Curr-block-depth -3156 # result/eax = allocate(Heap, Stmt-size) -3157 # result->tag = 0/Block -3158 # while true # line loop -3159 # clear-stream(line) -3160 # read-line-buffered(in, line) -3161 # if (line->write == 0) break # end of file -3162 # word-slice = next-word(line) -3163 # if slice-empty?(word-slice) # end of line -3164 # continue -3165 # else if slice-starts-with?(word-slice, "#") -3166 # continue -3167 # else if slice-equal?(word-slice, "{") -3168 # assert(no-tokens-in(line)) -3169 # block = parse-mu-block(in, vars, fn) -3170 # append-to-block(result, block) -3171 # else if slice-equal?(word-slice, "}") -3172 # break -3173 # else if slice-ends-with?(word-slice, ":") -3174 # # TODO: check the rest of line -3175 # named-block = parse-mu-named-block(word-slice, in, vars, fn) -3176 # append-to-block(result, named-block) -3177 # else if slice-equal?(word-slice, "var") -3178 # var-def = parse-mu-var-def(line, vars) -3179 # append-to-block(result, var-def) -3180 # else -3181 # stmt = parse-mu-stmt(line, vars, fn) -3182 # append-to-block(result, stmt) -3183 # decrement *Curr-block-depth -3184 # return result -3185 # -3186 # . prologue -3187 55/push-ebp -3188 89/<- %ebp 4/r32/esp -3189 # . save registers -3190 51/push-ecx -3191 52/push-edx -3192 53/push-ebx -3193 57/push-edi -3194 # var line/ecx: (stream byte 512) -3195 81 5/subop/subtract %esp 0x200/imm32 -3196 68/push 0x200/imm32/length -3197 68/push 0/imm32/read -3198 68/push 0/imm32/write -3199 89/<- %ecx 4/r32/esp -3200 # var word-slice/edx: slice -3201 68/push 0/imm32/end -3202 68/push 0/imm32/start -3203 89/<- %edx 4/r32/esp -3204 # increment *Curr-block-depth -3205 ff 0/subop/increment *Curr-block-depth -3206 # edi = result -3207 (allocate Heap *Stmt-size) # => eax -3208 (zero-out %eax *Stmt-size) -3209 89/<- %edi 0/r32/eax -3210 # result->tag is implicitly block (0) -3211 { # line loop -3212 $parse-mu-block:line-loop: -3213 # line = read-line-buffered(in) -3214 (clear-stream %ecx) -3215 (read-line-buffered *(ebp+8) %ecx) -3216 #? (write-buffered Stderr "line: ") -3217 #? (write-stream-data Stderr %ecx) -3218 #? (write-buffered Stderr Newline) -3219 #? (flush Stderr) -3220 # if (line->write == 0) break -3221 81 7/subop/compare *ecx 0/imm32 -3222 0f 84/jump-if-= break/disp32 -3223 # word-slice = next-word(line) -3224 (next-word %ecx %edx) -3225 #? (write-buffered Stderr "word: ") -3226 #? (write-slice-buffered Stderr %edx) -3227 #? (write-buffered Stderr Newline) -3228 #? (flush Stderr) -3229 # if slice-empty?(word-slice) continue -3230 (slice-empty? %edx) -3231 3d/compare-eax-and 0/imm32 -3232 0f 85/jump-if-!= loop/disp32 -3233 # if (slice-starts-with?(word-slice, '#') continue -3234 # . eax = *word-slice->start -3235 8b/-> *edx 0/r32/eax -3236 8a/copy-byte *eax 0/r32/AL -3237 81 4/subop/and %eax 0xff/imm32 -3238 # . if (eax == '#') continue -3239 3d/compare-eax-and 0x23/imm32/hash -3240 0f 84/jump-if-= loop/disp32 -3241 # if slice-equal?(word-slice, "{") -3242 { -3243 $parse-mu-block:check-for-block: -3244 (slice-equal? %edx "{") -3245 3d/compare-eax-and 0/imm32 -3246 74/jump-if-= break/disp8 -3247 (check-no-tokens-left %ecx) -3248 # parse new block and append -3249 (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax -3250 (append-to-block Heap %edi %eax) -3251 e9/jump $parse-mu-block:line-loop/disp32 -3252 } -3253 # if slice-equal?(word-slice, "}") break -3254 $parse-mu-block:check-for-end: -3255 (slice-equal? %edx "}") -3256 3d/compare-eax-and 0/imm32 -3257 0f 85/jump-if-!= break/disp32 -3258 # if slice-ends-with?(word-slice, ":") parse named block and append -3259 { -3260 $parse-mu-block:check-for-named-block: -3261 # . eax = *(word-slice->end-1) -3262 8b/-> *(edx+4) 0/r32/eax -3263 48/decrement-eax -3264 8a/copy-byte *eax 0/r32/AL -3265 81 4/subop/and %eax 0xff/imm32 -3266 # . if (eax != ':') break -3267 3d/compare-eax-and 0x3a/imm32/colon -3268 0f 85/jump-if-!= break/disp32 +3140 $parse-mu-var-def:abort: +3141 (rewind-stream *(ebp+8)) +3142 # error("register variable requires a valid instruction to initialize but got '" line "'\n") +3143 (write-buffered Stderr "register variable requires a valid instruction to initialize but got '") +3144 (flush Stderr) +3145 (write-stream 2 *(ebp+8)) +3146 (write-buffered Stderr "'\n") +3147 (flush Stderr) +3148 # . syscall(exit, 1) +3149 bb/copy-to-ebx 1/imm32 +3150 b8/copy-to-eax 1/imm32/exit +3151 cd/syscall 0x80/imm8 +3152 # never gets here +3153 +3154 test-parse-mu-var-def: +3155 # 'var n: int' +3156 # . prologue +3157 55/push-ebp +3158 89/<- %ebp 4/r32/esp +3159 # setup +3160 (clear-stream _test-input-stream) +3161 (write _test-input-stream "n: int\n") # caller has consumed the 'var' +3162 # var vars/ecx: (stack (addr var) 4) +3163 81 5/subop/subtract %esp 0x10/imm32 +3164 68/push 0x10/imm32/length +3165 68/push 0/imm32/top +3166 89/<- %ecx 4/r32/esp +3167 (clear-stack %ecx) +3168 # convert +3169 (parse-mu-var-def _test-input-stream %ecx) # => eax +3170 # check result +3171 (check-ints-equal *eax 2 "F - test-parse-mu-var-def/tag") # Stmt-tag is vardef +3172 8b/-> *(eax+4) 0/r32/eax # Vardef-var +3173 (check-strings-equal *eax "n" "F - test-parse-mu-var-def/var-name") # Var-name +3174 (check-ints-equal *(eax+0x10) 0 "F - test-parse-mu-var-def/var-register") # Var-register +3175 # TODO: ensure stack-offset is -4 +3176 # TODO: ensure block-depth is 1 +3177 # ensure type is int +3178 8b/-> *(eax+4) 0/r32/eax # Var-type +3179 (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0") # Tree-left +3180 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-var-def/var-type:0") # Tree-right +3181 # . epilogue +3182 89/<- %esp 5/r32/ebp +3183 5d/pop-to-ebp +3184 c3/return +3185 +3186 test-parse-mu-reg-var-def: +3187 # 'var n/eax: int <- copy 0' +3188 # . prologue +3189 55/push-ebp +3190 89/<- %ebp 4/r32/esp +3191 # setup +3192 (clear-stream _test-input-stream) +3193 (write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var' +3194 # var vars/ecx: (stack (addr var) 4) +3195 81 5/subop/subtract %esp 0x10/imm32 +3196 68/push 0x10/imm32/length +3197 68/push 0/imm32/top +3198 89/<- %ecx 4/r32/esp +3199 (clear-stack %ecx) +3200 # convert +3201 (parse-mu-var-def _test-input-stream %ecx) # => eax +3202 # check result +3203 (check-ints-equal *eax 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is regvardef +3204 8b/-> *(eax+0xc) 0/r32/eax # Regvardef-outputs +3205 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/single-output") # List-next +3206 8b/-> *eax 0/r32/eax # List-value +3207 (check-strings-equal *eax "n" "F - test-parse-mu-reg-var-def/output-name") # Var-name +3208 (check-strings-equal *(eax+0x10) "eax" "F - test-parse-mu-reg-var-def/output-register") # Var-register +3209 # TODO: ensure stack-offset is -4 +3210 # TODO: ensure block-depth is 1 +3211 # ensure type is int +3212 8b/-> *(eax+4) 0/r32/eax # Var-type +3213 (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-left +3214 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-right +3215 # . epilogue +3216 89/<- %esp 5/r32/ebp +3217 5d/pop-to-ebp +3218 c3/return +3219 +3220 parse-mu-stmt: # line: (addr stream byte), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) +3221 # pseudocode: +3222 # var name: slice +3223 # result = allocate(Heap, Stmt-size) +3224 # if stmt-has-outputs?(line) +3225 # while true +3226 # name = next-mu-token(line) +3227 # if (name == '<-') break +3228 # assert(is-identifier?(name)) +3229 # var v: (handle var) = lookup-or-define-var(name, vars, fn) # regular stmts may define vars in fn outputs +3230 # result->outputs = append(result->outputs, v) +3231 # add-operation-and-inputs-to-stmt(result, line, vars) +3232 # +3233 # . prologue +3234 55/push-ebp +3235 89/<- %ebp 4/r32/esp +3236 # . save registers +3237 51/push-ecx +3238 57/push-edi +3239 # var name/ecx: slice +3240 68/push 0/imm32/end +3241 68/push 0/imm32/start +3242 89/<- %ecx 4/r32/esp +3243 # result/edi: (handle stmt) +3244 (allocate Heap *Stmt-size) # => eax +3245 (zero-out %eax *Stmt-size) +3246 89/<- %edi 0/r32/eax +3247 # result->tag = 1/stmt +3248 c7 0/subop/copy *edi 1/imm32/stmt1 # Stmt-tag +3249 { +3250 (stmt-has-outputs? *(ebp+8)) +3251 3d/compare-eax-and 0/imm32 +3252 0f 84/jump-if-= break/disp32 +3253 { +3254 $parse-mu-stmt:read-outputs: +3255 # name = next-mu-token(line) +3256 (next-mu-token *(ebp+8) %ecx) +3257 # if slice-empty?(word-slice) break +3258 (slice-empty? %ecx) +3259 3d/compare-eax-and 0/imm32 +3260 0f 85/jump-if-!= break/disp32 +3261 # if (name == "<-") break +3262 (slice-equal? %ecx "<-") +3263 3d/compare-eax-and 0/imm32 +3264 75/jump-if-!= break/disp8 +3265 # assert(is-identifier?(name)) +3266 (is-identifier? %ecx) +3267 3d/compare-eax-and 0/imm32 +3268 0f 84/jump-if-= $parse-mu-stmt:abort/disp32 3269 # -3270 # TODO: error-check the rest of 'line' -3271 (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax -3272 (append-to-block Heap %edi %eax) -3273 e9/jump $parse-mu-block:line-loop/disp32 +3270 (lookup-or-define-var %ecx *(ebp+0xc) *(ebp+0x10)) # => eax +3271 (append-list Heap %eax *(edi+0xc)) # Stmt1-outputs => eax +3272 89/<- *(edi+0xc) 0/r32/eax # Stmt1-outputs +3273 e9/jump loop/disp32 3274 } -3275 # if slice-equal?(word-slice, "var") -3276 { -3277 $parse-mu-block:check-for-var: -3278 (slice-equal? %edx "var") -3279 3d/compare-eax-and 0/imm32 -3280 74/jump-if-= break/disp8 -3281 # -3282 (parse-mu-var-def %ecx *(ebp+0xc)) # => eax -3283 (append-to-block Heap %edi %eax) -3284 e9/jump $parse-mu-block:line-loop/disp32 -3285 } -3286 $parse-mu-block:regular-stmt: -3287 # otherwise -3288 (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10)) # => eax -3289 (append-to-block Heap %edi %eax) -3290 e9/jump loop/disp32 -3291 } # end line loop -3292 # decrement *Curr-block-depth -3293 ff 1/subop/decrement *Curr-block-depth -3294 # return result -3295 89/<- %eax 7/r32/edi -3296 $parse-mu-block:end: -3297 # . reclaim locals -3298 81 0/subop/add %esp 0x214/imm32 -3299 # . restore registers -3300 5f/pop-to-edi -3301 5b/pop-to-ebx -3302 5a/pop-to-edx -3303 59/pop-to-ecx -3304 # . epilogue -3305 89/<- %esp 5/r32/ebp -3306 5d/pop-to-ebp -3307 c3/return -3308 -3309 $parse-mu-block:abort: -3310 # error("'{' or '}' should be on its own line, but got '") -3311 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") -3312 (rewind-stream %ecx) -3313 (write-stream 2 %ecx) -3314 (write-buffered Stderr "'\n") -3315 (flush Stderr) -3316 # . syscall(exit, 1) -3317 bb/copy-to-ebx 1/imm32 -3318 b8/copy-to-eax 1/imm32/exit -3319 cd/syscall 0x80/imm8 -3320 # never gets here -3321 -3322 check-no-tokens-left: # line: (addr stream byte) -3323 # . prologue -3324 55/push-ebp -3325 89/<- %ebp 4/r32/esp -3326 # . save registers -3327 50/push-eax -3328 51/push-ecx -3329 # var s/ecx: slice -3330 68/push 0/imm32/end -3331 68/push 0/imm32/start -3332 89/<- %ecx 4/r32/esp -3333 # -3334 (next-word *(ebp+8) %ecx) -3335 # if slice-empty?(s) return -3336 (slice-empty? %ecx) -3337 3d/compare-eax-and 0/imm32 -3338 75/jump-if-!= $check-no-tokens-left:end/disp8 -3339 # if (slice-starts-with?(s, '#') return -3340 # . eax = *s->start -3341 8b/-> *edx 0/r32/eax -3342 8a/copy-byte *eax 0/r32/AL -3343 81 4/subop/and %eax 0xff/imm32 -3344 # . if (eax == '#') continue -3345 3d/compare-eax-and 0x23/imm32/hash -3346 74/jump-if-= $check-no-tokens-left:end/disp8 -3347 # abort -3348 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") -3349 (rewind-stream %ecx) -3350 (write-stream 2 %ecx) -3351 (write-buffered Stderr "'\n") -3352 (flush Stderr) -3353 # . syscall(exit, 1) -3354 bb/copy-to-ebx 1/imm32 -3355 b8/copy-to-eax 1/imm32/exit -3356 cd/syscall 0x80/imm8 -3357 # never gets here -3358 $check-no-tokens-left:end: -3359 # . reclaim locals -3360 81 0/subop/add %esp 8/imm32 -3361 # . restore registers -3362 59/pop-to-ecx -3363 58/pop-to-eax -3364 # . epilogue -3365 89/<- %esp 5/r32/ebp -3366 5d/pop-to-ebp -3367 c3/return -3368 -3369 parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) -3370 # pseudocode: -3371 # result = parse-mu-block(in, vars, fn) -3372 # result->tag = named-block -3373 # result->name = slice-to-string(name) -3374 # return result -3375 # -3376 # . prologue -3377 55/push-ebp -3378 89/<- %ebp 4/r32/esp -3379 # . save registers -3380 51/push-ecx -3381 # var s/ecx: (addr array byte) = slice-to-string(name) -3382 (slice-to-string Heap *(ebp+8)) # => eax -3383 89/<- %ecx 0/r32/eax -3384 # -3385 (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) # => eax -3386 # result->tag = named-block -3387 c7 0/subop/copy *eax 4/imm32/named-block # Stmt-tag -3388 # result->name = slice-to-string(name) -3389 89/<- *(eax+8) 1/r32/ecx # Named-block-name -3390 $parse-mu-named-block:end: -3391 # . restore registers -3392 59/pop-to-ecx -3393 # . epilogue -3394 89/<- %esp 5/r32/ebp -3395 5d/pop-to-ebp -3396 c3/return -3397 -3398 parse-mu-var-def: # line: (addr stream byte), vars: (addr stack (handle var)) -> result/eax: (handle stmt) -3399 # . prologue -3400 55/push-ebp -3401 89/<- %ebp 4/r32/esp -3402 # . save registers -3403 51/push-ecx -3404 52/push-edx -3405 # var word-slice/ecx: slice -3406 68/push 0/imm32/end -3407 68/push 0/imm32/start -3408 89/<- %ecx 4/r32/esp -3409 # var v/edx: (handle var) = parse-var-with-type(line) -3410 (next-word *(ebp+8) %ecx) -3411 (parse-var-with-type %ecx *(ebp+8)) # => eax -3412 89/<- %edx 0/r32/eax -3413 # v->stack-offset = *Next-local-stack-offset -3414 8b/-> *Next-local-stack-offset 0/r32/eax -3415 89/<- *(edx+0xc) 0/r32/eax # Var-stack-offset -3416 # *Next-local-stack-offset -= size-of(v) -3417 (size-of %edx) # => eax -3418 29/subtract-from *Next-local-stack-offset 0/r32/eax -3419 # v->block-depth = *Curr-block-depth -3420 8b/-> *Curr-block-depth 0/r32/eax -3421 89/<- *(edx+8) 0/r32/eax -3422 # -3423 (push *(ebp+0xc) %edx) -3424 # either v has no register and there's no more to this line -3425 8b/-> *(edx+0x10) 0/r32/eax # Var-register -3426 3d/compare-eax-and 0/imm32 -3427 { -3428 75/jump-if-!= break/disp8 -3429 # TODO: ensure that there's nothing else on this line -3430 (new-vardef Heap %edx) # => eax -3431 eb/jump $parse-mu-var-def:end/disp8 -3432 } -3433 # or v has a register and there's more to this line -3434 { -3435 74/jump-if-= break/disp8 -3436 # ensure that the next word is '<-' -3437 (next-word *(ebp+8) %ecx) -3438 (slice-equal? %ecx "<-") # => eax -3439 3d/compare-eax-and 0/imm32 -3440 74/jump-if-= $parse-mu-var-def:abort/disp8 -3441 # -3442 (new-regvardef Heap %edx) # => eax -3443 (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc)) -3444 } -3445 $parse-mu-var-def:end: -3446 # . reclaim locals -3447 81 0/subop/add %esp 8/imm32 -3448 # . restore registers -3449 5a/pop-to-edx -3450 59/pop-to-ecx -3451 # . epilogue -3452 89/<- %esp 5/r32/ebp -3453 5d/pop-to-ebp -3454 c3/return -3455 -3456 $parse-mu-var-def:abort: -3457 (rewind-stream *(ebp+8)) -3458 # error("register variable requires a valid instruction to initialize but got '" line "'\n") -3459 (write-buffered Stderr "register variable requires a valid instruction to initialize but got '") -3460 (flush Stderr) -3461 (write-stream 2 *(ebp+8)) -3462 (write-buffered Stderr "'\n") -3463 (flush Stderr) -3464 # . syscall(exit, 1) -3465 bb/copy-to-ebx 1/imm32 -3466 b8/copy-to-eax 1/imm32/exit -3467 cd/syscall 0x80/imm8 -3468 # never gets here -3469 -3470 test-parse-mu-var-def: -3471 # 'var n: int' -3472 # . prologue -3473 55/push-ebp -3474 89/<- %ebp 4/r32/esp -3475 # setup -3476 (clear-stream _test-input-stream) -3477 (write _test-input-stream "n: int\n") # caller has consumed the 'var' -3478 # var vars/ecx: (stack (addr var) 4) -3479 81 5/subop/subtract %esp 0x10/imm32 -3480 68/push 0x10/imm32/length -3481 68/push 0/imm32/top -3482 89/<- %ecx 4/r32/esp -3483 (clear-stack %ecx) -3484 # convert -3485 (parse-mu-var-def _test-input-stream %ecx) # => eax -3486 # check result -3487 (check-ints-equal *eax 2 "F - test-parse-mu-var-def/tag") # Stmt-tag is vardef -3488 8b/-> *(eax+4) 0/r32/eax # Vardef-var -3489 (check-strings-equal *eax "n" "F - test-parse-mu-var-def/var-name") # Var-name -3490 (check-ints-equal *(eax+0x10) 0 "F - test-parse-mu-var-def/var-register") # Var-register -3491 # TODO: ensure stack-offset is -4 -3492 # TODO: ensure block-depth is 1 -3493 # ensure type is int -3494 8b/-> *(eax+4) 0/r32/eax # Var-type -3495 (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0") # Tree-left -3496 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-var-def/var-type:0") # Tree-right -3497 # . epilogue -3498 89/<- %esp 5/r32/ebp -3499 5d/pop-to-ebp -3500 c3/return -3501 -3502 test-parse-mu-reg-var-def: -3503 # 'var n/eax: int <- copy 0' -3504 # . prologue -3505 55/push-ebp -3506 89/<- %ebp 4/r32/esp -3507 # setup -3508 (clear-stream _test-input-stream) -3509 (write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var' -3510 # var vars/ecx: (stack (addr var) 4) -3511 81 5/subop/subtract %esp 0x10/imm32 -3512 68/push 0x10/imm32/length -3513 68/push 0/imm32/top -3514 89/<- %ecx 4/r32/esp -3515 (clear-stack %ecx) -3516 # convert -3517 (parse-mu-var-def _test-input-stream %ecx) # => eax -3518 # check result -3519 (check-ints-equal *eax 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is regvardef -3520 8b/-> *(eax+0xc) 0/r32/eax # Regvardef-outputs -3521 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/single-output") # List-next -3522 8b/-> *eax 0/r32/eax # List-value -3523 (check-strings-equal *eax "n" "F - test-parse-mu-reg-var-def/output-name") # Var-name -3524 (check-strings-equal *(eax+0x10) "eax" "F - test-parse-mu-reg-var-def/output-register") # Var-register -3525 # TODO: ensure stack-offset is -4 -3526 # TODO: ensure block-depth is 1 -3527 # ensure type is int -3528 8b/-> *(eax+4) 0/r32/eax # Var-type -3529 (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-left -3530 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-right -3531 # . epilogue -3532 89/<- %esp 5/r32/ebp -3533 5d/pop-to-ebp -3534 c3/return -3535 -3536 parse-mu-stmt: # line: (addr stream byte), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) -3537 # pseudocode: -3538 # var name: slice -3539 # result = allocate(Heap, Stmt-size) -3540 # if stmt-has-outputs?(line) -3541 # while true -3542 # name = next-mu-token(line) -3543 # if (name == '<-') break -3544 # assert(is-identifier?(name)) -3545 # var v: (handle var) = lookup-or-define-var(name, vars, fn) # regular stmts may define vars in fn outputs -3546 # result->outputs = append(result->outputs, v) -3547 # add-operation-and-inputs-to-stmt(result, line, vars) -3548 # -3549 # . prologue -3550 55/push-ebp -3551 89/<- %ebp 4/r32/esp -3552 # . save registers -3553 51/push-ecx -3554 57/push-edi -3555 # var name/ecx: slice -3556 68/push 0/imm32/end -3557 68/push 0/imm32/start -3558 89/<- %ecx 4/r32/esp -3559 # result/edi: (handle stmt) -3560 (allocate Heap *Stmt-size) # => eax -3561 (zero-out %eax *Stmt-size) -3562 89/<- %edi 0/r32/eax -3563 # result->tag = 1/stmt -3564 c7 0/subop/copy *edi 1/imm32/stmt1 # Stmt-tag -3565 { -3566 (stmt-has-outputs? *(ebp+8)) -3567 3d/compare-eax-and 0/imm32 -3568 0f 84/jump-if-= break/disp32 -3569 { -3570 $parse-mu-stmt:read-outputs: -3571 # name = next-mu-token(line) -3572 (next-mu-token *(ebp+8) %ecx) -3573 # if slice-empty?(word-slice) break -3574 (slice-empty? %ecx) -3575 3d/compare-eax-and 0/imm32 -3576 0f 85/jump-if-!= break/disp32 -3577 # if (name == "<-") break -3578 (slice-equal? %ecx "<-") -3579 3d/compare-eax-and 0/imm32 -3580 75/jump-if-!= break/disp8 -3581 # assert(is-identifier?(name)) -3582 (is-identifier? %ecx) -3583 3d/compare-eax-and 0/imm32 -3584 0f 84/jump-if-= $parse-mu-stmt:abort/disp32 -3585 # -3586 (lookup-or-define-var %ecx *(ebp+0xc) *(ebp+0x10)) # => eax -3587 (append-list Heap %eax *(edi+0xc)) # Stmt1-outputs => eax -3588 89/<- *(edi+0xc) 0/r32/eax # Stmt1-outputs -3589 e9/jump loop/disp32 -3590 } -3591 } -3592 (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc)) -3593 $parse-mu-stmt:end: -3594 # return result -3595 89/<- %eax 7/r32/edi -3596 # . reclaim locals -3597 81 0/subop/add %esp 8/imm32 -3598 # . restore registers -3599 5f/pop-to-edi -3600 59/pop-to-ecx -3601 # . epilogue -3602 89/<- %esp 5/r32/ebp -3603 5d/pop-to-ebp -3604 c3/return -3605 -3606 $parse-mu-stmt:abort: -3607 # error("invalid identifier '" name "'\n") -3608 (write-buffered Stderr "invalid identifier '") -3609 (write-slice-buffered Stderr %ecx) -3610 (write-buffered Stderr "'\n") -3611 (flush Stderr) -3612 # . syscall(exit, 1) -3613 bb/copy-to-ebx 1/imm32 -3614 b8/copy-to-eax 1/imm32/exit -3615 cd/syscall 0x80/imm8 -3616 # never gets here -3617 -3618 add-operation-and-inputs-to-stmt: # stmt: (handle stmt), line: (addr stream byte) -3619 # pseudocode: -3620 # stmt->name = slice-to-string(next-mu-token(line)) -3621 # while true -3622 # name = next-mu-token(line) -3623 # v = lookup-var-or-literal(name) -3624 # stmt->inouts = append(stmt->inouts, v) -3625 # -3626 # . prologue -3627 55/push-ebp -3628 89/<- %ebp 4/r32/esp -3629 # . save registers -3630 50/push-eax -3631 51/push-ecx -3632 57/push-edi -3633 # edi = stmt -3634 8b/-> *(ebp+8) 7/r32/edi -3635 # var name/ecx: slice -3636 68/push 0/imm32/end -3637 68/push 0/imm32/start -3638 89/<- %ecx 4/r32/esp -3639 $add-operation-and-inputs-to-stmt:read-operation: -3640 (next-mu-token *(ebp+0xc) %ecx) -3641 (slice-to-string Heap %ecx) # => eax -3642 89/<- *(edi+4) 0/r32/eax # Stmt1-operation or Regvardef-operation -3643 { -3644 $add-operation-and-inputs-to-stmt:read-inouts: -3645 # name = next-mu-token(line) -3646 (next-mu-token *(ebp+0xc) %ecx) -3647 # if slice-empty?(word-slice) break -3648 (slice-empty? %ecx) # => eax -3649 3d/compare-eax-and 0/imm32 -3650 0f 85/jump-if-!= break/disp32 -3651 # if (name == "<-") abort -3652 (slice-equal? %ecx "<-") -3653 3d/compare-eax-and 0/imm32 -3654 0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32 -3655 # if (name starts with "$") treat it as a literal -3656 { -3657 # var eax: byte = name[0] -3658 8b/-> *ecx 0/r32/eax -3659 8a/copy-byte *eax 0/r32/AL -3660 81 4/subop/and %eax 0xff/imm32 -3661 # if (eax != '$') goto next condition -3662 3d/compare-eax-and 0x24/imm32/dollar -3663 75/jump-if-!= break/disp8 -3664 # var eax: (handle var) -3665 (new-label Heap %ecx) # => eax -3666 # stmt->inouts = append(eax, stmt->inouts) -3667 (append-list Heap %eax *(edi+8)) # Stmt1-inouts => eax -3668 89/<- *(edi+8) 0/r32/eax # Stmt1-inouts -3669 # continue -3670 e9/jump $add-operation-and-inputs-to-stmt:read-inouts/disp32 -3671 } -3672 $add-operation-and-inputs-to-stmt:regular-inout: -3673 # otherwise -3674 (lookup-var-or-literal %ecx *(ebp+0x10)) # => eax -3675 (append-list Heap %eax *(edi+8)) # Stmt1-inouts or Regvardef-inouts => eax -3676 89/<- *(edi+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts -3677 e9/jump loop/disp32 -3678 } -3679 $add-operation-and-inputs-to-stmt:end: -3680 # . reclaim locals -3681 81 0/subop/add %esp 8/imm32 -3682 # . restore registers -3683 5f/pop-to-edi -3684 59/pop-to-ecx -3685 58/pop-to-eax -3686 # . epilogue -3687 89/<- %esp 5/r32/ebp -3688 5d/pop-to-ebp -3689 c3/return -3690 -3691 $add-operation-and-inputs-to-stmt:abort: -3692 # error("invalid statement '" line "'\n") -3693 (rewind-stream *(ebp+8)) -3694 (write-buffered Stderr "invalid identifier '") -3695 (flush Stderr) -3696 (write-stream 2 *(ebp+8)) -3697 (write-buffered Stderr "'\n") -3698 (flush Stderr) -3699 # . syscall(exit, 1) -3700 bb/copy-to-ebx 1/imm32 -3701 b8/copy-to-eax 1/imm32/exit -3702 cd/syscall 0x80/imm8 -3703 # never gets here -3704 -3705 stmt-has-outputs?: # line: (addr stream byte) -> result/eax: boolean -3706 # . prologue -3707 55/push-ebp -3708 89/<- %ebp 4/r32/esp -3709 # . save registers -3710 51/push-ecx -3711 # var word-slice/ecx: slice -3712 68/push 0/imm32/end -3713 68/push 0/imm32/start -3714 89/<- %ecx 4/r32/esp -3715 # result = false -3716 b8/copy-to-eax 0/imm32/false -3717 (rewind-stream *(ebp+8)) -3718 { -3719 (next-mu-token *(ebp+8) %ecx) -3720 # if slice-empty?(word-slice) break -3721 (slice-empty? %ecx) -3722 3d/compare-eax-and 0/imm32 -3723 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) -3724 0f 85/jump-if-!= break/disp32 -3725 # if slice-starts-with?(word-slice, '#') break -3726 # . eax = *word-slice->start -3727 8b/-> *ecx 0/r32/eax -3728 8a/copy-byte *eax 0/r32/AL -3729 81 4/subop/and %eax 0xff/imm32 -3730 # . if (eax == '#') break -3731 3d/compare-eax-and 0x23/imm32/hash -3732 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) -3733 0f 84/jump-if-= break/disp32 -3734 # if slice-equal?(word-slice, '<-') return true -3735 (slice-equal? %ecx "<-") -3736 3d/compare-eax-and 0/imm32 -3737 74/jump-if-= loop/disp8 -3738 b8/copy-to-eax 1/imm32/true -3739 } -3740 $stmt-has-outputs:end: -3741 (rewind-stream *(ebp+8)) -3742 # . reclaim locals -3743 81 0/subop/add %esp 8/imm32 -3744 # . restore registers -3745 59/pop-to-ecx -3746 # . epilogue -3747 89/<- %esp 5/r32/ebp -3748 5d/pop-to-ebp -3749 c3/return -3750 -3751 # if 'name' starts with a digit, create a new literal var for it -3752 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found -3753 lookup-var-or-literal: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) +3275 } +3276 (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc)) +3277 $parse-mu-stmt:end: +3278 # return result +3279 89/<- %eax 7/r32/edi +3280 # . reclaim locals +3281 81 0/subop/add %esp 8/imm32 +3282 # . restore registers +3283 5f/pop-to-edi +3284 59/pop-to-ecx +3285 # . epilogue +3286 89/<- %esp 5/r32/ebp +3287 5d/pop-to-ebp +3288 c3/return +3289 +3290 $parse-mu-stmt:abort: +3291 # error("invalid identifier '" name "'\n") +3292 (write-buffered Stderr "invalid identifier '") +3293 (write-slice-buffered Stderr %ecx) +3294 (write-buffered Stderr "'\n") +3295 (flush Stderr) +3296 # . syscall(exit, 1) +3297 bb/copy-to-ebx 1/imm32 +3298 b8/copy-to-eax 1/imm32/exit +3299 cd/syscall 0x80/imm8 +3300 # never gets here +3301 +3302 add-operation-and-inputs-to-stmt: # stmt: (handle stmt), line: (addr stream byte) +3303 # pseudocode: +3304 # stmt->name = slice-to-string(next-mu-token(line)) +3305 # while true +3306 # name = next-mu-token(line) +3307 # v = lookup-var-or-literal(name) +3308 # stmt->inouts = append(stmt->inouts, v) +3309 # +3310 # . prologue +3311 55/push-ebp +3312 89/<- %ebp 4/r32/esp +3313 # . save registers +3314 50/push-eax +3315 51/push-ecx +3316 57/push-edi +3317 # edi = stmt +3318 8b/-> *(ebp+8) 7/r32/edi +3319 # var name/ecx: slice +3320 68/push 0/imm32/end +3321 68/push 0/imm32/start +3322 89/<- %ecx 4/r32/esp +3323 $add-operation-and-inputs-to-stmt:read-operation: +3324 (next-mu-token *(ebp+0xc) %ecx) +3325 (slice-to-string Heap %ecx) # => eax +3326 89/<- *(edi+4) 0/r32/eax # Stmt1-operation or Regvardef-operation +3327 { +3328 $add-operation-and-inputs-to-stmt:read-inouts: +3329 # name = next-mu-token(line) +3330 (next-mu-token *(ebp+0xc) %ecx) +3331 # if slice-empty?(word-slice) break +3332 (slice-empty? %ecx) # => eax +3333 3d/compare-eax-and 0/imm32 +3334 0f 85/jump-if-!= break/disp32 +3335 # if (name == "<-") abort +3336 (slice-equal? %ecx "<-") +3337 3d/compare-eax-and 0/imm32 +3338 0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32 +3339 # if (name starts with "$") treat it as a literal +3340 { +3341 # var eax: byte = name[0] +3342 8b/-> *ecx 0/r32/eax +3343 8a/copy-byte *eax 0/r32/AL +3344 81 4/subop/and %eax 0xff/imm32 +3345 # if (eax != '$') goto next condition +3346 3d/compare-eax-and 0x24/imm32/dollar +3347 75/jump-if-!= break/disp8 +3348 # var eax: (handle var) +3349 (new-label Heap %ecx) # => eax +3350 # stmt->inouts = append(eax, stmt->inouts) +3351 (append-list Heap %eax *(edi+8)) # Stmt1-inouts => eax +3352 89/<- *(edi+8) 0/r32/eax # Stmt1-inouts +3353 # continue +3354 e9/jump $add-operation-and-inputs-to-stmt:read-inouts/disp32 +3355 } +3356 $add-operation-and-inputs-to-stmt:regular-inout: +3357 # otherwise +3358 (lookup-var-or-literal %ecx *(ebp+0x10)) # => eax +3359 (append-list Heap %eax *(edi+8)) # Stmt1-inouts or Regvardef-inouts => eax +3360 89/<- *(edi+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts +3361 e9/jump loop/disp32 +3362 } +3363 $add-operation-and-inputs-to-stmt:end: +3364 # . reclaim locals +3365 81 0/subop/add %esp 8/imm32 +3366 # . restore registers +3367 5f/pop-to-edi +3368 59/pop-to-ecx +3369 58/pop-to-eax +3370 # . epilogue +3371 89/<- %esp 5/r32/ebp +3372 5d/pop-to-ebp +3373 c3/return +3374 +3375 $add-operation-and-inputs-to-stmt:abort: +3376 # error("invalid statement '" line "'\n") +3377 (rewind-stream *(ebp+8)) +3378 (write-buffered Stderr "invalid identifier '") +3379 (flush Stderr) +3380 (write-stream 2 *(ebp+8)) +3381 (write-buffered Stderr "'\n") +3382 (flush Stderr) +3383 # . syscall(exit, 1) +3384 bb/copy-to-ebx 1/imm32 +3385 b8/copy-to-eax 1/imm32/exit +3386 cd/syscall 0x80/imm8 +3387 # never gets here +3388 +3389 stmt-has-outputs?: # line: (addr stream byte) -> result/eax: boolean +3390 # . prologue +3391 55/push-ebp +3392 89/<- %ebp 4/r32/esp +3393 # . save registers +3394 51/push-ecx +3395 # var word-slice/ecx: slice +3396 68/push 0/imm32/end +3397 68/push 0/imm32/start +3398 89/<- %ecx 4/r32/esp +3399 # result = false +3400 b8/copy-to-eax 0/imm32/false +3401 (rewind-stream *(ebp+8)) +3402 { +3403 (next-mu-token *(ebp+8) %ecx) +3404 # if slice-empty?(word-slice) break +3405 (slice-empty? %ecx) +3406 3d/compare-eax-and 0/imm32 +3407 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) +3408 0f 85/jump-if-!= break/disp32 +3409 # if slice-starts-with?(word-slice, '#') break +3410 # . eax = *word-slice->start +3411 8b/-> *ecx 0/r32/eax +3412 8a/copy-byte *eax 0/r32/AL +3413 81 4/subop/and %eax 0xff/imm32 +3414 # . if (eax == '#') break +3415 3d/compare-eax-and 0x23/imm32/hash +3416 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) +3417 0f 84/jump-if-= break/disp32 +3418 # if slice-equal?(word-slice, '<-') return true +3419 (slice-equal? %ecx "<-") +3420 3d/compare-eax-and 0/imm32 +3421 74/jump-if-= loop/disp8 +3422 b8/copy-to-eax 1/imm32/true +3423 } +3424 $stmt-has-outputs:end: +3425 (rewind-stream *(ebp+8)) +3426 # . reclaim locals +3427 81 0/subop/add %esp 8/imm32 +3428 # . restore registers +3429 59/pop-to-ecx +3430 # . epilogue +3431 89/<- %esp 5/r32/ebp +3432 5d/pop-to-ebp +3433 c3/return +3434 +3435 # if 'name' starts with a digit, create a new literal var for it +3436 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found +3437 lookup-var-or-literal: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) +3438 # . prologue +3439 55/push-ebp +3440 89/<- %ebp 4/r32/esp +3441 # . save registers +3442 51/push-ecx +3443 56/push-esi +3444 # esi = name +3445 8b/-> *(ebp+8) 6/r32/esi +3446 # if slice-empty?(name) abort +3447 (slice-empty? %esi) # => eax +3448 3d/compare-eax-and 0/imm32 +3449 0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32 +3450 # var c/ecx: byte = *name->start +3451 8b/-> *esi 1/r32/ecx +3452 8a/copy-byte *ecx 1/r32/CL +3453 81 4/subop/and %ecx 0xff/imm32 +3454 # if is-decimal-digit?(c) return new var(name) +3455 { +3456 (is-decimal-digit? %ecx) # => eax +3457 81 7/subop/compare %eax 0/imm32 +3458 74/jump-if-= break/disp8 +3459 (new-literal-integer Heap %esi) # => eax +3460 eb/jump $lookup-var-or-literal:end/disp8 +3461 } +3462 # else if (c == '"') return new var(name) +3463 { +3464 81 7/subop/compare %ecx 0x22/imm32/dquote +3465 75/jump-if-!= break/disp8 +3466 (new-literal-string Heap %esi) # => eax +3467 eb/jump $lookup-var-or-literal:end/disp8 +3468 } +3469 # otherwise return lookup-var(name, vars) +3470 { +3471 (lookup-var %esi *(ebp+0xc)) # => eax +3472 } +3473 $lookup-var-or-literal:end: +3474 # . restore registers +3475 5e/pop-to-esi +3476 59/pop-to-ecx +3477 # . epilogue +3478 89/<- %esp 5/r32/ebp +3479 5d/pop-to-ebp +3480 c3/return +3481 +3482 $lookup-var-or-literal:abort: +3483 (write-buffered Stderr "empty variable!") +3484 (flush Stderr) +3485 # . syscall(exit, 1) +3486 bb/copy-to-ebx 1/imm32 +3487 b8/copy-to-eax 1/imm32/exit +3488 cd/syscall 0x80/imm8 +3489 # never gets here +3490 +3491 # return first 'name' from the top (back) of 'vars' and abort if not found +3492 lookup-var: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) +3493 # . prologue +3494 55/push-ebp +3495 89/<- %ebp 4/r32/esp +3496 # var target/eax: (handle array byte) = slice-to-string(name) +3497 (slice-to-string Heap *(ebp+8)) # => eax +3498 # +3499 (lookup-var-helper %eax *(ebp+0xc)) # => eax +3500 # if (result == 0) abort +3501 3d/compare-eax-and 0/imm32 +3502 74/jump-if-= $lookup-var:abort/disp8 +3503 $lookup-var:end: +3504 # . epilogue +3505 89/<- %esp 5/r32/ebp +3506 5d/pop-to-ebp +3507 c3/return +3508 +3509 $lookup-var:abort: +3510 (write-buffered Stderr "unknown variable '") +3511 (write-slice-buffered Stderr *(ebp+8)) +3512 (write-buffered Stderr "'\n") +3513 (flush Stderr) +3514 # . syscall(exit, 1) +3515 bb/copy-to-ebx 1/imm32 +3516 b8/copy-to-eax 1/imm32/exit +3517 cd/syscall 0x80/imm8 +3518 # never gets here +3519 +3520 # return first 'name' from the top (back) of 'vars', and 0/null if not found +3521 lookup-var-helper: # name: (addr array byte), vars: (addr stack (handle var)) -> result/eax: (handle var) +3522 # pseudocode: +3523 # var curr: (addr handle var) = &vars->data[vars->top - 4] +3524 # var min = vars->data +3525 # while curr >= min +3526 # var v: (handle var) = *curr +3527 # if v->name == name +3528 # return v +3529 # return 0 +3530 # +3531 # . prologue +3532 55/push-ebp +3533 89/<- %ebp 4/r32/esp +3534 # . save registers +3535 52/push-edx +3536 53/push-ebx +3537 56/push-esi +3538 # esi = vars +3539 8b/-> *(ebp+0xc) 6/r32/esi +3540 # ebx = vars->top +3541 8b/-> *esi 3/r32/ebx +3542 # if (vars->top > vars->length) abort +3543 3b/compare 0/r32/eax *(esi+4) +3544 0f 8f/jump-if-> $lookup-var-helper:error1/disp32 +3545 # var min/edx: (addr handle var) = vars->data +3546 8d/copy-address *(esi+8) 2/r32/edx +3547 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 4] +3548 81 5/subop/subtract %ebx 4/imm32 +3549 8d/copy-address *(esi+ebx+8) 3/r32/ebx +3550 { +3551 # if (curr < min) return 0 +3552 39/compare %ebx 2/r32/edx +3553 b8/copy-to-eax 0/imm32 +3554 0f 82/jump-if-addr< break/disp32 +3555 # var v/eax: (handle var) = *curr +3556 8b/-> *ebx 0/r32/eax +3557 # if (v->name == name) return v +3558 (string-equal? *eax *(ebp+8)) # Var-name +3559 3d/compare-eax-and 0/imm32 +3560 8b/-> *ebx 0/r32/eax +3561 75/jump-if-!= break/disp8 +3562 # curr -= 4 +3563 81 5/subop/subtract %ebx 4/imm32 +3564 e9/jump loop/disp32 +3565 } +3566 $lookup-var-helper:end: +3567 # . restore registers +3568 5e/pop-to-esi +3569 5b/pop-to-ebx +3570 5a/pop-to-edx +3571 # . epilogue +3572 89/<- %esp 5/r32/ebp +3573 5d/pop-to-ebp +3574 c3/return +3575 +3576 $lookup-var-helper:error1: +3577 (write-buffered Stderr "malformed stack when looking up '") +3578 (write-slice-buffered Stderr *(ebp+8)) +3579 (write-buffered Stderr "'\n") +3580 (flush Stderr) +3581 # . syscall(exit, 1) +3582 bb/copy-to-ebx 1/imm32 +3583 b8/copy-to-eax 1/imm32/exit +3584 cd/syscall 0x80/imm8 +3585 # never gets here +3586 +3587 # return first 'name' from the top (back) of 'vars' and create a new var for a fn output if not found +3588 lookup-or-define-var: # name: (addr slice), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle var) +3589 # . prologue +3590 55/push-ebp +3591 89/<- %ebp 4/r32/esp +3592 # . save registers +3593 51/push-ecx +3594 # var target/ecx: (handle array byte) = slice-to-string(name) +3595 (slice-to-string Heap *(ebp+8)) # => eax +3596 89/<- %ecx 0/r32/eax +3597 # +3598 (lookup-var-helper %ecx *(ebp+0xc)) # => eax +3599 { +3600 # if (result != 0) return +3601 3d/compare-eax-and 0/imm32 +3602 75/jump-if-!= break/disp8 +3603 # if name is one of fn's outputs, return it +3604 { +3605 (find-in-function-outputs *(ebp+0x10) %ecx) # => eax +3606 3d/compare-eax-and 0/imm32 +3607 # otherwise abort +3608 0f 84/jump-if-!= $lookup-var:abort/disp32 +3609 } +3610 } +3611 $lookup-or-define-var:end: +3612 # . restore registers +3613 59/pop-to-ecx +3614 # . epilogue +3615 89/<- %esp 5/r32/ebp +3616 5d/pop-to-ebp +3617 c3/return +3618 +3619 find-in-function-outputs: # fn: (handle function), name: (handle array byte) => result/eax: (handle var) +3620 # . prologue +3621 55/push-ebp +3622 89/<- %ebp 4/r32/esp +3623 # . save registers +3624 51/push-ecx +3625 # var curr/ecx: (handle list var) = fn->outputs +3626 8b/-> *(ebp+8) 1/r32/ecx +3627 8b/-> *(ecx+0xc) 1/r32/ecx +3628 # while curr != null +3629 { +3630 81 7/subop/compare %ecx 0/imm32 +3631 74/jump-if-= break/disp8 +3632 # var v: (handle var) = *curr +3633 8b/-> *ecx 0/r32/eax # List-value +3634 # if (curr->name == name) return curr +3635 50/push-eax +3636 (string-equal? *eax *(ebp+0xc)) +3637 3d/compare-eax-and 0/imm32 +3638 58/pop-to-eax +3639 75/jump-if-!= $find-in-function-outputs:end/disp8 +3640 # curr = curr->next +3641 8b/-> *(ecx+4) 1/r32/ecx # List-next +3642 eb/jump loop/disp8 +3643 } +3644 b8/copy-to-eax 0/imm32 +3645 $find-in-function-outputs:end: +3646 # . restore registers +3647 59/pop-to-ecx +3648 # . epilogue +3649 89/<- %esp 5/r32/ebp +3650 5d/pop-to-ebp +3651 c3/return +3652 +3653 test-parse-mu-stmt: +3654 # . prologue +3655 55/push-ebp +3656 89/<- %ebp 4/r32/esp +3657 # setup +3658 (clear-stream _test-input-stream) +3659 (write _test-input-stream "increment n\n") +3660 # var vars/ecx: (stack (addr var) 4) +3661 81 5/subop/subtract %esp 0x10/imm32 +3662 68/push 0x10/imm32/length +3663 68/push 0/imm32/top +3664 89/<- %ecx 4/r32/esp +3665 (clear-stack %ecx) +3666 # var v/edx: var +3667 81 5/subop/subtract %esp 0x14/imm32 # Var-size +3668 89/<- %edx 4/r32/esp +3669 (zero-out %edx 0x14) +3670 # v->name = "n" +3671 c7 0/subop/copy *edx "n"/imm32 # Var-name +3672 # +3673 (push %ecx %edx) +3674 # convert +3675 (parse-mu-stmt _test-input-stream %ecx) # => eax +3676 # check result +3677 (check-ints-equal *eax 1 "F - test-parse-mu-stmt/tag") # Stmt-tag is Stmt1 +3678 (check-strings-equal *(eax+4) "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation +3679 # edx: (handle list var) = result->inouts +3680 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts +3681 # ebx: (handle var) = result->inouts->value +3682 8b/-> *edx 3/r32/ebx # List-value +3683 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt/inout:0") # Var-name +3684 # . epilogue +3685 89/<- %esp 5/r32/ebp +3686 5d/pop-to-ebp +3687 c3/return +3688 +3689 test-parse-mu-stmt-with-comma: +3690 # . prologue +3691 55/push-ebp +3692 89/<- %ebp 4/r32/esp +3693 # setup +3694 (clear-stream _test-input-stream) +3695 (write _test-input-stream "copy-to n, 3\n") +3696 # var vars/ecx: (stack (addr var) 4) +3697 81 5/subop/subtract %esp 0x10/imm32 +3698 68/push 0x10/imm32/length +3699 68/push 0/imm32/top +3700 89/<- %ecx 4/r32/esp +3701 (clear-stack %ecx) +3702 # var v/edx: var +3703 81 5/subop/subtract %esp 0x14/imm32 # Var-size +3704 89/<- %edx 4/r32/esp +3705 (zero-out %edx 0x14) +3706 # v->name = "n" +3707 c7 0/subop/copy *edx "n"/imm32 # Var-name +3708 # +3709 (push %ecx %edx) +3710 # convert +3711 (parse-mu-stmt _test-input-stream %ecx) # => eax +3712 # check result +3713 (check-ints-equal *eax 1 "F - test-parse-mu-stmt-with-comma/tag") # Stmt-tag is Stmt1 +3714 (check-strings-equal *(eax+4) "copy-to" "F - test-parse-mu-stmt-with-comma/name") # Stmt1-operation +3715 # edx: (handle list var) = result->inouts +3716 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts +3717 # ebx: (handle var) = result->inouts->value +3718 8b/-> *edx 3/r32/ebx # List-value +3719 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt-with-comma/inout:0") # Var-name +3720 # . epilogue +3721 89/<- %esp 5/r32/ebp +3722 5d/pop-to-ebp +3723 c3/return +3724 +3725 new-function: # ad: (addr allocation-descriptor), name: (addr array byte), subx-name: (addr array byte), inouts: (handle list var), outputs: (handle list var), body: (handle block), next: (handle function) -> result/eax: (handle function) +3726 # . prologue +3727 55/push-ebp +3728 89/<- %ebp 4/r32/esp +3729 # . save registers +3730 51/push-ecx +3731 # +3732 (allocate *(ebp+8) *Function-size) # => eax +3733 8b/-> *(ebp+0xc) 1/r32/ecx +3734 89/<- *eax 1/r32/ecx # Function-name +3735 8b/-> *(ebp+0x10) 1/r32/ecx +3736 89/<- *(eax+4) 1/r32/ecx # Function-subx-name +3737 8b/-> *(ebp+0x14) 1/r32/ecx +3738 89/<- *(eax+8) 1/r32/ecx # Function-inouts +3739 8b/-> *(ebp+0x18) 1/r32/ecx +3740 89/<- *(eax+0xc) 1/r32/ecx # Function-outputs +3741 8b/-> *(ebp+0x1c) 1/r32/ecx +3742 89/<- *(eax+0x10) 1/r32/ecx # Function-body +3743 8b/-> *(ebp+0x20) 1/r32/ecx +3744 89/<- *(eax+0x14) 1/r32/ecx # Function-next +3745 $new-function:end: +3746 # . restore registers +3747 59/pop-to-ecx +3748 # . epilogue +3749 89/<- %esp 5/r32/ebp +3750 5d/pop-to-ebp +3751 c3/return +3752 +3753 new-var: # ad: (addr allocation-descriptor), name: (addr array byte), type: int, block: int, stack-offset: int, register: (addr array byte) -> result/eax: (handle var) 3754 # . prologue 3755 55/push-ebp 3756 89/<- %ebp 4/r32/esp 3757 # . save registers 3758 51/push-ecx -3759 56/push-esi -3760 # esi = name -3761 8b/-> *(ebp+8) 6/r32/esi -3762 # if slice-empty?(name) abort -3763 (slice-empty? %esi) # => eax -3764 3d/compare-eax-and 0/imm32 -3765 0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32 -3766 # var c/ecx: byte = *name->start -3767 8b/-> *esi 1/r32/ecx -3768 8a/copy-byte *ecx 1/r32/CL -3769 81 4/subop/and %ecx 0xff/imm32 -3770 # if is-decimal-digit?(c) return new var(name) -3771 { -3772 (is-decimal-digit? %ecx) # => eax -3773 81 7/subop/compare %eax 0/imm32 -3774 74/jump-if-= break/disp8 -3775 (new-literal-integer Heap %esi) # => eax -3776 eb/jump $lookup-var-or-literal:end/disp8 -3777 } -3778 # else if (c == '"') return new var(name) -3779 { -3780 81 7/subop/compare %ecx 0x22/imm32/dquote -3781 75/jump-if-!= break/disp8 -3782 (new-literal-string Heap %esi) # => eax -3783 eb/jump $lookup-var-or-literal:end/disp8 -3784 } -3785 # otherwise return lookup-var(name, vars) -3786 { -3787 (lookup-var %esi *(ebp+0xc)) # => eax -3788 } -3789 $lookup-var-or-literal:end: -3790 # . restore registers -3791 5e/pop-to-esi -3792 59/pop-to-ecx -3793 # . epilogue -3794 89/<- %esp 5/r32/ebp -3795 5d/pop-to-ebp -3796 c3/return -3797 -3798 $lookup-var-or-literal:abort: -3799 (write-buffered Stderr "empty variable!") -3800 (flush Stderr) -3801 # . syscall(exit, 1) -3802 bb/copy-to-ebx 1/imm32 -3803 b8/copy-to-eax 1/imm32/exit -3804 cd/syscall 0x80/imm8 -3805 # never gets here -3806 -3807 # return first 'name' from the top (back) of 'vars' and abort if not found -3808 lookup-var: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) -3809 # . prologue -3810 55/push-ebp -3811 89/<- %ebp 4/r32/esp -3812 # var target/eax: (handle array byte) = slice-to-string(name) -3813 (slice-to-string Heap *(ebp+8)) # => eax -3814 # -3815 (lookup-var-helper %eax *(ebp+0xc)) # => eax -3816 # if (result == 0) abort -3817 3d/compare-eax-and 0/imm32 -3818 74/jump-if-= $lookup-var:abort/disp8 -3819 $lookup-var:end: -3820 # . epilogue -3821 89/<- %esp 5/r32/ebp -3822 5d/pop-to-ebp -3823 c3/return -3824 -3825 $lookup-var:abort: -3826 (write-buffered Stderr "unknown variable '") -3827 (write-slice-buffered Stderr *(ebp+8)) -3828 (write-buffered Stderr "'\n") -3829 (flush Stderr) -3830 # . syscall(exit, 1) -3831 bb/copy-to-ebx 1/imm32 -3832 b8/copy-to-eax 1/imm32/exit -3833 cd/syscall 0x80/imm8 -3834 # never gets here -3835 -3836 # return first 'name' from the top (back) of 'vars', and 0/null if not found -3837 lookup-var-helper: # name: (addr array byte), vars: (addr stack (handle var)) -> result/eax: (handle var) -3838 # pseudocode: -3839 # var curr: (addr handle var) = &vars->data[vars->top - 4] -3840 # var min = vars->data -3841 # while curr >= min -3842 # var v: (handle var) = *curr -3843 # if v->name == name -3844 # return v -3845 # return 0 -3846 # -3847 # . prologue -3848 55/push-ebp -3849 89/<- %ebp 4/r32/esp -3850 # . save registers -3851 52/push-edx -3852 53/push-ebx -3853 56/push-esi -3854 # esi = vars -3855 8b/-> *(ebp+0xc) 6/r32/esi -3856 # ebx = vars->top -3857 8b/-> *esi 3/r32/ebx -3858 # if (vars->top > vars->length) abort -3859 3b/compare 0/r32/eax *(esi+4) -3860 0f 8f/jump-if-> $lookup-var-helper:error1/disp32 -3861 # var min/edx: (addr handle var) = vars->data -3862 8d/copy-address *(esi+8) 2/r32/edx -3863 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 4] -3864 81 5/subop/subtract %ebx 4/imm32 -3865 8d/copy-address *(esi+ebx+8) 3/r32/ebx -3866 { -3867 # if (curr < min) return 0 -3868 39/compare %ebx 2/r32/edx -3869 b8/copy-to-eax 0/imm32 -3870 0f 82/jump-if-addr< break/disp32 -3871 # var v/eax: (handle var) = *curr -3872 8b/-> *ebx 0/r32/eax -3873 # if (v->name == name) return v -3874 (string-equal? *eax *(ebp+8)) # Var-name -3875 3d/compare-eax-and 0/imm32 -3876 8b/-> *ebx 0/r32/eax -3877 75/jump-if-!= break/disp8 -3878 # curr -= 4 -3879 81 5/subop/subtract %ebx 4/imm32 -3880 e9/jump loop/disp32 -3881 } -3882 $lookup-var-helper:end: -3883 # . restore registers -3884 5e/pop-to-esi -3885 5b/pop-to-ebx -3886 5a/pop-to-edx -3887 # . epilogue -3888 89/<- %esp 5/r32/ebp -3889 5d/pop-to-ebp -3890 c3/return -3891 -3892 $lookup-var-helper:error1: -3893 (write-buffered Stderr "malformed stack when looking up '") -3894 (write-slice-buffered Stderr *(ebp+8)) -3895 (write-buffered Stderr "'\n") -3896 (flush Stderr) -3897 # . syscall(exit, 1) -3898 bb/copy-to-ebx 1/imm32 -3899 b8/copy-to-eax 1/imm32/exit -3900 cd/syscall 0x80/imm8 -3901 # never gets here -3902 -3903 # return first 'name' from the top (back) of 'vars' and create a new var for a fn output if not found -3904 lookup-or-define-var: # name: (addr slice), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle var) -3905 # . prologue -3906 55/push-ebp -3907 89/<- %ebp 4/r32/esp -3908 # . save registers -3909 51/push-ecx -3910 # var target/ecx: (handle array byte) = slice-to-string(name) -3911 (slice-to-string Heap *(ebp+8)) # => eax -3912 89/<- %ecx 0/r32/eax -3913 # -3914 (lookup-var-helper %ecx *(ebp+0xc)) # => eax -3915 { -3916 # if (result != 0) return -3917 3d/compare-eax-and 0/imm32 -3918 75/jump-if-!= break/disp8 -3919 # if name is one of fn's outputs, return it -3920 { -3921 (find-in-function-outputs *(ebp+0x10) %ecx) # => eax -3922 3d/compare-eax-and 0/imm32 -3923 # otherwise abort -3924 0f 84/jump-if-!= $lookup-var:abort/disp32 -3925 } -3926 } -3927 $lookup-or-define-var:end: -3928 # . restore registers -3929 59/pop-to-ecx -3930 # . epilogue -3931 89/<- %esp 5/r32/ebp -3932 5d/pop-to-ebp -3933 c3/return -3934 -3935 find-in-function-outputs: # fn: (handle function), name: (handle array byte) => result/eax: (handle var) -3936 # . prologue -3937 55/push-ebp -3938 89/<- %ebp 4/r32/esp -3939 # . save registers -3940 51/push-ecx -3941 # var curr/ecx: (handle list var) = fn->outputs -3942 8b/-> *(ebp+8) 1/r32/ecx -3943 8b/-> *(ecx+0xc) 1/r32/ecx -3944 # while curr != null -3945 { -3946 81 7/subop/compare %ecx 0/imm32 -3947 74/jump-if-= break/disp8 -3948 # var v: (handle var) = *curr -3949 8b/-> *ecx 0/r32/eax # List-value -3950 # if (curr->name == name) return curr -3951 50/push-eax -3952 (string-equal? *eax *(ebp+0xc)) -3953 3d/compare-eax-and 0/imm32 -3954 58/pop-to-eax -3955 75/jump-if-!= $find-in-function-outputs:end/disp8 -3956 # curr = curr->next -3957 8b/-> *(ecx+4) 1/r32/ecx # List-next -3958 eb/jump loop/disp8 -3959 } -3960 b8/copy-to-eax 0/imm32 -3961 $find-in-function-outputs:end: -3962 # . restore registers -3963 59/pop-to-ecx -3964 # . epilogue -3965 89/<- %esp 5/r32/ebp -3966 5d/pop-to-ebp -3967 c3/return -3968 -3969 test-parse-mu-stmt: -3970 # 'increment n' -3971 # . prologue -3972 55/push-ebp -3973 89/<- %ebp 4/r32/esp -3974 # setup -3975 (clear-stream _test-input-stream) -3976 (write _test-input-stream "increment n\n") -3977 # var vars/ecx: (stack (addr var) 4) -3978 81 5/subop/subtract %esp 0x10/imm32 -3979 68/push 0x10/imm32/length -3980 68/push 0/imm32/top -3981 89/<- %ecx 4/r32/esp -3982 (clear-stack %ecx) -3983 # var v/edx: var -3984 81 5/subop/subtract %esp 0x14/imm32 # Var-size -3985 89/<- %edx 4/r32/esp -3986 (zero-out %edx 0x14) -3987 # v->name = "n" -3988 c7 0/subop/copy *edx "n"/imm32 # Var-name -3989 # -3990 (push %ecx %edx) -3991 # convert -3992 (parse-mu-stmt _test-input-stream %ecx) # => eax -3993 # check result -3994 (check-ints-equal *eax 1 "F - test-parse-mu-stmt/tag") # Stmt-tag is Stmt1 -3995 (check-strings-equal *(eax+4) "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation -3996 # edx: (handle list var) = result->inouts -3997 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts -3998 # ebx: (handle var) = result->inouts->value -3999 8b/-> *edx 3/r32/ebx # List-value -4000 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt/inout:0") # Var-name -4001 # . epilogue -4002 89/<- %esp 5/r32/ebp -4003 5d/pop-to-ebp -4004 c3/return -4005 -4006 test-parse-mu-stmt-with-comma: -4007 # 'increment n' -4008 # . prologue -4009 55/push-ebp -4010 89/<- %ebp 4/r32/esp -4011 # setup -4012 (clear-stream _test-input-stream) -4013 (write _test-input-stream "copy-to n, 3\n") -4014 # var vars/ecx: (stack (addr var) 4) -4015 81 5/subop/subtract %esp 0x10/imm32 -4016 68/push 0x10/imm32/length -4017 68/push 0/imm32/top -4018 89/<- %ecx 4/r32/esp -4019 (clear-stack %ecx) -4020 # var v/edx: var -4021 81 5/subop/subtract %esp 0x14/imm32 # Var-size -4022 89/<- %edx 4/r32/esp -4023 (zero-out %edx 0x14) -4024 # v->name = "n" -4025 c7 0/subop/copy *edx "n"/imm32 # Var-name -4026 # -4027 (push %ecx %edx) -4028 # convert -4029 (parse-mu-stmt _test-input-stream %ecx) # => eax -4030 # check result -4031 (check-ints-equal *eax 1 "F - test-parse-mu-stmt-with-comma/tag") # Stmt-tag is Stmt1 -4032 (check-strings-equal *(eax+4) "copy-to" "F - test-parse-mu-stmt-with-comma/name") # Stmt1-operation -4033 # edx: (handle list var) = result->inouts -4034 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts -4035 # ebx: (handle var) = result->inouts->value -4036 8b/-> *edx 3/r32/ebx # List-value -4037 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt-with-comma/inout:0") # Var-name -4038 # . epilogue -4039 89/<- %esp 5/r32/ebp -4040 5d/pop-to-ebp -4041 c3/return -4042 -4043 new-function: # ad: (addr allocation-descriptor), name: (addr array byte), subx-name: (addr array byte), inouts: (handle list var), outputs: (handle list var), body: (handle block), next: (handle function) -> result/eax: (handle function) -4044 # . prologue -4045 55/push-ebp -4046 89/<- %ebp 4/r32/esp -4047 # . save registers -4048 51/push-ecx -4049 # -4050 (allocate *(ebp+8) *Function-size) # => eax -4051 8b/-> *(ebp+0xc) 1/r32/ecx -4052 89/<- *eax 1/r32/ecx # Function-name -4053 8b/-> *(ebp+0x10) 1/r32/ecx -4054 89/<- *(eax+4) 1/r32/ecx # Function-subx-name -4055 8b/-> *(ebp+0x14) 1/r32/ecx -4056 89/<- *(eax+8) 1/r32/ecx # Function-inouts -4057 8b/-> *(ebp+0x18) 1/r32/ecx -4058 89/<- *(eax+0xc) 1/r32/ecx # Function-outputs -4059 8b/-> *(ebp+0x1c) 1/r32/ecx -4060 89/<- *(eax+0x10) 1/r32/ecx # Function-body -4061 8b/-> *(ebp+0x20) 1/r32/ecx -4062 89/<- *(eax+0x14) 1/r32/ecx # Function-next -4063 $new-function:end: -4064 # . restore registers -4065 59/pop-to-ecx -4066 # . epilogue -4067 89/<- %esp 5/r32/ebp -4068 5d/pop-to-ebp -4069 c3/return +3759 # +3760 (allocate *(ebp+8) *Var-size) # => eax +3761 8b/-> *(ebp+0xc) 1/r32/ecx +3762 89/<- *eax 1/r32/ecx # Var-name +3763 8b/-> *(ebp+0x10) 1/r32/ecx +3764 89/<- *(eax+4) 1/r32/ecx # Var-type +3765 8b/-> *(ebp+0x14) 1/r32/ecx +3766 89/<- *(eax+8) 1/r32/ecx # Var-block-depth +3767 8b/-> *(ebp+0x18) 1/r32/ecx +3768 89/<- *(eax+0xc) 1/r32/ecx # Var-stack-offset +3769 8b/-> *(ebp+0x1c) 1/r32/ecx +3770 89/<- *(eax+0x10) 1/r32/ecx # Var-register +3771 $new-var:end: +3772 # . restore registers +3773 59/pop-to-ecx +3774 # . epilogue +3775 89/<- %esp 5/r32/ebp +3776 5d/pop-to-ebp +3777 c3/return +3778 +3779 new-literal-integer: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) +3780 # . prologue +3781 55/push-ebp +3782 89/<- %ebp 4/r32/esp +3783 # . save registers +3784 51/push-ecx +3785 # if (!is-hex-int?(name)) abort +3786 (is-hex-int? *(ebp+0xc)) # => eax +3787 3d/compare-eax-and 0/imm32 +3788 0f 84/jump-if-= $new-literal-integer:abort/disp32 +3789 # var s/ecx: (addr array byte) +3790 (slice-to-string Heap *(ebp+0xc)) # => eax +3791 89/<- %ecx 0/r32/eax +3792 # result/ecx = new var(s) +3793 (allocate *(ebp+8) *Var-size) # => eax +3794 (zero-out %eax *Var-size) +3795 89/<- *eax 1/r32/ecx # Var-name +3796 89/<- %ecx 0/r32/eax +3797 # result->type = new type() +3798 (allocate *(ebp+8) *Tree-size) # => eax +3799 (zero-out %eax *Tree-size) # default type is 'literal' +3800 89/<- *(ecx+4) 0/r32/eax # Var-type +3801 # move result to eax +3802 89/<- %eax 1/r32/ecx +3803 $new-literal-integer:end: +3804 # . restore registers +3805 59/pop-to-ecx +3806 # . epilogue +3807 89/<- %esp 5/r32/ebp +3808 5d/pop-to-ebp +3809 c3/return +3810 +3811 $new-literal-integer:abort: +3812 (write-buffered Stderr "variable cannot begin with a digit '") +3813 (write-slice-buffered Stderr *(ebp+0xc)) +3814 (write-buffered Stderr "'\n") +3815 (flush Stderr) +3816 # . syscall(exit, 1) +3817 bb/copy-to-ebx 1/imm32 +3818 b8/copy-to-eax 1/imm32/exit +3819 cd/syscall 0x80/imm8 +3820 # never gets here +3821 +3822 new-literal-string: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) +3823 # . prologue +3824 55/push-ebp +3825 89/<- %ebp 4/r32/esp +3826 # . save registers +3827 51/push-ecx +3828 # var s/ecx: (addr array byte) +3829 (slice-to-string Heap *(ebp+0xc)) # => eax +3830 89/<- %ecx 0/r32/eax +3831 # result/ecx = new var(s) +3832 (allocate *(ebp+8) *Var-size) # => eax +3833 (zero-out %eax) +3834 89/<- *eax 1/r32/ecx # Var-name +3835 89/<- %ecx 0/r32/eax +3836 # result->type = new type() +3837 (allocate *(ebp+8) *Tree-size) # => eax +3838 (zero-out %eax) # default type is 'literal' +3839 89/<- *(ecx+4) 0/r32/eax # Var-type +3840 # move result to eax +3841 89/<- %eax 1/r32/ecx +3842 $new-literal-string:end: +3843 # . restore registers +3844 59/pop-to-ecx +3845 # . epilogue +3846 89/<- %esp 5/r32/ebp +3847 5d/pop-to-ebp +3848 c3/return +3849 +3850 new-label: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) +3851 # . prologue +3852 55/push-ebp +3853 89/<- %ebp 4/r32/esp +3854 # . save registers +3855 51/push-ecx +3856 # var s/ecx: (addr array byte) +3857 (slice-to-string Heap *(ebp+0xc)) # => eax +3858 89/<- %ecx 0/r32/eax +3859 # +3860 (allocate *(ebp+8) *Var-size) # => eax +3861 89/<- *eax 1/r32/ecx # Var-name +3862 89/<- %ecx 0/r32/eax +3863 (allocate *(ebp+8) *Tree-size) # => eax +3864 89/<- *(ecx+4) 0/r32/eax # Var-type +3865 89/<- %eax 1/r32/ecx +3866 c7 0/subop/copy *(eax+8) 0/imm32 # Var-block-depth +3867 c7 0/subop/copy *(eax+0xc) 0/imm32 # Var-stack-offset +3868 c7 0/subop/copy *(eax+0x10) 0/imm32 # Var-register +3869 $new-label:end: +3870 # . restore registers +3871 59/pop-to-ecx +3872 # . epilogue +3873 89/<- %esp 5/r32/ebp +3874 5d/pop-to-ebp +3875 c3/return +3876 +3877 new-block: # ad: (addr allocation-descriptor), data: (handle list statement) -> result/eax: (handle statement) +3878 # . prologue +3879 55/push-ebp +3880 89/<- %ebp 4/r32/esp +3881 # . save registers +3882 51/push-ecx +3883 # +3884 (allocate *(ebp+8) *Stmt-size) # => eax +3885 (zero-out %eax *Stmt-size) +3886 c7 0/subop/copy *eax 0/imm32/tag/block # Stmt-tag +3887 8b/-> *(ebp+0xc) 1/r32/ecx +3888 89/<- *(eax+4) 1/r32/ecx # Block-statements +3889 $new-block:end: +3890 # . restore registers +3891 59/pop-to-ecx +3892 # . epilogue +3893 89/<- %esp 5/r32/ebp +3894 5d/pop-to-ebp +3895 c3/return +3896 +3897 new-vardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) +3898 # . prologue +3899 55/push-ebp +3900 89/<- %ebp 4/r32/esp +3901 # . save registers +3902 51/push-ecx +3903 # +3904 (allocate *(ebp+8) *Stmt-size) # => eax +3905 (zero-out %eax *Stmt-size) +3906 c7 0/subop/copy *eax 2/imm32/tag/var-on-stack # Stmt-tag +3907 # result->var = var +3908 8b/-> *(ebp+0xc) 1/r32/ecx +3909 89/<- *(eax+4) 1/r32/ecx # Vardef-var +3910 $new-vardef:end: +3911 # . restore registers +3912 59/pop-to-ecx +3913 # . epilogue +3914 89/<- %esp 5/r32/ebp +3915 5d/pop-to-ebp +3916 c3/return +3917 +3918 new-regvardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) +3919 # . prologue +3920 55/push-ebp +3921 89/<- %ebp 4/r32/esp +3922 # . save registers +3923 51/push-ecx +3924 57/push-edi +3925 # ecx = var +3926 8b/-> *(ebp+0xc) 1/r32/ecx +3927 # edi = result +3928 (allocate *(ebp+8) *Stmt-size) # => eax +3929 89/<- %edi 0/r32/eax +3930 (zero-out %edi *Stmt-size) +3931 # set tag +3932 c7 0/subop/copy *edi 3/imm32/tag/var-in-register # Stmt-tag +3933 # set output +3934 (append-list Heap %ecx *(edi+0xc)) # Regvardef-outputs => eax +3935 89/<- *(edi+0xc) 0/r32/eax # Regvardef-outputs +3936 $new-regvardef:end: +3937 89/<- %eax 7/r32/edi +3938 # . restore registers +3939 5f/pop-to-edi +3940 59/pop-to-ecx +3941 # . epilogue +3942 89/<- %esp 5/r32/ebp +3943 5d/pop-to-ebp +3944 c3/return +3945 +3946 new-named-block: # ad: (addr allocation-descriptor), name: (addr array byte), data: (handle list statement) -> result/eax: (handle statement) +3947 # . prologue +3948 55/push-ebp +3949 89/<- %ebp 4/r32/esp +3950 # . save registers +3951 51/push-ecx +3952 # +3953 (allocate *(ebp+8) *Stmt-size) # => eax +3954 (zero-out %eax *Stmt-size) +3955 c7 0/subop/copy *eax 4/imm32/tag/named-block +3956 8b/-> *(ebp+0xc) 1/r32/ecx +3957 89/<- *(eax+8) 1/r32/ecx # Named-block-name +3958 8b/-> *(ebp+0x10) 1/r32/ecx +3959 89/<- *(eax+4) 1/r32/ecx # Named-block-statements +3960 $new-named-block:end: +3961 # . restore registers +3962 59/pop-to-ecx +3963 # . epilogue +3964 89/<- %esp 5/r32/ebp +3965 5d/pop-to-ebp +3966 c3/return +3967 +3968 new-list: # ad: (addr allocation-descriptor), value: _type, next: (handle list _type) -> result/eax: (handle list _type) +3969 # . prologue +3970 55/push-ebp +3971 89/<- %ebp 4/r32/esp +3972 # . save registers +3973 51/push-ecx +3974 # +3975 (allocate *(ebp+8) *List-size) # => eax +3976 8b/-> *(ebp+0xc) 1/r32/ecx +3977 89/<- *eax 1/r32/ecx # List-value +3978 8b/-> *(ebp+0x10) 1/r32/ecx +3979 89/<- *(eax+4) 1/r32/ecx # List-next +3980 $new-list:end: +3981 # . restore registers +3982 59/pop-to-ecx +3983 # . epilogue +3984 89/<- %esp 5/r32/ebp +3985 5d/pop-to-ebp +3986 c3/return +3987 +3988 append-list: # ad: (addr allocation-descriptor), value: _type, list: (handle list _type) -> result/eax: (handle list _type) +3989 # . prologue +3990 55/push-ebp +3991 89/<- %ebp 4/r32/esp +3992 # . save registers +3993 51/push-ecx +3994 # +3995 (allocate *(ebp+8) *List-size) # => eax +3996 8b/-> *(ebp+0xc) 1/r32/ecx +3997 89/<- *eax 1/r32/ecx # List-value +3998 # if (list == null) return result +3999 81 7/subop/compare *(ebp+0x10) 0/imm32 +4000 74/jump-if-= $new-list:end/disp8 +4001 # otherwise append +4002 # var curr/ecx = list +4003 8b/-> *(ebp+0x10) 1/r32/ecx +4004 # while (curr->next != null) curr = curr->next +4005 { +4006 81 7/subop/compare *(ecx+4) 0/imm32 # List-next +4007 74/jump-if-= break/disp8 +4008 # curr = curr->next +4009 8b/-> *(ecx+4) 1/r32/ecx +4010 eb/jump loop/disp8 +4011 } +4012 # curr->next = result +4013 89/<- *(ecx+4) 0/r32/eax +4014 # return list +4015 8b/-> *(ebp+0x10) 0/r32/eax +4016 $append-list:end: +4017 # . restore registers +4018 59/pop-to-ecx +4019 # . epilogue +4020 89/<- %esp 5/r32/ebp +4021 5d/pop-to-ebp +4022 c3/return +4023 +4024 append-to-block: # ad: (addr allocation-descriptor), block: (handle block), x: (handle stmt) +4025 # . prologue +4026 55/push-ebp +4027 89/<- %ebp 4/r32/esp +4028 # . save registers +4029 56/push-esi +4030 # esi = block +4031 8b/-> *(ebp+0xc) 6/r32/esi +4032 (append-list *(ebp+8) *(ebp+0x10) *(esi+4)) # ad, x, Block-statements +4033 89/<- *(esi+4) 0/r32/eax # Block-statements +4034 $append-to-block:end: +4035 # . restore registers +4036 5e/pop-to-esi +4037 # . epilogue +4038 89/<- %esp 5/r32/ebp +4039 5d/pop-to-ebp +4040 c3/return +4041 +4042 ####################################################### +4043 # Type-checking +4044 ####################################################### +4045 +4046 check-mu-types: +4047 # . prologue +4048 55/push-ebp +4049 89/<- %ebp 4/r32/esp +4050 # +4051 $check-mu-types:end: +4052 # . epilogue +4053 89/<- %esp 5/r32/ebp +4054 5d/pop-to-ebp +4055 c3/return +4056 +4057 size-of: # n: (addr var) -> result/eax: int +4058 # . prologue +4059 55/push-ebp +4060 89/<- %ebp 4/r32/esp +4061 # hard-coded since we only support 'int' types for now +4062 b8/copy-to-eax 4/imm32 +4063 $size-of:end: +4064 # . epilogue +4065 89/<- %esp 5/r32/ebp +4066 5d/pop-to-ebp +4067 c3/return +4068 +4069 == data 4070 -4071 new-var: # ad: (addr allocation-descriptor), name: (addr array byte), type: int, block: int, stack-offset: int, register: (addr array byte) -> result/eax: (handle var) -4072 # . prologue -4073 55/push-ebp -4074 89/<- %ebp 4/r32/esp -4075 # . save registers -4076 51/push-ecx -4077 # -4078 (allocate *(ebp+8) *Var-size) # => eax -4079 8b/-> *(ebp+0xc) 1/r32/ecx -4080 89/<- *eax 1/r32/ecx # Var-name -4081 8b/-> *(ebp+0x10) 1/r32/ecx -4082 89/<- *(eax+4) 1/r32/ecx # Var-type -4083 8b/-> *(ebp+0x14) 1/r32/ecx -4084 89/<- *(eax+8) 1/r32/ecx # Var-block-depth -4085 8b/-> *(ebp+0x18) 1/r32/ecx -4086 89/<- *(eax+0xc) 1/r32/ecx # Var-stack-offset -4087 8b/-> *(ebp+0x1c) 1/r32/ecx -4088 89/<- *(eax+0x10) 1/r32/ecx # Var-register -4089 $new-var:end: -4090 # . restore registers -4091 59/pop-to-ecx -4092 # . epilogue -4093 89/<- %esp 5/r32/ebp -4094 5d/pop-to-ebp -4095 c3/return -4096 -4097 new-literal-integer: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -4098 # . prologue -4099 55/push-ebp -4100 89/<- %ebp 4/r32/esp -4101 # . save registers -4102 51/push-ecx -4103 # if (!is-hex-int?(name)) abort -4104 (is-hex-int? *(ebp+0xc)) # => eax -4105 3d/compare-eax-and 0/imm32 -4106 0f 84/jump-if-= $new-literal-integer:abort/disp32 -4107 # var s/ecx: (addr array byte) -4108 (slice-to-string Heap *(ebp+0xc)) # => eax -4109 89/<- %ecx 0/r32/eax -4110 # result/ecx = new var(s) -4111 (allocate *(ebp+8) *Var-size) # => eax -4112 (zero-out %eax *Var-size) -4113 89/<- *eax 1/r32/ecx # Var-name -4114 89/<- %ecx 0/r32/eax -4115 # result->type = new type() -4116 (allocate *(ebp+8) *Tree-size) # => eax -4117 (zero-out %eax *Tree-size) # default type is 'literal' -4118 89/<- *(ecx+4) 0/r32/eax # Var-type -4119 # move result to eax -4120 89/<- %eax 1/r32/ecx -4121 $new-literal-integer:end: +4071 # not yet used, but it will be +4072 Type-size: # (stream int) +4073 0x18/imm32/write +4074 0/imm32/read +4075 0x100/imm32/length +4076 # data +4077 4/imm32 # literal +4078 4/imm32 # int +4079 4/imm32 # addr +4080 0/imm32 # array (logic elsewhere) +4081 8/imm32 # handle (fat pointer) +4082 4/imm32 # bool +4083 0/imm32 +4084 0/imm32 +4085 # 0x20 +4086 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4087 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4088 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4089 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4090 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4091 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4092 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4093 +4094 == code +4095 +4096 ####################################################### +4097 # Code-generation +4098 ####################################################### +4099 +4100 emit-subx: # out: (addr buffered-file) +4101 # . prologue +4102 55/push-ebp +4103 89/<- %ebp 4/r32/esp +4104 # . save registers +4105 50/push-eax +4106 51/push-ecx +4107 57/push-edi +4108 # edi = out +4109 8b/-> *(ebp+8) 7/r32/edi +4110 # var curr/ecx: (handle function) = *Program +4111 8b/-> *Program 1/r32/ecx +4112 { +4113 # if (curr == null) break +4114 81 7/subop/compare %ecx 0/imm32 +4115 0f 84/jump-if-= break/disp32 +4116 (emit-subx-function %edi %ecx) +4117 # curr = curr->next +4118 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next +4119 e9/jump loop/disp32 +4120 } +4121 $emit-subx:end: 4122 # . restore registers -4123 59/pop-to-ecx -4124 # . epilogue -4125 89/<- %esp 5/r32/ebp -4126 5d/pop-to-ebp -4127 c3/return -4128 -4129 $new-literal-integer:abort: -4130 (write-buffered Stderr "variable cannot begin with a digit '") -4131 (write-slice-buffered Stderr *(ebp+0xc)) -4132 (write-buffered Stderr "'\n") -4133 (flush Stderr) -4134 # . syscall(exit, 1) -4135 bb/copy-to-ebx 1/imm32 -4136 b8/copy-to-eax 1/imm32/exit -4137 cd/syscall 0x80/imm8 -4138 # never gets here -4139 -4140 new-literal-string: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -4141 # . prologue -4142 55/push-ebp -4143 89/<- %ebp 4/r32/esp -4144 # . save registers -4145 51/push-ecx -4146 # var s/ecx: (addr array byte) -4147 (slice-to-string Heap *(ebp+0xc)) # => eax -4148 89/<- %ecx 0/r32/eax -4149 # result/ecx = new var(s) -4150 (allocate *(ebp+8) *Var-size) # => eax -4151 (zero-out %eax) -4152 89/<- *eax 1/r32/ecx # Var-name -4153 89/<- %ecx 0/r32/eax -4154 # result->type = new type() -4155 (allocate *(ebp+8) *Tree-size) # => eax -4156 (zero-out %eax) # default type is 'literal' -4157 89/<- *(ecx+4) 0/r32/eax # Var-type -4158 # move result to eax -4159 89/<- %eax 1/r32/ecx -4160 $new-literal-string:end: -4161 # . restore registers +4123 5f/pop-to-edi +4124 59/pop-to-ecx +4125 58/pop-to-eax +4126 # . epilogue +4127 89/<- %esp 5/r32/ebp +4128 5d/pop-to-ebp +4129 c3/return +4130 +4131 emit-subx-function: # out: (addr buffered-file), f: (handle function) +4132 # . prologue +4133 55/push-ebp +4134 89/<- %ebp 4/r32/esp +4135 # . save registers +4136 50/push-eax +4137 51/push-ecx +4138 52/push-edx +4139 57/push-edi +4140 # edi = out +4141 8b/-> *(ebp+8) 7/r32/edi +4142 # ecx = f +4143 8b/-> *(ebp+0xc) 1/r32/ecx +4144 # var vars/edx: (stack (addr var) 256) +4145 81 5/subop/subtract %esp 0x400/imm32 +4146 68/push 0x400/imm32/length +4147 68/push 0/imm32/top +4148 89/<- %edx 4/r32/esp +4149 # +4150 (write-buffered %edi *ecx) +4151 (write-buffered %edi ":\n") +4152 c7 0/subop/copy *Curr-block-depth 1/imm32 +4153 (emit-subx-prologue %edi) +4154 (emit-subx-block %edi *(ecx+0x10) %edx) # Function-body +4155 (emit-subx-epilogue %edi) +4156 $emit-subx-function:end: +4157 # . reclaim locals +4158 81 0/subop/add %esp 408/imm32 +4159 # . restore registers +4160 5f/pop-to-edi +4161 5a/pop-to-edx 4162 59/pop-to-ecx -4163 # . epilogue -4164 89/<- %esp 5/r32/ebp -4165 5d/pop-to-ebp -4166 c3/return -4167 -4168 new-label: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -4169 # . prologue -4170 55/push-ebp -4171 89/<- %ebp 4/r32/esp -4172 # . save registers -4173 51/push-ecx -4174 # var s/ecx: (addr array byte) -4175 (slice-to-string Heap *(ebp+0xc)) # => eax -4176 89/<- %ecx 0/r32/eax -4177 # -4178 (allocate *(ebp+8) *Var-size) # => eax -4179 89/<- *eax 1/r32/ecx # Var-name -4180 89/<- %ecx 0/r32/eax -4181 (allocate *(ebp+8) *Tree-size) # => eax -4182 89/<- *(ecx+4) 0/r32/eax # Var-type -4183 89/<- %eax 1/r32/ecx -4184 c7 0/subop/copy *(eax+8) 0/imm32 # Var-block-depth -4185 c7 0/subop/copy *(eax+0xc) 0/imm32 # Var-stack-offset -4186 c7 0/subop/copy *(eax+0x10) 0/imm32 # Var-register -4187 $new-label:end: -4188 # . restore registers -4189 59/pop-to-ecx -4190 # . epilogue -4191 89/<- %esp 5/r32/ebp -4192 5d/pop-to-ebp -4193 c3/return -4194 -4195 new-block: # ad: (addr allocation-descriptor), data: (handle list statement) -> result/eax: (handle statement) -4196 # . prologue -4197 55/push-ebp -4198 89/<- %ebp 4/r32/esp -4199 # . save registers -4200 51/push-ecx -4201 # -4202 (allocate *(ebp+8) *Stmt-size) # => eax -4203 (zero-out %eax *Stmt-size) -4204 c7 0/subop/copy *eax 0/imm32/tag/block # Stmt-tag -4205 8b/-> *(ebp+0xc) 1/r32/ecx -4206 89/<- *(eax+4) 1/r32/ecx # Block-statements -4207 $new-block:end: -4208 # . restore registers -4209 59/pop-to-ecx -4210 # . epilogue -4211 89/<- %esp 5/r32/ebp -4212 5d/pop-to-ebp -4213 c3/return -4214 -4215 new-vardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) -4216 # . prologue -4217 55/push-ebp -4218 89/<- %ebp 4/r32/esp -4219 # . save registers -4220 51/push-ecx -4221 # -4222 (allocate *(ebp+8) *Stmt-size) # => eax -4223 (zero-out %eax *Stmt-size) -4224 c7 0/subop/copy *eax 2/imm32/tag/var-on-stack # Stmt-tag -4225 # result->var = var -4226 8b/-> *(ebp+0xc) 1/r32/ecx -4227 89/<- *(eax+4) 1/r32/ecx # Vardef-var -4228 $new-vardef:end: -4229 # . restore registers -4230 59/pop-to-ecx -4231 # . epilogue -4232 89/<- %esp 5/r32/ebp -4233 5d/pop-to-ebp -4234 c3/return -4235 -4236 new-regvardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) -4237 # . prologue -4238 55/push-ebp -4239 89/<- %ebp 4/r32/esp -4240 # . save registers -4241 51/push-ecx -4242 57/push-edi -4243 # ecx = var -4244 8b/-> *(ebp+0xc) 1/r32/ecx -4245 # edi = result -4246 (allocate *(ebp+8) *Stmt-size) # => eax -4247 89/<- %edi 0/r32/eax -4248 (zero-out %edi *Stmt-size) -4249 # set tag -4250 c7 0/subop/copy *edi 3/imm32/tag/var-in-register # Stmt-tag -4251 # set output -4252 (append-list Heap %ecx *(edi+0xc)) # Regvardef-outputs => eax -4253 89/<- *(edi+0xc) 0/r32/eax # Regvardef-outputs -4254 $new-regvardef:end: -4255 89/<- %eax 7/r32/edi -4256 # . restore registers -4257 5f/pop-to-edi -4258 59/pop-to-ecx -4259 # . epilogue -4260 89/<- %esp 5/r32/ebp -4261 5d/pop-to-ebp -4262 c3/return -4263 -4264 new-named-block: # ad: (addr allocation-descriptor), name: (addr array byte), data: (handle list statement) -> result/eax: (handle statement) -4265 # . prologue -4266 55/push-ebp -4267 89/<- %ebp 4/r32/esp -4268 # . save registers -4269 51/push-ecx -4270 # -4271 (allocate *(ebp+8) *Stmt-size) # => eax -4272 (zero-out %eax *Stmt-size) -4273 c7 0/subop/copy *eax 4/imm32/tag/named-block -4274 8b/-> *(ebp+0xc) 1/r32/ecx -4275 89/<- *(eax+8) 1/r32/ecx # Named-block-name -4276 8b/-> *(ebp+0x10) 1/r32/ecx -4277 89/<- *(eax+4) 1/r32/ecx # Named-block-statements -4278 $new-named-block:end: -4279 # . restore registers -4280 59/pop-to-ecx -4281 # . epilogue -4282 89/<- %esp 5/r32/ebp -4283 5d/pop-to-ebp -4284 c3/return -4285 -4286 new-list: # ad: (addr allocation-descriptor), value: _type, next: (handle list _type) -> result/eax: (handle list _type) -4287 # . prologue -4288 55/push-ebp -4289 89/<- %ebp 4/r32/esp -4290 # . save registers -4291 51/push-ecx -4292 # -4293 (allocate *(ebp+8) *List-size) # => eax -4294 8b/-> *(ebp+0xc) 1/r32/ecx -4295 89/<- *eax 1/r32/ecx # List-value -4296 8b/-> *(ebp+0x10) 1/r32/ecx -4297 89/<- *(eax+4) 1/r32/ecx # List-next -4298 $new-list:end: -4299 # . restore registers -4300 59/pop-to-ecx -4301 # . epilogue -4302 89/<- %esp 5/r32/ebp -4303 5d/pop-to-ebp -4304 c3/return -4305 -4306 append-list: # ad: (addr allocation-descriptor), value: _type, list: (handle list _type) -> result/eax: (handle list _type) -4307 # . prologue -4308 55/push-ebp -4309 89/<- %ebp 4/r32/esp -4310 # . save registers -4311 51/push-ecx -4312 # -4313 (allocate *(ebp+8) *List-size) # => eax -4314 8b/-> *(ebp+0xc) 1/r32/ecx -4315 89/<- *eax 1/r32/ecx # List-value -4316 # if (list == null) return result -4317 81 7/subop/compare *(ebp+0x10) 0/imm32 -4318 74/jump-if-= $new-list:end/disp8 -4319 # otherwise append -4320 # var curr/ecx = list -4321 8b/-> *(ebp+0x10) 1/r32/ecx -4322 # while (curr->next != null) curr = curr->next -4323 { -4324 81 7/subop/compare *(ecx+4) 0/imm32 # List-next -4325 74/jump-if-= break/disp8 -4326 # curr = curr->next -4327 8b/-> *(ecx+4) 1/r32/ecx -4328 eb/jump loop/disp8 -4329 } -4330 # curr->next = result -4331 89/<- *(ecx+4) 0/r32/eax -4332 # return list -4333 8b/-> *(ebp+0x10) 0/r32/eax -4334 $append-list:end: -4335 # . restore registers -4336 59/pop-to-ecx -4337 # . epilogue -4338 89/<- %esp 5/r32/ebp -4339 5d/pop-to-ebp -4340 c3/return -4341 -4342 append-to-block: # ad: (addr allocation-descriptor), block: (handle block), x: (handle stmt) -4343 # . prologue -4344 55/push-ebp -4345 89/<- %ebp 4/r32/esp -4346 # . save registers -4347 56/push-esi -4348 # esi = block -4349 8b/-> *(ebp+0xc) 6/r32/esi -4350 (append-list *(ebp+8) *(ebp+0x10) *(esi+4)) # ad, x, Block-statements -4351 89/<- *(esi+4) 0/r32/eax # Block-statements -4352 $append-to-block:end: -4353 # . restore registers -4354 5e/pop-to-esi -4355 # . epilogue -4356 89/<- %esp 5/r32/ebp -4357 5d/pop-to-ebp -4358 c3/return -4359 -4360 ####################################################### -4361 # Type-checking -4362 ####################################################### -4363 -4364 check-mu-types: -4365 # . prologue -4366 55/push-ebp -4367 89/<- %ebp 4/r32/esp -4368 # -4369 $check-mu-types:end: -4370 # . epilogue -4371 89/<- %esp 5/r32/ebp -4372 5d/pop-to-ebp -4373 c3/return -4374 -4375 size-of: # n: (addr var) -> result/eax: int -4376 # . prologue -4377 55/push-ebp -4378 89/<- %ebp 4/r32/esp -4379 # hard-coded since we only support 'int' types for now -4380 b8/copy-to-eax 4/imm32 -4381 $size-of:end: -4382 # . epilogue -4383 89/<- %esp 5/r32/ebp -4384 5d/pop-to-ebp -4385 c3/return -4386 -4387 == data -4388 -4389 # not yet used, but it will be -4390 Type-size: # (stream int) -4391 0x18/imm32/write -4392 0/imm32/read -4393 0x100/imm32/length -4394 # data -4395 4/imm32 # literal -4396 4/imm32 # int -4397 4/imm32 # addr -4398 0/imm32 # array (logic elsewhere) -4399 8/imm32 # handle (fat pointer) -4400 4/imm32 # bool -4401 0/imm32 -4402 0/imm32 -4403 # 0x20 -4404 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4405 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4406 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4407 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4408 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4409 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4410 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4411 -4412 == code -4413 -4414 ####################################################### -4415 # Code-generation -4416 ####################################################### -4417 -4418 emit-subx: # out: (addr buffered-file) -4419 # . prologue -4420 55/push-ebp -4421 89/<- %ebp 4/r32/esp -4422 # . save registers -4423 50/push-eax -4424 51/push-ecx -4425 57/push-edi -4426 # edi = out -4427 8b/-> *(ebp+8) 7/r32/edi -4428 # var curr/ecx: (handle function) = *Program -4429 8b/-> *Program 1/r32/ecx -4430 { -4431 # if (curr == null) break -4432 81 7/subop/compare %ecx 0/imm32 -4433 0f 84/jump-if-= break/disp32 -4434 (emit-subx-function %edi %ecx) -4435 # curr = curr->next -4436 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next -4437 e9/jump loop/disp32 -4438 } -4439 $emit-subx:end: -4440 # . restore registers -4441 5f/pop-to-edi -4442 59/pop-to-ecx -4443 58/pop-to-eax -4444 # . epilogue -4445 89/<- %esp 5/r32/ebp -4446 5d/pop-to-ebp -4447 c3/return -4448 -4449 emit-subx-function: # out: (addr buffered-file), f: (handle function) -4450 # . prologue -4451 55/push-ebp -4452 89/<- %ebp 4/r32/esp -4453 # . save registers -4454 50/push-eax -4455 51/push-ecx -4456 52/push-edx -4457 57/push-edi -4458 # edi = out -4459 8b/-> *(ebp+8) 7/r32/edi -4460 # ecx = f -4461 8b/-> *(ebp+0xc) 1/r32/ecx -4462 # var vars/edx: (stack (addr var) 256) -4463 81 5/subop/subtract %esp 0x400/imm32 -4464 68/push 0x400/imm32/length -4465 68/push 0/imm32/top -4466 89/<- %edx 4/r32/esp -4467 # -4468 (write-buffered %edi *ecx) -4469 (write-buffered %edi ":\n") -4470 c7 0/subop/copy *Curr-block-depth 1/imm32 -4471 (emit-subx-prologue %edi) -4472 (emit-subx-block %edi *(ecx+0x10) %edx) # Function-body -4473 (emit-subx-epilogue %edi) -4474 $emit-subx-function:end: -4475 # . reclaim locals -4476 81 0/subop/add %esp 408/imm32 -4477 # . restore registers -4478 5f/pop-to-edi -4479 5a/pop-to-edx -4480 59/pop-to-ecx -4481 58/pop-to-eax -4482 # . epilogue -4483 89/<- %esp 5/r32/ebp -4484 5d/pop-to-ebp -4485 c3/return -4486 -4487 emit-subx-block: # out: (addr buffered-file), block: (handle block), vars: (addr stack (handle var)) -4488 # . prologue -4489 55/push-ebp -4490 89/<- %ebp 4/r32/esp -4491 # . save registers -4492 56/push-esi -4493 # var stmts/esi: (handle list statement) = block->statements -4494 8b/-> *(ebp+0xc) 6/r32/esi -4495 8b/-> *(esi+4) 6/r32/esi # Block-statements -4496 # -4497 { -4498 $emit-subx-block:check-empty: -4499 81 7/subop/compare %esi 0/imm32 -4500 0f 84/jump-if-= break/disp32 -4501 (emit-indent *(ebp+8) *Curr-block-depth) -4502 (write-buffered *(ebp+8) "{\n") -4503 ff 0/subop/increment *Curr-block-depth -4504 (emit-subx-stmt-list *(ebp+8) %esi *(ebp+0x10)) -4505 ff 1/subop/decrement *Curr-block-depth -4506 (emit-indent *(ebp+8) *Curr-block-depth) -4507 (write-buffered *(ebp+8) "}\n") -4508 } -4509 $emit-subx-block:end: -4510 # . restore registers -4511 5e/pop-to-esi -4512 # . epilogue -4513 89/<- %esp 5/r32/ebp -4514 5d/pop-to-ebp -4515 c3/return -4516 -4517 emit-subx-stmt-list: # out: (addr buffered-file), stmts: (handle list stmt), vars: (addr stack (handle var)) -4518 # . prologue -4519 55/push-ebp -4520 89/<- %ebp 4/r32/esp -4521 # . save registers -4522 50/push-eax -4523 51/push-ecx -4524 56/push-esi -4525 # esi = stmts -4526 8b/-> *(ebp+0xc) 6/r32/esi -4527 # -4528 { -4529 $emit-subx-stmt-list:loop: -4530 81 7/subop/compare %esi 0/imm32 -4531 0f 84/jump-if-= break/disp32 -4532 # var curr-stmt/ecx = stmts->value -4533 8b/-> *esi 1/r32/ecx # List-value -4534 { -4535 $emit-subx-stmt-list:check-for-block: -4536 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag -4537 75/jump-if-!= break/disp8 -4538 $emit-subx-stmt-list:block: -4539 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10)) -4540 } -4541 { -4542 $emit-subx-stmt-list:check-for-stmt: -4543 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag -4544 75/jump-if-!= break/disp8 -4545 $emit-subx-stmt-list:stmt: -4546 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) -4547 } -4548 { -4549 $emit-subx-stmt-list:check-for-vardef: -4550 81 7/subop/compare *ecx 2/imm32/vardef # Stmt-tag -4551 75/jump-if-!= break/disp8 -4552 $emit-subx-stmt-list:vardef: -4553 (emit-subx-var-def *(ebp+8) %ecx) -4554 (push *(ebp+0x10) *(ecx+4)) # Vardef-var -4555 } -4556 { -4557 $emit-subx-stmt-list:check-for-regvardef: -4558 81 7/subop/compare *ecx 3/imm32/regvardef # Stmt-tag -4559 0f 85/jump-if-!= break/disp32 -4560 $emit-subx-stmt-list:regvardef: -4561 # TODO: ensure that there's exactly one output -4562 # var output/eax: (handle var) = curr-stmt->outputs->value -4563 8b/-> *(ecx+0xc) 0/r32/eax -4564 8b/-> *eax 0/r32/eax -4565 # ensure that output is in a register -4566 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -4567 0f 84/jump-if-= $emit-subx-stmt-list:abort-regvardef-without-register/disp32 -4568 # emit spill -4569 (emit-indent *(ebp+8) *Curr-block-depth) -4570 (write-buffered *(ebp+8) "ff 6/subop/push %") -4571 (write-buffered *(ebp+8) *(eax+0x10)) -4572 (write-buffered *(ebp+8) Newline) -4573 # register variable definition -4574 (push *(ebp+0x10) %eax) -4575 # emit the instruction as usual -4576 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) -4577 } -4578 { -4579 $emit-subx-stmt-list:check-for-named-block: -4580 81 7/subop/compare *ecx 4/imm32/named-block # Stmt-tag -4581 75/jump-if-!= break/disp8 -4582 $emit-subx-stmt-list:named-block: -4583 (emit-subx-named-block *(ebp+8) %ecx *(ebp+0x10)) -4584 } -4585 8b/-> *(esi+4) 6/r32/esi # List-next -4586 e9/jump loop/disp32 -4587 } -4588 # reclaim locals -4589 { -4590 $emit-subx-stmt-list:reclaim-loop: -4591 8b/-> *(ebp+0x10) 0/r32/eax -4592 81 7/subop/compare *eax 0/imm32 # Stack-top -4593 0f 84/jump-if-= break/disp32 -4594 # var v/ecx : (handle var) = top(vars) -4595 (top %eax) # => eax -4596 89/<- %ecx 0/r32/eax -4597 # if v->block-depth == *Curr-block-depth -4598 8b/-> *Curr-block-depth 0/r32/eax -4599 39/compare *(ecx+8) 0/r32/eax # Var-block-depth -4600 0f 85/jump-if-!= break/disp32 -4601 # if v is in a register -4602 81 7/subop/compare *(ecx+0x10) 0/imm32 # Var-register -4603 { -4604 74/jump-if-= break/disp8 -4605 $emit-subx-stmt-list:reclaim-var-in-register: -4606 (emit-indent *(ebp+8) *Curr-block-depth) -4607 (write-buffered *(ebp+8) "8f 0/subop/pop %") -4608 (write-buffered *(ebp+8) *(ecx+0x10)) -4609 (write-buffered *(ebp+8) Newline) -4610 } -4611 # if v is on the stack -4612 { -4613 75/jump-if-!= break/disp8 -4614 $emit-subx-stmt-list:reclaim-var-on-stack: -4615 (size-of %ecx) # => eax -4616 01/add *Next-local-stack-offset 0/r32/eax -4617 (emit-indent *(ebp+8) *Curr-block-depth) -4618 (write-buffered *(ebp+8) "81 0/subop/add %esp ") -4619 (print-int32-buffered *(ebp+8) %eax) -4620 (write-buffered *(ebp+8) "/imm32\n") -4621 } -4622 # -4623 (pop *(ebp+0x10)) -4624 e9/jump loop/disp32 -4625 } -4626 $emit-subx-stmt-list:end: -4627 # . restore registers -4628 5e/pop-to-esi -4629 59/pop-to-ecx -4630 58/pop-to-eax -4631 # . epilogue -4632 89/<- %esp 5/r32/ebp -4633 5d/pop-to-ebp -4634 c3/return -4635 -4636 $emit-subx-stmt-list:abort-regvardef-without-register: -4637 # error("var '" var->name "' initialized from an instruction must live in a register\n") -4638 (write-buffered Stderr "var '") -4639 (write-buffered Stderr *eax) # Var-name -4640 (write-buffered Stderr "' initialized from an instruction must live in a register\n") -4641 (flush Stderr) -4642 # . syscall(exit, 1) -4643 bb/copy-to-ebx 1/imm32 -4644 b8/copy-to-eax 1/imm32/exit -4645 cd/syscall 0x80/imm8 -4646 # never gets here -4647 -4648 emit-subx-var-def: # out: (addr buffered-file), stmt: (handle statement) -4649 # . prologue -4650 55/push-ebp -4651 89/<- %ebp 4/r32/esp -4652 # . save registers -4653 50/push-eax -4654 51/push-ecx -4655 # eax = stmt -4656 8b/-> *(ebp+0xc) 0/r32/eax -4657 # var n/eax: int = size-of(stmt->var) -4658 (size-of *(eax+4)) # Vardef-var => eax -4659 # while n > 0 -4660 { -4661 3d/compare-eax-with 0/imm32 -4662 7e/jump-if-<= break/disp8 -4663 (emit-indent *(ebp+8) *Curr-block-depth) -4664 (write-buffered *(ebp+8) "68/push 0/imm32\n") -4665 # n -= 4 -4666 2d/subtract-from-eax 4/imm32 -4667 # -4668 eb/jump loop/disp8 -4669 } -4670 $emit-subx-var-def:end: -4671 # . restore registers -4672 59/pop-to-ecx -4673 58/pop-to-eax -4674 # . epilogue -4675 89/<- %esp 5/r32/ebp -4676 5d/pop-to-ebp -4677 c3/return -4678 -4679 emit-subx-statement: # out: (addr buffered-file), stmt: (handle statement), primitives: (handle primitive), functions: (handle function) -4680 # . prologue -4681 55/push-ebp -4682 89/<- %ebp 4/r32/esp -4683 # . save registers -4684 50/push-eax -4685 51/push-ecx -4686 # if stmt matches a primitive, emit it -4687 { -4688 $emit-subx-statement:check-for-primitive: -4689 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => curr/eax -4690 3d/compare-eax-and 0/imm32 -4691 74/jump-if-= break/disp8 -4692 $emit-subx-statement:primitive: -4693 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr -4694 e9/jump $emit-subx-statement:end/disp32 -4695 } -4696 # else if stmt matches a function, emit a call to it -4697 { -4698 $emit-subx-statement:check-for-call: -4699 (find-matching-function *(ebp+0x14) *(ebp+0xc)) # functions, stmt => curr/eax -4700 3d/compare-eax-and 0/imm32 -4701 74/jump-if-= break/disp8 -4702 $emit-subx-statement:call: -4703 (emit-subx-call *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr -4704 e9/jump $emit-subx-statement:end/disp32 -4705 } -4706 # else abort -4707 e9/jump $emit-subx-statement:abort/disp32 -4708 $emit-subx-statement:end: -4709 # . restore registers -4710 59/pop-to-ecx -4711 58/pop-to-eax -4712 # . epilogue -4713 89/<- %esp 5/r32/ebp -4714 5d/pop-to-ebp -4715 c3/return -4716 -4717 $emit-subx-statement:abort: -4718 # error("couldn't translate '" stmt "'\n") -4719 (write-buffered Stderr "couldn't translate an instruction with operation '") -4720 8b/-> *(ebp+0xc) 0/r32/eax -4721 (write-buffered Stderr *(eax+4)) # Stmt1-operation -4722 (write-buffered Stderr "'\n") -4723 (flush Stderr) -4724 # . syscall(exit, 1) -4725 bb/copy-to-ebx 1/imm32 -4726 b8/copy-to-eax 1/imm32/exit -4727 cd/syscall 0x80/imm8 -4728 # never gets here -4729 -4730 emit-subx-named-block: # out: (addr buffered-file), named-block: (handle named-block), vars: (addr stack (handle var)) -4731 # . prologue -4732 55/push-ebp -4733 89/<- %ebp 4/r32/esp -4734 # . save registers -4735 50/push-eax -4736 51/push-ecx -4737 56/push-esi -4738 # esi = block -4739 8b/-> *(ebp+0xc) 6/r32/esi -4740 # var stmts/ecx: (handle list statement) = block->statements -4741 8b/-> *(esi+4) 0/r32/eax # Block-statements -4742 # -4743 { -4744 $emit-subx-named-block:check-empty: -4745 81 7/subop/compare %eax 0/imm32 -4746 0f 84/jump-if-= break/disp32 -4747 (emit-indent *(ebp+8) *Curr-block-depth) -4748 (write-buffered *(ebp+8) "{\n") -4749 (write-buffered *(ebp+8) *(esi+8)) # Named-block-name -4750 (write-buffered *(ebp+8) "loop:\n") -4751 ff 0/subop/increment *Curr-block-depth -4752 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10)) -4753 ff 1/subop/decrement *Curr-block-depth -4754 (emit-indent *(ebp+8) *Curr-block-depth) -4755 (write-buffered *(ebp+8) "}\n") -4756 (write-buffered *(ebp+8) *(esi+8)) # Named-block-name -4757 (write-buffered *(ebp+8) "break:\n") -4758 } -4759 $emit-subx-named-block:end: -4760 # . restore registers -4761 5e/pop-to-esi -4762 59/pop-to-ecx -4763 58/pop-to-eax -4764 # . epilogue -4765 89/<- %esp 5/r32/ebp -4766 5d/pop-to-ebp -4767 c3/return -4768 -4769 # Primitives supported -4770 # For each operation, put variants with hard-coded registers before flexible ones. -4771 == data -4772 Primitives: -4773 # - increment/decrement -4774 _Primitive-inc-eax: -4775 # var/eax <- increment => 40/increment-eax -4776 "increment"/imm32/name -4777 0/imm32/no-inouts -4778 Single-int-var-in-eax/imm32/outputs -4779 "40/increment-eax"/imm32/subx-name -4780 0/imm32/no-rm32 -4781 0/imm32/no-r32 -4782 0/imm32/no-imm32 -4783 0/imm32/no-disp32 -4784 0/imm32/output-is-write-only -4785 _Primitive-inc-ecx/imm32/next -4786 _Primitive-inc-ecx: -4787 # var/ecx <- increment => 41/increment-ecx -4788 "increment"/imm32/name -4789 0/imm32/no-inouts -4790 Single-int-var-in-ecx/imm32/outputs -4791 "41/increment-ecx"/imm32/subx-name -4792 0/imm32/no-rm32 -4793 0/imm32/no-r32 -4794 0/imm32/no-imm32 -4795 0/imm32/no-disp32 -4796 0/imm32/output-is-write-only -4797 _Primitive-inc-edx/imm32/next -4798 _Primitive-inc-edx: -4799 # var/edx <- increment => 42/increment-edx -4800 "increment"/imm32/name -4801 0/imm32/no-inouts -4802 Single-int-var-in-edx/imm32/outputs -4803 "42/increment-edx"/imm32/subx-name -4804 0/imm32/no-rm32 -4805 0/imm32/no-r32 -4806 0/imm32/no-imm32 -4807 0/imm32/no-disp32 -4808 0/imm32/output-is-write-only -4809 _Primitive-inc-ebx/imm32/next -4810 _Primitive-inc-ebx: -4811 # var/ebx <- increment => 43/increment-ebx -4812 "increment"/imm32/name -4813 0/imm32/no-inouts -4814 Single-int-var-in-ebx/imm32/outputs -4815 "43/increment-ebx"/imm32/subx-name -4816 0/imm32/no-rm32 -4817 0/imm32/no-r32 -4818 0/imm32/no-imm32 -4819 0/imm32/no-disp32 -4820 0/imm32/output-is-write-only -4821 _Primitive-inc-esi/imm32/next -4822 _Primitive-inc-esi: -4823 # var/esi <- increment => 46/increment-esi -4824 "increment"/imm32/name -4825 0/imm32/no-inouts -4826 Single-int-var-in-esi/imm32/outputs -4827 "46/increment-esi"/imm32/subx-name -4828 0/imm32/no-rm32 -4829 0/imm32/no-r32 -4830 0/imm32/no-imm32 -4831 0/imm32/no-disp32 -4832 0/imm32/output-is-write-only -4833 _Primitive-inc-edi/imm32/next -4834 _Primitive-inc-edi: -4835 # var/edi <- increment => 47/increment-edi -4836 "increment"/imm32/name -4837 0/imm32/no-inouts -4838 Single-int-var-in-edi/imm32/outputs -4839 "47/increment-edi"/imm32/subx-name -4840 0/imm32/no-rm32 -4841 0/imm32/no-r32 -4842 0/imm32/no-imm32 -4843 0/imm32/no-disp32 -4844 0/imm32/output-is-write-only -4845 _Primitive-dec-eax/imm32/next -4846 _Primitive-dec-eax: -4847 # var/eax <- decrement => 48/decrement-eax -4848 "decrement"/imm32/name -4849 0/imm32/no-inouts -4850 Single-int-var-in-eax/imm32/outputs -4851 "48/decrement-eax"/imm32/subx-name -4852 0/imm32/no-rm32 -4853 0/imm32/no-r32 -4854 0/imm32/no-imm32 -4855 0/imm32/no-disp32 -4856 0/imm32/output-is-write-only -4857 _Primitive-dec-ecx/imm32/next -4858 _Primitive-dec-ecx: -4859 # var/ecx <- decrement => 49/decrement-ecx -4860 "decrement"/imm32/name -4861 0/imm32/no-inouts -4862 Single-int-var-in-ecx/imm32/outputs -4863 "49/decrement-ecx"/imm32/subx-name -4864 0/imm32/no-rm32 -4865 0/imm32/no-r32 -4866 0/imm32/no-imm32 -4867 0/imm32/no-disp32 -4868 0/imm32/output-is-write-only -4869 _Primitive-dec-edx/imm32/next -4870 _Primitive-dec-edx: -4871 # var/edx <- decrement => 4a/decrement-edx -4872 "decrement"/imm32/name -4873 0/imm32/no-inouts -4874 Single-int-var-in-edx/imm32/outputs -4875 "4a/decrement-edx"/imm32/subx-name -4876 0/imm32/no-rm32 -4877 0/imm32/no-r32 -4878 0/imm32/no-imm32 -4879 0/imm32/no-disp32 -4880 0/imm32/output-is-write-only -4881 _Primitive-dec-ebx/imm32/next -4882 _Primitive-dec-ebx: -4883 # var/ebx <- decrement => 4b/decrement-ebx -4884 "decrement"/imm32/name -4885 0/imm32/no-inouts -4886 Single-int-var-in-ebx/imm32/outputs -4887 "4b/decrement-ebx"/imm32/subx-name -4888 0/imm32/no-rm32 -4889 0/imm32/no-r32 -4890 0/imm32/no-imm32 -4891 0/imm32/no-disp32 -4892 0/imm32/output-is-write-only -4893 _Primitive-dec-esi/imm32/next -4894 _Primitive-dec-esi: -4895 # var/esi <- decrement => 4e/decrement-esi -4896 "decrement"/imm32/name -4897 0/imm32/no-inouts -4898 Single-int-var-in-esi/imm32/outputs -4899 "4e/decrement-esi"/imm32/subx-name -4900 0/imm32/no-rm32 -4901 0/imm32/no-r32 -4902 0/imm32/no-imm32 -4903 0/imm32/no-disp32 -4904 0/imm32/output-is-write-only -4905 _Primitive-dec-edi/imm32/next -4906 _Primitive-dec-edi: -4907 # var/edi <- decrement => 4f/decrement-edi -4908 "decrement"/imm32/name -4909 0/imm32/no-inouts -4910 Single-int-var-in-edi/imm32/outputs -4911 "4f/decrement-edi"/imm32/subx-name -4912 0/imm32/no-rm32 -4913 0/imm32/no-r32 -4914 0/imm32/no-imm32 -4915 0/imm32/no-disp32 -4916 0/imm32/output-is-write-only -4917 _Primitive-inc-mem/imm32/next -4918 _Primitive-inc-mem: -4919 # increment var => ff 0/subop/increment *(ebp+__) -4920 "increment"/imm32/name -4921 Single-int-var-on-stack/imm32/inouts -4922 0/imm32/no-outputs -4923 "ff 0/subop/increment"/imm32/subx-name -4924 1/imm32/rm32-is-first-inout -4925 0/imm32/no-r32 -4926 0/imm32/no-imm32 -4927 0/imm32/no-disp32 -4928 0/imm32/output-is-write-only -4929 _Primitive-inc-reg/imm32/next -4930 _Primitive-inc-reg: -4931 # var/reg <- increment => ff 0/subop/increment %__ -4932 "increment"/imm32/name -4933 0/imm32/no-inouts -4934 Single-int-var-in-some-register/imm32/outputs -4935 "ff 0/subop/increment"/imm32/subx-name -4936 3/imm32/rm32-is-first-output -4937 0/imm32/no-r32 -4938 0/imm32/no-imm32 -4939 0/imm32/no-disp32 -4940 0/imm32/output-is-write-only -4941 _Primitive-dec-mem/imm32/next -4942 _Primitive-dec-mem: -4943 # decrement var => ff 1/subop/decrement *(ebp+__) -4944 "decrement"/imm32/name -4945 Single-int-var-on-stack/imm32/inouts -4946 0/imm32/no-outputs -4947 "ff 1/subop/decrement"/imm32/subx-name -4948 1/imm32/rm32-is-first-inout -4949 0/imm32/no-r32 -4950 0/imm32/no-imm32 -4951 0/imm32/no-disp32 -4952 0/imm32/output-is-write-only -4953 _Primitive-dec-reg/imm32/next -4954 _Primitive-dec-reg: -4955 # var/reg <- decrement => ff 1/subop/decrement %__ -4956 "decrement"/imm32/name -4957 0/imm32/no-inouts -4958 Single-int-var-in-some-register/imm32/outputs -4959 "ff 1/subop/decrement"/imm32/subx-name -4960 3/imm32/rm32-is-first-output -4961 0/imm32/no-r32 -4962 0/imm32/no-imm32 -4963 0/imm32/no-disp32 -4964 0/imm32/output-is-write-only -4965 _Primitive-add-to-eax/imm32/next -4966 # - add -4967 _Primitive-add-to-eax: -4968 # var/eax <- add lit => 05/add-to-eax lit/imm32 -4969 "add"/imm32/name -4970 Single-lit-var/imm32/inouts -4971 Single-int-var-in-eax/imm32/outputs -4972 "05/add-to-eax"/imm32/subx-name -4973 0/imm32/no-rm32 -4974 0/imm32/no-r32 -4975 1/imm32/imm32-is-first-inout -4976 0/imm32/no-disp32 -4977 0/imm32/output-is-write-only -4978 _Primitive-add-reg-to-reg/imm32/next -4979 _Primitive-add-reg-to-reg: -4980 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 -4981 "add"/imm32/name -4982 Single-int-var-in-some-register/imm32/inouts -4983 Single-int-var-in-some-register/imm32/outputs -4984 "01/add-to"/imm32/subx-name -4985 3/imm32/rm32-is-first-output -4986 1/imm32/r32-is-first-inout -4987 0/imm32/no-imm32 -4988 0/imm32/no-disp32 -4989 0/imm32/output-is-write-only -4990 _Primitive-add-reg-to-mem/imm32/next -4991 _Primitive-add-reg-to-mem: -4992 # add-to var1 var2/reg => 01/add-to var1 var2/r32 -4993 "add-to"/imm32/name -4994 Two-args-int-stack-int-reg/imm32/inouts -4995 0/imm32/outputs -4996 "01/add-to"/imm32/subx-name -4997 1/imm32/rm32-is-first-inout -4998 2/imm32/r32-is-second-inout -4999 0/imm32/no-imm32 -5000 0/imm32/no-disp32 -5001 0/imm32/output-is-write-only -5002 _Primitive-add-mem-to-reg/imm32/next -5003 _Primitive-add-mem-to-reg: -5004 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 -5005 "add"/imm32/name -5006 Single-int-var-on-stack/imm32/inouts -5007 Single-int-var-in-some-register/imm32/outputs -5008 "03/add"/imm32/subx-name -5009 1/imm32/rm32-is-first-inout -5010 3/imm32/r32-is-first-output -5011 0/imm32/no-imm32 -5012 0/imm32/no-disp32 -5013 0/imm32/output-is-write-only -5014 _Primitive-add-lit-to-reg/imm32/next -5015 _Primitive-add-lit-to-reg: -5016 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 -5017 "add"/imm32/name -5018 Single-lit-var/imm32/inouts -5019 Single-int-var-in-some-register/imm32/outputs -5020 "81 0/subop/add"/imm32/subx-name -5021 3/imm32/rm32-is-first-output -5022 0/imm32/no-r32 -5023 1/imm32/imm32-is-first-inout -5024 0/imm32/no-disp32 -5025 0/imm32/output-is-write-only -5026 _Primitive-add-lit-to-mem/imm32/next -5027 _Primitive-add-lit-to-mem: -5028 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 -5029 "add-to"/imm32/name -5030 Int-var-and-literal/imm32/inouts -5031 0/imm32/outputs -5032 "81 0/subop/add"/imm32/subx-name -5033 1/imm32/rm32-is-first-inout -5034 0/imm32/no-r32 -5035 2/imm32/imm32-is-second-inout -5036 0/imm32/no-disp32 -5037 0/imm32/output-is-write-only -5038 _Primitive-subtract-from-eax/imm32/next -5039 # - subtract -5040 _Primitive-subtract-from-eax: -5041 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 -5042 "subtract"/imm32/name -5043 Single-lit-var/imm32/inouts -5044 Single-int-var-in-eax/imm32/outputs -5045 "2d/subtract-from-eax"/imm32/subx-name -5046 0/imm32/no-rm32 -5047 0/imm32/no-r32 -5048 1/imm32/imm32-is-first-inout -5049 0/imm32/no-disp32 -5050 0/imm32/output-is-write-only -5051 _Primitive-subtract-reg-from-reg/imm32/next -5052 _Primitive-subtract-reg-from-reg: -5053 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 -5054 "subtract"/imm32/name -5055 Single-int-var-in-some-register/imm32/inouts -5056 Single-int-var-in-some-register/imm32/outputs -5057 "29/subtract-from"/imm32/subx-name -5058 3/imm32/rm32-is-first-output -5059 1/imm32/r32-is-first-inout -5060 0/imm32/no-imm32 -5061 0/imm32/no-disp32 -5062 0/imm32/output-is-write-only -5063 _Primitive-subtract-reg-from-mem/imm32/next -5064 _Primitive-subtract-reg-from-mem: -5065 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 -5066 "subtract-from"/imm32/name -5067 Two-args-int-stack-int-reg/imm32/inouts -5068 0/imm32/outputs -5069 "29/subtract-from"/imm32/subx-name -5070 1/imm32/rm32-is-first-inout -5071 2/imm32/r32-is-second-inout -5072 0/imm32/no-imm32 -5073 0/imm32/no-disp32 -5074 0/imm32/output-is-write-only -5075 _Primitive-subtract-mem-from-reg/imm32/next -5076 _Primitive-subtract-mem-from-reg: -5077 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 -5078 "subtract"/imm32/name -5079 Single-int-var-on-stack/imm32/inouts -5080 Single-int-var-in-some-register/imm32/outputs -5081 "2b/subtract"/imm32/subx-name -5082 1/imm32/rm32-is-first-inout -5083 3/imm32/r32-is-first-output -5084 0/imm32/no-imm32 -5085 0/imm32/no-disp32 -5086 0/imm32/output-is-write-only -5087 _Primitive-subtract-lit-from-reg/imm32/next -5088 _Primitive-subtract-lit-from-reg: -5089 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 -5090 "subtract"/imm32/name -5091 Single-lit-var/imm32/inouts -5092 Single-int-var-in-some-register/imm32/outputs -5093 "81 5/subop/subtract"/imm32/subx-name -5094 3/imm32/rm32-is-first-output -5095 0/imm32/no-r32 -5096 1/imm32/imm32-is-first-inout -5097 0/imm32/no-disp32 -5098 0/imm32/output-is-write-only -5099 _Primitive-subtract-lit-from-mem/imm32/next -5100 _Primitive-subtract-lit-from-mem: -5101 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 -5102 "subtract-from"/imm32/name -5103 Int-var-and-literal/imm32/inouts -5104 0/imm32/outputs -5105 "81 5/subop/subtract"/imm32/subx-name -5106 1/imm32/rm32-is-first-inout -5107 0/imm32/no-r32 -5108 2/imm32/imm32-is-first-inout -5109 0/imm32/no-disp32 -5110 0/imm32/output-is-write-only -5111 _Primitive-and-with-eax/imm32/next -5112 # - and -5113 _Primitive-and-with-eax: -5114 # var/eax <- and lit => 25/and-with-eax lit/imm32 -5115 "and"/imm32/name -5116 Single-lit-var/imm32/inouts -5117 Single-int-var-in-eax/imm32/outputs -5118 "25/and-with-eax"/imm32/subx-name -5119 0/imm32/no-rm32 -5120 0/imm32/no-r32 -5121 1/imm32/imm32-is-first-inout -5122 0/imm32/no-disp32 -5123 0/imm32/output-is-write-only -5124 _Primitive-and-reg-with-reg/imm32/next -5125 _Primitive-and-reg-with-reg: -5126 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 -5127 "and"/imm32/name -5128 Single-int-var-in-some-register/imm32/inouts -5129 Single-int-var-in-some-register/imm32/outputs -5130 "21/and-with"/imm32/subx-name -5131 3/imm32/rm32-is-first-output -5132 1/imm32/r32-is-first-inout -5133 0/imm32/no-imm32 -5134 0/imm32/no-disp32 -5135 0/imm32/output-is-write-only -5136 _Primitive-and-reg-with-mem/imm32/next -5137 _Primitive-and-reg-with-mem: -5138 # and-with var1 var2/reg => 21/and-with var1 var2/r32 -5139 "and-with"/imm32/name -5140 Two-args-int-stack-int-reg/imm32/inouts -5141 0/imm32/outputs -5142 "21/and-with"/imm32/subx-name -5143 1/imm32/rm32-is-first-inout -5144 2/imm32/r32-is-second-inout -5145 0/imm32/no-imm32 -5146 0/imm32/no-disp32 -5147 0/imm32/output-is-write-only -5148 _Primitive-and-mem-with-reg/imm32/next -5149 _Primitive-and-mem-with-reg: -5150 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 -5151 "and"/imm32/name -5152 Single-int-var-on-stack/imm32/inouts -5153 Single-int-var-in-some-register/imm32/outputs -5154 "23/and"/imm32/subx-name -5155 1/imm32/rm32-is-first-inout -5156 3/imm32/r32-is-first-output -5157 0/imm32/no-imm32 -5158 0/imm32/no-disp32 -5159 0/imm32/output-is-write-only -5160 _Primitive-and-lit-with-reg/imm32/next -5161 _Primitive-and-lit-with-reg: -5162 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 -5163 "and"/imm32/name -5164 Single-lit-var/imm32/inouts -5165 Single-int-var-in-some-register/imm32/outputs -5166 "81 4/subop/and"/imm32/subx-name -5167 3/imm32/rm32-is-first-output -5168 0/imm32/no-r32 -5169 1/imm32/imm32-is-first-inout -5170 0/imm32/no-disp32 -5171 0/imm32/output-is-write-only -5172 _Primitive-and-lit-with-mem/imm32/next -5173 _Primitive-and-lit-with-mem: -5174 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 -5175 "and-with"/imm32/name -5176 Int-var-and-literal/imm32/inouts -5177 0/imm32/outputs -5178 "81 4/subop/and"/imm32/subx-name -5179 1/imm32/rm32-is-first-inout -5180 0/imm32/no-r32 -5181 2/imm32/imm32-is-first-inout -5182 0/imm32/no-disp32 -5183 0/imm32/output-is-write-only -5184 _Primitive-or-with-eax/imm32/next -5185 # - or -5186 _Primitive-or-with-eax: -5187 # var/eax <- or lit => 0d/or-with-eax lit/imm32 -5188 "or"/imm32/name -5189 Single-lit-var/imm32/inouts -5190 Single-int-var-in-eax/imm32/outputs -5191 "0d/or-with-eax"/imm32/subx-name -5192 0/imm32/no-rm32 -5193 0/imm32/no-r32 -5194 1/imm32/imm32-is-first-inout -5195 0/imm32/no-disp32 -5196 0/imm32/output-is-write-only -5197 _Primitive-or-reg-with-reg/imm32/next -5198 _Primitive-or-reg-with-reg: -5199 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 -5200 "or"/imm32/name -5201 Single-int-var-in-some-register/imm32/inouts -5202 Single-int-var-in-some-register/imm32/outputs -5203 "09/or-with"/imm32/subx-name -5204 3/imm32/rm32-is-first-output -5205 1/imm32/r32-is-first-inout -5206 0/imm32/no-imm32 -5207 0/imm32/no-disp32 -5208 0/imm32/output-is-write-only -5209 _Primitive-or-reg-with-mem/imm32/next -5210 _Primitive-or-reg-with-mem: -5211 # or-with var1 var2/reg => 09/or-with var1 var2/r32 -5212 "or-with"/imm32/name -5213 Two-args-int-stack-int-reg/imm32/inouts -5214 0/imm32/outputs -5215 "09/or-with"/imm32/subx-name -5216 1/imm32/rm32-is-first-inout -5217 2/imm32/r32-is-second-inout -5218 0/imm32/no-imm32 -5219 0/imm32/no-disp32 -5220 0/imm32/output-is-write-only -5221 _Primitive-or-mem-with-reg/imm32/next -5222 _Primitive-or-mem-with-reg: -5223 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 -5224 "or"/imm32/name -5225 Single-int-var-on-stack/imm32/inouts -5226 Single-int-var-in-some-register/imm32/outputs -5227 "0b/or"/imm32/subx-name -5228 1/imm32/rm32-is-first-inout -5229 3/imm32/r32-is-first-output -5230 0/imm32/no-imm32 -5231 0/imm32/no-disp32 -5232 0/imm32/output-is-write-only -5233 _Primitive-or-lit-with-reg/imm32/next -5234 _Primitive-or-lit-with-reg: -5235 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 -5236 "or"/imm32/name -5237 Single-lit-var/imm32/inouts -5238 Single-int-var-in-some-register/imm32/outputs -5239 "81 1/subop/or"/imm32/subx-name -5240 3/imm32/rm32-is-first-output -5241 0/imm32/no-r32 -5242 1/imm32/imm32-is-first-inout -5243 0/imm32/no-disp32 -5244 0/imm32/output-is-write-only -5245 _Primitive-or-lit-with-mem/imm32/next -5246 _Primitive-or-lit-with-mem: -5247 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 -5248 "or-with"/imm32/name -5249 Int-var-and-literal/imm32/inouts -5250 0/imm32/outputs -5251 "81 1/subop/or"/imm32/subx-name -5252 1/imm32/rm32-is-first-inout -5253 0/imm32/no-r32 -5254 2/imm32/imm32-is-second-inout -5255 0/imm32/no-disp32 -5256 0/imm32/output-is-write-only -5257 _Primitive-xor-with-eax/imm32/next -5258 # - xor -5259 _Primitive-xor-with-eax: -5260 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 -5261 "xor"/imm32/name -5262 Single-lit-var/imm32/inouts -5263 Single-int-var-in-eax/imm32/outputs -5264 "35/xor-with-eax"/imm32/subx-name -5265 0/imm32/no-rm32 -5266 0/imm32/no-r32 -5267 1/imm32/imm32-is-first-inout -5268 0/imm32/no-disp32 -5269 0/imm32/output-is-write-only -5270 _Primitive-xor-reg-with-reg/imm32/next -5271 _Primitive-xor-reg-with-reg: -5272 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 -5273 "xor"/imm32/name -5274 Single-int-var-in-some-register/imm32/inouts -5275 Single-int-var-in-some-register/imm32/outputs -5276 "31/xor-with"/imm32/subx-name -5277 3/imm32/rm32-is-first-output -5278 1/imm32/r32-is-first-inout -5279 0/imm32/no-imm32 -5280 0/imm32/no-disp32 -5281 0/imm32/output-is-write-only -5282 _Primitive-xor-reg-with-mem/imm32/next -5283 _Primitive-xor-reg-with-mem: -5284 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 -5285 "xor-with"/imm32/name -5286 Two-args-int-stack-int-reg/imm32/inouts -5287 0/imm32/outputs -5288 "31/xor-with"/imm32/subx-name -5289 1/imm32/rm32-is-first-inout -5290 2/imm32/r32-is-second-inout -5291 0/imm32/no-imm32 -5292 0/imm32/no-disp32 -5293 0/imm32/output-is-write-only -5294 _Primitive-xor-mem-with-reg/imm32/next -5295 _Primitive-xor-mem-with-reg: -5296 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 -5297 "xor"/imm32/name -5298 Single-int-var-on-stack/imm32/inouts -5299 Single-int-var-in-some-register/imm32/outputs -5300 "33/xor"/imm32/subx-name -5301 1/imm32/rm32-is-first-inout -5302 3/imm32/r32-is-first-output -5303 0/imm32/no-imm32 -5304 0/imm32/no-disp32 -5305 0/imm32/output-is-write-only -5306 _Primitive-xor-lit-with-reg/imm32/next -5307 _Primitive-xor-lit-with-reg: -5308 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 -5309 "xor"/imm32/name -5310 Single-lit-var/imm32/inouts -5311 Single-int-var-in-some-register/imm32/outputs -5312 "81 6/subop/xor"/imm32/subx-name -5313 3/imm32/rm32-is-first-output +4163 58/pop-to-eax +4164 # . epilogue +4165 89/<- %esp 5/r32/ebp +4166 5d/pop-to-ebp +4167 c3/return +4168 +4169 emit-subx-block: # out: (addr buffered-file), block: (handle block), vars: (addr stack (handle var)) +4170 # . prologue +4171 55/push-ebp +4172 89/<- %ebp 4/r32/esp +4173 # . save registers +4174 56/push-esi +4175 # var stmts/esi: (handle list statement) = block->statements +4176 8b/-> *(ebp+0xc) 6/r32/esi +4177 8b/-> *(esi+4) 6/r32/esi # Block-statements +4178 # +4179 { +4180 $emit-subx-block:check-empty: +4181 81 7/subop/compare %esi 0/imm32 +4182 0f 84/jump-if-= break/disp32 +4183 (emit-indent *(ebp+8) *Curr-block-depth) +4184 (write-buffered *(ebp+8) "{\n") +4185 ff 0/subop/increment *Curr-block-depth +4186 (emit-subx-stmt-list *(ebp+8) %esi *(ebp+0x10)) +4187 ff 1/subop/decrement *Curr-block-depth +4188 (emit-indent *(ebp+8) *Curr-block-depth) +4189 (write-buffered *(ebp+8) "}\n") +4190 } +4191 $emit-subx-block:end: +4192 # . restore registers +4193 5e/pop-to-esi +4194 # . epilogue +4195 89/<- %esp 5/r32/ebp +4196 5d/pop-to-ebp +4197 c3/return +4198 +4199 emit-subx-stmt-list: # out: (addr buffered-file), stmts: (handle list stmt), vars: (addr stack (handle var)) +4200 # . prologue +4201 55/push-ebp +4202 89/<- %ebp 4/r32/esp +4203 # . save registers +4204 50/push-eax +4205 51/push-ecx +4206 52/push-edx +4207 56/push-esi +4208 # esi = stmts +4209 8b/-> *(ebp+0xc) 6/r32/esi +4210 # var var-seen?/edx: boolean <- copy false +4211 ba/copy-to-edx 0/imm32/false +4212 # +4213 { +4214 $emit-subx-stmt-list:loop: +4215 81 7/subop/compare %esi 0/imm32 +4216 0f 84/jump-if-= break/disp32 +4217 # var curr-stmt/ecx = stmts->value +4218 8b/-> *esi 1/r32/ecx # List-value +4219 { +4220 $emit-subx-stmt-list:check-for-block: +4221 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag +4222 75/jump-if-!= break/disp8 +4223 $emit-subx-stmt-list:block: +4224 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10)) +4225 } +4226 { +4227 $emit-subx-stmt-list:check-for-stmt: +4228 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag +4229 0f 85/jump-if-!= break/disp32 +4230 { +4231 # if !var-seen? break +4232 81 7/subop/compare %edx 0/imm32/false +4233 0f 84/jump-if-= break/disp32 +4234 $emit-subx-stmt-list:check-for-break: +4235 # if (!string-starts-with?(var->operation, "break")) break +4236 (string-starts-with? *(ecx+4) "break") # Stmt1-operation => eax +4237 3d/compare-eax-and 0/imm32 +4238 0f 84/jump-if-= break/disp32 +4239 $emit-subx-stmt-list:break: +4240 # create a new block for the remaining statements +4241 (emit-indent *(ebp+8) *Curr-block-depth) +4242 (write-buffered *(ebp+8) "{\n") +4243 ff 0/subop/increment *Curr-block-depth +4244 (emit-subx-stmt-list *(ebp+8) %esi *(ebp+0x10)) +4245 ff 1/subop/decrement *Curr-block-depth +4246 (emit-indent *(ebp+8) *Curr-block-depth) +4247 (write-buffered *(ebp+8) "}\n") +4248 # return $emit-subx-stmt-list +4249 e9/jump $emit-subx-stmt-list:reclaim-loop/disp32 +4250 } +4251 { +4252 $emit-subx-stmt-list:check-for-loop: +4253 # TODO +4254 } +4255 $emit-subx-stmt-list:stmt: +4256 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) +4257 } +4258 { +4259 $emit-subx-stmt-list:check-for-vardef: +4260 81 7/subop/compare *ecx 2/imm32/vardef # Stmt-tag +4261 75/jump-if-!= break/disp8 +4262 $emit-subx-stmt-list:vardef: +4263 (emit-subx-var-def *(ebp+8) %ecx) +4264 (push *(ebp+0x10) *(ecx+4)) # Vardef-var +4265 # var-seen? = true +4266 ba/copy-to-edx 1/imm32/true +4267 } +4268 { +4269 $emit-subx-stmt-list:check-for-regvardef: +4270 81 7/subop/compare *ecx 3/imm32/regvardef # Stmt-tag +4271 0f 85/jump-if-!= break/disp32 +4272 $emit-subx-stmt-list:regvardef: +4273 # TODO: ensure that there's exactly one output +4274 # var output/eax: (handle var) = curr-stmt->outputs->value +4275 8b/-> *(ecx+0xc) 0/r32/eax +4276 8b/-> *eax 0/r32/eax +4277 # ensure that output is in a register +4278 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register +4279 0f 84/jump-if-= $emit-subx-stmt-list:abort-regvardef-without-register/disp32 +4280 # emit spill +4281 (emit-indent *(ebp+8) *Curr-block-depth) +4282 (write-buffered *(ebp+8) "ff 6/subop/push %") +4283 (write-buffered *(ebp+8) *(eax+0x10)) +4284 (write-buffered *(ebp+8) Newline) +4285 # register variable definition +4286 (push *(ebp+0x10) %eax) +4287 # emit the instruction as usual +4288 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) +4289 # var-seen? = true +4290 ba/copy-to-edx 1/imm32/true +4291 } +4292 { +4293 $emit-subx-stmt-list:check-for-named-block: +4294 81 7/subop/compare *ecx 4/imm32/named-block # Stmt-tag +4295 75/jump-if-!= break/disp8 +4296 $emit-subx-stmt-list:named-block: +4297 (emit-subx-named-block *(ebp+8) %ecx *(ebp+0x10)) +4298 } +4299 8b/-> *(esi+4) 6/r32/esi # List-next +4300 e9/jump loop/disp32 +4301 } +4302 # reclaim locals +4303 { +4304 $emit-subx-stmt-list:reclaim-loop: +4305 8b/-> *(ebp+0x10) 0/r32/eax +4306 81 7/subop/compare *eax 0/imm32 # Stack-top +4307 0f 84/jump-if-= break/disp32 +4308 # var v/ecx : (handle var) = top(vars) +4309 (top %eax) # => eax +4310 89/<- %ecx 0/r32/eax +4311 # if v->block-depth == *Curr-block-depth +4312 8b/-> *Curr-block-depth 0/r32/eax +4313 39/compare *(ecx+8) 0/r32/eax # Var-block-depth +4314 0f 85/jump-if-!= break/disp32 +4315 # if v is in a register +4316 81 7/subop/compare *(ecx+0x10) 0/imm32 # Var-register +4317 { +4318 74/jump-if-= break/disp8 +4319 $emit-subx-stmt-list:reclaim-var-in-register: +4320 (emit-indent *(ebp+8) *Curr-block-depth) +4321 (write-buffered *(ebp+8) "8f 0/subop/pop %") +4322 (write-buffered *(ebp+8) *(ecx+0x10)) +4323 (write-buffered *(ebp+8) Newline) +4324 } +4325 # if v is on the stack +4326 { +4327 75/jump-if-!= break/disp8 +4328 $emit-subx-stmt-list:reclaim-var-on-stack: +4329 (size-of %ecx) # => eax +4330 01/add *Next-local-stack-offset 0/r32/eax +4331 (emit-indent *(ebp+8) *Curr-block-depth) +4332 (write-buffered *(ebp+8) "81 0/subop/add %esp ") +4333 (print-int32-buffered *(ebp+8) %eax) +4334 (write-buffered *(ebp+8) "/imm32\n") +4335 } +4336 # +4337 (pop *(ebp+0x10)) +4338 e9/jump loop/disp32 +4339 } +4340 $emit-subx-stmt-list:end: +4341 # . restore registers +4342 5e/pop-to-esi +4343 5a/pop-to-edx +4344 59/pop-to-ecx +4345 58/pop-to-eax +4346 # . epilogue +4347 89/<- %esp 5/r32/ebp +4348 5d/pop-to-ebp +4349 c3/return +4350 +4351 $emit-subx-stmt-list:abort-regvardef-without-register: +4352 # error("var '" var->name "' initialized from an instruction must live in a register\n") +4353 (write-buffered Stderr "var '") +4354 (write-buffered Stderr *eax) # Var-name +4355 (write-buffered Stderr "' initialized from an instruction must live in a register\n") +4356 (flush Stderr) +4357 # . syscall(exit, 1) +4358 bb/copy-to-ebx 1/imm32 +4359 b8/copy-to-eax 1/imm32/exit +4360 cd/syscall 0x80/imm8 +4361 # never gets here +4362 +4363 emit-subx-var-def: # out: (addr buffered-file), stmt: (handle statement) +4364 # . prologue +4365 55/push-ebp +4366 89/<- %ebp 4/r32/esp +4367 # . save registers +4368 50/push-eax +4369 51/push-ecx +4370 # eax = stmt +4371 8b/-> *(ebp+0xc) 0/r32/eax +4372 # var n/eax: int = size-of(stmt->var) +4373 (size-of *(eax+4)) # Vardef-var => eax +4374 # while n > 0 +4375 { +4376 3d/compare-eax-with 0/imm32 +4377 7e/jump-if-<= break/disp8 +4378 (emit-indent *(ebp+8) *Curr-block-depth) +4379 (write-buffered *(ebp+8) "68/push 0/imm32\n") +4380 # n -= 4 +4381 2d/subtract-from-eax 4/imm32 +4382 # +4383 eb/jump loop/disp8 +4384 } +4385 $emit-subx-var-def:end: +4386 # . restore registers +4387 59/pop-to-ecx +4388 58/pop-to-eax +4389 # . epilogue +4390 89/<- %esp 5/r32/ebp +4391 5d/pop-to-ebp +4392 c3/return +4393 +4394 emit-subx-statement: # out: (addr buffered-file), stmt: (handle statement), primitives: (handle primitive), functions: (handle function) +4395 # . prologue +4396 55/push-ebp +4397 89/<- %ebp 4/r32/esp +4398 # . save registers +4399 50/push-eax +4400 51/push-ecx +4401 # if stmt matches a primitive, emit it +4402 { +4403 $emit-subx-statement:check-for-primitive: +4404 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => curr/eax +4405 3d/compare-eax-and 0/imm32 +4406 74/jump-if-= break/disp8 +4407 $emit-subx-statement:primitive: +4408 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr +4409 e9/jump $emit-subx-statement:end/disp32 +4410 } +4411 # else if stmt matches a function, emit a call to it +4412 { +4413 $emit-subx-statement:check-for-call: +4414 (find-matching-function *(ebp+0x14) *(ebp+0xc)) # functions, stmt => curr/eax +4415 3d/compare-eax-and 0/imm32 +4416 74/jump-if-= break/disp8 +4417 $emit-subx-statement:call: +4418 (emit-subx-call *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr +4419 e9/jump $emit-subx-statement:end/disp32 +4420 } +4421 # else abort +4422 e9/jump $emit-subx-statement:abort/disp32 +4423 $emit-subx-statement:end: +4424 # . restore registers +4425 59/pop-to-ecx +4426 58/pop-to-eax +4427 # . epilogue +4428 89/<- %esp 5/r32/ebp +4429 5d/pop-to-ebp +4430 c3/return +4431 +4432 $emit-subx-statement:abort: +4433 # error("couldn't translate '" stmt "'\n") +4434 (write-buffered Stderr "couldn't translate an instruction with operation '") +4435 8b/-> *(ebp+0xc) 0/r32/eax +4436 (write-buffered Stderr *(eax+4)) # Stmt1-operation +4437 (write-buffered Stderr "'\n") +4438 (flush Stderr) +4439 # . syscall(exit, 1) +4440 bb/copy-to-ebx 1/imm32 +4441 b8/copy-to-eax 1/imm32/exit +4442 cd/syscall 0x80/imm8 +4443 # never gets here +4444 +4445 emit-subx-named-block: # out: (addr buffered-file), named-block: (handle named-block), vars: (addr stack (handle var)) +4446 # . prologue +4447 55/push-ebp +4448 89/<- %ebp 4/r32/esp +4449 # . save registers +4450 50/push-eax +4451 51/push-ecx +4452 56/push-esi +4453 # esi = block +4454 8b/-> *(ebp+0xc) 6/r32/esi +4455 # var stmts/ecx: (handle list statement) = block->statements +4456 8b/-> *(esi+4) 0/r32/eax # Block-statements +4457 # +4458 { +4459 $emit-subx-named-block:check-empty: +4460 81 7/subop/compare %eax 0/imm32 +4461 0f 84/jump-if-= break/disp32 +4462 (emit-indent *(ebp+8) *Curr-block-depth) +4463 (write-buffered *(ebp+8) "{\n") +4464 (write-buffered *(ebp+8) *(esi+8)) # Named-block-name +4465 (write-buffered *(ebp+8) "loop:\n") +4466 ff 0/subop/increment *Curr-block-depth +4467 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10)) +4468 ff 1/subop/decrement *Curr-block-depth +4469 (emit-indent *(ebp+8) *Curr-block-depth) +4470 (write-buffered *(ebp+8) "}\n") +4471 (write-buffered *(ebp+8) *(esi+8)) # Named-block-name +4472 (write-buffered *(ebp+8) "break:\n") +4473 } +4474 $emit-subx-named-block:end: +4475 # . restore registers +4476 5e/pop-to-esi +4477 59/pop-to-ecx +4478 58/pop-to-eax +4479 # . epilogue +4480 89/<- %esp 5/r32/ebp +4481 5d/pop-to-ebp +4482 c3/return +4483 +4484 # Primitives supported +4485 # For each operation, put variants with hard-coded registers before flexible ones. +4486 == data +4487 Primitives: +4488 # - increment/decrement +4489 _Primitive-inc-eax: +4490 # var/eax <- increment => 40/increment-eax +4491 "increment"/imm32/name +4492 0/imm32/no-inouts +4493 Single-int-var-in-eax/imm32/outputs +4494 "40/increment-eax"/imm32/subx-name +4495 0/imm32/no-rm32 +4496 0/imm32/no-r32 +4497 0/imm32/no-imm32 +4498 0/imm32/no-disp32 +4499 0/imm32/output-is-write-only +4500 _Primitive-inc-ecx/imm32/next +4501 _Primitive-inc-ecx: +4502 # var/ecx <- increment => 41/increment-ecx +4503 "increment"/imm32/name +4504 0/imm32/no-inouts +4505 Single-int-var-in-ecx/imm32/outputs +4506 "41/increment-ecx"/imm32/subx-name +4507 0/imm32/no-rm32 +4508 0/imm32/no-r32 +4509 0/imm32/no-imm32 +4510 0/imm32/no-disp32 +4511 0/imm32/output-is-write-only +4512 _Primitive-inc-edx/imm32/next +4513 _Primitive-inc-edx: +4514 # var/edx <- increment => 42/increment-edx +4515 "increment"/imm32/name +4516 0/imm32/no-inouts +4517 Single-int-var-in-edx/imm32/outputs +4518 "42/increment-edx"/imm32/subx-name +4519 0/imm32/no-rm32 +4520 0/imm32/no-r32 +4521 0/imm32/no-imm32 +4522 0/imm32/no-disp32 +4523 0/imm32/output-is-write-only +4524 _Primitive-inc-ebx/imm32/next +4525 _Primitive-inc-ebx: +4526 # var/ebx <- increment => 43/increment-ebx +4527 "increment"/imm32/name +4528 0/imm32/no-inouts +4529 Single-int-var-in-ebx/imm32/outputs +4530 "43/increment-ebx"/imm32/subx-name +4531 0/imm32/no-rm32 +4532 0/imm32/no-r32 +4533 0/imm32/no-imm32 +4534 0/imm32/no-disp32 +4535 0/imm32/output-is-write-only +4536 _Primitive-inc-esi/imm32/next +4537 _Primitive-inc-esi: +4538 # var/esi <- increment => 46/increment-esi +4539 "increment"/imm32/name +4540 0/imm32/no-inouts +4541 Single-int-var-in-esi/imm32/outputs +4542 "46/increment-esi"/imm32/subx-name +4543 0/imm32/no-rm32 +4544 0/imm32/no-r32 +4545 0/imm32/no-imm32 +4546 0/imm32/no-disp32 +4547 0/imm32/output-is-write-only +4548 _Primitive-inc-edi/imm32/next +4549 _Primitive-inc-edi: +4550 # var/edi <- increment => 47/increment-edi +4551 "increment"/imm32/name +4552 0/imm32/no-inouts +4553 Single-int-var-in-edi/imm32/outputs +4554 "47/increment-edi"/imm32/subx-name +4555 0/imm32/no-rm32 +4556 0/imm32/no-r32 +4557 0/imm32/no-imm32 +4558 0/imm32/no-disp32 +4559 0/imm32/output-is-write-only +4560 _Primitive-dec-eax/imm32/next +4561 _Primitive-dec-eax: +4562 # var/eax <- decrement => 48/decrement-eax +4563 "decrement"/imm32/name +4564 0/imm32/no-inouts +4565 Single-int-var-in-eax/imm32/outputs +4566 "48/decrement-eax"/imm32/subx-name +4567 0/imm32/no-rm32 +4568 0/imm32/no-r32 +4569 0/imm32/no-imm32 +4570 0/imm32/no-disp32 +4571 0/imm32/output-is-write-only +4572 _Primitive-dec-ecx/imm32/next +4573 _Primitive-dec-ecx: +4574 # var/ecx <- decrement => 49/decrement-ecx +4575 "decrement"/imm32/name +4576 0/imm32/no-inouts +4577 Single-int-var-in-ecx/imm32/outputs +4578 "49/decrement-ecx"/imm32/subx-name +4579 0/imm32/no-rm32 +4580 0/imm32/no-r32 +4581 0/imm32/no-imm32 +4582 0/imm32/no-disp32 +4583 0/imm32/output-is-write-only +4584 _Primitive-dec-edx/imm32/next +4585 _Primitive-dec-edx: +4586 # var/edx <- decrement => 4a/decrement-edx +4587 "decrement"/imm32/name +4588 0/imm32/no-inouts +4589 Single-int-var-in-edx/imm32/outputs +4590 "4a/decrement-edx"/imm32/subx-name +4591 0/imm32/no-rm32 +4592 0/imm32/no-r32 +4593 0/imm32/no-imm32 +4594 0/imm32/no-disp32 +4595 0/imm32/output-is-write-only +4596 _Primitive-dec-ebx/imm32/next +4597 _Primitive-dec-ebx: +4598 # var/ebx <- decrement => 4b/decrement-ebx +4599 "decrement"/imm32/name +4600 0/imm32/no-inouts +4601 Single-int-var-in-ebx/imm32/outputs +4602 "4b/decrement-ebx"/imm32/subx-name +4603 0/imm32/no-rm32 +4604 0/imm32/no-r32 +4605 0/imm32/no-imm32 +4606 0/imm32/no-disp32 +4607 0/imm32/output-is-write-only +4608 _Primitive-dec-esi/imm32/next +4609 _Primitive-dec-esi: +4610 # var/esi <- decrement => 4e/decrement-esi +4611 "decrement"/imm32/name +4612 0/imm32/no-inouts +4613 Single-int-var-in-esi/imm32/outputs +4614 "4e/decrement-esi"/imm32/subx-name +4615 0/imm32/no-rm32 +4616 0/imm32/no-r32 +4617 0/imm32/no-imm32 +4618 0/imm32/no-disp32 +4619 0/imm32/output-is-write-only +4620 _Primitive-dec-edi/imm32/next +4621 _Primitive-dec-edi: +4622 # var/edi <- decrement => 4f/decrement-edi +4623 "decrement"/imm32/name +4624 0/imm32/no-inouts +4625 Single-int-var-in-edi/imm32/outputs +4626 "4f/decrement-edi"/imm32/subx-name +4627 0/imm32/no-rm32 +4628 0/imm32/no-r32 +4629 0/imm32/no-imm32 +4630 0/imm32/no-disp32 +4631 0/imm32/output-is-write-only +4632 _Primitive-inc-mem/imm32/next +4633 _Primitive-inc-mem: +4634 # increment var => ff 0/subop/increment *(ebp+__) +4635 "increment"/imm32/name +4636 Single-int-var-on-stack/imm32/inouts +4637 0/imm32/no-outputs +4638 "ff 0/subop/increment"/imm32/subx-name +4639 1/imm32/rm32-is-first-inout +4640 0/imm32/no-r32 +4641 0/imm32/no-imm32 +4642 0/imm32/no-disp32 +4643 0/imm32/output-is-write-only +4644 _Primitive-inc-reg/imm32/next +4645 _Primitive-inc-reg: +4646 # var/reg <- increment => ff 0/subop/increment %__ +4647 "increment"/imm32/name +4648 0/imm32/no-inouts +4649 Single-int-var-in-some-register/imm32/outputs +4650 "ff 0/subop/increment"/imm32/subx-name +4651 3/imm32/rm32-is-first-output +4652 0/imm32/no-r32 +4653 0/imm32/no-imm32 +4654 0/imm32/no-disp32 +4655 0/imm32/output-is-write-only +4656 _Primitive-dec-mem/imm32/next +4657 _Primitive-dec-mem: +4658 # decrement var => ff 1/subop/decrement *(ebp+__) +4659 "decrement"/imm32/name +4660 Single-int-var-on-stack/imm32/inouts +4661 0/imm32/no-outputs +4662 "ff 1/subop/decrement"/imm32/subx-name +4663 1/imm32/rm32-is-first-inout +4664 0/imm32/no-r32 +4665 0/imm32/no-imm32 +4666 0/imm32/no-disp32 +4667 0/imm32/output-is-write-only +4668 _Primitive-dec-reg/imm32/next +4669 _Primitive-dec-reg: +4670 # var/reg <- decrement => ff 1/subop/decrement %__ +4671 "decrement"/imm32/name +4672 0/imm32/no-inouts +4673 Single-int-var-in-some-register/imm32/outputs +4674 "ff 1/subop/decrement"/imm32/subx-name +4675 3/imm32/rm32-is-first-output +4676 0/imm32/no-r32 +4677 0/imm32/no-imm32 +4678 0/imm32/no-disp32 +4679 0/imm32/output-is-write-only +4680 _Primitive-add-to-eax/imm32/next +4681 # - add +4682 _Primitive-add-to-eax: +4683 # var/eax <- add lit => 05/add-to-eax lit/imm32 +4684 "add"/imm32/name +4685 Single-lit-var/imm32/inouts +4686 Single-int-var-in-eax/imm32/outputs +4687 "05/add-to-eax"/imm32/subx-name +4688 0/imm32/no-rm32 +4689 0/imm32/no-r32 +4690 1/imm32/imm32-is-first-inout +4691 0/imm32/no-disp32 +4692 0/imm32/output-is-write-only +4693 _Primitive-add-reg-to-reg/imm32/next +4694 _Primitive-add-reg-to-reg: +4695 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 +4696 "add"/imm32/name +4697 Single-int-var-in-some-register/imm32/inouts +4698 Single-int-var-in-some-register/imm32/outputs +4699 "01/add-to"/imm32/subx-name +4700 3/imm32/rm32-is-first-output +4701 1/imm32/r32-is-first-inout +4702 0/imm32/no-imm32 +4703 0/imm32/no-disp32 +4704 0/imm32/output-is-write-only +4705 _Primitive-add-reg-to-mem/imm32/next +4706 _Primitive-add-reg-to-mem: +4707 # add-to var1 var2/reg => 01/add-to var1 var2/r32 +4708 "add-to"/imm32/name +4709 Two-args-int-stack-int-reg/imm32/inouts +4710 0/imm32/outputs +4711 "01/add-to"/imm32/subx-name +4712 1/imm32/rm32-is-first-inout +4713 2/imm32/r32-is-second-inout +4714 0/imm32/no-imm32 +4715 0/imm32/no-disp32 +4716 0/imm32/output-is-write-only +4717 _Primitive-add-mem-to-reg/imm32/next +4718 _Primitive-add-mem-to-reg: +4719 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 +4720 "add"/imm32/name +4721 Single-int-var-on-stack/imm32/inouts +4722 Single-int-var-in-some-register/imm32/outputs +4723 "03/add"/imm32/subx-name +4724 1/imm32/rm32-is-first-inout +4725 3/imm32/r32-is-first-output +4726 0/imm32/no-imm32 +4727 0/imm32/no-disp32 +4728 0/imm32/output-is-write-only +4729 _Primitive-add-lit-to-reg/imm32/next +4730 _Primitive-add-lit-to-reg: +4731 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 +4732 "add"/imm32/name +4733 Single-lit-var/imm32/inouts +4734 Single-int-var-in-some-register/imm32/outputs +4735 "81 0/subop/add"/imm32/subx-name +4736 3/imm32/rm32-is-first-output +4737 0/imm32/no-r32 +4738 1/imm32/imm32-is-first-inout +4739 0/imm32/no-disp32 +4740 0/imm32/output-is-write-only +4741 _Primitive-add-lit-to-mem/imm32/next +4742 _Primitive-add-lit-to-mem: +4743 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 +4744 "add-to"/imm32/name +4745 Int-var-and-literal/imm32/inouts +4746 0/imm32/outputs +4747 "81 0/subop/add"/imm32/subx-name +4748 1/imm32/rm32-is-first-inout +4749 0/imm32/no-r32 +4750 2/imm32/imm32-is-second-inout +4751 0/imm32/no-disp32 +4752 0/imm32/output-is-write-only +4753 _Primitive-subtract-from-eax/imm32/next +4754 # - subtract +4755 _Primitive-subtract-from-eax: +4756 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 +4757 "subtract"/imm32/name +4758 Single-lit-var/imm32/inouts +4759 Single-int-var-in-eax/imm32/outputs +4760 "2d/subtract-from-eax"/imm32/subx-name +4761 0/imm32/no-rm32 +4762 0/imm32/no-r32 +4763 1/imm32/imm32-is-first-inout +4764 0/imm32/no-disp32 +4765 0/imm32/output-is-write-only +4766 _Primitive-subtract-reg-from-reg/imm32/next +4767 _Primitive-subtract-reg-from-reg: +4768 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 +4769 "subtract"/imm32/name +4770 Single-int-var-in-some-register/imm32/inouts +4771 Single-int-var-in-some-register/imm32/outputs +4772 "29/subtract-from"/imm32/subx-name +4773 3/imm32/rm32-is-first-output +4774 1/imm32/r32-is-first-inout +4775 0/imm32/no-imm32 +4776 0/imm32/no-disp32 +4777 0/imm32/output-is-write-only +4778 _Primitive-subtract-reg-from-mem/imm32/next +4779 _Primitive-subtract-reg-from-mem: +4780 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 +4781 "subtract-from"/imm32/name +4782 Two-args-int-stack-int-reg/imm32/inouts +4783 0/imm32/outputs +4784 "29/subtract-from"/imm32/subx-name +4785 1/imm32/rm32-is-first-inout +4786 2/imm32/r32-is-second-inout +4787 0/imm32/no-imm32 +4788 0/imm32/no-disp32 +4789 0/imm32/output-is-write-only +4790 _Primitive-subtract-mem-from-reg/imm32/next +4791 _Primitive-subtract-mem-from-reg: +4792 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 +4793 "subtract"/imm32/name +4794 Single-int-var-on-stack/imm32/inouts +4795 Single-int-var-in-some-register/imm32/outputs +4796 "2b/subtract"/imm32/subx-name +4797 1/imm32/rm32-is-first-inout +4798 3/imm32/r32-is-first-output +4799 0/imm32/no-imm32 +4800 0/imm32/no-disp32 +4801 0/imm32/output-is-write-only +4802 _Primitive-subtract-lit-from-reg/imm32/next +4803 _Primitive-subtract-lit-from-reg: +4804 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 +4805 "subtract"/imm32/name +4806 Single-lit-var/imm32/inouts +4807 Single-int-var-in-some-register/imm32/outputs +4808 "81 5/subop/subtract"/imm32/subx-name +4809 3/imm32/rm32-is-first-output +4810 0/imm32/no-r32 +4811 1/imm32/imm32-is-first-inout +4812 0/imm32/no-disp32 +4813 0/imm32/output-is-write-only +4814 _Primitive-subtract-lit-from-mem/imm32/next +4815 _Primitive-subtract-lit-from-mem: +4816 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 +4817 "subtract-from"/imm32/name +4818 Int-var-and-literal/imm32/inouts +4819 0/imm32/outputs +4820 "81 5/subop/subtract"/imm32/subx-name +4821 1/imm32/rm32-is-first-inout +4822 0/imm32/no-r32 +4823 2/imm32/imm32-is-first-inout +4824 0/imm32/no-disp32 +4825 0/imm32/output-is-write-only +4826 _Primitive-and-with-eax/imm32/next +4827 # - and +4828 _Primitive-and-with-eax: +4829 # var/eax <- and lit => 25/and-with-eax lit/imm32 +4830 "and"/imm32/name +4831 Single-lit-var/imm32/inouts +4832 Single-int-var-in-eax/imm32/outputs +4833 "25/and-with-eax"/imm32/subx-name +4834 0/imm32/no-rm32 +4835 0/imm32/no-r32 +4836 1/imm32/imm32-is-first-inout +4837 0/imm32/no-disp32 +4838 0/imm32/output-is-write-only +4839 _Primitive-and-reg-with-reg/imm32/next +4840 _Primitive-and-reg-with-reg: +4841 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 +4842 "and"/imm32/name +4843 Single-int-var-in-some-register/imm32/inouts +4844 Single-int-var-in-some-register/imm32/outputs +4845 "21/and-with"/imm32/subx-name +4846 3/imm32/rm32-is-first-output +4847 1/imm32/r32-is-first-inout +4848 0/imm32/no-imm32 +4849 0/imm32/no-disp32 +4850 0/imm32/output-is-write-only +4851 _Primitive-and-reg-with-mem/imm32/next +4852 _Primitive-and-reg-with-mem: +4853 # and-with var1 var2/reg => 21/and-with var1 var2/r32 +4854 "and-with"/imm32/name +4855 Two-args-int-stack-int-reg/imm32/inouts +4856 0/imm32/outputs +4857 "21/and-with"/imm32/subx-name +4858 1/imm32/rm32-is-first-inout +4859 2/imm32/r32-is-second-inout +4860 0/imm32/no-imm32 +4861 0/imm32/no-disp32 +4862 0/imm32/output-is-write-only +4863 _Primitive-and-mem-with-reg/imm32/next +4864 _Primitive-and-mem-with-reg: +4865 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 +4866 "and"/imm32/name +4867 Single-int-var-on-stack/imm32/inouts +4868 Single-int-var-in-some-register/imm32/outputs +4869 "23/and"/imm32/subx-name +4870 1/imm32/rm32-is-first-inout +4871 3/imm32/r32-is-first-output +4872 0/imm32/no-imm32 +4873 0/imm32/no-disp32 +4874 0/imm32/output-is-write-only +4875 _Primitive-and-lit-with-reg/imm32/next +4876 _Primitive-and-lit-with-reg: +4877 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 +4878 "and"/imm32/name +4879 Single-lit-var/imm32/inouts +4880 Single-int-var-in-some-register/imm32/outputs +4881 "81 4/subop/and"/imm32/subx-name +4882 3/imm32/rm32-is-first-output +4883 0/imm32/no-r32 +4884 1/imm32/imm32-is-first-inout +4885 0/imm32/no-disp32 +4886 0/imm32/output-is-write-only +4887 _Primitive-and-lit-with-mem/imm32/next +4888 _Primitive-and-lit-with-mem: +4889 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 +4890 "and-with"/imm32/name +4891 Int-var-and-literal/imm32/inouts +4892 0/imm32/outputs +4893 "81 4/subop/and"/imm32/subx-name +4894 1/imm32/rm32-is-first-inout +4895 0/imm32/no-r32 +4896 2/imm32/imm32-is-first-inout +4897 0/imm32/no-disp32 +4898 0/imm32/output-is-write-only +4899 _Primitive-or-with-eax/imm32/next +4900 # - or +4901 _Primitive-or-with-eax: +4902 # var/eax <- or lit => 0d/or-with-eax lit/imm32 +4903 "or"/imm32/name +4904 Single-lit-var/imm32/inouts +4905 Single-int-var-in-eax/imm32/outputs +4906 "0d/or-with-eax"/imm32/subx-name +4907 0/imm32/no-rm32 +4908 0/imm32/no-r32 +4909 1/imm32/imm32-is-first-inout +4910 0/imm32/no-disp32 +4911 0/imm32/output-is-write-only +4912 _Primitive-or-reg-with-reg/imm32/next +4913 _Primitive-or-reg-with-reg: +4914 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 +4915 "or"/imm32/name +4916 Single-int-var-in-some-register/imm32/inouts +4917 Single-int-var-in-some-register/imm32/outputs +4918 "09/or-with"/imm32/subx-name +4919 3/imm32/rm32-is-first-output +4920 1/imm32/r32-is-first-inout +4921 0/imm32/no-imm32 +4922 0/imm32/no-disp32 +4923 0/imm32/output-is-write-only +4924 _Primitive-or-reg-with-mem/imm32/next +4925 _Primitive-or-reg-with-mem: +4926 # or-with var1 var2/reg => 09/or-with var1 var2/r32 +4927 "or-with"/imm32/name +4928 Two-args-int-stack-int-reg/imm32/inouts +4929 0/imm32/outputs +4930 "09/or-with"/imm32/subx-name +4931 1/imm32/rm32-is-first-inout +4932 2/imm32/r32-is-second-inout +4933 0/imm32/no-imm32 +4934 0/imm32/no-disp32 +4935 0/imm32/output-is-write-only +4936 _Primitive-or-mem-with-reg/imm32/next +4937 _Primitive-or-mem-with-reg: +4938 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 +4939 "or"/imm32/name +4940 Single-int-var-on-stack/imm32/inouts +4941 Single-int-var-in-some-register/imm32/outputs +4942 "0b/or"/imm32/subx-name +4943 1/imm32/rm32-is-first-inout +4944 3/imm32/r32-is-first-output +4945 0/imm32/no-imm32 +4946 0/imm32/no-disp32 +4947 0/imm32/output-is-write-only +4948 _Primitive-or-lit-with-reg/imm32/next +4949 _Primitive-or-lit-with-reg: +4950 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 +4951 "or"/imm32/name +4952 Single-lit-var/imm32/inouts +4953 Single-int-var-in-some-register/imm32/outputs +4954 "81 1/subop/or"/imm32/subx-name +4955 3/imm32/rm32-is-first-output +4956 0/imm32/no-r32 +4957 1/imm32/imm32-is-first-inout +4958 0/imm32/no-disp32 +4959 0/imm32/output-is-write-only +4960 _Primitive-or-lit-with-mem/imm32/next +4961 _Primitive-or-lit-with-mem: +4962 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 +4963 "or-with"/imm32/name +4964 Int-var-and-literal/imm32/inouts +4965 0/imm32/outputs +4966 "81 1/subop/or"/imm32/subx-name +4967 1/imm32/rm32-is-first-inout +4968 0/imm32/no-r32 +4969 2/imm32/imm32-is-second-inout +4970 0/imm32/no-disp32 +4971 0/imm32/output-is-write-only +4972 _Primitive-xor-with-eax/imm32/next +4973 # - xor +4974 _Primitive-xor-with-eax: +4975 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 +4976 "xor"/imm32/name +4977 Single-lit-var/imm32/inouts +4978 Single-int-var-in-eax/imm32/outputs +4979 "35/xor-with-eax"/imm32/subx-name +4980 0/imm32/no-rm32 +4981 0/imm32/no-r32 +4982 1/imm32/imm32-is-first-inout +4983 0/imm32/no-disp32 +4984 0/imm32/output-is-write-only +4985 _Primitive-xor-reg-with-reg/imm32/next +4986 _Primitive-xor-reg-with-reg: +4987 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 +4988 "xor"/imm32/name +4989 Single-int-var-in-some-register/imm32/inouts +4990 Single-int-var-in-some-register/imm32/outputs +4991 "31/xor-with"/imm32/subx-name +4992 3/imm32/rm32-is-first-output +4993 1/imm32/r32-is-first-inout +4994 0/imm32/no-imm32 +4995 0/imm32/no-disp32 +4996 0/imm32/output-is-write-only +4997 _Primitive-xor-reg-with-mem/imm32/next +4998 _Primitive-xor-reg-with-mem: +4999 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 +5000 "xor-with"/imm32/name +5001 Two-args-int-stack-int-reg/imm32/inouts +5002 0/imm32/outputs +5003 "31/xor-with"/imm32/subx-name +5004 1/imm32/rm32-is-first-inout +5005 2/imm32/r32-is-second-inout +5006 0/imm32/no-imm32 +5007 0/imm32/no-disp32 +5008 0/imm32/output-is-write-only +5009 _Primitive-xor-mem-with-reg/imm32/next +5010 _Primitive-xor-mem-with-reg: +5011 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 +5012 "xor"/imm32/name +5013 Single-int-var-on-stack/imm32/inouts +5014 Single-int-var-in-some-register/imm32/outputs +5015 "33/xor"/imm32/subx-name +5016 1/imm32/rm32-is-first-inout +5017 3/imm32/r32-is-first-output +5018 0/imm32/no-imm32 +5019 0/imm32/no-disp32 +5020 0/imm32/output-is-write-only +5021 _Primitive-xor-lit-with-reg/imm32/next +5022 _Primitive-xor-lit-with-reg: +5023 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 +5024 "xor"/imm32/name +5025 Single-lit-var/imm32/inouts +5026 Single-int-var-in-some-register/imm32/outputs +5027 "81 6/subop/xor"/imm32/subx-name +5028 3/imm32/rm32-is-first-output +5029 0/imm32/no-r32 +5030 1/imm32/imm32-is-first-inout +5031 0/imm32/no-disp32 +5032 0/imm32/output-is-write-only +5033 _Primitive-xor-lit-with-mem/imm32/next +5034 _Primitive-xor-lit-with-mem: +5035 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 +5036 "xor-with"/imm32/name +5037 Int-var-and-literal/imm32/inouts +5038 0/imm32/outputs +5039 "81 6/subop/xor"/imm32/subx-name +5040 1/imm32/rm32-is-first-inout +5041 0/imm32/no-r32 +5042 2/imm32/imm32-is-first-inout +5043 0/imm32/no-disp32 +5044 0/imm32/output-is-write-only +5045 _Primitive-copy-to-eax/imm32/next +5046 # - copy +5047 _Primitive-copy-to-eax: +5048 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 +5049 "copy"/imm32/name +5050 Single-lit-var/imm32/inouts +5051 Single-int-var-in-eax/imm32/outputs +5052 "b8/copy-to-eax"/imm32/subx-name +5053 0/imm32/no-rm32 +5054 0/imm32/no-r32 +5055 1/imm32/imm32-is-first-inout +5056 0/imm32/no-disp32 +5057 1/imm32/output-is-write-only +5058 _Primitive-copy-to-ecx/imm32/next +5059 _Primitive-copy-to-ecx: +5060 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 +5061 "copy"/imm32/name +5062 Single-lit-var/imm32/inouts +5063 Single-int-var-in-ecx/imm32/outputs +5064 "b9/copy-to-ecx"/imm32/subx-name +5065 0/imm32/no-rm32 +5066 0/imm32/no-r32 +5067 1/imm32/imm32-is-first-inout +5068 0/imm32/no-disp32 +5069 1/imm32/output-is-write-only +5070 _Primitive-copy-to-edx/imm32/next +5071 _Primitive-copy-to-edx: +5072 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 +5073 "copy"/imm32/name +5074 Single-lit-var/imm32/inouts +5075 Single-int-var-in-edx/imm32/outputs +5076 "ba/copy-to-edx"/imm32/subx-name +5077 0/imm32/no-rm32 +5078 0/imm32/no-r32 +5079 1/imm32/imm32-is-first-inout +5080 0/imm32/no-disp32 +5081 1/imm32/output-is-write-only +5082 _Primitive-copy-to-ebx/imm32/next +5083 _Primitive-copy-to-ebx: +5084 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 +5085 "copy"/imm32/name +5086 Single-lit-var/imm32/inouts +5087 Single-int-var-in-ebx/imm32/outputs +5088 "bb/copy-to-ebx"/imm32/subx-name +5089 0/imm32/no-rm32 +5090 0/imm32/no-r32 +5091 1/imm32/imm32-is-first-inout +5092 0/imm32/no-disp32 +5093 1/imm32/output-is-write-only +5094 _Primitive-copy-to-esi/imm32/next +5095 _Primitive-copy-to-esi: +5096 # var/esi <- copy lit => be/copy-to-esi lit/imm32 +5097 "copy"/imm32/name +5098 Single-lit-var/imm32/inouts +5099 Single-int-var-in-esi/imm32/outputs +5100 "be/copy-to-esi"/imm32/subx-name +5101 0/imm32/no-rm32 +5102 0/imm32/no-r32 +5103 1/imm32/imm32-is-first-inout +5104 0/imm32/no-disp32 +5105 1/imm32/output-is-write-only +5106 _Primitive-copy-to-edi/imm32/next +5107 _Primitive-copy-to-edi: +5108 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 +5109 "copy"/imm32/name +5110 Single-lit-var/imm32/inouts +5111 Single-int-var-in-edi/imm32/outputs +5112 "bf/copy-to-edi"/imm32/subx-name +5113 0/imm32/no-rm32 +5114 0/imm32/no-r32 +5115 1/imm32/imm32-is-first-inout +5116 0/imm32/no-disp32 +5117 1/imm32/output-is-write-only +5118 _Primitive-copy-reg-to-reg/imm32/next +5119 _Primitive-copy-reg-to-reg: +5120 # var1/reg <- copy var2/reg => 89/copy-to var1/rm32 var2/r32 +5121 "copy"/imm32/name +5122 Single-int-var-in-some-register/imm32/inouts +5123 Single-int-var-in-some-register/imm32/outputs +5124 "89/copy-to"/imm32/subx-name +5125 3/imm32/rm32-is-first-output +5126 1/imm32/r32-is-first-inout +5127 0/imm32/no-imm32 +5128 0/imm32/no-disp32 +5129 1/imm32/output-is-write-only +5130 _Primitive-copy-reg-to-mem/imm32/next +5131 _Primitive-copy-reg-to-mem: +5132 # copy-to var1 var2/reg => 89/copy-to var1 var2/r32 +5133 "copy-to"/imm32/name +5134 Two-args-int-stack-int-reg/imm32/inouts +5135 0/imm32/outputs +5136 "89/copy-to"/imm32/subx-name +5137 1/imm32/rm32-is-first-inout +5138 2/imm32/r32-is-second-inout +5139 0/imm32/no-imm32 +5140 0/imm32/no-disp32 +5141 1/imm32/output-is-write-only +5142 _Primitive-copy-mem-to-reg/imm32/next +5143 _Primitive-copy-mem-to-reg: +5144 # var1/reg <- copy var2 => 8b/copy-from var2/rm32 var1/r32 +5145 "copy"/imm32/name +5146 Single-int-var-on-stack/imm32/inouts +5147 Single-int-var-in-some-register/imm32/outputs +5148 "8b/copy-from"/imm32/subx-name +5149 1/imm32/rm32-is-first-inout +5150 3/imm32/r32-is-first-output +5151 0/imm32/no-imm32 +5152 0/imm32/no-disp32 +5153 1/imm32/output-is-write-only +5154 _Primitive-copy-lit-to-reg/imm32/next +5155 _Primitive-copy-lit-to-reg: +5156 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 +5157 "copy"/imm32/name +5158 Single-lit-var/imm32/inouts +5159 Single-int-var-in-some-register/imm32/outputs +5160 "c7 0/subop/copy"/imm32/subx-name +5161 3/imm32/rm32-is-first-output +5162 0/imm32/no-r32 +5163 1/imm32/imm32-is-first-inout +5164 0/imm32/no-disp32 +5165 1/imm32/output-is-write-only +5166 _Primitive-copy-lit-to-mem/imm32/next +5167 _Primitive-copy-lit-to-mem: +5168 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 +5169 "copy-to"/imm32/name +5170 Int-var-and-literal/imm32/inouts +5171 0/imm32/outputs +5172 "c7 0/subop/copy"/imm32/subx-name +5173 1/imm32/rm32-is-first-inout +5174 0/imm32/no-r32 +5175 2/imm32/imm32-is-first-inout +5176 0/imm32/no-disp32 +5177 1/imm32/output-is-write-only +5178 _Primitive-compare-mem-with-reg/imm32/next +5179 # - compare +5180 _Primitive-compare-mem-with-reg: +5181 # compare var1 var2/reg => 39/compare-> var1/rm32 var2/r32 +5182 "compare"/imm32/name +5183 Two-args-int-stack-int-reg/imm32/inouts +5184 0/imm32/outputs +5185 "39/compare->"/imm32/subx-name +5186 1/imm32/rm32-is-first-inout +5187 2/imm32/r32-is-second-inout +5188 0/imm32/no-imm32 +5189 0/imm32/no-disp32 +5190 0/imm32/output-is-write-only +5191 _Primitive-compare-reg-with-mem/imm32/next +5192 _Primitive-compare-reg-with-mem: +5193 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 +5194 "compare"/imm32/name +5195 Two-args-int-reg-int-stack/imm32/inouts +5196 0/imm32/outputs +5197 "3b/compare<-"/imm32/subx-name +5198 2/imm32/rm32-is-second-inout +5199 1/imm32/r32-is-first-inout +5200 0/imm32/no-imm32 +5201 0/imm32/no-disp32 +5202 0/imm32/output-is-write-only +5203 _Primitive-compare-eax-with-literal/imm32/next +5204 _Primitive-compare-eax-with-literal: +5205 # compare var1/eax n => 3d/compare-eax-with n/imm32 +5206 "compare"/imm32/name +5207 Two-args-int-eax-int-literal/imm32/inouts +5208 0/imm32/outputs +5209 "3d/compare-eax-with"/imm32/subx-name +5210 0/imm32/no-rm32 +5211 0/imm32/no-r32 +5212 2/imm32/imm32-is-second-inout +5213 0/imm32/no-disp32 +5214 0/imm32/output-is-write-only +5215 _Primitive-compare-regmem-with-literal/imm32/next +5216 _Primitive-compare-regmem-with-literal: +5217 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 +5218 "compare"/imm32/name +5219 Int-var-and-literal/imm32/inouts +5220 0/imm32/outputs +5221 "81 7/subop/compare"/imm32/subx-name +5222 1/imm32/rm32-is-first-inout +5223 0/imm32/no-r32 +5224 2/imm32/imm32-is-second-inout +5225 0/imm32/no-disp32 +5226 0/imm32/output-is-write-only +5227 _Primitive-multiply-reg-by-mem/imm32/next +5228 # - multiply +5229 _Primitive-multiply-reg-by-mem: +5230 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 +5231 "multiply"/imm32/name +5232 Single-int-var-on-stack/imm32/inouts +5233 Single-int-var-in-some-register/imm32/outputs +5234 "0f af/multiply"/imm32/subx-name +5235 1/imm32/rm32-is-first-inout +5236 3/imm32/r32-is-first-output +5237 0/imm32/no-imm32 +5238 0/imm32/no-disp32 +5239 0/imm32/output-is-write-only +5240 _Primitive-break-if-addr</imm32/next +5241 # - branches +5242 _Primitive-break-if-addr<: +5243 "break-if-addr<"/imm32/name +5244 0/imm32/inouts +5245 0/imm32/outputs +5246 "0f 82/jump-if-addr< break/disp32"/imm32/subx-name +5247 0/imm32/no-rm32 +5248 0/imm32/no-r32 +5249 0/imm32/no-imm32 +5250 0/imm32/no-disp32 +5251 0/imm32/no-output +5252 _Primitive-break-if-addr>=/imm32/next +5253 _Primitive-break-if-addr>=: +5254 "break-if-addr>="/imm32/name +5255 0/imm32/inouts +5256 0/imm32/outputs +5257 "0f 83/jump-if-addr>= break/disp32"/imm32/subx-name +5258 0/imm32/no-rm32 +5259 0/imm32/no-r32 +5260 0/imm32/no-imm32 +5261 0/imm32/no-disp32 +5262 0/imm32/no-output +5263 _Primitive-break-if-=/imm32/next +5264 _Primitive-break-if-=: +5265 "break-if-="/imm32/name +5266 0/imm32/inouts +5267 0/imm32/outputs +5268 "0f 84/jump-if-= break/disp32"/imm32/subx-name +5269 0/imm32/no-rm32 +5270 0/imm32/no-r32 +5271 0/imm32/no-imm32 +5272 0/imm32/no-disp32 +5273 0/imm32/no-output +5274 _Primitive-break-if-!=/imm32/next +5275 _Primitive-break-if-!=: +5276 "break-if-!="/imm32/name +5277 0/imm32/inouts +5278 0/imm32/outputs +5279 "0f 85/jump-if-!= break/disp32"/imm32/subx-name +5280 0/imm32/no-rm32 +5281 0/imm32/no-r32 +5282 0/imm32/no-imm32 +5283 0/imm32/no-disp32 +5284 0/imm32/no-output +5285 _Primitive-break-if-addr<=/imm32/next +5286 _Primitive-break-if-addr<=: +5287 "break-if-addr<="/imm32/name +5288 0/imm32/inouts +5289 0/imm32/outputs +5290 "0f 86/jump-if-addr<= break/disp32"/imm32/subx-name +5291 0/imm32/no-rm32 +5292 0/imm32/no-r32 +5293 0/imm32/no-imm32 +5294 0/imm32/no-disp32 +5295 0/imm32/no-output +5296 _Primitive-break-if-addr>/imm32/next +5297 _Primitive-break-if-addr>: +5298 "break-if-addr>"/imm32/name +5299 0/imm32/inouts +5300 0/imm32/outputs +5301 "0f 87/jump-if-addr> break/disp32"/imm32/subx-name +5302 0/imm32/no-rm32 +5303 0/imm32/no-r32 +5304 0/imm32/no-imm32 +5305 0/imm32/no-disp32 +5306 0/imm32/no-output +5307 _Primitive-break-if-</imm32/next +5308 _Primitive-break-if-<: +5309 "break-if-<"/imm32/name +5310 0/imm32/inouts +5311 0/imm32/outputs +5312 "0f 8c/jump-if-< break/disp32"/imm32/subx-name +5313 0/imm32/no-rm32 5314 0/imm32/no-r32 -5315 1/imm32/imm32-is-first-inout +5315 0/imm32/no-imm32 5316 0/imm32/no-disp32 -5317 0/imm32/output-is-write-only -5318 _Primitive-xor-lit-with-mem/imm32/next -5319 _Primitive-xor-lit-with-mem: -5320 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 -5321 "xor-with"/imm32/name -5322 Int-var-and-literal/imm32/inouts -5323 0/imm32/outputs -5324 "81 6/subop/xor"/imm32/subx-name -5325 1/imm32/rm32-is-first-inout -5326 0/imm32/no-r32 -5327 2/imm32/imm32-is-first-inout -5328 0/imm32/no-disp32 -5329 0/imm32/output-is-write-only -5330 _Primitive-copy-to-eax/imm32/next -5331 # - copy -5332 _Primitive-copy-to-eax: -5333 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 -5334 "copy"/imm32/name -5335 Single-lit-var/imm32/inouts -5336 Single-int-var-in-eax/imm32/outputs -5337 "b8/copy-to-eax"/imm32/subx-name -5338 0/imm32/no-rm32 -5339 0/imm32/no-r32 -5340 1/imm32/imm32-is-first-inout -5341 0/imm32/no-disp32 -5342 1/imm32/output-is-write-only -5343 _Primitive-copy-to-ecx/imm32/next -5344 _Primitive-copy-to-ecx: -5345 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 -5346 "copy"/imm32/name -5347 Single-lit-var/imm32/inouts -5348 Single-int-var-in-ecx/imm32/outputs -5349 "b9/copy-to-ecx"/imm32/subx-name -5350 0/imm32/no-rm32 -5351 0/imm32/no-r32 -5352 1/imm32/imm32-is-first-inout -5353 0/imm32/no-disp32 -5354 1/imm32/output-is-write-only -5355 _Primitive-copy-to-edx/imm32/next -5356 _Primitive-copy-to-edx: -5357 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 -5358 "copy"/imm32/name -5359 Single-lit-var/imm32/inouts -5360 Single-int-var-in-edx/imm32/outputs -5361 "ba/copy-to-edx"/imm32/subx-name -5362 0/imm32/no-rm32 -5363 0/imm32/no-r32 -5364 1/imm32/imm32-is-first-inout -5365 0/imm32/no-disp32 -5366 1/imm32/output-is-write-only -5367 _Primitive-copy-to-ebx/imm32/next -5368 _Primitive-copy-to-ebx: -5369 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 -5370 "copy"/imm32/name -5371 Single-lit-var/imm32/inouts -5372 Single-int-var-in-ebx/imm32/outputs -5373 "bb/copy-to-ebx"/imm32/subx-name -5374 0/imm32/no-rm32 -5375 0/imm32/no-r32 -5376 1/imm32/imm32-is-first-inout -5377 0/imm32/no-disp32 -5378 1/imm32/output-is-write-only -5379 _Primitive-copy-to-esi/imm32/next -5380 _Primitive-copy-to-esi: -5381 # var/esi <- copy lit => be/copy-to-esi lit/imm32 -5382 "copy"/imm32/name -5383 Single-lit-var/imm32/inouts -5384 Single-int-var-in-esi/imm32/outputs -5385 "be/copy-to-esi"/imm32/subx-name -5386 0/imm32/no-rm32 -5387 0/imm32/no-r32 -5388 1/imm32/imm32-is-first-inout -5389 0/imm32/no-disp32 -5390 1/imm32/output-is-write-only -5391 _Primitive-copy-to-edi/imm32/next -5392 _Primitive-copy-to-edi: -5393 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 -5394 "copy"/imm32/name -5395 Single-lit-var/imm32/inouts -5396 Single-int-var-in-edi/imm32/outputs -5397 "bf/copy-to-edi"/imm32/subx-name -5398 0/imm32/no-rm32 -5399 0/imm32/no-r32 -5400 1/imm32/imm32-is-first-inout -5401 0/imm32/no-disp32 -5402 1/imm32/output-is-write-only -5403 _Primitive-copy-reg-to-reg/imm32/next -5404 _Primitive-copy-reg-to-reg: -5405 # var1/reg <- copy var2/reg => 89/copy-to var1/rm32 var2/r32 -5406 "copy"/imm32/name -5407 Single-int-var-in-some-register/imm32/inouts -5408 Single-int-var-in-some-register/imm32/outputs -5409 "89/copy-to"/imm32/subx-name -5410 3/imm32/rm32-is-first-output -5411 1/imm32/r32-is-first-inout -5412 0/imm32/no-imm32 -5413 0/imm32/no-disp32 -5414 1/imm32/output-is-write-only -5415 _Primitive-copy-reg-to-mem/imm32/next -5416 _Primitive-copy-reg-to-mem: -5417 # copy-to var1 var2/reg => 89/copy-to var1 var2/r32 -5418 "copy-to"/imm32/name -5419 Two-args-int-stack-int-reg/imm32/inouts -5420 0/imm32/outputs -5421 "89/copy-to"/imm32/subx-name -5422 1/imm32/rm32-is-first-inout -5423 2/imm32/r32-is-second-inout -5424 0/imm32/no-imm32 -5425 0/imm32/no-disp32 -5426 1/imm32/output-is-write-only -5427 _Primitive-copy-mem-to-reg/imm32/next -5428 _Primitive-copy-mem-to-reg: -5429 # var1/reg <- copy var2 => 8b/copy-from var2/rm32 var1/r32 -5430 "copy"/imm32/name -5431 Single-int-var-on-stack/imm32/inouts -5432 Single-int-var-in-some-register/imm32/outputs -5433 "8b/copy-from"/imm32/subx-name -5434 1/imm32/rm32-is-first-inout -5435 3/imm32/r32-is-first-output +5317 0/imm32/no-output +5318 _Primitive-break-if->=/imm32/next +5319 _Primitive-break-if->=: +5320 "break-if->="/imm32/name +5321 0/imm32/inouts +5322 0/imm32/outputs +5323 "0f 8d/jump-if->= break/disp32"/imm32/subx-name +5324 0/imm32/no-rm32 +5325 0/imm32/no-r32 +5326 0/imm32/no-imm32 +5327 0/imm32/no-disp32 +5328 0/imm32/no-output +5329 _Primitive-break-if-<=/imm32/next +5330 _Primitive-break-if-<=: +5331 "break-if-<="/imm32/name +5332 0/imm32/inouts +5333 0/imm32/outputs +5334 "0f 8e/jump-if-<= break/disp32"/imm32/subx-name +5335 0/imm32/no-rm32 +5336 0/imm32/no-r32 +5337 0/imm32/no-imm32 +5338 0/imm32/no-disp32 +5339 0/imm32/no-output +5340 _Primitive-break-if->/imm32/next +5341 _Primitive-break-if->: +5342 "break-if->"/imm32/name +5343 0/imm32/inouts +5344 0/imm32/outputs +5345 "0f 8f/jump-if-> break/disp32"/imm32/subx-name +5346 0/imm32/no-rm32 +5347 0/imm32/no-r32 +5348 0/imm32/no-imm32 +5349 0/imm32/no-disp32 +5350 0/imm32/no-output +5351 _Primitive-loop-if-addr</imm32/next +5352 _Primitive-loop-if-addr<: +5353 "loop-if-addr<"/imm32/name +5354 0/imm32/inouts +5355 0/imm32/outputs +5356 "0f 82/jump-if-addr< loop/disp32"/imm32/subx-name +5357 0/imm32/no-rm32 +5358 0/imm32/no-r32 +5359 0/imm32/no-imm32 +5360 0/imm32/no-disp32 +5361 0/imm32/no-output +5362 _Primitive-loop-if-addr>=/imm32/next +5363 _Primitive-loop-if-addr>=: +5364 "loop-if-addr>="/imm32/name +5365 0/imm32/inouts +5366 0/imm32/outputs +5367 "0f 83/jump-if-addr>= loop/disp32"/imm32/subx-name +5368 0/imm32/no-rm32 +5369 0/imm32/no-r32 +5370 0/imm32/no-imm32 +5371 0/imm32/no-disp32 +5372 0/imm32/no-output +5373 _Primitive-loop-if-=/imm32/next +5374 _Primitive-loop-if-=: +5375 "loop-if-="/imm32/name +5376 0/imm32/inouts +5377 0/imm32/outputs +5378 "0f 84/jump-if-= loop/disp32"/imm32/subx-name +5379 0/imm32/no-rm32 +5380 0/imm32/no-r32 +5381 0/imm32/no-imm32 +5382 0/imm32/no-disp32 +5383 0/imm32/no-output +5384 _Primitive-loop-if-!=/imm32/next +5385 _Primitive-loop-if-!=: +5386 "loop-if-!="/imm32/name +5387 0/imm32/inouts +5388 0/imm32/outputs +5389 "0f 85/jump-if-!= loop/disp32"/imm32/subx-name +5390 0/imm32/no-rm32 +5391 0/imm32/no-r32 +5392 0/imm32/no-imm32 +5393 0/imm32/no-disp32 +5394 0/imm32/no-output +5395 _Primitive-loop-if-addr<=/imm32/next +5396 _Primitive-loop-if-addr<=: +5397 "loop-if-addr<="/imm32/name +5398 0/imm32/inouts +5399 0/imm32/outputs +5400 "0f 86/jump-if-addr<= loop/disp32"/imm32/subx-name +5401 0/imm32/no-rm32 +5402 0/imm32/no-r32 +5403 0/imm32/no-imm32 +5404 0/imm32/no-disp32 +5405 0/imm32/no-output +5406 _Primitive-loop-if-addr>/imm32/next +5407 _Primitive-loop-if-addr>: +5408 "loop-if-addr>"/imm32/name +5409 0/imm32/inouts +5410 0/imm32/outputs +5411 "0f 87/jump-if-addr> loop/disp32"/imm32/subx-name +5412 0/imm32/no-rm32 +5413 0/imm32/no-r32 +5414 0/imm32/no-imm32 +5415 0/imm32/no-disp32 +5416 0/imm32/no-output +5417 _Primitive-loop-if-</imm32/next +5418 _Primitive-loop-if-<: +5419 "loop-if-<"/imm32/name +5420 0/imm32/inouts +5421 0/imm32/outputs +5422 "0f 8c/jump-if-< loop/disp32"/imm32/subx-name +5423 0/imm32/no-rm32 +5424 0/imm32/no-r32 +5425 0/imm32/no-imm32 +5426 0/imm32/no-disp32 +5427 0/imm32/no-output +5428 _Primitive-loop-if->=/imm32/next +5429 _Primitive-loop-if->=: +5430 "loop-if->="/imm32/name +5431 0/imm32/inouts +5432 0/imm32/outputs +5433 "0f 8d/jump-if->= loop/disp32"/imm32/subx-name +5434 0/imm32/no-rm32 +5435 0/imm32/no-r32 5436 0/imm32/no-imm32 5437 0/imm32/no-disp32 -5438 1/imm32/output-is-write-only -5439 _Primitive-copy-lit-to-reg/imm32/next -5440 _Primitive-copy-lit-to-reg: -5441 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 -5442 "copy"/imm32/name -5443 Single-lit-var/imm32/inouts -5444 Single-int-var-in-some-register/imm32/outputs -5445 "c7 0/subop/copy"/imm32/subx-name -5446 3/imm32/rm32-is-first-output -5447 0/imm32/no-r32 -5448 1/imm32/imm32-is-first-inout -5449 0/imm32/no-disp32 -5450 1/imm32/output-is-write-only -5451 _Primitive-copy-lit-to-mem/imm32/next -5452 _Primitive-copy-lit-to-mem: -5453 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 -5454 "copy-to"/imm32/name -5455 Int-var-and-literal/imm32/inouts -5456 0/imm32/outputs -5457 "c7 0/subop/copy"/imm32/subx-name -5458 1/imm32/rm32-is-first-inout -5459 0/imm32/no-r32 -5460 2/imm32/imm32-is-first-inout -5461 0/imm32/no-disp32 -5462 1/imm32/output-is-write-only -5463 _Primitive-compare-mem-with-reg/imm32/next -5464 # - compare -5465 _Primitive-compare-mem-with-reg: -5466 # compare var1 var2/reg => 39/compare-> var1/rm32 var2/r32 -5467 "compare"/imm32/name -5468 Two-args-int-stack-int-reg/imm32/inouts -5469 0/imm32/outputs -5470 "39/compare->"/imm32/subx-name -5471 1/imm32/rm32-is-first-inout -5472 2/imm32/r32-is-second-inout -5473 0/imm32/no-imm32 -5474 0/imm32/no-disp32 -5475 0/imm32/output-is-write-only -5476 _Primitive-compare-reg-with-mem/imm32/next -5477 _Primitive-compare-reg-with-mem: -5478 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 -5479 "compare"/imm32/name -5480 Two-args-int-reg-int-stack/imm32/inouts -5481 0/imm32/outputs -5482 "3b/compare<-"/imm32/subx-name -5483 2/imm32/rm32-is-second-inout -5484 1/imm32/r32-is-first-inout -5485 0/imm32/no-imm32 -5486 0/imm32/no-disp32 -5487 0/imm32/output-is-write-only -5488 _Primitive-compare-eax-with-literal/imm32/next -5489 _Primitive-compare-eax-with-literal: -5490 # compare var1/eax n => 3d/compare-eax-with n/imm32 -5491 "compare"/imm32/name -5492 Two-args-int-eax-int-literal/imm32/inouts -5493 0/imm32/outputs -5494 "3d/compare-eax-with"/imm32/subx-name -5495 0/imm32/no-rm32 -5496 0/imm32/no-r32 -5497 2/imm32/imm32-is-second-inout -5498 0/imm32/no-disp32 -5499 0/imm32/output-is-write-only -5500 _Primitive-compare-regmem-with-literal/imm32/next -5501 _Primitive-compare-regmem-with-literal: -5502 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 -5503 "compare"/imm32/name -5504 Int-var-and-literal/imm32/inouts -5505 0/imm32/outputs -5506 "81 7/subop/compare"/imm32/subx-name -5507 1/imm32/rm32-is-first-inout -5508 0/imm32/no-r32 -5509 2/imm32/imm32-is-second-inout -5510 0/imm32/no-disp32 -5511 0/imm32/output-is-write-only -5512 _Primitive-multiply-reg-by-mem/imm32/next -5513 # - multiply -5514 _Primitive-multiply-reg-by-mem: -5515 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 -5516 "multiply"/imm32/name -5517 Single-int-var-on-stack/imm32/inouts -5518 Single-int-var-in-some-register/imm32/outputs -5519 "0f af/multiply"/imm32/subx-name -5520 1/imm32/rm32-is-first-inout -5521 3/imm32/r32-is-first-output -5522 0/imm32/no-imm32 -5523 0/imm32/no-disp32 -5524 0/imm32/output-is-write-only -5525 _Primitive-break-if-addr</imm32/next -5526 # - branches -5527 _Primitive-break-if-addr<: -5528 "break-if-addr<"/imm32/name -5529 0/imm32/inouts -5530 0/imm32/outputs -5531 "0f 82/jump-if-addr< break/disp32"/imm32/subx-name -5532 0/imm32/no-rm32 -5533 0/imm32/no-r32 -5534 0/imm32/no-imm32 -5535 0/imm32/no-disp32 -5536 0/imm32/no-output -5537 _Primitive-break-if-addr>=/imm32/next -5538 _Primitive-break-if-addr>=: -5539 "break-if-addr>="/imm32/name -5540 0/imm32/inouts -5541 0/imm32/outputs -5542 "0f 83/jump-if-addr>= break/disp32"/imm32/subx-name -5543 0/imm32/no-rm32 -5544 0/imm32/no-r32 -5545 0/imm32/no-imm32 -5546 0/imm32/no-disp32 -5547 0/imm32/no-output -5548 _Primitive-break-if-=/imm32/next -5549 _Primitive-break-if-=: -5550 "break-if-="/imm32/name -5551 0/imm32/inouts -5552 0/imm32/outputs -5553 "0f 84/jump-if-= break/disp32"/imm32/subx-name -5554 0/imm32/no-rm32 -5555 0/imm32/no-r32 -5556 0/imm32/no-imm32 -5557 0/imm32/no-disp32 -5558 0/imm32/no-output -5559 _Primitive-break-if-!=/imm32/next -5560 _Primitive-break-if-!=: -5561 "break-if-!="/imm32/name -5562 0/imm32/inouts -5563 0/imm32/outputs -5564 "0f 85/jump-if-!= break/disp32"/imm32/subx-name -5565 0/imm32/no-rm32 -5566 0/imm32/no-r32 -5567 0/imm32/no-imm32 -5568 0/imm32/no-disp32 -5569 0/imm32/no-output -5570 _Primitive-break-if-addr<=/imm32/next -5571 _Primitive-break-if-addr<=: -5572 "break-if-addr<="/imm32/name -5573 0/imm32/inouts -5574 0/imm32/outputs -5575 "0f 86/jump-if-addr<= break/disp32"/imm32/subx-name -5576 0/imm32/no-rm32 -5577 0/imm32/no-r32 -5578 0/imm32/no-imm32 -5579 0/imm32/no-disp32 -5580 0/imm32/no-output -5581 _Primitive-break-if-addr>/imm32/next -5582 _Primitive-break-if-addr>: -5583 "break-if-addr>"/imm32/name -5584 0/imm32/inouts -5585 0/imm32/outputs -5586 "0f 87/jump-if-addr> break/disp32"/imm32/subx-name -5587 0/imm32/no-rm32 -5588 0/imm32/no-r32 -5589 0/imm32/no-imm32 -5590 0/imm32/no-disp32 -5591 0/imm32/no-output -5592 _Primitive-break-if-</imm32/next -5593 _Primitive-break-if-<: -5594 "break-if-<"/imm32/name -5595 0/imm32/inouts -5596 0/imm32/outputs -5597 "0f 8c/jump-if-< break/disp32"/imm32/subx-name -5598 0/imm32/no-rm32 -5599 0/imm32/no-r32 -5600 0/imm32/no-imm32 -5601 0/imm32/no-disp32 -5602 0/imm32/no-output -5603 _Primitive-break-if->=/imm32/next -5604 _Primitive-break-if->=: -5605 "break-if->="/imm32/name -5606 0/imm32/inouts -5607 0/imm32/outputs -5608 "0f 8d/jump-if->= break/disp32"/imm32/subx-name -5609 0/imm32/no-rm32 -5610 0/imm32/no-r32 -5611 0/imm32/no-imm32 -5612 0/imm32/no-disp32 -5613 0/imm32/no-output -5614 _Primitive-break-if-<=/imm32/next -5615 _Primitive-break-if-<=: -5616 "break-if-<="/imm32/name -5617 0/imm32/inouts -5618 0/imm32/outputs -5619 "0f 8e/jump-if-<= break/disp32"/imm32/subx-name -5620 0/imm32/no-rm32 -5621 0/imm32/no-r32 -5622 0/imm32/no-imm32 -5623 0/imm32/no-disp32 -5624 0/imm32/no-output -5625 _Primitive-break-if->/imm32/next -5626 _Primitive-break-if->: -5627 "break-if->"/imm32/name -5628 0/imm32/inouts -5629 0/imm32/outputs -5630 "0f 8f/jump-if-> break/disp32"/imm32/subx-name -5631 0/imm32/no-rm32 -5632 0/imm32/no-r32 -5633 0/imm32/no-imm32 -5634 0/imm32/no-disp32 -5635 0/imm32/no-output -5636 _Primitive-loop-if-addr</imm32/next -5637 _Primitive-loop-if-addr<: -5638 "loop-if-addr<"/imm32/name -5639 0/imm32/inouts -5640 0/imm32/outputs -5641 "0f 82/jump-if-addr< loop/disp32"/imm32/subx-name -5642 0/imm32/no-rm32 -5643 0/imm32/no-r32 -5644 0/imm32/no-imm32 -5645 0/imm32/no-disp32 -5646 0/imm32/no-output -5647 _Primitive-loop-if-addr>=/imm32/next -5648 _Primitive-loop-if-addr>=: -5649 "loop-if-addr>="/imm32/name -5650 0/imm32/inouts -5651 0/imm32/outputs -5652 "0f 83/jump-if-addr>= loop/disp32"/imm32/subx-name -5653 0/imm32/no-rm32 -5654 0/imm32/no-r32 -5655 0/imm32/no-imm32 -5656 0/imm32/no-disp32 -5657 0/imm32/no-output -5658 _Primitive-loop-if-=/imm32/next -5659 _Primitive-loop-if-=: -5660 "loop-if-="/imm32/name -5661 0/imm32/inouts -5662 0/imm32/outputs -5663 "0f 84/jump-if-= loop/disp32"/imm32/subx-name -5664 0/imm32/no-rm32 -5665 0/imm32/no-r32 -5666 0/imm32/no-imm32 -5667 0/imm32/no-disp32 -5668 0/imm32/no-output -5669 _Primitive-loop-if-!=/imm32/next -5670 _Primitive-loop-if-!=: -5671 "loop-if-!="/imm32/name -5672 0/imm32/inouts -5673 0/imm32/outputs -5674 "0f 85/jump-if-!= loop/disp32"/imm32/subx-name -5675 0/imm32/no-rm32 -5676 0/imm32/no-r32 -5677 0/imm32/no-imm32 -5678 0/imm32/no-disp32 -5679 0/imm32/no-output -5680 _Primitive-loop-if-addr<=/imm32/next -5681 _Primitive-loop-if-addr<=: -5682 "loop-if-addr<="/imm32/name -5683 0/imm32/inouts -5684 0/imm32/outputs -5685 "0f 86/jump-if-addr<= loop/disp32"/imm32/subx-name -5686 0/imm32/no-rm32 -5687 0/imm32/no-r32 -5688 0/imm32/no-imm32 -5689 0/imm32/no-disp32 -5690 0/imm32/no-output -5691 _Primitive-loop-if-addr>/imm32/next -5692 _Primitive-loop-if-addr>: -5693 "loop-if-addr>"/imm32/name -5694 0/imm32/inouts -5695 0/imm32/outputs -5696 "0f 87/jump-if-addr> loop/disp32"/imm32/subx-name -5697 0/imm32/no-rm32 -5698 0/imm32/no-r32 -5699 0/imm32/no-imm32 -5700 0/imm32/no-disp32 -5701 0/imm32/no-output -5702 _Primitive-loop-if-</imm32/next -5703 _Primitive-loop-if-<: -5704 "loop-if-<"/imm32/name -5705 0/imm32/inouts -5706 0/imm32/outputs -5707 "0f 8c/jump-if-< loop/disp32"/imm32/subx-name -5708 0/imm32/no-rm32 -5709 0/imm32/no-r32 -5710 0/imm32/no-imm32 -5711 0/imm32/no-disp32 -5712 0/imm32/no-output -5713 _Primitive-loop-if->=/imm32/next -5714 _Primitive-loop-if->=: -5715 "loop-if->="/imm32/name -5716 0/imm32/inouts -5717 0/imm32/outputs -5718 "0f 8d/jump-if->= loop/disp32"/imm32/subx-name -5719 0/imm32/no-rm32 -5720 0/imm32/no-r32 -5721 0/imm32/no-imm32 -5722 0/imm32/no-disp32 -5723 0/imm32/no-output -5724 _Primitive-loop-if-<=/imm32/next -5725 _Primitive-loop-if-<=: -5726 "loop-if-<="/imm32/name -5727 0/imm32/inouts -5728 0/imm32/outputs -5729 "0f 8e/jump-if-<= loop/disp32"/imm32/subx-name -5730 0/imm32/no-rm32 -5731 0/imm32/no-r32 -5732 0/imm32/no-imm32 -5733 0/imm32/no-disp32 -5734 0/imm32/no-output -5735 _Primitive-loop-if->/imm32/next -5736 _Primitive-loop-if->: -5737 "loop-if->"/imm32/name -5738 0/imm32/inouts -5739 0/imm32/outputs -5740 "0f 8f/jump-if-> loop/disp32"/imm32/subx-name -5741 0/imm32/no-rm32 -5742 0/imm32/no-r32 -5743 0/imm32/no-imm32 -5744 0/imm32/no-disp32 -5745 0/imm32/no-output -5746 _Primitive-loop/imm32/next # we probably don't need an unconditional break -5747 _Primitive-loop: -5748 "loop"/imm32/name -5749 0/imm32/inouts -5750 0/imm32/outputs -5751 "e9/jump loop/disp32"/imm32/subx-name -5752 0/imm32/no-rm32 -5753 0/imm32/no-r32 -5754 0/imm32/no-imm32 -5755 0/imm32/no-disp32 -5756 0/imm32/no-output -5757 _Primitive-break-if-addr<-named/imm32/next -5758 # - branches to named blocks -5759 _Primitive-break-if-addr<-named: -5760 "break-if-addr<"/imm32/name -5761 Single-lit-var/imm32/inouts -5762 0/imm32/outputs -5763 "0f 82/jump-if-addr<"/imm32/subx-name -5764 0/imm32/no-rm32 -5765 0/imm32/no-r32 -5766 0/imm32/no-imm32 -5767 1/imm32/disp32-is-first-inout -5768 0/imm32/no-output -5769 _Primitive-break-if-addr>=-named/imm32/next -5770 _Primitive-break-if-addr>=-named: -5771 "break-if-addr>="/imm32/name -5772 Single-lit-var/imm32/inouts -5773 0/imm32/outputs -5774 "0f 83/jump-if-addr>="/imm32/subx-name -5775 0/imm32/no-rm32 -5776 0/imm32/no-r32 -5777 0/imm32/no-imm32 -5778 1/imm32/disp32-is-first-inout -5779 0/imm32/no-output -5780 _Primitive-break-if-=-named/imm32/next -5781 _Primitive-break-if-=-named: -5782 "break-if-="/imm32/name -5783 Single-lit-var/imm32/inouts -5784 0/imm32/outputs -5785 "0f 84/jump-if-="/imm32/subx-name -5786 0/imm32/no-rm32 -5787 0/imm32/no-r32 -5788 0/imm32/no-imm32 -5789 1/imm32/disp32-is-first-inout -5790 0/imm32/no-output -5791 _Primitive-break-if-!=-named/imm32/next -5792 _Primitive-break-if-!=-named: -5793 "break-if-!="/imm32/name -5794 Single-lit-var/imm32/inouts -5795 0/imm32/outputs -5796 "0f 85/jump-if-!="/imm32/subx-name -5797 0/imm32/no-rm32 -5798 0/imm32/no-r32 -5799 0/imm32/no-imm32 -5800 1/imm32/disp32-is-first-inout -5801 0/imm32/no-output -5802 _Primitive-break-if-addr<=-named/imm32/next -5803 _Primitive-break-if-addr<=-named: -5804 "break-if-addr<="/imm32/name -5805 Single-lit-var/imm32/inouts -5806 0/imm32/outputs -5807 "0f 86/jump-if-addr<="/imm32/subx-name -5808 0/imm32/no-rm32 -5809 0/imm32/no-r32 -5810 0/imm32/no-imm32 -5811 1/imm32/disp32-is-first-inout -5812 0/imm32/no-output -5813 _Primitive-break-if-addr>-named/imm32/next -5814 _Primitive-break-if-addr>-named: -5815 "break-if-addr>"/imm32/name -5816 Single-lit-var/imm32/inouts -5817 0/imm32/outputs -5818 "0f 87/jump-if-addr>"/imm32/subx-name -5819 0/imm32/no-rm32 -5820 0/imm32/no-r32 -5821 0/imm32/no-imm32 -5822 1/imm32/disp32-is-first-inout -5823 0/imm32/no-output -5824 _Primitive-break-if-<-named/imm32/next -5825 _Primitive-break-if-<-named: -5826 "break-if-<"/imm32/name -5827 Single-lit-var/imm32/inouts -5828 0/imm32/outputs -5829 "0f 8c/jump-if-<"/imm32/subx-name -5830 0/imm32/no-rm32 -5831 0/imm32/no-r32 -5832 0/imm32/no-imm32 -5833 1/imm32/disp32-is-first-inout -5834 0/imm32/no-output -5835 _Primitive-break-if->=-named/imm32/next -5836 _Primitive-break-if->=-named: -5837 "break-if->="/imm32/name -5838 Single-lit-var/imm32/inouts -5839 0/imm32/outputs -5840 "0f 8d/jump-if->="/imm32/subx-name -5841 0/imm32/no-rm32 -5842 0/imm32/no-r32 -5843 0/imm32/no-imm32 -5844 1/imm32/disp32-is-first-inout -5845 0/imm32/no-output -5846 _Primitive-break-if-<=-named/imm32/next -5847 _Primitive-break-if-<=-named: -5848 "break-if-<="/imm32/name -5849 Single-lit-var/imm32/inouts -5850 0/imm32/outputs -5851 "0f 8e/jump-if-<="/imm32/subx-name -5852 0/imm32/no-rm32 -5853 0/imm32/no-r32 -5854 0/imm32/no-imm32 -5855 1/imm32/disp32-is-first-inout -5856 0/imm32/no-output -5857 _Primitive-break-if->-named/imm32/next -5858 _Primitive-break-if->-named: -5859 "break-if->"/imm32/name -5860 Single-lit-var/imm32/inouts -5861 0/imm32/outputs -5862 "0f 8f/jump-if->"/imm32/subx-name -5863 0/imm32/no-rm32 -5864 0/imm32/no-r32 -5865 0/imm32/no-imm32 -5866 1/imm32/disp32-is-first-inout -5867 0/imm32/no-output -5868 _Primitive-loop-if-addr<-named/imm32/next -5869 _Primitive-loop-if-addr<-named: -5870 "loop-if-addr<"/imm32/name -5871 Single-lit-var/imm32/inouts -5872 0/imm32/outputs -5873 "0f 82/jump-if-addr<"/imm32/subx-name -5874 0/imm32/no-rm32 -5875 0/imm32/no-r32 -5876 0/imm32/no-imm32 -5877 1/imm32/disp32-is-first-inout -5878 0/imm32/no-output -5879 _Primitive-loop-if-addr>=-named/imm32/next -5880 _Primitive-loop-if-addr>=-named: -5881 "loop-if-addr>="/imm32/name -5882 Single-lit-var/imm32/inouts -5883 0/imm32/outputs -5884 "0f 83/jump-if-addr>="/imm32/subx-name -5885 0/imm32/no-rm32 -5886 0/imm32/no-r32 -5887 0/imm32/no-imm32 -5888 1/imm32/disp32-is-first-inout -5889 0/imm32/no-output -5890 _Primitive-loop-if-=-named/imm32/next -5891 _Primitive-loop-if-=-named: -5892 "loop-if-="/imm32/name -5893 Single-lit-var/imm32/inouts -5894 0/imm32/outputs -5895 "0f 84/jump-if-="/imm32/subx-name -5896 0/imm32/no-rm32 -5897 0/imm32/no-r32 -5898 0/imm32/no-imm32 -5899 1/imm32/disp32-is-first-inout -5900 0/imm32/no-output -5901 _Primitive-loop-if-!=-named/imm32/next -5902 _Primitive-loop-if-!=-named: -5903 "loop-if-!="/imm32/name -5904 Single-lit-var/imm32/inouts -5905 0/imm32/outputs -5906 "0f 85/jump-if-!="/imm32/subx-name -5907 0/imm32/no-rm32 -5908 0/imm32/no-r32 -5909 0/imm32/no-imm32 -5910 1/imm32/disp32-is-first-inout -5911 0/imm32/no-output -5912 _Primitive-loop-if-addr<=-named/imm32/next -5913 _Primitive-loop-if-addr<=-named: -5914 "loop-if-addr<="/imm32/name -5915 Single-lit-var/imm32/inouts -5916 0/imm32/outputs -5917 "0f 86/jump-if-addr<="/imm32/subx-name -5918 0/imm32/no-rm32 -5919 0/imm32/no-r32 -5920 0/imm32/no-imm32 -5921 1/imm32/disp32-is-first-inout -5922 0/imm32/no-output -5923 _Primitive-loop-if-addr>-named/imm32/next -5924 _Primitive-loop-if-addr>-named: -5925 "loop-if-addr>"/imm32/name -5926 Single-lit-var/imm32/inouts -5927 0/imm32/outputs -5928 "0f 87/jump-if-addr>"/imm32/subx-name -5929 0/imm32/no-rm32 -5930 0/imm32/no-r32 -5931 0/imm32/no-imm32 -5932 1/imm32/disp32-is-first-inout -5933 0/imm32/no-output -5934 _Primitive-loop-if-<-named/imm32/next -5935 _Primitive-loop-if-<-named: -5936 "loop-if-<"/imm32/name -5937 Single-lit-var/imm32/inouts -5938 0/imm32/outputs -5939 "0f 8c/jump-if-<"/imm32/subx-name -5940 0/imm32/no-rm32 -5941 0/imm32/no-r32 -5942 0/imm32/no-imm32 -5943 1/imm32/disp32-is-first-inout -5944 0/imm32/no-output -5945 _Primitive-loop-if->=-named/imm32/next -5946 _Primitive-loop-if->=-named: -5947 "loop-if->="/imm32/name -5948 Single-lit-var/imm32/inouts -5949 0/imm32/outputs -5950 "0f 8d/jump-if->="/imm32/subx-name -5951 0/imm32/no-rm32 -5952 0/imm32/no-r32 -5953 0/imm32/no-imm32 -5954 1/imm32/disp32-is-first-inout -5955 0/imm32/no-output -5956 _Primitive-loop-if-<=-named/imm32/next -5957 _Primitive-loop-if-<=-named: -5958 "loop-if-<="/imm32/name -5959 Single-lit-var/imm32/inouts -5960 0/imm32/outputs -5961 "0f 8e/jump-if-<="/imm32/subx-name -5962 0/imm32/no-rm32 -5963 0/imm32/no-r32 -5964 0/imm32/no-imm32 -5965 1/imm32/disp32-is-first-inout -5966 0/imm32/no-output -5967 _Primitive-loop-if->-named/imm32/next -5968 _Primitive-loop-if->-named: -5969 "loop-if->"/imm32/name -5970 Single-lit-var/imm32/inouts -5971 0/imm32/outputs -5972 "0f 8f/jump-if->"/imm32/subx-name -5973 0/imm32/no-rm32 -5974 0/imm32/no-r32 -5975 0/imm32/no-imm32 -5976 1/imm32/disp32-is-first-inout -5977 0/imm32/no-output -5978 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break -5979 _Primitive-loop-named: -5980 "loop"/imm32/name -5981 Single-lit-var/imm32/inouts -5982 0/imm32/outputs -5983 "e9/jump"/imm32/subx-name -5984 0/imm32/no-rm32 -5985 0/imm32/no-r32 -5986 0/imm32/no-imm32 -5987 1/imm32/disp32-is-first-inout -5988 0/imm32/no-output -5989 0/imm32/next -5990 -5991 Single-int-var-on-stack: -5992 Int-var-on-stack/imm32 -5993 0/imm32/next -5994 -5995 Int-var-on-stack: -5996 "arg1"/imm32/name -5997 Type-int/imm32 -5998 1/imm32/some-block-depth -5999 1/imm32/some-stack-offset -6000 0/imm32/no-register -6001 -6002 Two-args-int-stack-int-reg: -6003 Int-var-on-stack/imm32 -6004 Single-int-var-in-some-register/imm32/next -6005 -6006 Two-args-int-reg-int-stack: -6007 Int-var-in-some-register/imm32 -6008 Single-int-var-on-stack/imm32/next -6009 -6010 Two-args-int-eax-int-literal: -6011 Int-var-in-eax/imm32 -6012 Single-lit-var/imm32/next -6013 -6014 Int-var-and-literal: -6015 Int-var-on-stack/imm32 -6016 Single-lit-var/imm32/next -6017 -6018 Single-int-var-in-some-register: -6019 Int-var-in-some-register/imm32 -6020 0/imm32/next -6021 -6022 Int-var-in-some-register: -6023 "arg1"/imm32/name -6024 Type-int/imm32 -6025 1/imm32/some-block-depth -6026 0/imm32/no-stack-offset -6027 "*"/imm32/register -6028 -6029 Single-int-var-in-eax: -6030 Int-var-in-eax/imm32 -6031 0/imm32/next -6032 -6033 Int-var-in-eax: -6034 "arg1"/imm32/name -6035 Type-int/imm32 -6036 1/imm32/some-block-depth -6037 0/imm32/no-stack-offset -6038 "eax"/imm32/register -6039 -6040 Single-int-var-in-ecx: -6041 Int-var-in-ecx/imm32 -6042 0/imm32/next -6043 -6044 Int-var-in-ecx: -6045 "arg1"/imm32/name -6046 Type-int/imm32 -6047 1/imm32/some-block-depth -6048 0/imm32/no-stack-offset -6049 "ecx"/imm32/register -6050 -6051 Single-int-var-in-edx: -6052 Int-var-in-edx/imm32 -6053 0/imm32/next -6054 -6055 Int-var-in-edx: -6056 "arg1"/imm32/name -6057 Type-int/imm32 -6058 1/imm32/some-block-depth -6059 0/imm32/no-stack-offset -6060 "edx"/imm32/register -6061 -6062 Single-int-var-in-ebx: -6063 Int-var-in-ebx/imm32 -6064 0/imm32/next -6065 -6066 Int-var-in-ebx: -6067 "arg1"/imm32/name -6068 Type-int/imm32 -6069 1/imm32/some-block-depth -6070 0/imm32/no-stack-offset -6071 "ebx"/imm32/register -6072 -6073 Single-int-var-in-esi: -6074 Int-var-in-esi/imm32 -6075 0/imm32/next -6076 -6077 Int-var-in-esi: -6078 "arg1"/imm32/name -6079 Type-int/imm32 -6080 1/imm32/some-block-depth -6081 0/imm32/no-stack-offset -6082 "esi"/imm32/register -6083 -6084 Single-int-var-in-edi: -6085 Int-var-in-edi/imm32 -6086 0/imm32/next -6087 -6088 Int-var-in-edi: -6089 "arg1"/imm32/name -6090 Type-int/imm32 -6091 1/imm32/some-block-depth -6092 0/imm32/no-stack-offset -6093 "edi"/imm32/register -6094 -6095 Single-lit-var: -6096 Lit-var/imm32 -6097 0/imm32/next -6098 -6099 Lit-var: -6100 "literal"/imm32/name -6101 Type-literal/imm32 -6102 1/imm32/some-block-depth -6103 0/imm32/no-stack-offset -6104 0/imm32/no-register -6105 -6106 Type-int: -6107 1/imm32/left/int -6108 0/imm32/right/null -6109 -6110 Type-literal: -6111 0/imm32/left/literal -6112 0/imm32/right/null -6113 -6114 == code -6115 emit-subx-primitive: # out: (addr buffered-file), stmt: (handle statement), primitive: (handle function) -6116 # . prologue -6117 55/push-ebp -6118 89/<- %ebp 4/r32/esp -6119 # . save registers -6120 50/push-eax -6121 51/push-ecx -6122 # ecx = primitive -6123 8b/-> *(ebp+0x10) 1/r32/ecx -6124 # emit primitive name -6125 (emit-indent *(ebp+8) *Curr-block-depth) -6126 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name -6127 # emit rm32 if necessary -6128 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt -6129 # emit r32 if necessary -6130 (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt -6131 # emit imm32 if necessary -6132 (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt -6133 # emit disp32 if necessary -6134 (emit-subx-disp32 *(ebp+8) *(ecx+0x1c) *(ebp+0xc)) # out, Primitive-subx-disp32, stmt -6135 (write-buffered *(ebp+8) Newline) -6136 $emit-subx-primitive:end: -6137 # . restore registers -6138 59/pop-to-ecx -6139 58/pop-to-eax -6140 # . epilogue -6141 89/<- %esp 5/r32/ebp -6142 5d/pop-to-ebp -6143 c3/return -6144 -6145 emit-subx-rm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6146 # . prologue -6147 55/push-ebp -6148 89/<- %ebp 4/r32/esp -6149 # . save registers -6150 50/push-eax -6151 # if (l == 0) return -6152 81 7/subop/compare *(ebp+0xc) 0/imm32 -6153 74/jump-if-= $emit-subx-rm32:end/disp8 -6154 # -6155 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -6156 (emit-subx-var-as-rm32 *(ebp+8) %eax) # out, var -6157 $emit-subx-rm32:end: -6158 # . restore registers -6159 58/pop-to-eax -6160 # . epilogue -6161 89/<- %esp 5/r32/ebp -6162 5d/pop-to-ebp -6163 c3/return -6164 -6165 get-stmt-operand-from-arg-location: # stmt: (handle statement), l: arg-location -> var/eax: (handle variable) -6166 # . prologue -6167 55/push-ebp -6168 89/<- %ebp 4/r32/esp -6169 # . save registers -6170 51/push-ecx -6171 # eax = l -6172 8b/-> *(ebp+0xc) 0/r32/eax -6173 # ecx = stmt -6174 8b/-> *(ebp+8) 1/r32/ecx -6175 # if (l == 1) return stmt->inouts->var -6176 { -6177 3d/compare-eax-and 1/imm32 -6178 75/jump-if-!= break/disp8 -6179 $get-stmt-operand-from-arg-location:1: -6180 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts -6181 8b/-> *eax 0/r32/eax # Operand-var -6182 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -6183 } -6184 # if (l == 2) return stmt->inouts->next->var -6185 { -6186 3d/compare-eax-and 2/imm32 -6187 75/jump-if-!= break/disp8 -6188 $get-stmt-operand-from-arg-location:2: -6189 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts -6190 8b/-> *(eax+4) 0/r32/eax # Operand-next -6191 8b/-> *eax 0/r32/eax # Operand-var -6192 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -6193 } -6194 # if (l == 3) return stmt->outputs -6195 { -6196 3d/compare-eax-and 3/imm32 -6197 75/jump-if-!= break/disp8 -6198 $get-stmt-operand-from-arg-location:3: -6199 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs -6200 8b/-> *eax 0/r32/eax # Operand-var -6201 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -6202 } -6203 # abort -6204 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 -6205 $get-stmt-operand-from-arg-location:end: -6206 # . restore registers -6207 59/pop-to-ecx -6208 # . epilogue -6209 89/<- %esp 5/r32/ebp -6210 5d/pop-to-ebp -6211 c3/return -6212 -6213 $get-stmt-operand-from-arg-location:abort: -6214 # error("invalid arg-location " eax) -6215 (write-buffered Stderr "invalid arg-location ") -6216 (print-int32-buffered Stderr %eax) -6217 (write-buffered Stderr Newline) -6218 (flush Stderr) -6219 # . syscall(exit, 1) -6220 bb/copy-to-ebx 1/imm32 -6221 b8/copy-to-eax 1/imm32/exit -6222 cd/syscall 0x80/imm8 -6223 # never gets here -6224 -6225 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6226 # . prologue -6227 55/push-ebp -6228 89/<- %ebp 4/r32/esp -6229 # . save registers -6230 50/push-eax -6231 51/push-ecx -6232 # if (location == 0) return -6233 81 7/subop/compare *(ebp+0xc) 0/imm32 -6234 0f 84/jump-if-= $emit-subx-r32:end/disp32 -6235 # -6236 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -6237 (maybe-get Registers *(eax+0x10) 8) # Var-register => eax: (addr register-index) -6238 (write-buffered *(ebp+8) Space) -6239 (print-int32-buffered *(ebp+8) *eax) -6240 (write-buffered *(ebp+8) "/r32") -6241 $emit-subx-r32:end: -6242 # . restore registers -6243 59/pop-to-ecx -6244 58/pop-to-eax -6245 # . epilogue -6246 89/<- %esp 5/r32/ebp -6247 5d/pop-to-ebp -6248 c3/return -6249 -6250 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6251 # . prologue -6252 55/push-ebp -6253 89/<- %ebp 4/r32/esp -6254 # . save registers -6255 50/push-eax +5438 0/imm32/no-output +5439 _Primitive-loop-if-<=/imm32/next +5440 _Primitive-loop-if-<=: +5441 "loop-if-<="/imm32/name +5442 0/imm32/inouts +5443 0/imm32/outputs +5444 "0f 8e/jump-if-<= loop/disp32"/imm32/subx-name +5445 0/imm32/no-rm32 +5446 0/imm32/no-r32 +5447 0/imm32/no-imm32 +5448 0/imm32/no-disp32 +5449 0/imm32/no-output +5450 _Primitive-loop-if->/imm32/next +5451 _Primitive-loop-if->: +5452 "loop-if->"/imm32/name +5453 0/imm32/inouts +5454 0/imm32/outputs +5455 "0f 8f/jump-if-> loop/disp32"/imm32/subx-name +5456 0/imm32/no-rm32 +5457 0/imm32/no-r32 +5458 0/imm32/no-imm32 +5459 0/imm32/no-disp32 +5460 0/imm32/no-output +5461 _Primitive-loop/imm32/next # we probably don't need an unconditional break +5462 _Primitive-loop: +5463 "loop"/imm32/name +5464 0/imm32/inouts +5465 0/imm32/outputs +5466 "e9/jump loop/disp32"/imm32/subx-name +5467 0/imm32/no-rm32 +5468 0/imm32/no-r32 +5469 0/imm32/no-imm32 +5470 0/imm32/no-disp32 +5471 0/imm32/no-output +5472 _Primitive-break-if-addr<-named/imm32/next +5473 # - branches to named blocks +5474 _Primitive-break-if-addr<-named: +5475 "break-if-addr<"/imm32/name +5476 Single-lit-var/imm32/inouts +5477 0/imm32/outputs +5478 "0f 82/jump-if-addr<"/imm32/subx-name +5479 0/imm32/no-rm32 +5480 0/imm32/no-r32 +5481 0/imm32/no-imm32 +5482 1/imm32/disp32-is-first-inout +5483 0/imm32/no-output +5484 _Primitive-break-if-addr>=-named/imm32/next +5485 _Primitive-break-if-addr>=-named: +5486 "break-if-addr>="/imm32/name +5487 Single-lit-var/imm32/inouts +5488 0/imm32/outputs +5489 "0f 83/jump-if-addr>="/imm32/subx-name +5490 0/imm32/no-rm32 +5491 0/imm32/no-r32 +5492 0/imm32/no-imm32 +5493 1/imm32/disp32-is-first-inout +5494 0/imm32/no-output +5495 _Primitive-break-if-=-named/imm32/next +5496 _Primitive-break-if-=-named: +5497 "break-if-="/imm32/name +5498 Single-lit-var/imm32/inouts +5499 0/imm32/outputs +5500 "0f 84/jump-if-="/imm32/subx-name +5501 0/imm32/no-rm32 +5502 0/imm32/no-r32 +5503 0/imm32/no-imm32 +5504 1/imm32/disp32-is-first-inout +5505 0/imm32/no-output +5506 _Primitive-break-if-!=-named/imm32/next +5507 _Primitive-break-if-!=-named: +5508 "break-if-!="/imm32/name +5509 Single-lit-var/imm32/inouts +5510 0/imm32/outputs +5511 "0f 85/jump-if-!="/imm32/subx-name +5512 0/imm32/no-rm32 +5513 0/imm32/no-r32 +5514 0/imm32/no-imm32 +5515 1/imm32/disp32-is-first-inout +5516 0/imm32/no-output +5517 _Primitive-break-if-addr<=-named/imm32/next +5518 _Primitive-break-if-addr<=-named: +5519 "break-if-addr<="/imm32/name +5520 Single-lit-var/imm32/inouts +5521 0/imm32/outputs +5522 "0f 86/jump-if-addr<="/imm32/subx-name +5523 0/imm32/no-rm32 +5524 0/imm32/no-r32 +5525 0/imm32/no-imm32 +5526 1/imm32/disp32-is-first-inout +5527 0/imm32/no-output +5528 _Primitive-break-if-addr>-named/imm32/next +5529 _Primitive-break-if-addr>-named: +5530 "break-if-addr>"/imm32/name +5531 Single-lit-var/imm32/inouts +5532 0/imm32/outputs +5533 "0f 87/jump-if-addr>"/imm32/subx-name +5534 0/imm32/no-rm32 +5535 0/imm32/no-r32 +5536 0/imm32/no-imm32 +5537 1/imm32/disp32-is-first-inout +5538 0/imm32/no-output +5539 _Primitive-break-if-<-named/imm32/next +5540 _Primitive-break-if-<-named: +5541 "break-if-<"/imm32/name +5542 Single-lit-var/imm32/inouts +5543 0/imm32/outputs +5544 "0f 8c/jump-if-<"/imm32/subx-name +5545 0/imm32/no-rm32 +5546 0/imm32/no-r32 +5547 0/imm32/no-imm32 +5548 1/imm32/disp32-is-first-inout +5549 0/imm32/no-output +5550 _Primitive-break-if->=-named/imm32/next +5551 _Primitive-break-if->=-named: +5552 "break-if->="/imm32/name +5553 Single-lit-var/imm32/inouts +5554 0/imm32/outputs +5555 "0f 8d/jump-if->="/imm32/subx-name +5556 0/imm32/no-rm32 +5557 0/imm32/no-r32 +5558 0/imm32/no-imm32 +5559 1/imm32/disp32-is-first-inout +5560 0/imm32/no-output +5561 _Primitive-break-if-<=-named/imm32/next +5562 _Primitive-break-if-<=-named: +5563 "break-if-<="/imm32/name +5564 Single-lit-var/imm32/inouts +5565 0/imm32/outputs +5566 "0f 8e/jump-if-<="/imm32/subx-name +5567 0/imm32/no-rm32 +5568 0/imm32/no-r32 +5569 0/imm32/no-imm32 +5570 1/imm32/disp32-is-first-inout +5571 0/imm32/no-output +5572 _Primitive-break-if->-named/imm32/next +5573 _Primitive-break-if->-named: +5574 "break-if->"/imm32/name +5575 Single-lit-var/imm32/inouts +5576 0/imm32/outputs +5577 "0f 8f/jump-if->"/imm32/subx-name +5578 0/imm32/no-rm32 +5579 0/imm32/no-r32 +5580 0/imm32/no-imm32 +5581 1/imm32/disp32-is-first-inout +5582 0/imm32/no-output +5583 _Primitive-loop-if-addr<-named/imm32/next +5584 _Primitive-loop-if-addr<-named: +5585 "loop-if-addr<"/imm32/name +5586 Single-lit-var/imm32/inouts +5587 0/imm32/outputs +5588 "0f 82/jump-if-addr<"/imm32/subx-name +5589 0/imm32/no-rm32 +5590 0/imm32/no-r32 +5591 0/imm32/no-imm32 +5592 1/imm32/disp32-is-first-inout +5593 0/imm32/no-output +5594 _Primitive-loop-if-addr>=-named/imm32/next +5595 _Primitive-loop-if-addr>=-named: +5596 "loop-if-addr>="/imm32/name +5597 Single-lit-var/imm32/inouts +5598 0/imm32/outputs +5599 "0f 83/jump-if-addr>="/imm32/subx-name +5600 0/imm32/no-rm32 +5601 0/imm32/no-r32 +5602 0/imm32/no-imm32 +5603 1/imm32/disp32-is-first-inout +5604 0/imm32/no-output +5605 _Primitive-loop-if-=-named/imm32/next +5606 _Primitive-loop-if-=-named: +5607 "loop-if-="/imm32/name +5608 Single-lit-var/imm32/inouts +5609 0/imm32/outputs +5610 "0f 84/jump-if-="/imm32/subx-name +5611 0/imm32/no-rm32 +5612 0/imm32/no-r32 +5613 0/imm32/no-imm32 +5614 1/imm32/disp32-is-first-inout +5615 0/imm32/no-output +5616 _Primitive-loop-if-!=-named/imm32/next +5617 _Primitive-loop-if-!=-named: +5618 "loop-if-!="/imm32/name +5619 Single-lit-var/imm32/inouts +5620 0/imm32/outputs +5621 "0f 85/jump-if-!="/imm32/subx-name +5622 0/imm32/no-rm32 +5623 0/imm32/no-r32 +5624 0/imm32/no-imm32 +5625 1/imm32/disp32-is-first-inout +5626 0/imm32/no-output +5627 _Primitive-loop-if-addr<=-named/imm32/next +5628 _Primitive-loop-if-addr<=-named: +5629 "loop-if-addr<="/imm32/name +5630 Single-lit-var/imm32/inouts +5631 0/imm32/outputs +5632 "0f 86/jump-if-addr<="/imm32/subx-name +5633 0/imm32/no-rm32 +5634 0/imm32/no-r32 +5635 0/imm32/no-imm32 +5636 1/imm32/disp32-is-first-inout +5637 0/imm32/no-output +5638 _Primitive-loop-if-addr>-named/imm32/next +5639 _Primitive-loop-if-addr>-named: +5640 "loop-if-addr>"/imm32/name +5641 Single-lit-var/imm32/inouts +5642 0/imm32/outputs +5643 "0f 87/jump-if-addr>"/imm32/subx-name +5644 0/imm32/no-rm32 +5645 0/imm32/no-r32 +5646 0/imm32/no-imm32 +5647 1/imm32/disp32-is-first-inout +5648 0/imm32/no-output +5649 _Primitive-loop-if-<-named/imm32/next +5650 _Primitive-loop-if-<-named: +5651 "loop-if-<"/imm32/name +5652 Single-lit-var/imm32/inouts +5653 0/imm32/outputs +5654 "0f 8c/jump-if-<"/imm32/subx-name +5655 0/imm32/no-rm32 +5656 0/imm32/no-r32 +5657 0/imm32/no-imm32 +5658 1/imm32/disp32-is-first-inout +5659 0/imm32/no-output +5660 _Primitive-loop-if->=-named/imm32/next +5661 _Primitive-loop-if->=-named: +5662 "loop-if->="/imm32/name +5663 Single-lit-var/imm32/inouts +5664 0/imm32/outputs +5665 "0f 8d/jump-if->="/imm32/subx-name +5666 0/imm32/no-rm32 +5667 0/imm32/no-r32 +5668 0/imm32/no-imm32 +5669 1/imm32/disp32-is-first-inout +5670 0/imm32/no-output +5671 _Primitive-loop-if-<=-named/imm32/next +5672 _Primitive-loop-if-<=-named: +5673 "loop-if-<="/imm32/name +5674 Single-lit-var/imm32/inouts +5675 0/imm32/outputs +5676 "0f 8e/jump-if-<="/imm32/subx-name +5677 0/imm32/no-rm32 +5678 0/imm32/no-r32 +5679 0/imm32/no-imm32 +5680 1/imm32/disp32-is-first-inout +5681 0/imm32/no-output +5682 _Primitive-loop-if->-named/imm32/next +5683 _Primitive-loop-if->-named: +5684 "loop-if->"/imm32/name +5685 Single-lit-var/imm32/inouts +5686 0/imm32/outputs +5687 "0f 8f/jump-if->"/imm32/subx-name +5688 0/imm32/no-rm32 +5689 0/imm32/no-r32 +5690 0/imm32/no-imm32 +5691 1/imm32/disp32-is-first-inout +5692 0/imm32/no-output +5693 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break +5694 _Primitive-loop-named: +5695 "loop"/imm32/name +5696 Single-lit-var/imm32/inouts +5697 0/imm32/outputs +5698 "e9/jump"/imm32/subx-name +5699 0/imm32/no-rm32 +5700 0/imm32/no-r32 +5701 0/imm32/no-imm32 +5702 1/imm32/disp32-is-first-inout +5703 0/imm32/no-output +5704 0/imm32/next +5705 +5706 Single-int-var-on-stack: +5707 Int-var-on-stack/imm32 +5708 0/imm32/next +5709 +5710 Int-var-on-stack: +5711 "arg1"/imm32/name +5712 Type-int/imm32 +5713 1/imm32/some-block-depth +5714 1/imm32/some-stack-offset +5715 0/imm32/no-register +5716 +5717 Two-args-int-stack-int-reg: +5718 Int-var-on-stack/imm32 +5719 Single-int-var-in-some-register/imm32/next +5720 +5721 Two-args-int-reg-int-stack: +5722 Int-var-in-some-register/imm32 +5723 Single-int-var-on-stack/imm32/next +5724 +5725 Two-args-int-eax-int-literal: +5726 Int-var-in-eax/imm32 +5727 Single-lit-var/imm32/next +5728 +5729 Int-var-and-literal: +5730 Int-var-on-stack/imm32 +5731 Single-lit-var/imm32/next +5732 +5733 Single-int-var-in-some-register: +5734 Int-var-in-some-register/imm32 +5735 0/imm32/next +5736 +5737 Int-var-in-some-register: +5738 "arg1"/imm32/name +5739 Type-int/imm32 +5740 1/imm32/some-block-depth +5741 0/imm32/no-stack-offset +5742 "*"/imm32/register +5743 +5744 Single-int-var-in-eax: +5745 Int-var-in-eax/imm32 +5746 0/imm32/next +5747 +5748 Int-var-in-eax: +5749 "arg1"/imm32/name +5750 Type-int/imm32 +5751 1/imm32/some-block-depth +5752 0/imm32/no-stack-offset +5753 "eax"/imm32/register +5754 +5755 Single-int-var-in-ecx: +5756 Int-var-in-ecx/imm32 +5757 0/imm32/next +5758 +5759 Int-var-in-ecx: +5760 "arg1"/imm32/name +5761 Type-int/imm32 +5762 1/imm32/some-block-depth +5763 0/imm32/no-stack-offset +5764 "ecx"/imm32/register +5765 +5766 Single-int-var-in-edx: +5767 Int-var-in-edx/imm32 +5768 0/imm32/next +5769 +5770 Int-var-in-edx: +5771 "arg1"/imm32/name +5772 Type-int/imm32 +5773 1/imm32/some-block-depth +5774 0/imm32/no-stack-offset +5775 "edx"/imm32/register +5776 +5777 Single-int-var-in-ebx: +5778 Int-var-in-ebx/imm32 +5779 0/imm32/next +5780 +5781 Int-var-in-ebx: +5782 "arg1"/imm32/name +5783 Type-int/imm32 +5784 1/imm32/some-block-depth +5785 0/imm32/no-stack-offset +5786 "ebx"/imm32/register +5787 +5788 Single-int-var-in-esi: +5789 Int-var-in-esi/imm32 +5790 0/imm32/next +5791 +5792 Int-var-in-esi: +5793 "arg1"/imm32/name +5794 Type-int/imm32 +5795 1/imm32/some-block-depth +5796 0/imm32/no-stack-offset +5797 "esi"/imm32/register +5798 +5799 Single-int-var-in-edi: +5800 Int-var-in-edi/imm32 +5801 0/imm32/next +5802 +5803 Int-var-in-edi: +5804 "arg1"/imm32/name +5805 Type-int/imm32 +5806 1/imm32/some-block-depth +5807 0/imm32/no-stack-offset +5808 "edi"/imm32/register +5809 +5810 Single-lit-var: +5811 Lit-var/imm32 +5812 0/imm32/next +5813 +5814 Lit-var: +5815 "literal"/imm32/name +5816 Type-literal/imm32 +5817 1/imm32/some-block-depth +5818 0/imm32/no-stack-offset +5819 0/imm32/no-register +5820 +5821 Type-int: +5822 1/imm32/left/int +5823 0/imm32/right/null +5824 +5825 Type-literal: +5826 0/imm32/left/literal +5827 0/imm32/right/null +5828 +5829 == code +5830 emit-subx-primitive: # out: (addr buffered-file), stmt: (handle statement), primitive: (handle function) +5831 # . prologue +5832 55/push-ebp +5833 89/<- %ebp 4/r32/esp +5834 # . save registers +5835 50/push-eax +5836 51/push-ecx +5837 # ecx = primitive +5838 8b/-> *(ebp+0x10) 1/r32/ecx +5839 # emit primitive name +5840 (emit-indent *(ebp+8) *Curr-block-depth) +5841 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name +5842 # emit rm32 if necessary +5843 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt +5844 # emit r32 if necessary +5845 (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt +5846 # emit imm32 if necessary +5847 (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt +5848 # emit disp32 if necessary +5849 (emit-subx-disp32 *(ebp+8) *(ecx+0x1c) *(ebp+0xc)) # out, Primitive-subx-disp32, stmt +5850 (write-buffered *(ebp+8) Newline) +5851 $emit-subx-primitive:end: +5852 # . restore registers +5853 59/pop-to-ecx +5854 58/pop-to-eax +5855 # . epilogue +5856 89/<- %esp 5/r32/ebp +5857 5d/pop-to-ebp +5858 c3/return +5859 +5860 emit-subx-rm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) +5861 # . prologue +5862 55/push-ebp +5863 89/<- %ebp 4/r32/esp +5864 # . save registers +5865 50/push-eax +5866 # if (l == 0) return +5867 81 7/subop/compare *(ebp+0xc) 0/imm32 +5868 74/jump-if-= $emit-subx-rm32:end/disp8 +5869 # +5870 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax +5871 (emit-subx-var-as-rm32 *(ebp+8) %eax) # out, var +5872 $emit-subx-rm32:end: +5873 # . restore registers +5874 58/pop-to-eax +5875 # . epilogue +5876 89/<- %esp 5/r32/ebp +5877 5d/pop-to-ebp +5878 c3/return +5879 +5880 get-stmt-operand-from-arg-location: # stmt: (handle statement), l: arg-location -> var/eax: (handle variable) +5881 # . prologue +5882 55/push-ebp +5883 89/<- %ebp 4/r32/esp +5884 # . save registers +5885 51/push-ecx +5886 # eax = l +5887 8b/-> *(ebp+0xc) 0/r32/eax +5888 # ecx = stmt +5889 8b/-> *(ebp+8) 1/r32/ecx +5890 # if (l == 1) return stmt->inouts->var +5891 { +5892 3d/compare-eax-and 1/imm32 +5893 75/jump-if-!= break/disp8 +5894 $get-stmt-operand-from-arg-location:1: +5895 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts +5896 8b/-> *eax 0/r32/eax # Operand-var +5897 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +5898 } +5899 # if (l == 2) return stmt->inouts->next->var +5900 { +5901 3d/compare-eax-and 2/imm32 +5902 75/jump-if-!= break/disp8 +5903 $get-stmt-operand-from-arg-location:2: +5904 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts +5905 8b/-> *(eax+4) 0/r32/eax # Operand-next +5906 8b/-> *eax 0/r32/eax # Operand-var +5907 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +5908 } +5909 # if (l == 3) return stmt->outputs +5910 { +5911 3d/compare-eax-and 3/imm32 +5912 75/jump-if-!= break/disp8 +5913 $get-stmt-operand-from-arg-location:3: +5914 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs +5915 8b/-> *eax 0/r32/eax # Operand-var +5916 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +5917 } +5918 # abort +5919 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 +5920 $get-stmt-operand-from-arg-location:end: +5921 # . restore registers +5922 59/pop-to-ecx +5923 # . epilogue +5924 89/<- %esp 5/r32/ebp +5925 5d/pop-to-ebp +5926 c3/return +5927 +5928 $get-stmt-operand-from-arg-location:abort: +5929 # error("invalid arg-location " eax) +5930 (write-buffered Stderr "invalid arg-location ") +5931 (print-int32-buffered Stderr %eax) +5932 (write-buffered Stderr Newline) +5933 (flush Stderr) +5934 # . syscall(exit, 1) +5935 bb/copy-to-ebx 1/imm32 +5936 b8/copy-to-eax 1/imm32/exit +5937 cd/syscall 0x80/imm8 +5938 # never gets here +5939 +5940 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) +5941 # . prologue +5942 55/push-ebp +5943 89/<- %ebp 4/r32/esp +5944 # . save registers +5945 50/push-eax +5946 51/push-ecx +5947 # if (location == 0) return +5948 81 7/subop/compare *(ebp+0xc) 0/imm32 +5949 0f 84/jump-if-= $emit-subx-r32:end/disp32 +5950 # +5951 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax +5952 (maybe-get Registers *(eax+0x10) 8) # Var-register => eax: (addr register-index) +5953 (write-buffered *(ebp+8) Space) +5954 (print-int32-buffered *(ebp+8) *eax) +5955 (write-buffered *(ebp+8) "/r32") +5956 $emit-subx-r32:end: +5957 # . restore registers +5958 59/pop-to-ecx +5959 58/pop-to-eax +5960 # . epilogue +5961 89/<- %esp 5/r32/ebp +5962 5d/pop-to-ebp +5963 c3/return +5964 +5965 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) +5966 # . prologue +5967 55/push-ebp +5968 89/<- %ebp 4/r32/esp +5969 # . save registers +5970 50/push-eax +5971 51/push-ecx +5972 # if (location == 0) return +5973 81 7/subop/compare *(ebp+0xc) 0/imm32 +5974 74/jump-if-= $emit-subx-imm32:end/disp8 +5975 # +5976 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax +5977 (write-buffered *(ebp+8) Space) +5978 (write-buffered *(ebp+8) *eax) # Var-name +5979 (write-buffered *(ebp+8) "/imm32") +5980 $emit-subx-imm32:end: +5981 # . restore registers +5982 59/pop-to-ecx +5983 58/pop-to-eax +5984 # . epilogue +5985 89/<- %esp 5/r32/ebp +5986 5d/pop-to-ebp +5987 c3/return +5988 +5989 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) +5990 # . prologue +5991 55/push-ebp +5992 89/<- %ebp 4/r32/esp +5993 # . save registers +5994 50/push-eax +5995 51/push-ecx +5996 # if (location == 0) return +5997 81 7/subop/compare *(ebp+0xc) 0/imm32 +5998 0f 84/jump-if-= $emit-subx-disp32:end/disp32 +5999 # +6000 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax +6001 (write-buffered *(ebp+8) Space) +6002 (write-buffered *(ebp+8) *eax) # Var-name +6003 # hack: if instruction operation starts with "break", emit ":break" +6004 # var name/ecx: (addr array byte) = stmt->operation +6005 8b/-> *(ebp+0x10) 0/r32/eax +6006 8b/-> *(eax+4) 1/r32/ecx +6007 { +6008 (string-starts-with? %ecx "break") # => eax +6009 3d/compare-eax-and 0/imm32 +6010 74/jump-if-= break/disp8 +6011 (write-buffered *(ebp+8) ":break") +6012 } +6013 # hack: if instruction operation starts with "loop", emit ":loop" +6014 { +6015 (string-starts-with? %ecx "loop") # => eax +6016 3d/compare-eax-and 0/imm32 +6017 74/jump-if-= break/disp8 +6018 (write-buffered *(ebp+8) ":loop") +6019 } +6020 (write-buffered *(ebp+8) "/disp32") +6021 $emit-subx-disp32:end: +6022 # . restore registers +6023 59/pop-to-ecx +6024 58/pop-to-eax +6025 # . epilogue +6026 89/<- %esp 5/r32/ebp +6027 5d/pop-to-ebp +6028 c3/return +6029 +6030 emit-subx-call: # out: (addr buffered-file), stmt: (handle statement), callee: (handle function) +6031 # . prologue +6032 55/push-ebp +6033 89/<- %ebp 4/r32/esp +6034 # . save registers +6035 50/push-eax +6036 51/push-ecx +6037 # +6038 (emit-indent *(ebp+8) *Curr-block-depth) +6039 (write-buffered *(ebp+8) "(") +6040 # - emit function name +6041 8b/-> *(ebp+0x10) 1/r32/ecx +6042 (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name +6043 # - emit arguments +6044 # var curr/ecx: (handle list var) = stmt->inouts +6045 8b/-> *(ebp+0xc) 1/r32/ecx +6046 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts +6047 { +6048 # if (curr == null) break +6049 81 7/subop/compare %ecx 0/imm32 +6050 74/jump-if-= break/disp8 +6051 # +6052 (emit-subx-call-operand *(ebp+8) *ecx) +6053 # curr = curr->next +6054 8b/-> *(ecx+4) 1/r32/ecx +6055 eb/jump loop/disp8 +6056 } +6057 # +6058 (write-buffered *(ebp+8) ")\n") +6059 $emit-subx-call:end: +6060 # . restore registers +6061 59/pop-to-ecx +6062 58/pop-to-eax +6063 # . epilogue +6064 89/<- %esp 5/r32/ebp +6065 5d/pop-to-ebp +6066 c3/return +6067 +6068 emit-subx-call-operand: # out: (addr buffered-file), operand: (handle variable) +6069 # shares code with emit-subx-var-as-rm32 +6070 # . prologue +6071 55/push-ebp +6072 89/<- %ebp 4/r32/esp +6073 # . save registers +6074 50/push-eax +6075 # eax = operand +6076 8b/-> *(ebp+0xc) 0/r32/eax +6077 # if (operand->register) emit "%__" +6078 { +6079 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register +6080 74/jump-if-= break/disp8 +6081 $emit-subx-call-operand:register: +6082 (write-buffered *(ebp+8) " %") +6083 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register +6084 e9/jump $emit-subx-call-operand:end/disp32 +6085 } +6086 # else if (operand->stack-offset) emit "*(ebp+__)" +6087 { +6088 81 7/subop/compare *(eax+0xc) 0/imm32 # Var-stack-offset +6089 74/jump-if-= break/disp8 +6090 $emit-subx-call-operand:stack: +6091 (write-buffered *(ebp+8) Space) +6092 (write-buffered *(ebp+8) "*(ebp+") +6093 8b/-> *(ebp+0xc) 0/r32/eax +6094 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-stack-offset +6095 (write-buffered *(ebp+8) ")") +6096 e9/jump $emit-subx-call-operand:end/disp32 +6097 } +6098 # else if (operand->type == literal) emit "__" +6099 { +6100 50/push-eax +6101 8b/-> *(eax+4) 0/r32/eax # Var-type +6102 81 7/subop/compare *eax 0/imm32 # Tree-left +6103 58/pop-to-eax +6104 75/jump-if-!= break/disp8 +6105 $emit-subx-call-operand:literal: +6106 (write-buffered *(ebp+8) Space) +6107 (write-buffered *(ebp+8) *eax) +6108 } +6109 $emit-subx-call-operand:end: +6110 # . restore registers +6111 58/pop-to-eax +6112 # . epilogue +6113 89/<- %esp 5/r32/ebp +6114 5d/pop-to-ebp +6115 c3/return +6116 +6117 emit-subx-var-as-rm32: # out: (addr buffered-file), operand: (handle variable) +6118 # . prologue +6119 55/push-ebp +6120 89/<- %ebp 4/r32/esp +6121 # . save registers +6122 50/push-eax +6123 # eax = operand +6124 8b/-> *(ebp+0xc) 0/r32/eax +6125 # if (operand->register) emit "%__" +6126 { +6127 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register +6128 74/jump-if-= break/disp8 +6129 $emit-subx-var-as-rm32:register: +6130 (write-buffered *(ebp+8) " %") +6131 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register +6132 } +6133 # else if (operand->stack-offset) emit "*(ebp+__)" +6134 { +6135 81 7/subop/compare *(eax+0xc) 0/imm32 # Var-stack-offset +6136 74/jump-if-= break/disp8 +6137 $emit-subx-var-as-rm32:stack: +6138 (write-buffered *(ebp+8) Space) +6139 (write-buffered *(ebp+8) "*(ebp+") +6140 8b/-> *(ebp+0xc) 0/r32/eax +6141 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-stack-offset +6142 (write-buffered *(ebp+8) ")") +6143 } +6144 $emit-subx-var-as-rm32:end: +6145 # . restore registers +6146 58/pop-to-eax +6147 # . epilogue +6148 89/<- %esp 5/r32/ebp +6149 5d/pop-to-ebp +6150 c3/return +6151 +6152 find-matching-function: # functions: (addr function), stmt: (handle statement) -> result/eax: (handle function) +6153 # . prologue +6154 55/push-ebp +6155 89/<- %ebp 4/r32/esp +6156 # . save registers +6157 51/push-ecx +6158 # var curr/ecx: (handle function) = functions +6159 8b/-> *(ebp+8) 1/r32/ecx +6160 { +6161 # if (curr == null) break +6162 81 7/subop/compare %ecx 0/imm32 +6163 74/jump-if-= break/disp8 +6164 # if match(stmt, curr) return curr +6165 { +6166 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax +6167 3d/compare-eax-and 0/imm32 +6168 74/jump-if-= break/disp8 +6169 89/<- %eax 1/r32/ecx +6170 eb/jump $find-matching-function:end/disp8 +6171 } +6172 # curr = curr->next +6173 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next +6174 eb/jump loop/disp8 +6175 } +6176 # return null +6177 b8/copy-to-eax 0/imm32 +6178 $find-matching-function:end: +6179 # . restore registers +6180 59/pop-to-ecx +6181 # . epilogue +6182 89/<- %esp 5/r32/ebp +6183 5d/pop-to-ebp +6184 c3/return +6185 +6186 find-matching-primitive: # primitives: (handle primitive), stmt: (handle statement) -> result/eax: (handle primitive) +6187 # . prologue +6188 55/push-ebp +6189 89/<- %ebp 4/r32/esp +6190 # . save registers +6191 51/push-ecx +6192 # var curr/ecx: (handle primitive) = primitives +6193 8b/-> *(ebp+8) 1/r32/ecx +6194 { +6195 $find-matching-primitive:loop: +6196 # if (curr == null) break +6197 81 7/subop/compare %ecx 0/imm32 +6198 0f 84/jump-if-= break/disp32 +6199 #? (write-buffered Stderr "prim: ") +6200 #? (write-buffered Stderr *ecx) # Primitive-name +6201 #? (write-buffered Stderr " => ") +6202 #? (write-buffered Stderr *(ecx+0xc)) # Primitive-subx-name +6203 #? (write-buffered Stderr Newline) +6204 #? (flush Stderr) +6205 # if match(curr, stmt) return curr +6206 { +6207 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax +6208 3d/compare-eax-and 0/imm32 +6209 74/jump-if-= break/disp8 +6210 89/<- %eax 1/r32/ecx +6211 eb/jump $find-matching-primitive:end/disp8 +6212 } +6213 $find-matching-primitive:next-primitive: +6214 # curr = curr->next +6215 8b/-> *(ecx+0x24) 1/r32/ecx # Primitive-next +6216 e9/jump loop/disp32 +6217 } +6218 # return null +6219 b8/copy-to-eax 0/imm32 +6220 $find-matching-primitive:end: +6221 # . restore registers +6222 59/pop-to-ecx +6223 # . epilogue +6224 89/<- %esp 5/r32/ebp +6225 5d/pop-to-ebp +6226 c3/return +6227 +6228 mu-stmt-matches-function?: # stmt: (handle statement), function: (handle function) => result/eax: boolean +6229 # . prologue +6230 55/push-ebp +6231 89/<- %ebp 4/r32/esp +6232 # . save registers +6233 51/push-ecx +6234 # return function->name == stmt->operation +6235 8b/-> *(ebp+8) 1/r32/ecx +6236 8b/-> *(ebp+0xc) 0/r32/eax +6237 (string-equal? *(ecx+4) *eax) # Stmt1-operation, Function-name => eax +6238 $mu-stmt-matches-function?:end: +6239 # . restore registers +6240 59/pop-to-ecx +6241 # . epilogue +6242 89/<- %esp 5/r32/ebp +6243 5d/pop-to-ebp +6244 c3/return +6245 +6246 mu-stmt-matches-primitive?: # stmt: (handle statement), primitive: (handle primitive) => result/eax: boolean +6247 # A mu stmt matches a primitive if the name matches, all the inout vars +6248 # match, and all the output vars match. +6249 # Vars match if types match and registers match. +6250 # In addition, a stmt output matches a primitive's output if types match +6251 # and the primitive has a wildcard register. +6252 # . prologue +6253 55/push-ebp +6254 89/<- %ebp 4/r32/esp +6255 # . save registers 6256 51/push-ecx -6257 # if (location == 0) return -6258 81 7/subop/compare *(ebp+0xc) 0/imm32 -6259 74/jump-if-= $emit-subx-imm32:end/disp8 -6260 # -6261 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -6262 (write-buffered *(ebp+8) Space) -6263 (write-buffered *(ebp+8) *eax) # Var-name -6264 (write-buffered *(ebp+8) "/imm32") -6265 $emit-subx-imm32:end: -6266 # . restore registers -6267 59/pop-to-ecx -6268 58/pop-to-eax -6269 # . epilogue -6270 89/<- %esp 5/r32/ebp -6271 5d/pop-to-ebp -6272 c3/return -6273 -6274 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6275 # . prologue -6276 55/push-ebp -6277 89/<- %ebp 4/r32/esp -6278 # . save registers -6279 50/push-eax -6280 51/push-ecx -6281 # if (location == 0) return -6282 81 7/subop/compare *(ebp+0xc) 0/imm32 -6283 0f 84/jump-if-= $emit-subx-disp32:end/disp32 -6284 # -6285 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -6286 (write-buffered *(ebp+8) Space) -6287 (write-buffered *(ebp+8) *eax) # Var-name -6288 # hack: if instruction operation starts with "break", emit ":break" -6289 # var name/ecx: (addr array byte) = stmt->operation -6290 8b/-> *(ebp+0x10) 0/r32/eax -6291 8b/-> *(eax+4) 1/r32/ecx -6292 { -6293 (string-starts-with? %ecx "break") # => eax -6294 3d/compare-eax-and 0/imm32 -6295 74/jump-if-= break/disp8 -6296 (write-buffered *(ebp+8) ":break") -6297 } -6298 # hack: if instruction operation starts with "loop", emit ":loop" -6299 { -6300 (string-starts-with? %ecx "loop") # => eax -6301 3d/compare-eax-and 0/imm32 -6302 74/jump-if-= break/disp8 -6303 (write-buffered *(ebp+8) ":loop") -6304 } -6305 (write-buffered *(ebp+8) "/disp32") -6306 $emit-subx-disp32:end: -6307 # . restore registers -6308 59/pop-to-ecx -6309 58/pop-to-eax -6310 # . epilogue -6311 89/<- %esp 5/r32/ebp -6312 5d/pop-to-ebp -6313 c3/return -6314 -6315 emit-subx-call: # out: (addr buffered-file), stmt: (handle statement), callee: (handle function) -6316 # . prologue -6317 55/push-ebp -6318 89/<- %ebp 4/r32/esp -6319 # . save registers -6320 50/push-eax -6321 51/push-ecx -6322 # -6323 (emit-indent *(ebp+8) *Curr-block-depth) -6324 (write-buffered *(ebp+8) "(") -6325 # - emit function name -6326 8b/-> *(ebp+0x10) 1/r32/ecx -6327 (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name -6328 # - emit arguments -6329 # var curr/ecx: (handle list var) = stmt->inouts -6330 8b/-> *(ebp+0xc) 1/r32/ecx -6331 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts -6332 { -6333 # if (curr == null) break -6334 81 7/subop/compare %ecx 0/imm32 -6335 74/jump-if-= break/disp8 -6336 # -6337 (emit-subx-call-operand *(ebp+8) *ecx) -6338 # curr = curr->next -6339 8b/-> *(ecx+4) 1/r32/ecx -6340 eb/jump loop/disp8 -6341 } -6342 # -6343 (write-buffered *(ebp+8) ")\n") -6344 $emit-subx-call:end: -6345 # . restore registers -6346 59/pop-to-ecx -6347 58/pop-to-eax -6348 # . epilogue -6349 89/<- %esp 5/r32/ebp -6350 5d/pop-to-ebp -6351 c3/return -6352 -6353 emit-subx-call-operand: # out: (addr buffered-file), operand: (handle variable) -6354 # shares code with emit-subx-var-as-rm32 -6355 # . prologue -6356 55/push-ebp -6357 89/<- %ebp 4/r32/esp -6358 # . save registers -6359 50/push-eax -6360 # eax = operand -6361 8b/-> *(ebp+0xc) 0/r32/eax -6362 # if (operand->register) emit "%__" -6363 { -6364 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -6365 74/jump-if-= break/disp8 -6366 $emit-subx-call-operand:register: -6367 (write-buffered *(ebp+8) " %") -6368 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register -6369 e9/jump $emit-subx-call-operand:end/disp32 -6370 } -6371 # else if (operand->stack-offset) emit "*(ebp+__)" -6372 { -6373 81 7/subop/compare *(eax+0xc) 0/imm32 # Var-stack-offset -6374 74/jump-if-= break/disp8 -6375 $emit-subx-call-operand:stack: -6376 (write-buffered *(ebp+8) Space) -6377 (write-buffered *(ebp+8) "*(ebp+") -6378 8b/-> *(ebp+0xc) 0/r32/eax -6379 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-stack-offset -6380 (write-buffered *(ebp+8) ")") -6381 e9/jump $emit-subx-call-operand:end/disp32 -6382 } -6383 # else if (operand->type == literal) emit "__" -6384 { -6385 50/push-eax -6386 8b/-> *(eax+4) 0/r32/eax # Var-type -6387 81 7/subop/compare *eax 0/imm32 # Tree-left -6388 58/pop-to-eax -6389 75/jump-if-!= break/disp8 -6390 $emit-subx-call-operand:literal: -6391 (write-buffered *(ebp+8) Space) -6392 (write-buffered *(ebp+8) *eax) -6393 } -6394 $emit-subx-call-operand:end: -6395 # . restore registers -6396 58/pop-to-eax -6397 # . epilogue -6398 89/<- %esp 5/r32/ebp -6399 5d/pop-to-ebp -6400 c3/return -6401 -6402 emit-subx-var-as-rm32: # out: (addr buffered-file), operand: (handle variable) -6403 # . prologue -6404 55/push-ebp -6405 89/<- %ebp 4/r32/esp -6406 # . save registers -6407 50/push-eax -6408 # eax = operand -6409 8b/-> *(ebp+0xc) 0/r32/eax -6410 # if (operand->register) emit "%__" -6411 { -6412 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -6413 74/jump-if-= break/disp8 -6414 $emit-subx-var-as-rm32:register: -6415 (write-buffered *(ebp+8) " %") -6416 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register -6417 } -6418 # else if (operand->stack-offset) emit "*(ebp+__)" -6419 { -6420 81 7/subop/compare *(eax+0xc) 0/imm32 # Var-stack-offset -6421 74/jump-if-= break/disp8 -6422 $emit-subx-var-as-rm32:stack: -6423 (write-buffered *(ebp+8) Space) -6424 (write-buffered *(ebp+8) "*(ebp+") -6425 8b/-> *(ebp+0xc) 0/r32/eax -6426 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-stack-offset -6427 (write-buffered *(ebp+8) ")") -6428 } -6429 $emit-subx-var-as-rm32:end: -6430 # . restore registers -6431 58/pop-to-eax -6432 # . epilogue -6433 89/<- %esp 5/r32/ebp -6434 5d/pop-to-ebp -6435 c3/return -6436 -6437 find-matching-function: # functions: (addr function), stmt: (handle statement) -> result/eax: (handle function) -6438 # . prologue -6439 55/push-ebp -6440 89/<- %ebp 4/r32/esp -6441 # . save registers -6442 51/push-ecx -6443 # var curr/ecx: (handle function) = functions -6444 8b/-> *(ebp+8) 1/r32/ecx -6445 { -6446 # if (curr == null) break -6447 81 7/subop/compare %ecx 0/imm32 -6448 74/jump-if-= break/disp8 -6449 # if match(stmt, curr) return curr -6450 { -6451 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax -6452 3d/compare-eax-and 0/imm32 -6453 74/jump-if-= break/disp8 -6454 89/<- %eax 1/r32/ecx -6455 eb/jump $find-matching-function:end/disp8 -6456 } -6457 # curr = curr->next -6458 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next -6459 eb/jump loop/disp8 -6460 } -6461 # return null -6462 b8/copy-to-eax 0/imm32 -6463 $find-matching-function:end: -6464 # . restore registers -6465 59/pop-to-ecx -6466 # . epilogue -6467 89/<- %esp 5/r32/ebp -6468 5d/pop-to-ebp -6469 c3/return -6470 -6471 find-matching-primitive: # primitives: (handle primitive), stmt: (handle statement) -> result/eax: (handle primitive) -6472 # . prologue -6473 55/push-ebp -6474 89/<- %ebp 4/r32/esp -6475 # . save registers -6476 51/push-ecx -6477 # var curr/ecx: (handle primitive) = primitives -6478 8b/-> *(ebp+8) 1/r32/ecx -6479 { -6480 $find-matching-primitive:loop: -6481 # if (curr == null) break -6482 81 7/subop/compare %ecx 0/imm32 -6483 0f 84/jump-if-= break/disp32 -6484 #? (write-buffered Stderr "prim: ") -6485 #? (write-buffered Stderr *ecx) # Primitive-name -6486 #? (write-buffered Stderr " => ") -6487 #? (write-buffered Stderr *(ecx+0xc)) # Primitive-subx-name -6488 #? (write-buffered Stderr Newline) -6489 #? (flush Stderr) -6490 # if match(curr, stmt) return curr -6491 { -6492 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax -6493 3d/compare-eax-and 0/imm32 -6494 74/jump-if-= break/disp8 -6495 89/<- %eax 1/r32/ecx -6496 eb/jump $find-matching-primitive:end/disp8 -6497 } -6498 $find-matching-primitive:next-primitive: -6499 # curr = curr->next -6500 8b/-> *(ecx+0x24) 1/r32/ecx # Primitive-next -6501 e9/jump loop/disp32 -6502 } -6503 # return null -6504 b8/copy-to-eax 0/imm32 -6505 $find-matching-primitive:end: -6506 # . restore registers -6507 59/pop-to-ecx -6508 # . epilogue -6509 89/<- %esp 5/r32/ebp -6510 5d/pop-to-ebp -6511 c3/return -6512 -6513 mu-stmt-matches-function?: # stmt: (handle statement), function: (handle function) => result/eax: boolean -6514 # . prologue -6515 55/push-ebp -6516 89/<- %ebp 4/r32/esp -6517 # . save registers -6518 51/push-ecx -6519 # return function->name == stmt->operation -6520 8b/-> *(ebp+8) 1/r32/ecx -6521 8b/-> *(ebp+0xc) 0/r32/eax -6522 (string-equal? *(ecx+4) *eax) # Stmt1-operation, Function-name => eax -6523 $mu-stmt-matches-function?:end: -6524 # . restore registers -6525 59/pop-to-ecx -6526 # . epilogue -6527 89/<- %esp 5/r32/ebp -6528 5d/pop-to-ebp -6529 c3/return -6530 -6531 mu-stmt-matches-primitive?: # stmt: (handle statement), primitive: (handle primitive) => result/eax: boolean -6532 # A mu stmt matches a primitive if the name matches, all the inout vars -6533 # match, and all the output vars match. -6534 # Vars match if types match and registers match. -6535 # In addition, a stmt output matches a primitive's output if types match -6536 # and the primitive has a wildcard register. -6537 # . prologue -6538 55/push-ebp -6539 89/<- %ebp 4/r32/esp -6540 # . save registers -6541 51/push-ecx -6542 52/push-edx -6543 53/push-ebx -6544 56/push-esi -6545 57/push-edi -6546 # ecx = stmt -6547 8b/-> *(ebp+8) 1/r32/ecx -6548 # edx = primitive -6549 8b/-> *(ebp+0xc) 2/r32/edx -6550 { -6551 $mu-stmt-matches-primitive?:check-name: -6552 # if (primitive->name != stmt->operation) return false -6553 (string-equal? *(ecx+4) *edx) # Stmt1-operation, Primitive-name => eax -6554 3d/compare-eax-and 0/imm32 -6555 75/jump-if-!= break/disp8 -6556 b8/copy-to-eax 0/imm32 -6557 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6558 } -6559 $mu-stmt-matches-primitive?:check-inouts: -6560 # for (curr/esi in stmt->inouts, curr2/edi in primitive->inouts) -6561 8b/-> *(ecx+8) 6/r32/esi # Stmt1-inouts -6562 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts -6563 { -6564 # if (curr == 0 && curr2 == 0) move on to check outputs -6565 { -6566 81 7/subop/compare %esi 0/imm32 -6567 75/jump-if-!= break/disp8 -6568 $mu-stmt-matches-primitive?:stmt-inout-is-null: -6569 { -6570 81 7/subop/compare %edi 0/imm32 -6571 75/jump-if-!= break/disp8 -6572 # -6573 e9/jump $mu-stmt-matches-primitive?:check-outputs/disp32 -6574 } -6575 # return false -6576 b8/copy-to-eax 0/imm32/false -6577 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6578 } -6579 # if (curr2 == 0) return false -6580 { -6581 81 7/subop/compare %edi 0/imm32 -6582 75/jump-if-!= break/disp8 -6583 $mu-stmt-matches-primitive?:prim-inout-is-null: -6584 b8/copy-to-eax 0/imm32/false -6585 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6586 } -6587 # if (curr != curr2) return false -6588 { -6589 (operand-matches-primitive? *esi *edi) # => eax -6590 3d/compare-eax-and 0/imm32 -6591 75/jump-if-!= break/disp8 -6592 b8/copy-to-eax 0/imm32/false -6593 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6594 } -6595 # curr=curr->next -6596 8b/-> *(esi+4) 6/r32/esi # Operand-next -6597 # curr2=curr2->next -6598 8b/-> *(edi+4) 7/r32/edi # Operand-next -6599 eb/jump loop/disp8 -6600 } -6601 $mu-stmt-matches-primitive?:check-outputs: -6602 # for (curr/esi in stmt->outputs, curr2/edi in primitive->outputs) -6603 8b/-> *(ecx+0xc) 6/r32/esi # Stmt1-outputs -6604 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs -6605 { -6606 # if (curr == 0) return (curr2 == 0) -6607 { -6608 $mu-stmt-matches-primitive?:check-output: -6609 81 7/subop/compare %esi 0/imm32 -6610 75/jump-if-!= break/disp8 -6611 { -6612 81 7/subop/compare %edi 0/imm32 -6613 75/jump-if-!= break/disp8 -6614 # return true -6615 b8/copy-to-eax 1/imm32 -6616 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6617 } -6618 # return false -6619 b8/copy-to-eax 0/imm32 -6620 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6621 } -6622 # if (curr2 == 0) return false -6623 { -6624 81 7/subop/compare %edi 0/imm32 -6625 75/jump-if-!= break/disp8 -6626 b8/copy-to-eax 0/imm32 -6627 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6628 } -6629 # if (curr != curr2) return false -6630 { -6631 (operand-matches-primitive? *esi *edi) # List-value List-value => eax -6632 3d/compare-eax-and 0/imm32 -6633 75/jump-if-!= break/disp8 -6634 b8/copy-to-eax 0/imm32 -6635 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6636 } -6637 # curr=curr->next -6638 8b/-> *(esi+4) 6/r32/esi # Operand-next -6639 # curr2=curr2->next -6640 8b/-> *(edi+4) 7/r32/edi # Operand-next -6641 eb/jump loop/disp8 -6642 } -6643 $mu-stmt-matches-primitive?:return-true: -6644 b8/copy-to-eax 1/imm32 -6645 $mu-stmt-matches-primitive?:end: -6646 # . restore registers -6647 5f/pop-to-edi -6648 5e/pop-to-esi -6649 5b/pop-to-ebx -6650 5a/pop-to-edx -6651 59/pop-to-ecx -6652 # . epilogue -6653 89/<- %esp 5/r32/ebp -6654 5d/pop-to-ebp -6655 c3/return -6656 -6657 operand-matches-primitive?: # var: (handle var), prim-var: (handle var) => result/eax: boolean -6658 # . prologue -6659 55/push-ebp -6660 89/<- %ebp 4/r32/esp -6661 # . save registers -6662 56/push-esi -6663 57/push-edi -6664 # esi = var -6665 8b/-> *(ebp+8) 6/r32/esi -6666 # edi = prim-var -6667 8b/-> *(ebp+0xc) 7/r32/edi -6668 # if (var->type != prim-var->type) return false -6669 (type-equal? *(esi+4) *(edi+4)) # Var-type, Var-type => eax -6670 3d/compare-eax-and 0/imm32 -6671 b8/copy-to-eax 0/imm32/false -6672 74/jump-if-= $operand-matches-primitive?:end/disp8 -6673 # return false if var->register doesn't match prim-var->register -6674 { -6675 # if addresses are equal, don't return here -6676 8b/-> *(esi+0x10) 0/r32/eax -6677 39/compare *(edi+0x10) 0/r32/eax -6678 74/jump-if-= break/disp8 -6679 # if either address is 0, return false -6680 3d/compare-eax-and 0/imm32 -6681 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result -6682 81 7/subop/compare *(edi+0x10) 0/imm32 -6683 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result -6684 # if prim-var->register is "*", return true -6685 (string-equal? *(edi+0x10) "*") # Var-register -6686 3d/compare-eax-and 0/imm32 -6687 b8/copy-to-eax 1/imm32/true -6688 75/jump-if-!= $operand-matches-primitive?:end/disp8 -6689 # if string contents don't match, return false -6690 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register -6691 3d/compare-eax-and 0/imm32 -6692 b8/copy-to-eax 0/imm32/false -6693 74/jump-if-= $operand-matches-primitive?:end/disp8 -6694 } -6695 # return true -6696 b8/copy-to-eax 1/imm32/true -6697 $operand-matches-primitive?:end: -6698 # . restore registers -6699 5f/pop-to-edi -6700 5e/pop-to-esi -6701 # . epilogue -6702 89/<- %esp 5/r32/ebp -6703 5d/pop-to-ebp -6704 c3/return -6705 -6706 type-equal?: # a: (handle tree type-id), b: (handle tree type-id) => result/eax: boolean -6707 # . prologue -6708 55/push-ebp -6709 89/<- %ebp 4/r32/esp -6710 # . save registers -6711 51/push-ecx -6712 52/push-edx -6713 # ecx = a -6714 8b/-> *(ebp+8) 1/r32/ecx -6715 # edx = b -6716 8b/-> *(ebp+0xc) 2/r32/edx -6717 # if (a == b) return true -6718 8b/-> %ecx 0/r32/eax # Var-type -6719 39/compare %edx 0/r32/eax # Var-type -6720 b8/copy-to-eax 1/imm32/true -6721 74/jump-if-= $type-equal?:end/disp8 -6722 # if (a < MAX_TYPE_ID) return false -6723 81 7/subop/compare %ecx 0x10000/imm32 -6724 b8/copy-to-eax 0/imm32/false -6725 72/jump-if-addr< $type-equal?:end/disp8 -6726 # if (b < MAX_TYPE_ID) return false -6727 81 7/subop/compare %edx 0x10000/imm32 -6728 b8/copy-to-eax 0/imm32/false -6729 72/jump-if-addr< $type-equal?:end/disp8 -6730 # if (!type-equal?(a->left, b->left)) return false -6731 (type-equal? *ecx *edx) # Tree-left, Tree-left => eax -6732 3d/compare-eax-and 0/imm32 -6733 74/jump-if-= $type-equal?:end/disp8 -6734 # return type-equal?(a->right, b->right) -6735 (type-equal? *(ecx+4) *(edx+4)) # Tree-right, Tree-right => eax -6736 $type-equal?:end: -6737 # . restore registers -6738 5a/pop-to-edx -6739 59/pop-to-ecx -6740 # . epilogue -6741 89/<- %esp 5/r32/ebp -6742 5d/pop-to-ebp -6743 c3/return -6744 -6745 test-emit-subx-statement-primitive: -6746 # Primitive operation on a variable on the stack. -6747 # increment foo -6748 # => -6749 # ff 0/subop/increment *(ebp-8) -6750 # -6751 # There's a variable on the var stack as follows: -6752 # name: 'foo' -6753 # type: int -6754 # stack-offset: -8 -6755 # -6756 # There's a primitive with this info: -6757 # name: 'increment' -6758 # inouts: int/mem -6759 # value: 'ff 0/subop/increment' -6760 # -6761 # There's nothing in functions. -6762 # -6763 # . prologue -6764 55/push-ebp -6765 89/<- %ebp 4/r32/esp -6766 # setup -6767 (clear-stream _test-output-stream) -6768 (clear-stream $_test-output-buffered-file->buffer) -6769 # var type/ecx: (handle tree type-id) = int -6770 68/push 0/imm32/right/null -6771 68/push 1/imm32/left/int -6772 89/<- %ecx 4/r32/esp -6773 # var var-foo/ecx: var -6774 68/push 0/imm32/no-register -6775 68/push -8/imm32/stack-offset -6776 68/push 1/imm32/block-depth -6777 51/push-ecx -6778 68/push "foo"/imm32 -6779 89/<- %ecx 4/r32/esp -6780 # var operand/ebx: (list var) -6781 68/push 0/imm32/next -6782 51/push-ecx/var-foo -6783 89/<- %ebx 4/r32/esp -6784 # var stmt/esi: statement -6785 68/push 0/imm32/next -6786 68/push 0/imm32/outputs -6787 53/push-ebx/operands -6788 68/push "increment"/imm32/operation -6789 68/push 1/imm32 -6790 89/<- %esi 4/r32/esp -6791 # var primitives/ebx: primitive -6792 68/push 0/imm32/next -6793 68/push 0/imm32/output-is-write-only -6794 68/push 0/imm32/no-disp32 -6795 68/push 0/imm32/no-imm32 -6796 68/push 0/imm32/no-r32 -6797 68/push 1/imm32/rm32-is-first-inout -6798 68/push "ff 0/subop/increment"/imm32/subx-name -6799 68/push 0/imm32/outputs -6800 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call -6801 68/push "increment"/imm32/name -6802 89/<- %ebx 4/r32/esp -6803 # convert -6804 c7 0/subop/copy *Curr-block-depth 0/imm32 -6805 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -6806 (flush _test-output-buffered-file) -6807 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -6813 # check output -6814 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-statement-primitive") -6815 # . epilogue -6816 89/<- %esp 5/r32/ebp -6817 5d/pop-to-ebp -6818 c3/return -6819 -6820 test-emit-subx-statement-primitive-register: -6821 # Primitive operation on a variable in a register. -6822 # foo <- increment -6823 # => -6824 # ff 0/subop/increment %eax # sub-optimal, but should suffice -6825 # -6826 # There's a variable on the var stack as follows: -6827 # name: 'foo' -6828 # type: int -6829 # register: 'eax' -6830 # -6831 # There's a primitive with this info: -6832 # name: 'increment' -6833 # out: int/reg -6834 # value: 'ff 0/subop/increment' +6257 52/push-edx +6258 53/push-ebx +6259 56/push-esi +6260 57/push-edi +6261 # ecx = stmt +6262 8b/-> *(ebp+8) 1/r32/ecx +6263 # edx = primitive +6264 8b/-> *(ebp+0xc) 2/r32/edx +6265 { +6266 $mu-stmt-matches-primitive?:check-name: +6267 # if (primitive->name != stmt->operation) return false +6268 (string-equal? *(ecx+4) *edx) # Stmt1-operation, Primitive-name => eax +6269 3d/compare-eax-and 0/imm32 +6270 75/jump-if-!= break/disp8 +6271 b8/copy-to-eax 0/imm32 +6272 e9/jump $mu-stmt-matches-primitive?:end/disp32 +6273 } +6274 $mu-stmt-matches-primitive?:check-inouts: +6275 # for (curr/esi in stmt->inouts, curr2/edi in primitive->inouts) +6276 8b/-> *(ecx+8) 6/r32/esi # Stmt1-inouts +6277 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts +6278 { +6279 # if (curr == 0 && curr2 == 0) move on to check outputs +6280 { +6281 81 7/subop/compare %esi 0/imm32 +6282 75/jump-if-!= break/disp8 +6283 $mu-stmt-matches-primitive?:stmt-inout-is-null: +6284 { +6285 81 7/subop/compare %edi 0/imm32 +6286 75/jump-if-!= break/disp8 +6287 # +6288 e9/jump $mu-stmt-matches-primitive?:check-outputs/disp32 +6289 } +6290 # return false +6291 b8/copy-to-eax 0/imm32/false +6292 e9/jump $mu-stmt-matches-primitive?:end/disp32 +6293 } +6294 # if (curr2 == 0) return false +6295 { +6296 81 7/subop/compare %edi 0/imm32 +6297 75/jump-if-!= break/disp8 +6298 $mu-stmt-matches-primitive?:prim-inout-is-null: +6299 b8/copy-to-eax 0/imm32/false +6300 e9/jump $mu-stmt-matches-primitive?:end/disp32 +6301 } +6302 # if (curr != curr2) return false +6303 { +6304 (operand-matches-primitive? *esi *edi) # => eax +6305 3d/compare-eax-and 0/imm32 +6306 75/jump-if-!= break/disp8 +6307 b8/copy-to-eax 0/imm32/false +6308 e9/jump $mu-stmt-matches-primitive?:end/disp32 +6309 } +6310 # curr=curr->next +6311 8b/-> *(esi+4) 6/r32/esi # Operand-next +6312 # curr2=curr2->next +6313 8b/-> *(edi+4) 7/r32/edi # Operand-next +6314 eb/jump loop/disp8 +6315 } +6316 $mu-stmt-matches-primitive?:check-outputs: +6317 # for (curr/esi in stmt->outputs, curr2/edi in primitive->outputs) +6318 8b/-> *(ecx+0xc) 6/r32/esi # Stmt1-outputs +6319 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs +6320 { +6321 # if (curr == 0) return (curr2 == 0) +6322 { +6323 $mu-stmt-matches-primitive?:check-output: +6324 81 7/subop/compare %esi 0/imm32 +6325 75/jump-if-!= break/disp8 +6326 { +6327 81 7/subop/compare %edi 0/imm32 +6328 75/jump-if-!= break/disp8 +6329 # return true +6330 b8/copy-to-eax 1/imm32 +6331 e9/jump $mu-stmt-matches-primitive?:end/disp32 +6332 } +6333 # return false +6334 b8/copy-to-eax 0/imm32 +6335 e9/jump $mu-stmt-matches-primitive?:end/disp32 +6336 } +6337 # if (curr2 == 0) return false +6338 { +6339 81 7/subop/compare %edi 0/imm32 +6340 75/jump-if-!= break/disp8 +6341 b8/copy-to-eax 0/imm32 +6342 e9/jump $mu-stmt-matches-primitive?:end/disp32 +6343 } +6344 # if (curr != curr2) return false +6345 { +6346 (operand-matches-primitive? *esi *edi) # List-value List-value => eax +6347 3d/compare-eax-and 0/imm32 +6348 75/jump-if-!= break/disp8 +6349 b8/copy-to-eax 0/imm32 +6350 e9/jump $mu-stmt-matches-primitive?:end/disp32 +6351 } +6352 # curr=curr->next +6353 8b/-> *(esi+4) 6/r32/esi # Operand-next +6354 # curr2=curr2->next +6355 8b/-> *(edi+4) 7/r32/edi # Operand-next +6356 eb/jump loop/disp8 +6357 } +6358 $mu-stmt-matches-primitive?:return-true: +6359 b8/copy-to-eax 1/imm32 +6360 $mu-stmt-matches-primitive?:end: +6361 # . restore registers +6362 5f/pop-to-edi +6363 5e/pop-to-esi +6364 5b/pop-to-ebx +6365 5a/pop-to-edx +6366 59/pop-to-ecx +6367 # . epilogue +6368 89/<- %esp 5/r32/ebp +6369 5d/pop-to-ebp +6370 c3/return +6371 +6372 operand-matches-primitive?: # var: (handle var), prim-var: (handle var) => result/eax: boolean +6373 # . prologue +6374 55/push-ebp +6375 89/<- %ebp 4/r32/esp +6376 # . save registers +6377 56/push-esi +6378 57/push-edi +6379 # esi = var +6380 8b/-> *(ebp+8) 6/r32/esi +6381 # edi = prim-var +6382 8b/-> *(ebp+0xc) 7/r32/edi +6383 # if (var->type != prim-var->type) return false +6384 (type-equal? *(esi+4) *(edi+4)) # Var-type, Var-type => eax +6385 3d/compare-eax-and 0/imm32 +6386 b8/copy-to-eax 0/imm32/false +6387 74/jump-if-= $operand-matches-primitive?:end/disp8 +6388 # return false if var->register doesn't match prim-var->register +6389 { +6390 # if addresses are equal, don't return here +6391 8b/-> *(esi+0x10) 0/r32/eax +6392 39/compare *(edi+0x10) 0/r32/eax +6393 74/jump-if-= break/disp8 +6394 # if either address is 0, return false +6395 3d/compare-eax-and 0/imm32 +6396 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result +6397 81 7/subop/compare *(edi+0x10) 0/imm32 +6398 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result +6399 # if prim-var->register is "*", return true +6400 (string-equal? *(edi+0x10) "*") # Var-register +6401 3d/compare-eax-and 0/imm32 +6402 b8/copy-to-eax 1/imm32/true +6403 75/jump-if-!= $operand-matches-primitive?:end/disp8 +6404 # if string contents don't match, return false +6405 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register +6406 3d/compare-eax-and 0/imm32 +6407 b8/copy-to-eax 0/imm32/false +6408 74/jump-if-= $operand-matches-primitive?:end/disp8 +6409 } +6410 # return true +6411 b8/copy-to-eax 1/imm32/true +6412 $operand-matches-primitive?:end: +6413 # . restore registers +6414 5f/pop-to-edi +6415 5e/pop-to-esi +6416 # . epilogue +6417 89/<- %esp 5/r32/ebp +6418 5d/pop-to-ebp +6419 c3/return +6420 +6421 type-equal?: # a: (handle tree type-id), b: (handle tree type-id) => result/eax: boolean +6422 # . prologue +6423 55/push-ebp +6424 89/<- %ebp 4/r32/esp +6425 # . save registers +6426 51/push-ecx +6427 52/push-edx +6428 # ecx = a +6429 8b/-> *(ebp+8) 1/r32/ecx +6430 # edx = b +6431 8b/-> *(ebp+0xc) 2/r32/edx +6432 # if (a == b) return true +6433 8b/-> %ecx 0/r32/eax # Var-type +6434 39/compare %edx 0/r32/eax # Var-type +6435 b8/copy-to-eax 1/imm32/true +6436 74/jump-if-= $type-equal?:end/disp8 +6437 # if (a < MAX_TYPE_ID) return false +6438 81 7/subop/compare %ecx 0x10000/imm32 +6439 b8/copy-to-eax 0/imm32/false +6440 72/jump-if-addr< $type-equal?:end/disp8 +6441 # if (b < MAX_TYPE_ID) return false +6442 81 7/subop/compare %edx 0x10000/imm32 +6443 b8/copy-to-eax 0/imm32/false +6444 72/jump-if-addr< $type-equal?:end/disp8 +6445 # if (!type-equal?(a->left, b->left)) return false +6446 (type-equal? *ecx *edx) # Tree-left, Tree-left => eax +6447 3d/compare-eax-and 0/imm32 +6448 74/jump-if-= $type-equal?:end/disp8 +6449 # return type-equal?(a->right, b->right) +6450 (type-equal? *(ecx+4) *(edx+4)) # Tree-right, Tree-right => eax +6451 $type-equal?:end: +6452 # . restore registers +6453 5a/pop-to-edx +6454 59/pop-to-ecx +6455 # . epilogue +6456 89/<- %esp 5/r32/ebp +6457 5d/pop-to-ebp +6458 c3/return +6459 +6460 test-emit-subx-statement-primitive: +6461 # Primitive operation on a variable on the stack. +6462 # increment foo +6463 # => +6464 # ff 0/subop/increment *(ebp-8) +6465 # +6466 # There's a variable on the var stack as follows: +6467 # name: 'foo' +6468 # type: int +6469 # stack-offset: -8 +6470 # +6471 # There's a primitive with this info: +6472 # name: 'increment' +6473 # inouts: int/mem +6474 # value: 'ff 0/subop/increment' +6475 # +6476 # There's nothing in functions. +6477 # +6478 # . prologue +6479 55/push-ebp +6480 89/<- %ebp 4/r32/esp +6481 # setup +6482 (clear-stream _test-output-stream) +6483 (clear-stream $_test-output-buffered-file->buffer) +6484 # var type/ecx: (handle tree type-id) = int +6485 68/push 0/imm32/right/null +6486 68/push 1/imm32/left/int +6487 89/<- %ecx 4/r32/esp +6488 # var var-foo/ecx: var +6489 68/push 0/imm32/no-register +6490 68/push -8/imm32/stack-offset +6491 68/push 1/imm32/block-depth +6492 51/push-ecx +6493 68/push "foo"/imm32 +6494 89/<- %ecx 4/r32/esp +6495 # var operand/ebx: (list var) +6496 68/push 0/imm32/next +6497 51/push-ecx/var-foo +6498 89/<- %ebx 4/r32/esp +6499 # var stmt/esi: statement +6500 68/push 0/imm32/next +6501 68/push 0/imm32/outputs +6502 53/push-ebx/operands +6503 68/push "increment"/imm32/operation +6504 68/push 1/imm32 +6505 89/<- %esi 4/r32/esp +6506 # var primitives/ebx: primitive +6507 68/push 0/imm32/next +6508 68/push 0/imm32/output-is-write-only +6509 68/push 0/imm32/no-disp32 +6510 68/push 0/imm32/no-imm32 +6511 68/push 0/imm32/no-r32 +6512 68/push 1/imm32/rm32-is-first-inout +6513 68/push "ff 0/subop/increment"/imm32/subx-name +6514 68/push 0/imm32/outputs +6515 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call +6516 68/push "increment"/imm32/name +6517 89/<- %ebx 4/r32/esp +6518 # convert +6519 c7 0/subop/copy *Curr-block-depth 0/imm32 +6520 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) +6521 (flush _test-output-buffered-file) +6522 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +6528 # check output +6529 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-statement-primitive") +6530 # . epilogue +6531 89/<- %esp 5/r32/ebp +6532 5d/pop-to-ebp +6533 c3/return +6534 +6535 test-emit-subx-statement-primitive-register: +6536 # Primitive operation on a variable in a register. +6537 # foo <- increment +6538 # => +6539 # ff 0/subop/increment %eax # sub-optimal, but should suffice +6540 # +6541 # There's a variable on the var stack as follows: +6542 # name: 'foo' +6543 # type: int +6544 # register: 'eax' +6545 # +6546 # There's a primitive with this info: +6547 # name: 'increment' +6548 # out: int/reg +6549 # value: 'ff 0/subop/increment' +6550 # +6551 # There's nothing in functions. +6552 # +6553 # . prologue +6554 55/push-ebp +6555 89/<- %ebp 4/r32/esp +6556 # setup +6557 (clear-stream _test-output-stream) +6558 (clear-stream $_test-output-buffered-file->buffer) +6559 # var type/ecx: (handle tree type-id) = int +6560 68/push 0/imm32/right/null +6561 68/push 1/imm32/left/int +6562 89/<- %ecx 4/r32/esp +6563 # var var-foo/ecx: var in eax +6564 68/push "eax"/imm32/register +6565 68/push 0/imm32/no-stack-offset +6566 68/push 1/imm32/block-depth +6567 51/push-ecx +6568 68/push "foo"/imm32 +6569 89/<- %ecx 4/r32/esp +6570 # var operand/ebx: (list var) +6571 68/push 0/imm32/next +6572 51/push-ecx/var-foo +6573 89/<- %ebx 4/r32/esp +6574 # var stmt/esi: statement +6575 68/push 0/imm32/next +6576 53/push-ebx/outputs +6577 68/push 0/imm32/inouts +6578 68/push "increment"/imm32/operation +6579 68/push 1/imm32 +6580 89/<- %esi 4/r32/esp +6581 # var formal-var/ebx: var in any register +6582 68/push Any-register/imm32 +6583 68/push 0/imm32/no-stack-offset +6584 68/push 1/imm32/block-depth +6585 ff 6/subop/push *(ecx+4) # Var-type +6586 68/push "dummy"/imm32 +6587 89/<- %ebx 4/r32/esp +6588 # var operand/ebx: (list var) +6589 68/push 0/imm32/next +6590 53/push-ebx/formal-var +6591 89/<- %ebx 4/r32/esp +6592 # var primitives/ebx: primitive +6593 68/push 0/imm32/next +6594 68/push 0/imm32/output-is-write-only +6595 68/push 0/imm32/no-disp32 +6596 68/push 0/imm32/no-imm32 +6597 68/push 0/imm32/no-r32 +6598 68/push 3/imm32/rm32-in-first-output +6599 68/push "ff 0/subop/increment"/imm32/subx-name +6600 53/push-ebx/outputs +6601 68/push 0/imm32/inouts +6602 68/push "increment"/imm32/name +6603 89/<- %ebx 4/r32/esp +6604 # convert +6605 c7 0/subop/copy *Curr-block-depth 0/imm32 +6606 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) +6607 (flush _test-output-buffered-file) +6608 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +6614 # check output +6615 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-primitive-register") +6616 # . epilogue +6617 89/<- %esp 5/r32/ebp +6618 5d/pop-to-ebp +6619 c3/return +6620 +6621 test-emit-subx-statement-select-primitive: +6622 # Select the right primitive between overloads. +6623 # foo <- increment +6624 # => +6625 # ff 0/subop/increment %eax # sub-optimal, but should suffice +6626 # +6627 # There's a variable on the var stack as follows: +6628 # name: 'foo' +6629 # type: int +6630 # register: 'eax' +6631 # +6632 # There's two primitives, as follows: +6633 # - name: 'increment' +6634 # out: int/reg +6635 # value: 'ff 0/subop/increment' +6636 # - name: 'increment' +6637 # inout: int/mem +6638 # value: 'ff 0/subop/increment' +6639 # +6640 # There's nothing in functions. +6641 # +6642 # . prologue +6643 55/push-ebp +6644 89/<- %ebp 4/r32/esp +6645 # setup +6646 (clear-stream _test-output-stream) +6647 (clear-stream $_test-output-buffered-file->buffer) +6648 # var type/ecx: (handle tree type-id) = int +6649 68/push 0/imm32/right/null +6650 68/push 1/imm32/left/int +6651 89/<- %ecx 4/r32/esp +6652 # var var-foo/ecx: var in eax +6653 68/push "eax"/imm32/register +6654 68/push 0/imm32/no-stack-offset +6655 68/push 1/imm32/block-depth +6656 51/push-ecx +6657 68/push "foo"/imm32 +6658 89/<- %ecx 4/r32/esp +6659 # var real-outputs/edi: (list var) +6660 68/push 0/imm32/next +6661 51/push-ecx/var-foo +6662 89/<- %edi 4/r32/esp +6663 # var stmt/esi: statement +6664 68/push 0/imm32/next +6665 57/push-edi/outputs +6666 68/push 0/imm32/inouts +6667 68/push "increment"/imm32/operation +6668 68/push 1/imm32 +6669 89/<- %esi 4/r32/esp +6670 # var formal-var/ebx: var in any register +6671 68/push Any-register/imm32 +6672 68/push 0/imm32/no-stack-offset +6673 68/push 1/imm32/block-depth +6674 ff 6/subop/push *(ecx+4) # Var-type +6675 68/push "dummy"/imm32 +6676 89/<- %ebx 4/r32/esp +6677 # var formal-outputs/ebx: (list var) = {formal-var, 0} +6678 68/push 0/imm32/next +6679 53/push-ebx/formal-var +6680 89/<- %ebx 4/r32/esp +6681 # var primitive1/ebx: primitive +6682 68/push 0/imm32/next +6683 68/push 0/imm32/output-is-write-only +6684 68/push 0/imm32/no-disp32 +6685 68/push 0/imm32/no-imm32 +6686 68/push 0/imm32/no-r32 +6687 68/push 3/imm32/rm32-in-first-output +6688 68/push "ff 0/subop/increment"/imm32/subx-name +6689 53/push-ebx/outputs/formal-outputs +6690 68/push 0/imm32/inouts +6691 68/push "increment"/imm32/name +6692 89/<- %ebx 4/r32/esp +6693 # var primitives/ebx: primitive +6694 53/push-ebx/next +6695 68/push 0/imm32/output-is-write-only +6696 68/push 0/imm32/no-disp32 +6697 68/push 0/imm32/no-imm32 +6698 68/push 0/imm32/no-r32 +6699 68/push 1/imm32/rm32-is-first-inout +6700 68/push "ff 0/subop/increment"/imm32/subx-name +6701 68/push 0/imm32/outputs +6702 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call +6703 68/push "increment"/imm32/name +6704 89/<- %ebx 4/r32/esp +6705 # convert +6706 c7 0/subop/copy *Curr-block-depth 0/imm32 +6707 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) +6708 (flush _test-output-buffered-file) +6709 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +6715 # check output +6716 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive") +6717 # . epilogue +6718 89/<- %esp 5/r32/ebp +6719 5d/pop-to-ebp +6720 c3/return +6721 +6722 test-emit-subx-statement-select-primitive-2: +6723 # Select the right primitive between overloads. +6724 # foo <- increment +6725 # => +6726 # ff 0/subop/increment %eax # sub-optimal, but should suffice +6727 # +6728 # There's a variable on the var stack as follows: +6729 # name: 'foo' +6730 # type: int +6731 # register: 'eax' +6732 # +6733 # There's two primitives, as follows: +6734 # - name: 'increment' +6735 # out: int/reg +6736 # value: 'ff 0/subop/increment' +6737 # - name: 'increment' +6738 # inout: int/mem +6739 # value: 'ff 0/subop/increment' +6740 # +6741 # There's nothing in functions. +6742 # +6743 # . prologue +6744 55/push-ebp +6745 89/<- %ebp 4/r32/esp +6746 # setup +6747 (clear-stream _test-output-stream) +6748 (clear-stream $_test-output-buffered-file->buffer) +6749 # var type/ecx: (handle tree type-id) = int +6750 68/push 0/imm32/right/null +6751 68/push 1/imm32/left/int +6752 89/<- %ecx 4/r32/esp +6753 # var var-foo/ecx: var in eax +6754 68/push "eax"/imm32/register +6755 68/push 0/imm32/no-stack-offset +6756 68/push 1/imm32/block-depth +6757 51/push-ecx +6758 68/push "foo"/imm32 +6759 89/<- %ecx 4/r32/esp +6760 # var inouts/edi: (list var) +6761 68/push 0/imm32/next +6762 51/push-ecx/var-foo +6763 89/<- %edi 4/r32/esp +6764 # var stmt/esi: statement +6765 68/push 0/imm32/next +6766 68/push 0/imm32/outputs +6767 57/push-edi/inouts +6768 68/push "increment"/imm32/operation +6769 68/push 1/imm32 +6770 89/<- %esi 4/r32/esp +6771 # var formal-var/ebx: var in any register +6772 68/push Any-register/imm32 +6773 68/push 0/imm32/no-stack-offset +6774 68/push 1/imm32/block-depth +6775 ff 6/subop/push *(ecx+4) # Var-type +6776 68/push "dummy"/imm32 +6777 89/<- %ebx 4/r32/esp +6778 # var operand/ebx: (list var) +6779 68/push 0/imm32/next +6780 53/push-ebx/formal-var +6781 89/<- %ebx 4/r32/esp +6782 # var primitive1/ebx: primitive +6783 68/push 0/imm32/next +6784 68/push 0/imm32/output-is-write-only +6785 68/push 0/imm32/no-disp32 +6786 68/push 0/imm32/no-imm32 +6787 68/push 0/imm32/no-r32 +6788 68/push 3/imm32/rm32-in-first-output +6789 68/push "ff 0/subop/increment"/imm32/subx-name +6790 53/push-ebx/outputs/formal-outputs +6791 68/push 0/imm32/inouts +6792 68/push "increment"/imm32/name +6793 89/<- %ebx 4/r32/esp +6794 # var primitives/ebx: primitive +6795 53/push-ebx/next +6796 68/push 0/imm32/output-is-write-only +6797 68/push 0/imm32/no-disp32 +6798 68/push 0/imm32/no-imm32 +6799 68/push 0/imm32/no-r32 +6800 68/push 1/imm32/rm32-is-first-inout +6801 68/push "ff 0/subop/increment"/imm32/subx-name +6802 68/push 0/imm32/outputs +6803 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call +6804 68/push "increment"/imm32/name +6805 89/<- %ebx 4/r32/esp +6806 # convert +6807 c7 0/subop/copy *Curr-block-depth 0/imm32 +6808 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) +6809 (flush _test-output-buffered-file) +6810 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +6816 # check output +6817 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2") +6818 # . epilogue +6819 89/<- %esp 5/r32/ebp +6820 5d/pop-to-ebp +6821 c3/return +6822 +6823 test-increment-register: +6824 # Select the right register between overloads. +6825 # foo <- increment +6826 # => +6827 # 50/increment-eax +6828 # +6829 # There's a variable on the var stack as follows: +6830 # name: 'foo' +6831 # type: int +6832 # register: 'eax' +6833 # +6834 # Primitives are the global definitions. 6835 # -6836 # There's nothing in functions. +6836 # There are no functions defined. 6837 # 6838 # . prologue 6839 55/push-ebp @@ -6819,1166 +6799,896 @@ if ('onhashchange' in window) { 6852 51/push-ecx 6853 68/push "foo"/imm32 6854 89/<- %ecx 4/r32/esp -6855 # var operand/ebx: (list var) +6855 # var real-outputs/edi: (list var) 6856 68/push 0/imm32/next 6857 51/push-ecx/var-foo -6858 89/<- %ebx 4/r32/esp +6858 89/<- %edi 4/r32/esp 6859 # var stmt/esi: statement 6860 68/push 0/imm32/next -6861 53/push-ebx/outputs +6861 57/push-edi/outputs 6862 68/push 0/imm32/inouts 6863 68/push "increment"/imm32/operation -6864 68/push 1/imm32 +6864 68/push 1/imm32/regular-statement 6865 89/<- %esi 4/r32/esp -6866 # var formal-var/ebx: var in any register -6867 68/push Any-register/imm32 -6868 68/push 0/imm32/no-stack-offset -6869 68/push 1/imm32/block-depth -6870 ff 6/subop/push *(ecx+4) # Var-type -6871 68/push "dummy"/imm32 -6872 89/<- %ebx 4/r32/esp -6873 # var operand/ebx: (list var) -6874 68/push 0/imm32/next -6875 53/push-ebx/formal-var -6876 89/<- %ebx 4/r32/esp -6877 # var primitives/ebx: primitive -6878 68/push 0/imm32/next -6879 68/push 0/imm32/output-is-write-only -6880 68/push 0/imm32/no-disp32 -6881 68/push 0/imm32/no-imm32 -6882 68/push 0/imm32/no-r32 -6883 68/push 3/imm32/rm32-in-first-output -6884 68/push "ff 0/subop/increment"/imm32/subx-name -6885 53/push-ebx/outputs -6886 68/push 0/imm32/inouts -6887 68/push "increment"/imm32/name -6888 89/<- %ebx 4/r32/esp -6889 # convert -6890 c7 0/subop/copy *Curr-block-depth 0/imm32 -6891 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -6892 (flush _test-output-buffered-file) -6893 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -6899 # check output -6900 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-primitive-register") -6901 # . epilogue -6902 89/<- %esp 5/r32/ebp -6903 5d/pop-to-ebp -6904 c3/return -6905 -6906 test-emit-subx-statement-select-primitive: -6907 # Select the right primitive between overloads. -6908 # foo <- increment -6909 # => -6910 # ff 0/subop/increment %eax # sub-optimal, but should suffice -6911 # -6912 # There's a variable on the var stack as follows: -6913 # name: 'foo' -6914 # type: int -6915 # register: 'eax' -6916 # -6917 # There's two primitives, as follows: -6918 # - name: 'increment' -6919 # out: int/reg -6920 # value: 'ff 0/subop/increment' -6921 # - name: 'increment' -6922 # inout: int/mem -6923 # value: 'ff 0/subop/increment' -6924 # -6925 # There's nothing in functions. -6926 # -6927 # . prologue -6928 55/push-ebp -6929 89/<- %ebp 4/r32/esp -6930 # setup -6931 (clear-stream _test-output-stream) -6932 (clear-stream $_test-output-buffered-file->buffer) -6933 # var type/ecx: (handle tree type-id) = int -6934 68/push 0/imm32/right/null -6935 68/push 1/imm32/left/int -6936 89/<- %ecx 4/r32/esp -6937 # var var-foo/ecx: var in eax -6938 68/push "eax"/imm32/register -6939 68/push 0/imm32/no-stack-offset -6940 68/push 1/imm32/block-depth -6941 51/push-ecx -6942 68/push "foo"/imm32 -6943 89/<- %ecx 4/r32/esp -6944 # var real-outputs/edi: (list var) -6945 68/push 0/imm32/next -6946 51/push-ecx/var-foo -6947 89/<- %edi 4/r32/esp -6948 # var stmt/esi: statement -6949 68/push 0/imm32/next -6950 57/push-edi/outputs -6951 68/push 0/imm32/inouts -6952 68/push "increment"/imm32/operation -6953 68/push 1/imm32 -6954 89/<- %esi 4/r32/esp -6955 # var formal-var/ebx: var in any register -6956 68/push Any-register/imm32 -6957 68/push 0/imm32/no-stack-offset -6958 68/push 1/imm32/block-depth -6959 ff 6/subop/push *(ecx+4) # Var-type -6960 68/push "dummy"/imm32 -6961 89/<- %ebx 4/r32/esp -6962 # var formal-outputs/ebx: (list var) = {formal-var, 0} -6963 68/push 0/imm32/next -6964 53/push-ebx/formal-var -6965 89/<- %ebx 4/r32/esp -6966 # var primitive1/ebx: primitive -6967 68/push 0/imm32/next -6968 68/push 0/imm32/output-is-write-only -6969 68/push 0/imm32/no-disp32 -6970 68/push 0/imm32/no-imm32 -6971 68/push 0/imm32/no-r32 -6972 68/push 3/imm32/rm32-in-first-output -6973 68/push "ff 0/subop/increment"/imm32/subx-name -6974 53/push-ebx/outputs/formal-outputs -6975 68/push 0/imm32/inouts -6976 68/push "increment"/imm32/name -6977 89/<- %ebx 4/r32/esp -6978 # var primitives/ebx: primitive -6979 53/push-ebx/next -6980 68/push 0/imm32/output-is-write-only -6981 68/push 0/imm32/no-disp32 -6982 68/push 0/imm32/no-imm32 -6983 68/push 0/imm32/no-r32 -6984 68/push 1/imm32/rm32-is-first-inout -6985 68/push "ff 0/subop/increment"/imm32/subx-name -6986 68/push 0/imm32/outputs -6987 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -6988 68/push "increment"/imm32/name -6989 89/<- %ebx 4/r32/esp -6990 # convert -6991 c7 0/subop/copy *Curr-block-depth 0/imm32 -6992 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -6993 (flush _test-output-buffered-file) -6994 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7000 # check output -7001 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive") -7002 # . epilogue -7003 89/<- %esp 5/r32/ebp -7004 5d/pop-to-ebp -7005 c3/return -7006 -7007 test-emit-subx-statement-select-primitive-2: -7008 # Select the right primitive between overloads. -7009 # foo <- increment -7010 # => -7011 # ff 0/subop/increment %eax # sub-optimal, but should suffice -7012 # -7013 # There's a variable on the var stack as follows: -7014 # name: 'foo' -7015 # type: int -7016 # register: 'eax' -7017 # -7018 # There's two primitives, as follows: -7019 # - name: 'increment' -7020 # out: int/reg -7021 # value: 'ff 0/subop/increment' -7022 # - name: 'increment' -7023 # inout: int/mem -7024 # value: 'ff 0/subop/increment' -7025 # -7026 # There's nothing in functions. -7027 # -7028 # . prologue -7029 55/push-ebp -7030 89/<- %ebp 4/r32/esp -7031 # setup -7032 (clear-stream _test-output-stream) -7033 (clear-stream $_test-output-buffered-file->buffer) -7034 # var type/ecx: (handle tree type-id) = int -7035 68/push 0/imm32/right/null -7036 68/push 1/imm32/left/int -7037 89/<- %ecx 4/r32/esp -7038 # var var-foo/ecx: var in eax -7039 68/push "eax"/imm32/register -7040 68/push 0/imm32/no-stack-offset -7041 68/push 1/imm32/block-depth -7042 51/push-ecx -7043 68/push "foo"/imm32 -7044 89/<- %ecx 4/r32/esp -7045 # var inouts/edi: (list var) -7046 68/push 0/imm32/next -7047 51/push-ecx/var-foo -7048 89/<- %edi 4/r32/esp -7049 # var stmt/esi: statement -7050 68/push 0/imm32/next -7051 68/push 0/imm32/outputs -7052 57/push-edi/inouts -7053 68/push "increment"/imm32/operation -7054 68/push 1/imm32 -7055 89/<- %esi 4/r32/esp -7056 # var formal-var/ebx: var in any register -7057 68/push Any-register/imm32 -7058 68/push 0/imm32/no-stack-offset -7059 68/push 1/imm32/block-depth -7060 ff 6/subop/push *(ecx+4) # Var-type -7061 68/push "dummy"/imm32 -7062 89/<- %ebx 4/r32/esp -7063 # var operand/ebx: (list var) -7064 68/push 0/imm32/next -7065 53/push-ebx/formal-var -7066 89/<- %ebx 4/r32/esp -7067 # var primitive1/ebx: primitive -7068 68/push 0/imm32/next -7069 68/push 0/imm32/output-is-write-only -7070 68/push 0/imm32/no-disp32 -7071 68/push 0/imm32/no-imm32 -7072 68/push 0/imm32/no-r32 -7073 68/push 3/imm32/rm32-in-first-output -7074 68/push "ff 0/subop/increment"/imm32/subx-name -7075 53/push-ebx/outputs/formal-outputs -7076 68/push 0/imm32/inouts -7077 68/push "increment"/imm32/name -7078 89/<- %ebx 4/r32/esp -7079 # var primitives/ebx: primitive -7080 53/push-ebx/next -7081 68/push 0/imm32/output-is-write-only -7082 68/push 0/imm32/no-disp32 -7083 68/push 0/imm32/no-imm32 -7084 68/push 0/imm32/no-r32 -7085 68/push 1/imm32/rm32-is-first-inout -7086 68/push "ff 0/subop/increment"/imm32/subx-name -7087 68/push 0/imm32/outputs -7088 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -7089 68/push "increment"/imm32/name -7090 89/<- %ebx 4/r32/esp -7091 # convert -7092 c7 0/subop/copy *Curr-block-depth 0/imm32 -7093 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -7094 (flush _test-output-buffered-file) -7095 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7101 # check output -7102 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2") -7103 # . epilogue -7104 89/<- %esp 5/r32/ebp -7105 5d/pop-to-ebp -7106 c3/return -7107 -7108 test-increment-register: -7109 # Select the right primitive between overloads. -7110 # foo <- increment -7111 # => -7112 # 50/increment-eax -7113 # -7114 # There's a variable on the var stack as follows: -7115 # name: 'foo' -7116 # type: int -7117 # register: 'eax' -7118 # -7119 # Primitives are the global definitions. -7120 # -7121 # There are no functions defined. -7122 # -7123 # . prologue -7124 55/push-ebp -7125 89/<- %ebp 4/r32/esp -7126 # setup -7127 (clear-stream _test-output-stream) -7128 (clear-stream $_test-output-buffered-file->buffer) -7129 # var type/ecx: (handle tree type-id) = int -7130 68/push 0/imm32/right/null -7131 68/push 1/imm32/left/int -7132 89/<- %ecx 4/r32/esp -7133 # var var-foo/ecx: var in eax -7134 68/push "eax"/imm32/register -7135 68/push 0/imm32/no-stack-offset -7136 68/push 1/imm32/block-depth -7137 51/push-ecx -7138 68/push "foo"/imm32 -7139 89/<- %ecx 4/r32/esp -7140 # var real-outputs/edi: (list var) -7141 68/push 0/imm32/next -7142 51/push-ecx/var-foo -7143 89/<- %edi 4/r32/esp -7144 # var stmt/esi: statement -7145 68/push 0/imm32/next -7146 57/push-edi/outputs -7147 68/push 0/imm32/inouts -7148 68/push "increment"/imm32/operation -7149 68/push 1/imm32/regular-statement -7150 89/<- %esi 4/r32/esp -7151 # convert -7152 c7 0/subop/copy *Curr-block-depth 0/imm32 -7153 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7154 (flush _test-output-buffered-file) -7155 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7161 # check output -7162 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") -7163 # . epilogue -7164 89/<- %esp 5/r32/ebp -7165 5d/pop-to-ebp -7166 c3/return -7167 -7168 test-increment-var: -7169 # Select the right primitive between overloads. -7170 # foo <- increment -7171 # => -7172 # ff 0/subop/increment %eax # sub-optimal, but should suffice -7173 # -7174 # There's a variable on the var stack as follows: -7175 # name: 'foo' -7176 # type: int -7177 # register: 'eax' -7178 # -7179 # Primitives are the global definitions. -7180 # -7181 # There are no functions defined. -7182 # -7183 # . prologue -7184 55/push-ebp -7185 89/<- %ebp 4/r32/esp -7186 # setup -7187 (clear-stream _test-output-stream) -7188 (clear-stream $_test-output-buffered-file->buffer) -7189 # var type/ecx: (handle tree type-id) = int -7190 68/push 0/imm32/right/null -7191 68/push 1/imm32/left/int -7192 89/<- %ecx 4/r32/esp -7193 # var var-foo/ecx: var in eax -7194 68/push "eax"/imm32/register -7195 68/push 0/imm32/no-stack-offset -7196 68/push 1/imm32/block-depth -7197 51/push-ecx -7198 68/push "foo"/imm32 -7199 89/<- %ecx 4/r32/esp -7200 # var inouts/edi: (list var) -7201 68/push 0/imm32/next -7202 51/push-ecx/var-foo -7203 89/<- %edi 4/r32/esp -7204 # var stmt/esi: statement -7205 68/push 0/imm32/next -7206 68/push 0/imm32/outputs -7207 57/push-edi/inouts -7208 68/push "increment"/imm32/operation -7209 68/push 1/imm32 -7210 89/<- %esi 4/r32/esp -7211 # convert -7212 c7 0/subop/copy *Curr-block-depth 0/imm32 -7213 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7214 (flush _test-output-buffered-file) -7215 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7221 # check output -7222 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-increment-var") -7223 # . epilogue -7224 89/<- %esp 5/r32/ebp -7225 5d/pop-to-ebp -7226 c3/return -7227 -7228 test-add-reg-to-reg: -7229 # var1/reg <- add var2/reg -7230 # => -7231 # 01/add %var1 var2 -7232 # -7233 # . prologue -7234 55/push-ebp -7235 89/<- %ebp 4/r32/esp -7236 # setup -7237 (clear-stream _test-output-stream) -7238 (clear-stream $_test-output-buffered-file->buffer) -7239 # var type/ecx: (handle tree type-id) = int -7240 68/push 0/imm32/right/null -7241 68/push 1/imm32/left/int -7242 89/<- %ecx 4/r32/esp -7243 # var var-var1/ecx: var in eax -7244 68/push "eax"/imm32/register -7245 68/push 0/imm32/no-stack-offset -7246 68/push 1/imm32/block-depth -7247 51/push-ecx -7248 68/push "var1"/imm32 -7249 89/<- %ecx 4/r32/esp -7250 # var var-var2/edx: var in ecx -7251 68/push "ecx"/imm32/register -7252 68/push 0/imm32/no-stack-offset -7253 68/push 1/imm32/block-depth -7254 ff 6/subop/push *(ecx+4) # Var-type -7255 68/push "var2"/imm32 -7256 89/<- %edx 4/r32/esp -7257 # var inouts/esi: (list var2) -7258 68/push 0/imm32/next -7259 52/push-edx/var-var2 -7260 89/<- %esi 4/r32/esp -7261 # var outputs/edi: (list var1) -7262 68/push 0/imm32/next -7263 51/push-ecx/var-var1 -7264 89/<- %edi 4/r32/esp -7265 # var stmt/esi: statement -7266 68/push 0/imm32/next -7267 57/push-edi/outputs -7268 56/push-esi/inouts -7269 68/push "add"/imm32/operation -7270 68/push 1/imm32 -7271 89/<- %esi 4/r32/esp -7272 # convert -7273 c7 0/subop/copy *Curr-block-depth 0/imm32 -7274 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7275 (flush _test-output-buffered-file) -7276 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7282 # check output -7283 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") -7284 # . epilogue -7285 89/<- %esp 5/r32/ebp -7286 5d/pop-to-ebp -7287 c3/return -7288 -7289 test-add-reg-to-mem: -7290 # add-to var1 var2/reg -7291 # => -7292 # 01/add *(ebp+__) var2 -7293 # -7294 # . prologue -7295 55/push-ebp -7296 89/<- %ebp 4/r32/esp -7297 # setup -7298 (clear-stream _test-output-stream) -7299 (clear-stream $_test-output-buffered-file->buffer) -7300 # var type/ecx: (handle tree type-id) = int -7301 68/push 0/imm32/right/null -7302 68/push 1/imm32/left/int -7303 89/<- %ecx 4/r32/esp -7304 # var var-var1/ecx: var -7305 68/push 0/imm32/no-register -7306 68/push 8/imm32/stack-offset -7307 68/push 1/imm32/block-depth -7308 51/push-ecx -7309 68/push "var1"/imm32 -7310 89/<- %ecx 4/r32/esp -7311 # var var-var2/edx: var in ecx -7312 68/push "ecx"/imm32/register -7313 68/push 0/imm32/no-stack-offset -7314 68/push 1/imm32/block-depth -7315 ff 6/subop/push *(ecx+4) # Var-type -7316 68/push "var2"/imm32 -7317 89/<- %edx 4/r32/esp -7318 # var inouts/esi: (list var2) -7319 68/push 0/imm32/next -7320 52/push-edx/var-var2 -7321 89/<- %esi 4/r32/esp -7322 # var inouts = (list var1 var2) -7323 56/push-esi/next -7324 51/push-ecx/var-var1 -7325 89/<- %esi 4/r32/esp -7326 # var stmt/esi: statement -7327 68/push 0/imm32/next -7328 68/push 0/imm32/outputs -7329 56/push-esi/inouts -7330 68/push "add-to"/imm32/operation -7331 68/push 1/imm32 -7332 89/<- %esi 4/r32/esp -7333 # convert -7334 c7 0/subop/copy *Curr-block-depth 0/imm32 -7335 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7336 (flush _test-output-buffered-file) -7337 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7343 # check output -7344 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") -7345 # . epilogue -7346 89/<- %esp 5/r32/ebp -7347 5d/pop-to-ebp -7348 c3/return -7349 -7350 test-add-mem-to-reg: -7351 # var1/reg <- add var2 -7352 # => -7353 # 03/add *(ebp+__) var1 -7354 # -7355 # . prologue -7356 55/push-ebp -7357 89/<- %ebp 4/r32/esp -7358 # setup -7359 (clear-stream _test-output-stream) -7360 (clear-stream $_test-output-buffered-file->buffer) -7361 # var type/ecx: (handle tree type-id) = int -7362 68/push 0/imm32/right/null -7363 68/push 1/imm32/left/int -7364 89/<- %ecx 4/r32/esp -7365 # var var-var1/ecx: var in eax -7366 68/push "eax"/imm32/register -7367 68/push 0/imm32/no-stack-offset -7368 68/push 1/imm32/block-depth -7369 51/push-ecx -7370 68/push "var1"/imm32 -7371 89/<- %ecx 4/r32/esp -7372 # var var-var2/edx: var -7373 68/push 0/imm32/no-register -7374 68/push 8/imm32/stack-offset -7375 68/push 1/imm32/block-depth -7376 ff 6/subop/push *(ecx+4) # Var-type -7377 68/push "var2"/imm32 -7378 89/<- %edx 4/r32/esp -7379 # var inouts/esi: (list var2) -7380 68/push 0/imm32/next -7381 52/push-edx/var-var2 -7382 89/<- %esi 4/r32/esp -7383 # var outputs/edi: (list var1) -7384 68/push 0/imm32/next -7385 51/push-ecx/var-var1 -7386 89/<- %edi 4/r32/esp -7387 # var stmt/esi: statement -7388 68/push 0/imm32/next -7389 57/push-edi/outputs -7390 56/push-esi/inouts -7391 68/push "add"/imm32/operation -7392 68/push 1/imm32 -7393 89/<- %esi 4/r32/esp -7394 # convert -7395 c7 0/subop/copy *Curr-block-depth 0/imm32 -7396 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7397 (flush _test-output-buffered-file) -7398 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7404 # check output -7405 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") -7406 # . epilogue -7407 89/<- %esp 5/r32/ebp -7408 5d/pop-to-ebp -7409 c3/return -7410 -7411 test-add-literal-to-eax: -7412 # var1/eax <- add 0x34 -7413 # => -7414 # 05/add-to-eax 0x34/imm32 -7415 # -7416 # . prologue -7417 55/push-ebp -7418 89/<- %ebp 4/r32/esp -7419 # setup -7420 (clear-stream _test-output-stream) -7421 (clear-stream $_test-output-buffered-file->buffer) -7422 # var type/ecx: (handle tree type-id) = int -7423 68/push 0/imm32/right/null -7424 68/push 1/imm32/left/int -7425 89/<- %ecx 4/r32/esp -7426 # var var-var1/ecx: var in eax -7427 68/push "eax"/imm32/register -7428 68/push 0/imm32/no-stack-offset -7429 68/push 1/imm32/block-depth -7430 51/push-ecx -7431 68/push "var1"/imm32 -7432 89/<- %ecx 4/r32/esp -7433 # var type/edx: (handle tree type-id) = literal -7434 68/push 0/imm32/right/null -7435 68/push 0/imm32/left/literal -7436 89/<- %edx 4/r32/esp -7437 # var var-var2/edx: var literal -7438 68/push 0/imm32/no-register -7439 68/push 0/imm32/no-stack-offset -7440 68/push 1/imm32/block-depth -7441 52/push-edx -7442 68/push "0x34"/imm32 -7443 89/<- %edx 4/r32/esp -7444 # var inouts/esi: (list var2) -7445 68/push 0/imm32/next -7446 52/push-edx/var-var2 -7447 89/<- %esi 4/r32/esp -7448 # var outputs/edi: (list var1) -7449 68/push 0/imm32/next -7450 51/push-ecx/var-var1 -7451 89/<- %edi 4/r32/esp -7452 # var stmt/esi: statement -7453 68/push 0/imm32/next -7454 57/push-edi/outputs -7455 56/push-esi/inouts -7456 68/push "add"/imm32/operation -7457 68/push 1/imm32 -7458 89/<- %esi 4/r32/esp -7459 # convert -7460 c7 0/subop/copy *Curr-block-depth 0/imm32 -7461 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7462 (flush _test-output-buffered-file) -7463 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7469 # check output -7470 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") -7471 # . epilogue -7472 89/<- %esp 5/r32/ebp -7473 5d/pop-to-ebp -7474 c3/return -7475 -7476 test-add-literal-to-reg: -7477 # var1/ecx <- add 0x34 -7478 # => -7479 # 81 0/subop/add %ecx 0x34/imm32 -7480 # -7481 # . prologue -7482 55/push-ebp -7483 89/<- %ebp 4/r32/esp -7484 # setup -7485 (clear-stream _test-output-stream) -7486 (clear-stream $_test-output-buffered-file->buffer) -7487 # var type/ecx: (handle tree type-id) = int -7488 68/push 0/imm32/right/null -7489 68/push 1/imm32/left/int -7490 89/<- %ecx 4/r32/esp -7491 # var var-var1/ecx: var in ecx -7492 68/push "ecx"/imm32/register -7493 68/push 0/imm32/no-stack-offset -7494 68/push 1/imm32/block-depth -7495 51/push-ecx -7496 68/push "var1"/imm32 -7497 89/<- %ecx 4/r32/esp -7498 # var type/edx: (handle tree type-id) = literal -7499 68/push 0/imm32/right/null -7500 68/push 0/imm32/left/literal -7501 89/<- %edx 4/r32/esp -7502 # var var-var2/edx: var literal -7503 68/push 0/imm32/no-register -7504 68/push 0/imm32/no-stack-offset -7505 68/push 1/imm32/block-depth -7506 52/push-edx -7507 68/push "0x34"/imm32 -7508 89/<- %edx 4/r32/esp -7509 # var inouts/esi: (list var2) -7510 68/push 0/imm32/next -7511 52/push-edx/var-var2 -7512 89/<- %esi 4/r32/esp -7513 # var outputs/edi: (list var1) -7514 68/push 0/imm32/next -7515 51/push-ecx/var-var1 -7516 89/<- %edi 4/r32/esp -7517 # var stmt/esi: statement -7518 68/push 0/imm32/next -7519 57/push-edi/outputs -7520 56/push-esi/inouts -7521 68/push "add"/imm32/operation -7522 68/push 1/imm32 -7523 89/<- %esi 4/r32/esp -7524 # convert -7525 c7 0/subop/copy *Curr-block-depth 0/imm32 -7526 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7527 (flush _test-output-buffered-file) -7528 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7534 # check output -7535 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") -7536 # . epilogue -7537 89/<- %esp 5/r32/ebp -7538 5d/pop-to-ebp -7539 c3/return -7540 -7541 test-add-literal-to-mem: -7542 # add-to var1, 0x34 -7543 # => -7544 # 81 0/subop/add %eax 0x34/imm32 -7545 # -7546 # . prologue -7547 55/push-ebp -7548 89/<- %ebp 4/r32/esp -7549 # setup -7550 (clear-stream _test-output-stream) -7551 (clear-stream $_test-output-buffered-file->buffer) -7552 # var type/ecx: (handle tree type-id) = int -7553 68/push 0/imm32/right/null -7554 68/push 1/imm32/left/int -7555 89/<- %ecx 4/r32/esp -7556 # var var-var1/ecx: var -7557 68/push 0/imm32/no-register -7558 68/push 8/imm32/stack-offset -7559 68/push 1/imm32/block-depth -7560 51/push-ecx -7561 68/push "var1"/imm32 -7562 89/<- %ecx 4/r32/esp -7563 # var type/edx: (handle tree type-id) = literal -7564 68/push 0/imm32/right/null -7565 68/push 0/imm32/left/literal -7566 89/<- %edx 4/r32/esp -7567 # var var-var2/edx: var literal -7568 68/push 0/imm32/no-register -7569 68/push 0/imm32/no-stack-offset -7570 68/push 1/imm32/block-depth -7571 52/push-edx -7572 68/push "0x34"/imm32 -7573 89/<- %edx 4/r32/esp -7574 # var inouts/esi: (list var2) -7575 68/push 0/imm32/next -7576 52/push-edx/var-var2 -7577 89/<- %esi 4/r32/esp -7578 # var inouts = (list var1 inouts) -7579 56/push-esi/next -7580 51/push-ecx/var-var1 -7581 89/<- %esi 4/r32/esp -7582 # var stmt/esi: statement -7583 68/push 0/imm32/next -7584 68/push 0/imm32/outputs -7585 56/push-esi/inouts -7586 68/push "add-to"/imm32/operation -7587 68/push 1/imm32 -7588 89/<- %esi 4/r32/esp -7589 # convert -7590 c7 0/subop/copy *Curr-block-depth 0/imm32 -7591 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7592 (flush _test-output-buffered-file) -7593 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7599 # check output -7600 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") -7601 # . epilogue -7602 89/<- %esp 5/r32/ebp -7603 5d/pop-to-ebp -7604 c3/return -7605 -7606 test-compare-mem-with-reg: -7607 # compare var1, var2/eax -7608 # => -7609 # 39/compare *(ebp+___) 0/r32/eax -7610 # -7611 # . prologue -7612 55/push-ebp -7613 89/<- %ebp 4/r32/esp -7614 # setup -7615 (clear-stream _test-output-stream) -7616 (clear-stream $_test-output-buffered-file->buffer) -7617 # var type/ecx: (handle tree type-id) = int -7618 68/push 0/imm32/right/null -7619 68/push 1/imm32/left/int -7620 89/<- %ecx 4/r32/esp -7621 # var var-var2/ecx: var in eax -7622 68/push "eax"/imm32/register -7623 68/push 0/imm32/no-stack-offset -7624 68/push 1/imm32/block-depth -7625 51/push-ecx -7626 68/push "var2"/imm32 -7627 89/<- %ecx 4/r32/esp -7628 # var var-var1/edx: var -7629 68/push 0/imm32/no-register -7630 68/push 8/imm32/stack-offset -7631 68/push 1/imm32/block-depth -7632 ff 6/subop/push *(ecx+4) # Var-type -7633 68/push "var1"/imm32 -7634 89/<- %edx 4/r32/esp -7635 # var inouts/esi: (list var1 var2) -7636 68/push 0/imm32/next -7637 51/push-ecx/var-var2 -7638 89/<- %esi 4/r32/esp -7639 56/push-esi -7640 52/push-edx/var-var1 -7641 89/<- %esi 4/r32/esp -7642 # var stmt/esi: statement -7643 68/push 0/imm32/next -7644 68/push 0/imm32/outputs -7645 56/push-esi/inouts -7646 68/push "compare"/imm32/operation -7647 68/push 1/imm32 -7648 89/<- %esi 4/r32/esp -7649 # convert -7650 c7 0/subop/copy *Curr-block-depth 0/imm32 -7651 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7652 (flush _test-output-buffered-file) -7653 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7659 # check output -7660 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") -7661 # . epilogue -7662 89/<- %esp 5/r32/ebp -7663 5d/pop-to-ebp -7664 c3/return -7665 -7666 test-compare-reg-with-mem: -7667 # compare var1/eax, var2 -7668 # => -7669 # 3b/compare *(ebp+___) 0/r32/eax -7670 # -7671 # . prologue -7672 55/push-ebp -7673 89/<- %ebp 4/r32/esp -7674 # setup -7675 (clear-stream _test-output-stream) -7676 (clear-stream $_test-output-buffered-file->buffer) -7677 # var type/ecx: (handle tree type-id) = int -7678 68/push 0/imm32/right/null -7679 68/push 1/imm32/left/int -7680 89/<- %ecx 4/r32/esp -7681 # var var-var1/ecx: var in eax -7682 68/push "eax"/imm32/register -7683 68/push 0/imm32/no-stack-offset -7684 68/push 1/imm32/block-depth -7685 51/push-ecx -7686 68/push "var1"/imm32 -7687 89/<- %ecx 4/r32/esp -7688 # var var-var2/edx: var -7689 68/push 0/imm32/no-register -7690 68/push 8/imm32/stack-offset -7691 68/push 1/imm32/block-depth -7692 ff 6/subop/push *(ecx+4) # Var-type -7693 68/push "var2"/imm32 -7694 89/<- %edx 4/r32/esp -7695 # var inouts/esi: (list var1 var2) -7696 68/push 0/imm32/next -7697 52/push-edx/var-var2 -7698 89/<- %esi 4/r32/esp -7699 56/push-esi -7700 51/push-ecx/var-var1 -7701 89/<- %esi 4/r32/esp -7702 # var stmt/esi: statement -7703 68/push 0/imm32/next -7704 68/push 0/imm32/outputs -7705 56/push-esi/inouts -7706 68/push "compare"/imm32/operation -7707 68/push 1/imm32 -7708 89/<- %esi 4/r32/esp -7709 # convert -7710 c7 0/subop/copy *Curr-block-depth 0/imm32 -7711 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7712 (flush _test-output-buffered-file) -7713 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7719 # check output -7720 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") -7721 # . epilogue -7722 89/<- %esp 5/r32/ebp -7723 5d/pop-to-ebp -7724 c3/return -7725 -7726 test-compare-mem-with-literal: -7727 # compare var1, 0x34 -7728 # => -7729 # 81 7/subop/compare *(ebp+___) 0x34/imm32 -7730 # -7731 # . prologue -7732 55/push-ebp -7733 89/<- %ebp 4/r32/esp -7734 # setup -7735 (clear-stream _test-output-stream) -7736 (clear-stream $_test-output-buffered-file->buffer) -7737 # var type/ecx: (handle tree type-id) = int -7738 68/push 0/imm32/right/null -7739 68/push 1/imm32/left/int -7740 89/<- %ecx 4/r32/esp -7741 # var var-var1/ecx: var -7742 68/push 0/imm32/no-register -7743 68/push 8/imm32/stack-offset -7744 68/push 1/imm32/block-depth -7745 51/push-ecx -7746 68/push "var1"/imm32 -7747 89/<- %ecx 4/r32/esp -7748 # var type/edx: (handle tree type-id) = literal -7749 68/push 0/imm32/right/null -7750 68/push 0/imm32/left/literal -7751 89/<- %edx 4/r32/esp -7752 # var var-var2/edx: var literal -7753 68/push 0/imm32/no-register -7754 68/push 0/imm32/no-stack-offset -7755 68/push 1/imm32/block-depth -7756 52/push-edx -7757 68/push "0x34"/imm32 -7758 89/<- %edx 4/r32/esp -7759 # var inouts/esi: (list var2) -7760 68/push 0/imm32/next -7761 52/push-edx/var-var2 -7762 89/<- %esi 4/r32/esp -7763 # var inouts = (list var1 inouts) -7764 56/push-esi/next -7765 51/push-ecx/var-var1 -7766 89/<- %esi 4/r32/esp -7767 # var stmt/esi: statement -7768 68/push 0/imm32/next -7769 68/push 0/imm32/outputs -7770 56/push-esi/inouts -7771 68/push "compare"/imm32/operation -7772 68/push 1/imm32 -7773 89/<- %esi 4/r32/esp -7774 # convert -7775 c7 0/subop/copy *Curr-block-depth 0/imm32 -7776 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7777 (flush _test-output-buffered-file) -7778 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7784 # check output -7785 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") -7786 # . epilogue -7787 89/<- %esp 5/r32/ebp -7788 5d/pop-to-ebp -7789 c3/return -7790 -7791 test-compare-eax-with-literal: -7792 # compare var1/eax 0x34 -7793 # => -7794 # 3d/compare-eax-with 0x34/imm32 -7795 # -7796 # . prologue -7797 55/push-ebp -7798 89/<- %ebp 4/r32/esp -7799 # setup -7800 (clear-stream _test-output-stream) -7801 (clear-stream $_test-output-buffered-file->buffer) -7802 # var type/ecx: (handle tree type-id) = int -7803 68/push 0/imm32/right/null -7804 68/push 1/imm32/left/int -7805 89/<- %ecx 4/r32/esp -7806 # var var-var1/ecx: var in eax -7807 68/push "eax"/imm32/register -7808 68/push 0/imm32/no-stack-offset -7809 68/push 1/imm32/block-depth -7810 51/push-ecx -7811 68/push "var1"/imm32 -7812 89/<- %ecx 4/r32/esp -7813 # var type/edx: (handle tree type-id) = literal -7814 68/push 0/imm32/right/null -7815 68/push 0/imm32/left/literal -7816 89/<- %edx 4/r32/esp -7817 # var var-var2/edx: var literal -7818 68/push 0/imm32/no-register -7819 68/push 0/imm32/no-stack-offset -7820 68/push 1/imm32/block-depth -7821 52/push-edx -7822 68/push "0x34"/imm32 -7823 89/<- %edx 4/r32/esp -7824 # var inouts/esi: (list var2) -7825 68/push 0/imm32/next -7826 52/push-edx/var-var2 -7827 89/<- %esi 4/r32/esp -7828 # var inouts = (list var1 inouts) -7829 56/push-esi/next -7830 51/push-ecx/var-var1 -7831 89/<- %esi 4/r32/esp -7832 # var stmt/esi: statement -7833 68/push 0/imm32/next -7834 68/push 0/imm32/outputs -7835 56/push-esi/inouts -7836 68/push "compare"/imm32/operation -7837 68/push 1/imm32/regular-stmt -7838 89/<- %esi 4/r32/esp -7839 # convert -7840 c7 0/subop/copy *Curr-block-depth 0/imm32 -7841 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7842 (flush _test-output-buffered-file) -7843 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7849 # check output -7850 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") -7851 # . epilogue -7852 89/<- %esp 5/r32/ebp -7853 5d/pop-to-ebp -7854 c3/return -7855 -7856 test-compare-reg-with-literal: -7857 # compare var1/ecx 0x34 -7858 # => -7859 # 81 7/subop/compare %ecx 0x34/imm32 -7860 # -7861 # . prologue -7862 55/push-ebp -7863 89/<- %ebp 4/r32/esp -7864 # setup -7865 (clear-stream _test-output-stream) -7866 (clear-stream $_test-output-buffered-file->buffer) -7867 # var type/ecx: (handle tree type-id) = int -7868 68/push 0/imm32/right/null -7869 68/push 1/imm32/left/int -7870 89/<- %ecx 4/r32/esp -7871 # var var-var1/ecx: var in ecx -7872 68/push "ecx"/imm32/register -7873 68/push 0/imm32/no-stack-offset -7874 68/push 1/imm32/block-depth -7875 51/push-ecx -7876 68/push "var1"/imm32 -7877 89/<- %ecx 4/r32/esp -7878 # var type/edx: (handle tree type-id) = literal -7879 68/push 0/imm32/right/null -7880 68/push 0/imm32/left/literal -7881 89/<- %edx 4/r32/esp -7882 # var var-var2/edx: var literal -7883 68/push 0/imm32/no-register -7884 68/push 0/imm32/no-stack-offset -7885 68/push 1/imm32/block-depth -7886 52/push-edx -7887 68/push "0x34"/imm32 -7888 89/<- %edx 4/r32/esp -7889 # var inouts/esi: (list var2) -7890 68/push 0/imm32/next -7891 52/push-edx/var-var2 -7892 89/<- %esi 4/r32/esp -7893 # var inouts = (list var1 inouts) -7894 56/push-esi/next -7895 51/push-ecx/var-var1 -7896 89/<- %esi 4/r32/esp -7897 # var stmt/esi: statement -7898 68/push 0/imm32/next -7899 68/push 0/imm32/outputs -7900 56/push-esi/inouts -7901 68/push "compare"/imm32/operation -7902 68/push 1/imm32/regular-stmt -7903 89/<- %esi 4/r32/esp -7904 # convert -7905 c7 0/subop/copy *Curr-block-depth 0/imm32 -7906 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7907 (flush _test-output-buffered-file) -7908 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7914 # check output -7915 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") -7916 # . epilogue -7917 89/<- %esp 5/r32/ebp -7918 5d/pop-to-ebp -7919 c3/return -7920 -7921 test-emit-subx-statement-function-call: -7922 # Call a function on a variable on the stack. -7923 # f foo -7924 # => -7925 # (f2 *(ebp-8)) -7926 # (Changing the function name supports overloading in general, but here it -7927 # just serves to help disambiguate things.) -7928 # -7929 # There's a variable on the var stack as follows: -7930 # name: 'foo' -7931 # type: int -7932 # stack-offset: -8 -7933 # -7934 # There's nothing in primitives. -7935 # -7936 # There's a function with this info: -7937 # name: 'f' -7938 # inout: int/mem -7939 # value: 'f2' -7940 # -7941 # . prologue -7942 55/push-ebp -7943 89/<- %ebp 4/r32/esp -7944 # setup -7945 (clear-stream _test-output-stream) -7946 (clear-stream $_test-output-buffered-file->buffer) -7947 # var type/ecx: (handle tree type-id) = int -7948 68/push 0/imm32/right/null -7949 68/push 1/imm32/left/int -7950 89/<- %ecx 4/r32/esp -7951 # var var-foo/ecx: var -7952 68/push 0/imm32/no-register -7953 68/push -8/imm32/stack-offset -7954 68/push 0/imm32/block-depth -7955 51/push-ecx -7956 68/push "foo"/imm32 -7957 89/<- %ecx 4/r32/esp -7958 # var operands/esi: (list var) -7959 68/push 0/imm32/next -7960 51/push-ecx/var-foo -7961 89/<- %esi 4/r32/esp -7962 # var stmt/esi: statement -7963 68/push 0/imm32/next -7964 68/push 0/imm32/outputs -7965 56/push-esi/inouts -7966 68/push "f"/imm32/operation -7967 68/push 1/imm32 -7968 89/<- %esi 4/r32/esp -7969 # var functions/ebx: function -7970 68/push 0/imm32/next -7971 68/push 0/imm32/body -7972 68/push 0/imm32/outputs -7973 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -7974 68/push "f2"/imm32/subx-name -7975 68/push "f"/imm32/name -7976 89/<- %ebx 4/r32/esp -7977 # convert -7978 c7 0/subop/copy *Curr-block-depth 0/imm32 -7979 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) -7980 (flush _test-output-buffered-file) -7981 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7987 # check output -7988 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-statement-function-call") -7989 # . epilogue -7990 89/<- %esp 5/r32/ebp -7991 5d/pop-to-ebp -7992 c3/return -7993 -7994 test-emit-subx-statement-function-call-with-literal-arg: -7995 # Call a function on a literal. -7996 # f 34 -7997 # => -7998 # (f2 34) -7999 # -8000 # . prologue -8001 55/push-ebp -8002 89/<- %ebp 4/r32/esp -8003 # setup -8004 (clear-stream _test-output-stream) -8005 (clear-stream $_test-output-buffered-file->buffer) -8006 # var type/ecx: (handle tree type-id) = literal -8007 68/push 0/imm32/right/null -8008 68/push 0/imm32/left/literal -8009 89/<- %ecx 4/r32/esp -8010 # var var-foo/ecx: var literal -8011 68/push 0/imm32/no-register -8012 68/push 0/imm32/no-stack-offset -8013 68/push 0/imm32/block-depth -8014 51/push-ecx -8015 68/push "34"/imm32 -8016 89/<- %ecx 4/r32/esp -8017 # var operands/esi: (list var) -8018 68/push 0/imm32/next -8019 51/push-ecx/var-foo -8020 89/<- %esi 4/r32/esp -8021 # var stmt/esi: statement -8022 68/push 0/imm32/next -8023 68/push 0/imm32/outputs -8024 56/push-esi/inouts -8025 68/push "f"/imm32/operation -8026 68/push 1/imm32 -8027 89/<- %esi 4/r32/esp -8028 # var functions/ebx: function -8029 68/push 0/imm32/next -8030 68/push 0/imm32/body -8031 68/push 0/imm32/outputs -8032 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -8033 68/push "f2"/imm32/subx-name -8034 68/push "f"/imm32/name -8035 89/<- %ebx 4/r32/esp -8036 # convert -8037 c7 0/subop/copy *Curr-block-depth 0/imm32 -8038 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) -8039 (flush _test-output-buffered-file) -8040 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -8046 # check output -8047 (check-next-stream-line-equal _test-output-stream "(f2 34)" "F - test-emit-subx-statement-function-call-with-literal-arg") -8048 # . epilogue -8049 89/<- %esp 5/r32/ebp -8050 5d/pop-to-ebp -8051 c3/return -8052 -8053 emit-indent: # out: (addr buffered-file), n: int -8054 # . prologue -8055 55/push-ebp -8056 89/<- %ebp 4/r32/esp -8057 # . save registers -8058 50/push-eax -8059 # var i/eax: int = n -8060 8b/-> *(ebp+0xc) 0/r32/eax -8061 { -8062 # if (i <= 0) break -8063 3d/compare-eax-with 0/imm32 -8064 7e/jump-if-<= break/disp8 -8065 (write-buffered *(ebp+8) " ") -8066 48/decrement-eax -8067 eb/jump loop/disp8 -8068 } -8069 $emit-indent:end: -8070 # . restore registers -8071 58/pop-to-eax -8072 # . epilogue -8073 89/<- %esp 5/r32/ebp -8074 5d/pop-to-ebp -8075 c3/return -8076 -8077 emit-subx-prologue: # out: (addr buffered-file) -8078 # . prologue -8079 55/push-ebp -8080 89/<- %ebp 4/r32/esp -8081 # -8082 (write-buffered *(ebp+8) " # . prologue\n") -8083 (write-buffered *(ebp+8) " 55/push-ebp\n") -8084 (write-buffered *(ebp+8) " 89/<- %ebp 4/r32/esp\n") -8085 $emit-subx-prologue:end: -8086 # . epilogue -8087 89/<- %esp 5/r32/ebp -8088 5d/pop-to-ebp -8089 c3/return -8090 -8091 emit-subx-epilogue: # out: (addr buffered-file) -8092 # . prologue -8093 55/push-ebp -8094 89/<- %ebp 4/r32/esp -8095 # -8096 (write-buffered *(ebp+8) " # . epilogue\n") -8097 (write-buffered *(ebp+8) " 89/<- %esp 5/r32/ebp\n") -8098 (write-buffered *(ebp+8) " 5d/pop-to-ebp\n") -8099 (write-buffered *(ebp+8) " c3/return\n") -8100 $emit-subx-epilogue:end: -8101 # . epilogue -8102 89/<- %esp 5/r32/ebp -8103 5d/pop-to-ebp -8104 c3/return +6866 # convert +6867 c7 0/subop/copy *Curr-block-depth 0/imm32 +6868 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +6869 (flush _test-output-buffered-file) +6870 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +6876 # check output +6877 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") +6878 # . epilogue +6879 89/<- %esp 5/r32/ebp +6880 5d/pop-to-ebp +6881 c3/return +6882 +6883 test-increment-var: +6884 # Select the right primitive between overloads. +6885 # foo <- increment +6886 # => +6887 # ff 0/subop/increment %eax # sub-optimal, but should suffice +6888 # +6889 # There's a variable on the var stack as follows: +6890 # name: 'foo' +6891 # type: int +6892 # register: 'eax' +6893 # +6894 # Primitives are the global definitions. +6895 # +6896 # There are no functions defined. +6897 # +6898 # . prologue +6899 55/push-ebp +6900 89/<- %ebp 4/r32/esp +6901 # setup +6902 (clear-stream _test-output-stream) +6903 (clear-stream $_test-output-buffered-file->buffer) +6904 # var type/ecx: (handle tree type-id) = int +6905 68/push 0/imm32/right/null +6906 68/push 1/imm32/left/int +6907 89/<- %ecx 4/r32/esp +6908 # var var-foo/ecx: var in eax +6909 68/push "eax"/imm32/register +6910 68/push 0/imm32/no-stack-offset +6911 68/push 1/imm32/block-depth +6912 51/push-ecx +6913 68/push "foo"/imm32 +6914 89/<- %ecx 4/r32/esp +6915 # var inouts/edi: (list var) +6916 68/push 0/imm32/next +6917 51/push-ecx/var-foo +6918 89/<- %edi 4/r32/esp +6919 # var stmt/esi: statement +6920 68/push 0/imm32/next +6921 68/push 0/imm32/outputs +6922 57/push-edi/inouts +6923 68/push "increment"/imm32/operation +6924 68/push 1/imm32 +6925 89/<- %esi 4/r32/esp +6926 # convert +6927 c7 0/subop/copy *Curr-block-depth 0/imm32 +6928 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +6929 (flush _test-output-buffered-file) +6930 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +6936 # check output +6937 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-increment-var") +6938 # . epilogue +6939 89/<- %esp 5/r32/ebp +6940 5d/pop-to-ebp +6941 c3/return +6942 +6943 test-add-reg-to-reg: +6944 # var1/reg <- add var2/reg +6945 # => +6946 # 01/add %var1 var2 +6947 # +6948 # . prologue +6949 55/push-ebp +6950 89/<- %ebp 4/r32/esp +6951 # setup +6952 (clear-stream _test-output-stream) +6953 (clear-stream $_test-output-buffered-file->buffer) +6954 # var type/ecx: (handle tree type-id) = int +6955 68/push 0/imm32/right/null +6956 68/push 1/imm32/left/int +6957 89/<- %ecx 4/r32/esp +6958 # var var-var1/ecx: var in eax +6959 68/push "eax"/imm32/register +6960 68/push 0/imm32/no-stack-offset +6961 68/push 1/imm32/block-depth +6962 51/push-ecx +6963 68/push "var1"/imm32 +6964 89/<- %ecx 4/r32/esp +6965 # var var-var2/edx: var in ecx +6966 68/push "ecx"/imm32/register +6967 68/push 0/imm32/no-stack-offset +6968 68/push 1/imm32/block-depth +6969 ff 6/subop/push *(ecx+4) # Var-type +6970 68/push "var2"/imm32 +6971 89/<- %edx 4/r32/esp +6972 # var inouts/esi: (list var2) +6973 68/push 0/imm32/next +6974 52/push-edx/var-var2 +6975 89/<- %esi 4/r32/esp +6976 # var outputs/edi: (list var1) +6977 68/push 0/imm32/next +6978 51/push-ecx/var-var1 +6979 89/<- %edi 4/r32/esp +6980 # var stmt/esi: statement +6981 68/push 0/imm32/next +6982 57/push-edi/outputs +6983 56/push-esi/inouts +6984 68/push "add"/imm32/operation +6985 68/push 1/imm32 +6986 89/<- %esi 4/r32/esp +6987 # convert +6988 c7 0/subop/copy *Curr-block-depth 0/imm32 +6989 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +6990 (flush _test-output-buffered-file) +6991 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +6997 # check output +6998 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") +6999 # . epilogue +7000 89/<- %esp 5/r32/ebp +7001 5d/pop-to-ebp +7002 c3/return +7003 +7004 test-add-reg-to-mem: +7005 # add-to var1 var2/reg +7006 # => +7007 # 01/add *(ebp+__) var2 +7008 # +7009 # . prologue +7010 55/push-ebp +7011 89/<- %ebp 4/r32/esp +7012 # setup +7013 (clear-stream _test-output-stream) +7014 (clear-stream $_test-output-buffered-file->buffer) +7015 # var type/ecx: (handle tree type-id) = int +7016 68/push 0/imm32/right/null +7017 68/push 1/imm32/left/int +7018 89/<- %ecx 4/r32/esp +7019 # var var-var1/ecx: var +7020 68/push 0/imm32/no-register +7021 68/push 8/imm32/stack-offset +7022 68/push 1/imm32/block-depth +7023 51/push-ecx +7024 68/push "var1"/imm32 +7025 89/<- %ecx 4/r32/esp +7026 # var var-var2/edx: var in ecx +7027 68/push "ecx"/imm32/register +7028 68/push 0/imm32/no-stack-offset +7029 68/push 1/imm32/block-depth +7030 ff 6/subop/push *(ecx+4) # Var-type +7031 68/push "var2"/imm32 +7032 89/<- %edx 4/r32/esp +7033 # var inouts/esi: (list var2) +7034 68/push 0/imm32/next +7035 52/push-edx/var-var2 +7036 89/<- %esi 4/r32/esp +7037 # var inouts = (list var1 var2) +7038 56/push-esi/next +7039 51/push-ecx/var-var1 +7040 89/<- %esi 4/r32/esp +7041 # var stmt/esi: statement +7042 68/push 0/imm32/next +7043 68/push 0/imm32/outputs +7044 56/push-esi/inouts +7045 68/push "add-to"/imm32/operation +7046 68/push 1/imm32 +7047 89/<- %esi 4/r32/esp +7048 # convert +7049 c7 0/subop/copy *Curr-block-depth 0/imm32 +7050 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +7051 (flush _test-output-buffered-file) +7052 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +7058 # check output +7059 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") +7060 # . epilogue +7061 89/<- %esp 5/r32/ebp +7062 5d/pop-to-ebp +7063 c3/return +7064 +7065 test-add-mem-to-reg: +7066 # var1/reg <- add var2 +7067 # => +7068 # 03/add *(ebp+__) var1 +7069 # +7070 # . prologue +7071 55/push-ebp +7072 89/<- %ebp 4/r32/esp +7073 # setup +7074 (clear-stream _test-output-stream) +7075 (clear-stream $_test-output-buffered-file->buffer) +7076 # var type/ecx: (handle tree type-id) = int +7077 68/push 0/imm32/right/null +7078 68/push 1/imm32/left/int +7079 89/<- %ecx 4/r32/esp +7080 # var var-var1/ecx: var in eax +7081 68/push "eax"/imm32/register +7082 68/push 0/imm32/no-stack-offset +7083 68/push 1/imm32/block-depth +7084 51/push-ecx +7085 68/push "var1"/imm32 +7086 89/<- %ecx 4/r32/esp +7087 # var var-var2/edx: var +7088 68/push 0/imm32/no-register +7089 68/push 8/imm32/stack-offset +7090 68/push 1/imm32/block-depth +7091 ff 6/subop/push *(ecx+4) # Var-type +7092 68/push "var2"/imm32 +7093 89/<- %edx 4/r32/esp +7094 # var inouts/esi: (list var2) +7095 68/push 0/imm32/next +7096 52/push-edx/var-var2 +7097 89/<- %esi 4/r32/esp +7098 # var outputs/edi: (list var1) +7099 68/push 0/imm32/next +7100 51/push-ecx/var-var1 +7101 89/<- %edi 4/r32/esp +7102 # var stmt/esi: statement +7103 68/push 0/imm32/next +7104 57/push-edi/outputs +7105 56/push-esi/inouts +7106 68/push "add"/imm32/operation +7107 68/push 1/imm32 +7108 89/<- %esi 4/r32/esp +7109 # convert +7110 c7 0/subop/copy *Curr-block-depth 0/imm32 +7111 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +7112 (flush _test-output-buffered-file) +7113 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +7119 # check output +7120 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") +7121 # . epilogue +7122 89/<- %esp 5/r32/ebp +7123 5d/pop-to-ebp +7124 c3/return +7125 +7126 test-add-literal-to-eax: +7127 # var1/eax <- add 0x34 +7128 # => +7129 # 05/add-to-eax 0x34/imm32 +7130 # +7131 # . prologue +7132 55/push-ebp +7133 89/<- %ebp 4/r32/esp +7134 # setup +7135 (clear-stream _test-output-stream) +7136 (clear-stream $_test-output-buffered-file->buffer) +7137 # var type/ecx: (handle tree type-id) = int +7138 68/push 0/imm32/right/null +7139 68/push 1/imm32/left/int +7140 89/<- %ecx 4/r32/esp +7141 # var var-var1/ecx: var in eax +7142 68/push "eax"/imm32/register +7143 68/push 0/imm32/no-stack-offset +7144 68/push 1/imm32/block-depth +7145 51/push-ecx +7146 68/push "var1"/imm32 +7147 89/<- %ecx 4/r32/esp +7148 # var type/edx: (handle tree type-id) = literal +7149 68/push 0/imm32/right/null +7150 68/push 0/imm32/left/literal +7151 89/<- %edx 4/r32/esp +7152 # var var-var2/edx: var literal +7153 68/push 0/imm32/no-register +7154 68/push 0/imm32/no-stack-offset +7155 68/push 1/imm32/block-depth +7156 52/push-edx +7157 68/push "0x34"/imm32 +7158 89/<- %edx 4/r32/esp +7159 # var inouts/esi: (list var2) +7160 68/push 0/imm32/next +7161 52/push-edx/var-var2 +7162 89/<- %esi 4/r32/esp +7163 # var outputs/edi: (list var1) +7164 68/push 0/imm32/next +7165 51/push-ecx/var-var1 +7166 89/<- %edi 4/r32/esp +7167 # var stmt/esi: statement +7168 68/push 0/imm32/next +7169 57/push-edi/outputs +7170 56/push-esi/inouts +7171 68/push "add"/imm32/operation +7172 68/push 1/imm32 +7173 89/<- %esi 4/r32/esp +7174 # convert +7175 c7 0/subop/copy *Curr-block-depth 0/imm32 +7176 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +7177 (flush _test-output-buffered-file) +7178 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +7184 # check output +7185 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") +7186 # . epilogue +7187 89/<- %esp 5/r32/ebp +7188 5d/pop-to-ebp +7189 c3/return +7190 +7191 test-add-literal-to-reg: +7192 # var1/ecx <- add 0x34 +7193 # => +7194 # 81 0/subop/add %ecx 0x34/imm32 +7195 # +7196 # . prologue +7197 55/push-ebp +7198 89/<- %ebp 4/r32/esp +7199 # setup +7200 (clear-stream _test-output-stream) +7201 (clear-stream $_test-output-buffered-file->buffer) +7202 # var type/ecx: (handle tree type-id) = int +7203 68/push 0/imm32/right/null +7204 68/push 1/imm32/left/int +7205 89/<- %ecx 4/r32/esp +7206 # var var-var1/ecx: var in ecx +7207 68/push "ecx"/imm32/register +7208 68/push 0/imm32/no-stack-offset +7209 68/push 1/imm32/block-depth +7210 51/push-ecx +7211 68/push "var1"/imm32 +7212 89/<- %ecx 4/r32/esp +7213 # var type/edx: (handle tree type-id) = literal +7214 68/push 0/imm32/right/null +7215 68/push 0/imm32/left/literal +7216 89/<- %edx 4/r32/esp +7217 # var var-var2/edx: var literal +7218 68/push 0/imm32/no-register +7219 68/push 0/imm32/no-stack-offset +7220 68/push 1/imm32/block-depth +7221 52/push-edx +7222 68/push "0x34"/imm32 +7223 89/<- %edx 4/r32/esp +7224 # var inouts/esi: (list var2) +7225 68/push 0/imm32/next +7226 52/push-edx/var-var2 +7227 89/<- %esi 4/r32/esp +7228 # var outputs/edi: (list var1) +7229 68/push 0/imm32/next +7230 51/push-ecx/var-var1 +7231 89/<- %edi 4/r32/esp +7232 # var stmt/esi: statement +7233 68/push 0/imm32/next +7234 57/push-edi/outputs +7235 56/push-esi/inouts +7236 68/push "add"/imm32/operation +7237 68/push 1/imm32 +7238 89/<- %esi 4/r32/esp +7239 # convert +7240 c7 0/subop/copy *Curr-block-depth 0/imm32 +7241 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +7242 (flush _test-output-buffered-file) +7243 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +7249 # check output +7250 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") +7251 # . epilogue +7252 89/<- %esp 5/r32/ebp +7253 5d/pop-to-ebp +7254 c3/return +7255 +7256 test-add-literal-to-mem: +7257 # add-to var1, 0x34 +7258 # => +7259 # 81 0/subop/add %eax 0x34/imm32 +7260 # +7261 # . prologue +7262 55/push-ebp +7263 89/<- %ebp 4/r32/esp +7264 # setup +7265 (clear-stream _test-output-stream) +7266 (clear-stream $_test-output-buffered-file->buffer) +7267 # var type/ecx: (handle tree type-id) = int +7268 68/push 0/imm32/right/null +7269 68/push 1/imm32/left/int +7270 89/<- %ecx 4/r32/esp +7271 # var var-var1/ecx: var +7272 68/push 0/imm32/no-register +7273 68/push 8/imm32/stack-offset +7274 68/push 1/imm32/block-depth +7275 51/push-ecx +7276 68/push "var1"/imm32 +7277 89/<- %ecx 4/r32/esp +7278 # var type/edx: (handle tree type-id) = literal +7279 68/push 0/imm32/right/null +7280 68/push 0/imm32/left/literal +7281 89/<- %edx 4/r32/esp +7282 # var var-var2/edx: var literal +7283 68/push 0/imm32/no-register +7284 68/push 0/imm32/no-stack-offset +7285 68/push 1/imm32/block-depth +7286 52/push-edx +7287 68/push "0x34"/imm32 +7288 89/<- %edx 4/r32/esp +7289 # var inouts/esi: (list var2) +7290 68/push 0/imm32/next +7291 52/push-edx/var-var2 +7292 89/<- %esi 4/r32/esp +7293 # var inouts = (list var1 inouts) +7294 56/push-esi/next +7295 51/push-ecx/var-var1 +7296 89/<- %esi 4/r32/esp +7297 # var stmt/esi: statement +7298 68/push 0/imm32/next +7299 68/push 0/imm32/outputs +7300 56/push-esi/inouts +7301 68/push "add-to"/imm32/operation +7302 68/push 1/imm32 +7303 89/<- %esi 4/r32/esp +7304 # convert +7305 c7 0/subop/copy *Curr-block-depth 0/imm32 +7306 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +7307 (flush _test-output-buffered-file) +7308 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +7314 # check output +7315 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") +7316 # . epilogue +7317 89/<- %esp 5/r32/ebp +7318 5d/pop-to-ebp +7319 c3/return +7320 +7321 test-compare-mem-with-reg: +7322 # compare var1, var2/eax +7323 # => +7324 # 39/compare *(ebp+___) 0/r32/eax +7325 # +7326 # . prologue +7327 55/push-ebp +7328 89/<- %ebp 4/r32/esp +7329 # setup +7330 (clear-stream _test-output-stream) +7331 (clear-stream $_test-output-buffered-file->buffer) +7332 # var type/ecx: (handle tree type-id) = int +7333 68/push 0/imm32/right/null +7334 68/push 1/imm32/left/int +7335 89/<- %ecx 4/r32/esp +7336 # var var-var2/ecx: var in eax +7337 68/push "eax"/imm32/register +7338 68/push 0/imm32/no-stack-offset +7339 68/push 1/imm32/block-depth +7340 51/push-ecx +7341 68/push "var2"/imm32 +7342 89/<- %ecx 4/r32/esp +7343 # var var-var1/edx: var +7344 68/push 0/imm32/no-register +7345 68/push 8/imm32/stack-offset +7346 68/push 1/imm32/block-depth +7347 ff 6/subop/push *(ecx+4) # Var-type +7348 68/push "var1"/imm32 +7349 89/<- %edx 4/r32/esp +7350 # var inouts/esi: (list var1 var2) +7351 68/push 0/imm32/next +7352 51/push-ecx/var-var2 +7353 89/<- %esi 4/r32/esp +7354 56/push-esi +7355 52/push-edx/var-var1 +7356 89/<- %esi 4/r32/esp +7357 # var stmt/esi: statement +7358 68/push 0/imm32/next +7359 68/push 0/imm32/outputs +7360 56/push-esi/inouts +7361 68/push "compare"/imm32/operation +7362 68/push 1/imm32 +7363 89/<- %esi 4/r32/esp +7364 # convert +7365 c7 0/subop/copy *Curr-block-depth 0/imm32 +7366 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +7367 (flush _test-output-buffered-file) +7368 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +7374 # check output +7375 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") +7376 # . epilogue +7377 89/<- %esp 5/r32/ebp +7378 5d/pop-to-ebp +7379 c3/return +7380 +7381 test-compare-reg-with-mem: +7382 # compare var1/eax, var2 +7383 # => +7384 # 3b/compare *(ebp+___) 0/r32/eax +7385 # +7386 # . prologue +7387 55/push-ebp +7388 89/<- %ebp 4/r32/esp +7389 # setup +7390 (clear-stream _test-output-stream) +7391 (clear-stream $_test-output-buffered-file->buffer) +7392 # var type/ecx: (handle tree type-id) = int +7393 68/push 0/imm32/right/null +7394 68/push 1/imm32/left/int +7395 89/<- %ecx 4/r32/esp +7396 # var var-var1/ecx: var in eax +7397 68/push "eax"/imm32/register +7398 68/push 0/imm32/no-stack-offset +7399 68/push 1/imm32/block-depth +7400 51/push-ecx +7401 68/push "var1"/imm32 +7402 89/<- %ecx 4/r32/esp +7403 # var var-var2/edx: var +7404 68/push 0/imm32/no-register +7405 68/push 8/imm32/stack-offset +7406 68/push 1/imm32/block-depth +7407 ff 6/subop/push *(ecx+4) # Var-type +7408 68/push "var2"/imm32 +7409 89/<- %edx 4/r32/esp +7410 # var inouts/esi: (list var1 var2) +7411 68/push 0/imm32/next +7412 52/push-edx/var-var2 +7413 89/<- %esi 4/r32/esp +7414 56/push-esi +7415 51/push-ecx/var-var1 +7416 89/<- %esi 4/r32/esp +7417 # var stmt/esi: statement +7418 68/push 0/imm32/next +7419 68/push 0/imm32/outputs +7420 56/push-esi/inouts +7421 68/push "compare"/imm32/operation +7422 68/push 1/imm32 +7423 89/<- %esi 4/r32/esp +7424 # convert +7425 c7 0/subop/copy *Curr-block-depth 0/imm32 +7426 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +7427 (flush _test-output-buffered-file) +7428 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +7434 # check output +7435 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") +7436 # . epilogue +7437 89/<- %esp 5/r32/ebp +7438 5d/pop-to-ebp +7439 c3/return +7440 +7441 test-compare-mem-with-literal: +7442 # compare var1, 0x34 +7443 # => +7444 # 81 7/subop/compare *(ebp+___) 0x34/imm32 +7445 # +7446 # . prologue +7447 55/push-ebp +7448 89/<- %ebp 4/r32/esp +7449 # setup +7450 (clear-stream _test-output-stream) +7451 (clear-stream $_test-output-buffered-file->buffer) +7452 # var type/ecx: (handle tree type-id) = int +7453 68/push 0/imm32/right/null +7454 68/push 1/imm32/left/int +7455 89/<- %ecx 4/r32/esp +7456 # var var-var1/ecx: var +7457 68/push 0/imm32/no-register +7458 68/push 8/imm32/stack-offset +7459 68/push 1/imm32/block-depth +7460 51/push-ecx +7461 68/push "var1"/imm32 +7462 89/<- %ecx 4/r32/esp +7463 # var type/edx: (handle tree type-id) = literal +7464 68/push 0/imm32/right/null +7465 68/push 0/imm32/left/literal +7466 89/<- %edx 4/r32/esp +7467 # var var-var2/edx: var literal +7468 68/push 0/imm32/no-register +7469 68/push 0/imm32/no-stack-offset +7470 68/push 1/imm32/block-depth +7471 52/push-edx +7472 68/push "0x34"/imm32 +7473 89/<- %edx 4/r32/esp +7474 # var inouts/esi: (list var2) +7475 68/push 0/imm32/next +7476 52/push-edx/var-var2 +7477 89/<- %esi 4/r32/esp +7478 # var inouts = (list var1 inouts) +7479 56/push-esi/next +7480 51/push-ecx/var-var1 +7481 89/<- %esi 4/r32/esp +7482 # var stmt/esi: statement +7483 68/push 0/imm32/next +7484 68/push 0/imm32/outputs +7485 56/push-esi/inouts +7486 68/push "compare"/imm32/operation +7487 68/push 1/imm32 +7488 89/<- %esi 4/r32/esp +7489 # convert +7490 c7 0/subop/copy *Curr-block-depth 0/imm32 +7491 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +7492 (flush _test-output-buffered-file) +7493 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +7499 # check output +7500 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") +7501 # . epilogue +7502 89/<- %esp 5/r32/ebp +7503 5d/pop-to-ebp +7504 c3/return +7505 +7506 test-compare-eax-with-literal: +7507 # compare var1/eax 0x34 +7508 # => +7509 # 3d/compare-eax-with 0x34/imm32 +7510 # +7511 # . prologue +7512 55/push-ebp +7513 89/<- %ebp 4/r32/esp +7514 # setup +7515 (clear-stream _test-output-stream) +7516 (clear-stream $_test-output-buffered-file->buffer) +7517 # var type/ecx: (handle tree type-id) = int +7518 68/push 0/imm32/right/null +7519 68/push 1/imm32/left/int +7520 89/<- %ecx 4/r32/esp +7521 # var var-var1/ecx: var in eax +7522 68/push "eax"/imm32/register +7523 68/push 0/imm32/no-stack-offset +7524 68/push 1/imm32/block-depth +7525 51/push-ecx +7526 68/push "var1"/imm32 +7527 89/<- %ecx 4/r32/esp +7528 # var type/edx: (handle tree type-id) = literal +7529 68/push 0/imm32/right/null +7530 68/push 0/imm32/left/literal +7531 89/<- %edx 4/r32/esp +7532 # var var-var2/edx: var literal +7533 68/push 0/imm32/no-register +7534 68/push 0/imm32/no-stack-offset +7535 68/push 1/imm32/block-depth +7536 52/push-edx +7537 68/push "0x34"/imm32 +7538 89/<- %edx 4/r32/esp +7539 # var inouts/esi: (list var2) +7540 68/push 0/imm32/next +7541 52/push-edx/var-var2 +7542 89/<- %esi 4/r32/esp +7543 # var inouts = (list var1 inouts) +7544 56/push-esi/next +7545 51/push-ecx/var-var1 +7546 89/<- %esi 4/r32/esp +7547 # var stmt/esi: statement +7548 68/push 0/imm32/next +7549 68/push 0/imm32/outputs +7550 56/push-esi/inouts +7551 68/push "compare"/imm32/operation +7552 68/push 1/imm32/regular-stmt +7553 89/<- %esi 4/r32/esp +7554 # convert +7555 c7 0/subop/copy *Curr-block-depth 0/imm32 +7556 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +7557 (flush _test-output-buffered-file) +7558 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +7564 # check output +7565 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") +7566 # . epilogue +7567 89/<- %esp 5/r32/ebp +7568 5d/pop-to-ebp +7569 c3/return +7570 +7571 test-compare-reg-with-literal: +7572 # compare var1/ecx 0x34 +7573 # => +7574 # 81 7/subop/compare %ecx 0x34/imm32 +7575 # +7576 # . prologue +7577 55/push-ebp +7578 89/<- %ebp 4/r32/esp +7579 # setup +7580 (clear-stream _test-output-stream) +7581 (clear-stream $_test-output-buffered-file->buffer) +7582 # var type/ecx: (handle tree type-id) = int +7583 68/push 0/imm32/right/null +7584 68/push 1/imm32/left/int +7585 89/<- %ecx 4/r32/esp +7586 # var var-var1/ecx: var in ecx +7587 68/push "ecx"/imm32/register +7588 68/push 0/imm32/no-stack-offset +7589 68/push 1/imm32/block-depth +7590 51/push-ecx +7591 68/push "var1"/imm32 +7592 89/<- %ecx 4/r32/esp +7593 # var type/edx: (handle tree type-id) = literal +7594 68/push 0/imm32/right/null +7595 68/push 0/imm32/left/literal +7596 89/<- %edx 4/r32/esp +7597 # var var-var2/edx: var literal +7598 68/push 0/imm32/no-register +7599 68/push 0/imm32/no-stack-offset +7600 68/push 1/imm32/block-depth +7601 52/push-edx +7602 68/push "0x34"/imm32 +7603 89/<- %edx 4/r32/esp +7604 # var inouts/esi: (list var2) +7605 68/push 0/imm32/next +7606 52/push-edx/var-var2 +7607 89/<- %esi 4/r32/esp +7608 # var inouts = (list var1 inouts) +7609 56/push-esi/next +7610 51/push-ecx/var-var1 +7611 89/<- %esi 4/r32/esp +7612 # var stmt/esi: statement +7613 68/push 0/imm32/next +7614 68/push 0/imm32/outputs +7615 56/push-esi/inouts +7616 68/push "compare"/imm32/operation +7617 68/push 1/imm32/regular-stmt +7618 89/<- %esi 4/r32/esp +7619 # convert +7620 c7 0/subop/copy *Curr-block-depth 0/imm32 +7621 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +7622 (flush _test-output-buffered-file) +7623 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +7629 # check output +7630 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") +7631 # . epilogue +7632 89/<- %esp 5/r32/ebp +7633 5d/pop-to-ebp +7634 c3/return +7635 +7636 test-emit-subx-statement-function-call: +7637 # Call a function on a variable on the stack. +7638 # f foo +7639 # => +7640 # (f2 *(ebp-8)) +7641 # (Changing the function name supports overloading in general, but here it +7642 # just serves to help disambiguate things.) +7643 # +7644 # There's a variable on the var stack as follows: +7645 # name: 'foo' +7646 # type: int +7647 # stack-offset: -8 +7648 # +7649 # There's nothing in primitives. +7650 # +7651 # There's a function with this info: +7652 # name: 'f' +7653 # inout: int/mem +7654 # value: 'f2' +7655 # +7656 # . prologue +7657 55/push-ebp +7658 89/<- %ebp 4/r32/esp +7659 # setup +7660 (clear-stream _test-output-stream) +7661 (clear-stream $_test-output-buffered-file->buffer) +7662 # var type/ecx: (handle tree type-id) = int +7663 68/push 0/imm32/right/null +7664 68/push 1/imm32/left/int +7665 89/<- %ecx 4/r32/esp +7666 # var var-foo/ecx: var +7667 68/push 0/imm32/no-register +7668 68/push -8/imm32/stack-offset +7669 68/push 0/imm32/block-depth +7670 51/push-ecx +7671 68/push "foo"/imm32 +7672 89/<- %ecx 4/r32/esp +7673 # var operands/esi: (list var) +7674 68/push 0/imm32/next +7675 51/push-ecx/var-foo +7676 89/<- %esi 4/r32/esp +7677 # var stmt/esi: statement +7678 68/push 0/imm32/next +7679 68/push 0/imm32/outputs +7680 56/push-esi/inouts +7681 68/push "f"/imm32/operation +7682 68/push 1/imm32 +7683 89/<- %esi 4/r32/esp +7684 # var functions/ebx: function +7685 68/push 0/imm32/next +7686 68/push 0/imm32/body +7687 68/push 0/imm32/outputs +7688 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call +7689 68/push "f2"/imm32/subx-name +7690 68/push "f"/imm32/name +7691 89/<- %ebx 4/r32/esp +7692 # convert +7693 c7 0/subop/copy *Curr-block-depth 0/imm32 +7694 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) +7695 (flush _test-output-buffered-file) +7696 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +7702 # check output +7703 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-statement-function-call") +7704 # . epilogue +7705 89/<- %esp 5/r32/ebp +7706 5d/pop-to-ebp +7707 c3/return +7708 +7709 test-emit-subx-statement-function-call-with-literal-arg: +7710 # Call a function on a literal. +7711 # f 34 +7712 # => +7713 # (f2 34) +7714 # +7715 # . prologue +7716 55/push-ebp +7717 89/<- %ebp 4/r32/esp +7718 # setup +7719 (clear-stream _test-output-stream) +7720 (clear-stream $_test-output-buffered-file->buffer) +7721 # var type/ecx: (handle tree type-id) = literal +7722 68/push 0/imm32/right/null +7723 68/push 0/imm32/left/literal +7724 89/<- %ecx 4/r32/esp +7725 # var var-foo/ecx: var literal +7726 68/push 0/imm32/no-register +7727 68/push 0/imm32/no-stack-offset +7728 68/push 0/imm32/block-depth +7729 51/push-ecx +7730 68/push "34"/imm32 +7731 89/<- %ecx 4/r32/esp +7732 # var operands/esi: (list var) +7733 68/push 0/imm32/next +7734 51/push-ecx/var-foo +7735 89/<- %esi 4/r32/esp +7736 # var stmt/esi: statement +7737 68/push 0/imm32/next +7738 68/push 0/imm32/outputs +7739 56/push-esi/inouts +7740 68/push "f"/imm32/operation +7741 68/push 1/imm32 +7742 89/<- %esi 4/r32/esp +7743 # var functions/ebx: function +7744 68/push 0/imm32/next +7745 68/push 0/imm32/body +7746 68/push 0/imm32/outputs +7747 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call +7748 68/push "f2"/imm32/subx-name +7749 68/push "f"/imm32/name +7750 89/<- %ebx 4/r32/esp +7751 # convert +7752 c7 0/subop/copy *Curr-block-depth 0/imm32 +7753 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) +7754 (flush _test-output-buffered-file) +7755 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +7761 # check output +7762 (check-next-stream-line-equal _test-output-stream "(f2 34)" "F - test-emit-subx-statement-function-call-with-literal-arg") +7763 # . epilogue +7764 89/<- %esp 5/r32/ebp +7765 5d/pop-to-ebp +7766 c3/return +7767 +7768 emit-indent: # out: (addr buffered-file), n: int +7769 # . prologue +7770 55/push-ebp +7771 89/<- %ebp 4/r32/esp +7772 # . save registers +7773 50/push-eax +7774 # var i/eax: int = n +7775 8b/-> *(ebp+0xc) 0/r32/eax +7776 { +7777 # if (i <= 0) break +7778 3d/compare-eax-with 0/imm32 +7779 7e/jump-if-<= break/disp8 +7780 (write-buffered *(ebp+8) " ") +7781 48/decrement-eax +7782 eb/jump loop/disp8 +7783 } +7784 $emit-indent:end: +7785 # . restore registers +7786 58/pop-to-eax +7787 # . epilogue +7788 89/<- %esp 5/r32/ebp +7789 5d/pop-to-ebp +7790 c3/return +7791 +7792 emit-subx-prologue: # out: (addr buffered-file) +7793 # . prologue +7794 55/push-ebp +7795 89/<- %ebp 4/r32/esp +7796 # +7797 (write-buffered *(ebp+8) " # . prologue\n") +7798 (write-buffered *(ebp+8) " 55/push-ebp\n") +7799 (write-buffered *(ebp+8) " 89/<- %ebp 4/r32/esp\n") +7800 $emit-subx-prologue:end: +7801 # . epilogue +7802 89/<- %esp 5/r32/ebp +7803 5d/pop-to-ebp +7804 c3/return +7805 +7806 emit-subx-epilogue: # out: (addr buffered-file) +7807 # . prologue +7808 55/push-ebp +7809 89/<- %ebp 4/r32/esp +7810 # +7811 (write-buffered *(ebp+8) " # . epilogue\n") +7812 (write-buffered *(ebp+8) " 89/<- %esp 5/r32/ebp\n") +7813 (write-buffered *(ebp+8) " 5d/pop-to-ebp\n") +7814 (write-buffered *(ebp+8) " c3/return\n") +7815 $emit-subx-epilogue:end: +7816 # . epilogue +7817 89/<- %esp 5/r32/ebp +7818 5d/pop-to-ebp +7819 c3/return -- cgit 1.4.1-2-gfad0