From 399d2972f25bd67f001de68f429e14a1270c9db6 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 1 Feb 2020 22:56:51 -0800 Subject: 5972 --- html/apps/mu.subx.html | 13183 ++++++++++++++++++++++++----------------------- 1 file changed, 6703 insertions(+), 6480 deletions(-) (limited to 'html/apps/*.subx.html') diff --git a/html/apps/mu.subx.html b/html/apps/mu.subx.html index 8ac2db8e..d915a4ea 100644 --- a/html/apps/mu.subx.html +++ b/html/apps/mu.subx.html @@ -385,7 +385,7 @@ if ('onhashchange' in window) { 323 0/imm32 324 Var-type: 325 4/imm32 - 326 Var-block: + 326 Var-block-depth: 327 8/imm32 328 Var-stack-offset: 329 0xc/imm32 @@ -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 @@ -515,14 +515,14 @@ if ('onhashchange' in window) { 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") + 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 @@ -569,23 +569,23 @@ if ('onhashchange' in window) { 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") + 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") + 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 @@ -620,14 +620,14 @@ if ('onhashchange' in window) { 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") + 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 @@ -667,17 +667,17 @@ if ('onhashchange' in window) { 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") + 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 @@ -717,17 +717,17 @@ if ('onhashchange' in window) { 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") + 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 @@ -770,18 +770,18 @@ if ('onhashchange' in window) { 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") + 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 @@ -824,18 +824,18 @@ if ('onhashchange' in window) { 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") + 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 @@ -878,18 +878,18 @@ if ('onhashchange' in window) { 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") + 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 @@ -950,29 +950,29 @@ if ('onhashchange' in window) { 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") + 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 @@ -1016,19 +1016,19 @@ if ('onhashchange' in window) { 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") +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 @@ -1073,20 +1073,20 @@ if ('onhashchange' in window) { 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") +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 @@ -1136,21 +1136,21 @@ if ('onhashchange' in window) { 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") +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 @@ -1202,23 +1202,23 @@ if ('onhashchange' in window) { 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") +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 @@ -1273,22 +1273,22 @@ if ('onhashchange' in window) { 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") +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 @@ -1345,6417 +1345,6640 @@ if ('onhashchange' in window) { 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") +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 ####################################################### -1385 # Parsing -1386 ####################################################### -1387 -1388 parse-mu: # in: (addr buffered-file) -1389 # pseudocode -1390 # var curr-function: (addr (handle function)) = Program -1391 # var line: (stream byte 512) -1392 # var word-slice: slice -1393 # while true # line loop -1394 # clear-stream(line) -1395 # read-line-buffered(in, line) -1396 # if (line->write == 0) break # end of file -1397 # word-slice = next-mu-token(line) -1398 # if slice-empty?(word-slice) # end of line -1399 # continue -1400 # else if slice-starts-with?(word-slice, "#") # comment -1401 # continue # end of line -1402 # else if slice-equal(word-slice, "fn") -1403 # var new-function: (handle function) = allocate(function) -1404 # var vars: (stack (addr var) 256) -1405 # populate-mu-function-header(in, new-function, vars) -1406 # populate-mu-function-body(in, new-function, vars) -1407 # assert(vars->top == 0) -1408 # *curr-function = new-function -1409 # curr-function = &new-function->next -1410 # else -1411 # abort() -1412 # -1413 # . prologue -1414 55/push-ebp -1415 89/<- %ebp 4/r32/esp -1416 # . save registers -1417 50/push-eax -1418 51/push-ecx -1419 52/push-edx -1420 53/push-ebx -1421 57/push-edi -1422 # var line/ecx: (stream byte 512) -1423 81 5/subop/subtract %esp 0x200/imm32 -1424 68/push 0x200/imm32/length -1425 68/push 0/imm32/read -1426 68/push 0/imm32/write -1427 89/<- %ecx 4/r32/esp -1428 # var word-slice/edx: slice -1429 68/push 0/imm32/end -1430 68/push 0/imm32/start -1431 89/<- %edx 4/r32/esp -1432 # var curr-function/edi: (addr (handle function)) = Program -1433 bf/copy-to-edi Program/imm32 -1434 # var vars/ebx: (stack (addr var) 256) -1435 81 5/subop/subtract %esp 0x400/imm32 -1436 68/push 0x400/imm32/length -1437 68/push 0/imm32/top -1438 89/<- %ebx 4/r32/esp -1439 { -1440 $parse-mu:line-loop: -1441 (clear-stream %ecx) -1442 (read-line-buffered *(ebp+8) %ecx) -1443 # if (line->write == 0) break -1444 81 7/subop/compare *ecx 0/imm32 -1445 0f 84/jump-if-= break/disp32 -1446 +-- 6 lines: #? # dump line --------------------------------------------------------------------------------------------------------------------------- -1452 (next-mu-token %ecx %edx) -1453 # if slice-empty?(word-slice) continue -1454 (slice-empty? %edx) -1455 3d/compare-eax-and 0/imm32 -1456 0f 85/jump-if-!= loop/disp32 -1457 # if (*word-slice->start == "#") continue -1458 # . eax = *word-slice->start -1459 8b/-> *edx 0/r32/eax -1460 8a/copy-byte *eax 0/r32/AL -1461 81 4/subop/and %eax 0xff/imm32 -1462 # . if (eax == '#') continue -1463 3d/compare-eax-and 0x23/imm32/hash -1464 0f 84/jump-if-= loop/disp32 -1465 # if (slice-equal?(word-slice, "fn")) parse a function -1466 { -1467 $parse-mu:fn: -1468 (slice-equal? %edx "fn") -1469 3d/compare-eax-and 0/imm32 -1470 0f 84/jump-if-= break/disp32 -1471 # var new-function/eax: (handle function) = populate-mu-function(in, new-function, vars) -1472 (allocate Heap *Function-size) # => eax -1473 (zero-out %eax *Function-size) -1474 (clear-stack %ebx) -1475 (populate-mu-function-header %ecx %eax %ebx) -1476 (populate-mu-function-body *(ebp+8) %eax %ebx) -1477 # *curr-function = new-function -1478 89/<- *edi 0/r32/eax -1479 # curr-function = &new-function->next -1480 8d/address-> *(eax+0x14) 7/r32/edi # Function-next -1481 e9/jump $parse-mu:line-loop/disp32 -1482 } -1483 # otherwise abort -1484 e9/jump $parse-mu:error1/disp32 -1485 } # end line loop -1486 $parse-mu:end: -1487 # . reclaim locals -1488 81 0/subop/add %esp 0x630/imm32 -1489 # . restore registers -1490 5f/pop-to-edi -1491 5b/pop-to-ebx -1492 5a/pop-to-edx -1493 59/pop-to-ecx -1494 58/pop-to-eax -1495 # . epilogue -1496 89/<- %esp 5/r32/ebp -1497 5d/pop-to-ebp -1498 c3/return -1499 -1500 $parse-mu:error1: -1501 # error("unexpected top-level command: " word-slice "\n") -1502 (write-buffered Stderr "unexpected top-level command: ") -1503 (write-slice-buffered Stderr %edx) -1504 (write-buffered Stderr "\n") -1505 (flush Stderr) -1506 # . syscall(exit, 1) -1507 bb/copy-to-ebx 1/imm32 -1508 b8/copy-to-eax 1/imm32/exit -1509 cd/syscall 0x80/imm8 -1510 # never gets here -1511 -1512 $parse-mu:error2: -1513 # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n") -1514 (print-int32-buffered Stderr *ebx) -1515 (write-buffered Stderr " vars not reclaimed after fn '") -1516 (write-slice-buffered Stderr *eax) # Function-name -1517 (write-buffered Stderr "'\n") -1518 (flush Stderr) -1519 # . syscall(exit, 1) -1520 bb/copy-to-ebx 1/imm32 -1521 b8/copy-to-eax 1/imm32/exit -1522 cd/syscall 0x80/imm8 -1523 # never gets here -1524 -1525 # scenarios considered: -1526 # ✗ fn foo # no block -1527 # ✓ fn foo { -1528 # ✗ fn foo { { -1529 # ✗ fn foo { } -1530 # ✗ fn foo { } { -1531 # ✗ fn foo x { -1532 # ✗ fn foo x: { -1533 # ✓ fn foo x: int { -1534 # ✓ fn foo x: int { -1535 # ✓ fn foo x: int -> y/eax: int { -1536 populate-mu-function-header: # first-line: (addr stream byte), out: (handle function), vars: (addr stack (handle var)) -1537 # pseudocode: -1538 # var name: slice -1539 # next-word(first-line, name) -1540 # assert(name not in '{' '}' '->') -1541 # out->name = slice-to-string(name) -1542 # var next-offset: int = 8 -1543 # ## inouts -1544 # while true -1545 # ## name -1546 # name = next-word(first-line) -1547 # if (name == '{') goto done -1548 # if (name == '->') break -1549 # assert(name != '}') -1550 # var v: (handle var) = parse-var-with-type(name, first-line) -1551 # assert(v->register == null) -1552 # v->stack-offset = next-offset -1553 # next-offset += size-of(v) -1554 # out->inouts = append(out->inouts, v) -1555 # push(vars, v) -1556 # ## outputs -1557 # while true -1558 # ## name -1559 # name = next-word(first-line) -1560 # assert(name not in '{' '}' '->') -1561 # var v: (handle var) = parse-var-with-type(name, first-line) -1562 # assert(v->register != null) -1563 # out->outputs = append(out->outputs, v) -1564 # done: -1565 # -1566 # . prologue -1567 55/push-ebp -1568 89/<- %ebp 4/r32/esp -1569 # . save registers -1570 50/push-eax -1571 51/push-ecx -1572 52/push-edx -1573 53/push-ebx -1574 57/push-edi -1575 # edi = out -1576 8b/-> *(ebp+0xc) 7/r32/edi -1577 # var word-slice/ecx: slice -1578 68/push 0/imm32/end -1579 68/push 0/imm32/start -1580 89/<- %ecx 4/r32/esp -1581 # var next-offset/edx = 8 -1582 ba/copy-to-edx 8/imm32 -1583 # read function name -1584 (next-word *(ebp+8) %ecx) -1585 # error checking -1586 # if (word-slice == '{') abort -1587 (slice-equal? %ecx "{") # => eax -1588 3d/compare-eax-and 0/imm32 -1589 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1590 # if (word-slice == '->') abort -1591 (slice-equal? %ecx "->") # => eax -1592 3d/compare-eax-and 0/imm32 -1593 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1594 # if (word-slice == '}') abort -1595 (slice-equal? %ecx "}") # => eax -1596 3d/compare-eax-and 0/imm32 -1597 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1598 # save function name -1599 (slice-to-string Heap %ecx) # => eax -1600 89/<- *edi 0/r32/eax # Function-name -1601 # initialize default subx-name as well -1602 89/<- *(edi+4) 0/r32/eax # Function-subx-name -1603 # save function inouts -1604 { -1605 $populate-mu-function-header:check-for-inout: -1606 (next-word *(ebp+8) %ecx) -1607 # if (word-slice == '{') goto done -1608 (slice-equal? %ecx "{") # => eax -1609 3d/compare-eax-and 0/imm32 -1610 0f 85/jump-if-!= $populate-mu-function-header:done/disp32 -1611 # if (word-slice == '->') break -1612 (slice-equal? %ecx "->") # => eax -1613 3d/compare-eax-and 0/imm32 -1614 0f 85/jump-if-!= break/disp32 -1615 # if (word-slice == '}') abort -1616 (slice-equal? %ecx "}") # => eax -1617 3d/compare-eax-and 0/imm32 -1618 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1619 # var v/ebx: (handle var) = parse-var-with-type(word-slice, first-line) -1620 (parse-var-with-type %ecx *(ebp+8)) # => eax -1621 89/<- %ebx 0/r32/eax -1622 # assert(v->register == null) -1623 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -1624 0f 85/jump-if-!= $populate-mu-function-header:error2/disp32 -1625 # v->stack-offset = next-offset -1626 89/<- *(ebx+0xc) 2/r32/edx # Var-stack-offset -1627 # next-offset += size-of(v) -1628 (size-of %ebx) # => eax -1629 01/add %edx 0/r32/eax -1630 # -1631 (append-list Heap %ebx *(edi+8)) # Function-inouts => eax -1632 89/<- *(edi+8) 0/r32/eax # Function-inouts -1633 (push *(ebp+0x10) %ebx) -1634 # -1635 e9/jump loop/disp32 -1636 } -1637 # save function outputs -1638 { -1639 $parse-var-with-type:check-for-out: -1640 (next-word *(ebp+8) %ecx) -1641 # if (word-slice == '{') break -1642 (slice-equal? %ecx "{") # => eax -1643 3d/compare-eax-and 0/imm32 -1644 0f 85/jump-if-!= break/disp32 -1645 # if (word-slice == '->') abort -1646 (slice-equal? %ecx "->") # => eax -1647 3d/compare-eax-and 0/imm32 -1648 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1649 # if (word-slice == '}') abort -1650 (slice-equal? %ecx "}") # => eax -1651 3d/compare-eax-and 0/imm32 -1652 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1653 # -1654 (parse-var-with-type %ecx *(ebp+8)) # => eax -1655 89/<- %ebx 0/r32/eax -1656 # assert(var->register != null) -1657 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -1658 0f 84/jump-if-= $populate-mu-function-header:error3/disp32 -1659 (append-list Heap %ebx *(edi+0xc)) # Function-outputs => eax -1660 89/<- *(edi+0xc) 0/r32/eax # Function-outputs -1661 e9/jump loop/disp32 -1662 } -1663 $populate-mu-function-header:done: -1664 (check-no-tokens-left *(ebp+8)) -1665 $populate-mu-function-header:end: -1666 # . reclaim locals -1667 81 0/subop/add %esp 8/imm32 -1668 # . restore registers -1669 5f/pop-to-edi -1670 5b/pop-to-ebx -1671 5a/pop-to-edx -1672 59/pop-to-ecx -1673 58/pop-to-eax -1674 # . epilogue -1675 89/<- %esp 5/r32/ebp -1676 5d/pop-to-ebp -1677 c3/return -1678 -1679 $populate-mu-function-header:error1: -1680 # error("function header not in form 'fn <name> {'") -1681 (write-buffered Stderr "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '") -1682 (flush Stderr) -1683 (rewind-stream *(ebp+8)) -1684 (write-stream 2 *(ebp+8)) -1685 (write-buffered Stderr "'\n") -1686 (flush Stderr) -1687 # . syscall(exit, 1) -1688 bb/copy-to-ebx 1/imm32 -1689 b8/copy-to-eax 1/imm32/exit -1690 cd/syscall 0x80/imm8 -1691 # never gets here -1692 -1693 $populate-mu-function-header:error2: -1694 # error("function input '" var "' cannot be in a register") -1695 (write-buffered Stderr "function input '") -1696 (write-buffered Stderr *ebx) # Var-name -1697 (write-buffered Stderr "' cannot be in a register") -1698 (flush Stderr) -1699 # . syscall(exit, 1) -1700 bb/copy-to-ebx 1/imm32 -1701 b8/copy-to-eax 1/imm32/exit -1702 cd/syscall 0x80/imm8 -1703 # never gets here -1704 -1705 $populate-mu-function-header:error3: -1706 # error("function input '" var "' must be in a register") -1707 (write-buffered Stderr "function input '") -1708 (write-buffered Stderr *eax) # Var-name -1709 (write-buffered Stderr " must be in a register'") -1710 (flush Stderr) -1711 (rewind-stream *(ebp+8)) -1712 (write-stream 2 *(ebp+8)) -1713 (write-buffered Stderr "'\n") -1714 (flush Stderr) -1715 # . syscall(exit, 1) -1716 bb/copy-to-ebx 1/imm32 -1717 b8/copy-to-eax 1/imm32/exit -1718 cd/syscall 0x80/imm8 -1719 # never gets here -1720 -1721 test-function-header-with-arg: -1722 # 'foo n : int {' -1723 # . prologue -1724 55/push-ebp -1725 89/<- %ebp 4/r32/esp -1726 # setup -1727 (clear-stream _test-input-stream) -1728 (write _test-input-stream "foo n : int {\n") -1729 # var result/ecx: function -1730 2b/subtract-> *Function-size 4/r32/esp -1731 89/<- %ecx 4/r32/esp -1732 (zero-out %ecx *Function-size) -1733 # var vars/ebx: (stack (addr var) 16) -1734 81 5/subop/subtract %esp 0x10/imm32 -1735 68/push 0x10/imm32/length -1736 68/push 0/imm32/top -1737 89/<- %ebx 4/r32/esp -1738 # convert -1739 (populate-mu-function-header _test-input-stream %ecx %ebx) -1740 # check result -1741 (check-strings-equal *ecx "foo" "F - test-function-header-with-arg/name") # Function-name -1742 # edx: (handle list var) = result->inouts -1743 8b/-> *(ecx+8) 2/r32/edx # Function-inouts -1744 # ebx: (handle var) = result->inouts->value -1745 8b/-> *edx 3/r32/ebx # List-value -1746 (check-strings-equal *ebx "n" "F - test-function-header-with-arg/inout:0") # Var-name -1747 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1748 (check-ints-equal *ebx 1 "F - test-function-header-with-arg/inout:0/type:0") # Tree-left -1749 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-arg/inout:0/type:1") # Tree-right -1750 # . epilogue -1751 89/<- %esp 5/r32/ebp -1752 5d/pop-to-ebp -1753 c3/return -1754 -1755 test-function-header-with-multiple-args: -1756 # 'fn foo a: int, b: int, c: int {' -1757 # . prologue -1758 55/push-ebp -1759 89/<- %ebp 4/r32/esp -1760 # setup -1761 (clear-stream _test-input-stream) -1762 (write _test-input-stream "foo a: int, b: int c: int {\n") -1763 # result/ecx: (handle function) -1764 2b/subtract-> *Function-size 4/r32/esp -1765 89/<- %ecx 4/r32/esp -1766 (zero-out %ecx *Function-size) -1767 # var vars/ebx: (stack (addr var) 16) -1768 81 5/subop/subtract %esp 0x10/imm32 -1769 68/push 0x10/imm32/length -1770 68/push 0/imm32/top -1771 89/<- %ebx 4/r32/esp -1772 # convert -1773 (populate-mu-function-header _test-input-stream %ecx %ebx) -1774 # check result -1775 (check-strings-equal *ecx "foo") # Function-name -1776 # edx: (handle list var) = result->inouts -1777 8b/-> *(ecx+8) 2/r32/edx # Function-inouts -1778 $test-function-header-with-multiple-args:inout0: -1779 # ebx: (handle var) = result->inouts->value -1780 8b/-> *edx 3/r32/ebx # List-value -1781 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name -1782 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1783 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:0/type:0") # Tree-left -1784 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:0/type:1") # Tree-right -1785 # edx = result->inouts->next -1786 8b/-> *(edx+4) 2/r32/edx # List-next -1787 $test-function-header-with-multiple-args:inout1: -1788 # ebx = result->inouts->next->value -1789 8b/-> *edx 3/r32/ebx # List-value -1790 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args/inout:1") # Var-name -1791 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1792 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:1/type:0") # Tree-left -1793 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:1/type:1") # Tree-right -1794 # edx = result->inouts->next->next -1795 8b/-> *(edx+4) 2/r32/edx # List-next -1796 $test-function-header-with-multiple-args:inout2: -1797 # ebx = result->inouts->next->next->value -1798 8b/-> *edx 3/r32/ebx # List-value -1799 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args/inout:2") # Var-name -1800 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1801 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:2/type:0") # Tree-left -1802 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:2/type:1") # Tree-right -1803 # . epilogue -1804 89/<- %esp 5/r32/ebp -1805 5d/pop-to-ebp -1806 c3/return -1807 -1808 test-function-with-multiple-args-and-outputs: -1809 # fn foo a: int, b: int, c: int -> x: int, y: int { -1810 # . prologue -1811 55/push-ebp -1812 89/<- %ebp 4/r32/esp -1813 # setup -1814 (clear-stream _test-input-stream) -1815 (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx: int {\n") -1816 # result/ecx: (handle function) -1817 2b/subtract-> *Function-size 4/r32/esp -1818 89/<- %ecx 4/r32/esp -1819 (zero-out %ecx *Function-size) -1820 # var vars/ebx: (stack (addr var) 16) -1821 81 5/subop/subtract %esp 0x10/imm32 -1822 68/push 0x10/imm32/length -1823 68/push 0/imm32/top -1824 89/<- %ebx 4/r32/esp -1825 # convert -1826 (populate-mu-function-header _test-input-stream %ecx %ebx) -1827 # check result -1828 (check-strings-equal *ecx "foo") # Function-name -1829 # edx: (handle list var) = result->inouts -1830 8b/-> *(ecx+8) 2/r32/edx # Function-inouts -1831 # ebx: (handle var) = result->inouts->value -1832 8b/-> *edx 3/r32/ebx # List-value -1833 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0") # Var-name -1834 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1835 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0") # Tree-left -1836 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1") # Tree-right -1837 # edx = result->inouts->next -1838 8b/-> *(edx+4) 2/r32/edx # List-next -1839 # ebx = result->inouts->next->value -1840 8b/-> *edx 3/r32/ebx # List-value -1841 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1") # Var-name -1842 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1843 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0") # Tree-left -1844 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1") # Tree-right -1845 # edx = result->inouts->next->next -1846 8b/-> *(edx+4) 2/r32/edx # List-next -1847 # ebx = result->inouts->next->next->value -1848 8b/-> *edx 3/r32/ebx # List-value -1849 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2") # Var-name -1850 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1851 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0") # Tree-left -1852 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1") # Tree-right -1853 # edx: (handle list var) = result->outputs -1854 8b/-> *(ecx+0xc) 2/r32/edx # Function-outputs -1855 # ebx: (handle var) = result->outputs->value -1856 8b/-> *edx 3/r32/ebx # List-value -1857 (check-strings-equal *ebx "x" "F - test-function-header-with-multiple-args-and-outputs/output:0") # Var-name -1858 (check-strings-equal *(ebx+0x10) "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register -1859 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1860 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-left -1861 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-right -1862 # edx = result->outputs->next -1863 8b/-> *(edx+4) 2/r32/edx # List-next -1864 # ebx = result->outputs->next->value -1865 8b/-> *edx 3/r32/ebx # List-value -1866 (check-strings-equal *ebx "y" "F - test-function-header-with-multiple-args-and-outputs/output:1") # Var-name -1867 (check-strings-equal *(ebx+0x10) "edx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register -1868 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1869 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-left -1870 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-right -1871 # . epilogue -1872 89/<- %esp 5/r32/ebp -1873 5d/pop-to-ebp -1874 c3/return -1875 -1876 # format for variables with types -1877 # x: int -1878 # x: int -1879 # x: int, -1880 # ignores at most one trailing colon or comma -1881 parse-var-with-type: # name: (addr slice), first-line: (addr stream byte) -> result/eax: (handle var) -1882 # pseudocode: -1883 # var v: (handle var) = allocate(Heap, Var-size) -1884 # var s: slice -1885 # next-token-from-slice(name->start, name->end, '/', s) -1886 # var end: (addr byte) = s->end -1887 # if (slice-ends-with(s, ":")) -1888 # decrement s->end -1889 # if (slice-ends-with(s, ",")) -1890 # decrement s->end -1891 # v->name = slice-to-string(s) -1892 # ## register -1893 # next-token-from-slice(end, name->end, '/', s) -1894 # if (slice-ends-with(s, ":")) -1895 # decrement s->end -1896 # if (slice-ends-with(s, ",")) -1897 # decrement s->end -1898 # if (!slice-empty?(s)) -1899 # v->register = slice-to-string(s) -1900 # ## type -1901 # var type: (handle tree type-id) = parse-type(first-line) -1902 # v->type = type -1903 # return v -1904 # -1905 # . prologue -1906 55/push-ebp -1907 89/<- %ebp 4/r32/esp -1908 # . save registers -1909 51/push-ecx -1910 52/push-edx -1911 53/push-ebx -1912 56/push-esi -1913 57/push-edi -1914 # var result/edi: (handle var) = allocate(Heap, Var-size) -1915 (allocate Heap *Var-size) # => eax -1916 (zero-out %eax *Var-size) -1917 89/<- %edi 0/r32/eax -1918 # esi = name -1919 8b/-> *(ebp+8) 6/r32/esi -1920 # var s/ecx: slice -1921 68/push 0/imm32/end -1922 68/push 0/imm32/start -1923 89/<- %ecx 4/r32/esp -1924 $parse-var-with-type:save-name: -1925 # save v->name -1926 (next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/' -1927 # . end/edx = s->end -1928 8b/-> *(ecx+4) 2/r32/edx -1929 # . if s ends with ':', decrement s->end -1930 { -1931 8b/-> *(ecx+4) 0/r32/eax -1932 48/decrement-eax -1933 8a/copy-byte *eax 3/r32/BL -1934 81 4/subop/and %ebx 0xff/imm32 -1935 81 7/subop/compare %ebx 0x3a/imm32/colon -1936 75/jump-if-!= break/disp8 -1937 89/<- *(ecx+4) 0/r32/eax -1938 } -1939 # . if s ends with ',', decrement s->end -1940 { -1941 8b/-> *(ecx+4) 0/r32/eax -1942 48/decrement-eax -1943 8a/copy-byte *eax 3/r32/BL -1944 81 4/subop/and %ebx 0xff/imm32 -1945 81 7/subop/compare %ebx 0x2c/imm32/comma -1946 75/jump-if-!= break/disp8 -1947 89/<- *(ecx+4) 0/r32/eax -1948 } -1949 $parse-var-with-type:write-name: -1950 (slice-to-string Heap %ecx) # => eax -1951 89/<- *edi 0/r32/eax # Var-name -1952 # save v->register -1953 $parse-var-with-type:save-register: -1954 (next-token-from-slice %edx *(esi+4) 0x2f %ecx) # end, name->end, '/' -1955 # . if s ends with ':', decrement s->end -1956 { -1957 8b/-> *(ecx+4) 0/r32/eax -1958 48/decrement-eax -1959 8a/copy-byte *eax 3/r32/BL -1960 81 4/subop/and %ebx 0xff/imm32 -1961 81 7/subop/compare %ebx 0x3a/imm32/colon -1962 75/jump-if-!= break/disp8 -1963 89/<- *(ecx+4) 0/r32/eax -1964 } -1965 # . if s ends with ',', decrement s->end -1966 { -1967 8b/-> *(ecx+4) 0/r32/eax -1968 48/decrement-eax -1969 8a/copy-byte *eax 3/r32/BL -1970 81 4/subop/and %ebx 0xff/imm32 -1971 81 7/subop/compare %ebx 0x2c/imm32/comma -1972 75/jump-if-!= break/disp8 -1973 89/<- *(ecx+4) 0/r32/eax -1974 } -1975 # if (!slice-empty?(s)) v->register = slice-to-string(s) -1976 { -1977 $parse-var-with-type:write-register: -1978 # HACK: s->end can be less than s->start with all the decrements above -1979 # That's probably a sign we have the wrong algorithm for this function. -1980 8b/-> *ecx 0/r32/eax -1981 39/compare 0/r32/eax *(ecx+4) -1982 76/jump-if-<= break/disp8 -1983 (slice-to-string Heap %ecx) -1984 89/<- *(edi+0x10) 0/r32/eax # Var-register -1985 } -1986 $parse-var-with-type:save-type: -1987 (parse-type Heap *(ebp+0xc)) # => eax -1988 89/<- *(edi+4) 0/r32/eax # Var-type -1989 $parse-var-with-type:end: -1990 # return result -1991 89/<- %eax 7/r32/edi -1992 # . reclaim locals -1993 81 0/subop/add %esp 8/imm32 -1994 # . restore registers -1995 5f/pop-to-edi -1996 5e/pop-to-esi -1997 5b/pop-to-ebx -1998 5a/pop-to-edx -1999 59/pop-to-ecx -2000 # . epilogue -2001 89/<- %esp 5/r32/ebp -2002 5d/pop-to-ebp -2003 c3/return -2004 -2005 $parse-var-with-type:abort: -2006 # error("function header not in form 'fn <name> {'") -2007 (write-buffered Stderr "var should have form 'name: type' in '") -2008 (flush Stderr) -2009 (rewind-stream *(ebp+0xc)) -2010 (write-stream 2 *(ebp+0xc)) -2011 (write-buffered Stderr "'\n") -2012 (flush Stderr) -2013 # . syscall(exit, 1) -2014 bb/copy-to-ebx 1/imm32 -2015 b8/copy-to-eax 1/imm32/exit -2016 cd/syscall 0x80/imm8 -2017 # never gets here -2018 -2019 parse-type: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) -2020 # pseudocode: -2021 # var s: slice = next-mu-token(in) -2022 # assert s != "" -2023 # assert s != "->" -2024 # assert s != "{" -2025 # assert s != "}" -2026 # if s == ")" -2027 # return 0 -2028 # result = allocate(Tree) -2029 # zero-out(result, *Tree-size) -2030 # if s != "(" -2031 # result->left = pos-slice(Type-id, s) -2032 # return -2033 # result->left = parse-type(ad, in) -2034 # result->right = parse-type-tree(ad, in) -2035 # -2036 # . prologue -2037 55/push-ebp -2038 89/<- %ebp 4/r32/esp -2039 # . save registers -2040 51/push-ecx -2041 52/push-edx -2042 # var s/ecx: slice -2043 68/push 0/imm32 -2044 68/push 0/imm32 -2045 89/<- %ecx 4/r32/esp -2046 # s = next-mu-token(in) -2047 (next-mu-token *(ebp+0xc) %ecx) -2048 #? (write-buffered Stderr "tok: ") -2049 #? (write-slice-buffered Stderr %ecx) -2050 #? (write-buffered Stderr "$\n") -2051 #? (flush Stderr) -2052 # assert s != "" -2053 (slice-equal? %ecx "") -2054 3d/compare-eax-and 0/imm32 -2055 0f 85/jump-if-!= $parse-type:abort/disp32 -2056 # assert s != "{" -2057 (slice-equal? %ecx "{") -2058 3d/compare-eax-and 0/imm32 -2059 0f 85/jump-if-!= $parse-type:abort/disp32 -2060 # assert s != "}" -2061 (slice-equal? %ecx "}") -2062 3d/compare-eax-and 0/imm32 -2063 0f 85/jump-if-!= $parse-type:abort/disp32 -2064 # assert s != "->" -2065 (slice-equal? %ecx "->") -2066 3d/compare-eax-and 0/imm32 -2067 0f 85/jump-if-!= $parse-type:abort/disp32 -2068 # if (s == ")") return 0 -2069 (slice-equal? %ecx ")") -2070 3d/compare-eax-and 0/imm32 -2071 b8/copy-to-eax 0/imm32 -2072 0f 85/jump-if-!= $parse-type:end/disp32 -2073 # var result/edx: (handle tree type-id) -2074 (allocate *(ebp+8) *Tree-size) # => eax -2075 (zero-out %eax *Tree-size) -2076 89/<- %edx 0/r32/eax -2077 { -2078 # if (s != "(") break -2079 (slice-equal? %ecx "(") -2080 3d/compare-eax-and 0/imm32 -2081 75/jump-if-!= break/disp8 -2082 # result->left = pos-slice(Type-id, s) -2083 (pos-slice Type-id %ecx) -2084 #? (write-buffered Stderr "=> {") -2085 #? (print-int32-buffered Stderr %eax) -2086 #? (write-buffered Stderr ", 0}\n") -2087 #? (flush Stderr) -2088 89/<- *edx 0/r32/eax # Tree-left -2089 e9/jump $parse-type:return-edx/disp32 -2090 } -2091 # otherwise s == "(" -2092 # result->left = parse-type(ad, in) -2093 (parse-type *(ebp+8) *(ebp+0xc)) -2094 #? (write-buffered Stderr "=> {") -2095 #? (print-int32-buffered Stderr %eax) -2096 89/<- *edx 0/r32/eax # Tree-left -2097 # result->right = parse-type-tree(ad, in) -2098 (parse-type-tree *(ebp+8) *(ebp+0xc)) -2099 #? (write-buffered Stderr Space) -2100 #? (print-int32-buffered Stderr %eax) -2101 #? (write-buffered Stderr "}\n") -2102 #? (flush Stderr) -2103 89/<- *(edx+4) 0/r32/eax # Tree-right -2104 $parse-type:return-edx: -2105 89/<- %eax 2/r32/edx -2106 $parse-type:end: -2107 # . reclaim locals -2108 81 0/subop/add %esp 8/imm32 -2109 # . restore registers -2110 5a/pop-to-edx -2111 59/pop-to-ecx -2112 # . epilogue -2113 89/<- %esp 5/r32/ebp -2114 5d/pop-to-ebp -2115 c3/return -2116 -2117 $parse-type:abort: -2118 # error("unexpected token when parsing type: '" s "'\n") -2119 (write-buffered Stderr "unexpected token when parsing type: '") -2120 (write-slice-buffered Stderr %ecx) -2121 (write-buffered Stderr "'\n") -2122 (flush Stderr) -2123 # . syscall(exit, 1) -2124 bb/copy-to-ebx 1/imm32 -2125 b8/copy-to-eax 1/imm32/exit -2126 cd/syscall 0x80/imm8 -2127 # never gets here -2128 -2129 parse-type-tree: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) -2130 # pseudocode: -2131 # var tmp: (handle tree type-id) = parse-type(ad, in) -2132 # if tmp == 0 -2133 # return 0 -2134 # result = allocate(Tree) -2135 # zero-out(result, *Tree-size) -2136 # result->left = tmp -2137 # result->right = parse-type-tree(ad, in) -2138 # -2139 # . prologue -2140 55/push-ebp -2141 89/<- %ebp 4/r32/esp -2142 # . save registers -2143 51/push-ecx -2144 52/push-edx -2145 # var tmp/eax: (handle tree type-id) = parse-type(ad, in) -2146 (parse-type *(ebp+8) *(ebp+0xc)) -2147 # if (tmp == 0) return tmp -2148 3d/compare-eax-and 0/imm32 -2149 74/jump-if-= $parse-type-tree:end/disp8 -2150 # var tmp2/ecx = tmp -2151 89/<- %ecx 0/r32/eax -2152 # var result/edx: (handle tree type-id) -2153 (allocate *(ebp+8) *Tree-size) # => eax -2154 (zero-out %eax *Tree-size) -2155 89/<- %edx 0/r32/eax -2156 # result->left = tmp2 -2157 89/<- *edx 1/r32/ecx # Tree-left -2158 # result->right = parse-type-tree(ad, in) -2159 (parse-type-tree *(ebp+8) *(ebp+0xc)) -2160 89/<- *(edx+4) 0/r32/eax # Tree-right -2161 $parse-type-tree:return-edx: -2162 89/<- %eax 2/r32/edx -2163 $parse-type-tree:end: -2164 # . restore registers -2165 5a/pop-to-edx -2166 59/pop-to-ecx -2167 # . epilogue -2168 89/<- %esp 5/r32/ebp -2169 5d/pop-to-ebp -2170 c3/return -2171 -2172 next-mu-token: # in: (addr stream byte), out: (addr slice) -2173 # pseudocode: -2174 # start: -2175 # skip-chars-matching-whitespace(in) -2176 # if in->read >= in->write # end of in -2177 # out = {0, 0} -2178 # return -2179 # out->start = &in->data[in->read] -2180 # var curr-byte/eax: byte = in->data[in->read] -2181 # if curr->byte == ':' # comment token -2182 # ++in->read -2183 # goto start -2184 # if curr->byte == ',' # comment token -2185 # ++in->read -2186 # goto start -2187 # if curr-byte == '#' # comment -2188 # in->read = in->write # skip to end of in -2189 # goto done -2190 # if curr-byte == '"' # string literal -2191 # skip-string(in) -2192 # goto done # no metadata -2193 # if curr-byte == '(' -2194 # ++in->read -2195 # goto done -2196 # if curr-byte == ')' -2197 # ++in->read -2198 # goto done -2199 # # read a word -2200 # while true -2201 # if in->read >= in->write -2202 # break -2203 # curr-byte = in->data[in->read] -2204 # if curr-byte == ' ' -2205 # break -2206 # if curr-byte == '\r' -2207 # break -2208 # if curr-byte == '\n' -2209 # break -2210 # if curr-byte == '(' -2211 # break -2212 # if curr-byte == ')' -2213 # break -2214 # if curr-byte == ':' -2215 # break -2216 # if curr-byte == ',' -2217 # break -2218 # ++in->read -2219 # done: -2220 # out->end = &in->data[in->read] -2221 # # hack: skip a few trailing delimiters, because we don't always use -2222 # # this correct tokenizer in later tokens -2223 # while true -2224 # if in->read >= in->write -2225 # break -2226 # curr-byte = in->data[in->read] -2227 # if curr-byte == ':' -2228 # ++in->read -2229 # else if curr-byte == ',' -2230 # ++in->read -2231 # else -2232 # break -2233 # -2234 # . prologue -2235 55/push-ebp -2236 89/<- %ebp 4/r32/esp -2237 # . save registers -2238 50/push-eax -2239 51/push-ecx -2240 56/push-esi -2241 57/push-edi -2242 # esi = in -2243 8b/-> *(ebp+8) 6/r32/esi -2244 # edi = out -2245 8b/-> *(ebp+0xc) 7/r32/edi -2246 $next-mu-token:start: -2247 (skip-chars-matching-whitespace %esi) -2248 $next-mu-token:check0: -2249 # if (in->read >= in->write) return out = {0, 0} -2250 # . ecx = in->read -2251 8b/-> *(esi+4) 1/r32/ecx -2252 # . if (ecx >= in->write) return out = {0, 0} -2253 3b/compare 1/r32/ecx *esi -2254 c7 0/subop/copy *edi 0/imm32 -2255 c7 0/subop/copy *(edi+4) 0/imm32 -2256 0f 8d/jump-if->= $next-mu-token:end/disp32 -2257 # out->start = &in->data[in->read] -2258 8d/copy-address *(esi+ecx+0xc) 0/r32/eax -2259 89/<- *edi 0/r32/eax -2260 # var curr-byte/eax: byte = in->data[in->read] -2261 31/xor %eax 0/r32/eax -2262 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -2263 { -2264 $next-mu-token:check-for-colon: -2265 # if (curr-byte != ':') break -2266 3d/compare-eax-and 0x3a/imm32/colon -2267 75/jump-if-!= break/disp8 -2268 # ++in->read -2269 ff 0/subop/increment *(esi+4) -2270 # restart -2271 e9/jump $next-mu-token:start/disp32 -2272 } -2273 { -2274 $next-mu-token:check-for-comma: -2275 # if (curr-byte != ',') break -2276 3d/compare-eax-and 0x2c/imm32/comma -2277 75/jump-if-!= break/disp8 -2278 # ++in->read -2279 ff 0/subop/increment *(esi+4) -2280 # restart -2281 e9/jump $next-mu-token:start/disp32 -2282 } -2283 { -2284 $next-mu-token:check-for-comment: -2285 # if (curr-byte != '#') break -2286 3d/compare-eax-and 0x23/imm32/pound -2287 75/jump-if-!= break/disp8 -2288 # in->read = in->write # skip rest of in -2289 8b/-> *esi 0/r32/eax -2290 89/<- *(esi+4) 0/r32/eax -2291 # return -2292 e9/jump $next-mu-token:done/disp32 -2293 } -2294 { -2295 $next-mu-token:check-for-string-literal: -2296 # if (curr-byte != '"') break -2297 3d/compare-eax-and 0x22/imm32/dquote -2298 75/jump-if-!= break/disp8 -2299 (skip-string %esi) -2300 # return -2301 e9/jump $next-mu-token:done/disp32 -2302 } -2303 { -2304 $next-mu-token:check-for-open-paren: -2305 # if (curr-byte != '(') break -2306 3d/compare-eax-and 0x28/imm32/open-paren -2307 75/jump-if-!= break/disp8 -2308 # ++in->read -2309 ff 0/subop/increment *(esi+4) -2310 # return -2311 e9/jump $next-mu-token:done/disp32 -2312 } -2313 { -2314 $next-mu-token:check-for-close-paren: -2315 # if (curr-byte != ')') break -2316 3d/compare-eax-and 0x29/imm32/close-paren -2317 75/jump-if-!= break/disp8 -2318 # ++in->read -2319 ff 0/subop/increment *(esi+4) -2320 # return -2321 e9/jump $next-mu-token:done/disp32 -2322 } -2323 { -2324 $next-mu-token:regular-word-without-metadata: -2325 # if (in->read >= in->write) break -2326 # . ecx = in->read -2327 8b/-> *(esi+4) 1/r32/ecx -2328 # . if (ecx >= in->write) break -2329 3b/compare *esi 1/r32/ecx -2330 7d/jump-if->= break/disp8 -2331 # var c/eax: byte = in->data[in->read] -2332 31/xor %eax 0/r32/eax -2333 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -2334 # if (c == ' ') break -2335 3d/compare-eax-and 0x20/imm32/space -2336 74/jump-if-= break/disp8 -2337 # if (c == '\r') break -2338 3d/compare-eax-and 0xd/imm32/carriage-return -2339 74/jump-if-= break/disp8 -2340 # if (c == '\n') break -2341 3d/compare-eax-and 0xa/imm32/newline -2342 74/jump-if-= break/disp8 -2343 # if (c == '(') break -2344 3d/compare-eax-and 0x28/imm32/open-paren -2345 0f 84/jump-if-= break/disp32 -2346 # if (c == ')') break -2347 3d/compare-eax-and 0x29/imm32/close-paren -2348 0f 84/jump-if-= break/disp32 -2349 # if (c == ':') break -2350 3d/compare-eax-and 0x3a/imm32/colon -2351 0f 84/jump-if-= break/disp32 -2352 # if (c == ',') break -2353 3d/compare-eax-and 0x2c/imm32/comma -2354 0f 84/jump-if-= break/disp32 -2355 # ++in->read -2356 ff 0/subop/increment *(esi+4) -2357 # -2358 e9/jump loop/disp32 -2359 } -2360 $next-mu-token:done: -2361 # out->end = &in->data[in->read] -2362 8b/-> *(esi+4) 1/r32/ecx -2363 8d/copy-address *(esi+ecx+0xc) 0/r32/eax -2364 89/<- *(edi+4) 0/r32/eax -2365 { -2366 $next-mu-token:skip-trailing-delimiters: -2367 # if (in->read >= in->write) break -2368 # . ecx = in->read -2369 8b/-> *(esi+4) 1/r32/ecx -2370 # . if (ecx >= in->write) break -2371 3b/compare *esi 1/r32/ecx -2372 7d/jump-if->= break/disp8 -2373 # var c/eax: byte = in->data[in->read] -2374 31/xor %eax 0/r32/eax -2375 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -2376 # if (c == ':') ++in->read and loop -2377 { -2378 3d/compare-eax-and 0x3a/imm32/colon -2379 75/jump-if-!= break/disp8 -2380 # ++in->read -2381 ff 0/subop/increment *(esi+4) -2382 # -2383 eb/jump $next-mu-token:skip-trailing-delimiters/disp8 -2384 } -2385 # if (c == ',') ++in->read and loop -2386 { -2387 3d/compare-eax-and 0x2c/imm32/comma -2388 75/jump-if-!= break/disp8 -2389 # ++in->read -2390 ff 0/subop/increment *(esi+4) -2391 # -2392 eb/jump $next-mu-token:skip-trailing-delimiters/disp8 -2393 } -2394 # else break -2395 } -2396 $next-mu-token:end: -2397 # . restore registers -2398 5f/pop-to-edi -2399 5e/pop-to-esi -2400 59/pop-to-ecx -2401 58/pop-to-eax -2402 # . epilogue -2403 89/<- %esp 5/r32/ebp -2404 5d/pop-to-ebp -2405 c3/return -2406 -2407 # return the index in an array of strings matching 's' -2408 # index is denominated in elements, not bytes -2409 pos-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int -2410 # . prologue -2411 55/push-ebp -2412 89/<- %ebp 4/r32/esp -2413 # . save registers -2414 51/push-ecx -2415 52/push-edx -2416 53/push-ebx -2417 56/push-esi -2418 #? (write-buffered Stderr "pos-slice: ") -2419 #? (write-slice-buffered Stderr *(ebp+0xc)) -2420 #? (write-buffered Stderr "\n") -2421 #? (flush Stderr) -2422 # esi = arr -2423 8b/-> *(ebp+8) 6/r32/esi -2424 # var index/ecx: int = 0 -2425 b9/copy-to-ecx 0/imm32 -2426 # var curr/edx: (addr (addr array byte)) = arr->data -2427 8d/copy-address *(esi+0xc) 2/r32/edx -2428 # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write] -2429 8b/-> *esi 3/r32/ebx -2430 8d/copy-address *(esi+ebx+0xc) 3/r32/ebx -2431 { -2432 #? (write-buffered Stderr " ") -2433 #? (print-int32-buffered Stderr %ecx) -2434 #? (write-buffered Stderr "\n") -2435 #? (flush Stderr) -2436 # if (curr >= max) return -1 -2437 39/compare %edx 3/r32/ebx -2438 b8/copy-to-eax -1/imm32 -2439 73/jump-if-addr>= $pos-slice:end/disp8 -2440 # if (slice-equal?(s, *curr)) break -2441 (slice-equal? *(ebp+0xc) *edx) # => eax -2442 3d/compare-eax-and 0/imm32 -2443 75/jump-if-!= break/disp8 -2444 # ++index -2445 41/increment-ecx -2446 # curr += 4 -2447 81 0/subop/add %edx 4/imm32 -2448 # -2449 eb/jump loop/disp8 -2450 } -2451 # return index -2452 89/<- %eax 1/r32/ecx -2453 $pos-slice:end: -2454 #? (write-buffered Stderr "=> ") -2455 #? (print-int32-buffered Stderr %eax) -2456 #? (write-buffered Stderr "\n") -2457 # . restore registers -2458 5e/pop-to-esi -2459 5b/pop-to-ebx -2460 5a/pop-to-edx -2461 59/pop-to-ecx -2462 # . epilogue -2463 89/<- %esp 5/r32/ebp -2464 5d/pop-to-ebp -2465 c3/return -2466 -2467 == data -2468 -2469 Type-id: # (stream (address array byte)) -2470 0x18/imm32/write -2471 0/imm32/read -2472 0x100/imm32/length -2473 # data -2474 "literal"/imm32 # 0 -2475 "int"/imm32 # 1 -2476 "addr"/imm32 # 2 -2477 "array"/imm32 # 3 -2478 "handle"/imm32 # 4 -2479 "bool"/imm32 # 5 -2480 0/imm32 -2481 0/imm32 -2482 # 0x20 -2483 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2484 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2485 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2486 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2487 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2488 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2489 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2490 -2491 == code -2492 -2493 test-parse-var-with-type: -2494 # . prologue -2495 55/push-ebp -2496 89/<- %ebp 4/r32/esp -2497 # (eax..ecx) = "x:" -2498 b8/copy-to-eax "x:"/imm32 -2499 8b/-> *eax 1/r32/ecx -2500 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2501 05/add-to-eax 4/imm32 -2502 # var slice/ecx: slice = {eax, ecx} -2503 51/push-ecx -2504 50/push-eax -2505 89/<- %ecx 4/r32/esp -2506 # _test-input-stream contains "int" -2507 (clear-stream _test-input-stream) -2508 (write _test-input-stream "int") -2509 # -2510 (parse-var-with-type %ecx _test-input-stream) -2511 8b/-> *eax 2/r32/edx # Var-name -2512 (check-strings-equal %edx "x" "F - test-var-with-type/name") -2513 8b/-> *(eax+4) 2/r32/edx # Var-type -2514 (check-ints-equal *edx 1 "F - test-var-with-type/type") -2515 (check-ints-equal *(edx+4) 0 "F - test-var-with-type/type") -2516 # . epilogue -2517 89/<- %esp 5/r32/ebp -2518 5d/pop-to-ebp -2519 c3/return -2520 -2521 test-parse-var-with-type-and-register: -2522 # . prologue -2523 55/push-ebp -2524 89/<- %ebp 4/r32/esp -2525 # (eax..ecx) = "x/eax" -2526 b8/copy-to-eax "x/eax"/imm32 -2527 8b/-> *eax 1/r32/ecx -2528 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2529 05/add-to-eax 4/imm32 -2530 # var slice/ecx: slice = {eax, ecx} -2531 51/push-ecx -2532 50/push-eax -2533 89/<- %ecx 4/r32/esp -2534 # _test-input-stream contains ": int" -2535 (clear-stream _test-input-stream) -2536 (write _test-input-stream ": int") -2537 # -2538 (parse-var-with-type %ecx _test-input-stream) -2539 8b/-> *eax 2/r32/edx # Var-name -2540 (check-strings-equal %edx "x" "F - test-var-with-type-and-register/name") -2541 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2542 (check-strings-equal %edx "eax" "F - test-var-with-type-and-register/register") -2543 8b/-> *(eax+4) 2/r32/edx # Var-type -2544 (check-ints-equal *edx 1 "F - test-var-with-type-and-register/type") -2545 (check-ints-equal *(edx+4) 0 "F - test-var-with-type-and-register/type") -2546 # . epilogue -2547 89/<- %esp 5/r32/ebp -2548 5d/pop-to-ebp -2549 c3/return -2550 -2551 test-parse-var-with-trailing-characters: -2552 # . prologue -2553 55/push-ebp -2554 89/<- %ebp 4/r32/esp -2555 # (eax..ecx) = "x:" -2556 b8/copy-to-eax "x:"/imm32 -2557 8b/-> *eax 1/r32/ecx -2558 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2559 05/add-to-eax 4/imm32 -2560 # var slice/ecx: slice = {eax, ecx} -2561 51/push-ecx -2562 50/push-eax -2563 89/<- %ecx 4/r32/esp -2564 # _test-input-stream contains "int," -2565 (clear-stream _test-input-stream) -2566 (write _test-input-stream "int,") -2567 # -2568 (parse-var-with-type %ecx _test-input-stream) -2569 8b/-> *eax 2/r32/edx # Var-name -2570 (check-strings-equal %edx "x" "F - test-var-with-trailing-characters/name") -2571 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2572 (check-ints-equal %edx 0 "F - test-var-with-trailing-characters/register") -2573 8b/-> *(eax+4) 2/r32/edx # Var-type -2574 (check-ints-equal *edx 1 "F - test-var-with-trailing-characters/type") -2575 (check-ints-equal *(edx+4) 0 "F - test-var-with-trailing-characters/type") -2576 # . epilogue -2577 89/<- %esp 5/r32/ebp -2578 5d/pop-to-ebp -2579 c3/return -2580 -2581 test-parse-var-with-register-and-trailing-characters: -2582 # . prologue -2583 55/push-ebp -2584 89/<- %ebp 4/r32/esp -2585 # (eax..ecx) = "x/eax:" -2586 b8/copy-to-eax "x/eax:"/imm32 -2587 8b/-> *eax 1/r32/ecx -2588 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2589 05/add-to-eax 4/imm32 -2590 # var slice/ecx: slice = {eax, ecx} -2591 51/push-ecx -2592 50/push-eax -2593 89/<- %ecx 4/r32/esp -2594 # _test-input-stream contains "int," -2595 (clear-stream _test-input-stream) -2596 (write _test-input-stream "int,") -2597 # -2598 (parse-var-with-type %ecx _test-input-stream) -2599 8b/-> *eax 2/r32/edx # Var-name -2600 (check-strings-equal %edx "x" "F - test-var-with-register-and-trailing-characters/name") -2601 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2602 (check-strings-equal %edx "eax" "F - test-var-with-register-and-trailing-characters/register") -2603 8b/-> *(eax+4) 2/r32/edx # Var-type -2604 (check-ints-equal *edx 1 "F - test-var-with-register-and-trailing-characters/type") -2605 (check-ints-equal *(edx+4) 0 "F - test-var-with-register-and-trailing-characters/type") -2606 # . epilogue -2607 89/<- %esp 5/r32/ebp -2608 5d/pop-to-ebp -2609 c3/return -2610 -2611 test-parse-var-with-compound-type: -2612 # . prologue -2613 55/push-ebp -2614 89/<- %ebp 4/r32/esp -2615 # (eax..ecx) = "x:" -2616 b8/copy-to-eax "x:"/imm32 -2617 8b/-> *eax 1/r32/ecx -2618 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2619 05/add-to-eax 4/imm32 -2620 # var slice/ecx: slice = {eax, ecx} -2621 51/push-ecx -2622 50/push-eax -2623 89/<- %ecx 4/r32/esp -2624 # _test-input-stream contains "(addr int)" -2625 (clear-stream _test-input-stream) -2626 (write _test-input-stream "(addr int)") -2627 # -2628 (parse-var-with-type %ecx _test-input-stream) -2629 8b/-> *eax 2/r32/edx # Var-name -2630 (check-strings-equal %edx "x" "F - test-var-with-compound-type/name") -2631 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2632 (check-ints-equal %edx 0 "F - test-var-with-compound-type/register") -2633 # var type/edx: (handle tree type-id) = var->type -2634 8b/-> *(eax+4) 2/r32/edx # Var-type -2635 # type->left == atom(addr) -2636 8b/-> *edx 0/r32/eax # Atom-value -2637 (check-ints-equal *eax 2 "F - test-var-with-compound-type/type:0") # Tree-left -2638 # type->right->left == atom(int) -2639 8b/-> *(edx+4) 2/r32/edx # Tree-right -2640 8b/-> *edx 0/r32/eax # Tree-left -2641 (check-ints-equal *eax 1 "F - test-var-with-compound-type/type:1") # Atom-value -2642 # type->right->right == null -2643 (check-ints-equal *(edx+4) 0 "F - test-var-with-compound-type/type:2") # Tree-right -2644 # . epilogue -2645 89/<- %esp 5/r32/ebp -2646 5d/pop-to-ebp -2647 c3/return -2648 -2649 # identifier starts with a letter or '$' or '_' -2650 # no constraints at the moment on later letters -2651 # all we really want to do so far is exclude '{', '}' and '->' -2652 is-identifier?: # in: (addr slice) -> result/eax: boolean -2653 # . prologue -2654 55/push-ebp -2655 89/<- %ebp 4/r32/esp -2656 # if (slice-empty?(in)) return false -2657 (slice-empty? *(ebp+8)) # => eax -2658 3d/compare-eax-and 0/imm32 -2659 75/jump-if-!= $is-identifier?:false/disp8 -2660 # var c/eax: byte = *in->start -2661 8b/-> *(ebp+8) 0/r32/eax -2662 8b/-> *eax 0/r32/eax -2663 8a/copy-byte *eax 0/r32/AL -2664 81 4/subop/and %eax 0xff/imm32 -2665 # if (c == '$') return true -2666 3d/compare-eax-and 0x24/imm32/$ -2667 74/jump-if-= $is-identifier?:true/disp8 -2668 # if (c == '_') return true -2669 3d/compare-eax-and 0x5f/imm32/_ -2670 74/jump-if-= $is-identifier?:true/disp8 -2671 # drop case -2672 25/and-eax-with 0x5f/imm32 -2673 # if (c < 'A') return false -2674 3d/compare-eax-and 0x41/imm32/A -2675 7c/jump-if-< $is-identifier?:false/disp8 -2676 # if (c > 'Z') return false -2677 3d/compare-eax-and 0x5a/imm32/Z -2678 7f/jump-if-> $is-identifier?:false/disp8 -2679 # otherwise return true -2680 $is-identifier?:true: -2681 b8/copy-to-eax 1/imm32/true -2682 eb/jump $is-identifier?:end/disp8 -2683 $is-identifier?:false: -2684 b8/copy-to-eax 0/imm32/false -2685 $is-identifier?:end: -2686 # . epilogue -2687 89/<- %esp 5/r32/ebp -2688 5d/pop-to-ebp -2689 c3/return -2690 -2691 test-is-identifier-dollar: -2692 # . prologue -2693 55/push-ebp -2694 89/<- %ebp 4/r32/esp -2695 # (eax..ecx) = "$a" -2696 b8/copy-to-eax "$a"/imm32 -2697 8b/-> *eax 1/r32/ecx -2698 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2699 05/add-to-eax 4/imm32 -2700 # var slice/ecx: slice = {eax, ecx} -2701 51/push-ecx -2702 50/push-eax -2703 89/<- %ecx 4/r32/esp -2704 # -2705 (is-identifier? %ecx) -2706 (check-ints-equal %eax 1 "F - test-is-identifier-dollar") -2707 # . epilogue -2708 89/<- %esp 5/r32/ebp -2709 5d/pop-to-ebp -2710 c3/return -2711 -2712 test-is-identifier-underscore: -2713 # . prologue -2714 55/push-ebp -2715 89/<- %ebp 4/r32/esp -2716 # (eax..ecx) = "_a" -2717 b8/copy-to-eax "_a"/imm32 -2718 8b/-> *eax 1/r32/ecx -2719 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2720 05/add-to-eax 4/imm32 -2721 # var slice/ecx: slice = {eax, ecx} -2722 51/push-ecx -2723 50/push-eax -2724 89/<- %ecx 4/r32/esp -2725 # -2726 (is-identifier? %ecx) -2727 (check-ints-equal %eax 1 "F - test-is-identifier-underscore") -2728 # . epilogue -2729 89/<- %esp 5/r32/ebp -2730 5d/pop-to-ebp -2731 c3/return -2732 -2733 test-is-identifier-a: -2734 # . prologue -2735 55/push-ebp -2736 89/<- %ebp 4/r32/esp -2737 # (eax..ecx) = "a$" -2738 b8/copy-to-eax "a$"/imm32 -2739 8b/-> *eax 1/r32/ecx -2740 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2741 05/add-to-eax 4/imm32 -2742 # var slice/ecx: slice = {eax, ecx} -2743 51/push-ecx -2744 50/push-eax -2745 89/<- %ecx 4/r32/esp -2746 # -2747 (is-identifier? %ecx) -2748 (check-ints-equal %eax 1 "F - test-is-identifier-a") -2749 # . epilogue -2750 89/<- %esp 5/r32/ebp -2751 5d/pop-to-ebp -2752 c3/return -2753 -2754 test-is-identifier-z: -2755 # . prologue -2756 55/push-ebp -2757 89/<- %ebp 4/r32/esp -2758 # (eax..ecx) = "z$" -2759 b8/copy-to-eax "z$"/imm32 -2760 8b/-> *eax 1/r32/ecx -2761 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2762 05/add-to-eax 4/imm32 -2763 # var slice/ecx: slice = {eax, ecx} -2764 51/push-ecx -2765 50/push-eax -2766 89/<- %ecx 4/r32/esp -2767 # -2768 (is-identifier? %ecx) -2769 (check-ints-equal %eax 1 "F - test-is-identifier-z") -2770 # . epilogue -2771 89/<- %esp 5/r32/ebp -2772 5d/pop-to-ebp -2773 c3/return -2774 -2775 test-is-identifier-A: -2776 # . prologue -2777 55/push-ebp -2778 89/<- %ebp 4/r32/esp -2779 # (eax..ecx) = "A$" -2780 b8/copy-to-eax "A$"/imm32 -2781 8b/-> *eax 1/r32/ecx -2782 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2783 05/add-to-eax 4/imm32 -2784 # var slice/ecx: slice = {eax, ecx} -2785 51/push-ecx -2786 50/push-eax -2787 89/<- %ecx 4/r32/esp -2788 # -2789 (is-identifier? %ecx) -2790 (check-ints-equal %eax 1 "F - test-is-identifier-A") -2791 # . epilogue -2792 89/<- %esp 5/r32/ebp -2793 5d/pop-to-ebp -2794 c3/return -2795 -2796 test-is-identifier-Z: -2797 # . prologue -2798 55/push-ebp -2799 89/<- %ebp 4/r32/esp -2800 # (eax..ecx) = "Z$" -2801 b8/copy-to-eax "Z$"/imm32 -2802 8b/-> *eax 1/r32/ecx -2803 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2804 05/add-to-eax 4/imm32 -2805 # var slice/ecx: slice = {eax, ecx} -2806 51/push-ecx -2807 50/push-eax -2808 89/<- %ecx 4/r32/esp -2809 # -2810 (is-identifier? %ecx) -2811 (check-ints-equal %eax 1 "F - test-is-identifier-Z") -2812 # . epilogue -2813 89/<- %esp 5/r32/ebp -2814 5d/pop-to-ebp -2815 c3/return -2816 -2817 test-is-identifier-@: -2818 # character before 'A' is invalid -2819 # . prologue -2820 55/push-ebp -2821 89/<- %ebp 4/r32/esp -2822 # (eax..ecx) = "@a" -2823 b8/copy-to-eax "@a"/imm32 -2824 8b/-> *eax 1/r32/ecx -2825 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2826 05/add-to-eax 4/imm32 -2827 # var slice/ecx: slice = {eax, ecx} -2828 51/push-ecx -2829 50/push-eax -2830 89/<- %ecx 4/r32/esp -2831 # -2832 (is-identifier? %ecx) -2833 (check-ints-equal %eax 0 "F - test-is-identifier-@") -2834 # . epilogue -2835 89/<- %esp 5/r32/ebp -2836 5d/pop-to-ebp -2837 c3/return -2838 -2839 test-is-identifier-square-bracket: -2840 # character after 'Z' is invalid -2841 # . prologue -2842 55/push-ebp -2843 89/<- %ebp 4/r32/esp -2844 # (eax..ecx) = "[a" -2845 b8/copy-to-eax "[a"/imm32 -2846 8b/-> *eax 1/r32/ecx -2847 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2848 05/add-to-eax 4/imm32 -2849 # var slice/ecx: slice = {eax, ecx} -2850 51/push-ecx -2851 50/push-eax -2852 89/<- %ecx 4/r32/esp -2853 # -2854 (is-identifier? %ecx) -2855 (check-ints-equal %eax 0 "F - test-is-identifier-@") -2856 # . epilogue -2857 89/<- %esp 5/r32/ebp -2858 5d/pop-to-ebp -2859 c3/return -2860 -2861 test-is-identifier-backtick: -2862 # character before 'a' is invalid -2863 # . prologue -2864 55/push-ebp -2865 89/<- %ebp 4/r32/esp -2866 # (eax..ecx) = "`a" -2867 b8/copy-to-eax "`a"/imm32 -2868 8b/-> *eax 1/r32/ecx -2869 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2870 05/add-to-eax 4/imm32 -2871 # var slice/ecx: slice = {eax, ecx} -2872 51/push-ecx -2873 50/push-eax -2874 89/<- %ecx 4/r32/esp -2875 # -2876 (is-identifier? %ecx) -2877 (check-ints-equal %eax 0 "F - test-is-identifier-backtick") -2878 # . epilogue -2879 89/<- %esp 5/r32/ebp -2880 5d/pop-to-ebp -2881 c3/return -2882 -2883 test-is-identifier-curly-brace-open: -2884 # character after 'z' is invalid; also used for blocks -2885 # . prologue -2886 55/push-ebp -2887 89/<- %ebp 4/r32/esp -2888 # (eax..ecx) = "{a" -2889 b8/copy-to-eax "{a"/imm32 -2890 8b/-> *eax 1/r32/ecx -2891 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2892 05/add-to-eax 4/imm32 -2893 # var slice/ecx: slice = {eax, ecx} -2894 51/push-ecx -2895 50/push-eax -2896 89/<- %ecx 4/r32/esp -2897 # -2898 (is-identifier? %ecx) -2899 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open") -2900 # . epilogue -2901 89/<- %esp 5/r32/ebp -2902 5d/pop-to-ebp -2903 c3/return -2904 -2905 test-is-identifier-curly-brace-close: -2906 # . prologue -2907 55/push-ebp -2908 89/<- %ebp 4/r32/esp -2909 # (eax..ecx) = "}a" -2910 b8/copy-to-eax "}a"/imm32 -2911 8b/-> *eax 1/r32/ecx -2912 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2913 05/add-to-eax 4/imm32 -2914 # var slice/ecx: slice = {eax, ecx} -2915 51/push-ecx -2916 50/push-eax -2917 89/<- %ecx 4/r32/esp -2918 # -2919 (is-identifier? %ecx) -2920 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close") -2921 # . epilogue -2922 89/<- %esp 5/r32/ebp -2923 5d/pop-to-ebp -2924 c3/return -2925 -2926 test-is-identifier-hyphen: -2927 # disallow leading '-' since '->' has special meaning -2928 # . prologue -2929 55/push-ebp -2930 89/<- %ebp 4/r32/esp -2931 # (eax..ecx) = "-a" -2932 b8/copy-to-eax "-a"/imm32 -2933 8b/-> *eax 1/r32/ecx -2934 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2935 05/add-to-eax 4/imm32 -2936 # var slice/ecx: slice = {eax, ecx} -2937 51/push-ecx -2938 50/push-eax -2939 89/<- %ecx 4/r32/esp -2940 # -2941 (is-identifier? %ecx) -2942 (check-ints-equal %eax 0 "F - test-is-identifier-hyphen") -2943 # . epilogue -2944 89/<- %esp 5/r32/ebp -2945 5d/pop-to-ebp -2946 c3/return -2947 -2948 populate-mu-function-body: # in: (addr buffered-file), out: (handle function), vars: (addr stack (handle var)) -2949 # . prologue -2950 55/push-ebp -2951 89/<- %ebp 4/r32/esp -2952 # . save registers -2953 50/push-eax -2954 56/push-esi -2955 57/push-edi -2956 # esi = in -2957 8b/-> *(ebp+8) 6/r32/esi -2958 # edi = out -2959 8b/-> *(ebp+0xc) 7/r32/edi -2960 # initialize some global state -2961 c7 0/subop/copy *Curr-block-depth 0/imm32 -2962 c7 0/subop/copy *Next-local-stack-offset -4/imm32 -2963 # var eax: (handle block) = parse-mu-block(in, vars) -2964 (parse-mu-block %esi *(ebp+0x10) %edi) # => eax -2965 # out->body = eax -2966 89/<- *(edi+0x10) 0/r32/eax # Function-body -2967 $populate-mu-function-body:end: -2968 # . restore registers -2969 5f/pop-to-edi -2970 5e/pop-to-esi -2971 58/pop-to-eax -2972 # . epilogue -2973 89/<- %esp 5/r32/ebp -2974 5d/pop-to-ebp -2975 c3/return -2976 -2977 == data -2978 -2979 # Global state when parsing a function -2980 Curr-block-depth: # (addr int) -2981 0/imm32 -2982 Next-local-stack-offset: # (addr int) -2983 -4/imm32 -2984 -2985 == code -2986 -2987 # parses a block, assuming that the leading '{' has already been read by the caller -2988 parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle block) -2989 # pseudocode: -2990 # var line: (stream byte 512) -2991 # var word-slice: slice -2992 # result/eax = allocate(Heap, Stmt-size) -2993 # result->tag = 0/Block -2994 # while true # line loop -2995 # clear-stream(line) -2996 # read-line-buffered(in, line) -2997 # if (line->write == 0) break # end of file -2998 # word-slice = next-word(line) -2999 # if slice-empty?(word-slice) # end of line -3000 # continue -3001 # else if slice-starts-with?(word-slice, "#") -3002 # continue -3003 # else if slice-equal?(word-slice, "{") -3004 # assert(no-tokens-in(line)) -3005 # block = parse-mu-block(in, vars, fn) -3006 # append-to-block(result, block) -3007 # else if slice-equal?(word-slice, "}") -3008 # break -3009 # else if slice-ends-with?(word-slice, ":") -3010 # # TODO: check the rest of line -3011 # named-block = parse-mu-named-block(word-slice, in, vars, fn) -3012 # append-to-block(result, named-block) -3013 # else if slice-equal?(word-slice, "var") -3014 # var-def = parse-mu-var-def(line, vars) -3015 # append-to-block(result, var-def) -3016 # else -3017 # stmt = parse-mu-stmt(line, vars, fn) -3018 # append-to-block(result, stmt) -3019 # return result -3020 # -3021 # . prologue -3022 55/push-ebp -3023 89/<- %ebp 4/r32/esp -3024 # . save registers -3025 51/push-ecx -3026 52/push-edx -3027 53/push-ebx -3028 57/push-edi -3029 # var line/ecx: (stream byte 512) -3030 81 5/subop/subtract %esp 0x200/imm32 -3031 68/push 0x200/imm32/length -3032 68/push 0/imm32/read -3033 68/push 0/imm32/write -3034 89/<- %ecx 4/r32/esp -3035 # var word-slice/edx: slice -3036 68/push 0/imm32/end -3037 68/push 0/imm32/start -3038 89/<- %edx 4/r32/esp -3039 # edi = result -3040 (allocate Heap *Stmt-size) # => eax -3041 (zero-out %eax *Stmt-size) -3042 89/<- %edi 0/r32/eax -3043 # result->tag is implicitly block (0) -3044 { # line loop -3045 $parse-mu-block:line-loop: -3046 # line = read-line-buffered(in) -3047 (clear-stream %ecx) -3048 (read-line-buffered *(ebp+8) %ecx) -3049 #? (write-buffered Stderr "line: ") -3050 #? (write-stream-data Stderr %ecx) -3051 #? (write-buffered Stderr Newline) -3052 #? (flush Stderr) -3053 # if (line->write == 0) break -3054 81 7/subop/compare *ecx 0/imm32 -3055 0f 84/jump-if-= break/disp32 -3056 # word-slice = next-word(line) -3057 (next-word %ecx %edx) -3058 #? (write-buffered Stderr "word: ") -3059 #? (write-slice-buffered Stderr %edx) -3060 #? (write-buffered Stderr Newline) -3061 #? (flush Stderr) -3062 # if slice-empty?(word-slice) continue -3063 (slice-empty? %edx) -3064 3d/compare-eax-and 0/imm32 -3065 0f 85/jump-if-!= loop/disp32 -3066 # if (slice-starts-with?(word-slice, '#') continue -3067 # . eax = *word-slice->start -3068 8b/-> *edx 0/r32/eax -3069 8a/copy-byte *eax 0/r32/AL -3070 81 4/subop/and %eax 0xff/imm32 -3071 # . if (eax == '#') continue -3072 3d/compare-eax-and 0x23/imm32/hash -3073 0f 84/jump-if-= loop/disp32 -3074 # if slice-equal?(word-slice, "{") -3075 { -3076 $parse-mu-block:check-for-block: -3077 (slice-equal? %edx "{") -3078 3d/compare-eax-and 0/imm32 -3079 74/jump-if-= break/disp8 -3080 (check-no-tokens-left %ecx) -3081 # parse new block and append -3082 (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax -3083 (append-to-block Heap %edi %eax) -3084 e9/jump $parse-mu-block:line-loop/disp32 -3085 } -3086 # if slice-equal?(word-slice, "}") break -3087 $parse-mu-block:check-for-end: -3088 (slice-equal? %edx "}") -3089 3d/compare-eax-and 0/imm32 -3090 0f 85/jump-if-!= break/disp32 -3091 # if slice-ends-with?(word-slice, ":") parse named block and append -3092 { -3093 $parse-mu-block:check-for-named-block: -3094 # . eax = *(word-slice->end-1) -3095 8b/-> *(edx+4) 0/r32/eax -3096 48/decrement-eax -3097 8a/copy-byte *eax 0/r32/AL -3098 81 4/subop/and %eax 0xff/imm32 -3099 # . if (eax != ':') break -3100 3d/compare-eax-and 0x3a/imm32/colon -3101 0f 85/jump-if-!= break/disp32 -3102 # -3103 # TODO: error-check the rest of 'line' -3104 (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax -3105 (append-to-block Heap %edi %eax) -3106 e9/jump $parse-mu-block:line-loop/disp32 -3107 } -3108 # if slice-equal?(word-slice, "var") -3109 { -3110 $parse-mu-block:check-for-var: -3111 (slice-equal? %edx "var") -3112 3d/compare-eax-and 0/imm32 -3113 74/jump-if-= break/disp8 -3114 # -3115 (parse-mu-var-def %ecx *(ebp+0xc)) # => eax -3116 (append-to-block Heap %edi %eax) -3117 e9/jump $parse-mu-block:line-loop/disp32 -3118 } -3119 $parse-mu-block:regular-stmt: -3120 # otherwise -3121 (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10)) # => eax -3122 (append-to-block Heap %edi %eax) -3123 e9/jump loop/disp32 -3124 } # end line loop -3125 # return result -3126 89/<- %eax 7/r32/edi -3127 $parse-mu-block:end: -3128 # . reclaim locals -3129 81 0/subop/add %esp 0x214/imm32 -3130 # . restore registers -3131 5f/pop-to-edi -3132 5b/pop-to-ebx -3133 5a/pop-to-edx -3134 59/pop-to-ecx +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") +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: +2775 # . prologue +2776 55/push-ebp +2777 89/<- %ebp 4/r32/esp +2778 # (eax..ecx) = "x:" +2779 b8/copy-to-eax "x:"/imm32 +2780 8b/-> *eax 1/r32/ecx +2781 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2782 05/add-to-eax 4/imm32 +2783 # var slice/ecx: slice = {eax, ecx} +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 3135 # . epilogue 3136 89/<- %esp 5/r32/ebp 3137 5d/pop-to-ebp 3138 c3/return 3139 -3140 $parse-mu-block:abort: -3141 # error("'{' or '}' should be on its own line, but got '") -3142 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") -3143 (rewind-stream %ecx) -3144 (write-stream 2 %ecx) -3145 (write-buffered Stderr "'\n") -3146 (flush Stderr) -3147 # . syscall(exit, 1) -3148 bb/copy-to-ebx 1/imm32 -3149 b8/copy-to-eax 1/imm32/exit -3150 cd/syscall 0x80/imm8 -3151 # never gets here -3152 -3153 check-no-tokens-left: # line: (addr stream byte) -3154 # . prologue -3155 55/push-ebp -3156 89/<- %ebp 4/r32/esp -3157 # . save registers -3158 50/push-eax -3159 51/push-ecx -3160 # var s/ecx: slice -3161 68/push 0/imm32/end -3162 68/push 0/imm32/start -3163 89/<- %ecx 4/r32/esp -3164 # -3165 (next-word *(ebp+8) %ecx) -3166 # if slice-empty?(s) return -3167 (slice-empty? %ecx) -3168 3d/compare-eax-and 0/imm32 -3169 75/jump-if-!= $check-no-tokens-left:end/disp8 -3170 # if (slice-starts-with?(s, '#') return -3171 # . eax = *s->start -3172 8b/-> *edx 0/r32/eax -3173 8a/copy-byte *eax 0/r32/AL -3174 81 4/subop/and %eax 0xff/imm32 -3175 # . if (eax == '#') continue -3176 3d/compare-eax-and 0x23/imm32/hash -3177 74/jump-if-= $check-no-tokens-left:end/disp8 -3178 # abort -3179 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") -3180 (rewind-stream %ecx) -3181 (write-stream 2 %ecx) -3182 (write-buffered Stderr "'\n") -3183 (flush Stderr) -3184 # . syscall(exit, 1) -3185 bb/copy-to-ebx 1/imm32 -3186 b8/copy-to-eax 1/imm32/exit -3187 cd/syscall 0x80/imm8 -3188 # never gets here -3189 $check-no-tokens-left:end: -3190 # . reclaim locals -3191 81 0/subop/add %esp 8/imm32 -3192 # . restore registers -3193 59/pop-to-ecx -3194 58/pop-to-eax -3195 # . epilogue -3196 89/<- %esp 5/r32/ebp -3197 5d/pop-to-ebp -3198 c3/return -3199 -3200 parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) -3201 # pseudocode: -3202 # result = parse-mu-block(in, vars, fn) -3203 # result->tag = named-block -3204 # result->name = slice-to-string(name) -3205 # return result -3206 # -3207 # . prologue -3208 55/push-ebp -3209 89/<- %ebp 4/r32/esp -3210 # . save registers -3211 51/push-ecx -3212 # var s/ecx: (addr array byte) = slice-to-string(name) -3213 (slice-to-string Heap *(ebp+8)) # => eax -3214 89/<- %ecx 0/r32/eax -3215 # -3216 (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) # => eax -3217 # result->tag = named-block -3218 c7 0/subop/copy *eax 4/imm32/named-block # Stmt-tag -3219 # result->name = slice-to-string(name) -3220 89/<- *(eax+8) 1/r32/ecx # Named-block-name -3221 $parse-mu-named-block:end: -3222 # . restore registers -3223 59/pop-to-ecx -3224 # . epilogue -3225 89/<- %esp 5/r32/ebp -3226 5d/pop-to-ebp -3227 c3/return -3228 -3229 parse-mu-var-def: # line: (addr stream byte), vars: (addr stack (handle var)) -> result/eax: (handle stmt) -3230 # . prologue -3231 55/push-ebp -3232 89/<- %ebp 4/r32/esp -3233 # . save registers -3234 51/push-ecx -3235 52/push-edx -3236 # var word-slice/ecx: slice -3237 68/push 0/imm32/end -3238 68/push 0/imm32/start -3239 89/<- %ecx 4/r32/esp -3240 # var v/edx: (handle var) = parse-var-with-type(line) -3241 (next-word *(ebp+8) %ecx) -3242 (parse-var-with-type %ecx *(ebp+8)) # => eax -3243 89/<- %edx 0/r32/eax -3244 # v->stack-offset = *Next-local-stack-offset -3245 8b/-> *Next-local-stack-offset 0/r32/eax -3246 89/<- *(edx+0xc) 0/r32/eax # Var-stack-offset -3247 # *Next-local-stack-offset -= size-of(v) -3248 (size-of %edx) -3249 29/subtract-from *Next-local-stack-offset 0/r32/eax -3250 # -3251 (push *(ebp+0xc) %edx) -3252 # either v has no register and there's no more to this line -3253 8b/-> *(edx+0x10) 0/r32/eax # Var-register -3254 3d/compare-eax-and 0/imm32 -3255 { -3256 75/jump-if-!= break/disp8 -3257 # TODO: ensure that there's nothing else on this line -3258 (new-vardef Heap %edx) # => eax -3259 eb/jump $parse-mu-var-def:end/disp8 -3260 } -3261 # or v has a register and there's more to this line -3262 { -3263 74/jump-if-= break/disp8 -3264 # ensure that the next word is '<-' -3265 (next-word *(ebp+8) %ecx) -3266 (slice-equal? %ecx "<-") # => eax -3267 3d/compare-eax-and 0/imm32 -3268 74/jump-if-= $parse-mu-var-def:abort/disp8 -3269 # -3270 (new-regvardef Heap %edx) # => eax -3271 (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc)) -3272 } -3273 $parse-mu-var-def:end: -3274 # . reclaim locals -3275 81 0/subop/add %esp 8/imm32 -3276 # . restore registers -3277 5a/pop-to-edx -3278 59/pop-to-ecx -3279 # . epilogue -3280 89/<- %esp 5/r32/ebp -3281 5d/pop-to-ebp -3282 c3/return -3283 -3284 $parse-mu-var-def:abort: -3285 (rewind-stream *(ebp+8)) -3286 # error("register variable requires a valid instruction to initialize but got '" line "'\n") -3287 (write-buffered Stderr "register variable requires a valid instruction to initialize but got '") -3288 (flush Stderr) -3289 (write-stream 2 *(ebp+8)) -3290 (write-buffered Stderr "'\n") -3291 (flush Stderr) -3292 # . syscall(exit, 1) -3293 bb/copy-to-ebx 1/imm32 -3294 b8/copy-to-eax 1/imm32/exit -3295 cd/syscall 0x80/imm8 -3296 # never gets here -3297 -3298 test-parse-mu-var-def: -3299 # 'var n: int' -3300 # . prologue -3301 55/push-ebp -3302 89/<- %ebp 4/r32/esp -3303 # setup -3304 (clear-stream _test-input-stream) -3305 (write _test-input-stream "n: int\n") # caller has consumed the 'var' -3306 # var vars/ecx: (stack (addr var) 4) -3307 81 5/subop/subtract %esp 0x10/imm32 -3308 68/push 0x10/imm32/length -3309 68/push 0/imm32/top -3310 89/<- %ecx 4/r32/esp -3311 (clear-stack %ecx) -3312 # convert -3313 (parse-mu-var-def _test-input-stream %ecx) # => eax -3314 # check result -3315 (check-ints-equal *eax 2 "F - test-parse-mu-var-def/tag") # Stmt-tag is vardef -3316 8b/-> *(eax+4) 0/r32/eax # Vardef-var -3317 (check-strings-equal *eax "n" "F - test-parse-mu-var-def/var-name") # Var-name -3318 (check-ints-equal *(eax+0x10) 0 "F - test-parse-mu-var-def/var-register") # Var-register -3319 # TODO: ensure stack-offset is -4 -3320 # TODO: ensure block-depth is 1 -3321 # ensure type is int -3322 8b/-> *(eax+4) 0/r32/eax # Var-type -3323 (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0") # Tree-left -3324 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-var-def/var-type:0") # Tree-right -3325 # . epilogue -3326 89/<- %esp 5/r32/ebp -3327 5d/pop-to-ebp -3328 c3/return -3329 -3330 test-parse-mu-reg-var-def: -3331 # 'var n/eax: int <- copy 0' -3332 # . prologue -3333 55/push-ebp -3334 89/<- %ebp 4/r32/esp -3335 # setup -3336 (clear-stream _test-input-stream) -3337 (write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var' -3338 # var vars/ecx: (stack (addr var) 4) -3339 81 5/subop/subtract %esp 0x10/imm32 -3340 68/push 0x10/imm32/length -3341 68/push 0/imm32/top -3342 89/<- %ecx 4/r32/esp -3343 (clear-stack %ecx) -3344 # convert -3345 (parse-mu-var-def _test-input-stream %ecx) # => eax -3346 # check result -3347 (check-ints-equal *eax 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is regvardef -3348 8b/-> *(eax+0xc) 0/r32/eax # Regvardef-outputs -3349 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/single-output") # List-next -3350 8b/-> *eax 0/r32/eax # List-value -3351 (check-strings-equal *eax "n" "F - test-parse-mu-reg-var-def/output-name") # Var-name -3352 (check-strings-equal *(eax+0x10) "eax" "F - test-parse-mu-reg-var-def/output-register") # Var-register -3353 # TODO: ensure stack-offset is -4 -3354 # TODO: ensure block-depth is 1 -3355 # ensure type is int -3356 8b/-> *(eax+4) 0/r32/eax # Var-type -3357 (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-left -3358 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-right -3359 # . epilogue -3360 89/<- %esp 5/r32/ebp -3361 5d/pop-to-ebp -3362 c3/return -3363 -3364 parse-mu-stmt: # line: (addr stream byte), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) -3365 # pseudocode: -3366 # var name: slice -3367 # result = allocate(Heap, Stmt-size) -3368 # if stmt-has-outputs?(line) -3369 # while true -3370 # name = next-mu-token(line) -3371 # if (name == '<-') break -3372 # assert(is-identifier?(name)) -3373 # var v: (handle var) = lookup-or-define-var(name, vars, fn) # regular stmts may define vars in fn outputs -3374 # result->outputs = append(result->outputs, v) -3375 # add-operation-and-inputs-to-stmt(result, line, vars) -3376 # -3377 # . prologue -3378 55/push-ebp -3379 89/<- %ebp 4/r32/esp -3380 # . save registers -3381 51/push-ecx -3382 57/push-edi -3383 # var name/ecx: slice -3384 68/push 0/imm32/end -3385 68/push 0/imm32/start -3386 89/<- %ecx 4/r32/esp -3387 # result/edi: (handle stmt) -3388 (allocate Heap *Stmt-size) # => eax -3389 (zero-out %eax *Stmt-size) -3390 89/<- %edi 0/r32/eax -3391 # result->tag = 1/stmt -3392 c7 0/subop/copy *edi 1/imm32/stmt1 # Stmt-tag -3393 { -3394 (stmt-has-outputs? *(ebp+8)) -3395 3d/compare-eax-and 0/imm32 -3396 0f 84/jump-if-= break/disp32 -3397 { -3398 $parse-mu-stmt:read-outputs: -3399 # name = next-mu-token(line) -3400 (next-mu-token *(ebp+8) %ecx) -3401 # if slice-empty?(word-slice) break -3402 (slice-empty? %ecx) -3403 3d/compare-eax-and 0/imm32 -3404 0f 85/jump-if-!= break/disp32 -3405 # if (name == "<-") break -3406 (slice-equal? %ecx "<-") -3407 3d/compare-eax-and 0/imm32 -3408 75/jump-if-!= break/disp8 -3409 # assert(is-identifier?(name)) -3410 (is-identifier? %ecx) -3411 3d/compare-eax-and 0/imm32 -3412 0f 84/jump-if-= $parse-mu-stmt:abort/disp32 -3413 # -3414 (lookup-or-define-var %ecx *(ebp+0xc) *(ebp+0x10)) # => eax -3415 (append-list Heap %eax *(edi+0xc)) # Stmt1-outputs => eax -3416 89/<- *(edi+0xc) 0/r32/eax # Stmt1-outputs -3417 e9/jump loop/disp32 -3418 } -3419 } -3420 (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc)) -3421 $parse-mu-stmt:end: -3422 # return result -3423 89/<- %eax 7/r32/edi -3424 # . reclaim locals -3425 81 0/subop/add %esp 8/imm32 -3426 # . restore registers -3427 5f/pop-to-edi -3428 59/pop-to-ecx -3429 # . epilogue -3430 89/<- %esp 5/r32/ebp -3431 5d/pop-to-ebp -3432 c3/return -3433 -3434 $parse-mu-stmt:abort: -3435 # error("invalid identifier '" name "'\n") -3436 (write-buffered Stderr "invalid identifier '") -3437 (write-slice-buffered Stderr %ecx) -3438 (write-buffered Stderr "'\n") -3439 (flush Stderr) -3440 # . syscall(exit, 1) -3441 bb/copy-to-ebx 1/imm32 -3442 b8/copy-to-eax 1/imm32/exit -3443 cd/syscall 0x80/imm8 -3444 # never gets here -3445 -3446 add-operation-and-inputs-to-stmt: # stmt: (handle stmt), line: (addr stream byte) -3447 # pseudocode: -3448 # stmt->name = slice-to-string(next-mu-token(line)) -3449 # while true -3450 # name = next-mu-token(line) -3451 # v = lookup-var-or-literal(name) -3452 # stmt->inouts = append(stmt->inouts, v) -3453 # -3454 # . prologue -3455 55/push-ebp -3456 89/<- %ebp 4/r32/esp -3457 # . save registers -3458 50/push-eax -3459 51/push-ecx -3460 57/push-edi -3461 # edi = stmt -3462 8b/-> *(ebp+8) 7/r32/edi -3463 # var name/ecx: slice -3464 68/push 0/imm32/end -3465 68/push 0/imm32/start -3466 89/<- %ecx 4/r32/esp -3467 $add-operation-and-inputs-to-stmt:read-operation: -3468 (next-mu-token *(ebp+0xc) %ecx) -3469 (slice-to-string Heap %ecx) # => eax -3470 89/<- *(edi+4) 0/r32/eax # Stmt1-operation or Regvardef-operation -3471 { -3472 $add-operation-and-inputs-to-stmt:read-inouts: -3473 # name = next-mu-token(line) -3474 (next-mu-token *(ebp+0xc) %ecx) -3475 # if slice-empty?(word-slice) break -3476 (slice-empty? %ecx) # => eax -3477 3d/compare-eax-and 0/imm32 -3478 0f 85/jump-if-!= break/disp32 -3479 # if (name == "<-") abort -3480 (slice-equal? %ecx "<-") -3481 3d/compare-eax-and 0/imm32 -3482 0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32 -3483 # if (name starts with "$") treat it as a literal -3484 { -3485 # var eax: byte = name[0] -3486 8b/-> *ecx 0/r32/eax -3487 8a/copy-byte *eax 0/r32/AL -3488 81 4/subop/and %eax 0xff/imm32 -3489 # if (eax != '$') goto next condition -3490 3d/compare-eax-and 0x24/imm32/dollar -3491 75/jump-if-!= break/disp8 -3492 # var eax: (handle var) -3493 (new-label Heap %ecx) # => eax -3494 # stmt->inouts = append(eax, stmt->inouts) -3495 (append-list Heap %eax *(edi+8)) # Stmt1-inouts => eax -3496 89/<- *(edi+8) 0/r32/eax # Stmt1-inouts -3497 # continue -3498 e9/jump $add-operation-and-inputs-to-stmt:read-inouts/disp32 -3499 } -3500 $add-operation-and-inputs-to-stmt:regular-inout: -3501 # otherwise -3502 (lookup-var-or-literal %ecx *(ebp+0x10)) # => eax -3503 (append-list Heap %eax *(edi+8)) # Stmt1-inouts or Regvardef-inouts => eax -3504 89/<- *(edi+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts -3505 e9/jump loop/disp32 -3506 } -3507 $add-operation-and-inputs-to-stmt:end: -3508 # . reclaim locals -3509 81 0/subop/add %esp 8/imm32 -3510 # . restore registers -3511 5f/pop-to-edi -3512 59/pop-to-ecx -3513 58/pop-to-eax -3514 # . epilogue -3515 89/<- %esp 5/r32/ebp -3516 5d/pop-to-ebp -3517 c3/return -3518 -3519 $add-operation-and-inputs-to-stmt:abort: -3520 # error("invalid statement '" line "'\n") -3521 (rewind-stream *(ebp+8)) -3522 (write-buffered Stderr "invalid identifier '") -3523 (flush Stderr) -3524 (write-stream 2 *(ebp+8)) -3525 (write-buffered Stderr "'\n") -3526 (flush Stderr) -3527 # . syscall(exit, 1) -3528 bb/copy-to-ebx 1/imm32 -3529 b8/copy-to-eax 1/imm32/exit -3530 cd/syscall 0x80/imm8 -3531 # never gets here -3532 -3533 stmt-has-outputs?: # line: (addr stream byte) -> result/eax: boolean -3534 # . prologue -3535 55/push-ebp -3536 89/<- %ebp 4/r32/esp -3537 # . save registers -3538 51/push-ecx -3539 # var word-slice/ecx: slice -3540 68/push 0/imm32/end -3541 68/push 0/imm32/start -3542 89/<- %ecx 4/r32/esp -3543 # result = false -3544 b8/copy-to-eax 0/imm32/false -3545 (rewind-stream *(ebp+8)) -3546 { -3547 (next-mu-token *(ebp+8) %ecx) -3548 # if slice-empty?(word-slice) break -3549 (slice-empty? %ecx) -3550 3d/compare-eax-and 0/imm32 -3551 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) -3552 0f 85/jump-if-!= break/disp32 -3553 # if slice-starts-with?(word-slice, '#') break -3554 # . eax = *word-slice->start -3555 8b/-> *ecx 0/r32/eax -3556 8a/copy-byte *eax 0/r32/AL -3557 81 4/subop/and %eax 0xff/imm32 -3558 # . if (eax == '#') break -3559 3d/compare-eax-and 0x23/imm32/hash -3560 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) -3561 0f 84/jump-if-= break/disp32 -3562 # if slice-equal?(word-slice, '<-') return true -3563 (slice-equal? %ecx "<-") -3564 3d/compare-eax-and 0/imm32 -3565 74/jump-if-= loop/disp8 -3566 b8/copy-to-eax 1/imm32/true -3567 } -3568 $stmt-has-outputs:end: -3569 (rewind-stream *(ebp+8)) -3570 # . reclaim locals -3571 81 0/subop/add %esp 8/imm32 -3572 # . restore registers -3573 59/pop-to-ecx -3574 # . epilogue -3575 89/<- %esp 5/r32/ebp -3576 5d/pop-to-ebp -3577 c3/return -3578 -3579 # if 'name' starts with a digit, create a new literal var for it -3580 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found -3581 lookup-var-or-literal: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) -3582 # . prologue -3583 55/push-ebp -3584 89/<- %ebp 4/r32/esp -3585 # . save registers -3586 51/push-ecx -3587 56/push-esi -3588 # esi = name -3589 8b/-> *(ebp+8) 6/r32/esi -3590 # if slice-empty?(name) abort -3591 (slice-empty? %esi) # => eax -3592 3d/compare-eax-and 0/imm32 -3593 0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32 -3594 # var c/ecx: byte = *name->start -3595 8b/-> *esi 1/r32/ecx -3596 8a/copy-byte *ecx 1/r32/CL -3597 81 4/subop/and %ecx 0xff/imm32 -3598 # if is-decimal-digit?(c) return new var(name) -3599 { -3600 (is-decimal-digit? %ecx) # => eax -3601 81 7/subop/compare %eax 0/imm32 -3602 74/jump-if-= break/disp8 -3603 (new-literal-integer Heap %esi) # => eax -3604 eb/jump $lookup-var-or-literal:end/disp8 -3605 } -3606 # else if (c == '"') return new var(name) -3607 { -3608 81 7/subop/compare %ecx 0x22/imm32/dquote -3609 75/jump-if-!= break/disp8 -3610 (new-literal-string Heap %esi) # => eax -3611 eb/jump $lookup-var-or-literal:end/disp8 -3612 } -3613 # otherwise return lookup-var(name, vars) -3614 { -3615 (lookup-var %esi *(ebp+0xc)) # => eax -3616 } -3617 $lookup-var-or-literal:end: -3618 # . restore registers -3619 5e/pop-to-esi -3620 59/pop-to-ecx -3621 # . epilogue -3622 89/<- %esp 5/r32/ebp -3623 5d/pop-to-ebp -3624 c3/return -3625 -3626 $lookup-var-or-literal:abort: -3627 (write-buffered Stderr "empty variable!") -3628 (flush Stderr) -3629 # . syscall(exit, 1) -3630 bb/copy-to-ebx 1/imm32 -3631 b8/copy-to-eax 1/imm32/exit -3632 cd/syscall 0x80/imm8 -3633 # never gets here -3634 -3635 # return first 'name' from the top (back) of 'vars' and abort if not found -3636 lookup-var: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) -3637 # . prologue -3638 55/push-ebp -3639 89/<- %ebp 4/r32/esp -3640 # var target/eax: (handle array byte) = slice-to-string(name) -3641 (slice-to-string Heap *(ebp+8)) # => eax -3642 # -3643 (lookup-var-helper %eax *(ebp+0xc)) # => eax -3644 # if (result == 0) abort -3645 3d/compare-eax-and 0/imm32 -3646 74/jump-if-= $lookup-var:abort/disp8 -3647 $lookup-var:end: -3648 # . epilogue -3649 89/<- %esp 5/r32/ebp -3650 5d/pop-to-ebp -3651 c3/return -3652 -3653 $lookup-var:abort: -3654 (write-buffered Stderr "unknown variable '") -3655 (write-slice-buffered Stderr *(ebp+8)) -3656 (write-buffered Stderr "'\n") -3657 (flush Stderr) -3658 # . syscall(exit, 1) -3659 bb/copy-to-ebx 1/imm32 -3660 b8/copy-to-eax 1/imm32/exit -3661 cd/syscall 0x80/imm8 -3662 # never gets here -3663 -3664 # return first 'name' from the top (back) of 'vars', and 0/null if not found -3665 lookup-var-helper: # name: (addr array byte), vars: (addr stack (handle var)) -> result/eax: (handle var) -3666 # pseudocode: -3667 # var curr: (addr handle var) = &vars->data[vars->top - 4] -3668 # var min = vars->data -3669 # while curr >= min -3670 # var v: (handle var) = *curr -3671 # if v->name == name -3672 # return v -3673 # return 0 -3674 # -3675 # . prologue -3676 55/push-ebp -3677 89/<- %ebp 4/r32/esp -3678 # . save registers -3679 52/push-edx -3680 53/push-ebx -3681 56/push-esi -3682 # esi = vars -3683 8b/-> *(ebp+0xc) 6/r32/esi -3684 # ebx = vars->top -3685 8b/-> *esi 3/r32/ebx -3686 # if (vars->top > vars->length) abort -3687 3b/compare 0/r32/eax *(esi+4) -3688 0f 8f/jump-if-> $lookup-var-helper:error1/disp32 -3689 # var min/edx: (addr handle var) = vars->data -3690 8d/copy-address *(esi+8) 2/r32/edx -3691 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 4] -3692 81 5/subop/subtract %ebx 4/imm32 -3693 8d/copy-address *(esi+ebx+8) 3/r32/ebx -3694 { -3695 # if (curr < min) return 0 -3696 39/compare %ebx 2/r32/edx -3697 b8/copy-to-eax 0/imm32 -3698 0f 82/jump-if-addr< break/disp32 -3699 # var v/eax: (handle var) = *curr -3700 8b/-> *ebx 0/r32/eax -3701 # if (v->name == name) return v -3702 (string-equal? *eax *(ebp+8)) # Var-name -3703 3d/compare-eax-and 0/imm32 -3704 8b/-> *ebx 0/r32/eax -3705 75/jump-if-!= break/disp8 -3706 # curr -= 4 -3707 81 5/subop/subtract %ebx 4/imm32 -3708 e9/jump loop/disp32 -3709 } -3710 $lookup-var-helper:end: -3711 # . restore registers -3712 5e/pop-to-esi -3713 5b/pop-to-ebx -3714 5a/pop-to-edx -3715 # . epilogue -3716 89/<- %esp 5/r32/ebp -3717 5d/pop-to-ebp -3718 c3/return -3719 -3720 $lookup-var-helper:error1: -3721 (write-buffered Stderr "malformed stack when looking up '") -3722 (write-slice-buffered Stderr *(ebp+8)) -3723 (write-buffered Stderr "'\n") -3724 (flush Stderr) -3725 # . syscall(exit, 1) -3726 bb/copy-to-ebx 1/imm32 -3727 b8/copy-to-eax 1/imm32/exit -3728 cd/syscall 0x80/imm8 -3729 # never gets here -3730 -3731 # return first 'name' from the top (back) of 'vars' and create a new var for a fn output if not found -3732 lookup-or-define-var: # name: (addr slice), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle var) -3733 # . prologue -3734 55/push-ebp -3735 89/<- %ebp 4/r32/esp -3736 # . save registers -3737 51/push-ecx -3738 # var target/ecx: (handle array byte) = slice-to-string(name) -3739 (slice-to-string Heap *(ebp+8)) # => eax -3740 89/<- %ecx 0/r32/eax -3741 # -3742 (lookup-var-helper %ecx *(ebp+0xc)) # => eax -3743 { -3744 # if (result != 0) return -3745 3d/compare-eax-and 0/imm32 -3746 75/jump-if-!= break/disp8 -3747 # if name is one of fn's outputs, return it -3748 { -3749 (find-in-function-outputs *(ebp+0x10) %ecx) # => eax -3750 3d/compare-eax-and 0/imm32 -3751 # otherwise abort -3752 0f 84/jump-if-!= $lookup-var:abort/disp32 -3753 } -3754 } -3755 $lookup-or-define-var:end: -3756 # . restore registers -3757 59/pop-to-ecx -3758 # . epilogue -3759 89/<- %esp 5/r32/ebp -3760 5d/pop-to-ebp -3761 c3/return -3762 -3763 find-in-function-outputs: # fn: (handle function), name: (handle array byte) => result/eax: (handle var) -3764 # . prologue -3765 55/push-ebp -3766 89/<- %ebp 4/r32/esp -3767 # . save registers -3768 51/push-ecx -3769 # var curr/ecx: (handle list var) = fn->outputs -3770 8b/-> *(ebp+8) 1/r32/ecx -3771 8b/-> *(ecx+0xc) 1/r32/ecx -3772 # while curr != null -3773 { -3774 81 7/subop/compare %ecx 0/imm32 -3775 74/jump-if-= break/disp8 -3776 # var v: (handle var) = *curr -3777 8b/-> *ecx 0/r32/eax # List-value -3778 # if (curr->name == name) return curr -3779 50/push-eax -3780 (string-equal? *eax *(ebp+0xc)) -3781 3d/compare-eax-and 0/imm32 -3782 58/pop-to-eax -3783 75/jump-if-!= $find-in-function-outputs:end/disp8 -3784 # curr = curr->next -3785 8b/-> *(ecx+4) 1/r32/ecx # List-next -3786 eb/jump loop/disp8 -3787 } -3788 b8/copy-to-eax 0/imm32 -3789 $find-in-function-outputs:end: +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 +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 +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) +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 59/pop-to-ecx -3792 # . epilogue -3793 89/<- %esp 5/r32/ebp -3794 5d/pop-to-ebp -3795 c3/return -3796 -3797 test-parse-mu-stmt: -3798 # 'increment n' -3799 # . prologue -3800 55/push-ebp -3801 89/<- %ebp 4/r32/esp -3802 # setup -3803 (clear-stream _test-input-stream) -3804 (write _test-input-stream "increment n\n") -3805 # var vars/ecx: (stack (addr var) 4) -3806 81 5/subop/subtract %esp 0x10/imm32 -3807 68/push 0x10/imm32/length -3808 68/push 0/imm32/top -3809 89/<- %ecx 4/r32/esp -3810 (clear-stack %ecx) -3811 # var v/edx: var -3812 81 5/subop/subtract %esp 0x14/imm32 # Var-size -3813 89/<- %edx 4/r32/esp -3814 (zero-out %edx 0x14) -3815 # v->name = "n" -3816 c7 0/subop/copy *edx "n"/imm32 # Var-name -3817 # -3818 (push %ecx %edx) -3819 # convert -3820 (parse-mu-stmt _test-input-stream %ecx) # => eax -3821 # check result -3822 (check-ints-equal *eax 1 "F - test-parse-mu-stmt/tag") # Stmt-tag is Stmt1 -3823 (check-strings-equal *(eax+4) "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation -3824 # edx: (handle list var) = result->inouts -3825 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts -3826 # ebx: (handle var) = result->inouts->value -3827 8b/-> *edx 3/r32/ebx # List-value -3828 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt/inout:0") # Var-name -3829 # . epilogue -3830 89/<- %esp 5/r32/ebp -3831 5d/pop-to-ebp -3832 c3/return -3833 -3834 test-parse-mu-stmt-with-comma: -3835 # 'increment n' -3836 # . prologue -3837 55/push-ebp -3838 89/<- %ebp 4/r32/esp -3839 # setup -3840 (clear-stream _test-input-stream) -3841 (write _test-input-stream "copy-to n, 3\n") -3842 # var vars/ecx: (stack (addr var) 4) -3843 81 5/subop/subtract %esp 0x10/imm32 -3844 68/push 0x10/imm32/length -3845 68/push 0/imm32/top -3846 89/<- %ecx 4/r32/esp -3847 (clear-stack %ecx) -3848 # var v/edx: var -3849 81 5/subop/subtract %esp 0x14/imm32 # Var-size -3850 89/<- %edx 4/r32/esp -3851 (zero-out %edx 0x14) -3852 # v->name = "n" -3853 c7 0/subop/copy *edx "n"/imm32 # Var-name -3854 # -3855 (push %ecx %edx) -3856 # convert -3857 (parse-mu-stmt _test-input-stream %ecx) # => eax -3858 # check result -3859 (check-ints-equal *eax 1 "F - test-parse-mu-stmt-with-comma/tag") # Stmt-tag is Stmt1 -3860 (check-strings-equal *(eax+4) "copy-to" "F - test-parse-mu-stmt-with-comma/name") # Stmt1-operation -3861 # edx: (handle list var) = result->inouts -3862 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts -3863 # ebx: (handle var) = result->inouts->value -3864 8b/-> *edx 3/r32/ebx # List-value -3865 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt-with-comma/inout:0") # Var-name -3866 # . epilogue -3867 89/<- %esp 5/r32/ebp -3868 5d/pop-to-ebp -3869 c3/return -3870 -3871 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) -3872 # . prologue -3873 55/push-ebp -3874 89/<- %ebp 4/r32/esp -3875 # . save registers -3876 51/push-ecx -3877 # -3878 (allocate *(ebp+8) *Function-size) # => eax -3879 8b/-> *(ebp+0xc) 1/r32/ecx -3880 89/<- *eax 1/r32/ecx # Function-name -3881 8b/-> *(ebp+0x10) 1/r32/ecx -3882 89/<- *(eax+4) 1/r32/ecx # Function-subx-name -3883 8b/-> *(ebp+0x14) 1/r32/ecx -3884 89/<- *(eax+8) 1/r32/ecx # Function-inouts -3885 8b/-> *(ebp+0x18) 1/r32/ecx -3886 89/<- *(eax+0xc) 1/r32/ecx # Function-outputs -3887 8b/-> *(ebp+0x1c) 1/r32/ecx -3888 89/<- *(eax+0x10) 1/r32/ecx # Function-body -3889 8b/-> *(ebp+0x20) 1/r32/ecx -3890 89/<- *(eax+0x14) 1/r32/ecx # Function-next -3891 $new-function:end: -3892 # . restore registers -3893 59/pop-to-ecx -3894 # . epilogue -3895 89/<- %esp 5/r32/ebp -3896 5d/pop-to-ebp -3897 c3/return -3898 -3899 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) -3900 # . prologue -3901 55/push-ebp -3902 89/<- %ebp 4/r32/esp -3903 # . save registers -3904 51/push-ecx -3905 # -3906 (allocate *(ebp+8) *Var-size) # => eax -3907 8b/-> *(ebp+0xc) 1/r32/ecx -3908 89/<- *eax 1/r32/ecx # Var-name -3909 8b/-> *(ebp+0x10) 1/r32/ecx -3910 89/<- *(eax+4) 1/r32/ecx # Var-type -3911 8b/-> *(ebp+0x14) 1/r32/ecx -3912 89/<- *(eax+8) 1/r32/ecx # Var-block -3913 8b/-> *(ebp+0x18) 1/r32/ecx -3914 89/<- *(eax+0xc) 1/r32/ecx # Var-stack-offset -3915 8b/-> *(ebp+0x1c) 1/r32/ecx -3916 89/<- *(eax+0x10) 1/r32/ecx # Var-register -3917 $new-var:end: -3918 # . restore registers -3919 59/pop-to-ecx -3920 # . epilogue -3921 89/<- %esp 5/r32/ebp -3922 5d/pop-to-ebp -3923 c3/return -3924 -3925 new-literal-integer: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -3926 # . prologue -3927 55/push-ebp -3928 89/<- %ebp 4/r32/esp -3929 # . save registers -3930 51/push-ecx -3931 # if (!is-hex-int?(name)) abort -3932 (is-hex-int? *(ebp+0xc)) # => eax -3933 3d/compare-eax-and 0/imm32 -3934 0f 84/jump-if-= $new-literal-integer:abort/disp32 -3935 # var s/ecx: (addr array byte) -3936 (slice-to-string Heap *(ebp+0xc)) # => eax -3937 89/<- %ecx 0/r32/eax -3938 # result/ecx = new var(s) -3939 (allocate *(ebp+8) *Var-size) # => eax -3940 (zero-out %eax *Var-size) -3941 89/<- *eax 1/r32/ecx # Var-name -3942 89/<- %ecx 0/r32/eax -3943 # result->type = new type() -3944 (allocate *(ebp+8) *Tree-size) # => eax -3945 (zero-out %eax *Tree-size) # default type is 'literal' -3946 89/<- *(ecx+4) 0/r32/eax # Var-type -3947 # move result to eax -3948 89/<- %eax 1/r32/ecx -3949 $new-literal-integer:end: -3950 # . restore registers -3951 59/pop-to-ecx -3952 # . epilogue -3953 89/<- %esp 5/r32/ebp -3954 5d/pop-to-ebp -3955 c3/return -3956 -3957 $new-literal-integer:abort: -3958 (write-buffered Stderr "variable cannot begin with a digit '") -3959 (write-slice-buffered Stderr *(ebp+0xc)) -3960 (write-buffered Stderr "'\n") -3961 (flush Stderr) -3962 # . syscall(exit, 1) -3963 bb/copy-to-ebx 1/imm32 -3964 b8/copy-to-eax 1/imm32/exit -3965 cd/syscall 0x80/imm8 -3966 # never gets here -3967 -3968 new-literal-string: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -3969 # . prologue -3970 55/push-ebp -3971 89/<- %ebp 4/r32/esp -3972 # . save registers -3973 51/push-ecx -3974 # var s/ecx: (addr array byte) -3975 (slice-to-string Heap *(ebp+0xc)) # => eax -3976 89/<- %ecx 0/r32/eax -3977 # result/ecx = new var(s) -3978 (allocate *(ebp+8) *Var-size) # => eax -3979 (zero-out %eax) -3980 89/<- *eax 1/r32/ecx # Var-name -3981 89/<- %ecx 0/r32/eax -3982 # result->type = new type() -3983 (allocate *(ebp+8) *Tree-size) # => eax -3984 (zero-out %eax) # default type is 'literal' -3985 89/<- *(ecx+4) 0/r32/eax # Var-type -3986 # move result to eax -3987 89/<- %eax 1/r32/ecx -3988 $new-literal-string:end: -3989 # . restore registers -3990 59/pop-to-ecx -3991 # . epilogue -3992 89/<- %esp 5/r32/ebp -3993 5d/pop-to-ebp -3994 c3/return -3995 -3996 new-label: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -3997 # . prologue -3998 55/push-ebp -3999 89/<- %ebp 4/r32/esp -4000 # . save registers -4001 51/push-ecx -4002 # var s/ecx: (addr array byte) -4003 (slice-to-string Heap *(ebp+0xc)) # => eax -4004 89/<- %ecx 0/r32/eax -4005 # -4006 (allocate *(ebp+8) *Var-size) # => eax -4007 89/<- *eax 1/r32/ecx # Var-name -4008 89/<- %ecx 0/r32/eax -4009 (allocate *(ebp+8) *Tree-size) # => eax -4010 89/<- *(ecx+4) 0/r32/eax # Var-type -4011 89/<- %eax 1/r32/ecx -4012 c7 0/subop/copy *(eax+8) 0/imm32 # Var-block -4013 c7 0/subop/copy *(eax+0xc) 0/imm32 # Var-stack-offset -4014 c7 0/subop/copy *(eax+0x10) 0/imm32 # Var-register -4015 $new-label:end: -4016 # . restore registers -4017 59/pop-to-ecx -4018 # . epilogue -4019 89/<- %esp 5/r32/ebp -4020 5d/pop-to-ebp -4021 c3/return -4022 -4023 new-block: # ad: (addr allocation-descriptor), data: (handle list statement) -> result/eax: (handle statement) -4024 # . prologue -4025 55/push-ebp -4026 89/<- %ebp 4/r32/esp -4027 # . save registers -4028 51/push-ecx -4029 # -4030 (allocate *(ebp+8) *Stmt-size) # => eax -4031 (zero-out %eax *Stmt-size) -4032 c7 0/subop/copy *eax 0/imm32/tag/block # Stmt-tag -4033 8b/-> *(ebp+0xc) 1/r32/ecx -4034 89/<- *(eax+4) 1/r32/ecx # Block-statements -4035 $new-block:end: -4036 # . restore registers -4037 59/pop-to-ecx +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-vardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) +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) *Stmt-size) # => eax -4051 (zero-out %eax *Stmt-size) -4052 c7 0/subop/copy *eax 2/imm32/tag/var-on-stack # Stmt-tag -4053 # result->var = var -4054 8b/-> *(ebp+0xc) 1/r32/ecx -4055 89/<- *(eax+4) 1/r32/ecx # Vardef-var -4056 $new-vardef:end: -4057 # . restore registers -4058 59/pop-to-ecx -4059 # . epilogue -4060 89/<- %esp 5/r32/ebp -4061 5d/pop-to-ebp -4062 c3/return -4063 -4064 new-regvardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) -4065 # . prologue -4066 55/push-ebp -4067 89/<- %ebp 4/r32/esp -4068 # . save registers -4069 51/push-ecx -4070 57/push-edi -4071 # ecx = var -4072 8b/-> *(ebp+0xc) 1/r32/ecx -4073 # edi = result -4074 (allocate *(ebp+8) *Stmt-size) # => eax -4075 89/<- %edi 0/r32/eax -4076 (zero-out %edi *Stmt-size) -4077 # set tag -4078 c7 0/subop/copy *edi 3/imm32/tag/var-in-register # Stmt-tag -4079 # set output -4080 (append-list Heap %ecx *(edi+0xc)) # Regvardef-outputs => eax -4081 89/<- *(edi+0xc) 0/r32/eax # Regvardef-outputs -4082 $new-regvardef:end: -4083 89/<- %eax 7/r32/edi -4084 # . restore registers -4085 5f/pop-to-edi -4086 59/pop-to-ecx -4087 # . epilogue -4088 89/<- %esp 5/r32/ebp -4089 5d/pop-to-ebp -4090 c3/return -4091 -4092 new-named-block: # ad: (addr allocation-descriptor), name: (addr array byte), data: (handle list statement) -> result/eax: (handle statement) -4093 # . prologue -4094 55/push-ebp -4095 89/<- %ebp 4/r32/esp -4096 # . save registers -4097 51/push-ecx -4098 # -4099 (allocate *(ebp+8) *Stmt-size) # => eax -4100 (zero-out %eax *Stmt-size) -4101 c7 0/subop/copy *eax 4/imm32/tag/named-block -4102 8b/-> *(ebp+0xc) 1/r32/ecx -4103 89/<- *(eax+8) 1/r32/ecx # Named-block-name -4104 8b/-> *(ebp+0x10) 1/r32/ecx -4105 89/<- *(eax+4) 1/r32/ecx # Named-block-statements -4106 $new-named-block:end: -4107 # . restore registers -4108 59/pop-to-ecx -4109 # . epilogue -4110 89/<- %esp 5/r32/ebp -4111 5d/pop-to-ebp -4112 c3/return -4113 -4114 new-list: # ad: (addr allocation-descriptor), value: _type, next: (handle list _type) -> result/eax: (handle list _type) -4115 # . prologue -4116 55/push-ebp -4117 89/<- %ebp 4/r32/esp -4118 # . save registers -4119 51/push-ecx -4120 # -4121 (allocate *(ebp+8) *List-size) # => eax -4122 8b/-> *(ebp+0xc) 1/r32/ecx -4123 89/<- *eax 1/r32/ecx # List-value -4124 8b/-> *(ebp+0x10) 1/r32/ecx -4125 89/<- *(eax+4) 1/r32/ecx # List-next -4126 $new-list:end: -4127 # . restore registers -4128 59/pop-to-ecx -4129 # . epilogue -4130 89/<- %esp 5/r32/ebp -4131 5d/pop-to-ebp -4132 c3/return -4133 -4134 append-list: # ad: (addr allocation-descriptor), value: _type, list: (handle list _type) -> result/eax: (handle list _type) -4135 # . prologue -4136 55/push-ebp -4137 89/<- %ebp 4/r32/esp -4138 # . save registers -4139 51/push-ecx -4140 # -4141 (allocate *(ebp+8) *List-size) # => eax -4142 8b/-> *(ebp+0xc) 1/r32/ecx -4143 89/<- *eax 1/r32/ecx # List-value -4144 # if (list == null) return result -4145 81 7/subop/compare *(ebp+0x10) 0/imm32 -4146 74/jump-if-= $new-list:end/disp8 -4147 # otherwise append -4148 # var curr/ecx = list -4149 8b/-> *(ebp+0x10) 1/r32/ecx -4150 # while (curr->next != null) curr = curr->next -4151 { -4152 81 7/subop/compare *(ecx+4) 0/imm32 # List-next -4153 74/jump-if-= break/disp8 -4154 # curr = curr->next -4155 8b/-> *(ecx+4) 1/r32/ecx -4156 eb/jump loop/disp8 -4157 } -4158 # curr->next = result -4159 89/<- *(ecx+4) 0/r32/eax -4160 # return list -4161 8b/-> *(ebp+0x10) 0/r32/eax -4162 $append-list:end: -4163 # . restore registers -4164 59/pop-to-ecx -4165 # . epilogue -4166 89/<- %esp 5/r32/ebp -4167 5d/pop-to-ebp -4168 c3/return -4169 -4170 append-to-block: # ad: (addr allocation-descriptor), block: (handle block), x: (handle stmt) -4171 # . prologue -4172 55/push-ebp -4173 89/<- %ebp 4/r32/esp -4174 # . save registers -4175 56/push-esi -4176 # esi = block -4177 8b/-> *(ebp+0xc) 6/r32/esi -4178 (append-list *(ebp+8) *(ebp+0x10) *(esi+4)) # ad, x, Block-statements -4179 89/<- *(esi+4) 0/r32/eax # Block-statements -4180 $append-to-block:end: -4181 # . restore registers -4182 5e/pop-to-esi -4183 # . epilogue -4184 89/<- %esp 5/r32/ebp -4185 5d/pop-to-ebp -4186 c3/return -4187 -4188 ####################################################### -4189 # Type-checking -4190 ####################################################### -4191 -4192 check-mu-types: -4193 # . prologue -4194 55/push-ebp -4195 89/<- %ebp 4/r32/esp -4196 # -4197 $check-mu-types:end: -4198 # . epilogue -4199 89/<- %esp 5/r32/ebp -4200 5d/pop-to-ebp -4201 c3/return -4202 -4203 size-of: # n: (addr var) -> result/eax: int -4204 # . prologue -4205 55/push-ebp -4206 89/<- %ebp 4/r32/esp -4207 # hard-coded since we only support 'int' types for now -4208 b8/copy-to-eax 4/imm32 -4209 $size-of:end: +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 +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: +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 +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 == data -4216 -4217 # not yet used, but it will be -4218 Type-size: # (stream int) -4219 0x18/imm32/write -4220 0/imm32/read -4221 0x100/imm32/length -4222 # data -4223 4/imm32 # literal -4224 4/imm32 # int -4225 4/imm32 # addr -4226 0/imm32 # array (logic elsewhere) -4227 8/imm32 # handle (fat pointer) -4228 4/imm32 # bool -4229 0/imm32 -4230 0/imm32 -4231 # 0x20 -4232 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4233 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4234 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4235 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4236 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4237 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4238 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4239 -4240 == code -4241 -4242 ####################################################### -4243 # Code-generation -4244 ####################################################### -4245 -4246 emit-subx: # out: (addr buffered-file) -4247 # . prologue -4248 55/push-ebp -4249 89/<- %ebp 4/r32/esp -4250 # . save registers -4251 50/push-eax -4252 51/push-ecx -4253 57/push-edi -4254 # edi = out -4255 8b/-> *(ebp+8) 7/r32/edi -4256 # var curr/ecx: (handle function) = *Program -4257 8b/-> *Program 1/r32/ecx -4258 { -4259 # if (curr == null) break -4260 81 7/subop/compare %ecx 0/imm32 -4261 0f 84/jump-if-= break/disp32 -4262 (emit-subx-function %edi %ecx) -4263 # curr = curr->next -4264 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next -4265 e9/jump loop/disp32 -4266 } -4267 $emit-subx:end: -4268 # . restore registers -4269 5f/pop-to-edi -4270 59/pop-to-ecx -4271 58/pop-to-eax -4272 # . epilogue -4273 89/<- %esp 5/r32/ebp -4274 5d/pop-to-ebp -4275 c3/return -4276 -4277 emit-subx-function: # out: (addr buffered-file), f: (handle function) -4278 # . prologue -4279 55/push-ebp -4280 89/<- %ebp 4/r32/esp -4281 # . save registers -4282 50/push-eax -4283 51/push-ecx -4284 52/push-edx -4285 57/push-edi -4286 # edi = out -4287 8b/-> *(ebp+8) 7/r32/edi -4288 # ecx = f -4289 8b/-> *(ebp+0xc) 1/r32/ecx -4290 # var vars/edx: (stack (addr var) 256) -4291 81 5/subop/subtract %esp 0x400/imm32 -4292 68/push 0x400/imm32/length -4293 68/push 0/imm32/top -4294 89/<- %edx 4/r32/esp -4295 # -4296 (write-buffered %edi *ecx) -4297 (write-buffered %edi ":\n") -4298 (emit-subx-prologue %edi) -4299 (emit-subx-block %edi *(ecx+0x10) %edx) # Function-body -4300 (emit-subx-epilogue %edi) -4301 $emit-subx-function:end: -4302 # . reclaim locals -4303 81 0/subop/add %esp 408/imm32 -4304 # . restore registers -4305 5f/pop-to-edi -4306 5a/pop-to-edx -4307 59/pop-to-ecx -4308 58/pop-to-eax -4309 # . epilogue -4310 89/<- %esp 5/r32/ebp -4311 5d/pop-to-ebp -4312 c3/return -4313 -4314 emit-subx-block: # out: (addr buffered-file), block: (handle block), vars: (addr stack (handle var)) -4315 # . prologue -4316 55/push-ebp -4317 89/<- %ebp 4/r32/esp -4318 # . save registers -4319 56/push-esi -4320 # var stmts/esi: (handle list statement) = block->statements -4321 8b/-> *(ebp+0xc) 6/r32/esi -4322 8b/-> *(esi+4) 6/r32/esi # Block-statements -4323 # -4324 { -4325 $emit-subx-block:check-empty: -4326 81 7/subop/compare %esi 0/imm32 -4327 0f 84/jump-if-= break/disp32 -4328 (write-buffered *(ebp+8) "{\n") -4329 (emit-subx-stmt-list *(ebp+8) %esi *(ebp+0x10)) -4330 (write-buffered *(ebp+8) "}\n") -4331 } -4332 $emit-subx-block:end: -4333 # . restore registers -4334 5e/pop-to-esi -4335 # . epilogue -4336 89/<- %esp 5/r32/ebp -4337 5d/pop-to-ebp -4338 c3/return -4339 -4340 emit-subx-stmt-list: # out: (addr buffered-file), stmts: (handle list stmt), vars: (addr stack (handle var)) -4341 # . prologue -4342 55/push-ebp -4343 89/<- %ebp 4/r32/esp -4344 # . save registers -4345 50/push-eax -4346 51/push-ecx +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 = stmts +4348 # esi = block 4349 8b/-> *(ebp+0xc) 6/r32/esi -4350 # -4351 { -4352 $emit-subx-stmt-list:loop: -4353 81 7/subop/compare %esi 0/imm32 -4354 0f 84/jump-if-= break/disp32 -4355 # var curr-stmt/ecx = stmts->value -4356 8b/-> *esi 1/r32/ecx # List-value -4357 { -4358 $emit-subx-stmt-list:check-for-block: -4359 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag -4360 75/jump-if-!= break/disp8 -4361 $emit-subx-stmt-list:block: -4362 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10)) -4363 } -4364 { -4365 $emit-subx-stmt-list:check-for-stmt: -4366 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag -4367 75/jump-if-!= break/disp8 -4368 $emit-subx-stmt-list:stmt: -4369 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) -4370 } -4371 { -4372 $emit-subx-stmt-list:check-for-vardef: -4373 81 7/subop/compare *ecx 2/imm32/vardef # Stmt-tag -4374 75/jump-if-!= break/disp8 -4375 $emit-subx-stmt-list:vardef: -4376 (emit-subx-var-def *(ebp+8) %ecx) -4377 (push *(ebp+0x10) *(ecx+4)) # Vardef-var -4378 } -4379 { -4380 $emit-subx-stmt-list:check-for-regvardef: -4381 81 7/subop/compare *ecx 3/imm32/regvardef # Stmt-tag -4382 0f 85/jump-if-!= break/disp32 -4383 $emit-subx-stmt-list:regvardef: -4384 # TODO: ensure that there's exactly one output -4385 # var output/eax: (handle var) = curr-stmt->outputs->value -4386 8b/-> *(ecx+0xc) 0/r32/eax -4387 8b/-> *eax 0/r32/eax -4388 # ensure that output is in a register -4389 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -4390 0f 84/jump-if-= $emit-subx-stmt-list:abort-regvardef-without-register/disp32 -4391 # emit spill -4392 (write-buffered *(ebp+8) "ff 6/subop/push %") -4393 (write-buffered *(ebp+8) *(eax+0x10)) -4394 (write-buffered *(ebp+8) Newline) -4395 # register variable definition -4396 (push *(ebp+0x10) %eax) -4397 # emit the instruction as usual -4398 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) -4399 } -4400 { -4401 $emit-subx-stmt-list:check-for-named-block: -4402 81 7/subop/compare *ecx 4/imm32/named-block # Stmt-tag -4403 75/jump-if-!= break/disp8 -4404 $emit-subx-stmt-list:named-block: -4405 (emit-subx-named-block *(ebp+8) %ecx *(ebp+0x10)) -4406 } -4407 8b/-> *(esi+4) 6/r32/esi # List-next -4408 e9/jump loop/disp32 -4409 } -4410 # reclaim locals -4411 # TODO: support nested blocks; take block-ids into account -4412 { -4413 $emit-subx-stmt-list:reclaim-loop: -4414 8b/-> *(ebp+0x10) 0/r32/eax -4415 81 7/subop/compare *eax 0/imm32 # Stack-top -4416 0f 84/jump-if-= break/disp32 -4417 # var v/ecx : (handle var) = top(vars) -4418 (top %eax) # => eax -4419 89/<- %ecx 0/r32/eax -4420 # if v is in a register -4421 81 7/subop/compare *(ecx+0x10) 0/imm32 # Var-register -4422 { -4423 74/jump-if-= break/disp8 -4424 $emit-subx-stmt-list:reclaim-var-in-register: -4425 (write-buffered *(ebp+8) "8f 0/subop/pop %") -4426 (write-buffered *(ebp+8) *(ecx+0x10)) -4427 (write-buffered *(ebp+8) Newline) -4428 } -4429 # if v is on the stack -4430 { -4431 75/jump-if-!= break/disp8 -4432 $emit-subx-stmt-list:reclaim-var-on-stack: -4433 (size-of %ecx) # => eax -4434 01/add *Next-local-stack-offset 0/r32/eax -4435 (write-buffered *(ebp+8) "81 0/subop/add %esp ") -4436 (print-int32-buffered *(ebp+8) %eax) -4437 (write-buffered *(ebp+8) "/imm32\n") -4438 } -4439 # -4440 (pop *(ebp+0x10)) -4441 e9/jump loop/disp32 -4442 } -4443 $emit-subx-stmt-list:end: -4444 # . restore registers -4445 5e/pop-to-esi -4446 59/pop-to-ecx -4447 58/pop-to-eax -4448 # . epilogue -4449 89/<- %esp 5/r32/ebp -4450 5d/pop-to-ebp -4451 c3/return -4452 -4453 $emit-subx-stmt-list:abort-regvardef-without-register: -4454 # error("var '" var->name "' initialized from an instruction must live in a register\n") -4455 (write-buffered Stderr "var '") -4456 (write-buffered Stderr *eax) # Var-name -4457 (write-buffered Stderr "' initialized from an instruction must live in a register\n") -4458 (flush Stderr) -4459 # . syscall(exit, 1) -4460 bb/copy-to-ebx 1/imm32 -4461 b8/copy-to-eax 1/imm32/exit -4462 cd/syscall 0x80/imm8 -4463 # never gets here -4464 -4465 emit-subx-var-def: # out: (addr buffered-file), stmt: (handle statement) -4466 # . prologue -4467 55/push-ebp -4468 89/<- %ebp 4/r32/esp -4469 # . save registers -4470 50/push-eax -4471 51/push-ecx -4472 # eax = stmt -4473 8b/-> *(ebp+0xc) 0/r32/eax -4474 # var n/eax: int = size-of(stmt->var) -4475 (size-of *(eax+4)) # Vardef-var => eax -4476 # while n > 0 -4477 { -4478 3d/compare-eax-with 0/imm32 -4479 7e/jump-if-<= break/disp8 -4480 (write-buffered *(ebp+8) "68/push 0/imm32\n") -4481 # n -= 4 -4482 2d/subtract-from-eax 4/imm32 -4483 # -4484 eb/jump loop/disp8 -4485 } -4486 $emit-subx-var-def:end: -4487 # . restore registers -4488 59/pop-to-ecx -4489 58/pop-to-eax -4490 # . epilogue -4491 89/<- %esp 5/r32/ebp -4492 5d/pop-to-ebp -4493 c3/return -4494 -4495 emit-subx-statement: # out: (addr buffered-file), stmt: (handle statement), primitives: (handle primitive), functions: (handle function) -4496 # . prologue -4497 55/push-ebp -4498 89/<- %ebp 4/r32/esp -4499 # . save registers -4500 50/push-eax -4501 51/push-ecx -4502 # if stmt matches a primitive, emit it -4503 { -4504 $emit-subx-statement:check-for-primitive: -4505 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => curr/eax -4506 3d/compare-eax-and 0/imm32 -4507 74/jump-if-= break/disp8 -4508 $emit-subx-statement:primitive: -4509 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr -4510 e9/jump $emit-subx-statement:end/disp32 -4511 } -4512 # else if stmt matches a function, emit a call to it -4513 { -4514 $emit-subx-statement:check-for-call: -4515 (find-matching-function *(ebp+0x14) *(ebp+0xc)) # functions, stmt => curr/eax -4516 3d/compare-eax-and 0/imm32 -4517 74/jump-if-= break/disp8 -4518 $emit-subx-statement:call: -4519 (emit-subx-call *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr -4520 e9/jump $emit-subx-statement:end/disp32 -4521 } -4522 # else abort -4523 e9/jump $emit-subx-statement:abort/disp32 -4524 $emit-subx-statement:end: -4525 # . restore registers -4526 59/pop-to-ecx -4527 58/pop-to-eax -4528 # . epilogue -4529 89/<- %esp 5/r32/ebp -4530 5d/pop-to-ebp -4531 c3/return -4532 -4533 $emit-subx-statement:abort: -4534 # error("couldn't translate '" stmt "'\n") -4535 (write-buffered Stderr "couldn't translate an instruction with operation '") -4536 8b/-> *(ebp+0xc) 0/r32/eax -4537 (write-buffered Stderr *(eax+4)) # Stmt1-operation -4538 (write-buffered Stderr "'\n") -4539 (flush Stderr) -4540 # . syscall(exit, 1) -4541 bb/copy-to-ebx 1/imm32 -4542 b8/copy-to-eax 1/imm32/exit -4543 cd/syscall 0x80/imm8 -4544 # never gets here -4545 -4546 emit-subx-named-block: # out: (addr buffered-file), named-block: (handle named-block), vars: (addr stack (handle var)) -4547 # . prologue -4548 55/push-ebp -4549 89/<- %ebp 4/r32/esp -4550 # . save registers -4551 50/push-eax -4552 51/push-ecx -4553 56/push-esi -4554 # esi = block -4555 8b/-> *(ebp+0xc) 6/r32/esi -4556 # var stmts/ecx: (handle list statement) = block->statements -4557 8b/-> *(esi+4) 0/r32/eax # Block-statements -4558 # -4559 { -4560 $emit-subx-named-block:check-empty: -4561 81 7/subop/compare %eax 0/imm32 -4562 0f 84/jump-if-= break/disp32 -4563 (write-buffered *(ebp+8) "{\n") -4564 (write-buffered *(ebp+8) *(esi+8)) # Named-block-name -4565 (write-buffered *(ebp+8) "loop:\n") -4566 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10)) -4567 (write-buffered *(ebp+8) "}\n") -4568 (write-buffered *(ebp+8) *(esi+8)) # Named-block-name -4569 (write-buffered *(ebp+8) "break:\n") -4570 } -4571 $emit-subx-named-block:end: -4572 # . restore registers -4573 5e/pop-to-esi -4574 59/pop-to-ecx -4575 58/pop-to-eax -4576 # . epilogue -4577 89/<- %esp 5/r32/ebp -4578 5d/pop-to-ebp -4579 c3/return -4580 -4581 # Primitives supported -4582 # For each operation, put variants with hard-coded registers before flexible ones. -4583 == data -4584 Primitives: -4585 # - increment/decrement -4586 _Primitive-inc-eax: -4587 # var/eax <- increment => 40/increment-eax -4588 "increment"/imm32/name -4589 0/imm32/no-inouts -4590 Single-int-var-in-eax/imm32/outputs -4591 "40/increment-eax"/imm32/subx-name -4592 0/imm32/no-rm32 -4593 0/imm32/no-r32 -4594 0/imm32/no-imm32 -4595 0/imm32/no-disp32 -4596 0/imm32/output-is-write-only -4597 _Primitive-inc-ecx/imm32/next -4598 _Primitive-inc-ecx: -4599 # var/ecx <- increment => 41/increment-ecx -4600 "increment"/imm32/name -4601 0/imm32/no-inouts -4602 Single-int-var-in-ecx/imm32/outputs -4603 "41/increment-ecx"/imm32/subx-name -4604 0/imm32/no-rm32 -4605 0/imm32/no-r32 -4606 0/imm32/no-imm32 -4607 0/imm32/no-disp32 -4608 0/imm32/output-is-write-only -4609 _Primitive-inc-edx/imm32/next -4610 _Primitive-inc-edx: -4611 # var/edx <- increment => 42/increment-edx -4612 "increment"/imm32/name -4613 0/imm32/no-inouts -4614 Single-int-var-in-edx/imm32/outputs -4615 "42/increment-edx"/imm32/subx-name -4616 0/imm32/no-rm32 -4617 0/imm32/no-r32 -4618 0/imm32/no-imm32 -4619 0/imm32/no-disp32 -4620 0/imm32/output-is-write-only -4621 _Primitive-inc-ebx/imm32/next -4622 _Primitive-inc-ebx: -4623 # var/ebx <- increment => 43/increment-ebx -4624 "increment"/imm32/name -4625 0/imm32/no-inouts -4626 Single-int-var-in-ebx/imm32/outputs -4627 "43/increment-ebx"/imm32/subx-name -4628 0/imm32/no-rm32 -4629 0/imm32/no-r32 -4630 0/imm32/no-imm32 -4631 0/imm32/no-disp32 -4632 0/imm32/output-is-write-only -4633 _Primitive-inc-esi/imm32/next -4634 _Primitive-inc-esi: -4635 # var/esi <- increment => 46/increment-esi -4636 "increment"/imm32/name -4637 0/imm32/no-inouts -4638 Single-int-var-in-esi/imm32/outputs -4639 "46/increment-esi"/imm32/subx-name -4640 0/imm32/no-rm32 -4641 0/imm32/no-r32 -4642 0/imm32/no-imm32 -4643 0/imm32/no-disp32 -4644 0/imm32/output-is-write-only -4645 _Primitive-inc-edi/imm32/next -4646 _Primitive-inc-edi: -4647 # var/edi <- increment => 47/increment-edi -4648 "increment"/imm32/name -4649 0/imm32/no-inouts -4650 Single-int-var-in-edi/imm32/outputs -4651 "47/increment-edi"/imm32/subx-name -4652 0/imm32/no-rm32 -4653 0/imm32/no-r32 -4654 0/imm32/no-imm32 -4655 0/imm32/no-disp32 -4656 0/imm32/output-is-write-only -4657 _Primitive-dec-eax/imm32/next -4658 _Primitive-dec-eax: -4659 # var/eax <- decrement => 48/decrement-eax -4660 "decrement"/imm32/name -4661 0/imm32/no-inouts -4662 Single-int-var-in-eax/imm32/outputs -4663 "48/decrement-eax"/imm32/subx-name -4664 0/imm32/no-rm32 -4665 0/imm32/no-r32 -4666 0/imm32/no-imm32 -4667 0/imm32/no-disp32 -4668 0/imm32/output-is-write-only -4669 _Primitive-dec-ecx/imm32/next -4670 _Primitive-dec-ecx: -4671 # var/ecx <- decrement => 49/decrement-ecx -4672 "decrement"/imm32/name -4673 0/imm32/no-inouts -4674 Single-int-var-in-ecx/imm32/outputs -4675 "49/decrement-ecx"/imm32/subx-name -4676 0/imm32/no-rm32 -4677 0/imm32/no-r32 -4678 0/imm32/no-imm32 -4679 0/imm32/no-disp32 -4680 0/imm32/output-is-write-only -4681 _Primitive-dec-edx/imm32/next -4682 _Primitive-dec-edx: -4683 # var/edx <- decrement => 4a/decrement-edx -4684 "decrement"/imm32/name -4685 0/imm32/no-inouts -4686 Single-int-var-in-edx/imm32/outputs -4687 "4a/decrement-edx"/imm32/subx-name -4688 0/imm32/no-rm32 -4689 0/imm32/no-r32 -4690 0/imm32/no-imm32 -4691 0/imm32/no-disp32 -4692 0/imm32/output-is-write-only -4693 _Primitive-dec-ebx/imm32/next -4694 _Primitive-dec-ebx: -4695 # var/ebx <- decrement => 4b/decrement-ebx -4696 "decrement"/imm32/name -4697 0/imm32/no-inouts -4698 Single-int-var-in-ebx/imm32/outputs -4699 "4b/decrement-ebx"/imm32/subx-name -4700 0/imm32/no-rm32 -4701 0/imm32/no-r32 -4702 0/imm32/no-imm32 -4703 0/imm32/no-disp32 -4704 0/imm32/output-is-write-only -4705 _Primitive-dec-esi/imm32/next -4706 _Primitive-dec-esi: -4707 # var/esi <- decrement => 4e/decrement-esi -4708 "decrement"/imm32/name -4709 0/imm32/no-inouts -4710 Single-int-var-in-esi/imm32/outputs -4711 "4e/decrement-esi"/imm32/subx-name -4712 0/imm32/no-rm32 -4713 0/imm32/no-r32 -4714 0/imm32/no-imm32 -4715 0/imm32/no-disp32 -4716 0/imm32/output-is-write-only -4717 _Primitive-dec-edi/imm32/next -4718 _Primitive-dec-edi: -4719 # var/edi <- decrement => 4f/decrement-edi -4720 "decrement"/imm32/name -4721 0/imm32/no-inouts -4722 Single-int-var-in-edi/imm32/outputs -4723 "4f/decrement-edi"/imm32/subx-name -4724 0/imm32/no-rm32 -4725 0/imm32/no-r32 -4726 0/imm32/no-imm32 -4727 0/imm32/no-disp32 -4728 0/imm32/output-is-write-only -4729 _Primitive-inc-mem/imm32/next -4730 _Primitive-inc-mem: -4731 # increment var => ff 0/subop/increment *(ebp+__) -4732 "increment"/imm32/name -4733 Single-int-var-on-stack/imm32/inouts -4734 0/imm32/no-outputs -4735 "ff 0/subop/increment"/imm32/subx-name -4736 1/imm32/rm32-is-first-inout -4737 0/imm32/no-r32 -4738 0/imm32/no-imm32 -4739 0/imm32/no-disp32 -4740 0/imm32/output-is-write-only -4741 _Primitive-inc-reg/imm32/next -4742 _Primitive-inc-reg: -4743 # var/reg <- increment => ff 0/subop/increment %__ -4744 "increment"/imm32/name -4745 0/imm32/no-inouts -4746 Single-int-var-in-some-register/imm32/outputs -4747 "ff 0/subop/increment"/imm32/subx-name -4748 3/imm32/rm32-is-first-output -4749 0/imm32/no-r32 -4750 0/imm32/no-imm32 -4751 0/imm32/no-disp32 -4752 0/imm32/output-is-write-only -4753 _Primitive-dec-mem/imm32/next -4754 _Primitive-dec-mem: -4755 # decrement var => ff 1/subop/decrement *(ebp+__) -4756 "decrement"/imm32/name -4757 Single-int-var-on-stack/imm32/inouts -4758 0/imm32/no-outputs -4759 "ff 1/subop/decrement"/imm32/subx-name -4760 1/imm32/rm32-is-first-inout -4761 0/imm32/no-r32 -4762 0/imm32/no-imm32 -4763 0/imm32/no-disp32 -4764 0/imm32/output-is-write-only -4765 _Primitive-dec-reg/imm32/next -4766 _Primitive-dec-reg: -4767 # var/reg <- decrement => ff 1/subop/decrement %__ -4768 "decrement"/imm32/name -4769 0/imm32/no-inouts -4770 Single-int-var-in-some-register/imm32/outputs -4771 "ff 1/subop/decrement"/imm32/subx-name -4772 3/imm32/rm32-is-first-output -4773 0/imm32/no-r32 -4774 0/imm32/no-imm32 -4775 0/imm32/no-disp32 -4776 0/imm32/output-is-write-only -4777 _Primitive-add-to-eax/imm32/next -4778 # - add -4779 _Primitive-add-to-eax: -4780 # var/eax <- add lit => 05/add-to-eax lit/imm32 -4781 "add"/imm32/name -4782 Single-lit-var/imm32/inouts -4783 Single-int-var-in-eax/imm32/outputs -4784 "05/add-to-eax"/imm32/subx-name -4785 0/imm32/no-rm32 -4786 0/imm32/no-r32 -4787 1/imm32/imm32-is-first-inout -4788 0/imm32/no-disp32 -4789 0/imm32/output-is-write-only -4790 _Primitive-add-reg-to-reg/imm32/next -4791 _Primitive-add-reg-to-reg: -4792 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 -4793 "add"/imm32/name -4794 Single-int-var-in-some-register/imm32/inouts -4795 Single-int-var-in-some-register/imm32/outputs -4796 "01/add-to"/imm32/subx-name -4797 3/imm32/rm32-is-first-output -4798 1/imm32/r32-is-first-inout -4799 0/imm32/no-imm32 -4800 0/imm32/no-disp32 -4801 0/imm32/output-is-write-only -4802 _Primitive-add-reg-to-mem/imm32/next -4803 _Primitive-add-reg-to-mem: -4804 # add-to var1 var2/reg => 01/add-to var1 var2/r32 -4805 "add-to"/imm32/name -4806 Two-args-int-stack-int-reg/imm32/inouts -4807 0/imm32/outputs -4808 "01/add-to"/imm32/subx-name -4809 1/imm32/rm32-is-first-inout -4810 2/imm32/r32-is-second-inout -4811 0/imm32/no-imm32 -4812 0/imm32/no-disp32 -4813 0/imm32/output-is-write-only -4814 _Primitive-add-mem-to-reg/imm32/next -4815 _Primitive-add-mem-to-reg: -4816 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 -4817 "add"/imm32/name -4818 Single-int-var-on-stack/imm32/inouts -4819 Single-int-var-in-some-register/imm32/outputs -4820 "03/add"/imm32/subx-name -4821 1/imm32/rm32-is-first-inout -4822 3/imm32/r32-is-first-output -4823 0/imm32/no-imm32 -4824 0/imm32/no-disp32 -4825 0/imm32/output-is-write-only -4826 _Primitive-add-lit-to-reg/imm32/next -4827 _Primitive-add-lit-to-reg: -4828 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 -4829 "add"/imm32/name -4830 Single-lit-var/imm32/inouts -4831 Single-int-var-in-some-register/imm32/outputs -4832 "81 0/subop/add"/imm32/subx-name -4833 3/imm32/rm32-is-first-output -4834 0/imm32/no-r32 -4835 1/imm32/imm32-is-first-inout -4836 0/imm32/no-disp32 -4837 0/imm32/output-is-write-only -4838 _Primitive-add-lit-to-mem/imm32/next -4839 _Primitive-add-lit-to-mem: -4840 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 -4841 "add-to"/imm32/name -4842 Int-var-and-literal/imm32/inouts -4843 0/imm32/outputs -4844 "81 0/subop/add"/imm32/subx-name -4845 1/imm32/rm32-is-first-inout -4846 0/imm32/no-r32 -4847 2/imm32/imm32-is-second-inout -4848 0/imm32/no-disp32 -4849 0/imm32/output-is-write-only -4850 _Primitive-subtract-from-eax/imm32/next -4851 # - subtract -4852 _Primitive-subtract-from-eax: -4853 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 -4854 "subtract"/imm32/name -4855 Single-lit-var/imm32/inouts -4856 Single-int-var-in-eax/imm32/outputs -4857 "2d/subtract-from-eax"/imm32/subx-name -4858 0/imm32/no-rm32 -4859 0/imm32/no-r32 -4860 1/imm32/imm32-is-first-inout -4861 0/imm32/no-disp32 -4862 0/imm32/output-is-write-only -4863 _Primitive-subtract-reg-from-reg/imm32/next -4864 _Primitive-subtract-reg-from-reg: -4865 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 -4866 "subtract"/imm32/name -4867 Single-int-var-in-some-register/imm32/inouts -4868 Single-int-var-in-some-register/imm32/outputs -4869 "29/subtract-from"/imm32/subx-name -4870 3/imm32/rm32-is-first-output -4871 1/imm32/r32-is-first-inout -4872 0/imm32/no-imm32 -4873 0/imm32/no-disp32 -4874 0/imm32/output-is-write-only -4875 _Primitive-subtract-reg-from-mem/imm32/next -4876 _Primitive-subtract-reg-from-mem: -4877 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 -4878 "subtract-from"/imm32/name -4879 Two-args-int-stack-int-reg/imm32/inouts -4880 0/imm32/outputs -4881 "29/subtract-from"/imm32/subx-name -4882 1/imm32/rm32-is-first-inout -4883 2/imm32/r32-is-second-inout -4884 0/imm32/no-imm32 -4885 0/imm32/no-disp32 -4886 0/imm32/output-is-write-only -4887 _Primitive-subtract-mem-from-reg/imm32/next -4888 _Primitive-subtract-mem-from-reg: -4889 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 -4890 "subtract"/imm32/name -4891 Single-int-var-on-stack/imm32/inouts -4892 Single-int-var-in-some-register/imm32/outputs -4893 "2b/subtract"/imm32/subx-name -4894 1/imm32/rm32-is-first-inout -4895 3/imm32/r32-is-first-output -4896 0/imm32/no-imm32 -4897 0/imm32/no-disp32 -4898 0/imm32/output-is-write-only -4899 _Primitive-subtract-lit-from-reg/imm32/next -4900 _Primitive-subtract-lit-from-reg: -4901 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 -4902 "subtract"/imm32/name -4903 Single-lit-var/imm32/inouts -4904 Single-int-var-in-some-register/imm32/outputs -4905 "81 5/subop/subtract"/imm32/subx-name -4906 3/imm32/rm32-is-first-output -4907 0/imm32/no-r32 -4908 1/imm32/imm32-is-first-inout -4909 0/imm32/no-disp32 -4910 0/imm32/output-is-write-only -4911 _Primitive-subtract-lit-from-mem/imm32/next -4912 _Primitive-subtract-lit-from-mem: -4913 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 -4914 "subtract-from"/imm32/name -4915 Int-var-and-literal/imm32/inouts -4916 0/imm32/outputs -4917 "81 5/subop/subtract"/imm32/subx-name -4918 1/imm32/rm32-is-first-inout -4919 0/imm32/no-r32 -4920 2/imm32/imm32-is-first-inout -4921 0/imm32/no-disp32 -4922 0/imm32/output-is-write-only -4923 _Primitive-and-with-eax/imm32/next -4924 # - and -4925 _Primitive-and-with-eax: -4926 # var/eax <- and lit => 25/and-with-eax lit/imm32 -4927 "and"/imm32/name -4928 Single-lit-var/imm32/inouts -4929 Single-int-var-in-eax/imm32/outputs -4930 "25/and-with-eax"/imm32/subx-name -4931 0/imm32/no-rm32 -4932 0/imm32/no-r32 -4933 1/imm32/imm32-is-first-inout -4934 0/imm32/no-disp32 -4935 0/imm32/output-is-write-only -4936 _Primitive-and-reg-with-reg/imm32/next -4937 _Primitive-and-reg-with-reg: -4938 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 -4939 "and"/imm32/name -4940 Single-int-var-in-some-register/imm32/inouts -4941 Single-int-var-in-some-register/imm32/outputs -4942 "21/and-with"/imm32/subx-name -4943 3/imm32/rm32-is-first-output -4944 1/imm32/r32-is-first-inout -4945 0/imm32/no-imm32 -4946 0/imm32/no-disp32 -4947 0/imm32/output-is-write-only -4948 _Primitive-and-reg-with-mem/imm32/next -4949 _Primitive-and-reg-with-mem: -4950 # and-with var1 var2/reg => 21/and-with var1 var2/r32 -4951 "and-with"/imm32/name -4952 Two-args-int-stack-int-reg/imm32/inouts -4953 0/imm32/outputs -4954 "21/and-with"/imm32/subx-name -4955 1/imm32/rm32-is-first-inout -4956 2/imm32/r32-is-second-inout -4957 0/imm32/no-imm32 -4958 0/imm32/no-disp32 -4959 0/imm32/output-is-write-only -4960 _Primitive-and-mem-with-reg/imm32/next -4961 _Primitive-and-mem-with-reg: -4962 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 -4963 "and"/imm32/name -4964 Single-int-var-on-stack/imm32/inouts -4965 Single-int-var-in-some-register/imm32/outputs -4966 "23/and"/imm32/subx-name -4967 1/imm32/rm32-is-first-inout -4968 3/imm32/r32-is-first-output -4969 0/imm32/no-imm32 -4970 0/imm32/no-disp32 -4971 0/imm32/output-is-write-only -4972 _Primitive-and-lit-with-reg/imm32/next -4973 _Primitive-and-lit-with-reg: -4974 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 -4975 "and"/imm32/name -4976 Single-lit-var/imm32/inouts -4977 Single-int-var-in-some-register/imm32/outputs -4978 "81 4/subop/and"/imm32/subx-name -4979 3/imm32/rm32-is-first-output -4980 0/imm32/no-r32 -4981 1/imm32/imm32-is-first-inout -4982 0/imm32/no-disp32 -4983 0/imm32/output-is-write-only -4984 _Primitive-and-lit-with-mem/imm32/next -4985 _Primitive-and-lit-with-mem: -4986 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 -4987 "and-with"/imm32/name -4988 Int-var-and-literal/imm32/inouts -4989 0/imm32/outputs -4990 "81 4/subop/and"/imm32/subx-name -4991 1/imm32/rm32-is-first-inout -4992 0/imm32/no-r32 -4993 2/imm32/imm32-is-first-inout -4994 0/imm32/no-disp32 -4995 0/imm32/output-is-write-only -4996 _Primitive-or-with-eax/imm32/next -4997 # - or -4998 _Primitive-or-with-eax: -4999 # var/eax <- or lit => 0d/or-with-eax lit/imm32 -5000 "or"/imm32/name -5001 Single-lit-var/imm32/inouts -5002 Single-int-var-in-eax/imm32/outputs -5003 "0d/or-with-eax"/imm32/subx-name -5004 0/imm32/no-rm32 -5005 0/imm32/no-r32 -5006 1/imm32/imm32-is-first-inout -5007 0/imm32/no-disp32 -5008 0/imm32/output-is-write-only -5009 _Primitive-or-reg-with-reg/imm32/next -5010 _Primitive-or-reg-with-reg: -5011 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 -5012 "or"/imm32/name -5013 Single-int-var-in-some-register/imm32/inouts -5014 Single-int-var-in-some-register/imm32/outputs -5015 "09/or-with"/imm32/subx-name -5016 3/imm32/rm32-is-first-output -5017 1/imm32/r32-is-first-inout -5018 0/imm32/no-imm32 -5019 0/imm32/no-disp32 -5020 0/imm32/output-is-write-only -5021 _Primitive-or-reg-with-mem/imm32/next -5022 _Primitive-or-reg-with-mem: -5023 # or-with var1 var2/reg => 09/or-with var1 var2/r32 -5024 "or-with"/imm32/name -5025 Two-args-int-stack-int-reg/imm32/inouts -5026 0/imm32/outputs -5027 "09/or-with"/imm32/subx-name -5028 1/imm32/rm32-is-first-inout -5029 2/imm32/r32-is-second-inout -5030 0/imm32/no-imm32 -5031 0/imm32/no-disp32 -5032 0/imm32/output-is-write-only -5033 _Primitive-or-mem-with-reg/imm32/next -5034 _Primitive-or-mem-with-reg: -5035 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 -5036 "or"/imm32/name -5037 Single-int-var-on-stack/imm32/inouts -5038 Single-int-var-in-some-register/imm32/outputs -5039 "0b/or"/imm32/subx-name -5040 1/imm32/rm32-is-first-inout -5041 3/imm32/r32-is-first-output -5042 0/imm32/no-imm32 -5043 0/imm32/no-disp32 -5044 0/imm32/output-is-write-only -5045 _Primitive-or-lit-with-reg/imm32/next -5046 _Primitive-or-lit-with-reg: -5047 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 -5048 "or"/imm32/name -5049 Single-lit-var/imm32/inouts -5050 Single-int-var-in-some-register/imm32/outputs -5051 "81 1/subop/or"/imm32/subx-name -5052 3/imm32/rm32-is-first-output -5053 0/imm32/no-r32 -5054 1/imm32/imm32-is-first-inout -5055 0/imm32/no-disp32 -5056 0/imm32/output-is-write-only -5057 _Primitive-or-lit-with-mem/imm32/next -5058 _Primitive-or-lit-with-mem: -5059 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 -5060 "or-with"/imm32/name -5061 Int-var-and-literal/imm32/inouts -5062 0/imm32/outputs -5063 "81 1/subop/or"/imm32/subx-name -5064 1/imm32/rm32-is-first-inout -5065 0/imm32/no-r32 -5066 2/imm32/imm32-is-second-inout -5067 0/imm32/no-disp32 -5068 0/imm32/output-is-write-only -5069 _Primitive-xor-with-eax/imm32/next -5070 # - xor -5071 _Primitive-xor-with-eax: -5072 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 -5073 "xor"/imm32/name -5074 Single-lit-var/imm32/inouts -5075 Single-int-var-in-eax/imm32/outputs -5076 "35/xor-with-eax"/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 0/imm32/output-is-write-only -5082 _Primitive-xor-reg-with-reg/imm32/next -5083 _Primitive-xor-reg-with-reg: -5084 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 -5085 "xor"/imm32/name -5086 Single-int-var-in-some-register/imm32/inouts -5087 Single-int-var-in-some-register/imm32/outputs -5088 "31/xor-with"/imm32/subx-name -5089 3/imm32/rm32-is-first-output -5090 1/imm32/r32-is-first-inout -5091 0/imm32/no-imm32 -5092 0/imm32/no-disp32 -5093 0/imm32/output-is-write-only -5094 _Primitive-xor-reg-with-mem/imm32/next -5095 _Primitive-xor-reg-with-mem: -5096 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 -5097 "xor-with"/imm32/name -5098 Two-args-int-stack-int-reg/imm32/inouts -5099 0/imm32/outputs -5100 "31/xor-with"/imm32/subx-name -5101 1/imm32/rm32-is-first-inout -5102 2/imm32/r32-is-second-inout -5103 0/imm32/no-imm32 -5104 0/imm32/no-disp32 -5105 0/imm32/output-is-write-only -5106 _Primitive-xor-mem-with-reg/imm32/next -5107 _Primitive-xor-mem-with-reg: -5108 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 -5109 "xor"/imm32/name -5110 Single-int-var-on-stack/imm32/inouts -5111 Single-int-var-in-some-register/imm32/outputs -5112 "33/xor"/imm32/subx-name -5113 1/imm32/rm32-is-first-inout -5114 3/imm32/r32-is-first-output -5115 0/imm32/no-imm32 -5116 0/imm32/no-disp32 -5117 0/imm32/output-is-write-only -5118 _Primitive-xor-lit-with-reg/imm32/next -5119 _Primitive-xor-lit-with-reg: -5120 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 -5121 "xor"/imm32/name -5122 Single-lit-var/imm32/inouts -5123 Single-int-var-in-some-register/imm32/outputs -5124 "81 6/subop/xor"/imm32/subx-name -5125 3/imm32/rm32-is-first-output -5126 0/imm32/no-r32 -5127 1/imm32/imm32-is-first-inout -5128 0/imm32/no-disp32 -5129 0/imm32/output-is-write-only -5130 _Primitive-xor-lit-with-mem/imm32/next -5131 _Primitive-xor-lit-with-mem: -5132 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 -5133 "xor-with"/imm32/name -5134 Int-var-and-literal/imm32/inouts -5135 0/imm32/outputs -5136 "81 6/subop/xor"/imm32/subx-name -5137 1/imm32/rm32-is-first-inout -5138 0/imm32/no-r32 -5139 2/imm32/imm32-is-first-inout -5140 0/imm32/no-disp32 -5141 0/imm32/output-is-write-only -5142 _Primitive-copy-to-eax/imm32/next -5143 # - copy -5144 _Primitive-copy-to-eax: -5145 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 -5146 "copy"/imm32/name -5147 Single-lit-var/imm32/inouts -5148 Single-int-var-in-eax/imm32/outputs -5149 "b8/copy-to-eax"/imm32/subx-name -5150 0/imm32/no-rm32 -5151 0/imm32/no-r32 -5152 1/imm32/imm32-is-first-inout -5153 0/imm32/no-disp32 -5154 1/imm32/output-is-write-only -5155 _Primitive-copy-to-ecx/imm32/next -5156 _Primitive-copy-to-ecx: -5157 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 -5158 "copy"/imm32/name -5159 Single-lit-var/imm32/inouts -5160 Single-int-var-in-ecx/imm32/outputs -5161 "b9/copy-to-ecx"/imm32/subx-name -5162 0/imm32/no-rm32 -5163 0/imm32/no-r32 -5164 1/imm32/imm32-is-first-inout -5165 0/imm32/no-disp32 -5166 1/imm32/output-is-write-only -5167 _Primitive-copy-to-edx/imm32/next -5168 _Primitive-copy-to-edx: -5169 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 -5170 "copy"/imm32/name -5171 Single-lit-var/imm32/inouts -5172 Single-int-var-in-edx/imm32/outputs -5173 "ba/copy-to-edx"/imm32/subx-name -5174 0/imm32/no-rm32 -5175 0/imm32/no-r32 -5176 1/imm32/imm32-is-first-inout -5177 0/imm32/no-disp32 -5178 1/imm32/output-is-write-only -5179 _Primitive-copy-to-ebx/imm32/next -5180 _Primitive-copy-to-ebx: -5181 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 -5182 "copy"/imm32/name -5183 Single-lit-var/imm32/inouts -5184 Single-int-var-in-ebx/imm32/outputs -5185 "bb/copy-to-ebx"/imm32/subx-name -5186 0/imm32/no-rm32 -5187 0/imm32/no-r32 -5188 1/imm32/imm32-is-first-inout -5189 0/imm32/no-disp32 -5190 1/imm32/output-is-write-only -5191 _Primitive-copy-to-esi/imm32/next -5192 _Primitive-copy-to-esi: -5193 # var/esi <- copy lit => be/copy-to-esi lit/imm32 -5194 "copy"/imm32/name -5195 Single-lit-var/imm32/inouts -5196 Single-int-var-in-esi/imm32/outputs -5197 "be/copy-to-esi"/imm32/subx-name -5198 0/imm32/no-rm32 -5199 0/imm32/no-r32 -5200 1/imm32/imm32-is-first-inout -5201 0/imm32/no-disp32 -5202 1/imm32/output-is-write-only -5203 _Primitive-copy-to-edi/imm32/next -5204 _Primitive-copy-to-edi: -5205 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 -5206 "copy"/imm32/name -5207 Single-lit-var/imm32/inouts -5208 Single-int-var-in-edi/imm32/outputs -5209 "bf/copy-to-edi"/imm32/subx-name -5210 0/imm32/no-rm32 -5211 0/imm32/no-r32 -5212 1/imm32/imm32-is-first-inout -5213 0/imm32/no-disp32 -5214 1/imm32/output-is-write-only -5215 _Primitive-copy-reg-to-reg/imm32/next -5216 _Primitive-copy-reg-to-reg: -5217 # var1/reg <- copy var2/reg => 89/copy-to var1/rm32 var2/r32 -5218 "copy"/imm32/name -5219 Single-int-var-in-some-register/imm32/inouts -5220 Single-int-var-in-some-register/imm32/outputs -5221 "89/copy-to"/imm32/subx-name -5222 3/imm32/rm32-is-first-output -5223 1/imm32/r32-is-first-inout -5224 0/imm32/no-imm32 -5225 0/imm32/no-disp32 -5226 1/imm32/output-is-write-only -5227 _Primitive-copy-reg-to-mem/imm32/next -5228 _Primitive-copy-reg-to-mem: -5229 # copy-to var1 var2/reg => 89/copy-to var1 var2/r32 -5230 "copy-to"/imm32/name -5231 Two-args-int-stack-int-reg/imm32/inouts -5232 0/imm32/outputs -5233 "89/copy-to"/imm32/subx-name -5234 1/imm32/rm32-is-first-inout -5235 2/imm32/r32-is-second-inout -5236 0/imm32/no-imm32 -5237 0/imm32/no-disp32 -5238 1/imm32/output-is-write-only -5239 _Primitive-copy-mem-to-reg/imm32/next -5240 _Primitive-copy-mem-to-reg: -5241 # var1/reg <- copy var2 => 8b/copy-from var2/rm32 var1/r32 -5242 "copy"/imm32/name -5243 Single-int-var-on-stack/imm32/inouts -5244 Single-int-var-in-some-register/imm32/outputs -5245 "8b/copy-from"/imm32/subx-name -5246 1/imm32/rm32-is-first-inout -5247 3/imm32/r32-is-first-output -5248 0/imm32/no-imm32 -5249 0/imm32/no-disp32 -5250 1/imm32/output-is-write-only -5251 _Primitive-copy-lit-to-reg/imm32/next -5252 _Primitive-copy-lit-to-reg: -5253 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 -5254 "copy"/imm32/name -5255 Single-lit-var/imm32/inouts -5256 Single-int-var-in-some-register/imm32/outputs -5257 "c7 0/subop/copy"/imm32/subx-name -5258 3/imm32/rm32-is-first-output -5259 0/imm32/no-r32 -5260 1/imm32/imm32-is-first-inout -5261 0/imm32/no-disp32 -5262 1/imm32/output-is-write-only -5263 _Primitive-copy-lit-to-mem/imm32/next -5264 _Primitive-copy-lit-to-mem: -5265 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 -5266 "copy-to"/imm32/name -5267 Int-var-and-literal/imm32/inouts -5268 0/imm32/outputs -5269 "c7 0/subop/copy"/imm32/subx-name -5270 1/imm32/rm32-is-first-inout -5271 0/imm32/no-r32 -5272 2/imm32/imm32-is-first-inout -5273 0/imm32/no-disp32 -5274 1/imm32/output-is-write-only -5275 _Primitive-compare-mem-with-reg/imm32/next -5276 # - compare -5277 _Primitive-compare-mem-with-reg: -5278 # compare var1 var2/reg => 39/compare-> var1/rm32 var2/r32 -5279 "compare"/imm32/name -5280 Two-args-int-stack-int-reg/imm32/inouts -5281 0/imm32/outputs -5282 "39/compare->"/imm32/subx-name -5283 1/imm32/rm32-is-first-inout -5284 2/imm32/r32-is-second-inout -5285 0/imm32/no-imm32 -5286 0/imm32/no-disp32 -5287 0/imm32/output-is-write-only -5288 _Primitive-compare-reg-with-mem/imm32/next -5289 _Primitive-compare-reg-with-mem: -5290 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 -5291 "compare"/imm32/name -5292 Two-args-int-reg-int-stack/imm32/inouts -5293 0/imm32/outputs -5294 "3b/compare<-"/imm32/subx-name -5295 2/imm32/rm32-is-second-inout -5296 1/imm32/r32-is-first-inout -5297 0/imm32/no-imm32 -5298 0/imm32/no-disp32 -5299 0/imm32/output-is-write-only -5300 _Primitive-compare-eax-with-literal/imm32/next -5301 _Primitive-compare-eax-with-literal: -5302 # compare var1/eax n => 3d/compare-eax-with n/imm32 -5303 "compare"/imm32/name -5304 Two-args-int-eax-int-literal/imm32/inouts -5305 0/imm32/outputs -5306 "3d/compare-eax-with"/imm32/subx-name -5307 0/imm32/no-rm32 -5308 0/imm32/no-r32 -5309 2/imm32/imm32-is-second-inout -5310 0/imm32/no-disp32 -5311 0/imm32/output-is-write-only -5312 _Primitive-compare-regmem-with-literal/imm32/next -5313 _Primitive-compare-regmem-with-literal: -5314 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 -5315 "compare"/imm32/name -5316 Int-var-and-literal/imm32/inouts -5317 0/imm32/outputs -5318 "81 7/subop/compare"/imm32/subx-name -5319 1/imm32/rm32-is-first-inout -5320 0/imm32/no-r32 -5321 2/imm32/imm32-is-second-inout -5322 0/imm32/no-disp32 -5323 0/imm32/output-is-write-only -5324 _Primitive-multiply-reg-by-mem/imm32/next -5325 # - multiply -5326 _Primitive-multiply-reg-by-mem: -5327 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 -5328 "multiply"/imm32/name -5329 Single-int-var-on-stack/imm32/inouts -5330 Single-int-var-in-some-register/imm32/outputs -5331 "0f af/multiply"/imm32/subx-name -5332 1/imm32/rm32-is-first-inout -5333 3/imm32/r32-is-first-output -5334 0/imm32/no-imm32 -5335 0/imm32/no-disp32 -5336 0/imm32/output-is-write-only -5337 _Primitive-break-if-addr</imm32/next -5338 # - branches -5339 _Primitive-break-if-addr<: -5340 "break-if-addr<"/imm32/name -5341 0/imm32/inouts -5342 0/imm32/outputs -5343 "0f 82/jump-if-addr< break/disp32"/imm32/subx-name -5344 0/imm32/no-rm32 -5345 0/imm32/no-r32 -5346 0/imm32/no-imm32 -5347 0/imm32/no-disp32 -5348 0/imm32/no-output -5349 _Primitive-break-if-addr>=/imm32/next -5350 _Primitive-break-if-addr>=: -5351 "break-if-addr>="/imm32/name -5352 0/imm32/inouts -5353 0/imm32/outputs -5354 "0f 83/jump-if-addr>= break/disp32"/imm32/subx-name -5355 0/imm32/no-rm32 -5356 0/imm32/no-r32 -5357 0/imm32/no-imm32 -5358 0/imm32/no-disp32 -5359 0/imm32/no-output -5360 _Primitive-break-if-=/imm32/next -5361 _Primitive-break-if-=: -5362 "break-if-="/imm32/name -5363 0/imm32/inouts -5364 0/imm32/outputs -5365 "0f 84/jump-if-= break/disp32"/imm32/subx-name -5366 0/imm32/no-rm32 -5367 0/imm32/no-r32 -5368 0/imm32/no-imm32 -5369 0/imm32/no-disp32 -5370 0/imm32/no-output -5371 _Primitive-break-if-!=/imm32/next -5372 _Primitive-break-if-!=: -5373 "break-if-!="/imm32/name -5374 0/imm32/inouts -5375 0/imm32/outputs -5376 "0f 85/jump-if-!= break/disp32"/imm32/subx-name -5377 0/imm32/no-rm32 -5378 0/imm32/no-r32 -5379 0/imm32/no-imm32 -5380 0/imm32/no-disp32 -5381 0/imm32/no-output -5382 _Primitive-break-if-addr<=/imm32/next -5383 _Primitive-break-if-addr<=: -5384 "break-if-addr<="/imm32/name -5385 0/imm32/inouts -5386 0/imm32/outputs -5387 "0f 86/jump-if-addr<= break/disp32"/imm32/subx-name -5388 0/imm32/no-rm32 -5389 0/imm32/no-r32 -5390 0/imm32/no-imm32 -5391 0/imm32/no-disp32 -5392 0/imm32/no-output -5393 _Primitive-break-if-addr>/imm32/next -5394 _Primitive-break-if-addr>: -5395 "break-if-addr>"/imm32/name -5396 0/imm32/inouts -5397 0/imm32/outputs -5398 "0f 87/jump-if-addr> break/disp32"/imm32/subx-name -5399 0/imm32/no-rm32 -5400 0/imm32/no-r32 -5401 0/imm32/no-imm32 -5402 0/imm32/no-disp32 -5403 0/imm32/no-output -5404 _Primitive-break-if-</imm32/next -5405 _Primitive-break-if-<: -5406 "break-if-<"/imm32/name -5407 0/imm32/inouts -5408 0/imm32/outputs -5409 "0f 8c/jump-if-< break/disp32"/imm32/subx-name -5410 0/imm32/no-rm32 -5411 0/imm32/no-r32 +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 +5314 0/imm32/no-r32 +5315 1/imm32/imm32-is-first-inout +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 0/imm32/no-output -5415 _Primitive-break-if->=/imm32/next -5416 _Primitive-break-if->=: -5417 "break-if->="/imm32/name -5418 0/imm32/inouts -5419 0/imm32/outputs -5420 "0f 8d/jump-if->= break/disp32"/imm32/subx-name -5421 0/imm32/no-rm32 -5422 0/imm32/no-r32 -5423 0/imm32/no-imm32 -5424 0/imm32/no-disp32 -5425 0/imm32/no-output -5426 _Primitive-break-if-<=/imm32/next -5427 _Primitive-break-if-<=: -5428 "break-if-<="/imm32/name -5429 0/imm32/inouts -5430 0/imm32/outputs -5431 "0f 8e/jump-if-<= break/disp32"/imm32/subx-name -5432 0/imm32/no-rm32 -5433 0/imm32/no-r32 -5434 0/imm32/no-imm32 -5435 0/imm32/no-disp32 -5436 0/imm32/no-output -5437 _Primitive-break-if->/imm32/next -5438 _Primitive-break-if->: -5439 "break-if->"/imm32/name -5440 0/imm32/inouts -5441 0/imm32/outputs -5442 "0f 8f/jump-if-> break/disp32"/imm32/subx-name -5443 0/imm32/no-rm32 -5444 0/imm32/no-r32 -5445 0/imm32/no-imm32 -5446 0/imm32/no-disp32 -5447 0/imm32/no-output -5448 _Primitive-loop-if-addr</imm32/next -5449 _Primitive-loop-if-addr<: -5450 "loop-if-addr<"/imm32/name -5451 0/imm32/inouts -5452 0/imm32/outputs -5453 "0f 82/jump-if-addr< loop/disp32"/imm32/subx-name -5454 0/imm32/no-rm32 -5455 0/imm32/no-r32 -5456 0/imm32/no-imm32 -5457 0/imm32/no-disp32 -5458 0/imm32/no-output -5459 _Primitive-loop-if-addr>=/imm32/next -5460 _Primitive-loop-if-addr>=: -5461 "loop-if-addr>="/imm32/name -5462 0/imm32/inouts -5463 0/imm32/outputs -5464 "0f 83/jump-if-addr>= loop/disp32"/imm32/subx-name -5465 0/imm32/no-rm32 -5466 0/imm32/no-r32 -5467 0/imm32/no-imm32 -5468 0/imm32/no-disp32 -5469 0/imm32/no-output -5470 _Primitive-loop-if-=/imm32/next -5471 _Primitive-loop-if-=: -5472 "loop-if-="/imm32/name -5473 0/imm32/inouts -5474 0/imm32/outputs -5475 "0f 84/jump-if-= loop/disp32"/imm32/subx-name -5476 0/imm32/no-rm32 -5477 0/imm32/no-r32 -5478 0/imm32/no-imm32 -5479 0/imm32/no-disp32 -5480 0/imm32/no-output -5481 _Primitive-loop-if-!=/imm32/next -5482 _Primitive-loop-if-!=: -5483 "loop-if-!="/imm32/name -5484 0/imm32/inouts -5485 0/imm32/outputs -5486 "0f 85/jump-if-!= loop/disp32"/imm32/subx-name -5487 0/imm32/no-rm32 -5488 0/imm32/no-r32 -5489 0/imm32/no-imm32 -5490 0/imm32/no-disp32 -5491 0/imm32/no-output -5492 _Primitive-loop-if-addr<=/imm32/next -5493 _Primitive-loop-if-addr<=: -5494 "loop-if-addr<="/imm32/name -5495 0/imm32/inouts -5496 0/imm32/outputs -5497 "0f 86/jump-if-addr<= loop/disp32"/imm32/subx-name -5498 0/imm32/no-rm32 -5499 0/imm32/no-r32 -5500 0/imm32/no-imm32 -5501 0/imm32/no-disp32 -5502 0/imm32/no-output -5503 _Primitive-loop-if-addr>/imm32/next -5504 _Primitive-loop-if-addr>: -5505 "loop-if-addr>"/imm32/name -5506 0/imm32/inouts -5507 0/imm32/outputs -5508 "0f 87/jump-if-addr> loop/disp32"/imm32/subx-name -5509 0/imm32/no-rm32 -5510 0/imm32/no-r32 -5511 0/imm32/no-imm32 -5512 0/imm32/no-disp32 -5513 0/imm32/no-output -5514 _Primitive-loop-if-</imm32/next -5515 _Primitive-loop-if-<: -5516 "loop-if-<"/imm32/name -5517 0/imm32/inouts -5518 0/imm32/outputs -5519 "0f 8c/jump-if-< loop/disp32"/imm32/subx-name -5520 0/imm32/no-rm32 -5521 0/imm32/no-r32 +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 +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/no-output -5525 _Primitive-loop-if->=/imm32/next -5526 _Primitive-loop-if->=: -5527 "loop-if->="/imm32/name -5528 0/imm32/inouts -5529 0/imm32/outputs -5530 "0f 8d/jump-if->= loop/disp32"/imm32/subx-name -5531 0/imm32/no-rm32 -5532 0/imm32/no-r32 -5533 0/imm32/no-imm32 -5534 0/imm32/no-disp32 -5535 0/imm32/no-output -5536 _Primitive-loop-if-<=/imm32/next -5537 _Primitive-loop-if-<=: -5538 "loop-if-<="/imm32/name -5539 0/imm32/inouts -5540 0/imm32/outputs -5541 "0f 8e/jump-if-<= loop/disp32"/imm32/subx-name -5542 0/imm32/no-rm32 -5543 0/imm32/no-r32 -5544 0/imm32/no-imm32 -5545 0/imm32/no-disp32 -5546 0/imm32/no-output -5547 _Primitive-loop-if->/imm32/next -5548 _Primitive-loop-if->: -5549 "loop-if->"/imm32/name -5550 0/imm32/inouts -5551 0/imm32/outputs -5552 "0f 8f/jump-if-> loop/disp32"/imm32/subx-name -5553 0/imm32/no-rm32 -5554 0/imm32/no-r32 -5555 0/imm32/no-imm32 -5556 0/imm32/no-disp32 -5557 0/imm32/no-output -5558 _Primitive-loop/imm32/next # we probably don't need an unconditional break -5559 _Primitive-loop: -5560 "loop"/imm32/name -5561 0/imm32/inouts -5562 0/imm32/outputs -5563 "e9/jump loop/disp32"/imm32/subx-name -5564 0/imm32/no-rm32 -5565 0/imm32/no-r32 -5566 0/imm32/no-imm32 -5567 0/imm32/no-disp32 -5568 0/imm32/no-output -5569 _Primitive-break-if-addr<-named/imm32/next -5570 # - branches to named blocks -5571 _Primitive-break-if-addr<-named: -5572 "break-if-addr<"/imm32/name -5573 Single-lit-var/imm32/inouts +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 82/jump-if-addr<"/imm32/subx-name +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 1/imm32/disp32-is-first-inout +5579 0/imm32/no-disp32 5580 0/imm32/no-output -5581 _Primitive-break-if-addr>=-named/imm32/next -5582 _Primitive-break-if-addr>=-named: -5583 "break-if-addr>="/imm32/name -5584 Single-lit-var/imm32/inouts +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 83/jump-if-addr>="/imm32/subx-name +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 1/imm32/disp32-is-first-inout +5590 0/imm32/no-disp32 5591 0/imm32/no-output -5592 _Primitive-break-if-=-named/imm32/next -5593 _Primitive-break-if-=-named: -5594 "break-if-="/imm32/name -5595 Single-lit-var/imm32/inouts +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 84/jump-if-="/imm32/subx-name +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 1/imm32/disp32-is-first-inout +5601 0/imm32/no-disp32 5602 0/imm32/no-output -5603 _Primitive-break-if-!=-named/imm32/next -5604 _Primitive-break-if-!=-named: -5605 "break-if-!="/imm32/name -5606 Single-lit-var/imm32/inouts +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 85/jump-if-!="/imm32/subx-name +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 1/imm32/disp32-is-first-inout +5612 0/imm32/no-disp32 5613 0/imm32/no-output -5614 _Primitive-break-if-addr<=-named/imm32/next -5615 _Primitive-break-if-addr<=-named: -5616 "break-if-addr<="/imm32/name -5617 Single-lit-var/imm32/inouts +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 86/jump-if-addr<="/imm32/subx-name +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 1/imm32/disp32-is-first-inout +5623 0/imm32/no-disp32 5624 0/imm32/no-output -5625 _Primitive-break-if-addr>-named/imm32/next -5626 _Primitive-break-if-addr>-named: -5627 "break-if-addr>"/imm32/name -5628 Single-lit-var/imm32/inouts +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 87/jump-if-addr>"/imm32/subx-name +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 1/imm32/disp32-is-first-inout +5634 0/imm32/no-disp32 5635 0/imm32/no-output -5636 _Primitive-break-if-<-named/imm32/next -5637 _Primitive-break-if-<-named: -5638 "break-if-<"/imm32/name -5639 Single-lit-var/imm32/inouts +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 8c/jump-if-<"/imm32/subx-name +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 1/imm32/disp32-is-first-inout +5645 0/imm32/no-disp32 5646 0/imm32/no-output -5647 _Primitive-break-if->=-named/imm32/next -5648 _Primitive-break-if->=-named: -5649 "break-if->="/imm32/name -5650 Single-lit-var/imm32/inouts +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 8d/jump-if->="/imm32/subx-name +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 1/imm32/disp32-is-first-inout +5656 0/imm32/no-disp32 5657 0/imm32/no-output -5658 _Primitive-break-if-<=-named/imm32/next -5659 _Primitive-break-if-<=-named: -5660 "break-if-<="/imm32/name -5661 Single-lit-var/imm32/inouts +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 8e/jump-if-<="/imm32/subx-name +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 1/imm32/disp32-is-first-inout +5667 0/imm32/no-disp32 5668 0/imm32/no-output -5669 _Primitive-break-if->-named/imm32/next -5670 _Primitive-break-if->-named: -5671 "break-if->"/imm32/name -5672 Single-lit-var/imm32/inouts +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 8f/jump-if->"/imm32/subx-name +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 1/imm32/disp32-is-first-inout +5678 0/imm32/no-disp32 5679 0/imm32/no-output -5680 _Primitive-loop-if-addr<-named/imm32/next -5681 _Primitive-loop-if-addr<-named: -5682 "loop-if-addr<"/imm32/name -5683 Single-lit-var/imm32/inouts +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 82/jump-if-addr<"/imm32/subx-name +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 1/imm32/disp32-is-first-inout +5689 0/imm32/no-disp32 5690 0/imm32/no-output -5691 _Primitive-loop-if-addr>=-named/imm32/next -5692 _Primitive-loop-if-addr>=-named: -5693 "loop-if-addr>="/imm32/name -5694 Single-lit-var/imm32/inouts +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 83/jump-if-addr>="/imm32/subx-name +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 1/imm32/disp32-is-first-inout +5700 0/imm32/no-disp32 5701 0/imm32/no-output -5702 _Primitive-loop-if-=-named/imm32/next -5703 _Primitive-loop-if-=-named: -5704 "loop-if-="/imm32/name -5705 Single-lit-var/imm32/inouts +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 84/jump-if-="/imm32/subx-name +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 1/imm32/disp32-is-first-inout +5711 0/imm32/no-disp32 5712 0/imm32/no-output -5713 _Primitive-loop-if-!=-named/imm32/next -5714 _Primitive-loop-if-!=-named: -5715 "loop-if-!="/imm32/name -5716 Single-lit-var/imm32/inouts +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 85/jump-if-!="/imm32/subx-name +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 1/imm32/disp32-is-first-inout +5722 0/imm32/no-disp32 5723 0/imm32/no-output -5724 _Primitive-loop-if-addr<=-named/imm32/next -5725 _Primitive-loop-if-addr<=-named: -5726 "loop-if-addr<="/imm32/name -5727 Single-lit-var/imm32/inouts +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 86/jump-if-addr<="/imm32/subx-name +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 1/imm32/disp32-is-first-inout +5733 0/imm32/no-disp32 5734 0/imm32/no-output -5735 _Primitive-loop-if-addr>-named/imm32/next -5736 _Primitive-loop-if-addr>-named: -5737 "loop-if-addr>"/imm32/name -5738 Single-lit-var/imm32/inouts +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 87/jump-if-addr>"/imm32/subx-name +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 1/imm32/disp32-is-first-inout +5744 0/imm32/no-disp32 5745 0/imm32/no-output -5746 _Primitive-loop-if-<-named/imm32/next -5747 _Primitive-loop-if-<-named: -5748 "loop-if-<"/imm32/name -5749 Single-lit-var/imm32/inouts +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 "0f 8c/jump-if-<"/imm32/subx-name +5751 "e9/jump loop/disp32"/imm32/subx-name 5752 0/imm32/no-rm32 5753 0/imm32/no-r32 5754 0/imm32/no-imm32 -5755 1/imm32/disp32-is-first-inout +5755 0/imm32/no-disp32 5756 0/imm32/no-output -5757 _Primitive-loop-if->=-named/imm32/next -5758 _Primitive-loop-if->=-named: -5759 "loop-if->="/imm32/name -5760 Single-lit-var/imm32/inouts -5761 0/imm32/outputs -5762 "0f 8d/jump-if->="/imm32/subx-name -5763 0/imm32/no-rm32 -5764 0/imm32/no-r32 -5765 0/imm32/no-imm32 -5766 1/imm32/disp32-is-first-inout -5767 0/imm32/no-output -5768 _Primitive-loop-if-<=-named/imm32/next -5769 _Primitive-loop-if-<=-named: -5770 "loop-if-<="/imm32/name -5771 Single-lit-var/imm32/inouts -5772 0/imm32/outputs -5773 "0f 8e/jump-if-<="/imm32/subx-name -5774 0/imm32/no-rm32 -5775 0/imm32/no-r32 -5776 0/imm32/no-imm32 -5777 1/imm32/disp32-is-first-inout -5778 0/imm32/no-output -5779 _Primitive-loop-if->-named/imm32/next -5780 _Primitive-loop-if->-named: -5781 "loop-if->"/imm32/name -5782 Single-lit-var/imm32/inouts -5783 0/imm32/outputs -5784 "0f 8f/jump-if->"/imm32/subx-name -5785 0/imm32/no-rm32 -5786 0/imm32/no-r32 -5787 0/imm32/no-imm32 -5788 1/imm32/disp32-is-first-inout -5789 0/imm32/no-output -5790 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break -5791 _Primitive-loop-named: -5792 "loop"/imm32/name -5793 Single-lit-var/imm32/inouts -5794 0/imm32/outputs -5795 "e9/jump"/imm32/subx-name -5796 0/imm32/no-rm32 -5797 0/imm32/no-r32 -5798 0/imm32/no-imm32 -5799 1/imm32/disp32-is-first-inout -5800 0/imm32/no-output -5801 0/imm32/next -5802 -5803 Single-int-var-on-stack: -5804 Int-var-on-stack/imm32 -5805 0/imm32/next -5806 -5807 Int-var-on-stack: -5808 "arg1"/imm32/name -5809 Type-int/imm32 -5810 1/imm32/some-block-depth -5811 1/imm32/some-stack-offset -5812 0/imm32/no-register -5813 -5814 Two-args-int-stack-int-reg: -5815 Int-var-on-stack/imm32 -5816 Single-int-var-in-some-register/imm32/next -5817 -5818 Two-args-int-reg-int-stack: -5819 Int-var-in-some-register/imm32 -5820 Single-int-var-on-stack/imm32/next -5821 -5822 Two-args-int-eax-int-literal: -5823 Int-var-in-eax/imm32 -5824 Single-lit-var/imm32/next -5825 -5826 Int-var-and-literal: -5827 Int-var-on-stack/imm32 -5828 Single-lit-var/imm32/next -5829 -5830 Single-int-var-in-some-register: -5831 Int-var-in-some-register/imm32 -5832 0/imm32/next -5833 -5834 Int-var-in-some-register: -5835 "arg1"/imm32/name -5836 Type-int/imm32 -5837 1/imm32/some-block-depth -5838 0/imm32/no-stack-offset -5839 "*"/imm32/register -5840 -5841 Single-int-var-in-eax: -5842 Int-var-in-eax/imm32 -5843 0/imm32/next -5844 -5845 Int-var-in-eax: -5846 "arg1"/imm32/name -5847 Type-int/imm32 -5848 1/imm32/some-block-depth -5849 0/imm32/no-stack-offset -5850 "eax"/imm32/register -5851 -5852 Single-int-var-in-ecx: -5853 Int-var-in-ecx/imm32 -5854 0/imm32/next -5855 -5856 Int-var-in-ecx: -5857 "arg1"/imm32/name -5858 Type-int/imm32 -5859 1/imm32/some-block-depth -5860 0/imm32/no-stack-offset -5861 "ecx"/imm32/register -5862 -5863 Single-int-var-in-edx: -5864 Int-var-in-edx/imm32 -5865 0/imm32/next -5866 -5867 Int-var-in-edx: -5868 "arg1"/imm32/name -5869 Type-int/imm32 -5870 1/imm32/some-block-depth -5871 0/imm32/no-stack-offset -5872 "edx"/imm32/register -5873 -5874 Single-int-var-in-ebx: -5875 Int-var-in-ebx/imm32 -5876 0/imm32/next -5877 -5878 Int-var-in-ebx: -5879 "arg1"/imm32/name -5880 Type-int/imm32 -5881 1/imm32/some-block-depth -5882 0/imm32/no-stack-offset -5883 "ebx"/imm32/register -5884 -5885 Single-int-var-in-esi: -5886 Int-var-in-esi/imm32 -5887 0/imm32/next -5888 -5889 Int-var-in-esi: -5890 "arg1"/imm32/name -5891 Type-int/imm32 -5892 1/imm32/some-block-depth -5893 0/imm32/no-stack-offset -5894 "esi"/imm32/register -5895 -5896 Single-int-var-in-edi: -5897 Int-var-in-edi/imm32 -5898 0/imm32/next -5899 -5900 Int-var-in-edi: -5901 "arg1"/imm32/name -5902 Type-int/imm32 -5903 1/imm32/some-block-depth -5904 0/imm32/no-stack-offset -5905 "edi"/imm32/register -5906 -5907 Single-lit-var: -5908 Lit-var/imm32 -5909 0/imm32/next -5910 -5911 Lit-var: -5912 "literal"/imm32/name -5913 Type-literal/imm32 -5914 1/imm32/some-block-depth -5915 0/imm32/no-stack-offset -5916 0/imm32/no-register -5917 -5918 Type-int: -5919 1/imm32/left/int -5920 0/imm32/right/null -5921 -5922 Type-literal: -5923 0/imm32/left/literal -5924 0/imm32/right/null -5925 -5926 == code -5927 emit-subx-primitive: # out: (addr buffered-file), stmt: (handle statement), primitive: (handle function) -5928 # . prologue -5929 55/push-ebp -5930 89/<- %ebp 4/r32/esp -5931 # . save registers -5932 50/push-eax -5933 51/push-ecx -5934 # ecx = primitive -5935 8b/-> *(ebp+0x10) 1/r32/ecx -5936 # emit primitive name -5937 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name -5938 # emit rm32 if necessary -5939 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt -5940 # emit r32 if necessary -5941 (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt -5942 # emit imm32 if necessary -5943 (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt -5944 # emit disp32 if necessary -5945 (emit-subx-disp32 *(ebp+8) *(ecx+0x1c) *(ebp+0xc)) # out, Primitive-subx-disp32, stmt -5946 (write-buffered *(ebp+8) Newline) -5947 $emit-subx-primitive:end: -5948 # . restore registers -5949 59/pop-to-ecx -5950 58/pop-to-eax -5951 # . epilogue -5952 89/<- %esp 5/r32/ebp -5953 5d/pop-to-ebp -5954 c3/return -5955 -5956 emit-subx-rm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -5957 # . prologue -5958 55/push-ebp -5959 89/<- %ebp 4/r32/esp -5960 # . save registers -5961 50/push-eax -5962 # if (l == 0) return -5963 81 7/subop/compare *(ebp+0xc) 0/imm32 -5964 74/jump-if-= $emit-subx-rm32:end/disp8 -5965 # -5966 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -5967 (emit-subx-var-as-rm32 *(ebp+8) %eax) # out, var -5968 $emit-subx-rm32:end: -5969 # . restore registers -5970 58/pop-to-eax -5971 # . epilogue -5972 89/<- %esp 5/r32/ebp -5973 5d/pop-to-ebp -5974 c3/return -5975 -5976 get-stmt-operand-from-arg-location: # stmt: (handle statement), l: arg-location -> var/eax: (handle variable) -5977 # . prologue -5978 55/push-ebp -5979 89/<- %ebp 4/r32/esp -5980 # . save registers -5981 51/push-ecx -5982 # eax = l -5983 8b/-> *(ebp+0xc) 0/r32/eax -5984 # ecx = stmt -5985 8b/-> *(ebp+8) 1/r32/ecx -5986 # if (l == 1) return stmt->inouts->var -5987 { -5988 3d/compare-eax-and 1/imm32 -5989 75/jump-if-!= break/disp8 -5990 $get-stmt-operand-from-arg-location:1: -5991 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts -5992 8b/-> *eax 0/r32/eax # Operand-var -5993 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -5994 } -5995 # if (l == 2) return stmt->inouts->next->var -5996 { -5997 3d/compare-eax-and 2/imm32 -5998 75/jump-if-!= break/disp8 -5999 $get-stmt-operand-from-arg-location:2: -6000 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts -6001 8b/-> *(eax+4) 0/r32/eax # Operand-next -6002 8b/-> *eax 0/r32/eax # Operand-var -6003 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -6004 } -6005 # if (l == 3) return stmt->outputs -6006 { -6007 3d/compare-eax-and 3/imm32 -6008 75/jump-if-!= break/disp8 -6009 $get-stmt-operand-from-arg-location:3: -6010 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs -6011 8b/-> *eax 0/r32/eax # Operand-var -6012 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -6013 } -6014 # abort -6015 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 -6016 $get-stmt-operand-from-arg-location:end: -6017 # . restore registers -6018 59/pop-to-ecx -6019 # . epilogue -6020 89/<- %esp 5/r32/ebp -6021 5d/pop-to-ebp -6022 c3/return -6023 -6024 $get-stmt-operand-from-arg-location:abort: -6025 # error("invalid arg-location " eax) -6026 (write-buffered Stderr "invalid arg-location ") -6027 (print-int32-buffered Stderr %eax) -6028 (write-buffered Stderr Newline) -6029 (flush Stderr) -6030 # . syscall(exit, 1) -6031 bb/copy-to-ebx 1/imm32 -6032 b8/copy-to-eax 1/imm32/exit -6033 cd/syscall 0x80/imm8 -6034 # never gets here -6035 -6036 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6037 # . prologue -6038 55/push-ebp -6039 89/<- %ebp 4/r32/esp -6040 # . save registers -6041 50/push-eax -6042 51/push-ecx -6043 # if (location == 0) return -6044 81 7/subop/compare *(ebp+0xc) 0/imm32 -6045 0f 84/jump-if-= $emit-subx-r32:end/disp32 -6046 # -6047 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -6048 (maybe-get Registers *(eax+0x10) 8) # Var-register => eax: (addr register-index) -6049 (write-buffered *(ebp+8) Space) -6050 (print-int32-buffered *(ebp+8) *eax) -6051 (write-buffered *(ebp+8) "/r32") -6052 $emit-subx-r32:end: -6053 # . restore registers -6054 59/pop-to-ecx -6055 58/pop-to-eax -6056 # . epilogue -6057 89/<- %esp 5/r32/ebp -6058 5d/pop-to-ebp -6059 c3/return -6060 -6061 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6062 # . prologue -6063 55/push-ebp -6064 89/<- %ebp 4/r32/esp -6065 # . save registers -6066 50/push-eax -6067 51/push-ecx -6068 # if (location == 0) return -6069 81 7/subop/compare *(ebp+0xc) 0/imm32 -6070 74/jump-if-= $emit-subx-imm32:end/disp8 -6071 # -6072 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -6073 (write-buffered *(ebp+8) Space) -6074 (write-buffered *(ebp+8) *eax) # Var-name -6075 (write-buffered *(ebp+8) "/imm32") -6076 $emit-subx-imm32:end: -6077 # . restore registers -6078 59/pop-to-ecx -6079 58/pop-to-eax -6080 # . epilogue -6081 89/<- %esp 5/r32/ebp -6082 5d/pop-to-ebp -6083 c3/return -6084 -6085 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6086 # . prologue -6087 55/push-ebp -6088 89/<- %ebp 4/r32/esp -6089 # . save registers -6090 50/push-eax -6091 51/push-ecx -6092 # if (location == 0) return -6093 81 7/subop/compare *(ebp+0xc) 0/imm32 -6094 0f 84/jump-if-= $emit-subx-disp32:end/disp32 -6095 # -6096 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -6097 (write-buffered *(ebp+8) Space) -6098 (write-buffered *(ebp+8) *eax) # Var-name -6099 # hack: if instruction operation starts with "break", emit ":break" -6100 # var name/ecx: (addr array byte) = stmt->operation -6101 8b/-> *(ebp+0x10) 0/r32/eax -6102 8b/-> *(eax+4) 1/r32/ecx -6103 { -6104 (string-starts-with? %ecx "break") # => eax -6105 3d/compare-eax-and 0/imm32 -6106 74/jump-if-= break/disp8 -6107 (write-buffered *(ebp+8) ":break") -6108 } -6109 # hack: if instruction operation starts with "loop", emit ":loop" -6110 { -6111 (string-starts-with? %ecx "loop") # => eax -6112 3d/compare-eax-and 0/imm32 -6113 74/jump-if-= break/disp8 -6114 (write-buffered *(ebp+8) ":loop") -6115 } -6116 (write-buffered *(ebp+8) "/disp32") -6117 $emit-subx-disp32:end: -6118 # . restore registers -6119 59/pop-to-ecx -6120 58/pop-to-eax -6121 # . epilogue -6122 89/<- %esp 5/r32/ebp -6123 5d/pop-to-ebp -6124 c3/return -6125 -6126 emit-subx-call: # out: (addr buffered-file), stmt: (handle statement), callee: (handle function) -6127 # . prologue -6128 55/push-ebp -6129 89/<- %ebp 4/r32/esp -6130 # . save registers -6131 50/push-eax -6132 51/push-ecx -6133 # -6134 (write-buffered *(ebp+8) "(") -6135 # - emit function name -6136 8b/-> *(ebp+0x10) 1/r32/ecx -6137 (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name -6138 # - emit arguments -6139 # var curr/ecx: (handle list var) = stmt->inouts -6140 8b/-> *(ebp+0xc) 1/r32/ecx -6141 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts -6142 { -6143 # if (curr == null) break -6144 81 7/subop/compare %ecx 0/imm32 -6145 74/jump-if-= break/disp8 -6146 # -6147 (emit-subx-call-operand *(ebp+8) *ecx) -6148 # curr = curr->next -6149 8b/-> *(ecx+4) 1/r32/ecx -6150 eb/jump loop/disp8 -6151 } -6152 # -6153 (write-buffered *(ebp+8) ")\n") -6154 $emit-subx-call:end: -6155 # . restore registers -6156 59/pop-to-ecx -6157 58/pop-to-eax -6158 # . epilogue -6159 89/<- %esp 5/r32/ebp -6160 5d/pop-to-ebp -6161 c3/return -6162 -6163 emit-subx-call-operand: # out: (addr buffered-file), operand: (handle variable) -6164 # shares code with emit-subx-var-as-rm32 -6165 # . prologue -6166 55/push-ebp -6167 89/<- %ebp 4/r32/esp -6168 # . save registers -6169 50/push-eax -6170 # eax = operand -6171 8b/-> *(ebp+0xc) 0/r32/eax -6172 # if (operand->register) emit "%__" -6173 { -6174 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -6175 74/jump-if-= break/disp8 -6176 $emit-subx-call-operand:register: -6177 (write-buffered *(ebp+8) " %") -6178 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register -6179 e9/jump $emit-subx-call-operand:end/disp32 -6180 } -6181 # else if (operand->stack-offset) emit "*(ebp+__)" -6182 { -6183 81 7/subop/compare *(eax+0xc) 0/imm32 # Var-stack-offset -6184 74/jump-if-= break/disp8 -6185 $emit-subx-call-operand:stack: -6186 (write-buffered *(ebp+8) Space) -6187 (write-buffered *(ebp+8) "*(ebp+") -6188 8b/-> *(ebp+0xc) 0/r32/eax -6189 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-stack-offset -6190 (write-buffered *(ebp+8) ")") -6191 e9/jump $emit-subx-call-operand:end/disp32 -6192 } -6193 # else if (operand->type == literal) emit "__" -6194 { -6195 50/push-eax -6196 8b/-> *(eax+4) 0/r32/eax # Var-type -6197 81 7/subop/compare *eax 0/imm32 # Tree-left -6198 58/pop-to-eax -6199 75/jump-if-!= break/disp8 -6200 $emit-subx-call-operand:literal: -6201 (write-buffered *(ebp+8) Space) -6202 (write-buffered *(ebp+8) *eax) -6203 } -6204 $emit-subx-call-operand:end: -6205 # . restore registers -6206 58/pop-to-eax -6207 # . epilogue -6208 89/<- %esp 5/r32/ebp -6209 5d/pop-to-ebp -6210 c3/return -6211 -6212 emit-subx-var-as-rm32: # out: (addr buffered-file), operand: (handle variable) -6213 # . prologue -6214 55/push-ebp -6215 89/<- %ebp 4/r32/esp -6216 # . save registers -6217 50/push-eax -6218 # eax = operand -6219 8b/-> *(ebp+0xc) 0/r32/eax -6220 # if (operand->register) emit "%__" -6221 { -6222 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -6223 74/jump-if-= break/disp8 -6224 $emit-subx-var-as-rm32:register: -6225 (write-buffered *(ebp+8) " %") -6226 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register -6227 } -6228 # else if (operand->stack-offset) emit "*(ebp+__)" -6229 { -6230 81 7/subop/compare *(eax+0xc) 0/imm32 # Var-stack-offset -6231 74/jump-if-= break/disp8 -6232 $emit-subx-var-as-rm32:stack: -6233 (write-buffered *(ebp+8) Space) -6234 (write-buffered *(ebp+8) "*(ebp+") -6235 8b/-> *(ebp+0xc) 0/r32/eax -6236 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-stack-offset -6237 (write-buffered *(ebp+8) ")") -6238 } -6239 $emit-subx-var-as-rm32:end: -6240 # . restore registers -6241 58/pop-to-eax -6242 # . epilogue -6243 89/<- %esp 5/r32/ebp -6244 5d/pop-to-ebp -6245 c3/return -6246 -6247 find-matching-function: # functions: (addr function), stmt: (handle statement) -> result/eax: (handle function) -6248 # . prologue -6249 55/push-ebp -6250 89/<- %ebp 4/r32/esp -6251 # . save registers -6252 51/push-ecx -6253 # var curr/ecx: (handle function) = functions -6254 8b/-> *(ebp+8) 1/r32/ecx -6255 { -6256 # if (curr == null) break -6257 81 7/subop/compare %ecx 0/imm32 -6258 74/jump-if-= break/disp8 -6259 # if match(stmt, curr) return curr -6260 { -6261 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax -6262 3d/compare-eax-and 0/imm32 -6263 74/jump-if-= break/disp8 -6264 89/<- %eax 1/r32/ecx -6265 eb/jump $find-matching-function:end/disp8 -6266 } -6267 # curr = curr->next -6268 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next -6269 eb/jump loop/disp8 -6270 } -6271 # return null -6272 b8/copy-to-eax 0/imm32 -6273 $find-matching-function:end: -6274 # . restore registers -6275 59/pop-to-ecx -6276 # . epilogue -6277 89/<- %esp 5/r32/ebp -6278 5d/pop-to-ebp -6279 c3/return -6280 -6281 find-matching-primitive: # primitives: (handle primitive), stmt: (handle statement) -> result/eax: (handle primitive) -6282 # . prologue -6283 55/push-ebp -6284 89/<- %ebp 4/r32/esp -6285 # . save registers -6286 51/push-ecx -6287 # var curr/ecx: (handle primitive) = primitives -6288 8b/-> *(ebp+8) 1/r32/ecx -6289 { -6290 $find-matching-primitive:loop: -6291 # if (curr == null) break -6292 81 7/subop/compare %ecx 0/imm32 -6293 0f 84/jump-if-= break/disp32 -6294 #? (write-buffered Stderr "prim: ") -6295 #? (write-buffered Stderr *ecx) # Primitive-name -6296 #? (write-buffered Stderr " => ") -6297 #? (write-buffered Stderr *(ecx+0xc)) # Primitive-subx-name -6298 #? (write-buffered Stderr Newline) -6299 #? (flush Stderr) -6300 # if match(curr, stmt) return curr -6301 { -6302 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax -6303 3d/compare-eax-and 0/imm32 -6304 74/jump-if-= break/disp8 -6305 89/<- %eax 1/r32/ecx -6306 eb/jump $find-matching-primitive:end/disp8 -6307 } -6308 $find-matching-primitive:next-primitive: -6309 # curr = curr->next -6310 8b/-> *(ecx+0x24) 1/r32/ecx # Primitive-next -6311 e9/jump loop/disp32 -6312 } -6313 # return null -6314 b8/copy-to-eax 0/imm32 -6315 $find-matching-primitive:end: -6316 # . restore registers -6317 59/pop-to-ecx -6318 # . epilogue -6319 89/<- %esp 5/r32/ebp -6320 5d/pop-to-ebp -6321 c3/return -6322 -6323 mu-stmt-matches-function?: # stmt: (handle statement), function: (handle function) => result/eax: boolean -6324 # . prologue -6325 55/push-ebp -6326 89/<- %ebp 4/r32/esp -6327 # . save registers -6328 51/push-ecx -6329 # return function->name == stmt->operation -6330 8b/-> *(ebp+8) 1/r32/ecx -6331 8b/-> *(ebp+0xc) 0/r32/eax -6332 (string-equal? *(ecx+4) *eax) # Stmt1-operation, Function-name => eax -6333 $mu-stmt-matches-function?:end: -6334 # . restore registers -6335 59/pop-to-ecx -6336 # . epilogue -6337 89/<- %esp 5/r32/ebp -6338 5d/pop-to-ebp -6339 c3/return -6340 -6341 mu-stmt-matches-primitive?: # stmt: (handle statement), primitive: (handle primitive) => result/eax: boolean -6342 # A mu stmt matches a primitive if the name matches, all the inout vars -6343 # match, and all the output vars match. -6344 # Vars match if types match and registers match. -6345 # In addition, a stmt output matches a primitive's output if types match -6346 # and the primitive has a wildcard register. -6347 # . prologue -6348 55/push-ebp -6349 89/<- %ebp 4/r32/esp -6350 # . save registers -6351 51/push-ecx -6352 52/push-edx -6353 53/push-ebx -6354 56/push-esi -6355 57/push-edi -6356 # ecx = stmt -6357 8b/-> *(ebp+8) 1/r32/ecx -6358 # edx = primitive -6359 8b/-> *(ebp+0xc) 2/r32/edx -6360 { -6361 $mu-stmt-matches-primitive?:check-name: -6362 # if (primitive->name != stmt->operation) return false -6363 (string-equal? *(ecx+4) *edx) # Stmt1-operation, Primitive-name => eax -6364 3d/compare-eax-and 0/imm32 -6365 75/jump-if-!= break/disp8 -6366 b8/copy-to-eax 0/imm32 -6367 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6368 } -6369 $mu-stmt-matches-primitive?:check-inouts: -6370 # for (curr/esi in stmt->inouts, curr2/edi in primitive->inouts) -6371 8b/-> *(ecx+8) 6/r32/esi # Stmt1-inouts -6372 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts -6373 { -6374 # if (curr == 0 && curr2 == 0) move on to check outputs -6375 { -6376 81 7/subop/compare %esi 0/imm32 -6377 75/jump-if-!= break/disp8 -6378 $mu-stmt-matches-primitive?:stmt-inout-is-null: -6379 { -6380 81 7/subop/compare %edi 0/imm32 -6381 75/jump-if-!= break/disp8 -6382 # -6383 e9/jump $mu-stmt-matches-primitive?:check-outputs/disp32 -6384 } -6385 # return false -6386 b8/copy-to-eax 0/imm32/false -6387 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6388 } -6389 # if (curr2 == 0) return false -6390 { -6391 81 7/subop/compare %edi 0/imm32 -6392 75/jump-if-!= break/disp8 -6393 $mu-stmt-matches-primitive?:prim-inout-is-null: -6394 b8/copy-to-eax 0/imm32/false -6395 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6396 } -6397 # if (curr != curr2) return false -6398 { -6399 (operand-matches-primitive? *esi *edi) # => eax -6400 3d/compare-eax-and 0/imm32 -6401 75/jump-if-!= break/disp8 -6402 b8/copy-to-eax 0/imm32/false -6403 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6404 } -6405 # curr=curr->next -6406 8b/-> *(esi+4) 6/r32/esi # Operand-next -6407 # curr2=curr2->next -6408 8b/-> *(edi+4) 7/r32/edi # Operand-next -6409 eb/jump loop/disp8 -6410 } -6411 $mu-stmt-matches-primitive?:check-outputs: -6412 # for (curr/esi in stmt->outputs, curr2/edi in primitive->outputs) -6413 8b/-> *(ecx+0xc) 6/r32/esi # Stmt1-outputs -6414 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs -6415 { -6416 # if (curr == 0) return (curr2 == 0) -6417 { -6418 $mu-stmt-matches-primitive?:check-output: -6419 81 7/subop/compare %esi 0/imm32 -6420 75/jump-if-!= break/disp8 -6421 { -6422 81 7/subop/compare %edi 0/imm32 -6423 75/jump-if-!= break/disp8 -6424 # return true -6425 b8/copy-to-eax 1/imm32 -6426 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6427 } -6428 # return false -6429 b8/copy-to-eax 0/imm32 -6430 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6431 } -6432 # if (curr2 == 0) return false -6433 { -6434 81 7/subop/compare %edi 0/imm32 -6435 75/jump-if-!= break/disp8 -6436 b8/copy-to-eax 0/imm32 -6437 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6438 } -6439 # if (curr != curr2) return false -6440 { -6441 (operand-matches-primitive? *esi *edi) # List-value List-value => eax -6442 3d/compare-eax-and 0/imm32 -6443 75/jump-if-!= break/disp8 -6444 b8/copy-to-eax 0/imm32 -6445 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6446 } -6447 # curr=curr->next -6448 8b/-> *(esi+4) 6/r32/esi # Operand-next -6449 # curr2=curr2->next -6450 8b/-> *(edi+4) 7/r32/edi # Operand-next -6451 eb/jump loop/disp8 -6452 } -6453 $mu-stmt-matches-primitive?:return-true: -6454 b8/copy-to-eax 1/imm32 -6455 $mu-stmt-matches-primitive?:end: -6456 # . restore registers -6457 5f/pop-to-edi -6458 5e/pop-to-esi -6459 5b/pop-to-ebx -6460 5a/pop-to-edx -6461 59/pop-to-ecx -6462 # . epilogue -6463 89/<- %esp 5/r32/ebp -6464 5d/pop-to-ebp -6465 c3/return -6466 -6467 operand-matches-primitive?: # var: (handle var), prim-var: (handle var) => result/eax: boolean -6468 # . prologue -6469 55/push-ebp -6470 89/<- %ebp 4/r32/esp -6471 # . save registers -6472 56/push-esi -6473 57/push-edi -6474 # esi = var -6475 8b/-> *(ebp+8) 6/r32/esi -6476 # edi = prim-var -6477 8b/-> *(ebp+0xc) 7/r32/edi -6478 # if (var->type != prim-var->type) return false -6479 (type-equal? *(esi+4) *(edi+4)) # Var-type, Var-type => eax -6480 3d/compare-eax-and 0/imm32 -6481 b8/copy-to-eax 0/imm32/false -6482 74/jump-if-= $operand-matches-primitive?:end/disp8 -6483 # return false if var->register doesn't match prim-var->register -6484 { -6485 # if addresses are equal, don't return here -6486 8b/-> *(esi+0x10) 0/r32/eax -6487 39/compare *(edi+0x10) 0/r32/eax -6488 74/jump-if-= break/disp8 -6489 # if either address is 0, return false -6490 3d/compare-eax-and 0/imm32 -6491 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result -6492 81 7/subop/compare *(edi+0x10) 0/imm32 -6493 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result -6494 # if prim-var->register is "*", return true -6495 (string-equal? *(edi+0x10) "*") # Var-register -6496 3d/compare-eax-and 0/imm32 -6497 b8/copy-to-eax 1/imm32/true -6498 75/jump-if-!= $operand-matches-primitive?:end/disp8 -6499 # if string contents don't match, return false -6500 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register -6501 3d/compare-eax-and 0/imm32 -6502 b8/copy-to-eax 0/imm32/false -6503 74/jump-if-= $operand-matches-primitive?:end/disp8 -6504 } -6505 # return true -6506 b8/copy-to-eax 1/imm32/true -6507 $operand-matches-primitive?:end: -6508 # . restore registers -6509 5f/pop-to-edi -6510 5e/pop-to-esi -6511 # . epilogue -6512 89/<- %esp 5/r32/ebp -6513 5d/pop-to-ebp -6514 c3/return -6515 -6516 type-equal?: # a: (handle tree type-id), b: (handle tree type-id) => result/eax: boolean -6517 # . prologue -6518 55/push-ebp -6519 89/<- %ebp 4/r32/esp -6520 # . save registers -6521 51/push-ecx -6522 52/push-edx -6523 # ecx = a -6524 8b/-> *(ebp+8) 1/r32/ecx -6525 # edx = b -6526 8b/-> *(ebp+0xc) 2/r32/edx -6527 # if (a == b) return true -6528 8b/-> %ecx 0/r32/eax # Var-type -6529 39/compare %edx 0/r32/eax # Var-type -6530 b8/copy-to-eax 1/imm32/true -6531 74/jump-if-= $type-equal?:end/disp8 -6532 # if (a < MAX_TYPE_ID) return false -6533 81 7/subop/compare %ecx 0x10000/imm32 -6534 b8/copy-to-eax 0/imm32/false -6535 72/jump-if-addr< $type-equal?:end/disp8 -6536 # if (b < MAX_TYPE_ID) return false -6537 81 7/subop/compare %edx 0x10000/imm32 -6538 b8/copy-to-eax 0/imm32/false -6539 72/jump-if-addr< $type-equal?:end/disp8 -6540 # if (!type-equal?(a->left, b->left)) return false -6541 (type-equal? *ecx *edx) # Tree-left, Tree-left => eax -6542 3d/compare-eax-and 0/imm32 -6543 74/jump-if-= $type-equal?:end/disp8 -6544 # return type-equal?(a->right, b->right) -6545 (type-equal? *(ecx+4) *(edx+4)) # Tree-right, Tree-right => eax -6546 $type-equal?:end: -6547 # . restore registers -6548 5a/pop-to-edx -6549 59/pop-to-ecx -6550 # . epilogue -6551 89/<- %esp 5/r32/ebp -6552 5d/pop-to-ebp -6553 c3/return -6554 -6555 test-emit-subx-statement-primitive: -6556 # Primitive operation on a variable on the stack. -6557 # increment foo -6558 # => -6559 # ff 0/subop/increment *(ebp-8) -6560 # -6561 # There's a variable on the var stack as follows: -6562 # name: 'foo' -6563 # type: int -6564 # stack-offset: -8 -6565 # -6566 # There's a primitive with this info: -6567 # name: 'increment' -6568 # inouts: int/mem -6569 # value: 'ff 0/subop/increment' -6570 # -6571 # There's nothing in functions. -6572 # -6573 # . prologue -6574 55/push-ebp -6575 89/<- %ebp 4/r32/esp -6576 # setup -6577 (clear-stream _test-output-stream) -6578 (clear-stream $_test-output-buffered-file->buffer) -6579 # var type/ecx: (handle tree type-id) = int -6580 68/push 0/imm32/right/null -6581 68/push 1/imm32/left/int -6582 89/<- %ecx 4/r32/esp -6583 # var var-foo/ecx: var -6584 68/push 0/imm32/no-register -6585 68/push -8/imm32/stack-offset -6586 68/push 1/imm32/block-depth -6587 51/push-ecx -6588 68/push "foo"/imm32 -6589 89/<- %ecx 4/r32/esp -6590 # var operand/ebx: (list var) -6591 68/push 0/imm32/next -6592 51/push-ecx/var-foo -6593 89/<- %ebx 4/r32/esp -6594 # var stmt/esi: statement -6595 68/push 0/imm32/next -6596 68/push 0/imm32/outputs -6597 53/push-ebx/operands -6598 68/push "increment"/imm32/operation -6599 68/push 1/imm32 -6600 89/<- %esi 4/r32/esp -6601 # var primitives/ebx: primitive -6602 68/push 0/imm32/next -6603 68/push 0/imm32/output-is-write-only -6604 68/push 0/imm32/no-disp32 -6605 68/push 0/imm32/no-imm32 -6606 68/push 0/imm32/no-r32 -6607 68/push 1/imm32/rm32-is-first-inout -6608 68/push "ff 0/subop/increment"/imm32/subx-name -6609 68/push 0/imm32/outputs -6610 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call -6611 68/push "increment"/imm32/name -6612 89/<- %ebx 4/r32/esp -6613 # convert -6614 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -6615 (flush _test-output-buffered-file) -6616 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -6622 # check output -6623 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-statement-primitive") -6624 # . epilogue -6625 89/<- %esp 5/r32/ebp -6626 5d/pop-to-ebp -6627 c3/return -6628 -6629 test-emit-subx-statement-primitive-register: -6630 # Primitive operation on a variable in a register. -6631 # foo <- increment -6632 # => -6633 # ff 0/subop/increment %eax # sub-optimal, but should suffice -6634 # -6635 # There's a variable on the var stack as follows: -6636 # name: 'foo' -6637 # type: int -6638 # register: 'eax' -6639 # -6640 # There's a primitive with this info: -6641 # name: 'increment' -6642 # out: int/reg -6643 # value: 'ff 0/subop/increment' -6644 # -6645 # There's nothing in functions. -6646 # -6647 # . prologue -6648 55/push-ebp -6649 89/<- %ebp 4/r32/esp -6650 # setup -6651 (clear-stream _test-output-stream) -6652 (clear-stream $_test-output-buffered-file->buffer) -6653 # var type/ecx: (handle tree type-id) = int -6654 68/push 0/imm32/right/null -6655 68/push 1/imm32/left/int -6656 89/<- %ecx 4/r32/esp -6657 # var var-foo/ecx: var in eax -6658 68/push "eax"/imm32/register -6659 68/push 0/imm32/no-stack-offset -6660 68/push 1/imm32/block-depth -6661 51/push-ecx -6662 68/push "foo"/imm32 -6663 89/<- %ecx 4/r32/esp -6664 # var operand/ebx: (list var) -6665 68/push 0/imm32/next -6666 51/push-ecx/var-foo -6667 89/<- %ebx 4/r32/esp -6668 # var stmt/esi: statement -6669 68/push 0/imm32/next -6670 53/push-ebx/outputs -6671 68/push 0/imm32/inouts -6672 68/push "increment"/imm32/operation -6673 68/push 1/imm32 -6674 89/<- %esi 4/r32/esp -6675 # var formal-var/ebx: var in any register -6676 68/push Any-register/imm32 -6677 68/push 0/imm32/no-stack-offset -6678 68/push 1/imm32/block-depth -6679 ff 6/subop/push *(ecx+4) # Var-type -6680 68/push "dummy"/imm32 -6681 89/<- %ebx 4/r32/esp -6682 # var operand/ebx: (list var) -6683 68/push 0/imm32/next -6684 53/push-ebx/formal-var -6685 89/<- %ebx 4/r32/esp -6686 # var primitives/ebx: primitive -6687 68/push 0/imm32/next -6688 68/push 0/imm32/output-is-write-only -6689 68/push 0/imm32/no-disp32 -6690 68/push 0/imm32/no-imm32 -6691 68/push 0/imm32/no-r32 -6692 68/push 3/imm32/rm32-in-first-output -6693 68/push "ff 0/subop/increment"/imm32/subx-name -6694 53/push-ebx/outputs -6695 68/push 0/imm32/inouts -6696 68/push "increment"/imm32/name -6697 89/<- %ebx 4/r32/esp -6698 # convert -6699 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -6700 (flush _test-output-buffered-file) -6701 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -6707 # check output -6708 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-primitive-register") -6709 # . epilogue -6710 89/<- %esp 5/r32/ebp -6711 5d/pop-to-ebp -6712 c3/return -6713 -6714 test-emit-subx-statement-select-primitive: -6715 # Select the right primitive between overloads. -6716 # foo <- increment -6717 # => -6718 # ff 0/subop/increment %eax # sub-optimal, but should suffice -6719 # -6720 # There's a variable on the var stack as follows: -6721 # name: 'foo' -6722 # type: int -6723 # register: 'eax' -6724 # -6725 # There's two primitives, as follows: -6726 # - name: 'increment' -6727 # out: int/reg -6728 # value: 'ff 0/subop/increment' -6729 # - name: 'increment' -6730 # inout: int/mem -6731 # value: 'ff 0/subop/increment' -6732 # -6733 # There's nothing in functions. -6734 # -6735 # . prologue -6736 55/push-ebp -6737 89/<- %ebp 4/r32/esp -6738 # setup -6739 (clear-stream _test-output-stream) -6740 (clear-stream $_test-output-buffered-file->buffer) -6741 # var type/ecx: (handle tree type-id) = int -6742 68/push 0/imm32/right/null -6743 68/push 1/imm32/left/int -6744 89/<- %ecx 4/r32/esp -6745 # var var-foo/ecx: var in eax -6746 68/push "eax"/imm32/register -6747 68/push 0/imm32/no-stack-offset -6748 68/push 1/imm32/block-depth -6749 51/push-ecx -6750 68/push "foo"/imm32 -6751 89/<- %ecx 4/r32/esp -6752 # var real-outputs/edi: (list var) -6753 68/push 0/imm32/next -6754 51/push-ecx/var-foo -6755 89/<- %edi 4/r32/esp -6756 # var stmt/esi: statement -6757 68/push 0/imm32/next -6758 57/push-edi/outputs -6759 68/push 0/imm32/inouts -6760 68/push "increment"/imm32/operation -6761 68/push 1/imm32 -6762 89/<- %esi 4/r32/esp -6763 # var formal-var/ebx: var in any register -6764 68/push Any-register/imm32 -6765 68/push 0/imm32/no-stack-offset -6766 68/push 1/imm32/block-depth -6767 ff 6/subop/push *(ecx+4) # Var-type -6768 68/push "dummy"/imm32 -6769 89/<- %ebx 4/r32/esp -6770 # var formal-outputs/ebx: (list var) = {formal-var, 0} -6771 68/push 0/imm32/next -6772 53/push-ebx/formal-var -6773 89/<- %ebx 4/r32/esp -6774 # var primitive1/ebx: primitive -6775 68/push 0/imm32/next -6776 68/push 0/imm32/output-is-write-only -6777 68/push 0/imm32/no-disp32 -6778 68/push 0/imm32/no-imm32 -6779 68/push 0/imm32/no-r32 -6780 68/push 3/imm32/rm32-in-first-output -6781 68/push "ff 0/subop/increment"/imm32/subx-name -6782 53/push-ebx/outputs/formal-outputs -6783 68/push 0/imm32/inouts -6784 68/push "increment"/imm32/name -6785 89/<- %ebx 4/r32/esp -6786 # var primitives/ebx: primitive -6787 53/push-ebx/next -6788 68/push 0/imm32/output-is-write-only -6789 68/push 0/imm32/no-disp32 -6790 68/push 0/imm32/no-imm32 -6791 68/push 0/imm32/no-r32 -6792 68/push 1/imm32/rm32-is-first-inout -6793 68/push "ff 0/subop/increment"/imm32/subx-name -6794 68/push 0/imm32/outputs -6795 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -6796 68/push "increment"/imm32/name -6797 89/<- %ebx 4/r32/esp -6798 # convert -6799 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -6800 (flush _test-output-buffered-file) -6801 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -6807 # check output -6808 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive") -6809 # . epilogue -6810 89/<- %esp 5/r32/ebp -6811 5d/pop-to-ebp -6812 c3/return -6813 -6814 test-emit-subx-statement-select-primitive-2: -6815 # Select the right primitive between overloads. -6816 # foo <- increment -6817 # => -6818 # ff 0/subop/increment %eax # sub-optimal, but should suffice -6819 # -6820 # There's a variable on the var stack as follows: -6821 # name: 'foo' -6822 # type: int -6823 # register: 'eax' -6824 # -6825 # There's two primitives, as follows: -6826 # - name: 'increment' -6827 # out: int/reg -6828 # value: 'ff 0/subop/increment' -6829 # - name: 'increment' -6830 # inout: int/mem -6831 # value: 'ff 0/subop/increment' -6832 # -6833 # There's nothing in functions. -6834 # -6835 # . prologue -6836 55/push-ebp -6837 89/<- %ebp 4/r32/esp -6838 # setup -6839 (clear-stream _test-output-stream) -6840 (clear-stream $_test-output-buffered-file->buffer) -6841 # var type/ecx: (handle tree type-id) = int -6842 68/push 0/imm32/right/null -6843 68/push 1/imm32/left/int -6844 89/<- %ecx 4/r32/esp -6845 # var var-foo/ecx: var in eax -6846 68/push "eax"/imm32/register -6847 68/push 0/imm32/no-stack-offset -6848 68/push 1/imm32/block-depth -6849 51/push-ecx -6850 68/push "foo"/imm32 -6851 89/<- %ecx 4/r32/esp -6852 # var inouts/edi: (list var) -6853 68/push 0/imm32/next -6854 51/push-ecx/var-foo -6855 89/<- %edi 4/r32/esp -6856 # var stmt/esi: statement -6857 68/push 0/imm32/next -6858 68/push 0/imm32/outputs -6859 57/push-edi/inouts -6860 68/push "increment"/imm32/operation -6861 68/push 1/imm32 -6862 89/<- %esi 4/r32/esp -6863 # var formal-var/ebx: var in any register -6864 68/push Any-register/imm32 -6865 68/push 0/imm32/no-stack-offset -6866 68/push 1/imm32/block-depth -6867 ff 6/subop/push *(ecx+4) # Var-type -6868 68/push "dummy"/imm32 -6869 89/<- %ebx 4/r32/esp -6870 # var operand/ebx: (list var) -6871 68/push 0/imm32/next -6872 53/push-ebx/formal-var -6873 89/<- %ebx 4/r32/esp -6874 # var primitive1/ebx: primitive -6875 68/push 0/imm32/next -6876 68/push 0/imm32/output-is-write-only -6877 68/push 0/imm32/no-disp32 -6878 68/push 0/imm32/no-imm32 -6879 68/push 0/imm32/no-r32 -6880 68/push 3/imm32/rm32-in-first-output -6881 68/push "ff 0/subop/increment"/imm32/subx-name -6882 53/push-ebx/outputs/formal-outputs -6883 68/push 0/imm32/inouts -6884 68/push "increment"/imm32/name -6885 89/<- %ebx 4/r32/esp -6886 # var primitives/ebx: primitive -6887 53/push-ebx/next -6888 68/push 0/imm32/output-is-write-only -6889 68/push 0/imm32/no-disp32 -6890 68/push 0/imm32/no-imm32 -6891 68/push 0/imm32/no-r32 -6892 68/push 1/imm32/rm32-is-first-inout -6893 68/push "ff 0/subop/increment"/imm32/subx-name -6894 68/push 0/imm32/outputs -6895 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -6896 68/push "increment"/imm32/name -6897 89/<- %ebx 4/r32/esp -6898 # convert -6899 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -6900 (flush _test-output-buffered-file) -6901 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -6907 # check output -6908 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2") -6909 # . epilogue -6910 89/<- %esp 5/r32/ebp -6911 5d/pop-to-ebp -6912 c3/return -6913 -6914 test-increment-register: -6915 # Select the right primitive between overloads. -6916 # foo <- increment -6917 # => -6918 # 50/increment-eax -6919 # -6920 # There's a variable on the var stack as follows: -6921 # name: 'foo' -6922 # type: int -6923 # register: 'eax' +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 +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' +6835 # +6836 # There's nothing in functions. +6837 # +6838 # . prologue +6839 55/push-ebp +6840 89/<- %ebp 4/r32/esp +6841 # setup +6842 (clear-stream _test-output-stream) +6843 (clear-stream $_test-output-buffered-file->buffer) +6844 # var type/ecx: (handle tree type-id) = int +6845 68/push 0/imm32/right/null +6846 68/push 1/imm32/left/int +6847 89/<- %ecx 4/r32/esp +6848 # var var-foo/ecx: var in eax +6849 68/push "eax"/imm32/register +6850 68/push 0/imm32/no-stack-offset +6851 68/push 1/imm32/block-depth +6852 51/push-ecx +6853 68/push "foo"/imm32 +6854 89/<- %ecx 4/r32/esp +6855 # var operand/ebx: (list var) +6856 68/push 0/imm32/next +6857 51/push-ecx/var-foo +6858 89/<- %ebx 4/r32/esp +6859 # var stmt/esi: statement +6860 68/push 0/imm32/next +6861 53/push-ebx/outputs +6862 68/push 0/imm32/inouts +6863 68/push "increment"/imm32/operation +6864 68/push 1/imm32 +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 # Primitives are the global definitions. +6925 # There's nothing in functions. 6926 # -6927 # There are no functions defined. -6928 # -6929 # . prologue -6930 55/push-ebp -6931 89/<- %ebp 4/r32/esp -6932 # setup -6933 (clear-stream _test-output-stream) -6934 (clear-stream $_test-output-buffered-file->buffer) -6935 # var type/ecx: (handle tree type-id) = int -6936 68/push 0/imm32/right/null -6937 68/push 1/imm32/left/int -6938 89/<- %ecx 4/r32/esp -6939 # var var-foo/ecx: var in eax -6940 68/push "eax"/imm32/register -6941 68/push 0/imm32/no-stack-offset -6942 68/push 1/imm32/block-depth -6943 51/push-ecx -6944 68/push "foo"/imm32 -6945 89/<- %ecx 4/r32/esp -6946 # var real-outputs/edi: (list var) -6947 68/push 0/imm32/next -6948 51/push-ecx/var-foo -6949 89/<- %edi 4/r32/esp -6950 # var stmt/esi: statement -6951 68/push 0/imm32/next -6952 57/push-edi/outputs -6953 68/push 0/imm32/inouts -6954 68/push "increment"/imm32/operation -6955 68/push 1/imm32/regular-statement -6956 89/<- %esi 4/r32/esp -6957 # convert -6958 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -6959 (flush _test-output-buffered-file) -6960 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -6966 # check output -6967 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") -6968 # . epilogue -6969 89/<- %esp 5/r32/ebp -6970 5d/pop-to-ebp -6971 c3/return -6972 -6973 test-increment-var: -6974 # Select the right primitive between overloads. -6975 # foo <- increment -6976 # => -6977 # ff 0/subop/increment %eax # sub-optimal, but should suffice -6978 # -6979 # There's a variable on the var stack as follows: -6980 # name: 'foo' -6981 # type: int -6982 # register: 'eax' -6983 # -6984 # Primitives are the global definitions. -6985 # -6986 # There are no functions defined. -6987 # -6988 # . prologue -6989 55/push-ebp -6990 89/<- %ebp 4/r32/esp -6991 # setup -6992 (clear-stream _test-output-stream) -6993 (clear-stream $_test-output-buffered-file->buffer) -6994 # var type/ecx: (handle tree type-id) = int -6995 68/push 0/imm32/right/null -6996 68/push 1/imm32/left/int -6997 89/<- %ecx 4/r32/esp -6998 # var var-foo/ecx: var in eax -6999 68/push "eax"/imm32/register -7000 68/push 0/imm32/no-stack-offset -7001 68/push 1/imm32/block-depth -7002 51/push-ecx -7003 68/push "foo"/imm32 -7004 89/<- %ecx 4/r32/esp -7005 # var inouts/edi: (list var) -7006 68/push 0/imm32/next -7007 51/push-ecx/var-foo -7008 89/<- %edi 4/r32/esp -7009 # var stmt/esi: statement -7010 68/push 0/imm32/next -7011 68/push 0/imm32/outputs -7012 57/push-edi/inouts -7013 68/push "increment"/imm32/operation -7014 68/push 1/imm32 -7015 89/<- %esi 4/r32/esp -7016 # convert -7017 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7018 (flush _test-output-buffered-file) -7019 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7025 # check output -7026 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-increment-var") -7027 # . epilogue -7028 89/<- %esp 5/r32/ebp -7029 5d/pop-to-ebp -7030 c3/return -7031 -7032 test-add-reg-to-reg: -7033 # var1/reg <- add var2/reg -7034 # => -7035 # 01/add %var1 var2 -7036 # -7037 # . prologue -7038 55/push-ebp -7039 89/<- %ebp 4/r32/esp -7040 # setup -7041 (clear-stream _test-output-stream) -7042 (clear-stream $_test-output-buffered-file->buffer) -7043 # var type/ecx: (handle tree type-id) = int -7044 68/push 0/imm32/right/null -7045 68/push 1/imm32/left/int -7046 89/<- %ecx 4/r32/esp -7047 # var var-var1/ecx: var in eax -7048 68/push "eax"/imm32/register -7049 68/push 0/imm32/no-stack-offset -7050 68/push 1/imm32/block-depth -7051 51/push-ecx -7052 68/push "var1"/imm32 -7053 89/<- %ecx 4/r32/esp -7054 # var var-var2/edx: var in ecx -7055 68/push "ecx"/imm32/register -7056 68/push 0/imm32/no-stack-offset -7057 68/push 1/imm32/block-depth -7058 ff 6/subop/push *(ecx+4) # Var-type -7059 68/push "var2"/imm32 -7060 89/<- %edx 4/r32/esp -7061 # var inouts/esi: (list var2) -7062 68/push 0/imm32/next -7063 52/push-edx/var-var2 -7064 89/<- %esi 4/r32/esp -7065 # var outputs/edi: (list var1) -7066 68/push 0/imm32/next -7067 51/push-ecx/var-var1 -7068 89/<- %edi 4/r32/esp -7069 # var stmt/esi: statement -7070 68/push 0/imm32/next -7071 57/push-edi/outputs -7072 56/push-esi/inouts -7073 68/push "add"/imm32/operation -7074 68/push 1/imm32 -7075 89/<- %esi 4/r32/esp -7076 # convert -7077 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7078 (flush _test-output-buffered-file) -7079 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7085 # check output -7086 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") -7087 # . epilogue -7088 89/<- %esp 5/r32/ebp -7089 5d/pop-to-ebp -7090 c3/return -7091 -7092 test-add-reg-to-mem: -7093 # add-to var1 var2/reg -7094 # => -7095 # 01/add *(ebp+__) var2 -7096 # -7097 # . prologue -7098 55/push-ebp -7099 89/<- %ebp 4/r32/esp -7100 # setup -7101 (clear-stream _test-output-stream) -7102 (clear-stream $_test-output-buffered-file->buffer) -7103 # var type/ecx: (handle tree type-id) = int -7104 68/push 0/imm32/right/null -7105 68/push 1/imm32/left/int -7106 89/<- %ecx 4/r32/esp -7107 # var var-var1/ecx: var -7108 68/push 0/imm32/no-register -7109 68/push 8/imm32/stack-offset -7110 68/push 1/imm32/block-depth -7111 51/push-ecx -7112 68/push "var1"/imm32 -7113 89/<- %ecx 4/r32/esp -7114 # var var-var2/edx: var in ecx -7115 68/push "ecx"/imm32/register -7116 68/push 0/imm32/no-stack-offset -7117 68/push 1/imm32/block-depth -7118 ff 6/subop/push *(ecx+4) # Var-type -7119 68/push "var2"/imm32 -7120 89/<- %edx 4/r32/esp -7121 # var inouts/esi: (list var2) -7122 68/push 0/imm32/next -7123 52/push-edx/var-var2 -7124 89/<- %esi 4/r32/esp -7125 # var inouts = (list var1 var2) -7126 56/push-esi/next -7127 51/push-ecx/var-var1 -7128 89/<- %esi 4/r32/esp -7129 # var stmt/esi: statement -7130 68/push 0/imm32/next -7131 68/push 0/imm32/outputs -7132 56/push-esi/inouts -7133 68/push "add-to"/imm32/operation -7134 68/push 1/imm32 -7135 89/<- %esi 4/r32/esp -7136 # convert -7137 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7138 (flush _test-output-buffered-file) -7139 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7145 # check output -7146 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") -7147 # . epilogue -7148 89/<- %esp 5/r32/ebp -7149 5d/pop-to-ebp -7150 c3/return -7151 -7152 test-add-mem-to-reg: -7153 # var1/reg <- add var2 -7154 # => -7155 # 03/add *(ebp+__) var1 -7156 # -7157 # . prologue -7158 55/push-ebp -7159 89/<- %ebp 4/r32/esp -7160 # setup -7161 (clear-stream _test-output-stream) -7162 (clear-stream $_test-output-buffered-file->buffer) -7163 # var type/ecx: (handle tree type-id) = int -7164 68/push 0/imm32/right/null -7165 68/push 1/imm32/left/int -7166 89/<- %ecx 4/r32/esp -7167 # var var-var1/ecx: var in eax -7168 68/push "eax"/imm32/register -7169 68/push 0/imm32/no-stack-offset -7170 68/push 1/imm32/block-depth -7171 51/push-ecx -7172 68/push "var1"/imm32 -7173 89/<- %ecx 4/r32/esp -7174 # var var-var2/edx: var -7175 68/push 0/imm32/no-register -7176 68/push 8/imm32/stack-offset -7177 68/push 1/imm32/block-depth -7178 ff 6/subop/push *(ecx+4) # Var-type -7179 68/push "var2"/imm32 -7180 89/<- %edx 4/r32/esp -7181 # var inouts/esi: (list var2) -7182 68/push 0/imm32/next -7183 52/push-edx/var-var2 -7184 89/<- %esi 4/r32/esp -7185 # var outputs/edi: (list var1) -7186 68/push 0/imm32/next -7187 51/push-ecx/var-var1 -7188 89/<- %edi 4/r32/esp -7189 # var stmt/esi: statement -7190 68/push 0/imm32/next -7191 57/push-edi/outputs -7192 56/push-esi/inouts -7193 68/push "add"/imm32/operation -7194 68/push 1/imm32 -7195 89/<- %esi 4/r32/esp -7196 # convert -7197 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7198 (flush _test-output-buffered-file) -7199 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7205 # check output -7206 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") -7207 # . epilogue -7208 89/<- %esp 5/r32/ebp -7209 5d/pop-to-ebp -7210 c3/return -7211 -7212 test-add-literal-to-eax: -7213 # var1/eax <- add 0x34 -7214 # => -7215 # 05/add-to-eax 0x34/imm32 -7216 # -7217 # . prologue -7218 55/push-ebp -7219 89/<- %ebp 4/r32/esp -7220 # setup -7221 (clear-stream _test-output-stream) -7222 (clear-stream $_test-output-buffered-file->buffer) -7223 # var type/ecx: (handle tree type-id) = int -7224 68/push 0/imm32/right/null -7225 68/push 1/imm32/left/int -7226 89/<- %ecx 4/r32/esp -7227 # var var-var1/ecx: var in eax -7228 68/push "eax"/imm32/register -7229 68/push 0/imm32/no-stack-offset -7230 68/push 1/imm32/block-depth -7231 51/push-ecx -7232 68/push "var1"/imm32 -7233 89/<- %ecx 4/r32/esp -7234 # var type/edx: (handle tree type-id) = literal -7235 68/push 0/imm32/right/null -7236 68/push 0/imm32/left/literal -7237 89/<- %edx 4/r32/esp -7238 # var var-var2/edx: var literal -7239 68/push 0/imm32/no-register -7240 68/push 0/imm32/no-stack-offset -7241 68/push 1/imm32/block-depth -7242 52/push-edx -7243 68/push "0x34"/imm32 -7244 89/<- %edx 4/r32/esp -7245 # var inouts/esi: (list var2) -7246 68/push 0/imm32/next -7247 52/push-edx/var-var2 -7248 89/<- %esi 4/r32/esp -7249 # var outputs/edi: (list var1) -7250 68/push 0/imm32/next -7251 51/push-ecx/var-var1 -7252 89/<- %edi 4/r32/esp -7253 # var stmt/esi: statement -7254 68/push 0/imm32/next -7255 57/push-edi/outputs -7256 56/push-esi/inouts -7257 68/push "add"/imm32/operation -7258 68/push 1/imm32 -7259 89/<- %esi 4/r32/esp -7260 # convert -7261 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7262 (flush _test-output-buffered-file) -7263 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7269 # check output -7270 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") -7271 # . epilogue -7272 89/<- %esp 5/r32/ebp -7273 5d/pop-to-ebp -7274 c3/return -7275 -7276 test-add-literal-to-reg: -7277 # var1/ecx <- add 0x34 -7278 # => -7279 # 81 0/subop/add %ecx 0x34/imm32 -7280 # -7281 # . prologue -7282 55/push-ebp -7283 89/<- %ebp 4/r32/esp -7284 # setup -7285 (clear-stream _test-output-stream) -7286 (clear-stream $_test-output-buffered-file->buffer) -7287 # var type/ecx: (handle tree type-id) = int -7288 68/push 0/imm32/right/null -7289 68/push 1/imm32/left/int -7290 89/<- %ecx 4/r32/esp -7291 # var var-var1/ecx: var in ecx -7292 68/push "ecx"/imm32/register -7293 68/push 0/imm32/no-stack-offset -7294 68/push 1/imm32/block-depth -7295 51/push-ecx -7296 68/push "var1"/imm32 -7297 89/<- %ecx 4/r32/esp -7298 # var type/edx: (handle tree type-id) = literal -7299 68/push 0/imm32/right/null -7300 68/push 0/imm32/left/literal -7301 89/<- %edx 4/r32/esp -7302 # var var-var2/edx: var literal -7303 68/push 0/imm32/no-register -7304 68/push 0/imm32/no-stack-offset -7305 68/push 1/imm32/block-depth -7306 52/push-edx -7307 68/push "0x34"/imm32 -7308 89/<- %edx 4/r32/esp -7309 # var inouts/esi: (list var2) -7310 68/push 0/imm32/next -7311 52/push-edx/var-var2 -7312 89/<- %esi 4/r32/esp -7313 # var outputs/edi: (list var1) -7314 68/push 0/imm32/next -7315 51/push-ecx/var-var1 -7316 89/<- %edi 4/r32/esp -7317 # var stmt/esi: statement -7318 68/push 0/imm32/next -7319 57/push-edi/outputs -7320 56/push-esi/inouts -7321 68/push "add"/imm32/operation -7322 68/push 1/imm32 -7323 89/<- %esi 4/r32/esp -7324 # convert -7325 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7326 (flush _test-output-buffered-file) -7327 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7333 # check output -7334 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") -7335 # . epilogue -7336 89/<- %esp 5/r32/ebp -7337 5d/pop-to-ebp -7338 c3/return -7339 -7340 test-add-literal-to-mem: -7341 # add-to var1, 0x34 -7342 # => -7343 # 81 0/subop/add %eax 0x34/imm32 -7344 # -7345 # . prologue -7346 55/push-ebp -7347 89/<- %ebp 4/r32/esp -7348 # setup -7349 (clear-stream _test-output-stream) -7350 (clear-stream $_test-output-buffered-file->buffer) -7351 # var type/ecx: (handle tree type-id) = int -7352 68/push 0/imm32/right/null -7353 68/push 1/imm32/left/int -7354 89/<- %ecx 4/r32/esp -7355 # var var-var1/ecx: var -7356 68/push 0/imm32/no-register -7357 68/push 8/imm32/stack-offset -7358 68/push 1/imm32/block-depth -7359 51/push-ecx -7360 68/push "var1"/imm32 -7361 89/<- %ecx 4/r32/esp -7362 # var type/edx: (handle tree type-id) = literal -7363 68/push 0/imm32/right/null -7364 68/push 0/imm32/left/literal -7365 89/<- %edx 4/r32/esp -7366 # var var-var2/edx: var literal -7367 68/push 0/imm32/no-register -7368 68/push 0/imm32/no-stack-offset -7369 68/push 1/imm32/block-depth -7370 52/push-edx -7371 68/push "0x34"/imm32 -7372 89/<- %edx 4/r32/esp -7373 # var inouts/esi: (list var2) -7374 68/push 0/imm32/next -7375 52/push-edx/var-var2 -7376 89/<- %esi 4/r32/esp -7377 # var inouts = (list var1 inouts) -7378 56/push-esi/next -7379 51/push-ecx/var-var1 -7380 89/<- %esi 4/r32/esp -7381 # var stmt/esi: statement -7382 68/push 0/imm32/next -7383 68/push 0/imm32/outputs -7384 56/push-esi/inouts -7385 68/push "add-to"/imm32/operation -7386 68/push 1/imm32 -7387 89/<- %esi 4/r32/esp -7388 # convert -7389 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7390 (flush _test-output-buffered-file) -7391 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7397 # check output -7398 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") -7399 # . epilogue -7400 89/<- %esp 5/r32/ebp -7401 5d/pop-to-ebp -7402 c3/return -7403 -7404 test-compare-mem-with-reg: -7405 # compare var1, var2/eax -7406 # => -7407 # 39/compare *(ebp+___) 0/r32/eax -7408 # -7409 # . prologue -7410 55/push-ebp -7411 89/<- %ebp 4/r32/esp -7412 # setup -7413 (clear-stream _test-output-stream) -7414 (clear-stream $_test-output-buffered-file->buffer) -7415 # var type/ecx: (handle tree type-id) = int -7416 68/push 0/imm32/right/null -7417 68/push 1/imm32/left/int -7418 89/<- %ecx 4/r32/esp -7419 # var var-var2/ecx: var in eax -7420 68/push "eax"/imm32/register -7421 68/push 0/imm32/no-stack-offset -7422 68/push 1/imm32/block-depth -7423 51/push-ecx -7424 68/push "var2"/imm32 +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/edx: var -7427 68/push 0/imm32/no-register -7428 68/push 8/imm32/stack-offset +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 ff 6/subop/push *(ecx+4) # Var-type +7430 51/push-ecx 7431 68/push "var1"/imm32 -7432 89/<- %edx 4/r32/esp -7433 # var inouts/esi: (list var1 var2) -7434 68/push 0/imm32/next -7435 51/push-ecx/var-var2 -7436 89/<- %esi 4/r32/esp -7437 56/push-esi -7438 52/push-edx/var-var1 -7439 89/<- %esi 4/r32/esp -7440 # var stmt/esi: statement -7441 68/push 0/imm32/next -7442 68/push 0/imm32/outputs -7443 56/push-esi/inouts -7444 68/push "compare"/imm32/operation -7445 68/push 1/imm32 -7446 89/<- %esi 4/r32/esp -7447 # convert -7448 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7449 (flush _test-output-buffered-file) -7450 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7456 # check output -7457 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") -7458 # . epilogue -7459 89/<- %esp 5/r32/ebp -7460 5d/pop-to-ebp -7461 c3/return -7462 -7463 test-compare-reg-with-mem: -7464 # compare var1/eax, var2 -7465 # => -7466 # 3b/compare *(ebp+___) 0/r32/eax -7467 # -7468 # . prologue -7469 55/push-ebp -7470 89/<- %ebp 4/r32/esp -7471 # setup -7472 (clear-stream _test-output-stream) -7473 (clear-stream $_test-output-buffered-file->buffer) -7474 # var type/ecx: (handle tree type-id) = int -7475 68/push 0/imm32/right/null -7476 68/push 1/imm32/left/int -7477 89/<- %ecx 4/r32/esp -7478 # var var-var1/ecx: var in eax -7479 68/push "eax"/imm32/register -7480 68/push 0/imm32/no-stack-offset -7481 68/push 1/imm32/block-depth -7482 51/push-ecx -7483 68/push "var1"/imm32 -7484 89/<- %ecx 4/r32/esp -7485 # var var-var2/edx: var -7486 68/push 0/imm32/no-register -7487 68/push 8/imm32/stack-offset -7488 68/push 1/imm32/block-depth -7489 ff 6/subop/push *(ecx+4) # Var-type -7490 68/push "var2"/imm32 -7491 89/<- %edx 4/r32/esp -7492 # var inouts/esi: (list var1 var2) -7493 68/push 0/imm32/next -7494 52/push-edx/var-var2 -7495 89/<- %esi 4/r32/esp -7496 56/push-esi -7497 51/push-ecx/var-var1 -7498 89/<- %esi 4/r32/esp -7499 # var stmt/esi: statement -7500 68/push 0/imm32/next -7501 68/push 0/imm32/outputs -7502 56/push-esi/inouts -7503 68/push "compare"/imm32/operation -7504 68/push 1/imm32 -7505 89/<- %esi 4/r32/esp -7506 # convert -7507 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7508 (flush _test-output-buffered-file) -7509 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7515 # check output -7516 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") -7517 # . epilogue -7518 89/<- %esp 5/r32/ebp -7519 5d/pop-to-ebp -7520 c3/return -7521 -7522 test-compare-mem-with-literal: -7523 # compare var1, 0x34 -7524 # => -7525 # 81 7/subop/compare *(ebp+___) 0x34/imm32 -7526 # -7527 # . prologue -7528 55/push-ebp -7529 89/<- %ebp 4/r32/esp -7530 # setup -7531 (clear-stream _test-output-stream) -7532 (clear-stream $_test-output-buffered-file->buffer) -7533 # var type/ecx: (handle tree type-id) = int -7534 68/push 0/imm32/right/null -7535 68/push 1/imm32/left/int -7536 89/<- %ecx 4/r32/esp -7537 # var var-var1/ecx: var -7538 68/push 0/imm32/no-register -7539 68/push 8/imm32/stack-offset -7540 68/push 1/imm32/block-depth -7541 51/push-ecx -7542 68/push "var1"/imm32 -7543 89/<- %ecx 4/r32/esp -7544 # var type/edx: (handle tree type-id) = literal -7545 68/push 0/imm32/right/null -7546 68/push 0/imm32/left/literal -7547 89/<- %edx 4/r32/esp -7548 # var var-var2/edx: var literal -7549 68/push 0/imm32/no-register -7550 68/push 0/imm32/no-stack-offset -7551 68/push 1/imm32/block-depth -7552 52/push-edx -7553 68/push "0x34"/imm32 -7554 89/<- %edx 4/r32/esp -7555 # var inouts/esi: (list var2) -7556 68/push 0/imm32/next -7557 52/push-edx/var-var2 -7558 89/<- %esi 4/r32/esp -7559 # var inouts = (list var1 inouts) -7560 56/push-esi/next -7561 51/push-ecx/var-var1 -7562 89/<- %esi 4/r32/esp -7563 # var stmt/esi: statement -7564 68/push 0/imm32/next -7565 68/push 0/imm32/outputs -7566 56/push-esi/inouts -7567 68/push "compare"/imm32/operation -7568 68/push 1/imm32 -7569 89/<- %esi 4/r32/esp -7570 # convert -7571 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7572 (flush _test-output-buffered-file) -7573 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7579 # check output -7580 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") -7581 # . epilogue -7582 89/<- %esp 5/r32/ebp -7583 5d/pop-to-ebp -7584 c3/return -7585 -7586 test-compare-eax-with-literal: -7587 # compare var1/eax 0x34 -7588 # => -7589 # 3d/compare-eax-with 0x34/imm32 -7590 # -7591 # . prologue -7592 55/push-ebp -7593 89/<- %ebp 4/r32/esp -7594 # setup -7595 (clear-stream _test-output-stream) -7596 (clear-stream $_test-output-buffered-file->buffer) -7597 # var type/ecx: (handle tree type-id) = int -7598 68/push 0/imm32/right/null -7599 68/push 1/imm32/left/int -7600 89/<- %ecx 4/r32/esp -7601 # var var-var1/ecx: var in eax -7602 68/push "eax"/imm32/register -7603 68/push 0/imm32/no-stack-offset -7604 68/push 1/imm32/block-depth -7605 51/push-ecx -7606 68/push "var1"/imm32 -7607 89/<- %ecx 4/r32/esp -7608 # var type/edx: (handle tree type-id) = literal -7609 68/push 0/imm32/right/null -7610 68/push 0/imm32/left/literal -7611 89/<- %edx 4/r32/esp -7612 # var var-var2/edx: var literal -7613 68/push 0/imm32/no-register -7614 68/push 0/imm32/no-stack-offset -7615 68/push 1/imm32/block-depth -7616 52/push-edx -7617 68/push "0x34"/imm32 -7618 89/<- %edx 4/r32/esp -7619 # var inouts/esi: (list var2) -7620 68/push 0/imm32/next -7621 52/push-edx/var-var2 -7622 89/<- %esi 4/r32/esp -7623 # var inouts = (list var1 inouts) -7624 56/push-esi/next -7625 51/push-ecx/var-var1 -7626 89/<- %esi 4/r32/esp -7627 # var stmt/esi: statement -7628 68/push 0/imm32/next -7629 68/push 0/imm32/outputs -7630 56/push-esi/inouts -7631 68/push "compare"/imm32/operation -7632 68/push 1/imm32/regular-stmt -7633 89/<- %esi 4/r32/esp -7634 # convert -7635 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7636 (flush _test-output-buffered-file) -7637 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7643 # check output -7644 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") -7645 # . epilogue -7646 89/<- %esp 5/r32/ebp -7647 5d/pop-to-ebp -7648 c3/return -7649 -7650 test-compare-reg-with-literal: -7651 # compare var1/ecx 0x34 -7652 # => -7653 # 81 7/subop/compare %ecx 0x34/imm32 -7654 # -7655 # . prologue -7656 55/push-ebp -7657 89/<- %ebp 4/r32/esp -7658 # setup -7659 (clear-stream _test-output-stream) -7660 (clear-stream $_test-output-buffered-file->buffer) -7661 # var type/ecx: (handle tree type-id) = int -7662 68/push 0/imm32/right/null -7663 68/push 1/imm32/left/int -7664 89/<- %ecx 4/r32/esp -7665 # var var-var1/ecx: var in ecx -7666 68/push "ecx"/imm32/register -7667 68/push 0/imm32/no-stack-offset -7668 68/push 1/imm32/block-depth -7669 51/push-ecx -7670 68/push "var1"/imm32 -7671 89/<- %ecx 4/r32/esp -7672 # var type/edx: (handle tree type-id) = literal -7673 68/push 0/imm32/right/null -7674 68/push 0/imm32/left/literal -7675 89/<- %edx 4/r32/esp -7676 # var var-var2/edx: var literal -7677 68/push 0/imm32/no-register -7678 68/push 0/imm32/no-stack-offset -7679 68/push 1/imm32/block-depth -7680 52/push-edx -7681 68/push "0x34"/imm32 -7682 89/<- %edx 4/r32/esp -7683 # var inouts/esi: (list var2) -7684 68/push 0/imm32/next -7685 52/push-edx/var-var2 -7686 89/<- %esi 4/r32/esp -7687 # var inouts = (list var1 inouts) -7688 56/push-esi/next -7689 51/push-ecx/var-var1 -7690 89/<- %esi 4/r32/esp -7691 # var stmt/esi: statement -7692 68/push 0/imm32/next -7693 68/push 0/imm32/outputs -7694 56/push-esi/inouts -7695 68/push "compare"/imm32/operation -7696 68/push 1/imm32/regular-stmt -7697 89/<- %esi 4/r32/esp -7698 # convert -7699 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7700 (flush _test-output-buffered-file) -7701 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7707 # check output -7708 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") -7709 # . epilogue -7710 89/<- %esp 5/r32/ebp -7711 5d/pop-to-ebp -7712 c3/return -7713 -7714 test-emit-subx-statement-function-call: -7715 # Call a function on a variable on the stack. -7716 # f foo -7717 # => -7718 # (f2 *(ebp-8)) -7719 # (Changing the function name supports overloading in general, but here it -7720 # just serves to help disambiguate things.) -7721 # -7722 # There's a variable on the var stack as follows: -7723 # name: 'foo' -7724 # type: int -7725 # stack-offset: -8 -7726 # -7727 # There's nothing in primitives. -7728 # -7729 # There's a function with this info: -7730 # name: 'f' -7731 # inout: int/mem -7732 # value: 'f2' -7733 # -7734 # . prologue -7735 55/push-ebp -7736 89/<- %ebp 4/r32/esp -7737 # setup -7738 (clear-stream _test-output-stream) -7739 (clear-stream $_test-output-buffered-file->buffer) -7740 # var type/ecx: (handle tree type-id) = int -7741 68/push 0/imm32/right/null -7742 68/push 1/imm32/left/int -7743 89/<- %ecx 4/r32/esp -7744 # var var-foo/ecx: var -7745 68/push 0/imm32/no-register -7746 68/push -8/imm32/stack-offset -7747 68/push 0/imm32/block-depth -7748 51/push-ecx -7749 68/push "foo"/imm32 -7750 89/<- %ecx 4/r32/esp -7751 # var operands/esi: (list var) -7752 68/push 0/imm32/next -7753 51/push-ecx/var-foo -7754 89/<- %esi 4/r32/esp -7755 # var stmt/esi: statement -7756 68/push 0/imm32/next -7757 68/push 0/imm32/outputs -7758 56/push-esi/inouts -7759 68/push "f"/imm32/operation -7760 68/push 1/imm32 -7761 89/<- %esi 4/r32/esp -7762 # var functions/ebx: function -7763 68/push 0/imm32/next -7764 68/push 0/imm32/body -7765 68/push 0/imm32/outputs -7766 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -7767 68/push "f2"/imm32/subx-name -7768 68/push "f"/imm32/name -7769 89/<- %ebx 4/r32/esp -7770 # convert -7771 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) -7772 (flush _test-output-buffered-file) -7773 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7779 # check output -7780 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-statement-function-call") -7781 # . epilogue -7782 89/<- %esp 5/r32/ebp -7783 5d/pop-to-ebp -7784 c3/return -7785 -7786 test-emit-subx-statement-function-call-with-literal-arg: -7787 # Call a function on a literal. -7788 # f 34 -7789 # => -7790 # (f2 34) -7791 # -7792 # . prologue -7793 55/push-ebp -7794 89/<- %ebp 4/r32/esp -7795 # setup -7796 (clear-stream _test-output-stream) -7797 (clear-stream $_test-output-buffered-file->buffer) -7798 # var type/ecx: (handle tree type-id) = literal -7799 68/push 0/imm32/right/null -7800 68/push 0/imm32/left/literal -7801 89/<- %ecx 4/r32/esp -7802 # var var-foo/ecx: var literal -7803 68/push 0/imm32/no-register -7804 68/push 0/imm32/no-stack-offset -7805 68/push 0/imm32/block-depth -7806 51/push-ecx -7807 68/push "34"/imm32 -7808 89/<- %ecx 4/r32/esp -7809 # var operands/esi: (list var) -7810 68/push 0/imm32/next -7811 51/push-ecx/var-foo -7812 89/<- %esi 4/r32/esp -7813 # var stmt/esi: statement -7814 68/push 0/imm32/next -7815 68/push 0/imm32/outputs -7816 56/push-esi/inouts -7817 68/push "f"/imm32/operation -7818 68/push 1/imm32 -7819 89/<- %esi 4/r32/esp -7820 # var functions/ebx: function -7821 68/push 0/imm32/next -7822 68/push 0/imm32/body -7823 68/push 0/imm32/outputs -7824 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -7825 68/push "f2"/imm32/subx-name -7826 68/push "f"/imm32/name -7827 89/<- %ebx 4/r32/esp -7828 # convert -7829 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) -7830 (flush _test-output-buffered-file) -7831 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7837 # check output -7838 (check-next-stream-line-equal _test-output-stream "(f2 34)" "F - test-emit-subx-statement-function-call-with-literal-arg") -7839 # . epilogue -7840 89/<- %esp 5/r32/ebp -7841 5d/pop-to-ebp -7842 c3/return -7843 -7844 emit-subx-prologue: # out: (addr buffered-file) -7845 # . prologue -7846 55/push-ebp -7847 89/<- %ebp 4/r32/esp -7848 # -7849 (write-buffered *(ebp+8) "# . prologue\n") -7850 (write-buffered *(ebp+8) "55/push-ebp\n") -7851 (write-buffered *(ebp+8) "89/<- %ebp 4/r32/esp\n") -7852 $emit-subx-prologue:end: -7853 # . epilogue -7854 89/<- %esp 5/r32/ebp -7855 5d/pop-to-ebp -7856 c3/return -7857 -7858 emit-subx-epilogue: # out: (addr buffered-file) -7859 # . prologue -7860 55/push-ebp -7861 89/<- %ebp 4/r32/esp -7862 # -7863 (write-buffered *(ebp+8) "# . epilogue\n") -7864 (write-buffered *(ebp+8) "89/<- %esp 5/r32/ebp\n") -7865 (write-buffered *(ebp+8) "5d/pop-to-ebp\n") -7866 (write-buffered *(ebp+8) "c3/return\n") -7867 $emit-subx-epilogue:end: -7868 # . epilogue -7869 89/<- %esp 5/r32/ebp -7870 5d/pop-to-ebp -7871 c3/return +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 -- cgit 1.4.1-2-gfad0