From ce29c91c9c271b27e97356e9bade8298f1612ce1 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sun, 16 Feb 2020 20:15:25 -0800 Subject: 6012 --- html/apps/mu.subx.html | 12594 +++++++++++++++++++++++------------------------ 1 file changed, 6264 insertions(+), 6330 deletions(-) (limited to 'html/apps/mu.subx.html') diff --git a/html/apps/mu.subx.html b/html/apps/mu.subx.html index 92d08cf4..f443d400 100644 --- a/html/apps/mu.subx.html +++ b/html/apps/mu.subx.html @@ -451,8 +451,8 @@ if ('onhashchange' in window) { 389 89/<- %ebp 4/r32/esp 390 # 391 (parse-mu *(ebp+8)) - 392 (check-mu-types) - 393 (emit-subx *(ebp+0xc)) + 392 (check-mu-types) + 393 (emit-subx *(ebp+0xc)) 394 $convert-mu:end: 395 # . epilogue 396 89/<- %esp 5/r32/ebp @@ -493,7 +493,7 @@ if ('onhashchange' in window) { 431 # convert 432 (convert-mu _test-input-buffered-file _test-output-buffered-file) 433 (flush _test-output-buffered-file) - 434 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 434 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 440 # check output 441 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-skeleton/0") 442 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-skeleton/1") @@ -525,7 +525,7 @@ if ('onhashchange' in window) { 468 # convert 469 (convert-mu _test-input-buffered-file _test-output-buffered-file) 470 (flush _test-output-buffered-file) - 471 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 471 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 477 # check first function 478 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-multiple-function-skeletons/0") 479 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/1") @@ -559,12 +559,12 @@ if ('onhashchange' in window) { 507 (clear-stream _test-output-stream) 508 (clear-stream $_test-output-buffered-file->buffer) 509 # - 510 (write _test-input-stream "fn foo n : int {\n") + 510 (write _test-input-stream "fn foo n: int {\n") 511 (write _test-input-stream "}\n") 512 # convert 513 (convert-mu _test-input-buffered-file _test-output-buffered-file) 514 (flush _test-output-buffered-file) - 515 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 515 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 521 # check output 522 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg/0") 523 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg/1") @@ -588,15 +588,15 @@ if ('onhashchange' in window) { 541 (clear-stream $_test-input-buffered-file->buffer) 542 (clear-stream _test-output-stream) 543 (clear-stream $_test-output-buffered-file->buffer) - 544 c7 0/subop/copy *Next-block-index 1/imm32 + 544 c7 0/subop/copy *Next-block-index 1/imm32 545 # - 546 (write _test-input-stream "fn foo n : int {\n") + 546 (write _test-input-stream "fn foo n: int {\n") 547 (write _test-input-stream " increment n\n") 548 (write _test-input-stream "}\n") 549 # convert 550 (convert-mu _test-input-buffered-file _test-output-buffered-file) 551 (flush _test-output-buffered-file) - 552 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 552 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 558 # check output 559 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg-and-body/0") 560 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg-and-body/1") @@ -625,7 +625,7 @@ if ('onhashchange' in window) { 583 (clear-stream $_test-input-buffered-file->buffer) 584 (clear-stream _test-output-stream) 585 (clear-stream $_test-output-buffered-file->buffer) - 586 c7 0/subop/copy *Next-block-index 1/imm32 + 586 c7 0/subop/copy *Next-block-index 1/imm32 587 # 588 (write _test-input-stream "fn foo a: int, b: int {\n") 589 (write _test-input-stream " increment b\n") @@ -633,7 +633,7 @@ if ('onhashchange' in window) { 591 # convert 592 (convert-mu _test-input-buffered-file _test-output-buffered-file) 593 (flush _test-output-buffered-file) - 594 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 594 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 600 # check output 601 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-distinguishes-args/0") 602 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-distinguishes-args/1") @@ -662,7 +662,7 @@ if ('onhashchange' in window) { 625 (clear-stream $_test-input-buffered-file->buffer) 626 (clear-stream _test-output-stream) 627 (clear-stream $_test-output-buffered-file->buffer) - 628 c7 0/subop/copy *Next-block-index 1/imm32 + 628 c7 0/subop/copy *Next-block-index 1/imm32 629 # 630 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") 631 (write _test-input-stream " result <- copy a\n") @@ -671,7 +671,7 @@ if ('onhashchange' in window) { 634 # convert 635 (convert-mu _test-input-buffered-file _test-output-buffered-file) 636 (flush _test-output-buffered-file) - 637 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 637 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 643 # check output 644 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-returns-result/0") 645 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-returns-result/1") @@ -701,7 +701,7 @@ if ('onhashchange' in window) { 669 (clear-stream $_test-input-buffered-file->buffer) 670 (clear-stream _test-output-stream) 671 (clear-stream $_test-output-buffered-file->buffer) - 672 c7 0/subop/copy *Next-block-index 1/imm32 + 672 c7 0/subop/copy *Next-block-index 1/imm32 673 # 674 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") 675 (write _test-input-stream " result <- copy a\n") @@ -710,7 +710,7 @@ if ('onhashchange' in window) { 678 # convert 679 (convert-mu _test-input-buffered-file _test-output-buffered-file) 680 (flush _test-output-buffered-file) - 681 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 681 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 687 # check output 688 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-literal-arg/0") 689 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-literal-arg/1") @@ -740,7 +740,7 @@ if ('onhashchange' in window) { 713 (clear-stream $_test-input-buffered-file->buffer) 714 (clear-stream _test-output-stream) 715 (clear-stream $_test-output-buffered-file->buffer) - 716 c7 0/subop/copy *Next-block-index 1/imm32 + 716 c7 0/subop/copy *Next-block-index 1/imm32 717 # 718 (write _test-input-stream "fn foo a: int, b: int -> result/ebx: int {\n") 719 (write _test-input-stream " result <- copy a\n") @@ -749,7 +749,7 @@ if ('onhashchange' in window) { 722 # convert 723 (convert-mu _test-input-buffered-file _test-output-buffered-file) 724 (flush _test-output-buffered-file) - 725 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 725 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 731 # check output 732 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-literal-arg-2/0") 733 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-literal-arg-2/1") @@ -779,7 +779,7 @@ if ('onhashchange' in window) { 757 (clear-stream $_test-input-buffered-file->buffer) 758 (clear-stream _test-output-stream) 759 (clear-stream $_test-output-buffered-file->buffer) - 760 c7 0/subop/copy *Next-block-index 1/imm32 + 760 c7 0/subop/copy *Next-block-index 1/imm32 761 # 762 (write _test-input-stream "fn main -> result/ebx: int {\n") 763 (write _test-input-stream " result <- do-add 3 4\n") @@ -791,7 +791,7 @@ if ('onhashchange' in window) { 769 # convert 770 (convert-mu _test-input-buffered-file _test-output-buffered-file) 771 (flush _test-output-buffered-file) - 772 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 772 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 778 # check output 779 (check-next-stream-line-equal _test-output-stream "main:" "F - test-convert-function-call-with-literal-arg/0") 780 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/1") @@ -834,7 +834,7 @@ if ('onhashchange' in window) { 817 (clear-stream $_test-input-buffered-file->buffer) 818 (clear-stream _test-output-stream) 819 (clear-stream $_test-output-buffered-file->buffer) - 820 c7 0/subop/copy *Next-block-index 1/imm32 + 820 c7 0/subop/copy *Next-block-index 1/imm32 821 # 822 (write _test-input-stream "fn foo {\n") 823 (write _test-input-stream " var x: int\n") @@ -843,7 +843,7 @@ if ('onhashchange' in window) { 826 # convert 827 (convert-mu _test-input-buffered-file _test-output-buffered-file) 828 (flush _test-output-buffered-file) - 829 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 829 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 835 # check output 836 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-mem/0") 837 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-mem/1") @@ -874,7 +874,7 @@ if ('onhashchange' in window) { 862 (clear-stream $_test-input-buffered-file->buffer) 863 (clear-stream _test-output-stream) 864 (clear-stream $_test-output-buffered-file->buffer) - 865 c7 0/subop/copy *Next-block-index 1/imm32 + 865 c7 0/subop/copy *Next-block-index 1/imm32 866 # 867 (write _test-input-stream "fn foo {\n") 868 (write _test-input-stream " var x/ecx: int <- copy 3\n") @@ -883,7 +883,7 @@ if ('onhashchange' in window) { 871 # convert 872 (convert-mu _test-input-buffered-file _test-output-buffered-file) 873 (flush _test-output-buffered-file) - 874 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 874 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 880 # check output 881 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-reg/0") 882 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-reg/1") @@ -915,7 +915,7 @@ if ('onhashchange' in window) { 908 (clear-stream $_test-input-buffered-file->buffer) 909 (clear-stream _test-output-stream) 910 (clear-stream $_test-output-buffered-file->buffer) - 911 c7 0/subop/copy *Next-block-index 1/imm32 + 911 c7 0/subop/copy *Next-block-index 1/imm32 912 # 913 (write _test-input-stream "fn foo {\n") 914 (write _test-input-stream " {\n") @@ -926,7 +926,7 @@ if ('onhashchange' in window) { 919 # convert 920 (convert-mu _test-input-buffered-file _test-output-buffered-file) 921 (flush _test-output-buffered-file) - 922 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 922 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 928 # check output 929 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-block/0") 930 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-block/1") @@ -961,7 +961,7 @@ if ('onhashchange' in window) { 959 (clear-stream $_test-input-buffered-file->buffer) 960 (clear-stream _test-output-stream) 961 (clear-stream $_test-output-buffered-file->buffer) - 962 c7 0/subop/copy *Next-block-index 1/imm32 + 962 c7 0/subop/copy *Next-block-index 1/imm32 963 # 964 (write _test-input-stream "fn foo {\n") 965 (write _test-input-stream " $bar: {\n") @@ -972,7 +972,7 @@ if ('onhashchange' in window) { 970 # convert 971 (convert-mu _test-input-buffered-file _test-output-buffered-file) 972 (flush _test-output-buffered-file) - 973 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 973 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 979 # check output 980 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-named-block/0") 981 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-named-block/1") @@ -1007,7 +1007,7 @@ if ('onhashchange' in window) { 1010 (clear-stream $_test-input-buffered-file->buffer) 1011 (clear-stream _test-output-stream) 1012 (clear-stream $_test-output-buffered-file->buffer) -1013 c7 0/subop/copy *Next-block-index 1/imm32 +1013 c7 0/subop/copy *Next-block-index 1/imm32 1014 # 1015 (write _test-input-stream "fn foo x: int {\n") 1016 (write _test-input-stream " {\n") @@ -1020,7 +1020,7 @@ if ('onhashchange' in window) { 1023 # convert 1024 (convert-mu _test-input-buffered-file _test-output-buffered-file) 1025 (flush _test-output-buffered-file) -1026 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1026 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 1032 # check output 1033 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-block/0") 1034 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-block/1") @@ -1056,7 +1056,7 @@ if ('onhashchange' in window) { 1064 (clear-stream $_test-input-buffered-file->buffer) 1065 (clear-stream _test-output-stream) 1066 (clear-stream $_test-output-buffered-file->buffer) -1067 c7 0/subop/copy *Next-block-index 1/imm32 +1067 c7 0/subop/copy *Next-block-index 1/imm32 1068 # 1069 (write _test-input-stream "fn foo x: int {\n") 1070 (write _test-input-stream " $bar: {\n") @@ -1069,7 +1069,7 @@ if ('onhashchange' in window) { 1077 # convert 1078 (convert-mu _test-input-buffered-file _test-output-buffered-file) 1079 (flush _test-output-buffered-file) -1080 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1080 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 1086 # check output 1087 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-named-block/0") 1088 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-named-block/1") @@ -1105,7 +1105,7 @@ if ('onhashchange' in window) { 1118 (clear-stream $_test-input-buffered-file->buffer) 1119 (clear-stream _test-output-stream) 1120 (clear-stream $_test-output-buffered-file->buffer) -1121 c7 0/subop/copy *Next-block-index 1/imm32 +1121 c7 0/subop/copy *Next-block-index 1/imm32 1122 # 1123 (write _test-input-stream "fn foo x: int {\n") 1124 (write _test-input-stream " {\n") @@ -1118,7 +1118,7 @@ if ('onhashchange' in window) { 1131 # convert 1132 (convert-mu _test-input-buffered-file _test-output-buffered-file) 1133 (flush _test-output-buffered-file) -1134 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1134 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 1140 # check output 1141 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-var-in-nested-block/0") 1142 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-var-in-nested-block/1") @@ -1157,7 +1157,7 @@ if ('onhashchange' in window) { 1175 (clear-stream $_test-input-buffered-file->buffer) 1176 (clear-stream _test-output-stream) 1177 (clear-stream $_test-output-buffered-file->buffer) -1178 c7 0/subop/copy *Next-block-index 1/imm32 +1178 c7 0/subop/copy *Next-block-index 1/imm32 1179 # 1180 (write _test-input-stream "fn foo x: int {\n") 1181 (write _test-input-stream " {\n") @@ -1171,7 +1171,7 @@ if ('onhashchange' in window) { 1189 # convert 1190 (convert-mu _test-input-buffered-file _test-output-buffered-file) 1191 (flush _test-output-buffered-file) -1192 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1192 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 1198 # check output 1199 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/0") 1200 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-multiple-vars-in-nested-blocks/1") @@ -1216,7 +1216,7 @@ if ('onhashchange' in window) { 1239 (clear-stream $_test-input-buffered-file->buffer) 1240 (clear-stream _test-output-stream) 1241 (clear-stream $_test-output-buffered-file->buffer) -1242 c7 0/subop/copy *Next-block-index 1/imm32 +1242 c7 0/subop/copy *Next-block-index 1/imm32 1243 # 1244 (write _test-input-stream "fn foo {\n") 1245 (write _test-input-stream " {\n") @@ -1228,7 +1228,7 @@ if ('onhashchange' in window) { 1251 # convert 1252 (convert-mu _test-input-buffered-file _test-output-buffered-file) 1253 (flush _test-output-buffered-file) -1254 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1254 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 1260 # check output 1261 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-local-vars/0") 1262 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-local-vars/1") @@ -1271,7 +1271,7 @@ if ('onhashchange' in window) { 1299 (clear-stream $_test-input-buffered-file->buffer) 1300 (clear-stream _test-output-stream) 1301 (clear-stream $_test-output-buffered-file->buffer) -1302 c7 0/subop/copy *Next-block-index 1/imm32 +1302 c7 0/subop/copy *Next-block-index 1/imm32 1303 # 1304 (write _test-input-stream "fn foo {\n") 1305 (write _test-input-stream " {\n") @@ -1283,7 +1283,7 @@ if ('onhashchange' in window) { 1311 # convert 1312 (convert-mu _test-input-buffered-file _test-output-buffered-file) 1313 (flush _test-output-buffered-file) -1314 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1314 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 1320 # check output 1321 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-conditional-loops-and-local-vars/0") 1322 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-conditional-loops-and-local-vars/1") @@ -1326,7 +1326,7 @@ if ('onhashchange' in window) { 1359 (clear-stream $_test-input-buffered-file->buffer) 1360 (clear-stream _test-output-stream) 1361 (clear-stream $_test-output-buffered-file->buffer) -1362 c7 0/subop/copy *Next-block-index 1/imm32 +1362 c7 0/subop/copy *Next-block-index 1/imm32 1363 # 1364 (write _test-input-stream "fn foo {\n") 1365 (write _test-input-stream " {\n") @@ -1338,7 +1338,7 @@ if ('onhashchange' in window) { 1371 # convert 1372 (convert-mu _test-input-buffered-file _test-output-buffered-file) 1373 (flush _test-output-buffered-file) -1374 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1374 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 1380 # check output 1381 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-unconditional-loops-and-local-vars/0") 1382 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-unconditional-loops-and-local-vars/1") @@ -1374,7 +1374,7 @@ if ('onhashchange' in window) { 1412 (clear-stream $_test-input-buffered-file->buffer) 1413 (clear-stream _test-output-stream) 1414 (clear-stream $_test-output-buffered-file->buffer) -1415 c7 0/subop/copy *Next-block-index 1/imm32 +1415 c7 0/subop/copy *Next-block-index 1/imm32 1416 # 1417 (write _test-input-stream "fn foo {\n") 1418 (write _test-input-stream " {\n") @@ -1387,7 +1387,7 @@ if ('onhashchange' in window) { 1425 # convert 1426 (convert-mu _test-input-buffered-file _test-output-buffered-file) 1427 (flush _test-output-buffered-file) -1428 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1428 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 1434 # check output 1435 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-loops-and-local-vars/0") 1436 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-loops-and-local-vars/1") @@ -1428,7 +1428,7 @@ if ('onhashchange' in window) { 1471 (clear-stream $_test-input-buffered-file->buffer) 1472 (clear-stream _test-output-stream) 1473 (clear-stream $_test-output-buffered-file->buffer) -1474 c7 0/subop/copy *Next-block-index 1/imm32 +1474 c7 0/subop/copy *Next-block-index 1/imm32 1475 # 1476 (write _test-input-stream "fn foo {\n") 1477 (write _test-input-stream " a: {\n") @@ -1444,7 +1444,7 @@ if ('onhashchange' in window) { 1487 # convert 1488 (convert-mu _test-input-buffered-file _test-output-buffered-file) 1489 (flush _test-output-buffered-file) -1490 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1490 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 1496 # check output 1497 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0") 1498 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1") @@ -1545,8 +1545,8 @@ if ('onhashchange' in window) { 1593 # if (line->write == 0) break 1594 81 7/subop/compare *ecx 0/imm32 1595 0f 84/jump-if-= break/disp32 -1596 +-- 6 lines: #? # dump line --------------------------------------------------------------------------------------------------------------------------- -1602 (next-mu-token %ecx %edx) +1596 +-- 6 lines: #? # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------ +1602 (next-mu-token %ecx %edx) 1603 # if slice-empty?(word-slice) continue 1604 (slice-empty? %edx) 1605 3d/compare-eax-and 0/imm32 @@ -1570,7 +1570,7 @@ if ('onhashchange' in window) { 1623 (zero-out %eax *Function-size) 1624 (clear-stack %ebx) 1625 (populate-mu-function-header %ecx %eax %ebx) -1626 (populate-mu-function-body *(ebp+8) %eax %ebx) +1626 (populate-mu-function-body *(ebp+8) %eax %ebx) 1627 # *curr-function = new-function 1628 89/<- *edi 0/r32/eax 1629 # curr-function = &new-function->next @@ -1633,14 +1633,14 @@ if ('onhashchange' in window) { 1686 populate-mu-function-header: # first-line: (addr stream byte), out: (handle function), vars: (addr stack (handle var)) 1687 # pseudocode: 1688 # var name: slice -1689 # next-word(first-line, name) +1689 # next-mu-token(first-line, name) 1690 # assert(name not in '{' '}' '->') 1691 # out->name = slice-to-string(name) 1692 # var next-offset: int = 8 1693 # ## inouts 1694 # while true 1695 # ## name -1696 # name = next-word(first-line) +1696 # name = next-mu-token(first-line) 1697 # if (name == '{') goto done 1698 # if (name == '->') break 1699 # assert(name != '}') @@ -1654,7 +1654,7 @@ if ('onhashchange' in window) { 1707 # ## outputs 1708 # while true 1709 # ## name -1710 # name = next-word(first-line) +1710 # name = next-mu-token(first-line) 1711 # assert(name not in '{' '}' '->') 1712 # var v: (handle var) = parse-var-with-type(name, first-line) 1713 # assert(v->register != null) @@ -1679,7 +1679,7 @@ if ('onhashchange' in window) { 1732 # var next-offset/edx = 8 1733 ba/copy-to-edx 8/imm32 1734 # read function name -1735 (next-word *(ebp+8) %ecx) +1735 (next-mu-token *(ebp+8) %ecx) 1736 # error checking 1737 # TODO: error if name starts with 'break' or 'loop' 1738 # if (word-slice == '{') abort @@ -1702,7 +1702,7 @@ if ('onhashchange' in window) { 1755 # save function inouts 1756 { 1757 $populate-mu-function-header:check-for-inout: -1758 (next-word *(ebp+8) %ecx) +1758 (next-mu-token *(ebp+8) %ecx) 1759 # if (word-slice == '{') goto done 1760 (slice-equal? %ecx "{") # => eax 1761 3d/compare-eax-and 0/imm32 @@ -1716,7 +1716,7 @@ if ('onhashchange' in window) { 1769 3d/compare-eax-and 0/imm32 1770 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 1771 # var v/ebx: (handle var) = parse-var-with-type(word-slice, first-line) -1772 (parse-var-with-type %ecx *(ebp+8)) # => eax +1772 (parse-var-with-type %ecx *(ebp+8)) # => eax 1773 89/<- %ebx 0/r32/eax 1774 # assert(v->register == null) 1775 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register @@ -1724,11 +1724,11 @@ if ('onhashchange' in window) { 1777 # v->stack-offset = next-offset 1778 89/<- *(ebx+0xc) 2/r32/edx # Var-stack-offset 1779 # next-offset += size-of(v) -1780 (size-of %ebx) # => eax +1780 (size-of %ebx) # => eax 1781 01/add %edx 0/r32/eax 1782 # v->block-depth is implicitly 0 1783 # -1784 (append-list Heap %ebx *(edi+8)) # Function-inouts => eax +1784 (append-list Heap %ebx *(edi+8)) # Function-inouts => eax 1785 89/<- *(edi+8) 0/r32/eax # Function-inouts 1786 (push *(ebp+0x10) %ebx) 1787 # @@ -1736,8 +1736,8 @@ if ('onhashchange' in window) { 1789 } 1790 # save function outputs 1791 { -1792 $parse-var-with-type:check-for-out: -1793 (next-word *(ebp+8) %ecx) +1792 $populate-mu-function-header:check-for-out: +1793 (next-mu-token *(ebp+8) %ecx) 1794 # if (word-slice == '{') break 1795 (slice-equal? %ecx "{") # => eax 1796 3d/compare-eax-and 0/imm32 @@ -1751,17 +1751,17 @@ if ('onhashchange' in window) { 1804 3d/compare-eax-and 0/imm32 1805 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 1806 # -1807 (parse-var-with-type %ecx *(ebp+8)) # => eax +1807 (parse-var-with-type %ecx *(ebp+8)) # => eax 1808 89/<- %ebx 0/r32/eax 1809 # assert(var->register != null) 1810 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register 1811 0f 84/jump-if-= $populate-mu-function-header:error3/disp32 -1812 (append-list Heap %ebx *(edi+0xc)) # Function-outputs => eax +1812 (append-list Heap %ebx *(edi+0xc)) # Function-outputs => eax 1813 89/<- *(edi+0xc) 0/r32/eax # Function-outputs 1814 e9/jump loop/disp32 1815 } 1816 $populate-mu-function-header:done: -1817 (check-no-tokens-left *(ebp+8)) +1817 (check-no-tokens-left *(ebp+8)) 1818 $populate-mu-function-header:end: 1819 # . reclaim locals 1820 81 0/subop/add %esp 8/imm32 @@ -1824,7 +1824,7 @@ if ('onhashchange' in window) { 1877 89/<- %ebp 4/r32/esp 1878 # setup 1879 (clear-stream _test-input-stream) -1880 (write _test-input-stream "foo n : int {\n") +1880 (write _test-input-stream "foo n: int {\n") 1881 # var result/ecx: function 1882 2b/subtract-> *Function-size 4/r32/esp 1883 89/<- %ecx 4/r32/esp @@ -1972,1740 +1972,1740 @@ if ('onhashchange' in window) { 2025 2026 # format for variables with types 2027 # x: int -2028 # x: int -2029 # x: int, -2030 # ignores at most one trailing colon or comma -2031 parse-var-with-type: # name: (addr slice), first-line: (addr stream byte) -> result/eax: (handle var) -2032 # pseudocode: -2033 # var v: (handle var) = allocate(Heap, Var-size) -2034 # var s: slice -2035 # next-token-from-slice(name->start, name->end, '/', s) -2036 # var end: (addr byte) = s->end -2037 # if (slice-ends-with(s, ":")) -2038 # decrement s->end -2039 # if (slice-ends-with(s, ",")) -2040 # decrement s->end +2028 # x: int, +2029 # x/eax: int +2030 # x/eax: int, +2031 # ignores at most one trailing comma +2032 # WARNING: modifies name +2033 parse-var-with-type: # name: (addr slice), first-line: (addr stream byte) -> result/eax: (handle var) +2034 # pseudocode: +2035 # var v: (handle var) = allocate(Heap, Var-size) +2036 # var s: slice +2037 # if (!slice-ends-with(name, ":")) +2038 # abort +2039 # --name->end to skip ':' +2040 # next-token-from-slice(name->start, name->end, '/', s) 2041 # v->name = slice-to-string(s) 2042 # ## register -2043 # next-token-from-slice(end, name->end, '/', s) -2044 # if (slice-ends-with(s, ":")) -2045 # decrement s->end -2046 # if (slice-ends-with(s, ",")) -2047 # decrement s->end -2048 # if (!slice-empty?(s)) -2049 # v->register = slice-to-string(s) -2050 # ## type -2051 # var type: (handle tree type-id) = parse-type(first-line) -2052 # v->type = type -2053 # return v -2054 # -2055 # . prologue -2056 55/push-ebp -2057 89/<- %ebp 4/r32/esp -2058 # . save registers -2059 51/push-ecx -2060 52/push-edx -2061 53/push-ebx -2062 56/push-esi -2063 57/push-edi -2064 # var result/edi: (handle var) = allocate(Heap, Var-size) -2065 (allocate Heap *Var-size) # => eax -2066 (zero-out %eax *Var-size) -2067 89/<- %edi 0/r32/eax -2068 # esi = name -2069 8b/-> *(ebp+8) 6/r32/esi -2070 # var s/ecx: slice -2071 68/push 0/imm32/end -2072 68/push 0/imm32/start -2073 89/<- %ecx 4/r32/esp -2074 $parse-var-with-type:save-name: -2075 # save v->name -2076 (next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/' -2077 # . end/edx = s->end -2078 8b/-> *(ecx+4) 2/r32/edx -2079 # . if s ends with ':', decrement s->end -2080 { -2081 8b/-> *(ecx+4) 0/r32/eax -2082 48/decrement-eax -2083 8a/copy-byte *eax 3/r32/BL -2084 81 4/subop/and %ebx 0xff/imm32 -2085 81 7/subop/compare %ebx 0x3a/imm32/colon -2086 75/jump-if-!= break/disp8 -2087 89/<- *(ecx+4) 0/r32/eax -2088 } -2089 # . if s ends with ',', decrement s->end -2090 { -2091 8b/-> *(ecx+4) 0/r32/eax -2092 48/decrement-eax -2093 8a/copy-byte *eax 3/r32/BL -2094 81 4/subop/and %ebx 0xff/imm32 -2095 81 7/subop/compare %ebx 0x2c/imm32/comma -2096 75/jump-if-!= break/disp8 -2097 89/<- *(ecx+4) 0/r32/eax +2043 # next-token-from-slice(s->end, name->end, '/', s) +2044 # if (!slice-empty?(s)) +2045 # v->register = slice-to-string(s) +2046 # ## type +2047 # var type: (handle tree type-id) = parse-type(first-line) +2048 # v->type = type +2049 # return v +2050 # +2051 # . prologue +2052 55/push-ebp +2053 89/<- %ebp 4/r32/esp +2054 # . save registers +2055 51/push-ecx +2056 52/push-edx +2057 53/push-ebx +2058 56/push-esi +2059 57/push-edi +2060 # esi = name +2061 8b/-> *(ebp+8) 6/r32/esi +2062 # if (!slice-ends-with?(name, ":")) abort +2063 8b/-> *(esi+4) 1/r32/ecx # Slice-end +2064 49/decrement-ecx +2065 8a/copy-byte *ecx 1/r32/CL +2066 81 4/subop/and %ecx 0xff/imm32 +2067 81 7/subop/compare %ecx 0x3a/imm32/colon +2068 0f 85/jump-if-!= $parse-var-with-type:abort/disp32 +2069 # --name->end to skip ':' +2070 ff 1/subop/decrement *(esi+4) +2071 # var result/edi: (handle var) = allocate(Heap, Var-size) +2072 (allocate Heap *Var-size) # => eax +2073 (zero-out %eax *Var-size) +2074 89/<- %edi 0/r32/eax +2075 # var s/ecx: slice +2076 68/push 0/imm32/end +2077 68/push 0/imm32/start +2078 89/<- %ecx 4/r32/esp +2079 $parse-var-with-type:save-name: +2080 # save v->name +2081 (next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/' +2082 # . end/edx = s->end +2083 8b/-> *(ecx+4) 2/r32/edx +2084 $parse-var-with-type:write-name: +2085 (slice-to-string Heap %ecx) # => eax +2086 89/<- *edi 0/r32/eax # Var-name +2087 # save v->register +2088 $parse-var-with-type:save-register: +2089 (next-token-from-slice %edx *(esi+4) 0x2f %ecx) # end, name->end, '/' +2090 # if (!slice-empty?(s)) v->register = slice-to-string(s) +2091 { +2092 $parse-var-with-type:write-register: +2093 (slice-empty? %ecx) # => eax +2094 3d/compare-eax-and 0/imm32/false +2095 75/jump-if-!= break/disp8 +2096 (slice-to-string Heap %ecx) +2097 89/<- *(edi+0x10) 0/r32/eax # Var-register 2098 } -2099 $parse-var-with-type:write-name: -2100 (slice-to-string Heap %ecx) # => eax -2101 89/<- *edi 0/r32/eax # Var-name -2102 # save v->register -2103 $parse-var-with-type:save-register: -2104 (next-token-from-slice %edx *(esi+4) 0x2f %ecx) # end, name->end, '/' -2105 # . if s ends with ':', decrement s->end -2106 { -2107 8b/-> *(ecx+4) 0/r32/eax -2108 48/decrement-eax -2109 8a/copy-byte *eax 3/r32/BL -2110 81 4/subop/and %ebx 0xff/imm32 -2111 81 7/subop/compare %ebx 0x3a/imm32/colon -2112 75/jump-if-!= break/disp8 -2113 89/<- *(ecx+4) 0/r32/eax -2114 } -2115 # . if s ends with ',', decrement s->end -2116 { -2117 8b/-> *(ecx+4) 0/r32/eax -2118 48/decrement-eax -2119 8a/copy-byte *eax 3/r32/BL -2120 81 4/subop/and %ebx 0xff/imm32 -2121 81 7/subop/compare %ebx 0x2c/imm32/comma -2122 75/jump-if-!= break/disp8 -2123 89/<- *(ecx+4) 0/r32/eax -2124 } -2125 # if (!slice-empty?(s)) v->register = slice-to-string(s) -2126 { -2127 $parse-var-with-type:write-register: -2128 # HACK: s->end can be less than s->start with all the decrements above -2129 # That's probably a sign we have the wrong algorithm for this function. -2130 8b/-> *ecx 0/r32/eax -2131 39/compare *(ecx+4) 0/r32/eax # Slice-end -2132 76/jump-if-<= break/disp8 -2133 (slice-to-string Heap %ecx) -2134 89/<- *(edi+0x10) 0/r32/eax # Var-register -2135 } -2136 $parse-var-with-type:save-type: -2137 (parse-type Heap *(ebp+0xc)) # => eax -2138 89/<- *(edi+4) 0/r32/eax # Var-type -2139 $parse-var-with-type:end: -2140 # return result -2141 89/<- %eax 7/r32/edi -2142 # . reclaim locals -2143 81 0/subop/add %esp 8/imm32 -2144 # . restore registers -2145 5f/pop-to-edi -2146 5e/pop-to-esi -2147 5b/pop-to-ebx -2148 5a/pop-to-edx -2149 59/pop-to-ecx -2150 # . epilogue -2151 89/<- %esp 5/r32/ebp -2152 5d/pop-to-ebp -2153 c3/return -2154 -2155 $parse-var-with-type:abort: -2156 # error("function header not in form 'fn <name> {'") -2157 (write-buffered Stderr "var should have form 'name: type' in '") -2158 (flush Stderr) -2159 (rewind-stream *(ebp+0xc)) -2160 (write-stream 2 *(ebp+0xc)) -2161 (write-buffered Stderr "'\n") -2162 (flush Stderr) -2163 # . syscall(exit, 1) -2164 bb/copy-to-ebx 1/imm32 -2165 b8/copy-to-eax 1/imm32/exit -2166 cd/syscall 0x80/imm8 -2167 # never gets here -2168 -2169 parse-type: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) -2170 # pseudocode: -2171 # var s: slice = next-mu-token(in) -2172 # assert s != "" -2173 # assert s != "->" -2174 # assert s != "{" -2175 # assert s != "}" -2176 # if s == ")" -2177 # return 0 -2178 # result = allocate(Tree) -2179 # zero-out(result, *Tree-size) -2180 # if s != "(" -2181 # result->left = pos-slice(Type-id, s) -2182 # return -2183 # result->left = parse-type(ad, in) -2184 # result->right = parse-type-tree(ad, in) -2185 # -2186 # . prologue -2187 55/push-ebp -2188 89/<- %ebp 4/r32/esp -2189 # . save registers -2190 51/push-ecx -2191 52/push-edx -2192 # var s/ecx: slice -2193 68/push 0/imm32 -2194 68/push 0/imm32 -2195 89/<- %ecx 4/r32/esp -2196 # s = next-mu-token(in) -2197 (next-mu-token *(ebp+0xc) %ecx) -2198 #? (write-buffered Stderr "tok: ") -2199 #? (write-slice-buffered Stderr %ecx) -2200 #? (write-buffered Stderr "$\n") -2201 #? (flush Stderr) -2202 # assert s != "" -2203 (slice-equal? %ecx "") -2204 3d/compare-eax-and 0/imm32 -2205 0f 85/jump-if-!= $parse-type:abort/disp32 -2206 # assert s != "{" -2207 (slice-equal? %ecx "{") -2208 3d/compare-eax-and 0/imm32 -2209 0f 85/jump-if-!= $parse-type:abort/disp32 -2210 # assert s != "}" -2211 (slice-equal? %ecx "}") -2212 3d/compare-eax-and 0/imm32 -2213 0f 85/jump-if-!= $parse-type:abort/disp32 -2214 # assert s != "->" -2215 (slice-equal? %ecx "->") -2216 3d/compare-eax-and 0/imm32 -2217 0f 85/jump-if-!= $parse-type:abort/disp32 -2218 # if (s == ")") return 0 -2219 (slice-equal? %ecx ")") -2220 3d/compare-eax-and 0/imm32 -2221 b8/copy-to-eax 0/imm32 -2222 0f 85/jump-if-!= $parse-type:end/disp32 -2223 # var result/edx: (handle tree type-id) -2224 (allocate *(ebp+8) *Tree-size) # => eax -2225 (zero-out %eax *Tree-size) -2226 89/<- %edx 0/r32/eax -2227 { -2228 # if (s != "(") break -2229 (slice-equal? %ecx "(") -2230 3d/compare-eax-and 0/imm32 -2231 75/jump-if-!= break/disp8 -2232 # result->left = pos-slice(Type-id, s) -2233 (pos-slice Type-id %ecx) -2234 #? (write-buffered Stderr "=> {") -2235 #? (print-int32-buffered Stderr %eax) -2236 #? (write-buffered Stderr ", 0}\n") -2237 #? (flush Stderr) -2238 89/<- *edx 0/r32/eax # Tree-left -2239 e9/jump $parse-type:return-edx/disp32 -2240 } -2241 # otherwise s == "(" -2242 # result->left = parse-type(ad, in) -2243 (parse-type *(ebp+8) *(ebp+0xc)) -2244 #? (write-buffered Stderr "=> {") -2245 #? (print-int32-buffered Stderr %eax) -2246 89/<- *edx 0/r32/eax # Tree-left -2247 # result->right = parse-type-tree(ad, in) -2248 (parse-type-tree *(ebp+8) *(ebp+0xc)) -2249 #? (write-buffered Stderr Space) -2250 #? (print-int32-buffered Stderr %eax) -2251 #? (write-buffered Stderr "}\n") -2252 #? (flush Stderr) -2253 89/<- *(edx+4) 0/r32/eax # Tree-right -2254 $parse-type:return-edx: -2255 89/<- %eax 2/r32/edx -2256 $parse-type:end: -2257 # . reclaim locals -2258 81 0/subop/add %esp 8/imm32 -2259 # . restore registers -2260 5a/pop-to-edx -2261 59/pop-to-ecx -2262 # . epilogue -2263 89/<- %esp 5/r32/ebp -2264 5d/pop-to-ebp -2265 c3/return -2266 -2267 $parse-type:abort: -2268 # error("unexpected token when parsing type: '" s "'\n") -2269 (write-buffered Stderr "unexpected token when parsing type: '") -2270 (write-slice-buffered Stderr %ecx) -2271 (write-buffered Stderr "'\n") -2272 (flush Stderr) -2273 # . syscall(exit, 1) -2274 bb/copy-to-ebx 1/imm32 -2275 b8/copy-to-eax 1/imm32/exit -2276 cd/syscall 0x80/imm8 -2277 # never gets here -2278 -2279 parse-type-tree: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) -2280 # pseudocode: -2281 # var tmp: (handle tree type-id) = parse-type(ad, in) -2282 # if tmp == 0 -2283 # return 0 -2284 # result = allocate(Tree) -2285 # zero-out(result, *Tree-size) -2286 # result->left = tmp -2287 # result->right = parse-type-tree(ad, in) -2288 # -2289 # . prologue -2290 55/push-ebp -2291 89/<- %ebp 4/r32/esp -2292 # . save registers -2293 51/push-ecx -2294 52/push-edx -2295 # var tmp/eax: (handle tree type-id) = parse-type(ad, in) -2296 (parse-type *(ebp+8) *(ebp+0xc)) -2297 # if (tmp == 0) return tmp -2298 3d/compare-eax-and 0/imm32 -2299 74/jump-if-= $parse-type-tree:end/disp8 -2300 # var tmp2/ecx = tmp -2301 89/<- %ecx 0/r32/eax -2302 # var result/edx: (handle tree type-id) -2303 (allocate *(ebp+8) *Tree-size) # => eax -2304 (zero-out %eax *Tree-size) -2305 89/<- %edx 0/r32/eax -2306 # result->left = tmp2 -2307 89/<- *edx 1/r32/ecx # Tree-left -2308 # result->right = parse-type-tree(ad, in) -2309 (parse-type-tree *(ebp+8) *(ebp+0xc)) -2310 89/<- *(edx+4) 0/r32/eax # Tree-right -2311 $parse-type-tree:return-edx: -2312 89/<- %eax 2/r32/edx -2313 $parse-type-tree:end: -2314 # . restore registers -2315 5a/pop-to-edx -2316 59/pop-to-ecx -2317 # . epilogue -2318 89/<- %esp 5/r32/ebp -2319 5d/pop-to-ebp -2320 c3/return -2321 -2322 next-mu-token: # in: (addr stream byte), out: (addr slice) -2323 # pseudocode: -2324 # start: -2325 # skip-chars-matching-whitespace(in) -2326 # if in->read >= in->write # end of in -2327 # out = {0, 0} -2328 # return -2329 # out->start = &in->data[in->read] -2330 # var curr-byte/eax: byte = in->data[in->read] -2331 # if curr->byte == ':' # comment token -2332 # ++in->read -2333 # goto start -2334 # if curr->byte == ',' # comment token -2335 # ++in->read -2336 # goto start -2337 # if curr-byte == '#' # comment -2338 # in->read = in->write # skip to end of in -2339 # goto done -2340 # if curr-byte == '"' # string literal -2341 # skip-string(in) -2342 # goto done # no metadata -2343 # if curr-byte == '(' -2344 # ++in->read -2345 # goto done -2346 # if curr-byte == ')' -2347 # ++in->read -2348 # goto done -2349 # # read a word -2350 # while true -2351 # if in->read >= in->write -2352 # break -2353 # curr-byte = in->data[in->read] -2354 # if curr-byte == ' ' -2355 # break -2356 # if curr-byte == '\r' -2357 # break -2358 # if curr-byte == '\n' -2359 # break -2360 # if curr-byte == '(' -2361 # break -2362 # if curr-byte == ')' -2363 # break -2364 # if curr-byte == ':' -2365 # break -2366 # if curr-byte == ',' -2367 # break -2368 # ++in->read -2369 # done: -2370 # out->end = &in->data[in->read] -2371 # # hack: skip a few trailing delimiters, because we don't always use -2372 # # this correct tokenizer in later tokens -2373 # while true -2374 # if in->read >= in->write -2375 # break -2376 # curr-byte = in->data[in->read] -2377 # if curr-byte == ':' -2378 # ++in->read -2379 # else if curr-byte == ',' -2380 # ++in->read -2381 # else -2382 # break -2383 # -2384 # . prologue -2385 55/push-ebp -2386 89/<- %ebp 4/r32/esp -2387 # . save registers -2388 50/push-eax -2389 51/push-ecx -2390 56/push-esi -2391 57/push-edi -2392 # esi = in -2393 8b/-> *(ebp+8) 6/r32/esi -2394 # edi = out -2395 8b/-> *(ebp+0xc) 7/r32/edi -2396 $next-mu-token:start: -2397 (skip-chars-matching-whitespace %esi) -2398 $next-mu-token:check0: -2399 # if (in->read >= in->write) return out = {0, 0} -2400 # . ecx = in->read -2401 8b/-> *(esi+4) 1/r32/ecx -2402 # . if (ecx >= in->write) return out = {0, 0} -2403 3b/compare 1/r32/ecx *esi -2404 c7 0/subop/copy *edi 0/imm32 -2405 c7 0/subop/copy *(edi+4) 0/imm32 -2406 0f 8d/jump-if->= $next-mu-token:end/disp32 -2407 # out->start = &in->data[in->read] -2408 8d/copy-address *(esi+ecx+0xc) 0/r32/eax -2409 89/<- *edi 0/r32/eax -2410 # var curr-byte/eax: byte = in->data[in->read] -2411 31/xor %eax 0/r32/eax -2412 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -2413 { -2414 $next-mu-token:check-for-colon: -2415 # if (curr-byte != ':') break -2416 3d/compare-eax-and 0x3a/imm32/colon -2417 75/jump-if-!= break/disp8 -2418 # ++in->read -2419 ff 0/subop/increment *(esi+4) -2420 # restart -2421 e9/jump $next-mu-token:start/disp32 -2422 } -2423 { -2424 $next-mu-token:check-for-comma: -2425 # if (curr-byte != ',') break -2426 3d/compare-eax-and 0x2c/imm32/comma -2427 75/jump-if-!= break/disp8 -2428 # ++in->read -2429 ff 0/subop/increment *(esi+4) -2430 # restart -2431 e9/jump $next-mu-token:start/disp32 -2432 } -2433 { -2434 $next-mu-token:check-for-comment: -2435 # if (curr-byte != '#') break -2436 3d/compare-eax-and 0x23/imm32/pound -2437 75/jump-if-!= break/disp8 -2438 # in->read = in->write # skip rest of in -2439 8b/-> *esi 0/r32/eax -2440 89/<- *(esi+4) 0/r32/eax -2441 # return -2442 e9/jump $next-mu-token:done/disp32 -2443 } -2444 { -2445 $next-mu-token:check-for-string-literal: -2446 # if (curr-byte != '"') break -2447 3d/compare-eax-and 0x22/imm32/dquote -2448 75/jump-if-!= break/disp8 -2449 (skip-string %esi) -2450 # return -2451 e9/jump $next-mu-token:done/disp32 -2452 } -2453 { -2454 $next-mu-token:check-for-open-paren: -2455 # if (curr-byte != '(') break -2456 3d/compare-eax-and 0x28/imm32/open-paren -2457 75/jump-if-!= break/disp8 -2458 # ++in->read -2459 ff 0/subop/increment *(esi+4) -2460 # return -2461 e9/jump $next-mu-token:done/disp32 -2462 } -2463 { -2464 $next-mu-token:check-for-close-paren: -2465 # if (curr-byte != ')') break -2466 3d/compare-eax-and 0x29/imm32/close-paren -2467 75/jump-if-!= break/disp8 -2468 # ++in->read -2469 ff 0/subop/increment *(esi+4) -2470 # return -2471 e9/jump $next-mu-token:done/disp32 -2472 } -2473 { -2474 $next-mu-token:regular-word-without-metadata: -2475 # if (in->read >= in->write) break -2476 # . ecx = in->read -2477 8b/-> *(esi+4) 1/r32/ecx -2478 # . if (ecx >= in->write) break -2479 3b/compare *esi 1/r32/ecx -2480 7d/jump-if->= break/disp8 -2481 # var c/eax: byte = in->data[in->read] -2482 31/xor %eax 0/r32/eax -2483 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -2484 # if (c == ' ') break -2485 3d/compare-eax-and 0x20/imm32/space -2486 74/jump-if-= break/disp8 -2487 # if (c == '\r') break -2488 3d/compare-eax-and 0xd/imm32/carriage-return -2489 74/jump-if-= break/disp8 -2490 # if (c == '\n') break -2491 3d/compare-eax-and 0xa/imm32/newline -2492 74/jump-if-= break/disp8 -2493 # if (c == '(') break -2494 3d/compare-eax-and 0x28/imm32/open-paren -2495 0f 84/jump-if-= break/disp32 -2496 # if (c == ')') break -2497 3d/compare-eax-and 0x29/imm32/close-paren -2498 0f 84/jump-if-= break/disp32 -2499 # if (c == ':') break -2500 3d/compare-eax-and 0x3a/imm32/colon -2501 0f 84/jump-if-= break/disp32 -2502 # if (c == ',') break -2503 3d/compare-eax-and 0x2c/imm32/comma -2504 0f 84/jump-if-= break/disp32 -2505 # ++in->read -2506 ff 0/subop/increment *(esi+4) -2507 # -2508 e9/jump loop/disp32 -2509 } -2510 $next-mu-token:done: -2511 # out->end = &in->data[in->read] -2512 8b/-> *(esi+4) 1/r32/ecx -2513 8d/copy-address *(esi+ecx+0xc) 0/r32/eax -2514 89/<- *(edi+4) 0/r32/eax -2515 { -2516 $next-mu-token:skip-trailing-delimiters: -2517 # if (in->read >= in->write) break -2518 # . ecx = in->read -2519 8b/-> *(esi+4) 1/r32/ecx -2520 # . if (ecx >= in->write) break -2521 3b/compare *esi 1/r32/ecx -2522 7d/jump-if->= break/disp8 -2523 # var c/eax: byte = in->data[in->read] -2524 31/xor %eax 0/r32/eax -2525 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -2526 # if (c == ':') ++in->read and loop -2527 { -2528 3d/compare-eax-and 0x3a/imm32/colon -2529 75/jump-if-!= break/disp8 -2530 # ++in->read -2531 ff 0/subop/increment *(esi+4) -2532 # -2533 eb/jump $next-mu-token:skip-trailing-delimiters/disp8 -2534 } -2535 # if (c == ',') ++in->read and loop -2536 { -2537 3d/compare-eax-and 0x2c/imm32/comma -2538 75/jump-if-!= break/disp8 -2539 # ++in->read -2540 ff 0/subop/increment *(esi+4) -2541 # -2542 eb/jump $next-mu-token:skip-trailing-delimiters/disp8 -2543 } -2544 # else break -2545 } -2546 $next-mu-token:end: -2547 # . restore registers -2548 5f/pop-to-edi -2549 5e/pop-to-esi -2550 59/pop-to-ecx -2551 58/pop-to-eax -2552 # . epilogue -2553 89/<- %esp 5/r32/ebp -2554 5d/pop-to-ebp -2555 c3/return -2556 -2557 # return the index in an array of strings matching 's' -2558 # index is denominated in elements, not bytes -2559 pos-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int -2560 # . prologue -2561 55/push-ebp -2562 89/<- %ebp 4/r32/esp -2563 # . save registers -2564 51/push-ecx -2565 52/push-edx -2566 53/push-ebx -2567 56/push-esi -2568 #? (write-buffered Stderr "pos-slice: ") -2569 #? (write-slice-buffered Stderr *(ebp+0xc)) -2570 #? (write-buffered Stderr "\n") -2571 #? (flush Stderr) -2572 # esi = arr -2573 8b/-> *(ebp+8) 6/r32/esi -2574 # var index/ecx: int = 0 -2575 b9/copy-to-ecx 0/imm32 -2576 # var curr/edx: (addr (addr array byte)) = arr->data -2577 8d/copy-address *(esi+0xc) 2/r32/edx -2578 # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write] -2579 8b/-> *esi 3/r32/ebx -2580 8d/copy-address *(esi+ebx+0xc) 3/r32/ebx -2581 { -2582 #? (write-buffered Stderr " ") -2583 #? (print-int32-buffered Stderr %ecx) -2584 #? (write-buffered Stderr "\n") -2585 #? (flush Stderr) -2586 # if (curr >= max) return -1 -2587 39/compare %edx 3/r32/ebx -2588 b8/copy-to-eax -1/imm32 -2589 73/jump-if-addr>= $pos-slice:end/disp8 -2590 # if (slice-equal?(s, *curr)) break -2591 (slice-equal? *(ebp+0xc) *edx) # => eax -2592 3d/compare-eax-and 0/imm32 -2593 75/jump-if-!= break/disp8 -2594 # ++index -2595 41/increment-ecx -2596 # curr += 4 -2597 81 0/subop/add %edx 4/imm32 -2598 # -2599 eb/jump loop/disp8 -2600 } -2601 # return index -2602 89/<- %eax 1/r32/ecx -2603 $pos-slice:end: -2604 #? (write-buffered Stderr "=> ") -2605 #? (print-int32-buffered Stderr %eax) -2606 #? (write-buffered Stderr "\n") -2607 # . restore registers -2608 5e/pop-to-esi -2609 5b/pop-to-ebx -2610 5a/pop-to-edx -2611 59/pop-to-ecx -2612 # . epilogue -2613 89/<- %esp 5/r32/ebp -2614 5d/pop-to-ebp -2615 c3/return -2616 -2617 == data -2618 -2619 Type-id: # (stream (address array byte)) -2620 0x18/imm32/write -2621 0/imm32/read -2622 0x100/imm32/length -2623 # data -2624 "literal"/imm32 # 0 -2625 "int"/imm32 # 1 -2626 "addr"/imm32 # 2 -2627 "array"/imm32 # 3 -2628 "handle"/imm32 # 4 -2629 "bool"/imm32 # 5 -2630 0/imm32 -2631 0/imm32 -2632 # 0x20 -2633 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2634 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2635 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2636 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2637 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2638 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2639 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2640 -2641 == code -2642 -2643 test-parse-var-with-type: -2644 # . prologue -2645 55/push-ebp -2646 89/<- %ebp 4/r32/esp -2647 # (eax..ecx) = "x:" -2648 b8/copy-to-eax "x:"/imm32 -2649 8b/-> *eax 1/r32/ecx -2650 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2651 05/add-to-eax 4/imm32 -2652 # var slice/ecx: slice = {eax, ecx} -2653 51/push-ecx -2654 50/push-eax -2655 89/<- %ecx 4/r32/esp -2656 # _test-input-stream contains "int" -2657 (clear-stream _test-input-stream) -2658 (write _test-input-stream "int") -2659 # -2660 (parse-var-with-type %ecx _test-input-stream) -2661 8b/-> *eax 2/r32/edx # Var-name -2662 (check-strings-equal %edx "x" "F - test-var-with-type/name") -2663 8b/-> *(eax+4) 2/r32/edx # Var-type -2664 (check-ints-equal *edx 1 "F - test-var-with-type/type") -2665 (check-ints-equal *(edx+4) 0 "F - test-var-with-type/type") -2666 # . epilogue -2667 89/<- %esp 5/r32/ebp -2668 5d/pop-to-ebp -2669 c3/return -2670 -2671 test-parse-var-with-type-and-register: -2672 # . prologue -2673 55/push-ebp -2674 89/<- %ebp 4/r32/esp -2675 # (eax..ecx) = "x/eax" -2676 b8/copy-to-eax "x/eax"/imm32 -2677 8b/-> *eax 1/r32/ecx -2678 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2679 05/add-to-eax 4/imm32 -2680 # var slice/ecx: slice = {eax, ecx} -2681 51/push-ecx -2682 50/push-eax -2683 89/<- %ecx 4/r32/esp -2684 # _test-input-stream contains ": int" -2685 (clear-stream _test-input-stream) -2686 (write _test-input-stream ": int") -2687 # -2688 (parse-var-with-type %ecx _test-input-stream) -2689 8b/-> *eax 2/r32/edx # Var-name -2690 (check-strings-equal %edx "x" "F - test-var-with-type-and-register/name") -2691 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2692 (check-strings-equal %edx "eax" "F - test-var-with-type-and-register/register") -2693 8b/-> *(eax+4) 2/r32/edx # Var-type -2694 (check-ints-equal *edx 1 "F - test-var-with-type-and-register/type") -2695 (check-ints-equal *(edx+4) 0 "F - test-var-with-type-and-register/type") -2696 # . epilogue -2697 89/<- %esp 5/r32/ebp -2698 5d/pop-to-ebp -2699 c3/return -2700 -2701 test-parse-var-with-trailing-characters: -2702 # . prologue -2703 55/push-ebp -2704 89/<- %ebp 4/r32/esp -2705 # (eax..ecx) = "x:" -2706 b8/copy-to-eax "x:"/imm32 -2707 8b/-> *eax 1/r32/ecx -2708 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2709 05/add-to-eax 4/imm32 -2710 # var slice/ecx: slice = {eax, ecx} -2711 51/push-ecx -2712 50/push-eax -2713 89/<- %ecx 4/r32/esp -2714 # _test-input-stream contains "int," -2715 (clear-stream _test-input-stream) -2716 (write _test-input-stream "int,") -2717 # -2718 (parse-var-with-type %ecx _test-input-stream) -2719 8b/-> *eax 2/r32/edx # Var-name -2720 (check-strings-equal %edx "x" "F - test-var-with-trailing-characters/name") -2721 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2722 (check-ints-equal %edx 0 "F - test-var-with-trailing-characters/register") -2723 8b/-> *(eax+4) 2/r32/edx # Var-type -2724 (check-ints-equal *edx 1 "F - test-var-with-trailing-characters/type") -2725 (check-ints-equal *(edx+4) 0 "F - test-var-with-trailing-characters/type") -2726 # . epilogue -2727 89/<- %esp 5/r32/ebp -2728 5d/pop-to-ebp -2729 c3/return -2730 -2731 test-parse-var-with-register-and-trailing-characters: -2732 # . prologue -2733 55/push-ebp -2734 89/<- %ebp 4/r32/esp -2735 # (eax..ecx) = "x/eax:" -2736 b8/copy-to-eax "x/eax:"/imm32 -2737 8b/-> *eax 1/r32/ecx -2738 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2739 05/add-to-eax 4/imm32 -2740 # var slice/ecx: slice = {eax, ecx} -2741 51/push-ecx -2742 50/push-eax -2743 89/<- %ecx 4/r32/esp -2744 # _test-input-stream contains "int," -2745 (clear-stream _test-input-stream) -2746 (write _test-input-stream "int,") -2747 # -2748 (parse-var-with-type %ecx _test-input-stream) -2749 8b/-> *eax 2/r32/edx # Var-name -2750 (check-strings-equal %edx "x" "F - test-var-with-register-and-trailing-characters/name") -2751 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2752 (check-strings-equal %edx "eax" "F - test-var-with-register-and-trailing-characters/register") -2753 8b/-> *(eax+4) 2/r32/edx # Var-type -2754 (check-ints-equal *edx 1 "F - test-var-with-register-and-trailing-characters/type") -2755 (check-ints-equal *(edx+4) 0 "F - test-var-with-register-and-trailing-characters/type") -2756 # . epilogue -2757 89/<- %esp 5/r32/ebp -2758 5d/pop-to-ebp -2759 c3/return -2760 -2761 test-parse-var-with-compound-type: -2762 # . prologue -2763 55/push-ebp -2764 89/<- %ebp 4/r32/esp -2765 # (eax..ecx) = "x:" -2766 b8/copy-to-eax "x:"/imm32 -2767 8b/-> *eax 1/r32/ecx -2768 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2769 05/add-to-eax 4/imm32 -2770 # var slice/ecx: slice = {eax, ecx} -2771 51/push-ecx -2772 50/push-eax -2773 89/<- %ecx 4/r32/esp -2774 # _test-input-stream contains "(addr int)" -2775 (clear-stream _test-input-stream) -2776 (write _test-input-stream "(addr int)") -2777 # -2778 (parse-var-with-type %ecx _test-input-stream) -2779 8b/-> *eax 2/r32/edx # Var-name -2780 (check-strings-equal %edx "x" "F - test-var-with-compound-type/name") -2781 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2782 (check-ints-equal %edx 0 "F - test-var-with-compound-type/register") -2783 # var type/edx: (handle tree type-id) = var->type -2784 8b/-> *(eax+4) 2/r32/edx # Var-type -2785 # type->left == atom(addr) -2786 8b/-> *edx 0/r32/eax # Atom-value -2787 (check-ints-equal *eax 2 "F - test-var-with-compound-type/type:0") # Tree-left -2788 # type->right->left == atom(int) -2789 8b/-> *(edx+4) 2/r32/edx # Tree-right -2790 8b/-> *edx 0/r32/eax # Tree-left -2791 (check-ints-equal *eax 1 "F - test-var-with-compound-type/type:1") # Atom-value -2792 # type->right->right == null -2793 (check-ints-equal *(edx+4) 0 "F - test-var-with-compound-type/type:2") # Tree-right -2794 # . epilogue -2795 89/<- %esp 5/r32/ebp -2796 5d/pop-to-ebp -2797 c3/return -2798 -2799 # identifier starts with a letter or '$' or '_' -2800 # no constraints at the moment on later letters -2801 # all we really want to do so far is exclude '{', '}' and '->' -2802 is-identifier?: # in: (addr slice) -> result/eax: boolean +2099 $parse-var-with-type:save-type: +2100 (parse-type Heap *(ebp+0xc)) # => eax +2101 89/<- *(edi+4) 0/r32/eax # Var-type +2102 $parse-var-with-type:end: +2103 # return result +2104 89/<- %eax 7/r32/edi +2105 # . reclaim locals +2106 81 0/subop/add %esp 8/imm32 +2107 # . restore registers +2108 5f/pop-to-edi +2109 5e/pop-to-esi +2110 5b/pop-to-ebx +2111 5a/pop-to-edx +2112 59/pop-to-ecx +2113 # . epilogue +2114 89/<- %esp 5/r32/ebp +2115 5d/pop-to-ebp +2116 c3/return +2117 +2118 $parse-var-with-type:abort: +2119 # error("var should have form 'name: type' in '" line "'\n") +2120 (write-buffered Stderr "var should have form 'name: type' in '") +2121 (flush Stderr) +2122 (rewind-stream *(ebp+0xc)) +2123 (write-stream 2 *(ebp+0xc)) +2124 (write-buffered Stderr "'\n") +2125 (flush Stderr) +2126 # . syscall(exit, 1) +2127 bb/copy-to-ebx 1/imm32 +2128 b8/copy-to-eax 1/imm32/exit +2129 cd/syscall 0x80/imm8 +2130 # never gets here +2131 +2132 parse-type: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) +2133 # pseudocode: +2134 # var s: slice = next-mu-token(in) +2135 # assert s != "" +2136 # assert s != "->" +2137 # assert s != "{" +2138 # assert s != "}" +2139 # if s == ")" +2140 # return 0 +2141 # result = allocate(Tree) +2142 # zero-out(result, *Tree-size) +2143 # if s != "(" +2144 # result->left = pos-slice(Type-id, s) +2145 # return +2146 # result->left = parse-type(ad, in) +2147 # result->right = parse-type-tree(ad, in) +2148 # +2149 # . prologue +2150 55/push-ebp +2151 89/<- %ebp 4/r32/esp +2152 # . save registers +2153 51/push-ecx +2154 52/push-edx +2155 # var s/ecx: slice +2156 68/push 0/imm32 +2157 68/push 0/imm32 +2158 89/<- %ecx 4/r32/esp +2159 # s = next-mu-token(in) +2160 (next-mu-token *(ebp+0xc) %ecx) +2161 #? (write-buffered Stderr "tok: ") +2162 #? (write-slice-buffered Stderr %ecx) +2163 #? (write-buffered Stderr "$\n") +2164 #? (flush Stderr) +2165 # assert s != "" +2166 (slice-equal? %ecx "") +2167 3d/compare-eax-and 0/imm32 +2168 0f 85/jump-if-!= $parse-type:abort/disp32 +2169 # assert s != "{" +2170 (slice-equal? %ecx "{") +2171 3d/compare-eax-and 0/imm32 +2172 0f 85/jump-if-!= $parse-type:abort/disp32 +2173 # assert s != "}" +2174 (slice-equal? %ecx "}") +2175 3d/compare-eax-and 0/imm32 +2176 0f 85/jump-if-!= $parse-type:abort/disp32 +2177 # assert s != "->" +2178 (slice-equal? %ecx "->") +2179 3d/compare-eax-and 0/imm32 +2180 0f 85/jump-if-!= $parse-type:abort/disp32 +2181 # if (s == ")") return 0 +2182 (slice-equal? %ecx ")") +2183 3d/compare-eax-and 0/imm32 +2184 b8/copy-to-eax 0/imm32 +2185 0f 85/jump-if-!= $parse-type:end/disp32 +2186 # var result/edx: (handle tree type-id) +2187 (allocate *(ebp+8) *Tree-size) # => eax +2188 (zero-out %eax *Tree-size) +2189 89/<- %edx 0/r32/eax +2190 { +2191 # if (s != "(") break +2192 (slice-equal? %ecx "(") +2193 3d/compare-eax-and 0/imm32 +2194 75/jump-if-!= break/disp8 +2195 # result->left = pos-slice(Type-id, s) +2196 (pos-slice Type-id %ecx) +2197 #? (write-buffered Stderr "=> {") +2198 #? (print-int32-buffered Stderr %eax) +2199 #? (write-buffered Stderr ", 0}\n") +2200 #? (flush Stderr) +2201 89/<- *edx 0/r32/eax # Tree-left +2202 e9/jump $parse-type:return-edx/disp32 +2203 } +2204 # otherwise s == "(" +2205 # result->left = parse-type(ad, in) +2206 (parse-type *(ebp+8) *(ebp+0xc)) +2207 #? (write-buffered Stderr "=> {") +2208 #? (print-int32-buffered Stderr %eax) +2209 89/<- *edx 0/r32/eax # Tree-left +2210 # result->right = parse-type-tree(ad, in) +2211 (parse-type-tree *(ebp+8) *(ebp+0xc)) +2212 #? (write-buffered Stderr Space) +2213 #? (print-int32-buffered Stderr %eax) +2214 #? (write-buffered Stderr "}\n") +2215 #? (flush Stderr) +2216 89/<- *(edx+4) 0/r32/eax # Tree-right +2217 $parse-type:return-edx: +2218 89/<- %eax 2/r32/edx +2219 $parse-type:end: +2220 # . reclaim locals +2221 81 0/subop/add %esp 8/imm32 +2222 # . restore registers +2223 5a/pop-to-edx +2224 59/pop-to-ecx +2225 # . epilogue +2226 89/<- %esp 5/r32/ebp +2227 5d/pop-to-ebp +2228 c3/return +2229 +2230 $parse-type:abort: +2231 # error("unexpected token when parsing type: '" s "'\n") +2232 (write-buffered Stderr "unexpected token when parsing type: '") +2233 (write-slice-buffered Stderr %ecx) +2234 (write-buffered Stderr "'\n") +2235 (flush Stderr) +2236 # . syscall(exit, 1) +2237 bb/copy-to-ebx 1/imm32 +2238 b8/copy-to-eax 1/imm32/exit +2239 cd/syscall 0x80/imm8 +2240 # never gets here +2241 +2242 parse-type-tree: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) +2243 # pseudocode: +2244 # var tmp: (handle tree type-id) = parse-type(ad, in) +2245 # if tmp == 0 +2246 # return 0 +2247 # result = allocate(Tree) +2248 # zero-out(result, *Tree-size) +2249 # result->left = tmp +2250 # result->right = parse-type-tree(ad, in) +2251 # +2252 # . prologue +2253 55/push-ebp +2254 89/<- %ebp 4/r32/esp +2255 # . save registers +2256 51/push-ecx +2257 52/push-edx +2258 # var tmp/eax: (handle tree type-id) = parse-type(ad, in) +2259 (parse-type *(ebp+8) *(ebp+0xc)) +2260 # if (tmp == 0) return tmp +2261 3d/compare-eax-and 0/imm32 +2262 74/jump-if-= $parse-type-tree:end/disp8 +2263 # var tmp2/ecx = tmp +2264 89/<- %ecx 0/r32/eax +2265 # var result/edx: (handle tree type-id) +2266 (allocate *(ebp+8) *Tree-size) # => eax +2267 (zero-out %eax *Tree-size) +2268 89/<- %edx 0/r32/eax +2269 # result->left = tmp2 +2270 89/<- *edx 1/r32/ecx # Tree-left +2271 # result->right = parse-type-tree(ad, in) +2272 (parse-type-tree *(ebp+8) *(ebp+0xc)) +2273 89/<- *(edx+4) 0/r32/eax # Tree-right +2274 $parse-type-tree:return-edx: +2275 89/<- %eax 2/r32/edx +2276 $parse-type-tree:end: +2277 # . restore registers +2278 5a/pop-to-edx +2279 59/pop-to-ecx +2280 # . epilogue +2281 89/<- %esp 5/r32/ebp +2282 5d/pop-to-ebp +2283 c3/return +2284 +2285 next-mu-token: # in: (addr stream byte), out: (addr slice) +2286 # pseudocode: +2287 # start: +2288 # skip-chars-matching-whitespace(in) +2289 # if in->read >= in->write # end of in +2290 # out = {0, 0} +2291 # return +2292 # out->start = &in->data[in->read] +2293 # var curr-byte/eax: byte = in->data[in->read] +2294 # if curr->byte == ',' # comment token +2295 # ++in->read +2296 # goto start +2297 # if curr-byte == '#' # comment +2298 # goto done # treat as eof +2299 # if curr-byte == '"' # string literal +2300 # skip-string(in) +2301 # goto done # no metadata +2302 # if curr-byte == '(' +2303 # ++in->read +2304 # goto done +2305 # if curr-byte == ')' +2306 # ++in->read +2307 # goto done +2308 # # read a word +2309 # while true +2310 # if in->read >= in->write +2311 # break +2312 # curr-byte = in->data[in->read] +2313 # if curr-byte == ' ' +2314 # break +2315 # if curr-byte == '\r' +2316 # break +2317 # if curr-byte == '\n' +2318 # break +2319 # if curr-byte == '(' +2320 # break +2321 # if curr-byte == ')' +2322 # break +2323 # if curr-byte == ',' +2324 # break +2325 # ++in->read +2326 # done: +2327 # out->end = &in->data[in->read] +2328 # +2329 # . prologue +2330 55/push-ebp +2331 89/<- %ebp 4/r32/esp +2332 # . save registers +2333 50/push-eax +2334 51/push-ecx +2335 56/push-esi +2336 57/push-edi +2337 # esi = in +2338 8b/-> *(ebp+8) 6/r32/esi +2339 # edi = out +2340 8b/-> *(ebp+0xc) 7/r32/edi +2341 $next-mu-token:start: +2342 (skip-chars-matching-whitespace %esi) +2343 $next-mu-token:check0: +2344 # if (in->read >= in->write) return out = {0, 0} +2345 # . ecx = in->read +2346 8b/-> *(esi+4) 1/r32/ecx +2347 # . if (ecx >= in->write) return out = {0, 0} +2348 3b/compare 1/r32/ecx *esi +2349 c7 0/subop/copy *edi 0/imm32 +2350 c7 0/subop/copy *(edi+4) 0/imm32 +2351 0f 8d/jump-if->= $next-mu-token:end/disp32 +2352 # out->start = &in->data[in->read] +2353 8d/copy-address *(esi+ecx+0xc) 0/r32/eax +2354 89/<- *edi 0/r32/eax +2355 # var curr-byte/eax: byte = in->data[in->read] +2356 31/xor %eax 0/r32/eax +2357 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL +2358 { +2359 $next-mu-token:check-for-comma: +2360 # if (curr-byte != ',') break +2361 3d/compare-eax-and 0x2c/imm32/comma +2362 75/jump-if-!= break/disp8 +2363 # ++in->read +2364 ff 0/subop/increment *(esi+4) +2365 # restart +2366 e9/jump $next-mu-token:start/disp32 +2367 } +2368 { +2369 $next-mu-token:check-for-comment: +2370 # if (curr-byte != '#') break +2371 3d/compare-eax-and 0x23/imm32/pound +2372 75/jump-if-!= break/disp8 +2373 # return eof +2374 e9/jump $next-mu-token:done/disp32 +2375 } +2376 { +2377 $next-mu-token:check-for-string-literal: +2378 # if (curr-byte != '"') break +2379 3d/compare-eax-and 0x22/imm32/dquote +2380 75/jump-if-!= break/disp8 +2381 (skip-string %esi) +2382 # return +2383 e9/jump $next-mu-token:done/disp32 +2384 } +2385 { +2386 $next-mu-token:check-for-open-paren: +2387 # if (curr-byte != '(') break +2388 3d/compare-eax-and 0x28/imm32/open-paren +2389 75/jump-if-!= break/disp8 +2390 # ++in->read +2391 ff 0/subop/increment *(esi+4) +2392 # return +2393 e9/jump $next-mu-token:done/disp32 +2394 } +2395 { +2396 $next-mu-token:check-for-close-paren: +2397 # if (curr-byte != ')') break +2398 3d/compare-eax-and 0x29/imm32/close-paren +2399 75/jump-if-!= break/disp8 +2400 # ++in->read +2401 ff 0/subop/increment *(esi+4) +2402 # return +2403 e9/jump $next-mu-token:done/disp32 +2404 } +2405 { +2406 $next-mu-token:regular-word-without-metadata: +2407 # if (in->read >= in->write) break +2408 # . ecx = in->read +2409 8b/-> *(esi+4) 1/r32/ecx +2410 # . if (ecx >= in->write) break +2411 3b/compare *esi 1/r32/ecx +2412 7d/jump-if->= break/disp8 +2413 # var c/eax: byte = in->data[in->read] +2414 31/xor %eax 0/r32/eax +2415 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL +2416 # if (c == ' ') break +2417 3d/compare-eax-and 0x20/imm32/space +2418 74/jump-if-= break/disp8 +2419 # if (c == '\r') break +2420 3d/compare-eax-and 0xd/imm32/carriage-return +2421 74/jump-if-= break/disp8 +2422 # if (c == '\n') break +2423 3d/compare-eax-and 0xa/imm32/newline +2424 74/jump-if-= break/disp8 +2425 # if (c == '(') break +2426 3d/compare-eax-and 0x28/imm32/open-paren +2427 0f 84/jump-if-= break/disp32 +2428 # if (c == ')') break +2429 3d/compare-eax-and 0x29/imm32/close-paren +2430 0f 84/jump-if-= break/disp32 +2431 # if (c == ',') break +2432 3d/compare-eax-and 0x2c/imm32/comma +2433 0f 84/jump-if-= break/disp32 +2434 # ++in->read +2435 ff 0/subop/increment *(esi+4) +2436 # +2437 e9/jump loop/disp32 +2438 } +2439 $next-mu-token:done: +2440 # out->end = &in->data[in->read] +2441 8b/-> *(esi+4) 1/r32/ecx +2442 8d/copy-address *(esi+ecx+0xc) 0/r32/eax +2443 89/<- *(edi+4) 0/r32/eax +2444 $next-mu-token:end: +2445 # . restore registers +2446 5f/pop-to-edi +2447 5e/pop-to-esi +2448 59/pop-to-ecx +2449 58/pop-to-eax +2450 # . epilogue +2451 89/<- %esp 5/r32/ebp +2452 5d/pop-to-ebp +2453 c3/return +2454 +2455 # return the index in an array of strings matching 's' +2456 # index is denominated in elements, not bytes +2457 pos-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int +2458 # . prologue +2459 55/push-ebp +2460 89/<- %ebp 4/r32/esp +2461 # . save registers +2462 51/push-ecx +2463 52/push-edx +2464 53/push-ebx +2465 56/push-esi +2466 #? (write-buffered Stderr "pos-slice: ") +2467 #? (write-slice-buffered Stderr *(ebp+0xc)) +2468 #? (write-buffered Stderr "\n") +2469 #? (flush Stderr) +2470 # esi = arr +2471 8b/-> *(ebp+8) 6/r32/esi +2472 # var index/ecx: int = 0 +2473 b9/copy-to-ecx 0/imm32 +2474 # var curr/edx: (addr (addr array byte)) = arr->data +2475 8d/copy-address *(esi+0xc) 2/r32/edx +2476 # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write] +2477 8b/-> *esi 3/r32/ebx +2478 8d/copy-address *(esi+ebx+0xc) 3/r32/ebx +2479 { +2480 #? (write-buffered Stderr " ") +2481 #? (print-int32-buffered Stderr %ecx) +2482 #? (write-buffered Stderr "\n") +2483 #? (flush Stderr) +2484 # if (curr >= max) return -1 +2485 39/compare %edx 3/r32/ebx +2486 b8/copy-to-eax -1/imm32 +2487 73/jump-if-addr>= $pos-slice:end/disp8 +2488 # if (slice-equal?(s, *curr)) break +2489 (slice-equal? *(ebp+0xc) *edx) # => eax +2490 3d/compare-eax-and 0/imm32 +2491 75/jump-if-!= break/disp8 +2492 # ++index +2493 41/increment-ecx +2494 # curr += 4 +2495 81 0/subop/add %edx 4/imm32 +2496 # +2497 eb/jump loop/disp8 +2498 } +2499 # return index +2500 89/<- %eax 1/r32/ecx +2501 $pos-slice:end: +2502 #? (write-buffered Stderr "=> ") +2503 #? (print-int32-buffered Stderr %eax) +2504 #? (write-buffered Stderr "\n") +2505 # . restore registers +2506 5e/pop-to-esi +2507 5b/pop-to-ebx +2508 5a/pop-to-edx +2509 59/pop-to-ecx +2510 # . epilogue +2511 89/<- %esp 5/r32/ebp +2512 5d/pop-to-ebp +2513 c3/return +2514 +2515 == data +2516 +2517 Type-id: # (stream (address array byte)) +2518 0x18/imm32/write +2519 0/imm32/read +2520 0x100/imm32/length +2521 # data +2522 "literal"/imm32 # 0 +2523 "int"/imm32 # 1 +2524 "addr"/imm32 # 2 +2525 "array"/imm32 # 3 +2526 "handle"/imm32 # 4 +2527 "bool"/imm32 # 5 +2528 0/imm32 +2529 0/imm32 +2530 # 0x20 +2531 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2532 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2533 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2534 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2535 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2536 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2537 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2538 +2539 == code +2540 +2541 test-parse-var-with-type: +2542 # . prologue +2543 55/push-ebp +2544 89/<- %ebp 4/r32/esp +2545 # (eax..ecx) = "x:" +2546 b8/copy-to-eax "x:"/imm32 +2547 8b/-> *eax 1/r32/ecx +2548 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2549 05/add-to-eax 4/imm32 +2550 # var slice/ecx: slice = {eax, ecx} +2551 51/push-ecx +2552 50/push-eax +2553 89/<- %ecx 4/r32/esp +2554 # _test-input-stream contains "int" +2555 (clear-stream _test-input-stream) +2556 (write _test-input-stream "int") +2557 # +2558 (parse-var-with-type %ecx _test-input-stream) +2559 8b/-> *eax 2/r32/edx # Var-name +2560 (check-strings-equal %edx "x" "F - test-var-with-type/name") +2561 8b/-> *(eax+4) 2/r32/edx # Var-type +2562 (check-ints-equal *edx 1 "F - test-var-with-type/type") +2563 (check-ints-equal *(edx+4) 0 "F - test-var-with-type/type") +2564 # . epilogue +2565 89/<- %esp 5/r32/ebp +2566 5d/pop-to-ebp +2567 c3/return +2568 +2569 test-parse-var-with-type-and-register: +2570 # . prologue +2571 55/push-ebp +2572 89/<- %ebp 4/r32/esp +2573 # (eax..ecx) = "x/eax:" +2574 b8/copy-to-eax "x/eax:"/imm32 +2575 8b/-> *eax 1/r32/ecx +2576 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2577 05/add-to-eax 4/imm32 +2578 # var slice/ecx: slice = {eax, ecx} +2579 51/push-ecx +2580 50/push-eax +2581 89/<- %ecx 4/r32/esp +2582 # _test-input-stream contains "int" +2583 (clear-stream _test-input-stream) +2584 (write _test-input-stream "int") +2585 # +2586 (parse-var-with-type %ecx _test-input-stream) +2587 8b/-> *eax 2/r32/edx # Var-name +2588 (check-strings-equal %edx "x" "F - test-var-with-type-and-register/name") +2589 8b/-> *(eax+0x10) 2/r32/edx # Var-register +2590 (check-strings-equal %edx "eax" "F - test-var-with-type-and-register/register") +2591 8b/-> *(eax+4) 2/r32/edx # Var-type +2592 (check-ints-equal *edx 1 "F - test-var-with-type-and-register/type") +2593 (check-ints-equal *(edx+4) 0 "F - test-var-with-type-and-register/type") +2594 # . epilogue +2595 89/<- %esp 5/r32/ebp +2596 5d/pop-to-ebp +2597 c3/return +2598 +2599 test-parse-var-with-trailing-characters: +2600 # . prologue +2601 55/push-ebp +2602 89/<- %ebp 4/r32/esp +2603 # (eax..ecx) = "x:" +2604 b8/copy-to-eax "x:"/imm32 +2605 8b/-> *eax 1/r32/ecx +2606 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2607 05/add-to-eax 4/imm32 +2608 # var slice/ecx: slice = {eax, ecx} +2609 51/push-ecx +2610 50/push-eax +2611 89/<- %ecx 4/r32/esp +2612 # _test-input-stream contains "int," +2613 (clear-stream _test-input-stream) +2614 (write _test-input-stream "int,") +2615 # +2616 (parse-var-with-type %ecx _test-input-stream) +2617 8b/-> *eax 2/r32/edx # Var-name +2618 (check-strings-equal %edx "x" "F - test-var-with-trailing-characters/name") +2619 8b/-> *(eax+0x10) 2/r32/edx # Var-register +2620 (check-ints-equal %edx 0 "F - test-var-with-trailing-characters/register") +2621 8b/-> *(eax+4) 2/r32/edx # Var-type +2622 (check-ints-equal *edx 1 "F - test-var-with-trailing-characters/type") +2623 (check-ints-equal *(edx+4) 0 "F - test-var-with-trailing-characters/type") +2624 # . epilogue +2625 89/<- %esp 5/r32/ebp +2626 5d/pop-to-ebp +2627 c3/return +2628 +2629 test-parse-var-with-register-and-trailing-characters: +2630 # . prologue +2631 55/push-ebp +2632 89/<- %ebp 4/r32/esp +2633 # (eax..ecx) = "x/eax:" +2634 b8/copy-to-eax "x/eax:"/imm32 +2635 8b/-> *eax 1/r32/ecx +2636 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2637 05/add-to-eax 4/imm32 +2638 # var slice/ecx: slice = {eax, ecx} +2639 51/push-ecx +2640 50/push-eax +2641 89/<- %ecx 4/r32/esp +2642 # _test-input-stream contains "int," +2643 (clear-stream _test-input-stream) +2644 (write _test-input-stream "int,") +2645 # +2646 (parse-var-with-type %ecx _test-input-stream) +2647 8b/-> *eax 2/r32/edx # Var-name +2648 (check-strings-equal %edx "x" "F - test-var-with-register-and-trailing-characters/name") +2649 8b/-> *(eax+0x10) 2/r32/edx # Var-register +2650 (check-strings-equal %edx "eax" "F - test-var-with-register-and-trailing-characters/register") +2651 8b/-> *(eax+4) 2/r32/edx # Var-type +2652 (check-ints-equal *edx 1 "F - test-var-with-register-and-trailing-characters/type") +2653 (check-ints-equal *(edx+4) 0 "F - test-var-with-register-and-trailing-characters/type") +2654 # . epilogue +2655 89/<- %esp 5/r32/ebp +2656 5d/pop-to-ebp +2657 c3/return +2658 +2659 test-parse-var-with-compound-type: +2660 # . prologue +2661 55/push-ebp +2662 89/<- %ebp 4/r32/esp +2663 # (eax..ecx) = "x:" +2664 b8/copy-to-eax "x:"/imm32 +2665 8b/-> *eax 1/r32/ecx +2666 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2667 05/add-to-eax 4/imm32 +2668 # var slice/ecx: slice = {eax, ecx} +2669 51/push-ecx +2670 50/push-eax +2671 89/<- %ecx 4/r32/esp +2672 # _test-input-stream contains "(addr int)" +2673 (clear-stream _test-input-stream) +2674 (write _test-input-stream "(addr int)") +2675 # +2676 (parse-var-with-type %ecx _test-input-stream) +2677 8b/-> *eax 2/r32/edx # Var-name +2678 (check-strings-equal %edx "x" "F - test-var-with-compound-type/name") +2679 8b/-> *(eax+0x10) 2/r32/edx # Var-register +2680 (check-ints-equal %edx 0 "F - test-var-with-compound-type/register") +2681 # var type/edx: (handle tree type-id) = var->type +2682 8b/-> *(eax+4) 2/r32/edx # Var-type +2683 # type->left == atom(addr) +2684 8b/-> *edx 0/r32/eax # Atom-value +2685 (check-ints-equal *eax 2 "F - test-var-with-compound-type/type:0") # Tree-left +2686 # type->right->left == atom(int) +2687 8b/-> *(edx+4) 2/r32/edx # Tree-right +2688 8b/-> *edx 0/r32/eax # Tree-left +2689 (check-ints-equal *eax 1 "F - test-var-with-compound-type/type:1") # Atom-value +2690 # type->right->right == null +2691 (check-ints-equal *(edx+4) 0 "F - test-var-with-compound-type/type:2") # Tree-right +2692 # . epilogue +2693 89/<- %esp 5/r32/ebp +2694 5d/pop-to-ebp +2695 c3/return +2696 +2697 # identifier starts with a letter or '$' or '_' +2698 # no constraints at the moment on later letters +2699 # all we really want to do so far is exclude '{', '}' and '->' +2700 is-identifier?: # in: (addr slice) -> result/eax: boolean +2701 # . prologue +2702 55/push-ebp +2703 89/<- %ebp 4/r32/esp +2704 # if (slice-empty?(in)) return false +2705 (slice-empty? *(ebp+8)) # => eax +2706 3d/compare-eax-and 0/imm32 +2707 75/jump-if-!= $is-identifier?:false/disp8 +2708 # var c/eax: byte = *in->start +2709 8b/-> *(ebp+8) 0/r32/eax +2710 8b/-> *eax 0/r32/eax +2711 8a/copy-byte *eax 0/r32/AL +2712 81 4/subop/and %eax 0xff/imm32 +2713 # if (c == '$') return true +2714 3d/compare-eax-and 0x24/imm32/$ +2715 74/jump-if-= $is-identifier?:true/disp8 +2716 # if (c == '_') return true +2717 3d/compare-eax-and 0x5f/imm32/_ +2718 74/jump-if-= $is-identifier?:true/disp8 +2719 # drop case +2720 25/and-eax-with 0x5f/imm32 +2721 # if (c < 'A') return false +2722 3d/compare-eax-and 0x41/imm32/A +2723 7c/jump-if-< $is-identifier?:false/disp8 +2724 # if (c > 'Z') return false +2725 3d/compare-eax-and 0x5a/imm32/Z +2726 7f/jump-if-> $is-identifier?:false/disp8 +2727 # otherwise return true +2728 $is-identifier?:true: +2729 b8/copy-to-eax 1/imm32/true +2730 eb/jump $is-identifier?:end/disp8 +2731 $is-identifier?:false: +2732 b8/copy-to-eax 0/imm32/false +2733 $is-identifier?:end: +2734 # . epilogue +2735 89/<- %esp 5/r32/ebp +2736 5d/pop-to-ebp +2737 c3/return +2738 +2739 test-is-identifier-dollar: +2740 # . prologue +2741 55/push-ebp +2742 89/<- %ebp 4/r32/esp +2743 # (eax..ecx) = "$a" +2744 b8/copy-to-eax "$a"/imm32 +2745 8b/-> *eax 1/r32/ecx +2746 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2747 05/add-to-eax 4/imm32 +2748 # var slice/ecx: slice = {eax, ecx} +2749 51/push-ecx +2750 50/push-eax +2751 89/<- %ecx 4/r32/esp +2752 # +2753 (is-identifier? %ecx) +2754 (check-ints-equal %eax 1 "F - test-is-identifier-dollar") +2755 # . epilogue +2756 89/<- %esp 5/r32/ebp +2757 5d/pop-to-ebp +2758 c3/return +2759 +2760 test-is-identifier-underscore: +2761 # . prologue +2762 55/push-ebp +2763 89/<- %ebp 4/r32/esp +2764 # (eax..ecx) = "_a" +2765 b8/copy-to-eax "_a"/imm32 +2766 8b/-> *eax 1/r32/ecx +2767 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2768 05/add-to-eax 4/imm32 +2769 # var slice/ecx: slice = {eax, ecx} +2770 51/push-ecx +2771 50/push-eax +2772 89/<- %ecx 4/r32/esp +2773 # +2774 (is-identifier? %ecx) +2775 (check-ints-equal %eax 1 "F - test-is-identifier-underscore") +2776 # . epilogue +2777 89/<- %esp 5/r32/ebp +2778 5d/pop-to-ebp +2779 c3/return +2780 +2781 test-is-identifier-a: +2782 # . prologue +2783 55/push-ebp +2784 89/<- %ebp 4/r32/esp +2785 # (eax..ecx) = "a$" +2786 b8/copy-to-eax "a$"/imm32 +2787 8b/-> *eax 1/r32/ecx +2788 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2789 05/add-to-eax 4/imm32 +2790 # var slice/ecx: slice = {eax, ecx} +2791 51/push-ecx +2792 50/push-eax +2793 89/<- %ecx 4/r32/esp +2794 # +2795 (is-identifier? %ecx) +2796 (check-ints-equal %eax 1 "F - test-is-identifier-a") +2797 # . epilogue +2798 89/<- %esp 5/r32/ebp +2799 5d/pop-to-ebp +2800 c3/return +2801 +2802 test-is-identifier-z: 2803 # . prologue 2804 55/push-ebp 2805 89/<- %ebp 4/r32/esp -2806 # if (slice-empty?(in)) return false -2807 (slice-empty? *(ebp+8)) # => eax -2808 3d/compare-eax-and 0/imm32 -2809 75/jump-if-!= $is-identifier?:false/disp8 -2810 # var c/eax: byte = *in->start -2811 8b/-> *(ebp+8) 0/r32/eax -2812 8b/-> *eax 0/r32/eax -2813 8a/copy-byte *eax 0/r32/AL -2814 81 4/subop/and %eax 0xff/imm32 -2815 # if (c == '$') return true -2816 3d/compare-eax-and 0x24/imm32/$ -2817 74/jump-if-= $is-identifier?:true/disp8 -2818 # if (c == '_') return true -2819 3d/compare-eax-and 0x5f/imm32/_ -2820 74/jump-if-= $is-identifier?:true/disp8 -2821 # drop case -2822 25/and-eax-with 0x5f/imm32 -2823 # if (c < 'A') return false -2824 3d/compare-eax-and 0x41/imm32/A -2825 7c/jump-if-< $is-identifier?:false/disp8 -2826 # if (c > 'Z') return false -2827 3d/compare-eax-and 0x5a/imm32/Z -2828 7f/jump-if-> $is-identifier?:false/disp8 -2829 # otherwise return true -2830 $is-identifier?:true: -2831 b8/copy-to-eax 1/imm32/true -2832 eb/jump $is-identifier?:end/disp8 -2833 $is-identifier?:false: -2834 b8/copy-to-eax 0/imm32/false -2835 $is-identifier?:end: -2836 # . epilogue -2837 89/<- %esp 5/r32/ebp -2838 5d/pop-to-ebp -2839 c3/return -2840 -2841 test-is-identifier-dollar: -2842 # . prologue -2843 55/push-ebp -2844 89/<- %ebp 4/r32/esp -2845 # (eax..ecx) = "$a" -2846 b8/copy-to-eax "$a"/imm32 -2847 8b/-> *eax 1/r32/ecx -2848 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2849 05/add-to-eax 4/imm32 -2850 # var slice/ecx: slice = {eax, ecx} -2851 51/push-ecx -2852 50/push-eax -2853 89/<- %ecx 4/r32/esp -2854 # -2855 (is-identifier? %ecx) -2856 (check-ints-equal %eax 1 "F - test-is-identifier-dollar") -2857 # . epilogue -2858 89/<- %esp 5/r32/ebp -2859 5d/pop-to-ebp -2860 c3/return -2861 -2862 test-is-identifier-underscore: -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 1 "F - test-is-identifier-underscore") -2878 # . epilogue -2879 89/<- %esp 5/r32/ebp -2880 5d/pop-to-ebp -2881 c3/return -2882 -2883 test-is-identifier-a: -2884 # . prologue -2885 55/push-ebp -2886 89/<- %ebp 4/r32/esp -2887 # (eax..ecx) = "a$" -2888 b8/copy-to-eax "a$"/imm32 -2889 8b/-> *eax 1/r32/ecx -2890 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2891 05/add-to-eax 4/imm32 -2892 # var slice/ecx: slice = {eax, ecx} -2893 51/push-ecx -2894 50/push-eax -2895 89/<- %ecx 4/r32/esp -2896 # -2897 (is-identifier? %ecx) -2898 (check-ints-equal %eax 1 "F - test-is-identifier-a") -2899 # . epilogue -2900 89/<- %esp 5/r32/ebp -2901 5d/pop-to-ebp -2902 c3/return -2903 -2904 test-is-identifier-z: -2905 # . prologue -2906 55/push-ebp -2907 89/<- %ebp 4/r32/esp -2908 # (eax..ecx) = "z$" -2909 b8/copy-to-eax "z$"/imm32 -2910 8b/-> *eax 1/r32/ecx -2911 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2912 05/add-to-eax 4/imm32 -2913 # var slice/ecx: slice = {eax, ecx} -2914 51/push-ecx -2915 50/push-eax -2916 89/<- %ecx 4/r32/esp -2917 # -2918 (is-identifier? %ecx) -2919 (check-ints-equal %eax 1 "F - test-is-identifier-z") -2920 # . epilogue -2921 89/<- %esp 5/r32/ebp -2922 5d/pop-to-ebp -2923 c3/return -2924 -2925 test-is-identifier-A: -2926 # . prologue -2927 55/push-ebp -2928 89/<- %ebp 4/r32/esp -2929 # (eax..ecx) = "A$" -2930 b8/copy-to-eax "A$"/imm32 -2931 8b/-> *eax 1/r32/ecx -2932 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2933 05/add-to-eax 4/imm32 -2934 # var slice/ecx: slice = {eax, ecx} -2935 51/push-ecx -2936 50/push-eax -2937 89/<- %ecx 4/r32/esp -2938 # -2939 (is-identifier? %ecx) -2940 (check-ints-equal %eax 1 "F - test-is-identifier-A") -2941 # . epilogue -2942 89/<- %esp 5/r32/ebp -2943 5d/pop-to-ebp -2944 c3/return -2945 -2946 test-is-identifier-Z: -2947 # . prologue -2948 55/push-ebp -2949 89/<- %ebp 4/r32/esp -2950 # (eax..ecx) = "Z$" -2951 b8/copy-to-eax "Z$"/imm32 -2952 8b/-> *eax 1/r32/ecx -2953 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2954 05/add-to-eax 4/imm32 -2955 # var slice/ecx: slice = {eax, ecx} -2956 51/push-ecx -2957 50/push-eax -2958 89/<- %ecx 4/r32/esp -2959 # -2960 (is-identifier? %ecx) -2961 (check-ints-equal %eax 1 "F - test-is-identifier-Z") -2962 # . epilogue -2963 89/<- %esp 5/r32/ebp -2964 5d/pop-to-ebp -2965 c3/return -2966 -2967 test-is-identifier-@: -2968 # character before 'A' is invalid -2969 # . prologue -2970 55/push-ebp -2971 89/<- %ebp 4/r32/esp -2972 # (eax..ecx) = "@a" -2973 b8/copy-to-eax "@a"/imm32 -2974 8b/-> *eax 1/r32/ecx -2975 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2976 05/add-to-eax 4/imm32 -2977 # var slice/ecx: slice = {eax, ecx} -2978 51/push-ecx -2979 50/push-eax -2980 89/<- %ecx 4/r32/esp -2981 # -2982 (is-identifier? %ecx) -2983 (check-ints-equal %eax 0 "F - test-is-identifier-@") -2984 # . epilogue -2985 89/<- %esp 5/r32/ebp -2986 5d/pop-to-ebp -2987 c3/return -2988 -2989 test-is-identifier-square-bracket: -2990 # character after 'Z' is invalid -2991 # . prologue -2992 55/push-ebp -2993 89/<- %ebp 4/r32/esp -2994 # (eax..ecx) = "[a" -2995 b8/copy-to-eax "[a"/imm32 -2996 8b/-> *eax 1/r32/ecx -2997 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2998 05/add-to-eax 4/imm32 -2999 # var slice/ecx: slice = {eax, ecx} -3000 51/push-ecx +2806 # (eax..ecx) = "z$" +2807 b8/copy-to-eax "z$"/imm32 +2808 8b/-> *eax 1/r32/ecx +2809 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2810 05/add-to-eax 4/imm32 +2811 # var slice/ecx: slice = {eax, ecx} +2812 51/push-ecx +2813 50/push-eax +2814 89/<- %ecx 4/r32/esp +2815 # +2816 (is-identifier? %ecx) +2817 (check-ints-equal %eax 1 "F - test-is-identifier-z") +2818 # . epilogue +2819 89/<- %esp 5/r32/ebp +2820 5d/pop-to-ebp +2821 c3/return +2822 +2823 test-is-identifier-A: +2824 # . prologue +2825 55/push-ebp +2826 89/<- %ebp 4/r32/esp +2827 # (eax..ecx) = "A$" +2828 b8/copy-to-eax "A$"/imm32 +2829 8b/-> *eax 1/r32/ecx +2830 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2831 05/add-to-eax 4/imm32 +2832 # var slice/ecx: slice = {eax, ecx} +2833 51/push-ecx +2834 50/push-eax +2835 89/<- %ecx 4/r32/esp +2836 # +2837 (is-identifier? %ecx) +2838 (check-ints-equal %eax 1 "F - test-is-identifier-A") +2839 # . epilogue +2840 89/<- %esp 5/r32/ebp +2841 5d/pop-to-ebp +2842 c3/return +2843 +2844 test-is-identifier-Z: +2845 # . prologue +2846 55/push-ebp +2847 89/<- %ebp 4/r32/esp +2848 # (eax..ecx) = "Z$" +2849 b8/copy-to-eax "Z$"/imm32 +2850 8b/-> *eax 1/r32/ecx +2851 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2852 05/add-to-eax 4/imm32 +2853 # var slice/ecx: slice = {eax, ecx} +2854 51/push-ecx +2855 50/push-eax +2856 89/<- %ecx 4/r32/esp +2857 # +2858 (is-identifier? %ecx) +2859 (check-ints-equal %eax 1 "F - test-is-identifier-Z") +2860 # . epilogue +2861 89/<- %esp 5/r32/ebp +2862 5d/pop-to-ebp +2863 c3/return +2864 +2865 test-is-identifier-@: +2866 # character before 'A' is invalid +2867 # . prologue +2868 55/push-ebp +2869 89/<- %ebp 4/r32/esp +2870 # (eax..ecx) = "@a" +2871 b8/copy-to-eax "@a"/imm32 +2872 8b/-> *eax 1/r32/ecx +2873 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2874 05/add-to-eax 4/imm32 +2875 # var slice/ecx: slice = {eax, ecx} +2876 51/push-ecx +2877 50/push-eax +2878 89/<- %ecx 4/r32/esp +2879 # +2880 (is-identifier? %ecx) +2881 (check-ints-equal %eax 0 "F - test-is-identifier-@") +2882 # . epilogue +2883 89/<- %esp 5/r32/ebp +2884 5d/pop-to-ebp +2885 c3/return +2886 +2887 test-is-identifier-square-bracket: +2888 # character after 'Z' is invalid +2889 # . prologue +2890 55/push-ebp +2891 89/<- %ebp 4/r32/esp +2892 # (eax..ecx) = "[a" +2893 b8/copy-to-eax "[a"/imm32 +2894 8b/-> *eax 1/r32/ecx +2895 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2896 05/add-to-eax 4/imm32 +2897 # var slice/ecx: slice = {eax, ecx} +2898 51/push-ecx +2899 50/push-eax +2900 89/<- %ecx 4/r32/esp +2901 # +2902 (is-identifier? %ecx) +2903 (check-ints-equal %eax 0 "F - test-is-identifier-@") +2904 # . epilogue +2905 89/<- %esp 5/r32/ebp +2906 5d/pop-to-ebp +2907 c3/return +2908 +2909 test-is-identifier-backtick: +2910 # character before 'a' is invalid +2911 # . prologue +2912 55/push-ebp +2913 89/<- %ebp 4/r32/esp +2914 # (eax..ecx) = "`a" +2915 b8/copy-to-eax "`a"/imm32 +2916 8b/-> *eax 1/r32/ecx +2917 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2918 05/add-to-eax 4/imm32 +2919 # var slice/ecx: slice = {eax, ecx} +2920 51/push-ecx +2921 50/push-eax +2922 89/<- %ecx 4/r32/esp +2923 # +2924 (is-identifier? %ecx) +2925 (check-ints-equal %eax 0 "F - test-is-identifier-backtick") +2926 # . epilogue +2927 89/<- %esp 5/r32/ebp +2928 5d/pop-to-ebp +2929 c3/return +2930 +2931 test-is-identifier-curly-brace-open: +2932 # character after 'z' is invalid; also used for blocks +2933 # . prologue +2934 55/push-ebp +2935 89/<- %ebp 4/r32/esp +2936 # (eax..ecx) = "{a" +2937 b8/copy-to-eax "{a"/imm32 +2938 8b/-> *eax 1/r32/ecx +2939 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2940 05/add-to-eax 4/imm32 +2941 # var slice/ecx: slice = {eax, ecx} +2942 51/push-ecx +2943 50/push-eax +2944 89/<- %ecx 4/r32/esp +2945 # +2946 (is-identifier? %ecx) +2947 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open") +2948 # . epilogue +2949 89/<- %esp 5/r32/ebp +2950 5d/pop-to-ebp +2951 c3/return +2952 +2953 test-is-identifier-curly-brace-close: +2954 # . prologue +2955 55/push-ebp +2956 89/<- %ebp 4/r32/esp +2957 # (eax..ecx) = "}a" +2958 b8/copy-to-eax "}a"/imm32 +2959 8b/-> *eax 1/r32/ecx +2960 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2961 05/add-to-eax 4/imm32 +2962 # var slice/ecx: slice = {eax, ecx} +2963 51/push-ecx +2964 50/push-eax +2965 89/<- %ecx 4/r32/esp +2966 # +2967 (is-identifier? %ecx) +2968 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close") +2969 # . epilogue +2970 89/<- %esp 5/r32/ebp +2971 5d/pop-to-ebp +2972 c3/return +2973 +2974 test-is-identifier-hyphen: +2975 # disallow leading '-' since '->' has special meaning +2976 # . prologue +2977 55/push-ebp +2978 89/<- %ebp 4/r32/esp +2979 # (eax..ecx) = "-a" +2980 b8/copy-to-eax "-a"/imm32 +2981 8b/-> *eax 1/r32/ecx +2982 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2983 05/add-to-eax 4/imm32 +2984 # var slice/ecx: slice = {eax, ecx} +2985 51/push-ecx +2986 50/push-eax +2987 89/<- %ecx 4/r32/esp +2988 # +2989 (is-identifier? %ecx) +2990 (check-ints-equal %eax 0 "F - test-is-identifier-hyphen") +2991 # . epilogue +2992 89/<- %esp 5/r32/ebp +2993 5d/pop-to-ebp +2994 c3/return +2995 +2996 populate-mu-function-body: # in: (addr buffered-file), out: (handle function), vars: (addr stack (handle var)) +2997 # . prologue +2998 55/push-ebp +2999 89/<- %ebp 4/r32/esp +3000 # . save registers 3001 50/push-eax -3002 89/<- %ecx 4/r32/esp -3003 # -3004 (is-identifier? %ecx) -3005 (check-ints-equal %eax 0 "F - test-is-identifier-@") -3006 # . epilogue -3007 89/<- %esp 5/r32/ebp -3008 5d/pop-to-ebp -3009 c3/return -3010 -3011 test-is-identifier-backtick: -3012 # character before 'a' is invalid -3013 # . prologue -3014 55/push-ebp -3015 89/<- %ebp 4/r32/esp -3016 # (eax..ecx) = "`a" -3017 b8/copy-to-eax "`a"/imm32 -3018 8b/-> *eax 1/r32/ecx -3019 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3020 05/add-to-eax 4/imm32 -3021 # var slice/ecx: slice = {eax, ecx} -3022 51/push-ecx -3023 50/push-eax -3024 89/<- %ecx 4/r32/esp -3025 # -3026 (is-identifier? %ecx) -3027 (check-ints-equal %eax 0 "F - test-is-identifier-backtick") -3028 # . epilogue -3029 89/<- %esp 5/r32/ebp -3030 5d/pop-to-ebp -3031 c3/return -3032 -3033 test-is-identifier-curly-brace-open: -3034 # character after 'z' is invalid; also used for blocks -3035 # . prologue -3036 55/push-ebp -3037 89/<- %ebp 4/r32/esp -3038 # (eax..ecx) = "{a" -3039 b8/copy-to-eax "{a"/imm32 -3040 8b/-> *eax 1/r32/ecx -3041 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3042 05/add-to-eax 4/imm32 -3043 # var slice/ecx: slice = {eax, ecx} -3044 51/push-ecx -3045 50/push-eax -3046 89/<- %ecx 4/r32/esp -3047 # -3048 (is-identifier? %ecx) -3049 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open") -3050 # . epilogue -3051 89/<- %esp 5/r32/ebp -3052 5d/pop-to-ebp -3053 c3/return -3054 -3055 test-is-identifier-curly-brace-close: -3056 # . prologue -3057 55/push-ebp -3058 89/<- %ebp 4/r32/esp -3059 # (eax..ecx) = "}a" -3060 b8/copy-to-eax "}a"/imm32 -3061 8b/-> *eax 1/r32/ecx -3062 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3063 05/add-to-eax 4/imm32 -3064 # var slice/ecx: slice = {eax, ecx} -3065 51/push-ecx -3066 50/push-eax -3067 89/<- %ecx 4/r32/esp -3068 # -3069 (is-identifier? %ecx) -3070 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close") -3071 # . epilogue -3072 89/<- %esp 5/r32/ebp -3073 5d/pop-to-ebp -3074 c3/return -3075 -3076 test-is-identifier-hyphen: -3077 # disallow leading '-' since '->' has special meaning -3078 # . prologue -3079 55/push-ebp -3080 89/<- %ebp 4/r32/esp -3081 # (eax..ecx) = "-a" -3082 b8/copy-to-eax "-a"/imm32 -3083 8b/-> *eax 1/r32/ecx -3084 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3085 05/add-to-eax 4/imm32 -3086 # var slice/ecx: slice = {eax, ecx} -3087 51/push-ecx -3088 50/push-eax -3089 89/<- %ecx 4/r32/esp -3090 # -3091 (is-identifier? %ecx) -3092 (check-ints-equal %eax 0 "F - test-is-identifier-hyphen") -3093 # . epilogue -3094 89/<- %esp 5/r32/ebp -3095 5d/pop-to-ebp -3096 c3/return -3097 -3098 populate-mu-function-body: # in: (addr buffered-file), out: (handle function), vars: (addr stack (handle var)) -3099 # . prologue -3100 55/push-ebp -3101 89/<- %ebp 4/r32/esp -3102 # . save registers -3103 50/push-eax -3104 56/push-esi -3105 57/push-edi -3106 # esi = in -3107 8b/-> *(ebp+8) 6/r32/esi -3108 # edi = out -3109 8b/-> *(ebp+0xc) 7/r32/edi -3110 # initialize some global state -3111 c7 0/subop/copy *Curr-block-depth 1/imm32 -3112 c7 0/subop/copy *Next-local-stack-offset -4/imm32 -3113 # var eax: (handle block) = parse-mu-block(in, vars, fn) -3114 (parse-mu-block %esi *(ebp+0x10) %edi) # => eax -3115 # out->body = eax -3116 89/<- *(edi+0x10) 0/r32/eax # Function-body -3117 $populate-mu-function-body:end: -3118 # . restore registers -3119 5f/pop-to-edi -3120 5e/pop-to-esi -3121 58/pop-to-eax -3122 # . epilogue -3123 89/<- %esp 5/r32/ebp -3124 5d/pop-to-ebp -3125 c3/return -3126 -3127 == data -3128 -3129 # Global state added to each var record when parsing a function -3130 -3131 Curr-block-depth: # (addr int) -3132 0/imm32 -3133 Next-local-stack-offset: # (addr int) -3134 -4/imm32 -3135 -3136 Next-block-index: # (addr int) -3137 1/imm32 -3138 -3139 == code -3140 -3141 # parses a block, assuming that the leading '{' has already been read by the caller -3142 parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle block) -3143 # pseudocode: -3144 # var line: (stream byte 512) -3145 # var word-slice: slice -3146 # increment *Curr-block-depth -3147 # result/eax = allocate(Heap, Stmt-size) -3148 # result->tag = 0/block -3149 # result->name = some unique name -3150 # while true # line loop -3151 # clear-stream(line) -3152 # read-line-buffered(in, line) -3153 # if (line->write == 0) break # end of file -3154 # word-slice = next-word(line) -3155 # if slice-empty?(word-slice) # end of line -3156 # continue -3157 # else if slice-starts-with?(word-slice, "#") -3158 # continue -3159 # else if slice-equal?(word-slice, "{") -3160 # assert(no-tokens-in(line)) -3161 # block = parse-mu-block(in, vars, fn) -3162 # append-to-block(result, block) -3163 # else if slice-equal?(word-slice, "}") -3164 # break -3165 # else if slice-ends-with?(word-slice, ":") -3166 # # TODO: error-check the rest of 'line' -3167 # --word-slice->end to skip ':' -3168 # named-block = parse-mu-named-block(word-slice, in, vars, fn) -3169 # append-to-block(result, named-block) -3170 # else if slice-equal?(word-slice, "var") -3171 # var-def = parse-mu-var-def(line, vars) -3172 # append-to-block(result, var-def) -3173 # else -3174 # stmt = parse-mu-stmt(line, vars, fn) -3175 # append-to-block(result, stmt) -3176 # decrement *Curr-block-depth -3177 # return result -3178 # -3179 # . prologue -3180 55/push-ebp -3181 89/<- %ebp 4/r32/esp -3182 # . save registers -3183 51/push-ecx -3184 52/push-edx -3185 53/push-ebx -3186 57/push-edi -3187 # var line/ecx: (stream byte 512) -3188 81 5/subop/subtract %esp 0x200/imm32 -3189 68/push 0x200/imm32/length -3190 68/push 0/imm32/read -3191 68/push 0/imm32/write -3192 89/<- %ecx 4/r32/esp -3193 # var word-slice/edx: slice -3194 68/push 0/imm32/end -3195 68/push 0/imm32/start -3196 89/<- %edx 4/r32/esp -3197 # edi = result -3198 (allocate Heap *Stmt-size) # => eax -3199 (zero-out %eax *Stmt-size) -3200 89/<- %edi 0/r32/eax -3201 # set result->tag -3202 c7 0/subop/copy *edi 0/imm32/block # Stmt-tag -3203 # set result->var -3204 (new-block-name *(ebp+0x10)) # => eax -3205 89/<- *(edi+8) 0/r32/eax # Block-var -3206 # push result->var to vars -3207 (push *(ebp+0xc) %eax) -3208 # increment *Curr-block-depth -3209 ff 0/subop/increment *Curr-block-depth -3210 { -3211 $parse-mu-block:line-loop: -3212 # line = read-line-buffered(in) -3213 (clear-stream %ecx) -3214 (read-line-buffered *(ebp+8) %ecx) -3215 #? (write-buffered Stderr "line: ") -3216 #? (write-stream-data Stderr %ecx) -3217 #? (write-buffered Stderr Newline) -3218 #? (flush Stderr) -3219 # if (line->write == 0) break -3220 81 7/subop/compare *ecx 0/imm32 -3221 0f 84/jump-if-= break/disp32 -3222 # word-slice = next-word(line) -3223 (next-word %ecx %edx) -3224 #? (write-buffered Stderr "word: ") -3225 #? (write-slice-buffered Stderr %edx) -3226 #? (write-buffered Stderr Newline) -3227 #? (flush Stderr) -3228 # if slice-empty?(word-slice) continue -3229 (slice-empty? %edx) -3230 3d/compare-eax-and 0/imm32 -3231 0f 85/jump-if-!= loop/disp32 -3232 # if (slice-starts-with?(word-slice, '#') continue -3233 # . eax = *word-slice->start -3234 8b/-> *edx 0/r32/eax -3235 8a/copy-byte *eax 0/r32/AL -3236 81 4/subop/and %eax 0xff/imm32 -3237 # . if (eax == '#') continue -3238 3d/compare-eax-and 0x23/imm32/hash -3239 0f 84/jump-if-= loop/disp32 -3240 # if slice-equal?(word-slice, "{") -3241 { -3242 $parse-mu-block:check-for-block: -3243 (slice-equal? %edx "{") -3244 3d/compare-eax-and 0/imm32 -3245 74/jump-if-= break/disp8 -3246 (check-no-tokens-left %ecx) -3247 # parse new block and append -3248 (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax -3249 (append-to-block Heap %edi %eax) -3250 e9/jump $parse-mu-block:line-loop/disp32 -3251 } -3252 # if slice-equal?(word-slice, "}") break -3253 $parse-mu-block:check-for-end: -3254 (slice-equal? %edx "}") -3255 3d/compare-eax-and 0/imm32 -3256 0f 85/jump-if-!= break/disp32 -3257 # if slice-ends-with?(word-slice, ":") parse named block and append -3258 { -3259 $parse-mu-block:check-for-named-block: -3260 # . eax = *(word-slice->end-1) -3261 8b/-> *(edx+4) 0/r32/eax -3262 48/decrement-eax -3263 8a/copy-byte *eax 0/r32/AL -3264 81 4/subop/and %eax 0xff/imm32 -3265 # . if (eax != ':') break -3266 3d/compare-eax-and 0x3a/imm32/colon -3267 0f 85/jump-if-!= break/disp32 -3268 # TODO: error-check the rest of 'line' -3269 # -3270 # skip ':' -3271 ff 1/subop/decrement *(edx+4) # Slice-end -3272 # -3273 (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax -3274 (append-to-block Heap %edi %eax) -3275 e9/jump $parse-mu-block:line-loop/disp32 -3276 } -3277 # if slice-equal?(word-slice, "var") -3278 { -3279 $parse-mu-block:check-for-var: -3280 (slice-equal? %edx "var") -3281 3d/compare-eax-and 0/imm32 -3282 74/jump-if-= break/disp8 -3283 # -3284 (parse-mu-var-def %ecx *(ebp+0xc)) # => eax -3285 (append-to-block Heap %edi %eax) -3286 e9/jump $parse-mu-block:line-loop/disp32 -3287 } -3288 $parse-mu-block:regular-stmt: -3289 # otherwise -3290 (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10)) # => eax -3291 (append-to-block Heap %edi %eax) -3292 e9/jump loop/disp32 -3293 } # end line loop -3294 # decrement *Curr-block-depth -3295 ff 1/subop/decrement *Curr-block-depth -3296 # -3297 (pop *(ebp+0xc)) # => eax -3298 # return result -3299 89/<- %eax 7/r32/edi -3300 $parse-mu-block:end: -3301 # . reclaim locals -3302 81 0/subop/add %esp 0x214/imm32 -3303 # . restore registers -3304 5f/pop-to-edi -3305 5b/pop-to-ebx -3306 5a/pop-to-edx -3307 59/pop-to-ecx -3308 # . epilogue -3309 89/<- %esp 5/r32/ebp -3310 5d/pop-to-ebp -3311 c3/return -3312 -3313 $parse-mu-block:abort: -3314 # error("'{' or '}' should be on its own line, but got '") -3315 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") -3316 (rewind-stream %ecx) -3317 (write-stream 2 %ecx) -3318 (write-buffered Stderr "'\n") -3319 (flush Stderr) -3320 # . syscall(exit, 1) -3321 bb/copy-to-ebx 1/imm32 -3322 b8/copy-to-eax 1/imm32/exit -3323 cd/syscall 0x80/imm8 -3324 # never gets here -3325 -3326 new-block-name: # fn: (handle function) -> result/eax: (handle var) -3327 # . prologue -3328 55/push-ebp -3329 89/<- %ebp 4/r32/esp -3330 # . save registers -3331 51/push-ecx -3332 52/push-edx -3333 # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:' -3334 8b/-> *(ebp+8) 0/r32/eax -3335 8b/-> *eax 0/r32/eax # Function-name -3336 8b/-> *eax 0/r32/eax # String-length -3337 05/add-to-eax 0xd/imm32 # 10 + 2 for '$:' -3338 89/<- %ecx 0/r32/eax -3339 # var name/edx: (stream byte n) -3340 29/subtract %esp 1/r32/ecx -3341 ff 6/subop/push %ecx -3342 68/push 0/imm32/read -3343 68/push 0/imm32/write -3344 89/<- %edx 4/r32/esp -3345 (clear-stream %edx) -3346 # eax = fn->name -3347 8b/-> *(ebp+8) 0/r32/eax -3348 8b/-> *eax 0/r32/eax # Function-name -3349 # construct result using Next-block-index (and increment it) -3350 (write %edx "$") -3351 (write %edx %eax) -3352 (write %edx ":") -3353 (print-int32 %edx *Next-block-index) -3354 ff 0/subop/increment *Next-block-index -3355 # var s/eax: slice = {name->data, name->data + name->write} (clobbering edx) -3356 # . eax = name->write -3357 8b/-> *edx 0/r32/eax -3358 # . edx = name->data -3359 8d/copy-address *(edx+0xc) 2/r32/edx -3360 # . eax = name->write + name->data -3361 01/add %eax 2/r32/edx -3362 # . push {edx, eax} -3363 ff 6/subop/push %eax -3364 ff 6/subop/push %edx -3365 89/<- %eax 4/r32/esp -3366 # var final-name/edx : (addr array byte) = slice-to-string(s) -3367 (slice-to-string Heap %eax) # => eax -3368 89/<- %edx 0/r32/eax -3369 # set result->var -3370 # . var type/eax: (handle tree type-id) = literal -3371 (allocate Heap *Tree-size) # => eax -3372 (zero-out %eax *Tree-size) # default type is 'literal' -3373 # . var result/eax: (handle var) = new-var(final-name, type) -3374 (new-var Heap %edx %eax *Curr-block-depth 0 0) # => eax -3375 $new-block-name:end: -3376 # . reclaim locals -3377 81 0/subop/add %ecx 0xc/imm32 # name.{read/write/len} -3378 81 0/subop/add %ecx 8/imm32 # slice -3379 01/add %esp 1/r32/ecx -3380 # . restore registers -3381 5a/pop-to-edx -3382 59/pop-to-ecx -3383 # . epilogue -3384 89/<- %esp 5/r32/ebp -3385 5d/pop-to-ebp -3386 c3/return -3387 -3388 check-no-tokens-left: # line: (addr stream byte) -3389 # . prologue -3390 55/push-ebp -3391 89/<- %ebp 4/r32/esp -3392 # . save registers -3393 50/push-eax -3394 51/push-ecx -3395 # var s/ecx: slice -3396 68/push 0/imm32/end -3397 68/push 0/imm32/start -3398 89/<- %ecx 4/r32/esp -3399 # -3400 (next-word *(ebp+8) %ecx) -3401 # if slice-empty?(s) return -3402 (slice-empty? %ecx) -3403 3d/compare-eax-and 0/imm32 -3404 75/jump-if-!= $check-no-tokens-left:end/disp8 -3405 # if (slice-starts-with?(s, '#') return -3406 # . eax = *s->start -3407 8b/-> *edx 0/r32/eax -3408 8a/copy-byte *eax 0/r32/AL -3409 81 4/subop/and %eax 0xff/imm32 -3410 # . if (eax == '#') continue -3411 3d/compare-eax-and 0x23/imm32/hash -3412 74/jump-if-= $check-no-tokens-left:end/disp8 -3413 # abort -3414 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") -3415 (rewind-stream %ecx) -3416 (write-stream 2 %ecx) -3417 (write-buffered Stderr "'\n") -3418 (flush Stderr) -3419 # . syscall(exit, 1) -3420 bb/copy-to-ebx 1/imm32 -3421 b8/copy-to-eax 1/imm32/exit -3422 cd/syscall 0x80/imm8 -3423 # never gets here -3424 $check-no-tokens-left:end: -3425 # . reclaim locals -3426 81 0/subop/add %esp 8/imm32 -3427 # . restore registers -3428 59/pop-to-ecx -3429 58/pop-to-eax -3430 # . epilogue -3431 89/<- %esp 5/r32/ebp -3432 5d/pop-to-ebp -3433 c3/return -3434 -3435 parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) -3436 # pseudocode: -3437 # var s: (addr array byte) = slice-to-string(name) -3438 # var v: (handle var) = new-var(s, 0) -3439 # v->block-depth = *Curr-block-depth # containing block depth -3440 # push(vars, v) -3441 # result = parse-mu-block(in, vars, fn) -3442 # pop(vars) -3443 # result->name = s -3444 # return result -3445 # -3446 # . prologue -3447 55/push-ebp -3448 89/<- %ebp 4/r32/esp -3449 # . save registers -3450 51/push-ecx -3451 # var s/ecx: (addr array byte) = slice-to-string(name) -3452 (slice-to-string Heap *(ebp+8)) # => eax -3453 89/<- %ecx 0/r32/eax -3454 # var type/eax: (handle tree type-id) = literal -3455 (allocate Heap *Tree-size) # => eax -3456 (zero-out %eax *Tree-size) # default type is 'literal' -3457 # var v/ecx: (handle var) = new-var(s, type) -3458 (new-var Heap %ecx %eax *Curr-block-depth 0 0) # => eax -3459 89/<- %ecx 0/r32/eax -3460 # push(vars, v) -3461 (push *(ebp+0x10) %ecx) -3462 # eax = result -3463 (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) # => eax -3464 # pop the var -3465 50/push-eax -3466 (pop *(ebp+0x10)) # => eax -3467 58/pop-to-eax -3468 # result->tag = named-block -3469 c7 0/subop/copy *eax 0/imm32/block # Stmt-tag -3470 # result->var = v -3471 89/<- *(eax+8) 1/r32/ecx # Block-var -3472 $parse-mu-named-block:end: -3473 # . restore registers -3474 59/pop-to-ecx -3475 # . epilogue -3476 89/<- %esp 5/r32/ebp -3477 5d/pop-to-ebp -3478 c3/return -3479 -3480 parse-mu-var-def: # line: (addr stream byte), vars: (addr stack (handle var)) -> result/eax: (handle stmt) -3481 # . prologue -3482 55/push-ebp -3483 89/<- %ebp 4/r32/esp -3484 # . save registers -3485 51/push-ecx -3486 52/push-edx -3487 # var word-slice/ecx: slice -3488 68/push 0/imm32/end -3489 68/push 0/imm32/start -3490 89/<- %ecx 4/r32/esp -3491 # var v/edx: (handle var) = parse-var-with-type(line) -3492 (next-word *(ebp+8) %ecx) -3493 (parse-var-with-type %ecx *(ebp+8)) # => eax -3494 89/<- %edx 0/r32/eax -3495 # v->stack-offset = *Next-local-stack-offset -3496 8b/-> *Next-local-stack-offset 0/r32/eax -3497 89/<- *(edx+0xc) 0/r32/eax # Var-stack-offset -3498 # *Next-local-stack-offset -= size-of(v) -3499 (size-of %edx) # => eax -3500 29/subtract-from *Next-local-stack-offset 0/r32/eax -3501 # v->block-depth = *Curr-block-depth -3502 8b/-> *Curr-block-depth 0/r32/eax -3503 89/<- *(edx+8) 0/r32/eax -3504 # -3505 (push *(ebp+0xc) %edx) -3506 # either v has no register and there's no more to this line -3507 8b/-> *(edx+0x10) 0/r32/eax # Var-register -3508 3d/compare-eax-and 0/imm32 -3509 { -3510 75/jump-if-!= break/disp8 -3511 # TODO: ensure that there's nothing else on this line -3512 (new-vardef Heap %edx) # => eax -3513 eb/jump $parse-mu-var-def:end/disp8 -3514 } -3515 # or v has a register and there's more to this line -3516 { -3517 74/jump-if-= break/disp8 -3518 # ensure that the next word is '<-' -3519 (next-word *(ebp+8) %ecx) -3520 (slice-equal? %ecx "<-") # => eax -3521 3d/compare-eax-and 0/imm32 -3522 74/jump-if-= $parse-mu-var-def:abort/disp8 -3523 # -3524 (new-regvardef Heap %edx) # => eax -3525 (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc)) -3526 } -3527 $parse-mu-var-def:end: -3528 # . reclaim locals -3529 81 0/subop/add %esp 8/imm32 -3530 # . restore registers -3531 5a/pop-to-edx -3532 59/pop-to-ecx -3533 # . epilogue -3534 89/<- %esp 5/r32/ebp -3535 5d/pop-to-ebp -3536 c3/return -3537 -3538 $parse-mu-var-def:abort: -3539 (rewind-stream *(ebp+8)) -3540 # error("register variable requires a valid instruction to initialize but got '" line "'\n") -3541 (write-buffered Stderr "register variable requires a valid instruction to initialize but got '") -3542 (flush Stderr) -3543 (write-stream 2 *(ebp+8)) -3544 (write-buffered Stderr "'\n") -3545 (flush Stderr) -3546 # . syscall(exit, 1) -3547 bb/copy-to-ebx 1/imm32 -3548 b8/copy-to-eax 1/imm32/exit -3549 cd/syscall 0x80/imm8 -3550 # never gets here -3551 -3552 test-parse-mu-var-def: -3553 # 'var n: int' -3554 # . prologue -3555 55/push-ebp -3556 89/<- %ebp 4/r32/esp -3557 # setup -3558 (clear-stream _test-input-stream) -3559 (write _test-input-stream "n: int\n") # caller has consumed the 'var' -3560 # var vars/ecx: (stack (addr var) 4) -3561 81 5/subop/subtract %esp 0x10/imm32 -3562 68/push 0x10/imm32/length -3563 68/push 0/imm32/top -3564 89/<- %ecx 4/r32/esp -3565 (clear-stack %ecx) -3566 # convert -3567 (parse-mu-var-def _test-input-stream %ecx) # => eax -3568 # check result -3569 (check-ints-equal *eax 2 "F - test-parse-mu-var-def/tag") # Stmt-tag is vardef -3570 8b/-> *(eax+4) 0/r32/eax # Vardef-var -3571 (check-strings-equal *eax "n" "F - test-parse-mu-var-def/var-name") # Var-name -3572 (check-ints-equal *(eax+0x10) 0 "F - test-parse-mu-var-def/var-register") # Var-register -3573 # TODO: ensure stack-offset is -4 -3574 # TODO: ensure block-depth is 1 -3575 # ensure type is int -3576 8b/-> *(eax+4) 0/r32/eax # Var-type -3577 (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0") # Tree-left -3578 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-var-def/var-type:0") # Tree-right -3579 # . epilogue -3580 89/<- %esp 5/r32/ebp -3581 5d/pop-to-ebp -3582 c3/return -3583 -3584 test-parse-mu-reg-var-def: -3585 # 'var n/eax: int <- copy 0' -3586 # . prologue -3587 55/push-ebp -3588 89/<- %ebp 4/r32/esp -3589 # setup -3590 (clear-stream _test-input-stream) -3591 (write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var' -3592 # var vars/ecx: (stack (addr var) 4) -3593 81 5/subop/subtract %esp 0x10/imm32 -3594 68/push 0x10/imm32/length -3595 68/push 0/imm32/top -3596 89/<- %ecx 4/r32/esp -3597 (clear-stack %ecx) -3598 # convert -3599 (parse-mu-var-def _test-input-stream %ecx) # => eax -3600 # check result -3601 (check-ints-equal *eax 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is regvardef -3602 8b/-> *(eax+0xc) 0/r32/eax # Regvardef-outputs -3603 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/single-output") # List-next -3604 8b/-> *eax 0/r32/eax # List-value -3605 (check-strings-equal *eax "n" "F - test-parse-mu-reg-var-def/output-name") # Var-name -3606 (check-strings-equal *(eax+0x10) "eax" "F - test-parse-mu-reg-var-def/output-register") # Var-register -3607 # TODO: ensure stack-offset is -4 -3608 # TODO: ensure block-depth is 1 -3609 # ensure type is int -3610 8b/-> *(eax+4) 0/r32/eax # Var-type -3611 (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-left -3612 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-right -3613 # . epilogue -3614 89/<- %esp 5/r32/ebp -3615 5d/pop-to-ebp -3616 c3/return -3617 -3618 parse-mu-stmt: # line: (addr stream byte), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) -3619 # pseudocode: -3620 # var name: slice -3621 # result = allocate(Heap, Stmt-size) -3622 # if stmt-has-outputs?(line) -3623 # while true -3624 # name = next-mu-token(line) -3625 # if (name == '<-') break -3626 # assert(is-identifier?(name)) -3627 # var v: (handle var) = lookup-or-define-var(name, vars, fn) # regular stmts may define vars in fn outputs -3628 # result->outputs = append(result->outputs, v) -3629 # add-operation-and-inputs-to-stmt(result, line, vars) -3630 # -3631 # . prologue -3632 55/push-ebp -3633 89/<- %ebp 4/r32/esp -3634 # . save registers -3635 51/push-ecx -3636 57/push-edi -3637 # var name/ecx: slice -3638 68/push 0/imm32/end -3639 68/push 0/imm32/start -3640 89/<- %ecx 4/r32/esp -3641 # result/edi: (handle stmt) -3642 (allocate Heap *Stmt-size) # => eax -3643 (zero-out %eax *Stmt-size) -3644 89/<- %edi 0/r32/eax -3645 # result->tag = 1/stmt -3646 c7 0/subop/copy *edi 1/imm32/stmt1 # Stmt-tag -3647 { -3648 (stmt-has-outputs? *(ebp+8)) -3649 3d/compare-eax-and 0/imm32 -3650 0f 84/jump-if-= break/disp32 -3651 { -3652 $parse-mu-stmt:read-outputs: -3653 # name = next-mu-token(line) -3654 (next-mu-token *(ebp+8) %ecx) -3655 # if slice-empty?(word-slice) break -3656 (slice-empty? %ecx) -3657 3d/compare-eax-and 0/imm32 -3658 0f 85/jump-if-!= break/disp32 -3659 # if (name == "<-") break -3660 (slice-equal? %ecx "<-") -3661 3d/compare-eax-and 0/imm32 -3662 75/jump-if-!= break/disp8 -3663 # assert(is-identifier?(name)) -3664 (is-identifier? %ecx) -3665 3d/compare-eax-and 0/imm32 -3666 0f 84/jump-if-= $parse-mu-stmt:abort/disp32 -3667 # -3668 (lookup-or-define-var %ecx *(ebp+0xc) *(ebp+0x10)) # => eax -3669 (append-list Heap %eax *(edi+0xc)) # Stmt1-outputs => eax -3670 89/<- *(edi+0xc) 0/r32/eax # Stmt1-outputs -3671 e9/jump loop/disp32 -3672 } -3673 } -3674 (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc)) -3675 $parse-mu-stmt:end: -3676 # return result -3677 89/<- %eax 7/r32/edi -3678 # . reclaim locals -3679 81 0/subop/add %esp 8/imm32 -3680 # . restore registers -3681 5f/pop-to-edi -3682 59/pop-to-ecx -3683 # . epilogue -3684 89/<- %esp 5/r32/ebp -3685 5d/pop-to-ebp -3686 c3/return -3687 -3688 $parse-mu-stmt:abort: -3689 # error("invalid identifier '" name "'\n") -3690 (write-buffered Stderr "invalid identifier '") -3691 (write-slice-buffered Stderr %ecx) -3692 (write-buffered Stderr "'\n") -3693 (flush Stderr) -3694 # . syscall(exit, 1) -3695 bb/copy-to-ebx 1/imm32 -3696 b8/copy-to-eax 1/imm32/exit -3697 cd/syscall 0x80/imm8 -3698 # never gets here -3699 -3700 add-operation-and-inputs-to-stmt: # stmt: (handle stmt), line: (addr stream byte), vars: (addr stack (handle var)) -3701 # pseudocode: -3702 # stmt->name = slice-to-string(next-mu-token(line)) -3703 # while true -3704 # name = next-mu-token(line) -3705 # v = lookup-var-or-literal(name) -3706 # stmt->inouts = append(stmt->inouts, v) -3707 # -3708 # . prologue -3709 55/push-ebp -3710 89/<- %ebp 4/r32/esp -3711 # . save registers -3712 50/push-eax -3713 51/push-ecx -3714 57/push-edi -3715 # edi = stmt -3716 8b/-> *(ebp+8) 7/r32/edi -3717 # var name/ecx: slice -3718 68/push 0/imm32/end -3719 68/push 0/imm32/start -3720 89/<- %ecx 4/r32/esp -3721 $add-operation-and-inputs-to-stmt:read-operation: -3722 (next-mu-token *(ebp+0xc) %ecx) -3723 (slice-to-string Heap %ecx) # => eax -3724 89/<- *(edi+4) 0/r32/eax # Stmt1-operation or Regvardef-operation -3725 { -3726 $add-operation-and-inputs-to-stmt:read-inouts: -3727 # name = next-mu-token(line) -3728 (next-mu-token *(ebp+0xc) %ecx) -3729 # if slice-empty?(word-slice) break -3730 (slice-empty? %ecx) # => eax -3731 3d/compare-eax-and 0/imm32 -3732 0f 85/jump-if-!= break/disp32 -3733 # if (name == "<-") abort -3734 (slice-equal? %ecx "<-") -3735 3d/compare-eax-and 0/imm32 -3736 0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32 -3737 # -3738 (lookup-var-or-literal %ecx *(ebp+0x10)) # => eax -3739 (append-list Heap %eax *(edi+8)) # Stmt1-inouts or Regvardef-inouts => eax -3740 89/<- *(edi+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts -3741 e9/jump loop/disp32 -3742 } -3743 $add-operation-and-inputs-to-stmt:end: -3744 # . reclaim locals -3745 81 0/subop/add %esp 8/imm32 -3746 # . restore registers -3747 5f/pop-to-edi -3748 59/pop-to-ecx -3749 58/pop-to-eax -3750 # . epilogue -3751 89/<- %esp 5/r32/ebp -3752 5d/pop-to-ebp -3753 c3/return -3754 -3755 $add-operation-and-inputs-to-stmt:abort: -3756 # error("invalid statement '" line "'\n") -3757 (rewind-stream *(ebp+8)) -3758 (write-buffered Stderr "invalid identifier '") -3759 (flush Stderr) -3760 (write-stream 2 *(ebp+8)) -3761 (write-buffered Stderr "'\n") +3002 56/push-esi +3003 57/push-edi +3004 # esi = in +3005 8b/-> *(ebp+8) 6/r32/esi +3006 # edi = out +3007 8b/-> *(ebp+0xc) 7/r32/edi +3008 # initialize some global state +3009 c7 0/subop/copy *Curr-block-depth 1/imm32 +3010 c7 0/subop/copy *Next-local-stack-offset -4/imm32 +3011 # var eax: (handle block) = parse-mu-block(in, vars, fn) +3012 (parse-mu-block %esi *(ebp+0x10) %edi) # => eax +3013 # out->body = eax +3014 89/<- *(edi+0x10) 0/r32/eax # Function-body +3015 $populate-mu-function-body:end: +3016 # . restore registers +3017 5f/pop-to-edi +3018 5e/pop-to-esi +3019 58/pop-to-eax +3020 # . epilogue +3021 89/<- %esp 5/r32/ebp +3022 5d/pop-to-ebp +3023 c3/return +3024 +3025 == data +3026 +3027 # Global state added to each var record when parsing a function +3028 +3029 Curr-block-depth: # (addr int) +3030 0/imm32 +3031 Next-local-stack-offset: # (addr int) +3032 -4/imm32 +3033 +3034 Next-block-index: # (addr int) +3035 1/imm32 +3036 +3037 == code +3038 +3039 # parses a block, assuming that the leading '{' has already been read by the caller +3040 parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle block) +3041 # pseudocode: +3042 # var line: (stream byte 512) +3043 # var word-slice: slice +3044 # increment *Curr-block-depth +3045 # result/eax = allocate(Heap, Stmt-size) +3046 # result->tag = 0/block +3047 # result->name = some unique name +3048 # while true # line loop +3049 # clear-stream(line) +3050 # read-line-buffered(in, line) +3051 # if (line->write == 0) break # end of file +3052 # word-slice = next-mu-token(line) +3053 # if slice-empty?(word-slice) # end of line +3054 # continue +3055 # else if slice-starts-with?(word-slice, "#") +3056 # continue +3057 # else if slice-equal?(word-slice, "{") +3058 # assert(no-tokens-in(line)) +3059 # block = parse-mu-block(in, vars, fn) +3060 # append-to-block(result, block) +3061 # else if slice-equal?(word-slice, "}") +3062 # break +3063 # else if slice-ends-with?(word-slice, ":") +3064 # # TODO: error-check the rest of 'line' +3065 # --word-slice->end to skip ':' +3066 # named-block = parse-mu-named-block(word-slice, in, vars, fn) +3067 # append-to-block(result, named-block) +3068 # else if slice-equal?(word-slice, "var") +3069 # var-def = parse-mu-var-def(line, vars) +3070 # append-to-block(result, var-def) +3071 # else +3072 # stmt = parse-mu-stmt(line, vars, fn) +3073 # append-to-block(result, stmt) +3074 # decrement *Curr-block-depth +3075 # return result +3076 # +3077 # . prologue +3078 55/push-ebp +3079 89/<- %ebp 4/r32/esp +3080 # . save registers +3081 51/push-ecx +3082 52/push-edx +3083 53/push-ebx +3084 57/push-edi +3085 # var line/ecx: (stream byte 512) +3086 81 5/subop/subtract %esp 0x200/imm32 +3087 68/push 0x200/imm32/length +3088 68/push 0/imm32/read +3089 68/push 0/imm32/write +3090 89/<- %ecx 4/r32/esp +3091 # var word-slice/edx: slice +3092 68/push 0/imm32/end +3093 68/push 0/imm32/start +3094 89/<- %edx 4/r32/esp +3095 # edi = result +3096 (allocate Heap *Stmt-size) # => eax +3097 (zero-out %eax *Stmt-size) +3098 89/<- %edi 0/r32/eax +3099 # set result->tag +3100 c7 0/subop/copy *edi 0/imm32/block # Stmt-tag +3101 # set result->var +3102 (new-block-name *(ebp+0x10)) # => eax +3103 89/<- *(edi+8) 0/r32/eax # Block-var +3104 # push result->var to vars +3105 (push *(ebp+0xc) %eax) +3106 # increment *Curr-block-depth +3107 ff 0/subop/increment *Curr-block-depth +3108 { +3109 $parse-mu-block:line-loop: +3110 # line = read-line-buffered(in) +3111 (clear-stream %ecx) +3112 (read-line-buffered *(ebp+8) %ecx) +3113 #? (write-buffered Stderr "line: ") +3114 #? (write-stream-data Stderr %ecx) +3115 #? (write-buffered Stderr Newline) +3116 #? (flush Stderr) +3117 # if (line->write == 0) break +3118 81 7/subop/compare *ecx 0/imm32 +3119 0f 84/jump-if-= break/disp32 +3120 # word-slice = next-mu-token(line) +3121 (next-mu-token %ecx %edx) +3122 #? (write-buffered Stderr "word: ") +3123 #? (write-slice-buffered Stderr %edx) +3124 #? (write-buffered Stderr Newline) +3125 #? (flush Stderr) +3126 # if slice-empty?(word-slice) continue +3127 (slice-empty? %edx) +3128 3d/compare-eax-and 0/imm32 +3129 0f 85/jump-if-!= loop/disp32 +3130 # if (slice-starts-with?(word-slice, '#') continue +3131 # . eax = *word-slice->start +3132 8b/-> *edx 0/r32/eax +3133 8a/copy-byte *eax 0/r32/AL +3134 81 4/subop/and %eax 0xff/imm32 +3135 # . if (eax == '#') continue +3136 3d/compare-eax-and 0x23/imm32/hash +3137 0f 84/jump-if-= loop/disp32 +3138 # if slice-equal?(word-slice, "{") +3139 { +3140 $parse-mu-block:check-for-block: +3141 (slice-equal? %edx "{") +3142 3d/compare-eax-and 0/imm32 +3143 74/jump-if-= break/disp8 +3144 (check-no-tokens-left %ecx) +3145 # parse new block and append +3146 (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax +3147 (append-to-block Heap %edi %eax) +3148 e9/jump $parse-mu-block:line-loop/disp32 +3149 } +3150 # if slice-equal?(word-slice, "}") break +3151 $parse-mu-block:check-for-end: +3152 (slice-equal? %edx "}") +3153 3d/compare-eax-and 0/imm32 +3154 0f 85/jump-if-!= break/disp32 +3155 # if slice-ends-with?(word-slice, ":") parse named block and append +3156 { +3157 $parse-mu-block:check-for-named-block: +3158 # . eax = *(word-slice->end-1) +3159 8b/-> *(edx+4) 0/r32/eax +3160 48/decrement-eax +3161 8a/copy-byte *eax 0/r32/AL +3162 81 4/subop/and %eax 0xff/imm32 +3163 # . if (eax != ':') break +3164 3d/compare-eax-and 0x3a/imm32/colon +3165 0f 85/jump-if-!= break/disp32 +3166 # TODO: error-check the rest of 'line' +3167 # +3168 # skip ':' +3169 ff 1/subop/decrement *(edx+4) # Slice-end +3170 # +3171 (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax +3172 (append-to-block Heap %edi %eax) +3173 e9/jump $parse-mu-block:line-loop/disp32 +3174 } +3175 # if slice-equal?(word-slice, "var") +3176 { +3177 $parse-mu-block:check-for-var: +3178 (slice-equal? %edx "var") +3179 3d/compare-eax-and 0/imm32 +3180 74/jump-if-= break/disp8 +3181 # +3182 (parse-mu-var-def %ecx *(ebp+0xc)) # => eax +3183 (append-to-block Heap %edi %eax) +3184 e9/jump $parse-mu-block:line-loop/disp32 +3185 } +3186 $parse-mu-block:regular-stmt: +3187 # otherwise +3188 (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10)) # => eax +3189 (append-to-block Heap %edi %eax) +3190 e9/jump loop/disp32 +3191 } # end line loop +3192 # decrement *Curr-block-depth +3193 ff 1/subop/decrement *Curr-block-depth +3194 # +3195 (pop *(ebp+0xc)) # => eax +3196 # return result +3197 89/<- %eax 7/r32/edi +3198 $parse-mu-block:end: +3199 # . reclaim locals +3200 81 0/subop/add %esp 0x214/imm32 +3201 # . restore registers +3202 5f/pop-to-edi +3203 5b/pop-to-ebx +3204 5a/pop-to-edx +3205 59/pop-to-ecx +3206 # . epilogue +3207 89/<- %esp 5/r32/ebp +3208 5d/pop-to-ebp +3209 c3/return +3210 +3211 $parse-mu-block:abort: +3212 # error("'{' or '}' should be on its own line, but got '") +3213 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") +3214 (rewind-stream %ecx) +3215 (write-stream 2 %ecx) +3216 (write-buffered Stderr "'\n") +3217 (flush Stderr) +3218 # . syscall(exit, 1) +3219 bb/copy-to-ebx 1/imm32 +3220 b8/copy-to-eax 1/imm32/exit +3221 cd/syscall 0x80/imm8 +3222 # never gets here +3223 +3224 new-block-name: # fn: (handle function) -> result/eax: (handle var) +3225 # . prologue +3226 55/push-ebp +3227 89/<- %ebp 4/r32/esp +3228 # . save registers +3229 51/push-ecx +3230 52/push-edx +3231 # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:' +3232 8b/-> *(ebp+8) 0/r32/eax +3233 8b/-> *eax 0/r32/eax # Function-name +3234 8b/-> *eax 0/r32/eax # String-length +3235 05/add-to-eax 0xd/imm32 # 10 + 2 for '$:' +3236 89/<- %ecx 0/r32/eax +3237 # var name/edx: (stream byte n) +3238 29/subtract %esp 1/r32/ecx +3239 ff 6/subop/push %ecx +3240 68/push 0/imm32/read +3241 68/push 0/imm32/write +3242 89/<- %edx 4/r32/esp +3243 (clear-stream %edx) +3244 # eax = fn->name +3245 8b/-> *(ebp+8) 0/r32/eax +3246 8b/-> *eax 0/r32/eax # Function-name +3247 # construct result using Next-block-index (and increment it) +3248 (write %edx "$") +3249 (write %edx %eax) +3250 (write %edx ":") +3251 (print-int32 %edx *Next-block-index) +3252 ff 0/subop/increment *Next-block-index +3253 # var s/eax: slice = {name->data, name->data + name->write} (clobbering edx) +3254 # . eax = name->write +3255 8b/-> *edx 0/r32/eax +3256 # . edx = name->data +3257 8d/copy-address *(edx+0xc) 2/r32/edx +3258 # . eax = name->write + name->data +3259 01/add %eax 2/r32/edx +3260 # . push {edx, eax} +3261 ff 6/subop/push %eax +3262 ff 6/subop/push %edx +3263 89/<- %eax 4/r32/esp +3264 # var final-name/edx: (addr array byte) = slice-to-string(s) +3265 (slice-to-string Heap %eax) # => eax +3266 89/<- %edx 0/r32/eax +3267 # set result->var +3268 # . var type/eax: (handle tree type-id) = literal +3269 (allocate Heap *Tree-size) # => eax +3270 (zero-out %eax *Tree-size) # default type is 'literal' +3271 # . var result/eax: (handle var) = new-var(final-name, type) +3272 (new-var Heap %edx %eax *Curr-block-depth 0 0) # => eax +3273 $new-block-name:end: +3274 # . reclaim locals +3275 81 0/subop/add %ecx 0xc/imm32 # name.{read/write/len} +3276 81 0/subop/add %ecx 8/imm32 # slice +3277 01/add %esp 1/r32/ecx +3278 # . restore registers +3279 5a/pop-to-edx +3280 59/pop-to-ecx +3281 # . epilogue +3282 89/<- %esp 5/r32/ebp +3283 5d/pop-to-ebp +3284 c3/return +3285 +3286 check-no-tokens-left: # line: (addr stream byte) +3287 # . prologue +3288 55/push-ebp +3289 89/<- %ebp 4/r32/esp +3290 # . save registers +3291 50/push-eax +3292 51/push-ecx +3293 # var s/ecx: slice +3294 68/push 0/imm32/end +3295 68/push 0/imm32/start +3296 89/<- %ecx 4/r32/esp +3297 # +3298 (next-mu-token *(ebp+8) %ecx) +3299 # if slice-empty?(s) return +3300 (slice-empty? %ecx) +3301 3d/compare-eax-and 0/imm32 +3302 75/jump-if-!= $check-no-tokens-left:end/disp8 +3303 # if (slice-starts-with?(s, '#') return +3304 # . eax = *s->start +3305 8b/-> *edx 0/r32/eax +3306 8a/copy-byte *eax 0/r32/AL +3307 81 4/subop/and %eax 0xff/imm32 +3308 # . if (eax == '#') continue +3309 3d/compare-eax-and 0x23/imm32/hash +3310 74/jump-if-= $check-no-tokens-left:end/disp8 +3311 # abort +3312 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") +3313 (rewind-stream %ecx) +3314 (write-stream 2 %ecx) +3315 (write-buffered Stderr "'\n") +3316 (flush Stderr) +3317 # . syscall(exit, 1) +3318 bb/copy-to-ebx 1/imm32 +3319 b8/copy-to-eax 1/imm32/exit +3320 cd/syscall 0x80/imm8 +3321 # never gets here +3322 $check-no-tokens-left:end: +3323 # . reclaim locals +3324 81 0/subop/add %esp 8/imm32 +3325 # . restore registers +3326 59/pop-to-ecx +3327 58/pop-to-eax +3328 # . epilogue +3329 89/<- %esp 5/r32/ebp +3330 5d/pop-to-ebp +3331 c3/return +3332 +3333 parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) +3334 # pseudocode: +3335 # var s: (addr array byte) = slice-to-string(name) +3336 # var v: (handle var) = new-var(s, 0) +3337 # v->block-depth = *Curr-block-depth # containing block depth +3338 # push(vars, v) +3339 # result = parse-mu-block(in, vars, fn) +3340 # pop(vars) +3341 # result->name = s +3342 # return result +3343 # +3344 # . prologue +3345 55/push-ebp +3346 89/<- %ebp 4/r32/esp +3347 # . save registers +3348 51/push-ecx +3349 # var s/ecx: (addr array byte) = slice-to-string(name) +3350 (slice-to-string Heap *(ebp+8)) # => eax +3351 89/<- %ecx 0/r32/eax +3352 # var type/eax: (handle tree type-id) = literal +3353 (allocate Heap *Tree-size) # => eax +3354 (zero-out %eax *Tree-size) # default type is 'literal' +3355 # var v/ecx: (handle var) = new-var(s, type) +3356 (new-var Heap %ecx %eax *Curr-block-depth 0 0) # => eax +3357 89/<- %ecx 0/r32/eax +3358 # push(vars, v) +3359 (push *(ebp+0x10) %ecx) +3360 # eax = result +3361 (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) # => eax +3362 # pop the var +3363 50/push-eax +3364 (pop *(ebp+0x10)) # => eax +3365 58/pop-to-eax +3366 # result->tag = named-block +3367 c7 0/subop/copy *eax 0/imm32/block # Stmt-tag +3368 # result->var = v +3369 89/<- *(eax+8) 1/r32/ecx # Block-var +3370 $parse-mu-named-block:end: +3371 # . restore registers +3372 59/pop-to-ecx +3373 # . epilogue +3374 89/<- %esp 5/r32/ebp +3375 5d/pop-to-ebp +3376 c3/return +3377 +3378 parse-mu-var-def: # line: (addr stream byte), vars: (addr stack (handle var)) -> result/eax: (handle stmt) +3379 # . prologue +3380 55/push-ebp +3381 89/<- %ebp 4/r32/esp +3382 # . save registers +3383 51/push-ecx +3384 52/push-edx +3385 # var word-slice/ecx: slice +3386 68/push 0/imm32/end +3387 68/push 0/imm32/start +3388 89/<- %ecx 4/r32/esp +3389 # var v/edx: (handle var) = parse-var-with-type(line) +3390 (next-mu-token *(ebp+8) %ecx) +3391 (parse-var-with-type %ecx *(ebp+8)) # => eax +3392 89/<- %edx 0/r32/eax +3393 # v->stack-offset = *Next-local-stack-offset +3394 8b/-> *Next-local-stack-offset 0/r32/eax +3395 89/<- *(edx+0xc) 0/r32/eax # Var-stack-offset +3396 # *Next-local-stack-offset -= size-of(v) +3397 (size-of %edx) # => eax +3398 29/subtract-from *Next-local-stack-offset 0/r32/eax +3399 # v->block-depth = *Curr-block-depth +3400 8b/-> *Curr-block-depth 0/r32/eax +3401 89/<- *(edx+8) 0/r32/eax +3402 # +3403 (push *(ebp+0xc) %edx) +3404 # either v has no register and there's no more to this line +3405 8b/-> *(edx+0x10) 0/r32/eax # Var-register +3406 3d/compare-eax-and 0/imm32 +3407 { +3408 75/jump-if-!= break/disp8 +3409 # TODO: ensure that there's nothing else on this line +3410 (new-vardef Heap %edx) # => eax +3411 eb/jump $parse-mu-var-def:end/disp8 +3412 } +3413 # or v has a register and there's more to this line +3414 { +3415 74/jump-if-= break/disp8 +3416 # ensure that the next word is '<-' +3417 (next-mu-token *(ebp+8) %ecx) +3418 (slice-equal? %ecx "<-") # => eax +3419 3d/compare-eax-and 0/imm32 +3420 74/jump-if-= $parse-mu-var-def:abort/disp8 +3421 # +3422 (new-regvardef Heap %edx) # => eax +3423 (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc)) +3424 } +3425 $parse-mu-var-def:end: +3426 # . reclaim locals +3427 81 0/subop/add %esp 8/imm32 +3428 # . restore registers +3429 5a/pop-to-edx +3430 59/pop-to-ecx +3431 # . epilogue +3432 89/<- %esp 5/r32/ebp +3433 5d/pop-to-ebp +3434 c3/return +3435 +3436 $parse-mu-var-def:abort: +3437 (rewind-stream *(ebp+8)) +3438 # error("register variable requires a valid instruction to initialize but got '" line "'\n") +3439 (write-buffered Stderr "register variable requires a valid instruction to initialize but got '") +3440 (flush Stderr) +3441 (write-stream 2 *(ebp+8)) +3442 (write-buffered Stderr "'\n") +3443 (flush Stderr) +3444 # . syscall(exit, 1) +3445 bb/copy-to-ebx 1/imm32 +3446 b8/copy-to-eax 1/imm32/exit +3447 cd/syscall 0x80/imm8 +3448 # never gets here +3449 +3450 test-parse-mu-var-def: +3451 # 'var n: int' +3452 # . prologue +3453 55/push-ebp +3454 89/<- %ebp 4/r32/esp +3455 # setup +3456 (clear-stream _test-input-stream) +3457 (write _test-input-stream "n: int\n") # caller has consumed the 'var' +3458 # var vars/ecx: (stack (addr var) 4) +3459 81 5/subop/subtract %esp 0x10/imm32 +3460 68/push 0x10/imm32/length +3461 68/push 0/imm32/top +3462 89/<- %ecx 4/r32/esp +3463 (clear-stack %ecx) +3464 # convert +3465 (parse-mu-var-def _test-input-stream %ecx) # => eax +3466 # check result +3467 (check-ints-equal *eax 2 "F - test-parse-mu-var-def/tag") # Stmt-tag is vardef +3468 8b/-> *(eax+4) 0/r32/eax # Vardef-var +3469 (check-strings-equal *eax "n" "F - test-parse-mu-var-def/var-name") # Var-name +3470 (check-ints-equal *(eax+0x10) 0 "F - test-parse-mu-var-def/var-register") # Var-register +3471 # TODO: ensure stack-offset is -4 +3472 # TODO: ensure block-depth is 1 +3473 # ensure type is int +3474 8b/-> *(eax+4) 0/r32/eax # Var-type +3475 (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0") # Tree-left +3476 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-var-def/var-type:0") # Tree-right +3477 # . epilogue +3478 89/<- %esp 5/r32/ebp +3479 5d/pop-to-ebp +3480 c3/return +3481 +3482 test-parse-mu-reg-var-def: +3483 # 'var n/eax: int <- copy 0' +3484 # . prologue +3485 55/push-ebp +3486 89/<- %ebp 4/r32/esp +3487 # setup +3488 (clear-stream _test-input-stream) +3489 (write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var' +3490 # var vars/ecx: (stack (addr var) 4) +3491 81 5/subop/subtract %esp 0x10/imm32 +3492 68/push 0x10/imm32/length +3493 68/push 0/imm32/top +3494 89/<- %ecx 4/r32/esp +3495 (clear-stack %ecx) +3496 # convert +3497 (parse-mu-var-def _test-input-stream %ecx) # => eax +3498 # check result +3499 (check-ints-equal *eax 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is regvardef +3500 8b/-> *(eax+0xc) 0/r32/eax # Regvardef-outputs +3501 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/single-output") # List-next +3502 8b/-> *eax 0/r32/eax # List-value +3503 (check-strings-equal *eax "n" "F - test-parse-mu-reg-var-def/output-name") # Var-name +3504 (check-strings-equal *(eax+0x10) "eax" "F - test-parse-mu-reg-var-def/output-register") # Var-register +3505 # TODO: ensure stack-offset is -4 +3506 # TODO: ensure block-depth is 1 +3507 # ensure type is int +3508 8b/-> *(eax+4) 0/r32/eax # Var-type +3509 (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-left +3510 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-right +3511 # . epilogue +3512 89/<- %esp 5/r32/ebp +3513 5d/pop-to-ebp +3514 c3/return +3515 +3516 parse-mu-stmt: # line: (addr stream byte), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) +3517 # pseudocode: +3518 # var name: slice +3519 # result = allocate(Heap, Stmt-size) +3520 # if stmt-has-outputs?(line) +3521 # while true +3522 # name = next-mu-token(line) +3523 # if (name == '<-') break +3524 # assert(is-identifier?(name)) +3525 # var v: (handle var) = lookup-or-define-var(name, vars, fn) # regular stmts may define vars in fn outputs +3526 # result->outputs = append(result->outputs, v) +3527 # add-operation-and-inputs-to-stmt(result, line, vars) +3528 # +3529 # . prologue +3530 55/push-ebp +3531 89/<- %ebp 4/r32/esp +3532 # . save registers +3533 51/push-ecx +3534 57/push-edi +3535 # var name/ecx: slice +3536 68/push 0/imm32/end +3537 68/push 0/imm32/start +3538 89/<- %ecx 4/r32/esp +3539 # result/edi: (handle stmt) +3540 (allocate Heap *Stmt-size) # => eax +3541 (zero-out %eax *Stmt-size) +3542 89/<- %edi 0/r32/eax +3543 # result->tag = 1/stmt +3544 c7 0/subop/copy *edi 1/imm32/stmt1 # Stmt-tag +3545 { +3546 (stmt-has-outputs? *(ebp+8)) +3547 3d/compare-eax-and 0/imm32 +3548 0f 84/jump-if-= break/disp32 +3549 { +3550 $parse-mu-stmt:read-outputs: +3551 # name = next-mu-token(line) +3552 (next-mu-token *(ebp+8) %ecx) +3553 # if slice-empty?(word-slice) break +3554 (slice-empty? %ecx) +3555 3d/compare-eax-and 0/imm32 +3556 0f 85/jump-if-!= break/disp32 +3557 # if (name == "<-") break +3558 (slice-equal? %ecx "<-") +3559 3d/compare-eax-and 0/imm32 +3560 75/jump-if-!= break/disp8 +3561 # assert(is-identifier?(name)) +3562 (is-identifier? %ecx) +3563 3d/compare-eax-and 0/imm32 +3564 0f 84/jump-if-= $parse-mu-stmt:abort/disp32 +3565 # +3566 (lookup-or-define-var %ecx *(ebp+0xc) *(ebp+0x10)) # => eax +3567 (append-list Heap %eax *(edi+0xc)) # Stmt1-outputs => eax +3568 89/<- *(edi+0xc) 0/r32/eax # Stmt1-outputs +3569 e9/jump loop/disp32 +3570 } +3571 } +3572 (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc)) +3573 $parse-mu-stmt:end: +3574 # return result +3575 89/<- %eax 7/r32/edi +3576 # . reclaim locals +3577 81 0/subop/add %esp 8/imm32 +3578 # . restore registers +3579 5f/pop-to-edi +3580 59/pop-to-ecx +3581 # . epilogue +3582 89/<- %esp 5/r32/ebp +3583 5d/pop-to-ebp +3584 c3/return +3585 +3586 $parse-mu-stmt:abort: +3587 # error("invalid identifier '" name "'\n") +3588 (write-buffered Stderr "invalid identifier '") +3589 (write-slice-buffered Stderr %ecx) +3590 (write-buffered Stderr "'\n") +3591 (flush Stderr) +3592 # . syscall(exit, 1) +3593 bb/copy-to-ebx 1/imm32 +3594 b8/copy-to-eax 1/imm32/exit +3595 cd/syscall 0x80/imm8 +3596 # never gets here +3597 +3598 add-operation-and-inputs-to-stmt: # stmt: (handle stmt), line: (addr stream byte), vars: (addr stack (handle var)) +3599 # pseudocode: +3600 # stmt->name = slice-to-string(next-mu-token(line)) +3601 # while true +3602 # name = next-mu-token(line) +3603 # v = lookup-var-or-literal(name) +3604 # stmt->inouts = append(stmt->inouts, v) +3605 # +3606 # . prologue +3607 55/push-ebp +3608 89/<- %ebp 4/r32/esp +3609 # . save registers +3610 50/push-eax +3611 51/push-ecx +3612 57/push-edi +3613 # edi = stmt +3614 8b/-> *(ebp+8) 7/r32/edi +3615 # var name/ecx: slice +3616 68/push 0/imm32/end +3617 68/push 0/imm32/start +3618 89/<- %ecx 4/r32/esp +3619 $add-operation-and-inputs-to-stmt:read-operation: +3620 (next-mu-token *(ebp+0xc) %ecx) +3621 (slice-to-string Heap %ecx) # => eax +3622 89/<- *(edi+4) 0/r32/eax # Stmt1-operation or Regvardef-operation +3623 { +3624 $add-operation-and-inputs-to-stmt:read-inouts: +3625 # name = next-mu-token(line) +3626 (next-mu-token *(ebp+0xc) %ecx) +3627 # if slice-empty?(word-slice) break +3628 (slice-empty? %ecx) # => eax +3629 3d/compare-eax-and 0/imm32 +3630 0f 85/jump-if-!= break/disp32 +3631 # if (name == "<-") abort +3632 (slice-equal? %ecx "<-") +3633 3d/compare-eax-and 0/imm32 +3634 0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32 +3635 # +3636 (lookup-var-or-literal %ecx *(ebp+0x10)) # => eax +3637 (append-list Heap %eax *(edi+8)) # Stmt1-inouts or Regvardef-inouts => eax +3638 89/<- *(edi+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts +3639 e9/jump loop/disp32 +3640 } +3641 $add-operation-and-inputs-to-stmt:end: +3642 # . reclaim locals +3643 81 0/subop/add %esp 8/imm32 +3644 # . restore registers +3645 5f/pop-to-edi +3646 59/pop-to-ecx +3647 58/pop-to-eax +3648 # . epilogue +3649 89/<- %esp 5/r32/ebp +3650 5d/pop-to-ebp +3651 c3/return +3652 +3653 $add-operation-and-inputs-to-stmt:abort: +3654 # error("invalid statement '" line "'\n") +3655 (rewind-stream *(ebp+8)) +3656 (write-buffered Stderr "invalid identifier '") +3657 (flush Stderr) +3658 (write-stream 2 *(ebp+8)) +3659 (write-buffered Stderr "'\n") +3660 (flush Stderr) +3661 # . syscall(exit, 1) +3662 bb/copy-to-ebx 1/imm32 +3663 b8/copy-to-eax 1/imm32/exit +3664 cd/syscall 0x80/imm8 +3665 # never gets here +3666 +3667 stmt-has-outputs?: # line: (addr stream byte) -> result/eax: boolean +3668 # . prologue +3669 55/push-ebp +3670 89/<- %ebp 4/r32/esp +3671 # . save registers +3672 51/push-ecx +3673 # var word-slice/ecx: slice +3674 68/push 0/imm32/end +3675 68/push 0/imm32/start +3676 89/<- %ecx 4/r32/esp +3677 # result = false +3678 b8/copy-to-eax 0/imm32/false +3679 (rewind-stream *(ebp+8)) +3680 { +3681 (next-mu-token *(ebp+8) %ecx) +3682 # if slice-empty?(word-slice) break +3683 (slice-empty? %ecx) +3684 3d/compare-eax-and 0/imm32 +3685 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) +3686 0f 85/jump-if-!= break/disp32 +3687 # if slice-starts-with?(word-slice, '#') break +3688 # . eax = *word-slice->start +3689 8b/-> *ecx 0/r32/eax +3690 8a/copy-byte *eax 0/r32/AL +3691 81 4/subop/and %eax 0xff/imm32 +3692 # . if (eax == '#') break +3693 3d/compare-eax-and 0x23/imm32/hash +3694 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) +3695 0f 84/jump-if-= break/disp32 +3696 # if slice-equal?(word-slice, '<-') return true +3697 (slice-equal? %ecx "<-") +3698 3d/compare-eax-and 0/imm32 +3699 74/jump-if-= loop/disp8 +3700 b8/copy-to-eax 1/imm32/true +3701 } +3702 $stmt-has-outputs:end: +3703 (rewind-stream *(ebp+8)) +3704 # . reclaim locals +3705 81 0/subop/add %esp 8/imm32 +3706 # . restore registers +3707 59/pop-to-ecx +3708 # . epilogue +3709 89/<- %esp 5/r32/ebp +3710 5d/pop-to-ebp +3711 c3/return +3712 +3713 # if 'name' starts with a digit, create a new literal var for it +3714 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found +3715 lookup-var-or-literal: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) +3716 # . prologue +3717 55/push-ebp +3718 89/<- %ebp 4/r32/esp +3719 # . save registers +3720 51/push-ecx +3721 56/push-esi +3722 # esi = name +3723 8b/-> *(ebp+8) 6/r32/esi +3724 # if slice-empty?(name) abort +3725 (slice-empty? %esi) # => eax +3726 3d/compare-eax-and 0/imm32 +3727 0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32 +3728 # var c/ecx: byte = *name->start +3729 8b/-> *esi 1/r32/ecx +3730 8a/copy-byte *ecx 1/r32/CL +3731 81 4/subop/and %ecx 0xff/imm32 +3732 # if is-decimal-digit?(c) return new var(name) +3733 { +3734 (is-decimal-digit? %ecx) # => eax +3735 81 7/subop/compare %eax 0/imm32 +3736 74/jump-if-= break/disp8 +3737 (new-literal-integer Heap %esi) # => eax +3738 eb/jump $lookup-var-or-literal:end/disp8 +3739 } +3740 # else if (c == '"') return new var(name) +3741 { +3742 81 7/subop/compare %ecx 0x22/imm32/dquote +3743 75/jump-if-!= break/disp8 +3744 (new-literal-string Heap %esi) # => eax +3745 eb/jump $lookup-var-or-literal:end/disp8 +3746 } +3747 # otherwise return lookup-var(name, vars) +3748 { +3749 (lookup-var %esi *(ebp+0xc)) # => eax +3750 } +3751 $lookup-var-or-literal:end: +3752 # . restore registers +3753 5e/pop-to-esi +3754 59/pop-to-ecx +3755 # . epilogue +3756 89/<- %esp 5/r32/ebp +3757 5d/pop-to-ebp +3758 c3/return +3759 +3760 $lookup-var-or-literal:abort: +3761 (write-buffered Stderr "empty variable!") 3762 (flush Stderr) 3763 # . syscall(exit, 1) 3764 bb/copy-to-ebx 1/imm32 @@ -3713,4585 +3713,4519 @@ if ('onhashchange' in window) { 3766 cd/syscall 0x80/imm8 3767 # never gets here 3768 -3769 stmt-has-outputs?: # line: (addr stream byte) -> result/eax: boolean -3770 # . prologue -3771 55/push-ebp -3772 89/<- %ebp 4/r32/esp -3773 # . save registers -3774 51/push-ecx -3775 # var word-slice/ecx: slice -3776 68/push 0/imm32/end -3777 68/push 0/imm32/start -3778 89/<- %ecx 4/r32/esp -3779 # result = false -3780 b8/copy-to-eax 0/imm32/false -3781 (rewind-stream *(ebp+8)) -3782 { -3783 (next-mu-token *(ebp+8) %ecx) -3784 # if slice-empty?(word-slice) break -3785 (slice-empty? %ecx) -3786 3d/compare-eax-and 0/imm32 -3787 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) -3788 0f 85/jump-if-!= break/disp32 -3789 # if slice-starts-with?(word-slice, '#') break -3790 # . eax = *word-slice->start -3791 8b/-> *ecx 0/r32/eax -3792 8a/copy-byte *eax 0/r32/AL -3793 81 4/subop/and %eax 0xff/imm32 -3794 # . if (eax == '#') break -3795 3d/compare-eax-and 0x23/imm32/hash -3796 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) -3797 0f 84/jump-if-= break/disp32 -3798 # if slice-equal?(word-slice, '<-') return true -3799 (slice-equal? %ecx "<-") -3800 3d/compare-eax-and 0/imm32 -3801 74/jump-if-= loop/disp8 -3802 b8/copy-to-eax 1/imm32/true -3803 } -3804 $stmt-has-outputs:end: -3805 (rewind-stream *(ebp+8)) -3806 # . reclaim locals -3807 81 0/subop/add %esp 8/imm32 -3808 # . restore registers -3809 59/pop-to-ecx -3810 # . epilogue -3811 89/<- %esp 5/r32/ebp -3812 5d/pop-to-ebp -3813 c3/return -3814 -3815 # if 'name' starts with a digit, create a new literal var for it -3816 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found -3817 lookup-var-or-literal: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) -3818 # . prologue -3819 55/push-ebp -3820 89/<- %ebp 4/r32/esp -3821 # . save registers -3822 51/push-ecx -3823 56/push-esi -3824 # esi = name -3825 8b/-> *(ebp+8) 6/r32/esi -3826 # if slice-empty?(name) abort -3827 (slice-empty? %esi) # => eax -3828 3d/compare-eax-and 0/imm32 -3829 0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32 -3830 # var c/ecx: byte = *name->start -3831 8b/-> *esi 1/r32/ecx -3832 8a/copy-byte *ecx 1/r32/CL -3833 81 4/subop/and %ecx 0xff/imm32 -3834 # if is-decimal-digit?(c) return new var(name) -3835 { -3836 (is-decimal-digit? %ecx) # => eax -3837 81 7/subop/compare %eax 0/imm32 -3838 74/jump-if-= break/disp8 -3839 (new-literal-integer Heap %esi) # => eax -3840 eb/jump $lookup-var-or-literal:end/disp8 -3841 } -3842 # else if (c == '"') return new var(name) -3843 { -3844 81 7/subop/compare %ecx 0x22/imm32/dquote -3845 75/jump-if-!= break/disp8 -3846 (new-literal-string Heap %esi) # => eax -3847 eb/jump $lookup-var-or-literal:end/disp8 -3848 } -3849 # otherwise return lookup-var(name, vars) -3850 { -3851 (lookup-var %esi *(ebp+0xc)) # => eax -3852 } -3853 $lookup-var-or-literal:end: -3854 # . restore registers -3855 5e/pop-to-esi -3856 59/pop-to-ecx -3857 # . epilogue -3858 89/<- %esp 5/r32/ebp -3859 5d/pop-to-ebp -3860 c3/return -3861 -3862 $lookup-var-or-literal:abort: -3863 (write-buffered Stderr "empty variable!") -3864 (flush Stderr) -3865 # . syscall(exit, 1) -3866 bb/copy-to-ebx 1/imm32 -3867 b8/copy-to-eax 1/imm32/exit -3868 cd/syscall 0x80/imm8 -3869 # never gets here -3870 -3871 # return first 'name' from the top (back) of 'vars' and abort if not found -3872 lookup-var: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) -3873 # . prologue -3874 55/push-ebp -3875 89/<- %ebp 4/r32/esp -3876 # var target/eax: (handle array byte) = slice-to-string(name) -3877 (slice-to-string Heap *(ebp+8)) # => eax -3878 # -3879 (lookup-var-helper %eax *(ebp+0xc)) # => eax -3880 # if (result == 0) abort -3881 3d/compare-eax-and 0/imm32 -3882 74/jump-if-= $lookup-var:abort/disp8 -3883 $lookup-var:end: -3884 # . epilogue -3885 89/<- %esp 5/r32/ebp -3886 5d/pop-to-ebp -3887 c3/return -3888 -3889 $lookup-var:abort: -3890 (write-buffered Stderr "unknown variable '") -3891 (write-slice-buffered Stderr *(ebp+8)) -3892 (write-buffered Stderr "'\n") -3893 (flush Stderr) -3894 # . syscall(exit, 1) -3895 bb/copy-to-ebx 1/imm32 -3896 b8/copy-to-eax 1/imm32/exit -3897 cd/syscall 0x80/imm8 -3898 # never gets here -3899 -3900 # return first 'name' from the top (back) of 'vars', and 0/null if not found -3901 lookup-var-helper: # name: (addr array byte), vars: (addr stack (handle var)) -> result/eax: (handle var) -3902 # pseudocode: -3903 # var curr: (addr handle var) = &vars->data[vars->top - 4] -3904 # var min = vars->data -3905 # while curr >= min -3906 # var v: (handle var) = *curr -3907 # if v->name == name -3908 # return v -3909 # return 0 -3910 # -3911 # . prologue -3912 55/push-ebp -3913 89/<- %ebp 4/r32/esp -3914 # . save registers -3915 52/push-edx -3916 53/push-ebx -3917 56/push-esi -3918 # esi = vars -3919 8b/-> *(ebp+0xc) 6/r32/esi -3920 # ebx = vars->top -3921 8b/-> *esi 3/r32/ebx -3922 # if (vars->top > vars->length) abort -3923 3b/compare 0/r32/eax *(esi+4) -3924 0f 8f/jump-if-> $lookup-var-helper:error1/disp32 -3925 # var min/edx: (addr handle var) = vars->data -3926 8d/copy-address *(esi+8) 2/r32/edx -3927 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 4] -3928 81 5/subop/subtract %ebx 4/imm32 -3929 8d/copy-address *(esi+ebx+8) 3/r32/ebx -3930 { -3931 # if (curr < min) return 0 -3932 39/compare %ebx 2/r32/edx -3933 b8/copy-to-eax 0/imm32 -3934 0f 82/jump-if-addr< break/disp32 -3935 # var v/eax: (handle var) = *curr -3936 8b/-> *ebx 0/r32/eax -3937 # if (v->name == name) return v -3938 (string-equal? *eax *(ebp+8)) # Var-name -3939 3d/compare-eax-and 0/imm32 -3940 8b/-> *ebx 0/r32/eax -3941 75/jump-if-!= break/disp8 -3942 # curr -= 4 -3943 81 5/subop/subtract %ebx 4/imm32 -3944 e9/jump loop/disp32 -3945 } -3946 $lookup-var-helper:end: -3947 # . restore registers -3948 5e/pop-to-esi -3949 5b/pop-to-ebx -3950 5a/pop-to-edx -3951 # . epilogue -3952 89/<- %esp 5/r32/ebp -3953 5d/pop-to-ebp -3954 c3/return -3955 -3956 $lookup-var-helper:error1: -3957 (write-buffered Stderr "malformed stack when looking up '") -3958 (write-slice-buffered Stderr *(ebp+8)) -3959 (write-buffered Stderr "'\n") -3960 (flush Stderr) -3961 # . syscall(exit, 1) -3962 bb/copy-to-ebx 1/imm32 -3963 b8/copy-to-eax 1/imm32/exit -3964 cd/syscall 0x80/imm8 -3965 # never gets here +3769 # return first 'name' from the top (back) of 'vars' and abort if not found +3770 lookup-var: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) +3771 # . prologue +3772 55/push-ebp +3773 89/<- %ebp 4/r32/esp +3774 # var target/eax: (handle array byte) = slice-to-string(name) +3775 (slice-to-string Heap *(ebp+8)) # => eax +3776 # +3777 (lookup-var-helper %eax *(ebp+0xc)) # => eax +3778 # if (result == 0) abort +3779 3d/compare-eax-and 0/imm32 +3780 74/jump-if-= $lookup-var:abort/disp8 +3781 $lookup-var:end: +3782 # . epilogue +3783 89/<- %esp 5/r32/ebp +3784 5d/pop-to-ebp +3785 c3/return +3786 +3787 $lookup-var:abort: +3788 (write-buffered Stderr "unknown variable '") +3789 (write-slice-buffered Stderr *(ebp+8)) +3790 (write-buffered Stderr "'\n") +3791 (flush Stderr) +3792 # . syscall(exit, 1) +3793 bb/copy-to-ebx 1/imm32 +3794 b8/copy-to-eax 1/imm32/exit +3795 cd/syscall 0x80/imm8 +3796 # never gets here +3797 +3798 # return first 'name' from the top (back) of 'vars', and 0/null if not found +3799 lookup-var-helper: # name: (addr array byte), vars: (addr stack (handle var)) -> result/eax: (handle var) +3800 # pseudocode: +3801 # var curr: (addr handle var) = &vars->data[vars->top - 4] +3802 # var min = vars->data +3803 # while curr >= min +3804 # var v: (handle var) = *curr +3805 # if v->name == name +3806 # return v +3807 # return 0 +3808 # +3809 # . prologue +3810 55/push-ebp +3811 89/<- %ebp 4/r32/esp +3812 # . save registers +3813 52/push-edx +3814 53/push-ebx +3815 56/push-esi +3816 # esi = vars +3817 8b/-> *(ebp+0xc) 6/r32/esi +3818 # ebx = vars->top +3819 8b/-> *esi 3/r32/ebx +3820 # if (vars->top > vars->length) abort +3821 3b/compare 0/r32/eax *(esi+4) +3822 0f 8f/jump-if-> $lookup-var-helper:error1/disp32 +3823 # var min/edx: (addr handle var) = vars->data +3824 8d/copy-address *(esi+8) 2/r32/edx +3825 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 4] +3826 81 5/subop/subtract %ebx 4/imm32 +3827 8d/copy-address *(esi+ebx+8) 3/r32/ebx +3828 { +3829 # if (curr < min) return 0 +3830 39/compare %ebx 2/r32/edx +3831 b8/copy-to-eax 0/imm32 +3832 0f 82/jump-if-addr< break/disp32 +3833 # var v/eax: (handle var) = *curr +3834 8b/-> *ebx 0/r32/eax +3835 # if (v->name == name) return v +3836 (string-equal? *eax *(ebp+8)) # Var-name +3837 3d/compare-eax-and 0/imm32 +3838 8b/-> *ebx 0/r32/eax +3839 75/jump-if-!= break/disp8 +3840 # curr -= 4 +3841 81 5/subop/subtract %ebx 4/imm32 +3842 e9/jump loop/disp32 +3843 } +3844 $lookup-var-helper:end: +3845 # . restore registers +3846 5e/pop-to-esi +3847 5b/pop-to-ebx +3848 5a/pop-to-edx +3849 # . epilogue +3850 89/<- %esp 5/r32/ebp +3851 5d/pop-to-ebp +3852 c3/return +3853 +3854 $lookup-var-helper:error1: +3855 (write-buffered Stderr "malformed stack when looking up '") +3856 (write-slice-buffered Stderr *(ebp+8)) +3857 (write-buffered Stderr "'\n") +3858 (flush Stderr) +3859 # . syscall(exit, 1) +3860 bb/copy-to-ebx 1/imm32 +3861 b8/copy-to-eax 1/imm32/exit +3862 cd/syscall 0x80/imm8 +3863 # never gets here +3864 +3865 # return first 'name' from the top (back) of 'vars' and create a new var for a fn output if not found +3866 lookup-or-define-var: # name: (addr slice), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle var) +3867 # . prologue +3868 55/push-ebp +3869 89/<- %ebp 4/r32/esp +3870 # . save registers +3871 51/push-ecx +3872 # var target/ecx: (handle array byte) = slice-to-string(name) +3873 (slice-to-string Heap *(ebp+8)) # => eax +3874 89/<- %ecx 0/r32/eax +3875 # +3876 (lookup-var-helper %ecx *(ebp+0xc)) # => eax +3877 { +3878 # if (result != 0) return +3879 3d/compare-eax-and 0/imm32 +3880 75/jump-if-!= break/disp8 +3881 # if name is one of fn's outputs, return it +3882 { +3883 (find-in-function-outputs *(ebp+0x10) %ecx) # => eax +3884 3d/compare-eax-and 0/imm32 +3885 # otherwise abort +3886 0f 84/jump-if-!= $lookup-var:abort/disp32 +3887 } +3888 } +3889 $lookup-or-define-var:end: +3890 # . restore registers +3891 59/pop-to-ecx +3892 # . epilogue +3893 89/<- %esp 5/r32/ebp +3894 5d/pop-to-ebp +3895 c3/return +3896 +3897 find-in-function-outputs: # fn: (handle function), name: (handle array byte) => result/eax: (handle var) +3898 # . prologue +3899 55/push-ebp +3900 89/<- %ebp 4/r32/esp +3901 # . save registers +3902 51/push-ecx +3903 # var curr/ecx: (handle list var) = fn->outputs +3904 8b/-> *(ebp+8) 1/r32/ecx +3905 8b/-> *(ecx+0xc) 1/r32/ecx +3906 # while curr != null +3907 { +3908 81 7/subop/compare %ecx 0/imm32 +3909 74/jump-if-= break/disp8 +3910 # var v: (handle var) = *curr +3911 8b/-> *ecx 0/r32/eax # List-value +3912 # if (curr->name == name) return curr +3913 50/push-eax +3914 (string-equal? *eax *(ebp+0xc)) +3915 3d/compare-eax-and 0/imm32 +3916 58/pop-to-eax +3917 75/jump-if-!= $find-in-function-outputs:end/disp8 +3918 # curr = curr->next +3919 8b/-> *(ecx+4) 1/r32/ecx # List-next +3920 eb/jump loop/disp8 +3921 } +3922 b8/copy-to-eax 0/imm32 +3923 $find-in-function-outputs:end: +3924 # . restore registers +3925 59/pop-to-ecx +3926 # . epilogue +3927 89/<- %esp 5/r32/ebp +3928 5d/pop-to-ebp +3929 c3/return +3930 +3931 test-parse-mu-stmt: +3932 # . prologue +3933 55/push-ebp +3934 89/<- %ebp 4/r32/esp +3935 # setup +3936 (clear-stream _test-input-stream) +3937 (write _test-input-stream "increment n\n") +3938 # var vars/ecx: (stack (addr var) 4) +3939 81 5/subop/subtract %esp 0x10/imm32 +3940 68/push 0x10/imm32/length +3941 68/push 0/imm32/top +3942 89/<- %ecx 4/r32/esp +3943 (clear-stack %ecx) +3944 # var v/edx: var +3945 81 5/subop/subtract %esp 0x14/imm32 # Var-size +3946 89/<- %edx 4/r32/esp +3947 (zero-out %edx 0x14) # Var-size +3948 # v->name = "n" +3949 c7 0/subop/copy *edx "n"/imm32 # Var-name +3950 # +3951 (push %ecx %edx) +3952 # convert +3953 (parse-mu-stmt _test-input-stream %ecx) # => eax +3954 # check result +3955 (check-ints-equal *eax 1 "F - test-parse-mu-stmt/tag") # Stmt-tag is Stmt1 +3956 (check-strings-equal *(eax+4) "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation +3957 # edx: (handle list var) = result->inouts +3958 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts +3959 # ebx: (handle var) = result->inouts->value +3960 8b/-> *edx 3/r32/ebx # List-value +3961 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt/inout:0") # Var-name +3962 # . epilogue +3963 89/<- %esp 5/r32/ebp +3964 5d/pop-to-ebp +3965 c3/return 3966 -3967 # return first 'name' from the top (back) of 'vars' and create a new var for a fn output if not found -3968 lookup-or-define-var: # name: (addr slice), vars: (addr stack (handle var)), fn: (handle function) -> 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 target/ecx: (handle array byte) = slice-to-string(name) -3975 (slice-to-string Heap *(ebp+8)) # => eax -3976 89/<- %ecx 0/r32/eax -3977 # -3978 (lookup-var-helper %ecx *(ebp+0xc)) # => eax -3979 { -3980 # if (result != 0) return -3981 3d/compare-eax-and 0/imm32 -3982 75/jump-if-!= break/disp8 -3983 # if name is one of fn's outputs, return it -3984 { -3985 (find-in-function-outputs *(ebp+0x10) %ecx) # => eax -3986 3d/compare-eax-and 0/imm32 -3987 # otherwise abort -3988 0f 84/jump-if-!= $lookup-var:abort/disp32 -3989 } -3990 } -3991 $lookup-or-define-var:end: -3992 # . restore registers -3993 59/pop-to-ecx -3994 # . epilogue -3995 89/<- %esp 5/r32/ebp -3996 5d/pop-to-ebp -3997 c3/return -3998 -3999 find-in-function-outputs: # fn: (handle function), name: (handle array byte) => result/eax: (handle var) -4000 # . prologue -4001 55/push-ebp -4002 89/<- %ebp 4/r32/esp -4003 # . save registers -4004 51/push-ecx -4005 # var curr/ecx: (handle list var) = fn->outputs -4006 8b/-> *(ebp+8) 1/r32/ecx -4007 8b/-> *(ecx+0xc) 1/r32/ecx -4008 # while curr != null -4009 { -4010 81 7/subop/compare %ecx 0/imm32 -4011 74/jump-if-= break/disp8 -4012 # var v: (handle var) = *curr -4013 8b/-> *ecx 0/r32/eax # List-value -4014 # if (curr->name == name) return curr -4015 50/push-eax -4016 (string-equal? *eax *(ebp+0xc)) -4017 3d/compare-eax-and 0/imm32 -4018 58/pop-to-eax -4019 75/jump-if-!= $find-in-function-outputs:end/disp8 -4020 # curr = curr->next -4021 8b/-> *(ecx+4) 1/r32/ecx # List-next -4022 eb/jump loop/disp8 -4023 } -4024 b8/copy-to-eax 0/imm32 -4025 $find-in-function-outputs:end: -4026 # . restore registers -4027 59/pop-to-ecx -4028 # . epilogue -4029 89/<- %esp 5/r32/ebp -4030 5d/pop-to-ebp -4031 c3/return -4032 -4033 test-parse-mu-stmt: -4034 # . prologue -4035 55/push-ebp -4036 89/<- %ebp 4/r32/esp -4037 # setup -4038 (clear-stream _test-input-stream) -4039 (write _test-input-stream "increment n\n") -4040 # var vars/ecx: (stack (addr var) 4) -4041 81 5/subop/subtract %esp 0x10/imm32 -4042 68/push 0x10/imm32/length -4043 68/push 0/imm32/top -4044 89/<- %ecx 4/r32/esp -4045 (clear-stack %ecx) -4046 # var v/edx: var -4047 81 5/subop/subtract %esp 0x14/imm32 # Var-size -4048 89/<- %edx 4/r32/esp -4049 (zero-out %edx 0x14) # Var-size -4050 # v->name = "n" -4051 c7 0/subop/copy *edx "n"/imm32 # Var-name -4052 # -4053 (push %ecx %edx) -4054 # convert -4055 (parse-mu-stmt _test-input-stream %ecx) # => eax -4056 # check result -4057 (check-ints-equal *eax 1 "F - test-parse-mu-stmt/tag") # Stmt-tag is Stmt1 -4058 (check-strings-equal *(eax+4) "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation -4059 # edx: (handle list var) = result->inouts -4060 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts -4061 # ebx: (handle var) = result->inouts->value -4062 8b/-> *edx 3/r32/ebx # List-value -4063 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt/inout:0") # Var-name -4064 # . epilogue -4065 89/<- %esp 5/r32/ebp -4066 5d/pop-to-ebp -4067 c3/return -4068 -4069 test-parse-mu-stmt-with-comma: -4070 # . prologue -4071 55/push-ebp -4072 89/<- %ebp 4/r32/esp -4073 # setup -4074 (clear-stream _test-input-stream) -4075 (write _test-input-stream "copy-to n, 3\n") -4076 # var vars/ecx: (stack (addr var) 4) -4077 81 5/subop/subtract %esp 0x10/imm32 -4078 68/push 0x10/imm32/length -4079 68/push 0/imm32/top -4080 89/<- %ecx 4/r32/esp -4081 (clear-stack %ecx) -4082 # var v/edx: var -4083 81 5/subop/subtract %esp 0x14/imm32 # Var-size -4084 89/<- %edx 4/r32/esp -4085 (zero-out %edx 0x14) # Var-size -4086 # v->name = "n" -4087 c7 0/subop/copy *edx "n"/imm32 # Var-name -4088 # -4089 (push %ecx %edx) -4090 # convert -4091 (parse-mu-stmt _test-input-stream %ecx) # => eax -4092 # check result -4093 (check-ints-equal *eax 1 "F - test-parse-mu-stmt-with-comma/tag") # Stmt-tag is Stmt1 -4094 (check-strings-equal *(eax+4) "copy-to" "F - test-parse-mu-stmt-with-comma/name") # Stmt1-operation -4095 # edx: (handle list var) = result->inouts -4096 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts -4097 # ebx: (handle var) = result->inouts->value -4098 8b/-> *edx 3/r32/ebx # List-value -4099 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt-with-comma/inout:0") # Var-name -4100 # . epilogue -4101 89/<- %esp 5/r32/ebp -4102 5d/pop-to-ebp -4103 c3/return -4104 -4105 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) -4106 # . prologue -4107 55/push-ebp -4108 89/<- %ebp 4/r32/esp -4109 # . save registers -4110 51/push-ecx -4111 # -4112 (allocate *(ebp+8) *Function-size) # => eax -4113 8b/-> *(ebp+0xc) 1/r32/ecx -4114 89/<- *eax 1/r32/ecx # Function-name -4115 8b/-> *(ebp+0x10) 1/r32/ecx -4116 89/<- *(eax+4) 1/r32/ecx # Function-subx-name -4117 8b/-> *(ebp+0x14) 1/r32/ecx -4118 89/<- *(eax+8) 1/r32/ecx # Function-inouts -4119 8b/-> *(ebp+0x18) 1/r32/ecx -4120 89/<- *(eax+0xc) 1/r32/ecx # Function-outputs -4121 8b/-> *(ebp+0x1c) 1/r32/ecx -4122 89/<- *(eax+0x10) 1/r32/ecx # Function-body -4123 8b/-> *(ebp+0x20) 1/r32/ecx -4124 89/<- *(eax+0x14) 1/r32/ecx # Function-next -4125 $new-function:end: -4126 # . restore registers -4127 59/pop-to-ecx -4128 # . epilogue -4129 89/<- %esp 5/r32/ebp -4130 5d/pop-to-ebp -4131 c3/return -4132 -4133 new-var: # ad: (addr allocation-descriptor), name: (addr array byte), type: (addr tree type-id), block: int, stack-offset: int, register: (addr array byte) -> result/eax: (handle var) -4134 # . prologue -4135 55/push-ebp -4136 89/<- %ebp 4/r32/esp -4137 # . save registers -4138 51/push-ecx -4139 # -4140 (allocate *(ebp+8) *Var-size) # => eax -4141 8b/-> *(ebp+0xc) 1/r32/ecx -4142 89/<- *eax 1/r32/ecx # Var-name -4143 8b/-> *(ebp+0x10) 1/r32/ecx -4144 89/<- *(eax+4) 1/r32/ecx # Var-type -4145 8b/-> *(ebp+0x14) 1/r32/ecx -4146 89/<- *(eax+8) 1/r32/ecx # Var-block-depth -4147 8b/-> *(ebp+0x18) 1/r32/ecx -4148 89/<- *(eax+0xc) 1/r32/ecx # Var-stack-offset -4149 8b/-> *(ebp+0x1c) 1/r32/ecx -4150 89/<- *(eax+0x10) 1/r32/ecx # Var-register -4151 $new-var:end: -4152 # . restore registers -4153 59/pop-to-ecx -4154 # . epilogue -4155 89/<- %esp 5/r32/ebp -4156 5d/pop-to-ebp -4157 c3/return -4158 -4159 new-literal-integer: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -4160 # . prologue -4161 55/push-ebp -4162 89/<- %ebp 4/r32/esp -4163 # . save registers -4164 51/push-ecx -4165 # if (!is-hex-int?(name)) abort -4166 (is-hex-int? *(ebp+0xc)) # => eax -4167 3d/compare-eax-and 0/imm32 -4168 0f 84/jump-if-= $new-literal-integer:abort/disp32 -4169 # var s/ecx: (addr array byte) -4170 (slice-to-string Heap *(ebp+0xc)) # => eax -4171 89/<- %ecx 0/r32/eax -4172 # result/ecx = new var(s) -4173 (allocate *(ebp+8) *Var-size) # => eax -4174 (zero-out %eax *Var-size) -4175 89/<- *eax 1/r32/ecx # Var-name -4176 89/<- %ecx 0/r32/eax -4177 # result->type = new type() -4178 (allocate *(ebp+8) *Tree-size) # => eax -4179 (zero-out %eax *Tree-size) # default type is 'literal' -4180 89/<- *(ecx+4) 0/r32/eax # Var-type -4181 # move result to eax -4182 89/<- %eax 1/r32/ecx -4183 $new-literal-integer:end: -4184 # . restore registers -4185 59/pop-to-ecx -4186 # . epilogue -4187 89/<- %esp 5/r32/ebp -4188 5d/pop-to-ebp -4189 c3/return -4190 -4191 $new-literal-integer:abort: -4192 (write-buffered Stderr "variable cannot begin with a digit '") -4193 (write-slice-buffered Stderr *(ebp+0xc)) -4194 (write-buffered Stderr "'\n") -4195 (flush Stderr) -4196 # . syscall(exit, 1) -4197 bb/copy-to-ebx 1/imm32 -4198 b8/copy-to-eax 1/imm32/exit -4199 cd/syscall 0x80/imm8 -4200 # never gets here -4201 -4202 new-literal-string: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -4203 # . prologue -4204 55/push-ebp -4205 89/<- %ebp 4/r32/esp -4206 # . save registers -4207 51/push-ecx -4208 # var s/ecx: (addr array byte) -4209 (slice-to-string Heap *(ebp+0xc)) # => eax -4210 89/<- %ecx 0/r32/eax -4211 # result/ecx = new var(s) -4212 (allocate *(ebp+8) *Var-size) # => eax -4213 (zero-out %eax *Var-size) -4214 89/<- *eax 1/r32/ecx # Var-name -4215 89/<- %ecx 0/r32/eax -4216 # result->type = new type() -4217 (allocate *(ebp+8) *Tree-size) # => eax -4218 (zero-out %eax *Tree-size) # default type is 'literal' -4219 89/<- *(ecx+4) 0/r32/eax # Var-type -4220 # move result to eax -4221 89/<- %eax 1/r32/ecx -4222 $new-literal-string:end: -4223 # . restore registers -4224 59/pop-to-ecx -4225 # . epilogue -4226 89/<- %esp 5/r32/ebp -4227 5d/pop-to-ebp -4228 c3/return -4229 -4230 new-label: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -4231 # . prologue -4232 55/push-ebp -4233 89/<- %ebp 4/r32/esp -4234 # . save registers -4235 51/push-ecx -4236 # var s/ecx: (addr array byte) -4237 (slice-to-string Heap *(ebp+0xc)) # => eax -4238 89/<- %ecx 0/r32/eax -4239 # -4240 (allocate *(ebp+8) *Var-size) # => eax -4241 89/<- *eax 1/r32/ecx # Var-name -4242 89/<- %ecx 0/r32/eax -4243 (allocate *(ebp+8) *Tree-size) # => eax -4244 (zero-out %eax *Tree-size) # labels are literals -4245 89/<- *(ecx+4) 0/r32/eax # Var-type -4246 89/<- %eax 1/r32/ecx -4247 c7 0/subop/copy *(eax+8) 0/imm32 # Var-block-depth -4248 c7 0/subop/copy *(eax+0xc) 0/imm32 # Var-stack-offset -4249 c7 0/subop/copy *(eax+0x10) 0/imm32 # Var-register -4250 $new-label:end: -4251 # . restore registers -4252 59/pop-to-ecx -4253 # . epilogue -4254 89/<- %esp 5/r32/ebp -4255 5d/pop-to-ebp -4256 c3/return -4257 -4258 new-block: # ad: (addr allocation-descriptor), data: (handle list statement) -> result/eax: (handle statement) -4259 # . prologue -4260 55/push-ebp -4261 89/<- %ebp 4/r32/esp -4262 # . save registers -4263 51/push-ecx -4264 # -4265 (allocate *(ebp+8) *Stmt-size) # => eax -4266 (zero-out %eax *Stmt-size) -4267 c7 0/subop/copy *eax 0/imm32/tag/block # Stmt-tag -4268 8b/-> *(ebp+0xc) 1/r32/ecx -4269 89/<- *(eax+4) 1/r32/ecx # Block-statements -4270 $new-block:end: -4271 # . restore registers -4272 59/pop-to-ecx -4273 # . epilogue -4274 89/<- %esp 5/r32/ebp -4275 5d/pop-to-ebp -4276 c3/return -4277 -4278 new-vardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) -4279 # . prologue -4280 55/push-ebp -4281 89/<- %ebp 4/r32/esp -4282 # . save registers -4283 51/push-ecx -4284 # -4285 (allocate *(ebp+8) *Stmt-size) # => eax -4286 (zero-out %eax *Stmt-size) -4287 c7 0/subop/copy *eax 2/imm32/tag/var-on-stack # Stmt-tag -4288 # result->var = var -4289 8b/-> *(ebp+0xc) 1/r32/ecx -4290 89/<- *(eax+4) 1/r32/ecx # Vardef-var -4291 $new-vardef:end: +3967 test-parse-mu-stmt-with-comma: +3968 # . prologue +3969 55/push-ebp +3970 89/<- %ebp 4/r32/esp +3971 # setup +3972 (clear-stream _test-input-stream) +3973 (write _test-input-stream "copy-to n, 3\n") +3974 # var vars/ecx: (stack (addr var) 4) +3975 81 5/subop/subtract %esp 0x10/imm32 +3976 68/push 0x10/imm32/length +3977 68/push 0/imm32/top +3978 89/<- %ecx 4/r32/esp +3979 (clear-stack %ecx) +3980 # var v/edx: var +3981 81 5/subop/subtract %esp 0x14/imm32 # Var-size +3982 89/<- %edx 4/r32/esp +3983 (zero-out %edx 0x14) # Var-size +3984 # v->name = "n" +3985 c7 0/subop/copy *edx "n"/imm32 # Var-name +3986 # +3987 (push %ecx %edx) +3988 # convert +3989 (parse-mu-stmt _test-input-stream %ecx) # => eax +3990 # check result +3991 (check-ints-equal *eax 1 "F - test-parse-mu-stmt-with-comma/tag") # Stmt-tag is Stmt1 +3992 (check-strings-equal *(eax+4) "copy-to" "F - test-parse-mu-stmt-with-comma/name") # Stmt1-operation +3993 # edx: (handle list var) = result->inouts +3994 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts +3995 # ebx: (handle var) = result->inouts->value +3996 8b/-> *edx 3/r32/ebx # List-value +3997 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt-with-comma/inout:0") # Var-name +3998 # . epilogue +3999 89/<- %esp 5/r32/ebp +4000 5d/pop-to-ebp +4001 c3/return +4002 +4003 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) +4004 # . prologue +4005 55/push-ebp +4006 89/<- %ebp 4/r32/esp +4007 # . save registers +4008 51/push-ecx +4009 # +4010 (allocate *(ebp+8) *Function-size) # => eax +4011 8b/-> *(ebp+0xc) 1/r32/ecx +4012 89/<- *eax 1/r32/ecx # Function-name +4013 8b/-> *(ebp+0x10) 1/r32/ecx +4014 89/<- *(eax+4) 1/r32/ecx # Function-subx-name +4015 8b/-> *(ebp+0x14) 1/r32/ecx +4016 89/<- *(eax+8) 1/r32/ecx # Function-inouts +4017 8b/-> *(ebp+0x18) 1/r32/ecx +4018 89/<- *(eax+0xc) 1/r32/ecx # Function-outputs +4019 8b/-> *(ebp+0x1c) 1/r32/ecx +4020 89/<- *(eax+0x10) 1/r32/ecx # Function-body +4021 8b/-> *(ebp+0x20) 1/r32/ecx +4022 89/<- *(eax+0x14) 1/r32/ecx # Function-next +4023 $new-function:end: +4024 # . restore registers +4025 59/pop-to-ecx +4026 # . epilogue +4027 89/<- %esp 5/r32/ebp +4028 5d/pop-to-ebp +4029 c3/return +4030 +4031 new-var: # ad: (addr allocation-descriptor), name: (addr array byte), type: (addr tree type-id), block: int, stack-offset: int, register: (addr array byte) -> result/eax: (handle var) +4032 # . prologue +4033 55/push-ebp +4034 89/<- %ebp 4/r32/esp +4035 # . save registers +4036 51/push-ecx +4037 # +4038 (allocate *(ebp+8) *Var-size) # => eax +4039 8b/-> *(ebp+0xc) 1/r32/ecx +4040 89/<- *eax 1/r32/ecx # Var-name +4041 8b/-> *(ebp+0x10) 1/r32/ecx +4042 89/<- *(eax+4) 1/r32/ecx # Var-type +4043 8b/-> *(ebp+0x14) 1/r32/ecx +4044 89/<- *(eax+8) 1/r32/ecx # Var-block-depth +4045 8b/-> *(ebp+0x18) 1/r32/ecx +4046 89/<- *(eax+0xc) 1/r32/ecx # Var-stack-offset +4047 8b/-> *(ebp+0x1c) 1/r32/ecx +4048 89/<- *(eax+0x10) 1/r32/ecx # Var-register +4049 $new-var:end: +4050 # . restore registers +4051 59/pop-to-ecx +4052 # . epilogue +4053 89/<- %esp 5/r32/ebp +4054 5d/pop-to-ebp +4055 c3/return +4056 +4057 new-literal-integer: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) +4058 # . prologue +4059 55/push-ebp +4060 89/<- %ebp 4/r32/esp +4061 # . save registers +4062 51/push-ecx +4063 # if (!is-hex-int?(name)) abort +4064 (is-hex-int? *(ebp+0xc)) # => eax +4065 3d/compare-eax-and 0/imm32 +4066 0f 84/jump-if-= $new-literal-integer:abort/disp32 +4067 # var s/ecx: (addr array byte) +4068 (slice-to-string Heap *(ebp+0xc)) # => eax +4069 89/<- %ecx 0/r32/eax +4070 # result/ecx = new var(s) +4071 (allocate *(ebp+8) *Var-size) # => eax +4072 (zero-out %eax *Var-size) +4073 89/<- *eax 1/r32/ecx # Var-name +4074 89/<- %ecx 0/r32/eax +4075 # result->type = new type() +4076 (allocate *(ebp+8) *Tree-size) # => eax +4077 (zero-out %eax *Tree-size) # default type is 'literal' +4078 89/<- *(ecx+4) 0/r32/eax # Var-type +4079 # move result to eax +4080 89/<- %eax 1/r32/ecx +4081 $new-literal-integer:end: +4082 # . restore registers +4083 59/pop-to-ecx +4084 # . epilogue +4085 89/<- %esp 5/r32/ebp +4086 5d/pop-to-ebp +4087 c3/return +4088 +4089 $new-literal-integer:abort: +4090 (write-buffered Stderr "variable cannot begin with a digit '") +4091 (write-slice-buffered Stderr *(ebp+0xc)) +4092 (write-buffered Stderr "'\n") +4093 (flush Stderr) +4094 # . syscall(exit, 1) +4095 bb/copy-to-ebx 1/imm32 +4096 b8/copy-to-eax 1/imm32/exit +4097 cd/syscall 0x80/imm8 +4098 # never gets here +4099 +4100 new-literal-string: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) +4101 # . prologue +4102 55/push-ebp +4103 89/<- %ebp 4/r32/esp +4104 # . save registers +4105 51/push-ecx +4106 # var s/ecx: (addr array byte) +4107 (slice-to-string Heap *(ebp+0xc)) # => eax +4108 89/<- %ecx 0/r32/eax +4109 # result/ecx = new var(s) +4110 (allocate *(ebp+8) *Var-size) # => eax +4111 (zero-out %eax *Var-size) +4112 89/<- *eax 1/r32/ecx # Var-name +4113 89/<- %ecx 0/r32/eax +4114 # result->type = new type() +4115 (allocate *(ebp+8) *Tree-size) # => eax +4116 (zero-out %eax *Tree-size) # default type is 'literal' +4117 89/<- *(ecx+4) 0/r32/eax # Var-type +4118 # move result to eax +4119 89/<- %eax 1/r32/ecx +4120 $new-literal-string:end: +4121 # . restore registers +4122 59/pop-to-ecx +4123 # . epilogue +4124 89/<- %esp 5/r32/ebp +4125 5d/pop-to-ebp +4126 c3/return +4127 +4128 new-label: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) +4129 # . prologue +4130 55/push-ebp +4131 89/<- %ebp 4/r32/esp +4132 # . save registers +4133 51/push-ecx +4134 # var s/ecx: (addr array byte) +4135 (slice-to-string Heap *(ebp+0xc)) # => eax +4136 89/<- %ecx 0/r32/eax +4137 # +4138 (allocate *(ebp+8) *Var-size) # => eax +4139 89/<- *eax 1/r32/ecx # Var-name +4140 89/<- %ecx 0/r32/eax +4141 (allocate *(ebp+8) *Tree-size) # => eax +4142 (zero-out %eax *Tree-size) # labels are literals +4143 89/<- *(ecx+4) 0/r32/eax # Var-type +4144 89/<- %eax 1/r32/ecx +4145 c7 0/subop/copy *(eax+8) 0/imm32 # Var-block-depth +4146 c7 0/subop/copy *(eax+0xc) 0/imm32 # Var-stack-offset +4147 c7 0/subop/copy *(eax+0x10) 0/imm32 # Var-register +4148 $new-label:end: +4149 # . restore registers +4150 59/pop-to-ecx +4151 # . epilogue +4152 89/<- %esp 5/r32/ebp +4153 5d/pop-to-ebp +4154 c3/return +4155 +4156 new-block: # ad: (addr allocation-descriptor), data: (handle list statement) -> result/eax: (handle statement) +4157 # . prologue +4158 55/push-ebp +4159 89/<- %ebp 4/r32/esp +4160 # . save registers +4161 51/push-ecx +4162 # +4163 (allocate *(ebp+8) *Stmt-size) # => eax +4164 (zero-out %eax *Stmt-size) +4165 c7 0/subop/copy *eax 0/imm32/tag/block # Stmt-tag +4166 8b/-> *(ebp+0xc) 1/r32/ecx +4167 89/<- *(eax+4) 1/r32/ecx # Block-statements +4168 $new-block:end: +4169 # . restore registers +4170 59/pop-to-ecx +4171 # . epilogue +4172 89/<- %esp 5/r32/ebp +4173 5d/pop-to-ebp +4174 c3/return +4175 +4176 new-vardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) +4177 # . prologue +4178 55/push-ebp +4179 89/<- %ebp 4/r32/esp +4180 # . save registers +4181 51/push-ecx +4182 # +4183 (allocate *(ebp+8) *Stmt-size) # => eax +4184 (zero-out %eax *Stmt-size) +4185 c7 0/subop/copy *eax 2/imm32/tag/var-on-stack # Stmt-tag +4186 # result->var = var +4187 8b/-> *(ebp+0xc) 1/r32/ecx +4188 89/<- *(eax+4) 1/r32/ecx # Vardef-var +4189 $new-vardef:end: +4190 # . restore registers +4191 59/pop-to-ecx +4192 # . epilogue +4193 89/<- %esp 5/r32/ebp +4194 5d/pop-to-ebp +4195 c3/return +4196 +4197 new-regvardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) +4198 # . prologue +4199 55/push-ebp +4200 89/<- %ebp 4/r32/esp +4201 # . save registers +4202 51/push-ecx +4203 57/push-edi +4204 # ecx = var +4205 8b/-> *(ebp+0xc) 1/r32/ecx +4206 # edi = result +4207 (allocate *(ebp+8) *Stmt-size) # => eax +4208 89/<- %edi 0/r32/eax +4209 (zero-out %edi *Stmt-size) +4210 # set tag +4211 c7 0/subop/copy *edi 3/imm32/tag/var-in-register # Stmt-tag +4212 # set output +4213 (append-list Heap %ecx *(edi+0xc)) # Regvardef-outputs => eax +4214 89/<- *(edi+0xc) 0/r32/eax # Regvardef-outputs +4215 $new-regvardef:end: +4216 89/<- %eax 7/r32/edi +4217 # . restore registers +4218 5f/pop-to-edi +4219 59/pop-to-ecx +4220 # . epilogue +4221 89/<- %esp 5/r32/ebp +4222 5d/pop-to-ebp +4223 c3/return +4224 +4225 new-list: # ad: (addr allocation-descriptor), value: _type, next: (handle list _type) -> result/eax: (handle list _type) +4226 # . prologue +4227 55/push-ebp +4228 89/<- %ebp 4/r32/esp +4229 # . save registers +4230 51/push-ecx +4231 # +4232 (allocate *(ebp+8) *List-size) # => eax +4233 8b/-> *(ebp+0xc) 1/r32/ecx +4234 89/<- *eax 1/r32/ecx # List-value +4235 8b/-> *(ebp+0x10) 1/r32/ecx +4236 89/<- *(eax+4) 1/r32/ecx # List-next +4237 $new-list:end: +4238 # . restore registers +4239 59/pop-to-ecx +4240 # . epilogue +4241 89/<- %esp 5/r32/ebp +4242 5d/pop-to-ebp +4243 c3/return +4244 +4245 append-list: # ad: (addr allocation-descriptor), value: _type, list: (handle list _type) -> result/eax: (handle list _type) +4246 # . prologue +4247 55/push-ebp +4248 89/<- %ebp 4/r32/esp +4249 # . save registers +4250 51/push-ecx +4251 # +4252 (allocate *(ebp+8) *List-size) # => eax +4253 8b/-> *(ebp+0xc) 1/r32/ecx +4254 89/<- *eax 1/r32/ecx # List-value +4255 # if (list == null) return result +4256 81 7/subop/compare *(ebp+0x10) 0/imm32 +4257 74/jump-if-= $new-list:end/disp8 +4258 # otherwise append +4259 # var curr/ecx = list +4260 8b/-> *(ebp+0x10) 1/r32/ecx +4261 # while (curr->next != null) curr = curr->next +4262 { +4263 81 7/subop/compare *(ecx+4) 0/imm32 # List-next +4264 74/jump-if-= break/disp8 +4265 # curr = curr->next +4266 8b/-> *(ecx+4) 1/r32/ecx +4267 eb/jump loop/disp8 +4268 } +4269 # curr->next = result +4270 89/<- *(ecx+4) 0/r32/eax +4271 # return list +4272 8b/-> *(ebp+0x10) 0/r32/eax +4273 $append-list:end: +4274 # . restore registers +4275 59/pop-to-ecx +4276 # . epilogue +4277 89/<- %esp 5/r32/ebp +4278 5d/pop-to-ebp +4279 c3/return +4280 +4281 append-to-block: # ad: (addr allocation-descriptor), block: (handle block), x: (handle stmt) +4282 # . prologue +4283 55/push-ebp +4284 89/<- %ebp 4/r32/esp +4285 # . save registers +4286 56/push-esi +4287 # esi = block +4288 8b/-> *(ebp+0xc) 6/r32/esi +4289 (append-list *(ebp+8) *(ebp+0x10) *(esi+4)) # ad, x, Block-statements +4290 89/<- *(esi+4) 0/r32/eax # Block-statements +4291 $append-to-block:end: 4292 # . restore registers -4293 59/pop-to-ecx +4293 5e/pop-to-esi 4294 # . epilogue 4295 89/<- %esp 5/r32/ebp 4296 5d/pop-to-ebp 4297 c3/return 4298 -4299 new-regvardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) -4300 # . prologue -4301 55/push-ebp -4302 89/<- %ebp 4/r32/esp -4303 # . save registers -4304 51/push-ecx -4305 57/push-edi -4306 # ecx = var -4307 8b/-> *(ebp+0xc) 1/r32/ecx -4308 # edi = result -4309 (allocate *(ebp+8) *Stmt-size) # => eax -4310 89/<- %edi 0/r32/eax -4311 (zero-out %edi *Stmt-size) -4312 # set tag -4313 c7 0/subop/copy *edi 3/imm32/tag/var-in-register # Stmt-tag -4314 # set output -4315 (append-list Heap %ecx *(edi+0xc)) # Regvardef-outputs => eax -4316 89/<- *(edi+0xc) 0/r32/eax # Regvardef-outputs -4317 $new-regvardef:end: -4318 89/<- %eax 7/r32/edi -4319 # . restore registers -4320 5f/pop-to-edi -4321 59/pop-to-ecx -4322 # . epilogue -4323 89/<- %esp 5/r32/ebp -4324 5d/pop-to-ebp -4325 c3/return -4326 -4327 new-list: # ad: (addr allocation-descriptor), value: _type, next: (handle list _type) -> result/eax: (handle list _type) -4328 # . prologue -4329 55/push-ebp -4330 89/<- %ebp 4/r32/esp -4331 # . save registers -4332 51/push-ecx -4333 # -4334 (allocate *(ebp+8) *List-size) # => eax -4335 8b/-> *(ebp+0xc) 1/r32/ecx -4336 89/<- *eax 1/r32/ecx # List-value -4337 8b/-> *(ebp+0x10) 1/r32/ecx -4338 89/<- *(eax+4) 1/r32/ecx # List-next -4339 $new-list:end: -4340 # . restore registers -4341 59/pop-to-ecx -4342 # . epilogue -4343 89/<- %esp 5/r32/ebp -4344 5d/pop-to-ebp -4345 c3/return -4346 -4347 append-list: # ad: (addr allocation-descriptor), value: _type, list: (handle list _type) -> result/eax: (handle list _type) -4348 # . prologue -4349 55/push-ebp -4350 89/<- %ebp 4/r32/esp -4351 # . save registers -4352 51/push-ecx -4353 # -4354 (allocate *(ebp+8) *List-size) # => eax -4355 8b/-> *(ebp+0xc) 1/r32/ecx -4356 89/<- *eax 1/r32/ecx # List-value -4357 # if (list == null) return result -4358 81 7/subop/compare *(ebp+0x10) 0/imm32 -4359 74/jump-if-= $new-list:end/disp8 -4360 # otherwise append -4361 # var curr/ecx = list -4362 8b/-> *(ebp+0x10) 1/r32/ecx -4363 # while (curr->next != null) curr = curr->next -4364 { -4365 81 7/subop/compare *(ecx+4) 0/imm32 # List-next -4366 74/jump-if-= break/disp8 -4367 # curr = curr->next -4368 8b/-> *(ecx+4) 1/r32/ecx -4369 eb/jump loop/disp8 -4370 } -4371 # curr->next = result -4372 89/<- *(ecx+4) 0/r32/eax -4373 # return list -4374 8b/-> *(ebp+0x10) 0/r32/eax -4375 $append-list:end: -4376 # . restore registers -4377 59/pop-to-ecx -4378 # . epilogue -4379 89/<- %esp 5/r32/ebp -4380 5d/pop-to-ebp -4381 c3/return -4382 -4383 append-to-block: # ad: (addr allocation-descriptor), block: (handle block), x: (handle stmt) -4384 # . prologue -4385 55/push-ebp -4386 89/<- %ebp 4/r32/esp -4387 # . save registers -4388 56/push-esi -4389 # esi = block -4390 8b/-> *(ebp+0xc) 6/r32/esi -4391 (append-list *(ebp+8) *(ebp+0x10) *(esi+4)) # ad, x, Block-statements -4392 89/<- *(esi+4) 0/r32/eax # Block-statements -4393 $append-to-block:end: -4394 # . restore registers -4395 5e/pop-to-esi -4396 # . epilogue -4397 89/<- %esp 5/r32/ebp -4398 5d/pop-to-ebp -4399 c3/return -4400 -4401 ####################################################### -4402 # Type-checking -4403 ####################################################### -4404 -4405 check-mu-types: -4406 # . prologue -4407 55/push-ebp -4408 89/<- %ebp 4/r32/esp -4409 # -4410 $check-mu-types:end: -4411 # . epilogue -4412 89/<- %esp 5/r32/ebp -4413 5d/pop-to-ebp -4414 c3/return -4415 -4416 size-of: # v: (addr var) -> result/eax: int -4417 # . prologue -4418 55/push-ebp -4419 89/<- %ebp 4/r32/esp -4420 # if v is a literal, return 0 -4421 8b/-> *(ebp+8) 0/r32/eax -4422 8b/-> *(eax+4) 0/r32/eax # Var-type -4423 81 7/subop/compare *eax 0/imm32 # Tree-left -4424 b8/copy-to-eax 0/imm32 -4425 74/jump-if-= $size-of:end/disp8 -4426 # hard-coded since we only support 'int' types for now -4427 b8/copy-to-eax 4/imm32 -4428 $size-of:end: +4299 ####################################################### +4300 # Type-checking +4301 ####################################################### +4302 +4303 check-mu-types: +4304 # . prologue +4305 55/push-ebp +4306 89/<- %ebp 4/r32/esp +4307 # +4308 $check-mu-types:end: +4309 # . epilogue +4310 89/<- %esp 5/r32/ebp +4311 5d/pop-to-ebp +4312 c3/return +4313 +4314 size-of: # v: (addr var) -> result/eax: int +4315 # . prologue +4316 55/push-ebp +4317 89/<- %ebp 4/r32/esp +4318 # if v is a literal, return 0 +4319 8b/-> *(ebp+8) 0/r32/eax +4320 8b/-> *(eax+4) 0/r32/eax # Var-type +4321 81 7/subop/compare *eax 0/imm32 # Tree-left +4322 b8/copy-to-eax 0/imm32 +4323 74/jump-if-= $size-of:end/disp8 +4324 # hard-coded since we only support 'int' types for now +4325 b8/copy-to-eax 4/imm32 +4326 $size-of:end: +4327 # . epilogue +4328 89/<- %esp 5/r32/ebp +4329 5d/pop-to-ebp +4330 c3/return +4331 +4332 == data +4333 +4334 # not yet used, but it will be +4335 Type-size: # (stream int) +4336 0x18/imm32/write +4337 0/imm32/read +4338 0x100/imm32/length +4339 # data +4340 4/imm32 # literal +4341 4/imm32 # int +4342 4/imm32 # addr +4343 0/imm32 # array (logic elsewhere) +4344 8/imm32 # handle (fat pointer) +4345 4/imm32 # bool +4346 0/imm32 +4347 0/imm32 +4348 # 0x20 +4349 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4350 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4351 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4352 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4353 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4354 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4355 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4356 +4357 == code +4358 +4359 ####################################################### +4360 # Code-generation +4361 ####################################################### +4362 +4363 emit-subx: # out: (addr buffered-file) +4364 # . prologue +4365 55/push-ebp +4366 89/<- %ebp 4/r32/esp +4367 # . save registers +4368 50/push-eax +4369 51/push-ecx +4370 57/push-edi +4371 # edi = out +4372 8b/-> *(ebp+8) 7/r32/edi +4373 # var curr/ecx: (handle function) = *Program +4374 8b/-> *Program 1/r32/ecx +4375 { +4376 # if (curr == null) break +4377 81 7/subop/compare %ecx 0/imm32 +4378 0f 84/jump-if-= break/disp32 +4379 (emit-subx-function %edi %ecx) +4380 # curr = curr->next +4381 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next +4382 e9/jump loop/disp32 +4383 } +4384 $emit-subx:end: +4385 # . restore registers +4386 5f/pop-to-edi +4387 59/pop-to-ecx +4388 58/pop-to-eax +4389 # . epilogue +4390 89/<- %esp 5/r32/ebp +4391 5d/pop-to-ebp +4392 c3/return +4393 +4394 emit-subx-function: # out: (addr buffered-file), f: (handle function) +4395 # . prologue +4396 55/push-ebp +4397 89/<- %ebp 4/r32/esp +4398 # . save registers +4399 50/push-eax +4400 51/push-ecx +4401 52/push-edx +4402 57/push-edi +4403 # edi = out +4404 8b/-> *(ebp+8) 7/r32/edi +4405 # ecx = f +4406 8b/-> *(ebp+0xc) 1/r32/ecx +4407 # var vars/edx: (stack (addr var) 256) +4408 81 5/subop/subtract %esp 0x400/imm32 +4409 68/push 0x400/imm32/length +4410 68/push 0/imm32/top +4411 89/<- %edx 4/r32/esp +4412 # +4413 (write-buffered %edi *ecx) +4414 (write-buffered %edi ":\n") +4415 # Important: each block's depth during code-generation should be identical +4416 # to what it was during parsing. +4417 c7 0/subop/copy *Curr-block-depth 1/imm32 +4418 (emit-subx-prologue %edi) +4419 (emit-subx-block %edi *(ecx+0x10) %edx) # Function-body +4420 (emit-subx-epilogue %edi) +4421 $emit-subx-function:end: +4422 # . reclaim locals +4423 81 0/subop/add %esp 408/imm32 +4424 # . restore registers +4425 5f/pop-to-edi +4426 5a/pop-to-edx +4427 59/pop-to-ecx +4428 58/pop-to-eax 4429 # . epilogue 4430 89/<- %esp 5/r32/ebp 4431 5d/pop-to-ebp 4432 c3/return 4433 -4434 == data -4435 -4436 # not yet used, but it will be -4437 Type-size: # (stream int) -4438 0x18/imm32/write -4439 0/imm32/read -4440 0x100/imm32/length -4441 # data -4442 4/imm32 # literal -4443 4/imm32 # int -4444 4/imm32 # addr -4445 0/imm32 # array (logic elsewhere) -4446 8/imm32 # handle (fat pointer) -4447 4/imm32 # bool -4448 0/imm32 -4449 0/imm32 -4450 # 0x20 -4451 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4452 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4453 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4454 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4455 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4456 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4457 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4458 -4459 == code -4460 -4461 ####################################################### -4462 # Code-generation -4463 ####################################################### -4464 -4465 emit-subx: # out: (addr buffered-file) -4466 # . prologue -4467 55/push-ebp -4468 89/<- %ebp 4/r32/esp -4469 # . save registers -4470 50/push-eax -4471 51/push-ecx -4472 57/push-edi -4473 # edi = out -4474 8b/-> *(ebp+8) 7/r32/edi -4475 # var curr/ecx: (handle function) = *Program -4476 8b/-> *Program 1/r32/ecx -4477 { -4478 # if (curr == null) break -4479 81 7/subop/compare %ecx 0/imm32 -4480 0f 84/jump-if-= break/disp32 -4481 (emit-subx-function %edi %ecx) -4482 # curr = curr->next -4483 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next -4484 e9/jump loop/disp32 -4485 } -4486 $emit-subx:end: -4487 # . restore registers -4488 5f/pop-to-edi -4489 59/pop-to-ecx -4490 58/pop-to-eax -4491 # . epilogue -4492 89/<- %esp 5/r32/ebp -4493 5d/pop-to-ebp -4494 c3/return -4495 -4496 emit-subx-function: # out: (addr buffered-file), f: (handle function) -4497 # . prologue -4498 55/push-ebp -4499 89/<- %ebp 4/r32/esp -4500 # . save registers -4501 50/push-eax -4502 51/push-ecx -4503 52/push-edx -4504 57/push-edi -4505 # edi = out -4506 8b/-> *(ebp+8) 7/r32/edi -4507 # ecx = f -4508 8b/-> *(ebp+0xc) 1/r32/ecx -4509 # var vars/edx: (stack (addr var) 256) -4510 81 5/subop/subtract %esp 0x400/imm32 -4511 68/push 0x400/imm32/length -4512 68/push 0/imm32/top -4513 89/<- %edx 4/r32/esp -4514 # -4515 (write-buffered %edi *ecx) -4516 (write-buffered %edi ":\n") -4517 # Important: each block's depth during code-generation should be identical -4518 # to what it was during parsing. -4519 c7 0/subop/copy *Curr-block-depth 1/imm32 -4520 (emit-subx-prologue %edi) -4521 (emit-subx-block %edi *(ecx+0x10) %edx) # Function-body -4522 (emit-subx-epilogue %edi) -4523 $emit-subx-function:end: -4524 # . reclaim locals -4525 81 0/subop/add %esp 408/imm32 -4526 # . restore registers -4527 5f/pop-to-edi -4528 5a/pop-to-edx -4529 59/pop-to-ecx -4530 58/pop-to-eax -4531 # . epilogue -4532 89/<- %esp 5/r32/ebp -4533 5d/pop-to-ebp -4534 c3/return -4535 -4536 emit-subx-stmt-list: # out: (addr buffered-file), stmts: (handle list stmt), vars: (addr stack (handle var)) -4537 # . prologue -4538 55/push-ebp -4539 89/<- %ebp 4/r32/esp -4540 # . save registers -4541 50/push-eax -4542 51/push-ecx -4543 52/push-edx -4544 53/push-ebx -4545 56/push-esi -4546 # esi = stmts -4547 8b/-> *(ebp+0xc) 6/r32/esi -4548 # var var-seen?/edx: boolean <- copy false -4549 ba/copy-to-edx 0/imm32/false -4550 # -4551 { -4552 $emit-subx-stmt-list:loop: -4553 81 7/subop/compare %esi 0/imm32 -4554 0f 84/jump-if-= break/disp32 -4555 # var curr-stmt/ecx = stmts->value -4556 8b/-> *esi 1/r32/ecx # List-value -4557 { -4558 $emit-subx-stmt-list:check-for-block: -4559 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag -4560 75/jump-if-!= break/disp8 -4561 $emit-subx-stmt-list:block: -4562 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10)) -4563 } -4564 { -4565 $emit-subx-stmt-list:check-for-stmt: -4566 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag -4567 0f 85/jump-if-!= break/disp32 -4568 $emit-subx-stmt-list:stmt1: -4569 { -4570 (is-mu-branch? %ecx) # => eax -4571 3d/compare-eax-and 0/imm32 -4572 0f 84/jump-if-= break/disp32 -4573 $emit-subx-stmt-list:branch-stmt: -4574 # if !var-seen? break -4575 81 7/subop/compare %edx 0/imm32/false -4576 0f 84/jump-if-= break/disp32 -4577 $emit-subx-stmt-list:branch-stmt-and-var-seen: -4578 +-- 26 lines: # unconditional loops -------------------------------------------------------------------------------------------------------------------------- -4604 +-- 78 lines: # conditional branches ------------------------------------------------------------------------------------------------------------------------- -4682 } -4683 $emit-subx-stmt-list:1-to-1: -4684 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) -4685 } -4686 { -4687 $emit-subx-stmt-list:check-for-vardef: -4688 81 7/subop/compare *ecx 2/imm32/vardef # Stmt-tag -4689 75/jump-if-!= break/disp8 -4690 $emit-subx-stmt-list:vardef: -4691 (emit-subx-var-def *(ebp+8) %ecx) -4692 (push *(ebp+0x10) *(ecx+4)) # Vardef-var -4693 # var-seen? = true -4694 ba/copy-to-edx 1/imm32/true -4695 } -4696 { -4697 $emit-subx-stmt-list:check-for-regvardef: -4698 81 7/subop/compare *ecx 3/imm32/regvardef # Stmt-tag -4699 0f 85/jump-if-!= break/disp32 -4700 $emit-subx-stmt-list:regvardef: -4701 # TODO: ensure that there's exactly one output -4702 # var output/eax: (handle var) = curr-stmt->outputs->value -4703 8b/-> *(ecx+0xc) 0/r32/eax -4704 8b/-> *eax 0/r32/eax -4705 # ensure that output is in a register -4706 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -4707 0f 84/jump-if-= $emit-subx-stmt-list:abort-regvardef-without-register/disp32 -4708 # emit spill -4709 (emit-indent *(ebp+8) *Curr-block-depth) -4710 (write-buffered *(ebp+8) "ff 6/subop/push %") -4711 (write-buffered *(ebp+8) *(eax+0x10)) -4712 (write-buffered *(ebp+8) Newline) -4713 # register variable definition -4714 (push *(ebp+0x10) %eax) -4715 # emit the instruction as usual -4716 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) -4717 # var-seen? = true -4718 ba/copy-to-edx 1/imm32/true -4719 } -4720 $emit-subx-stmt-list:continue: -4721 # TODO: raise an error on unrecognized Stmt-tag -4722 8b/-> *(esi+4) 6/r32/esi # List-next -4723 e9/jump loop/disp32 -4724 } -4725 $emit-subx-stmt-list:cleanup: -4726 (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth) -4727 (clean-up-blocks *(ebp+0x10) *Curr-block-depth) -4728 $emit-subx-stmt-list:end: -4729 # . restore registers -4730 5e/pop-to-esi -4731 5b/pop-to-ebx -4732 5a/pop-to-edx -4733 59/pop-to-ecx -4734 58/pop-to-eax -4735 # . epilogue -4736 89/<- %esp 5/r32/ebp -4737 5d/pop-to-ebp -4738 c3/return -4739 -4740 $emit-subx-stmt-list:abort-regvardef-without-register: -4741 # error("var '" var->name "' initialized from an instruction must live in a register\n") -4742 (write-buffered Stderr "var '") -4743 (write-buffered Stderr *eax) # Var-name -4744 (write-buffered Stderr "' initialized from an instruction must live in a register\n") -4745 (flush Stderr) -4746 # . syscall(exit, 1) -4747 bb/copy-to-ebx 1/imm32 -4748 b8/copy-to-eax 1/imm32/exit -4749 cd/syscall 0x80/imm8 -4750 # never gets here -4751 -4752 is-mu-branch?: # stmt: (addr stmt1) -> result/eax: boolean -4753 # . prologue -4754 55/push-ebp -4755 89/<- %ebp 4/r32/esp -4756 # . save registers -4757 51/push-ecx -4758 # ecx = stmt -4759 8b/-> *(ebp+8) 1/r32/ecx -4760 # if (stmt->operation starts with "loop") return true -4761 (string-starts-with? *(ecx+4) "loop") # Stmt1-operation => eax -4762 3d/compare-eax-and 0/imm32 -4763 75/jump-if-not-equal $is-mu-branch?:end/disp8 -4764 # otherwise return (stmt->operation starts with "break") -4765 (string-starts-with? *(ecx+4) "break") # Stmt1-operation => eax -4766 $is-mu-branch?:end: -4767 # . restore registers -4768 59/pop-to-ecx -4769 # . epilogue -4770 89/<- %esp 5/r32/ebp -4771 5d/pop-to-ebp -4772 c3/return -4773 -4774 emit-reverse-break: # out: (addr buffered-file), stmt: (addr stmt1) -4775 # . prologue -4776 55/push-ebp -4777 89/<- %ebp 4/r32/esp -4778 # . save registers -4779 50/push-eax -4780 # eax = stmt -4781 8b/-> *(ebp+0xc) 0/r32/eax -4782 # -4783 (get Reverse-branch *(eax+4) 8 "reverse-branch: ") # Stmt1-operation => eax: (addr addr array byte) -4784 (emit-indent *(ebp+8) *Curr-block-depth) -4785 (write-buffered *(ebp+8) *eax) -4786 (write-buffered *(ebp+8) " break/disp32\n") -4787 $emit-reverse-break:end: -4788 # . restore registers +4434 emit-subx-stmt-list: # out: (addr buffered-file), stmts: (handle list stmt), vars: (addr stack (handle var)) +4435 # . prologue +4436 55/push-ebp +4437 89/<- %ebp 4/r32/esp +4438 # . save registers +4439 50/push-eax +4440 51/push-ecx +4441 52/push-edx +4442 53/push-ebx +4443 56/push-esi +4444 # esi = stmts +4445 8b/-> *(ebp+0xc) 6/r32/esi +4446 # var var-seen?/edx: boolean <- copy false +4447 ba/copy-to-edx 0/imm32/false +4448 # +4449 { +4450 $emit-subx-stmt-list:loop: +4451 81 7/subop/compare %esi 0/imm32 +4452 0f 84/jump-if-= break/disp32 +4453 # var curr-stmt/ecx = stmts->value +4454 8b/-> *esi 1/r32/ecx # List-value +4455 { +4456 $emit-subx-stmt-list:check-for-block: +4457 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag +4458 75/jump-if-!= break/disp8 +4459 $emit-subx-stmt-list:block: +4460 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10)) +4461 } +4462 { +4463 $emit-subx-stmt-list:check-for-stmt: +4464 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag +4465 0f 85/jump-if-!= break/disp32 +4466 $emit-subx-stmt-list:stmt1: +4467 { +4468 (is-mu-branch? %ecx) # => eax +4469 3d/compare-eax-and 0/imm32 +4470 0f 84/jump-if-= break/disp32 +4471 $emit-subx-stmt-list:branch-stmt: +4472 # if !var-seen? break +4473 81 7/subop/compare %edx 0/imm32/false +4474 0f 84/jump-if-= break/disp32 +4475 $emit-subx-stmt-list:branch-stmt-and-var-seen: +4476 +-- 26 lines: # unconditional loops ----------------------------------------------------------------------------------------------------------------------------------------------------- +4502 +-- 78 lines: # conditional branches ---------------------------------------------------------------------------------------------------------------------------------------------------- +4580 } +4581 $emit-subx-stmt-list:1-to-1: +4582 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) +4583 } +4584 { +4585 $emit-subx-stmt-list:check-for-vardef: +4586 81 7/subop/compare *ecx 2/imm32/vardef # Stmt-tag +4587 75/jump-if-!= break/disp8 +4588 $emit-subx-stmt-list:vardef: +4589 (emit-subx-var-def *(ebp+8) %ecx) +4590 (push *(ebp+0x10) *(ecx+4)) # Vardef-var +4591 # var-seen? = true +4592 ba/copy-to-edx 1/imm32/true +4593 } +4594 { +4595 $emit-subx-stmt-list:check-for-regvardef: +4596 81 7/subop/compare *ecx 3/imm32/regvardef # Stmt-tag +4597 0f 85/jump-if-!= break/disp32 +4598 $emit-subx-stmt-list:regvardef: +4599 # TODO: ensure that there's exactly one output +4600 # var output/eax: (handle var) = curr-stmt->outputs->value +4601 8b/-> *(ecx+0xc) 0/r32/eax +4602 8b/-> *eax 0/r32/eax +4603 # ensure that output is in a register +4604 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register +4605 0f 84/jump-if-= $emit-subx-stmt-list:abort-regvardef-without-register/disp32 +4606 # emit spill +4607 (emit-indent *(ebp+8) *Curr-block-depth) +4608 (write-buffered *(ebp+8) "ff 6/subop/push %") +4609 (write-buffered *(ebp+8) *(eax+0x10)) +4610 (write-buffered *(ebp+8) Newline) +4611 # register variable definition +4612 (push *(ebp+0x10) %eax) +4613 # emit the instruction as usual +4614 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) +4615 # var-seen? = true +4616 ba/copy-to-edx 1/imm32/true +4617 } +4618 $emit-subx-stmt-list:continue: +4619 # TODO: raise an error on unrecognized Stmt-tag +4620 8b/-> *(esi+4) 6/r32/esi # List-next +4621 e9/jump loop/disp32 +4622 } +4623 $emit-subx-stmt-list:cleanup: +4624 (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth) +4625 (clean-up-blocks *(ebp+0x10) *Curr-block-depth) +4626 $emit-subx-stmt-list:end: +4627 # . restore registers +4628 5e/pop-to-esi +4629 5b/pop-to-ebx +4630 5a/pop-to-edx +4631 59/pop-to-ecx +4632 58/pop-to-eax +4633 # . epilogue +4634 89/<- %esp 5/r32/ebp +4635 5d/pop-to-ebp +4636 c3/return +4637 +4638 $emit-subx-stmt-list:abort-regvardef-without-register: +4639 # error("var '" var->name "' initialized from an instruction must live in a register\n") +4640 (write-buffered Stderr "var '") +4641 (write-buffered Stderr *eax) # Var-name +4642 (write-buffered Stderr "' initialized from an instruction must live in a register\n") +4643 (flush Stderr) +4644 # . syscall(exit, 1) +4645 bb/copy-to-ebx 1/imm32 +4646 b8/copy-to-eax 1/imm32/exit +4647 cd/syscall 0x80/imm8 +4648 # never gets here +4649 +4650 is-mu-branch?: # stmt: (addr stmt1) -> result/eax: boolean +4651 # . prologue +4652 55/push-ebp +4653 89/<- %ebp 4/r32/esp +4654 # . save registers +4655 51/push-ecx +4656 # ecx = stmt +4657 8b/-> *(ebp+8) 1/r32/ecx +4658 # if (stmt->operation starts with "loop") return true +4659 (string-starts-with? *(ecx+4) "loop") # Stmt1-operation => eax +4660 3d/compare-eax-and 0/imm32 +4661 75/jump-if-not-equal $is-mu-branch?:end/disp8 +4662 # otherwise return (stmt->operation starts with "break") +4663 (string-starts-with? *(ecx+4) "break") # Stmt1-operation => eax +4664 $is-mu-branch?:end: +4665 # . restore registers +4666 59/pop-to-ecx +4667 # . epilogue +4668 89/<- %esp 5/r32/ebp +4669 5d/pop-to-ebp +4670 c3/return +4671 +4672 emit-reverse-break: # out: (addr buffered-file), stmt: (addr stmt1) +4673 # . prologue +4674 55/push-ebp +4675 89/<- %ebp 4/r32/esp +4676 # . save registers +4677 50/push-eax +4678 # eax = stmt +4679 8b/-> *(ebp+0xc) 0/r32/eax +4680 # +4681 (get Reverse-branch *(eax+4) 8 "reverse-branch: ") # Stmt1-operation => eax: (addr addr array byte) +4682 (emit-indent *(ebp+8) *Curr-block-depth) +4683 (write-buffered *(ebp+8) *eax) +4684 (write-buffered *(ebp+8) " break/disp32\n") +4685 $emit-reverse-break:end: +4686 # . restore registers +4687 58/pop-to-eax +4688 # . epilogue +4689 89/<- %esp 5/r32/ebp +4690 5d/pop-to-ebp +4691 c3/return +4692 +4693 == data +4694 +4695 Reverse-branch: # (table string string) +4696 # a table is a stream +4697 0xa0/imm32/write +4698 0/imm32/read +4699 0xa0/imm32/length +4700 # data +4701 "break-if-="/imm32 "0f 85/jump-if-!="/imm32 +4702 "loop-if-="/imm32 "0f 85/jump-if-!="/imm32 +4703 "break-if-!="/imm32 "0f 84/jump-if-="/imm32 +4704 "loop-if-!="/imm32 "0f 84/jump-if-="/imm32 +4705 "break-if-<"/imm32 "0f 8d/jump-if->="/imm32 +4706 "loop-if-<"/imm32 "0f 8d/jump-if->="/imm32 +4707 "break-if->"/imm32 "0f 8e/jump-if-<="/imm32 +4708 "loop-if->"/imm32 "0f 8e/jump-if-<="/imm32 +4709 "break-if-<="/imm32 "0f 87/jump-if->"/imm32 +4710 "loop-if-<="/imm32 "0f 87/jump-if->"/imm32 +4711 "break-if->="/imm32 "0f 8c/jump-if-<"/imm32 +4712 "loop-if->="/imm32 "0f 8c/jump-if-<"/imm32 +4713 "break-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 +4714 "loop-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 +4715 "break-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 +4716 "loop-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 +4717 "break-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 +4718 "loop-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 +4719 "break-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 +4720 "loop-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 +4721 +4722 == code +4723 +4724 emit-unconditional-jump-to-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), depth: int, label-suffix: (addr array byte) +4725 # . prologue +4726 55/push-ebp +4727 89/<- %ebp 4/r32/esp +4728 # . save registers +4729 50/push-eax +4730 51/push-ecx +4731 52/push-edx +4732 53/push-ebx +4733 # ecx = vars +4734 8b/-> *(ebp+0xc) 1/r32/ecx +4735 # var eax: int = vars->top +4736 8b/-> *ecx 0/r32/eax +4737 # var min/ecx: (address (handle var)) = vars->data +4738 81 0/subop/add %ecx 8/imm32 +4739 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] +4740 81 5/subop/subtract %eax 4/imm32 +4741 8d/copy-address *(ecx+eax) 0/r32/eax +4742 # edx = depth +4743 8b/-> *(ebp+0x10) 2/r32/edx +4744 { +4745 $emit-unconditional-jump-to-depth:loop: +4746 # if (curr < min) break +4747 39/compare %eax 1/r32/ecx +4748 0f 82/jump-if-addr< break/disp32 +4749 # var v/ebx: (handle var) = *curr +4750 8b/-> *eax 3/r32/ebx +4751 # if (v->block-depth < until-block-depth) break +4752 39/compare *(ebx+8) 2/r32/edx # Var-block-depth +4753 0f 8c/jump-if-< break/disp32 +4754 { +4755 $emit-unconditional-jump-to-depth:check: +4756 # if v->block-depth != until-block-depth, continue +4757 39/compare *(ebx+8) 2/r32/edx # Var-block-depth +4758 0f 85/jump-if-!= break/disp32 +4759 $emit-unconditional-jump-to-depth:depth-found: +4760 # if v is not a literal, continue +4761 # . var eax: int = size-of(v) +4762 50/push-eax +4763 (size-of %ebx) # => eax +4764 # . if (eax != 0) continue +4765 3d/compare-eax-and 0/imm32 +4766 58/pop-to-eax +4767 # +4768 0f 85/jump-if-!= break/disp32 +4769 $emit-unconditional-jump-to-depth:label-found: +4770 # emit unconditional jump, then return +4771 (emit-indent *(ebp+8) *Curr-block-depth) +4772 (write-buffered *(ebp+8) "e9/jump ") +4773 (write-buffered *(ebp+8) *ebx) # Var-name +4774 (write-buffered *(ebp+8) ":") +4775 (write-buffered *(ebp+8) *(ebp+0x14)) +4776 (write-buffered *(ebp+8) "/disp32\n") +4777 eb/jump $emit-unconditional-jump-to-depth:end/disp8 +4778 } +4779 # curr -= 4 +4780 2d/subtract-from-eax 4/imm32 +4781 e9/jump loop/disp32 +4782 } +4783 # TODO: error if no label at 'depth' was found +4784 $emit-unconditional-jump-to-depth:end: +4785 # . restore registers +4786 5b/pop-to-ebx +4787 5a/pop-to-edx +4788 59/pop-to-ecx 4789 58/pop-to-eax 4790 # . epilogue 4791 89/<- %esp 5/r32/ebp 4792 5d/pop-to-ebp 4793 c3/return 4794 -4795 == data -4796 -4797 Reverse-branch: # (table string string) -4798 # a table is a stream -4799 0xa0/imm32/write -4800 0/imm32/read -4801 0xa0/imm32/length -4802 # data -4803 "break-if-="/imm32 "0f 85/jump-if-!="/imm32 -4804 "loop-if-="/imm32 "0f 85/jump-if-!="/imm32 -4805 "break-if-!="/imm32 "0f 84/jump-if-="/imm32 -4806 "loop-if-!="/imm32 "0f 84/jump-if-="/imm32 -4807 "break-if-<"/imm32 "0f 8d/jump-if->="/imm32 -4808 "loop-if-<"/imm32 "0f 8d/jump-if->="/imm32 -4809 "break-if->"/imm32 "0f 8e/jump-if-<="/imm32 -4810 "loop-if->"/imm32 "0f 8e/jump-if-<="/imm32 -4811 "break-if-<="/imm32 "0f 87/jump-if->"/imm32 -4812 "loop-if-<="/imm32 "0f 87/jump-if->"/imm32 -4813 "break-if->="/imm32 "0f 8c/jump-if-<"/imm32 -4814 "loop-if->="/imm32 "0f 8c/jump-if-<"/imm32 -4815 "break-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 -4816 "loop-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 -4817 "break-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 -4818 "loop-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 -4819 "break-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 -4820 "loop-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 -4821 "break-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 -4822 "loop-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 -4823 -4824 == code -4825 -4826 emit-unconditional-jump-to-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), depth: int, label-suffix: (addr array byte) -4827 # . prologue -4828 55/push-ebp -4829 89/<- %ebp 4/r32/esp -4830 # . save registers -4831 50/push-eax -4832 51/push-ecx -4833 52/push-edx -4834 53/push-ebx -4835 # ecx = vars -4836 8b/-> *(ebp+0xc) 1/r32/ecx -4837 # var eax: int = vars->top -4838 8b/-> *ecx 0/r32/eax -4839 # var min/ecx: (address (handle var)) = vars->data -4840 81 0/subop/add %ecx 8/imm32 -4841 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] -4842 81 5/subop/subtract %eax 4/imm32 -4843 8d/copy-address *(ecx+eax) 0/r32/eax -4844 # edx = depth -4845 8b/-> *(ebp+0x10) 2/r32/edx -4846 { -4847 $emit-unconditional-jump-to-depth:loop: -4848 # if (curr < min) break -4849 39/compare %eax 1/r32/ecx -4850 0f 82/jump-if-addr< break/disp32 -4851 # var v/ebx: (handle var) = *curr -4852 8b/-> *eax 3/r32/ebx -4853 # if (v->block-depth < until-block-depth) break -4854 39/compare *(ebx+8) 2/r32/edx # Var-block-depth -4855 0f 8c/jump-if-< break/disp32 -4856 { -4857 $emit-unconditional-jump-to-depth:check: -4858 # if v->block-depth != until-block-depth, continue -4859 39/compare *(ebx+8) 2/r32/edx # Var-block-depth -4860 0f 85/jump-if-!= break/disp32 -4861 $emit-unconditional-jump-to-depth:depth-found: -4862 # if v is not a literal, continue -4863 # . var eax: int = size-of(v) -4864 50/push-eax -4865 (size-of %ebx) # => eax -4866 # . if (eax != 0) continue -4867 3d/compare-eax-and 0/imm32 -4868 58/pop-to-eax -4869 # -4870 0f 85/jump-if-!= break/disp32 -4871 $emit-unconditional-jump-to-depth:label-found: -4872 # emit unconditional jump, then return -4873 (emit-indent *(ebp+8) *Curr-block-depth) -4874 (write-buffered *(ebp+8) "e9/jump ") -4875 (write-buffered *(ebp+8) *ebx) # Var-name -4876 (write-buffered *(ebp+8) ":") -4877 (write-buffered *(ebp+8) *(ebp+0x14)) -4878 (write-buffered *(ebp+8) "/disp32\n") -4879 eb/jump $emit-unconditional-jump-to-depth:end/disp8 -4880 } -4881 # curr -= 4 -4882 2d/subtract-from-eax 4/imm32 -4883 e9/jump loop/disp32 -4884 } -4885 # TODO: error if no label at 'depth' was found -4886 $emit-unconditional-jump-to-depth:end: -4887 # . restore registers -4888 5b/pop-to-ebx -4889 5a/pop-to-edx -4890 59/pop-to-ecx -4891 58/pop-to-eax -4892 # . epilogue -4893 89/<- %esp 5/r32/ebp -4894 5d/pop-to-ebp -4895 c3/return -4896 -4897 # emit clean-up code for 'vars' until some block depth -4898 # doesn't actually modify 'vars' so we need traverse manually inside the stack -4899 emit-cleanup-code-until-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-depth: int -4900 # . prologue -4901 55/push-ebp -4902 89/<- %ebp 4/r32/esp -4903 # . save registers -4904 50/push-eax -4905 51/push-ecx -4906 52/push-edx -4907 53/push-ebx -4908 # ecx = vars -4909 8b/-> *(ebp+0xc) 1/r32/ecx -4910 # var eax: int = vars->top -4911 8b/-> *ecx 0/r32/eax -4912 # var min/ecx: (address (handle var)) = vars->data -4913 81 0/subop/add %ecx 8/imm32 -4914 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] -4915 81 5/subop/subtract %eax 4/imm32 -4916 8d/copy-address *(ecx+eax) 0/r32/eax -4917 # edx = until-block-depth -4918 8b/-> *(ebp+0x10) 2/r32/edx -4919 { -4920 $emit-cleanup-code-until-depth:loop: -4921 # if (curr < min) break -4922 39/compare %eax 1/r32/ecx -4923 0f 82/jump-if-addr< break/disp32 -4924 # var v/ebx: (handle var) = *curr -4925 8b/-> *eax 3/r32/ebx -4926 # if (v->block-depth < until-block-depth) break -4927 39/compare *(ebx+8) 2/r32/edx # Var-block-depth -4928 0f 8c/jump-if-< break/disp32 -4929 # if v is in a register -4930 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -4931 { -4932 74/jump-if-= break/disp8 -4933 $emit-cleanup-code-until-depth:reclaim-var-in-register: -4934 (emit-indent *(ebp+8) *Curr-block-depth) -4935 (write-buffered *(ebp+8) "8f 0/subop/pop %") -4936 (write-buffered *(ebp+8) *(ebx+0x10)) -4937 (write-buffered *(ebp+8) Newline) -4938 } -4939 # otherwise v is on the stack -4940 { -4941 75/jump-if-!= break/disp8 -4942 $emit-cleanup-code-until-depth:reclaim-var-on-stack: -4943 50/push-eax -4944 (size-of %ebx) # => eax -4945 # don't emit code for labels -4946 3d/compare-eax-and 0/imm32 -4947 74/jump-if-= break/disp8 -4948 # -4949 (emit-indent *(ebp+8) *Curr-block-depth) -4950 (write-buffered *(ebp+8) "81 0/subop/add %esp ") -4951 (print-int32-buffered *(ebp+8) %eax) -4952 (write-buffered *(ebp+8) "/imm32\n") -4953 58/pop-to-eax -4954 } -4955 # curr -= 4 -4956 2d/subtract-from-eax 4/imm32 -4957 e9/jump loop/disp32 -4958 } -4959 $emit-cleanup-code-until-depth:end: -4960 # . restore registers -4961 5b/pop-to-ebx -4962 5a/pop-to-edx -4963 59/pop-to-ecx -4964 58/pop-to-eax -4965 # . epilogue -4966 89/<- %esp 5/r32/ebp -4967 5d/pop-to-ebp -4968 c3/return -4969 -4970 # emit clean-up code for 'vars' until a given label is encountered -4971 # doesn't actually modify 'vars' so we need traverse manually inside the stack -4972 emit-cleanup-code-until-target: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-label: (addr array byte) -4973 # . prologue -4974 55/push-ebp -4975 89/<- %ebp 4/r32/esp -4976 # . save registers -4977 50/push-eax -4978 51/push-ecx -4979 52/push-edx -4980 53/push-ebx -4981 # ecx = vars -4982 8b/-> *(ebp+0xc) 1/r32/ecx -4983 # var eax: int = vars->top -4984 8b/-> *ecx 0/r32/eax -4985 # var min/ecx: (address (handle var)) = vars->data -4986 81 0/subop/add %ecx 8/imm32 -4987 # var curr/edx: (address (handle var)) = &vars->data[vars->top - 4] -4988 81 5/subop/subtract %eax 4/imm32 -4989 8d/copy-address *(ecx+eax) 2/r32/edx -4990 { -4991 $emit-cleanup-code-until-target:loop: -4992 # if (curr < min) break -4993 39/compare %edx 1/r32/ecx -4994 0f 82/jump-if-addr< break/disp32 -4995 # var v/ebx: (handle var) = *curr -4996 8b/-> *edx 3/r32/ebx -4997 # if (v->name == until-block-label) break -4998 (string-equal? *ebx *(ebp+0x10)) # => eax -4999 3d/compare-eax-and 0/imm32 -5000 0f 85/jump-if-!= break/disp32 -5001 # if v is in a register -5002 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -5003 { -5004 74/jump-if-= break/disp8 -5005 $emit-cleanup-code-until-target:reclaim-var-in-register: -5006 (emit-indent *(ebp+8) *Curr-block-depth) -5007 (write-buffered *(ebp+8) "8f 0/subop/pop %") -5008 (write-buffered *(ebp+8) *(ebx+0x10)) -5009 (write-buffered *(ebp+8) Newline) -5010 } -5011 # otherwise v is on the stack -5012 { -5013 75/jump-if-!= break/disp8 -5014 $emit-cleanup-code-until-target:reclaim-var-on-stack: -5015 (size-of %ebx) # => eax -5016 # don't emit code for labels -5017 3d/compare-eax-and 0/imm32 -5018 74/jump-if-= break/disp8 -5019 # -5020 (emit-indent *(ebp+8) *Curr-block-depth) -5021 (write-buffered *(ebp+8) "81 0/subop/add %esp ") -5022 (print-int32-buffered *(ebp+8) %eax) -5023 (write-buffered *(ebp+8) "/imm32\n") -5024 } -5025 # curr -= 4 -5026 81 5/subop/subtract %edx 4/imm32 -5027 e9/jump loop/disp32 -5028 } -5029 $emit-cleanup-code-until-target:end: -5030 # . restore registers -5031 5b/pop-to-ebx -5032 5a/pop-to-edx -5033 59/pop-to-ecx -5034 58/pop-to-eax -5035 # . epilogue -5036 89/<- %esp 5/r32/ebp -5037 5d/pop-to-ebp -5038 c3/return -5039 -5040 # clean up global state for 'vars' until some block depth -5041 clean-up-blocks: # vars: (addr stack (handle var)), until-block-depth: int -5042 # . prologue -5043 55/push-ebp -5044 89/<- %ebp 4/r32/esp -5045 # . save registers -5046 50/push-eax -5047 51/push-ecx -5048 56/push-esi -5049 # esi = vars -5050 8b/-> *(ebp+8) 6/r32/esi -5051 # ecx = until-block-depth -5052 8b/-> *(ebp+0xc) 1/r32/ecx -5053 { -5054 $clean-up-blocks:reclaim-loop: -5055 # if (vars->top <= 0) break -5056 81 7/subop/compare *esi 0/imm32 # Stack-top -5057 7e/jump-if-<= break/disp8 -5058 # var v/eax : (handle var) = top(vars) -5059 (top %esi) # => eax -5060 # if (v->block-depth < until-block-depth) break -5061 39/compare *(eax+8) 1/r32/ecx # Var-block-depth -5062 7c/jump-if-< break/disp8 -5063 # if v is on the stack, update Next-local-stack-offset -5064 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -5065 { -5066 75/jump-if-!= break/disp8 -5067 $clean-up-blocks:reclaim-var-on-stack: -5068 (size-of %eax) # => eax -5069 01/add *Next-local-stack-offset 0/r32/eax -5070 } -5071 (pop %esi) -5072 e9/jump loop/disp32 -5073 } -5074 $clean-up-blocks:end: -5075 # . restore registers -5076 5e/pop-to-esi -5077 59/pop-to-ecx -5078 58/pop-to-eax -5079 # . epilogue -5080 89/<- %esp 5/r32/ebp -5081 5d/pop-to-ebp -5082 c3/return -5083 -5084 emit-subx-var-def: # out: (addr buffered-file), stmt: (handle statement) -5085 # . prologue -5086 55/push-ebp -5087 89/<- %ebp 4/r32/esp -5088 # . save registers -5089 50/push-eax -5090 51/push-ecx -5091 # eax = stmt -5092 8b/-> *(ebp+0xc) 0/r32/eax -5093 # var n/eax: int = size-of(stmt->var) -5094 (size-of *(eax+4)) # Vardef-var => eax -5095 # while n > 0 -5096 { -5097 3d/compare-eax-with 0/imm32 -5098 7e/jump-if-<= break/disp8 -5099 (emit-indent *(ebp+8) *Curr-block-depth) -5100 (write-buffered *(ebp+8) "68/push 0/imm32\n") -5101 # n -= 4 -5102 2d/subtract-from-eax 4/imm32 -5103 # -5104 eb/jump loop/disp8 -5105 } -5106 $emit-subx-var-def:end: -5107 # . restore registers -5108 59/pop-to-ecx -5109 58/pop-to-eax -5110 # . epilogue -5111 89/<- %esp 5/r32/ebp -5112 5d/pop-to-ebp -5113 c3/return -5114 -5115 emit-subx-statement: # out: (addr buffered-file), stmt: (handle statement), primitives: (handle primitive), functions: (handle function) -5116 # . prologue -5117 55/push-ebp -5118 89/<- %ebp 4/r32/esp -5119 # . save registers -5120 50/push-eax -5121 51/push-ecx -5122 # if stmt matches a primitive, emit it -5123 { -5124 $emit-subx-statement:check-for-primitive: -5125 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => curr/eax -5126 3d/compare-eax-and 0/imm32 -5127 74/jump-if-= break/disp8 -5128 $emit-subx-statement:primitive: -5129 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr -5130 e9/jump $emit-subx-statement:end/disp32 -5131 } -5132 # else if stmt matches a function, emit a call to it -5133 { -5134 $emit-subx-statement:check-for-call: -5135 (find-matching-function *(ebp+0x14) *(ebp+0xc)) # functions, stmt => curr/eax -5136 3d/compare-eax-and 0/imm32 -5137 74/jump-if-= break/disp8 -5138 $emit-subx-statement:call: -5139 (emit-subx-call *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr -5140 e9/jump $emit-subx-statement:end/disp32 -5141 } -5142 # else abort -5143 e9/jump $emit-subx-statement:abort/disp32 -5144 $emit-subx-statement:end: -5145 # . restore registers -5146 59/pop-to-ecx -5147 58/pop-to-eax -5148 # . epilogue -5149 89/<- %esp 5/r32/ebp -5150 5d/pop-to-ebp -5151 c3/return -5152 -5153 $emit-subx-statement:abort: -5154 # error("couldn't translate '" stmt "'\n") -5155 (write-buffered Stderr "couldn't translate an instruction with operation '") -5156 8b/-> *(ebp+0xc) 0/r32/eax -5157 (write-buffered Stderr *(eax+4)) # Stmt1-operation -5158 (write-buffered Stderr "'\n") -5159 (flush Stderr) -5160 # . syscall(exit, 1) -5161 bb/copy-to-ebx 1/imm32 -5162 b8/copy-to-eax 1/imm32/exit -5163 cd/syscall 0x80/imm8 -5164 # never gets here -5165 -5166 emit-subx-block: # out: (addr buffered-file), block: (handle block), vars: (addr stack (handle var)) -5167 # . prologue -5168 55/push-ebp -5169 89/<- %ebp 4/r32/esp -5170 # . save registers -5171 50/push-eax -5172 51/push-ecx -5173 56/push-esi -5174 # esi = block -5175 8b/-> *(ebp+0xc) 6/r32/esi -5176 # var stmts/eax: (handle list statement) = block->statements -5177 8b/-> *(esi+4) 0/r32/eax # Block-statements -5178 # -5179 { -5180 $emit-subx-block:check-empty: -5181 81 7/subop/compare %eax 0/imm32 -5182 0f 84/jump-if-= break/disp32 -5183 (emit-indent *(ebp+8) *Curr-block-depth) -5184 (write-buffered *(ebp+8) "{\n") -5185 # var v/ecx: (addr array byte) = block->var->name -5186 8b/-> *(esi+8) 1/r32/ecx # Block-var -5187 (write-buffered *(ebp+8) *ecx) # Var-name -5188 (write-buffered *(ebp+8) ":loop:\n") -5189 ff 0/subop/increment *Curr-block-depth -5190 (push *(ebp+0x10) %ecx) -5191 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10)) -5192 (pop *(ebp+0x10)) # => eax -5193 ff 1/subop/decrement *Curr-block-depth -5194 (emit-indent *(ebp+8) *Curr-block-depth) -5195 (write-buffered *(ebp+8) "}\n") -5196 (write-buffered *(ebp+8) *ecx) # Var-name -5197 (write-buffered *(ebp+8) ":break:\n") -5198 } -5199 $emit-subx-block:end: -5200 # . restore registers -5201 5e/pop-to-esi -5202 59/pop-to-ecx -5203 58/pop-to-eax -5204 # . epilogue -5205 89/<- %esp 5/r32/ebp -5206 5d/pop-to-ebp -5207 c3/return -5208 -5209 # Primitives supported -5210 # For each operation, put variants with hard-coded registers before flexible ones. -5211 == data -5212 Primitives: -5213 # - increment/decrement -5214 _Primitive-inc-eax: -5215 # var/eax <- increment => 40/increment-eax -5216 "increment"/imm32/name -5217 0/imm32/no-inouts -5218 Single-int-var-in-eax/imm32/outputs -5219 "40/increment-eax"/imm32/subx-name -5220 0/imm32/no-rm32 -5221 0/imm32/no-r32 -5222 0/imm32/no-imm32 -5223 0/imm32/no-disp32 -5224 0/imm32/output-is-write-only -5225 _Primitive-inc-ecx/imm32/next -5226 _Primitive-inc-ecx: -5227 # var/ecx <- increment => 41/increment-ecx -5228 "increment"/imm32/name -5229 0/imm32/no-inouts -5230 Single-int-var-in-ecx/imm32/outputs -5231 "41/increment-ecx"/imm32/subx-name -5232 0/imm32/no-rm32 -5233 0/imm32/no-r32 -5234 0/imm32/no-imm32 -5235 0/imm32/no-disp32 -5236 0/imm32/output-is-write-only -5237 _Primitive-inc-edx/imm32/next -5238 _Primitive-inc-edx: -5239 # var/edx <- increment => 42/increment-edx -5240 "increment"/imm32/name -5241 0/imm32/no-inouts -5242 Single-int-var-in-edx/imm32/outputs -5243 "42/increment-edx"/imm32/subx-name -5244 0/imm32/no-rm32 -5245 0/imm32/no-r32 -5246 0/imm32/no-imm32 -5247 0/imm32/no-disp32 -5248 0/imm32/output-is-write-only -5249 _Primitive-inc-ebx/imm32/next -5250 _Primitive-inc-ebx: -5251 # var/ebx <- increment => 43/increment-ebx -5252 "increment"/imm32/name -5253 0/imm32/no-inouts -5254 Single-int-var-in-ebx/imm32/outputs -5255 "43/increment-ebx"/imm32/subx-name -5256 0/imm32/no-rm32 -5257 0/imm32/no-r32 -5258 0/imm32/no-imm32 -5259 0/imm32/no-disp32 -5260 0/imm32/output-is-write-only -5261 _Primitive-inc-esi/imm32/next -5262 _Primitive-inc-esi: -5263 # var/esi <- increment => 46/increment-esi -5264 "increment"/imm32/name -5265 0/imm32/no-inouts -5266 Single-int-var-in-esi/imm32/outputs -5267 "46/increment-esi"/imm32/subx-name -5268 0/imm32/no-rm32 -5269 0/imm32/no-r32 -5270 0/imm32/no-imm32 -5271 0/imm32/no-disp32 -5272 0/imm32/output-is-write-only -5273 _Primitive-inc-edi/imm32/next -5274 _Primitive-inc-edi: -5275 # var/edi <- increment => 47/increment-edi -5276 "increment"/imm32/name -5277 0/imm32/no-inouts -5278 Single-int-var-in-edi/imm32/outputs -5279 "47/increment-edi"/imm32/subx-name -5280 0/imm32/no-rm32 -5281 0/imm32/no-r32 -5282 0/imm32/no-imm32 -5283 0/imm32/no-disp32 -5284 0/imm32/output-is-write-only -5285 _Primitive-dec-eax/imm32/next -5286 _Primitive-dec-eax: -5287 # var/eax <- decrement => 48/decrement-eax -5288 "decrement"/imm32/name -5289 0/imm32/no-inouts -5290 Single-int-var-in-eax/imm32/outputs -5291 "48/decrement-eax"/imm32/subx-name -5292 0/imm32/no-rm32 -5293 0/imm32/no-r32 -5294 0/imm32/no-imm32 -5295 0/imm32/no-disp32 -5296 0/imm32/output-is-write-only -5297 _Primitive-dec-ecx/imm32/next -5298 _Primitive-dec-ecx: -5299 # var/ecx <- decrement => 49/decrement-ecx -5300 "decrement"/imm32/name -5301 0/imm32/no-inouts -5302 Single-int-var-in-ecx/imm32/outputs -5303 "49/decrement-ecx"/imm32/subx-name -5304 0/imm32/no-rm32 -5305 0/imm32/no-r32 -5306 0/imm32/no-imm32 -5307 0/imm32/no-disp32 -5308 0/imm32/output-is-write-only -5309 _Primitive-dec-edx/imm32/next -5310 _Primitive-dec-edx: -5311 # var/edx <- decrement => 4a/decrement-edx -5312 "decrement"/imm32/name -5313 0/imm32/no-inouts -5314 Single-int-var-in-edx/imm32/outputs -5315 "4a/decrement-edx"/imm32/subx-name -5316 0/imm32/no-rm32 -5317 0/imm32/no-r32 -5318 0/imm32/no-imm32 -5319 0/imm32/no-disp32 -5320 0/imm32/output-is-write-only -5321 _Primitive-dec-ebx/imm32/next -5322 _Primitive-dec-ebx: -5323 # var/ebx <- decrement => 4b/decrement-ebx -5324 "decrement"/imm32/name -5325 0/imm32/no-inouts -5326 Single-int-var-in-ebx/imm32/outputs -5327 "4b/decrement-ebx"/imm32/subx-name -5328 0/imm32/no-rm32 -5329 0/imm32/no-r32 -5330 0/imm32/no-imm32 -5331 0/imm32/no-disp32 -5332 0/imm32/output-is-write-only -5333 _Primitive-dec-esi/imm32/next -5334 _Primitive-dec-esi: -5335 # var/esi <- decrement => 4e/decrement-esi -5336 "decrement"/imm32/name -5337 0/imm32/no-inouts -5338 Single-int-var-in-esi/imm32/outputs -5339 "4e/decrement-esi"/imm32/subx-name -5340 0/imm32/no-rm32 -5341 0/imm32/no-r32 -5342 0/imm32/no-imm32 -5343 0/imm32/no-disp32 -5344 0/imm32/output-is-write-only -5345 _Primitive-dec-edi/imm32/next -5346 _Primitive-dec-edi: -5347 # var/edi <- decrement => 4f/decrement-edi -5348 "decrement"/imm32/name -5349 0/imm32/no-inouts -5350 Single-int-var-in-edi/imm32/outputs -5351 "4f/decrement-edi"/imm32/subx-name -5352 0/imm32/no-rm32 -5353 0/imm32/no-r32 -5354 0/imm32/no-imm32 -5355 0/imm32/no-disp32 -5356 0/imm32/output-is-write-only -5357 _Primitive-inc-mem/imm32/next -5358 _Primitive-inc-mem: -5359 # increment var => ff 0/subop/increment *(ebp+__) -5360 "increment"/imm32/name -5361 Single-int-var-on-stack/imm32/inouts -5362 0/imm32/no-outputs -5363 "ff 0/subop/increment"/imm32/subx-name -5364 1/imm32/rm32-is-first-inout -5365 0/imm32/no-r32 -5366 0/imm32/no-imm32 -5367 0/imm32/no-disp32 -5368 0/imm32/output-is-write-only -5369 _Primitive-inc-reg/imm32/next -5370 _Primitive-inc-reg: -5371 # var/reg <- increment => ff 0/subop/increment %__ -5372 "increment"/imm32/name -5373 0/imm32/no-inouts -5374 Single-int-var-in-some-register/imm32/outputs -5375 "ff 0/subop/increment"/imm32/subx-name -5376 3/imm32/rm32-is-first-output -5377 0/imm32/no-r32 -5378 0/imm32/no-imm32 -5379 0/imm32/no-disp32 -5380 0/imm32/output-is-write-only -5381 _Primitive-dec-mem/imm32/next -5382 _Primitive-dec-mem: -5383 # decrement var => ff 1/subop/decrement *(ebp+__) -5384 "decrement"/imm32/name -5385 Single-int-var-on-stack/imm32/inouts -5386 0/imm32/no-outputs -5387 "ff 1/subop/decrement"/imm32/subx-name -5388 1/imm32/rm32-is-first-inout -5389 0/imm32/no-r32 -5390 0/imm32/no-imm32 -5391 0/imm32/no-disp32 -5392 0/imm32/output-is-write-only -5393 _Primitive-dec-reg/imm32/next -5394 _Primitive-dec-reg: -5395 # var/reg <- decrement => ff 1/subop/decrement %__ -5396 "decrement"/imm32/name -5397 0/imm32/no-inouts -5398 Single-int-var-in-some-register/imm32/outputs -5399 "ff 1/subop/decrement"/imm32/subx-name -5400 3/imm32/rm32-is-first-output -5401 0/imm32/no-r32 -5402 0/imm32/no-imm32 -5403 0/imm32/no-disp32 -5404 0/imm32/output-is-write-only -5405 _Primitive-add-to-eax/imm32/next -5406 # - add -5407 _Primitive-add-to-eax: -5408 # var/eax <- add lit => 05/add-to-eax lit/imm32 -5409 "add"/imm32/name -5410 Single-lit-var/imm32/inouts -5411 Single-int-var-in-eax/imm32/outputs -5412 "05/add-to-eax"/imm32/subx-name -5413 0/imm32/no-rm32 -5414 0/imm32/no-r32 -5415 1/imm32/imm32-is-first-inout -5416 0/imm32/no-disp32 -5417 0/imm32/output-is-write-only -5418 _Primitive-add-reg-to-reg/imm32/next -5419 _Primitive-add-reg-to-reg: -5420 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 -5421 "add"/imm32/name -5422 Single-int-var-in-some-register/imm32/inouts -5423 Single-int-var-in-some-register/imm32/outputs -5424 "01/add-to"/imm32/subx-name -5425 3/imm32/rm32-is-first-output -5426 1/imm32/r32-is-first-inout -5427 0/imm32/no-imm32 -5428 0/imm32/no-disp32 -5429 0/imm32/output-is-write-only -5430 _Primitive-add-reg-to-mem/imm32/next -5431 _Primitive-add-reg-to-mem: -5432 # add-to var1 var2/reg => 01/add-to var1 var2/r32 -5433 "add-to"/imm32/name -5434 Two-args-int-stack-int-reg/imm32/inouts -5435 0/imm32/outputs -5436 "01/add-to"/imm32/subx-name -5437 1/imm32/rm32-is-first-inout -5438 2/imm32/r32-is-second-inout -5439 0/imm32/no-imm32 -5440 0/imm32/no-disp32 -5441 0/imm32/output-is-write-only -5442 _Primitive-add-mem-to-reg/imm32/next -5443 _Primitive-add-mem-to-reg: -5444 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 -5445 "add"/imm32/name -5446 Single-int-var-on-stack/imm32/inouts -5447 Single-int-var-in-some-register/imm32/outputs -5448 "03/add"/imm32/subx-name -5449 1/imm32/rm32-is-first-inout -5450 3/imm32/r32-is-first-output -5451 0/imm32/no-imm32 -5452 0/imm32/no-disp32 -5453 0/imm32/output-is-write-only -5454 _Primitive-add-lit-to-reg/imm32/next -5455 _Primitive-add-lit-to-reg: -5456 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 -5457 "add"/imm32/name -5458 Single-lit-var/imm32/inouts -5459 Single-int-var-in-some-register/imm32/outputs -5460 "81 0/subop/add"/imm32/subx-name -5461 3/imm32/rm32-is-first-output -5462 0/imm32/no-r32 -5463 1/imm32/imm32-is-first-inout -5464 0/imm32/no-disp32 -5465 0/imm32/output-is-write-only -5466 _Primitive-add-lit-to-mem/imm32/next -5467 _Primitive-add-lit-to-mem: -5468 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 -5469 "add-to"/imm32/name -5470 Int-var-and-literal/imm32/inouts -5471 0/imm32/outputs -5472 "81 0/subop/add"/imm32/subx-name -5473 1/imm32/rm32-is-first-inout -5474 0/imm32/no-r32 -5475 2/imm32/imm32-is-second-inout -5476 0/imm32/no-disp32 -5477 0/imm32/output-is-write-only -5478 _Primitive-subtract-from-eax/imm32/next -5479 # - subtract -5480 _Primitive-subtract-from-eax: -5481 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 -5482 "subtract"/imm32/name -5483 Single-lit-var/imm32/inouts -5484 Single-int-var-in-eax/imm32/outputs -5485 "2d/subtract-from-eax"/imm32/subx-name -5486 0/imm32/no-rm32 -5487 0/imm32/no-r32 -5488 1/imm32/imm32-is-first-inout -5489 0/imm32/no-disp32 -5490 0/imm32/output-is-write-only -5491 _Primitive-subtract-reg-from-reg/imm32/next -5492 _Primitive-subtract-reg-from-reg: -5493 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 -5494 "subtract"/imm32/name -5495 Single-int-var-in-some-register/imm32/inouts -5496 Single-int-var-in-some-register/imm32/outputs -5497 "29/subtract-from"/imm32/subx-name -5498 3/imm32/rm32-is-first-output -5499 1/imm32/r32-is-first-inout -5500 0/imm32/no-imm32 -5501 0/imm32/no-disp32 -5502 0/imm32/output-is-write-only -5503 _Primitive-subtract-reg-from-mem/imm32/next -5504 _Primitive-subtract-reg-from-mem: -5505 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 -5506 "subtract-from"/imm32/name -5507 Two-args-int-stack-int-reg/imm32/inouts -5508 0/imm32/outputs -5509 "29/subtract-from"/imm32/subx-name -5510 1/imm32/rm32-is-first-inout -5511 2/imm32/r32-is-second-inout -5512 0/imm32/no-imm32 -5513 0/imm32/no-disp32 -5514 0/imm32/output-is-write-only -5515 _Primitive-subtract-mem-from-reg/imm32/next -5516 _Primitive-subtract-mem-from-reg: -5517 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 -5518 "subtract"/imm32/name -5519 Single-int-var-on-stack/imm32/inouts -5520 Single-int-var-in-some-register/imm32/outputs -5521 "2b/subtract"/imm32/subx-name -5522 1/imm32/rm32-is-first-inout -5523 3/imm32/r32-is-first-output -5524 0/imm32/no-imm32 -5525 0/imm32/no-disp32 -5526 0/imm32/output-is-write-only -5527 _Primitive-subtract-lit-from-reg/imm32/next -5528 _Primitive-subtract-lit-from-reg: -5529 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 -5530 "subtract"/imm32/name -5531 Single-lit-var/imm32/inouts -5532 Single-int-var-in-some-register/imm32/outputs -5533 "81 5/subop/subtract"/imm32/subx-name -5534 3/imm32/rm32-is-first-output -5535 0/imm32/no-r32 -5536 1/imm32/imm32-is-first-inout -5537 0/imm32/no-disp32 -5538 0/imm32/output-is-write-only -5539 _Primitive-subtract-lit-from-mem/imm32/next -5540 _Primitive-subtract-lit-from-mem: -5541 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 -5542 "subtract-from"/imm32/name -5543 Int-var-and-literal/imm32/inouts -5544 0/imm32/outputs -5545 "81 5/subop/subtract"/imm32/subx-name -5546 1/imm32/rm32-is-first-inout -5547 0/imm32/no-r32 -5548 2/imm32/imm32-is-first-inout -5549 0/imm32/no-disp32 -5550 0/imm32/output-is-write-only -5551 _Primitive-and-with-eax/imm32/next -5552 # - and -5553 _Primitive-and-with-eax: -5554 # var/eax <- and lit => 25/and-with-eax lit/imm32 -5555 "and"/imm32/name -5556 Single-lit-var/imm32/inouts -5557 Single-int-var-in-eax/imm32/outputs -5558 "25/and-with-eax"/imm32/subx-name -5559 0/imm32/no-rm32 -5560 0/imm32/no-r32 -5561 1/imm32/imm32-is-first-inout -5562 0/imm32/no-disp32 -5563 0/imm32/output-is-write-only -5564 _Primitive-and-reg-with-reg/imm32/next -5565 _Primitive-and-reg-with-reg: -5566 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 -5567 "and"/imm32/name -5568 Single-int-var-in-some-register/imm32/inouts -5569 Single-int-var-in-some-register/imm32/outputs -5570 "21/and-with"/imm32/subx-name -5571 3/imm32/rm32-is-first-output -5572 1/imm32/r32-is-first-inout -5573 0/imm32/no-imm32 -5574 0/imm32/no-disp32 -5575 0/imm32/output-is-write-only -5576 _Primitive-and-reg-with-mem/imm32/next -5577 _Primitive-and-reg-with-mem: -5578 # and-with var1 var2/reg => 21/and-with var1 var2/r32 -5579 "and-with"/imm32/name -5580 Two-args-int-stack-int-reg/imm32/inouts -5581 0/imm32/outputs -5582 "21/and-with"/imm32/subx-name -5583 1/imm32/rm32-is-first-inout -5584 2/imm32/r32-is-second-inout -5585 0/imm32/no-imm32 -5586 0/imm32/no-disp32 -5587 0/imm32/output-is-write-only -5588 _Primitive-and-mem-with-reg/imm32/next -5589 _Primitive-and-mem-with-reg: -5590 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 -5591 "and"/imm32/name -5592 Single-int-var-on-stack/imm32/inouts -5593 Single-int-var-in-some-register/imm32/outputs -5594 "23/and"/imm32/subx-name -5595 1/imm32/rm32-is-first-inout -5596 3/imm32/r32-is-first-output -5597 0/imm32/no-imm32 -5598 0/imm32/no-disp32 -5599 0/imm32/output-is-write-only -5600 _Primitive-and-lit-with-reg/imm32/next -5601 _Primitive-and-lit-with-reg: -5602 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 -5603 "and"/imm32/name -5604 Single-lit-var/imm32/inouts -5605 Single-int-var-in-some-register/imm32/outputs -5606 "81 4/subop/and"/imm32/subx-name -5607 3/imm32/rm32-is-first-output -5608 0/imm32/no-r32 -5609 1/imm32/imm32-is-first-inout -5610 0/imm32/no-disp32 -5611 0/imm32/output-is-write-only -5612 _Primitive-and-lit-with-mem/imm32/next -5613 _Primitive-and-lit-with-mem: -5614 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 -5615 "and-with"/imm32/name -5616 Int-var-and-literal/imm32/inouts -5617 0/imm32/outputs -5618 "81 4/subop/and"/imm32/subx-name -5619 1/imm32/rm32-is-first-inout -5620 0/imm32/no-r32 -5621 2/imm32/imm32-is-first-inout -5622 0/imm32/no-disp32 -5623 0/imm32/output-is-write-only -5624 _Primitive-or-with-eax/imm32/next -5625 # - or -5626 _Primitive-or-with-eax: -5627 # var/eax <- or lit => 0d/or-with-eax lit/imm32 -5628 "or"/imm32/name -5629 Single-lit-var/imm32/inouts -5630 Single-int-var-in-eax/imm32/outputs -5631 "0d/or-with-eax"/imm32/subx-name -5632 0/imm32/no-rm32 -5633 0/imm32/no-r32 -5634 1/imm32/imm32-is-first-inout -5635 0/imm32/no-disp32 -5636 0/imm32/output-is-write-only -5637 _Primitive-or-reg-with-reg/imm32/next -5638 _Primitive-or-reg-with-reg: -5639 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 -5640 "or"/imm32/name -5641 Single-int-var-in-some-register/imm32/inouts -5642 Single-int-var-in-some-register/imm32/outputs -5643 "09/or-with"/imm32/subx-name -5644 3/imm32/rm32-is-first-output -5645 1/imm32/r32-is-first-inout -5646 0/imm32/no-imm32 -5647 0/imm32/no-disp32 -5648 0/imm32/output-is-write-only -5649 _Primitive-or-reg-with-mem/imm32/next -5650 _Primitive-or-reg-with-mem: -5651 # or-with var1 var2/reg => 09/or-with var1 var2/r32 -5652 "or-with"/imm32/name -5653 Two-args-int-stack-int-reg/imm32/inouts -5654 0/imm32/outputs -5655 "09/or-with"/imm32/subx-name -5656 1/imm32/rm32-is-first-inout -5657 2/imm32/r32-is-second-inout -5658 0/imm32/no-imm32 -5659 0/imm32/no-disp32 -5660 0/imm32/output-is-write-only -5661 _Primitive-or-mem-with-reg/imm32/next -5662 _Primitive-or-mem-with-reg: -5663 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 -5664 "or"/imm32/name -5665 Single-int-var-on-stack/imm32/inouts -5666 Single-int-var-in-some-register/imm32/outputs -5667 "0b/or"/imm32/subx-name -5668 1/imm32/rm32-is-first-inout -5669 3/imm32/r32-is-first-output -5670 0/imm32/no-imm32 -5671 0/imm32/no-disp32 -5672 0/imm32/output-is-write-only -5673 _Primitive-or-lit-with-reg/imm32/next -5674 _Primitive-or-lit-with-reg: -5675 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 -5676 "or"/imm32/name -5677 Single-lit-var/imm32/inouts -5678 Single-int-var-in-some-register/imm32/outputs -5679 "81 1/subop/or"/imm32/subx-name -5680 3/imm32/rm32-is-first-output -5681 0/imm32/no-r32 -5682 1/imm32/imm32-is-first-inout -5683 0/imm32/no-disp32 -5684 0/imm32/output-is-write-only -5685 _Primitive-or-lit-with-mem/imm32/next -5686 _Primitive-or-lit-with-mem: -5687 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 -5688 "or-with"/imm32/name -5689 Int-var-and-literal/imm32/inouts -5690 0/imm32/outputs -5691 "81 1/subop/or"/imm32/subx-name -5692 1/imm32/rm32-is-first-inout -5693 0/imm32/no-r32 -5694 2/imm32/imm32-is-second-inout -5695 0/imm32/no-disp32 -5696 0/imm32/output-is-write-only -5697 _Primitive-xor-with-eax/imm32/next -5698 # - xor -5699 _Primitive-xor-with-eax: -5700 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 -5701 "xor"/imm32/name -5702 Single-lit-var/imm32/inouts -5703 Single-int-var-in-eax/imm32/outputs -5704 "35/xor-with-eax"/imm32/subx-name -5705 0/imm32/no-rm32 -5706 0/imm32/no-r32 -5707 1/imm32/imm32-is-first-inout -5708 0/imm32/no-disp32 -5709 0/imm32/output-is-write-only -5710 _Primitive-xor-reg-with-reg/imm32/next -5711 _Primitive-xor-reg-with-reg: -5712 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 -5713 "xor"/imm32/name -5714 Single-int-var-in-some-register/imm32/inouts -5715 Single-int-var-in-some-register/imm32/outputs -5716 "31/xor-with"/imm32/subx-name -5717 3/imm32/rm32-is-first-output -5718 1/imm32/r32-is-first-inout -5719 0/imm32/no-imm32 -5720 0/imm32/no-disp32 -5721 0/imm32/output-is-write-only -5722 _Primitive-xor-reg-with-mem/imm32/next -5723 _Primitive-xor-reg-with-mem: -5724 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 -5725 "xor-with"/imm32/name -5726 Two-args-int-stack-int-reg/imm32/inouts -5727 0/imm32/outputs -5728 "31/xor-with"/imm32/subx-name -5729 1/imm32/rm32-is-first-inout -5730 2/imm32/r32-is-second-inout -5731 0/imm32/no-imm32 -5732 0/imm32/no-disp32 -5733 0/imm32/output-is-write-only -5734 _Primitive-xor-mem-with-reg/imm32/next -5735 _Primitive-xor-mem-with-reg: -5736 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 -5737 "xor"/imm32/name -5738 Single-int-var-on-stack/imm32/inouts -5739 Single-int-var-in-some-register/imm32/outputs -5740 "33/xor"/imm32/subx-name -5741 1/imm32/rm32-is-first-inout -5742 3/imm32/r32-is-first-output -5743 0/imm32/no-imm32 -5744 0/imm32/no-disp32 -5745 0/imm32/output-is-write-only -5746 _Primitive-xor-lit-with-reg/imm32/next -5747 _Primitive-xor-lit-with-reg: -5748 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 -5749 "xor"/imm32/name -5750 Single-lit-var/imm32/inouts -5751 Single-int-var-in-some-register/imm32/outputs -5752 "81 6/subop/xor"/imm32/subx-name -5753 3/imm32/rm32-is-first-output -5754 0/imm32/no-r32 -5755 1/imm32/imm32-is-first-inout -5756 0/imm32/no-disp32 -5757 0/imm32/output-is-write-only -5758 _Primitive-xor-lit-with-mem/imm32/next -5759 _Primitive-xor-lit-with-mem: -5760 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 -5761 "xor-with"/imm32/name -5762 Int-var-and-literal/imm32/inouts -5763 0/imm32/outputs -5764 "81 6/subop/xor"/imm32/subx-name -5765 1/imm32/rm32-is-first-inout -5766 0/imm32/no-r32 -5767 2/imm32/imm32-is-first-inout -5768 0/imm32/no-disp32 -5769 0/imm32/output-is-write-only -5770 _Primitive-copy-to-eax/imm32/next -5771 # - copy -5772 _Primitive-copy-to-eax: -5773 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 -5774 "copy"/imm32/name -5775 Single-lit-var/imm32/inouts -5776 Single-int-var-in-eax/imm32/outputs -5777 "b8/copy-to-eax"/imm32/subx-name -5778 0/imm32/no-rm32 -5779 0/imm32/no-r32 -5780 1/imm32/imm32-is-first-inout -5781 0/imm32/no-disp32 -5782 1/imm32/output-is-write-only -5783 _Primitive-copy-to-ecx/imm32/next -5784 _Primitive-copy-to-ecx: -5785 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 -5786 "copy"/imm32/name -5787 Single-lit-var/imm32/inouts -5788 Single-int-var-in-ecx/imm32/outputs -5789 "b9/copy-to-ecx"/imm32/subx-name -5790 0/imm32/no-rm32 -5791 0/imm32/no-r32 -5792 1/imm32/imm32-is-first-inout -5793 0/imm32/no-disp32 -5794 1/imm32/output-is-write-only -5795 _Primitive-copy-to-edx/imm32/next -5796 _Primitive-copy-to-edx: -5797 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 -5798 "copy"/imm32/name -5799 Single-lit-var/imm32/inouts -5800 Single-int-var-in-edx/imm32/outputs -5801 "ba/copy-to-edx"/imm32/subx-name -5802 0/imm32/no-rm32 -5803 0/imm32/no-r32 -5804 1/imm32/imm32-is-first-inout -5805 0/imm32/no-disp32 -5806 1/imm32/output-is-write-only -5807 _Primitive-copy-to-ebx/imm32/next -5808 _Primitive-copy-to-ebx: -5809 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 -5810 "copy"/imm32/name -5811 Single-lit-var/imm32/inouts -5812 Single-int-var-in-ebx/imm32/outputs -5813 "bb/copy-to-ebx"/imm32/subx-name -5814 0/imm32/no-rm32 -5815 0/imm32/no-r32 -5816 1/imm32/imm32-is-first-inout -5817 0/imm32/no-disp32 -5818 1/imm32/output-is-write-only -5819 _Primitive-copy-to-esi/imm32/next -5820 _Primitive-copy-to-esi: -5821 # var/esi <- copy lit => be/copy-to-esi lit/imm32 -5822 "copy"/imm32/name -5823 Single-lit-var/imm32/inouts -5824 Single-int-var-in-esi/imm32/outputs -5825 "be/copy-to-esi"/imm32/subx-name -5826 0/imm32/no-rm32 -5827 0/imm32/no-r32 -5828 1/imm32/imm32-is-first-inout -5829 0/imm32/no-disp32 -5830 1/imm32/output-is-write-only -5831 _Primitive-copy-to-edi/imm32/next -5832 _Primitive-copy-to-edi: -5833 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 -5834 "copy"/imm32/name -5835 Single-lit-var/imm32/inouts -5836 Single-int-var-in-edi/imm32/outputs -5837 "bf/copy-to-edi"/imm32/subx-name -5838 0/imm32/no-rm32 -5839 0/imm32/no-r32 -5840 1/imm32/imm32-is-first-inout -5841 0/imm32/no-disp32 -5842 1/imm32/output-is-write-only -5843 _Primitive-copy-reg-to-reg/imm32/next -5844 _Primitive-copy-reg-to-reg: -5845 # var1/reg <- copy var2/reg => 89/copy-to var1/rm32 var2/r32 -5846 "copy"/imm32/name -5847 Single-int-var-in-some-register/imm32/inouts -5848 Single-int-var-in-some-register/imm32/outputs -5849 "89/copy-to"/imm32/subx-name -5850 3/imm32/rm32-is-first-output -5851 1/imm32/r32-is-first-inout -5852 0/imm32/no-imm32 -5853 0/imm32/no-disp32 -5854 1/imm32/output-is-write-only -5855 _Primitive-copy-reg-to-mem/imm32/next -5856 _Primitive-copy-reg-to-mem: -5857 # copy-to var1 var2/reg => 89/copy-to var1 var2/r32 -5858 "copy-to"/imm32/name -5859 Two-args-int-stack-int-reg/imm32/inouts -5860 0/imm32/outputs -5861 "89/copy-to"/imm32/subx-name -5862 1/imm32/rm32-is-first-inout -5863 2/imm32/r32-is-second-inout -5864 0/imm32/no-imm32 -5865 0/imm32/no-disp32 -5866 1/imm32/output-is-write-only -5867 _Primitive-copy-mem-to-reg/imm32/next -5868 _Primitive-copy-mem-to-reg: -5869 # var1/reg <- copy var2 => 8b/copy-from var2/rm32 var1/r32 -5870 "copy"/imm32/name -5871 Single-int-var-on-stack/imm32/inouts -5872 Single-int-var-in-some-register/imm32/outputs -5873 "8b/copy-from"/imm32/subx-name -5874 1/imm32/rm32-is-first-inout -5875 3/imm32/r32-is-first-output -5876 0/imm32/no-imm32 -5877 0/imm32/no-disp32 -5878 1/imm32/output-is-write-only -5879 _Primitive-copy-lit-to-reg/imm32/next -5880 _Primitive-copy-lit-to-reg: -5881 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 -5882 "copy"/imm32/name -5883 Single-lit-var/imm32/inouts -5884 Single-int-var-in-some-register/imm32/outputs -5885 "c7 0/subop/copy"/imm32/subx-name -5886 3/imm32/rm32-is-first-output -5887 0/imm32/no-r32 -5888 1/imm32/imm32-is-first-inout -5889 0/imm32/no-disp32 -5890 1/imm32/output-is-write-only -5891 _Primitive-copy-lit-to-mem/imm32/next -5892 _Primitive-copy-lit-to-mem: -5893 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 -5894 "copy-to"/imm32/name -5895 Int-var-and-literal/imm32/inouts -5896 0/imm32/outputs -5897 "c7 0/subop/copy"/imm32/subx-name -5898 1/imm32/rm32-is-first-inout -5899 0/imm32/no-r32 -5900 2/imm32/imm32-is-first-inout -5901 0/imm32/no-disp32 -5902 1/imm32/output-is-write-only -5903 _Primitive-compare-mem-with-reg/imm32/next -5904 # - compare -5905 _Primitive-compare-mem-with-reg: -5906 # compare var1 var2/reg => 39/compare-> var1/rm32 var2/r32 -5907 "compare"/imm32/name -5908 Two-args-int-stack-int-reg/imm32/inouts -5909 0/imm32/outputs -5910 "39/compare->"/imm32/subx-name -5911 1/imm32/rm32-is-first-inout -5912 2/imm32/r32-is-second-inout -5913 0/imm32/no-imm32 -5914 0/imm32/no-disp32 -5915 0/imm32/output-is-write-only -5916 _Primitive-compare-reg-with-mem/imm32/next -5917 _Primitive-compare-reg-with-mem: -5918 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 -5919 "compare"/imm32/name -5920 Two-args-int-reg-int-stack/imm32/inouts -5921 0/imm32/outputs -5922 "3b/compare<-"/imm32/subx-name -5923 2/imm32/rm32-is-second-inout -5924 1/imm32/r32-is-first-inout -5925 0/imm32/no-imm32 -5926 0/imm32/no-disp32 -5927 0/imm32/output-is-write-only -5928 _Primitive-compare-eax-with-literal/imm32/next -5929 _Primitive-compare-eax-with-literal: -5930 # compare var1/eax n => 3d/compare-eax-with n/imm32 -5931 "compare"/imm32/name -5932 Two-args-int-eax-int-literal/imm32/inouts -5933 0/imm32/outputs -5934 "3d/compare-eax-with"/imm32/subx-name -5935 0/imm32/no-rm32 -5936 0/imm32/no-r32 -5937 2/imm32/imm32-is-second-inout -5938 0/imm32/no-disp32 -5939 0/imm32/output-is-write-only -5940 _Primitive-compare-regmem-with-literal/imm32/next -5941 _Primitive-compare-regmem-with-literal: -5942 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 -5943 "compare"/imm32/name -5944 Int-var-and-literal/imm32/inouts +4795 # emit clean-up code for 'vars' until some block depth +4796 # doesn't actually modify 'vars' so we need traverse manually inside the stack +4797 emit-cleanup-code-until-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-depth: int +4798 # . prologue +4799 55/push-ebp +4800 89/<- %ebp 4/r32/esp +4801 # . save registers +4802 50/push-eax +4803 51/push-ecx +4804 52/push-edx +4805 53/push-ebx +4806 # ecx = vars +4807 8b/-> *(ebp+0xc) 1/r32/ecx +4808 # var eax: int = vars->top +4809 8b/-> *ecx 0/r32/eax +4810 # var min/ecx: (address (handle var)) = vars->data +4811 81 0/subop/add %ecx 8/imm32 +4812 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] +4813 81 5/subop/subtract %eax 4/imm32 +4814 8d/copy-address *(ecx+eax) 0/r32/eax +4815 # edx = until-block-depth +4816 8b/-> *(ebp+0x10) 2/r32/edx +4817 { +4818 $emit-cleanup-code-until-depth:loop: +4819 # if (curr < min) break +4820 39/compare %eax 1/r32/ecx +4821 0f 82/jump-if-addr< break/disp32 +4822 # var v/ebx: (handle var) = *curr +4823 8b/-> *eax 3/r32/ebx +4824 # if (v->block-depth < until-block-depth) break +4825 39/compare *(ebx+8) 2/r32/edx # Var-block-depth +4826 0f 8c/jump-if-< break/disp32 +4827 # if v is in a register +4828 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register +4829 { +4830 74/jump-if-= break/disp8 +4831 $emit-cleanup-code-until-depth:reclaim-var-in-register: +4832 (emit-indent *(ebp+8) *Curr-block-depth) +4833 (write-buffered *(ebp+8) "8f 0/subop/pop %") +4834 (write-buffered *(ebp+8) *(ebx+0x10)) +4835 (write-buffered *(ebp+8) Newline) +4836 } +4837 # otherwise v is on the stack +4838 { +4839 75/jump-if-!= break/disp8 +4840 $emit-cleanup-code-until-depth:reclaim-var-on-stack: +4841 50/push-eax +4842 (size-of %ebx) # => eax +4843 # don't emit code for labels +4844 3d/compare-eax-and 0/imm32 +4845 74/jump-if-= break/disp8 +4846 # +4847 (emit-indent *(ebp+8) *Curr-block-depth) +4848 (write-buffered *(ebp+8) "81 0/subop/add %esp ") +4849 (print-int32-buffered *(ebp+8) %eax) +4850 (write-buffered *(ebp+8) "/imm32\n") +4851 58/pop-to-eax +4852 } +4853 # curr -= 4 +4854 2d/subtract-from-eax 4/imm32 +4855 e9/jump loop/disp32 +4856 } +4857 $emit-cleanup-code-until-depth:end: +4858 # . restore registers +4859 5b/pop-to-ebx +4860 5a/pop-to-edx +4861 59/pop-to-ecx +4862 58/pop-to-eax +4863 # . epilogue +4864 89/<- %esp 5/r32/ebp +4865 5d/pop-to-ebp +4866 c3/return +4867 +4868 # emit clean-up code for 'vars' until a given label is encountered +4869 # doesn't actually modify 'vars' so we need traverse manually inside the stack +4870 emit-cleanup-code-until-target: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-label: (addr array byte) +4871 # . prologue +4872 55/push-ebp +4873 89/<- %ebp 4/r32/esp +4874 # . save registers +4875 50/push-eax +4876 51/push-ecx +4877 52/push-edx +4878 53/push-ebx +4879 # ecx = vars +4880 8b/-> *(ebp+0xc) 1/r32/ecx +4881 # var eax: int = vars->top +4882 8b/-> *ecx 0/r32/eax +4883 # var min/ecx: (address (handle var)) = vars->data +4884 81 0/subop/add %ecx 8/imm32 +4885 # var curr/edx: (address (handle var)) = &vars->data[vars->top - 4] +4886 81 5/subop/subtract %eax 4/imm32 +4887 8d/copy-address *(ecx+eax) 2/r32/edx +4888 { +4889 $emit-cleanup-code-until-target:loop: +4890 # if (curr < min) break +4891 39/compare %edx 1/r32/ecx +4892 0f 82/jump-if-addr< break/disp32 +4893 # var v/ebx: (handle var) = *curr +4894 8b/-> *edx 3/r32/ebx +4895 # if (v->name == until-block-label) break +4896 (string-equal? *ebx *(ebp+0x10)) # => eax +4897 3d/compare-eax-and 0/imm32 +4898 0f 85/jump-if-!= break/disp32 +4899 # if v is in a register +4900 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register +4901 { +4902 74/jump-if-= break/disp8 +4903 $emit-cleanup-code-until-target:reclaim-var-in-register: +4904 (emit-indent *(ebp+8) *Curr-block-depth) +4905 (write-buffered *(ebp+8) "8f 0/subop/pop %") +4906 (write-buffered *(ebp+8) *(ebx+0x10)) +4907 (write-buffered *(ebp+8) Newline) +4908 } +4909 # otherwise v is on the stack +4910 { +4911 75/jump-if-!= break/disp8 +4912 $emit-cleanup-code-until-target:reclaim-var-on-stack: +4913 (size-of %ebx) # => eax +4914 # don't emit code for labels +4915 3d/compare-eax-and 0/imm32 +4916 74/jump-if-= break/disp8 +4917 # +4918 (emit-indent *(ebp+8) *Curr-block-depth) +4919 (write-buffered *(ebp+8) "81 0/subop/add %esp ") +4920 (print-int32-buffered *(ebp+8) %eax) +4921 (write-buffered *(ebp+8) "/imm32\n") +4922 } +4923 # curr -= 4 +4924 81 5/subop/subtract %edx 4/imm32 +4925 e9/jump loop/disp32 +4926 } +4927 $emit-cleanup-code-until-target:end: +4928 # . restore registers +4929 5b/pop-to-ebx +4930 5a/pop-to-edx +4931 59/pop-to-ecx +4932 58/pop-to-eax +4933 # . epilogue +4934 89/<- %esp 5/r32/ebp +4935 5d/pop-to-ebp +4936 c3/return +4937 +4938 # clean up global state for 'vars' until some block depth +4939 clean-up-blocks: # vars: (addr stack (handle var)), until-block-depth: int +4940 # . prologue +4941 55/push-ebp +4942 89/<- %ebp 4/r32/esp +4943 # . save registers +4944 50/push-eax +4945 51/push-ecx +4946 56/push-esi +4947 # esi = vars +4948 8b/-> *(ebp+8) 6/r32/esi +4949 # ecx = until-block-depth +4950 8b/-> *(ebp+0xc) 1/r32/ecx +4951 { +4952 $clean-up-blocks:reclaim-loop: +4953 # if (vars->top <= 0) break +4954 81 7/subop/compare *esi 0/imm32 # Stack-top +4955 7e/jump-if-<= break/disp8 +4956 # var v/eax: (handle var) = top(vars) +4957 (top %esi) # => eax +4958 # if (v->block-depth < until-block-depth) break +4959 39/compare *(eax+8) 1/r32/ecx # Var-block-depth +4960 7c/jump-if-< break/disp8 +4961 # if v is on the stack, update Next-local-stack-offset +4962 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register +4963 { +4964 75/jump-if-!= break/disp8 +4965 $clean-up-blocks:reclaim-var-on-stack: +4966 (size-of %eax) # => eax +4967 01/add *Next-local-stack-offset 0/r32/eax +4968 } +4969 (pop %esi) +4970 e9/jump loop/disp32 +4971 } +4972 $clean-up-blocks:end: +4973 # . restore registers +4974 5e/pop-to-esi +4975 59/pop-to-ecx +4976 58/pop-to-eax +4977 # . epilogue +4978 89/<- %esp 5/r32/ebp +4979 5d/pop-to-ebp +4980 c3/return +4981 +4982 emit-subx-var-def: # out: (addr buffered-file), stmt: (handle statement) +4983 # . prologue +4984 55/push-ebp +4985 89/<- %ebp 4/r32/esp +4986 # . save registers +4987 50/push-eax +4988 51/push-ecx +4989 # eax = stmt +4990 8b/-> *(ebp+0xc) 0/r32/eax +4991 # var n/eax: int = size-of(stmt->var) +4992 (size-of *(eax+4)) # Vardef-var => eax +4993 # while n > 0 +4994 { +4995 3d/compare-eax-with 0/imm32 +4996 7e/jump-if-<= break/disp8 +4997 (emit-indent *(ebp+8) *Curr-block-depth) +4998 (write-buffered *(ebp+8) "68/push 0/imm32\n") +4999 # n -= 4 +5000 2d/subtract-from-eax 4/imm32 +5001 # +5002 eb/jump loop/disp8 +5003 } +5004 $emit-subx-var-def:end: +5005 # . restore registers +5006 59/pop-to-ecx +5007 58/pop-to-eax +5008 # . epilogue +5009 89/<- %esp 5/r32/ebp +5010 5d/pop-to-ebp +5011 c3/return +5012 +5013 emit-subx-statement: # out: (addr buffered-file), stmt: (handle statement), primitives: (handle primitive), functions: (handle function) +5014 # . prologue +5015 55/push-ebp +5016 89/<- %ebp 4/r32/esp +5017 # . save registers +5018 50/push-eax +5019 51/push-ecx +5020 # if stmt matches a primitive, emit it +5021 { +5022 $emit-subx-statement:check-for-primitive: +5023 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => curr/eax +5024 3d/compare-eax-and 0/imm32 +5025 74/jump-if-= break/disp8 +5026 $emit-subx-statement:primitive: +5027 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr +5028 e9/jump $emit-subx-statement:end/disp32 +5029 } +5030 # else if stmt matches a function, emit a call to it +5031 { +5032 $emit-subx-statement:check-for-call: +5033 (find-matching-function *(ebp+0x14) *(ebp+0xc)) # functions, stmt => curr/eax +5034 3d/compare-eax-and 0/imm32 +5035 74/jump-if-= break/disp8 +5036 $emit-subx-statement:call: +5037 (emit-subx-call *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr +5038 e9/jump $emit-subx-statement:end/disp32 +5039 } +5040 # else assume it's a SubX function (TODO: how to type-check?!) +5041 (emit-hailmary-call *(ebp+8) *(ebp+0xc)) +5042 $emit-subx-statement:end: +5043 # . restore registers +5044 59/pop-to-ecx +5045 58/pop-to-eax +5046 # . epilogue +5047 89/<- %esp 5/r32/ebp +5048 5d/pop-to-ebp +5049 c3/return +5050 +5051 $emit-subx-statement:abort: +5052 # error("couldn't translate '" stmt "'\n") +5053 (write-buffered Stderr "couldn't translate an instruction with operation '") +5054 8b/-> *(ebp+0xc) 0/r32/eax +5055 (write-buffered Stderr *(eax+4)) # Stmt1-operation +5056 (write-buffered Stderr "'\n") +5057 (flush Stderr) +5058 # . syscall(exit, 1) +5059 bb/copy-to-ebx 1/imm32 +5060 b8/copy-to-eax 1/imm32/exit +5061 cd/syscall 0x80/imm8 +5062 # never gets here +5063 +5064 emit-subx-block: # out: (addr buffered-file), block: (handle block), vars: (addr stack (handle var)) +5065 # . prologue +5066 55/push-ebp +5067 89/<- %ebp 4/r32/esp +5068 # . save registers +5069 50/push-eax +5070 51/push-ecx +5071 56/push-esi +5072 # esi = block +5073 8b/-> *(ebp+0xc) 6/r32/esi +5074 # var stmts/eax: (handle list statement) = block->statements +5075 8b/-> *(esi+4) 0/r32/eax # Block-statements +5076 # +5077 { +5078 $emit-subx-block:check-empty: +5079 81 7/subop/compare %eax 0/imm32 +5080 0f 84/jump-if-= break/disp32 +5081 (emit-indent *(ebp+8) *Curr-block-depth) +5082 (write-buffered *(ebp+8) "{\n") +5083 # var v/ecx: (addr array byte) = block->var->name +5084 8b/-> *(esi+8) 1/r32/ecx # Block-var +5085 (write-buffered *(ebp+8) *ecx) # Var-name +5086 (write-buffered *(ebp+8) ":loop:\n") +5087 ff 0/subop/increment *Curr-block-depth +5088 (push *(ebp+0x10) %ecx) +5089 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10)) +5090 (pop *(ebp+0x10)) # => eax +5091 ff 1/subop/decrement *Curr-block-depth +5092 (emit-indent *(ebp+8) *Curr-block-depth) +5093 (write-buffered *(ebp+8) "}\n") +5094 (write-buffered *(ebp+8) *ecx) # Var-name +5095 (write-buffered *(ebp+8) ":break:\n") +5096 } +5097 $emit-subx-block:end: +5098 # . restore registers +5099 5e/pop-to-esi +5100 59/pop-to-ecx +5101 58/pop-to-eax +5102 # . epilogue +5103 89/<- %esp 5/r32/ebp +5104 5d/pop-to-ebp +5105 c3/return +5106 +5107 # Primitives supported +5108 # For each operation, put variants with hard-coded registers before flexible ones. +5109 == data +5110 Primitives: +5111 # - increment/decrement +5112 _Primitive-inc-eax: +5113 # var/eax <- increment => 40/increment-eax +5114 "increment"/imm32/name +5115 0/imm32/no-inouts +5116 Single-int-var-in-eax/imm32/outputs +5117 "40/increment-eax"/imm32/subx-name +5118 0/imm32/no-rm32 +5119 0/imm32/no-r32 +5120 0/imm32/no-imm32 +5121 0/imm32/no-disp32 +5122 0/imm32/output-is-write-only +5123 _Primitive-inc-ecx/imm32/next +5124 _Primitive-inc-ecx: +5125 # var/ecx <- increment => 41/increment-ecx +5126 "increment"/imm32/name +5127 0/imm32/no-inouts +5128 Single-int-var-in-ecx/imm32/outputs +5129 "41/increment-ecx"/imm32/subx-name +5130 0/imm32/no-rm32 +5131 0/imm32/no-r32 +5132 0/imm32/no-imm32 +5133 0/imm32/no-disp32 +5134 0/imm32/output-is-write-only +5135 _Primitive-inc-edx/imm32/next +5136 _Primitive-inc-edx: +5137 # var/edx <- increment => 42/increment-edx +5138 "increment"/imm32/name +5139 0/imm32/no-inouts +5140 Single-int-var-in-edx/imm32/outputs +5141 "42/increment-edx"/imm32/subx-name +5142 0/imm32/no-rm32 +5143 0/imm32/no-r32 +5144 0/imm32/no-imm32 +5145 0/imm32/no-disp32 +5146 0/imm32/output-is-write-only +5147 _Primitive-inc-ebx/imm32/next +5148 _Primitive-inc-ebx: +5149 # var/ebx <- increment => 43/increment-ebx +5150 "increment"/imm32/name +5151 0/imm32/no-inouts +5152 Single-int-var-in-ebx/imm32/outputs +5153 "43/increment-ebx"/imm32/subx-name +5154 0/imm32/no-rm32 +5155 0/imm32/no-r32 +5156 0/imm32/no-imm32 +5157 0/imm32/no-disp32 +5158 0/imm32/output-is-write-only +5159 _Primitive-inc-esi/imm32/next +5160 _Primitive-inc-esi: +5161 # var/esi <- increment => 46/increment-esi +5162 "increment"/imm32/name +5163 0/imm32/no-inouts +5164 Single-int-var-in-esi/imm32/outputs +5165 "46/increment-esi"/imm32/subx-name +5166 0/imm32/no-rm32 +5167 0/imm32/no-r32 +5168 0/imm32/no-imm32 +5169 0/imm32/no-disp32 +5170 0/imm32/output-is-write-only +5171 _Primitive-inc-edi/imm32/next +5172 _Primitive-inc-edi: +5173 # var/edi <- increment => 47/increment-edi +5174 "increment"/imm32/name +5175 0/imm32/no-inouts +5176 Single-int-var-in-edi/imm32/outputs +5177 "47/increment-edi"/imm32/subx-name +5178 0/imm32/no-rm32 +5179 0/imm32/no-r32 +5180 0/imm32/no-imm32 +5181 0/imm32/no-disp32 +5182 0/imm32/output-is-write-only +5183 _Primitive-dec-eax/imm32/next +5184 _Primitive-dec-eax: +5185 # var/eax <- decrement => 48/decrement-eax +5186 "decrement"/imm32/name +5187 0/imm32/no-inouts +5188 Single-int-var-in-eax/imm32/outputs +5189 "48/decrement-eax"/imm32/subx-name +5190 0/imm32/no-rm32 +5191 0/imm32/no-r32 +5192 0/imm32/no-imm32 +5193 0/imm32/no-disp32 +5194 0/imm32/output-is-write-only +5195 _Primitive-dec-ecx/imm32/next +5196 _Primitive-dec-ecx: +5197 # var/ecx <- decrement => 49/decrement-ecx +5198 "decrement"/imm32/name +5199 0/imm32/no-inouts +5200 Single-int-var-in-ecx/imm32/outputs +5201 "49/decrement-ecx"/imm32/subx-name +5202 0/imm32/no-rm32 +5203 0/imm32/no-r32 +5204 0/imm32/no-imm32 +5205 0/imm32/no-disp32 +5206 0/imm32/output-is-write-only +5207 _Primitive-dec-edx/imm32/next +5208 _Primitive-dec-edx: +5209 # var/edx <- decrement => 4a/decrement-edx +5210 "decrement"/imm32/name +5211 0/imm32/no-inouts +5212 Single-int-var-in-edx/imm32/outputs +5213 "4a/decrement-edx"/imm32/subx-name +5214 0/imm32/no-rm32 +5215 0/imm32/no-r32 +5216 0/imm32/no-imm32 +5217 0/imm32/no-disp32 +5218 0/imm32/output-is-write-only +5219 _Primitive-dec-ebx/imm32/next +5220 _Primitive-dec-ebx: +5221 # var/ebx <- decrement => 4b/decrement-ebx +5222 "decrement"/imm32/name +5223 0/imm32/no-inouts +5224 Single-int-var-in-ebx/imm32/outputs +5225 "4b/decrement-ebx"/imm32/subx-name +5226 0/imm32/no-rm32 +5227 0/imm32/no-r32 +5228 0/imm32/no-imm32 +5229 0/imm32/no-disp32 +5230 0/imm32/output-is-write-only +5231 _Primitive-dec-esi/imm32/next +5232 _Primitive-dec-esi: +5233 # var/esi <- decrement => 4e/decrement-esi +5234 "decrement"/imm32/name +5235 0/imm32/no-inouts +5236 Single-int-var-in-esi/imm32/outputs +5237 "4e/decrement-esi"/imm32/subx-name +5238 0/imm32/no-rm32 +5239 0/imm32/no-r32 +5240 0/imm32/no-imm32 +5241 0/imm32/no-disp32 +5242 0/imm32/output-is-write-only +5243 _Primitive-dec-edi/imm32/next +5244 _Primitive-dec-edi: +5245 # var/edi <- decrement => 4f/decrement-edi +5246 "decrement"/imm32/name +5247 0/imm32/no-inouts +5248 Single-int-var-in-edi/imm32/outputs +5249 "4f/decrement-edi"/imm32/subx-name +5250 0/imm32/no-rm32 +5251 0/imm32/no-r32 +5252 0/imm32/no-imm32 +5253 0/imm32/no-disp32 +5254 0/imm32/output-is-write-only +5255 _Primitive-inc-mem/imm32/next +5256 _Primitive-inc-mem: +5257 # increment var => ff 0/subop/increment *(ebp+__) +5258 "increment"/imm32/name +5259 Single-int-var-on-stack/imm32/inouts +5260 0/imm32/no-outputs +5261 "ff 0/subop/increment"/imm32/subx-name +5262 1/imm32/rm32-is-first-inout +5263 0/imm32/no-r32 +5264 0/imm32/no-imm32 +5265 0/imm32/no-disp32 +5266 0/imm32/output-is-write-only +5267 _Primitive-inc-reg/imm32/next +5268 _Primitive-inc-reg: +5269 # var/reg <- increment => ff 0/subop/increment %__ +5270 "increment"/imm32/name +5271 0/imm32/no-inouts +5272 Single-int-var-in-some-register/imm32/outputs +5273 "ff 0/subop/increment"/imm32/subx-name +5274 3/imm32/rm32-is-first-output +5275 0/imm32/no-r32 +5276 0/imm32/no-imm32 +5277 0/imm32/no-disp32 +5278 0/imm32/output-is-write-only +5279 _Primitive-dec-mem/imm32/next +5280 _Primitive-dec-mem: +5281 # decrement var => ff 1/subop/decrement *(ebp+__) +5282 "decrement"/imm32/name +5283 Single-int-var-on-stack/imm32/inouts +5284 0/imm32/no-outputs +5285 "ff 1/subop/decrement"/imm32/subx-name +5286 1/imm32/rm32-is-first-inout +5287 0/imm32/no-r32 +5288 0/imm32/no-imm32 +5289 0/imm32/no-disp32 +5290 0/imm32/output-is-write-only +5291 _Primitive-dec-reg/imm32/next +5292 _Primitive-dec-reg: +5293 # var/reg <- decrement => ff 1/subop/decrement %__ +5294 "decrement"/imm32/name +5295 0/imm32/no-inouts +5296 Single-int-var-in-some-register/imm32/outputs +5297 "ff 1/subop/decrement"/imm32/subx-name +5298 3/imm32/rm32-is-first-output +5299 0/imm32/no-r32 +5300 0/imm32/no-imm32 +5301 0/imm32/no-disp32 +5302 0/imm32/output-is-write-only +5303 _Primitive-add-to-eax/imm32/next +5304 # - add +5305 _Primitive-add-to-eax: +5306 # var/eax <- add lit => 05/add-to-eax lit/imm32 +5307 "add"/imm32/name +5308 Single-lit-var/imm32/inouts +5309 Single-int-var-in-eax/imm32/outputs +5310 "05/add-to-eax"/imm32/subx-name +5311 0/imm32/no-rm32 +5312 0/imm32/no-r32 +5313 1/imm32/imm32-is-first-inout +5314 0/imm32/no-disp32 +5315 0/imm32/output-is-write-only +5316 _Primitive-add-reg-to-reg/imm32/next +5317 _Primitive-add-reg-to-reg: +5318 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 +5319 "add"/imm32/name +5320 Single-int-var-in-some-register/imm32/inouts +5321 Single-int-var-in-some-register/imm32/outputs +5322 "01/add-to"/imm32/subx-name +5323 3/imm32/rm32-is-first-output +5324 1/imm32/r32-is-first-inout +5325 0/imm32/no-imm32 +5326 0/imm32/no-disp32 +5327 0/imm32/output-is-write-only +5328 _Primitive-add-reg-to-mem/imm32/next +5329 _Primitive-add-reg-to-mem: +5330 # add-to var1 var2/reg => 01/add-to var1 var2/r32 +5331 "add-to"/imm32/name +5332 Two-args-int-stack-int-reg/imm32/inouts +5333 0/imm32/outputs +5334 "01/add-to"/imm32/subx-name +5335 1/imm32/rm32-is-first-inout +5336 2/imm32/r32-is-second-inout +5337 0/imm32/no-imm32 +5338 0/imm32/no-disp32 +5339 0/imm32/output-is-write-only +5340 _Primitive-add-mem-to-reg/imm32/next +5341 _Primitive-add-mem-to-reg: +5342 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 +5343 "add"/imm32/name +5344 Single-int-var-on-stack/imm32/inouts +5345 Single-int-var-in-some-register/imm32/outputs +5346 "03/add"/imm32/subx-name +5347 1/imm32/rm32-is-first-inout +5348 3/imm32/r32-is-first-output +5349 0/imm32/no-imm32 +5350 0/imm32/no-disp32 +5351 0/imm32/output-is-write-only +5352 _Primitive-add-lit-to-reg/imm32/next +5353 _Primitive-add-lit-to-reg: +5354 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 +5355 "add"/imm32/name +5356 Single-lit-var/imm32/inouts +5357 Single-int-var-in-some-register/imm32/outputs +5358 "81 0/subop/add"/imm32/subx-name +5359 3/imm32/rm32-is-first-output +5360 0/imm32/no-r32 +5361 1/imm32/imm32-is-first-inout +5362 0/imm32/no-disp32 +5363 0/imm32/output-is-write-only +5364 _Primitive-add-lit-to-mem/imm32/next +5365 _Primitive-add-lit-to-mem: +5366 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 +5367 "add-to"/imm32/name +5368 Int-var-and-literal/imm32/inouts +5369 0/imm32/outputs +5370 "81 0/subop/add"/imm32/subx-name +5371 1/imm32/rm32-is-first-inout +5372 0/imm32/no-r32 +5373 2/imm32/imm32-is-second-inout +5374 0/imm32/no-disp32 +5375 0/imm32/output-is-write-only +5376 _Primitive-subtract-from-eax/imm32/next +5377 # - subtract +5378 _Primitive-subtract-from-eax: +5379 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 +5380 "subtract"/imm32/name +5381 Single-lit-var/imm32/inouts +5382 Single-int-var-in-eax/imm32/outputs +5383 "2d/subtract-from-eax"/imm32/subx-name +5384 0/imm32/no-rm32 +5385 0/imm32/no-r32 +5386 1/imm32/imm32-is-first-inout +5387 0/imm32/no-disp32 +5388 0/imm32/output-is-write-only +5389 _Primitive-subtract-reg-from-reg/imm32/next +5390 _Primitive-subtract-reg-from-reg: +5391 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 +5392 "subtract"/imm32/name +5393 Single-int-var-in-some-register/imm32/inouts +5394 Single-int-var-in-some-register/imm32/outputs +5395 "29/subtract-from"/imm32/subx-name +5396 3/imm32/rm32-is-first-output +5397 1/imm32/r32-is-first-inout +5398 0/imm32/no-imm32 +5399 0/imm32/no-disp32 +5400 0/imm32/output-is-write-only +5401 _Primitive-subtract-reg-from-mem/imm32/next +5402 _Primitive-subtract-reg-from-mem: +5403 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 +5404 "subtract-from"/imm32/name +5405 Two-args-int-stack-int-reg/imm32/inouts +5406 0/imm32/outputs +5407 "29/subtract-from"/imm32/subx-name +5408 1/imm32/rm32-is-first-inout +5409 2/imm32/r32-is-second-inout +5410 0/imm32/no-imm32 +5411 0/imm32/no-disp32 +5412 0/imm32/output-is-write-only +5413 _Primitive-subtract-mem-from-reg/imm32/next +5414 _Primitive-subtract-mem-from-reg: +5415 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 +5416 "subtract"/imm32/name +5417 Single-int-var-on-stack/imm32/inouts +5418 Single-int-var-in-some-register/imm32/outputs +5419 "2b/subtract"/imm32/subx-name +5420 1/imm32/rm32-is-first-inout +5421 3/imm32/r32-is-first-output +5422 0/imm32/no-imm32 +5423 0/imm32/no-disp32 +5424 0/imm32/output-is-write-only +5425 _Primitive-subtract-lit-from-reg/imm32/next +5426 _Primitive-subtract-lit-from-reg: +5427 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 +5428 "subtract"/imm32/name +5429 Single-lit-var/imm32/inouts +5430 Single-int-var-in-some-register/imm32/outputs +5431 "81 5/subop/subtract"/imm32/subx-name +5432 3/imm32/rm32-is-first-output +5433 0/imm32/no-r32 +5434 1/imm32/imm32-is-first-inout +5435 0/imm32/no-disp32 +5436 0/imm32/output-is-write-only +5437 _Primitive-subtract-lit-from-mem/imm32/next +5438 _Primitive-subtract-lit-from-mem: +5439 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 +5440 "subtract-from"/imm32/name +5441 Int-var-and-literal/imm32/inouts +5442 0/imm32/outputs +5443 "81 5/subop/subtract"/imm32/subx-name +5444 1/imm32/rm32-is-first-inout +5445 0/imm32/no-r32 +5446 2/imm32/imm32-is-first-inout +5447 0/imm32/no-disp32 +5448 0/imm32/output-is-write-only +5449 _Primitive-and-with-eax/imm32/next +5450 # - and +5451 _Primitive-and-with-eax: +5452 # var/eax <- and lit => 25/and-with-eax lit/imm32 +5453 "and"/imm32/name +5454 Single-lit-var/imm32/inouts +5455 Single-int-var-in-eax/imm32/outputs +5456 "25/and-with-eax"/imm32/subx-name +5457 0/imm32/no-rm32 +5458 0/imm32/no-r32 +5459 1/imm32/imm32-is-first-inout +5460 0/imm32/no-disp32 +5461 0/imm32/output-is-write-only +5462 _Primitive-and-reg-with-reg/imm32/next +5463 _Primitive-and-reg-with-reg: +5464 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 +5465 "and"/imm32/name +5466 Single-int-var-in-some-register/imm32/inouts +5467 Single-int-var-in-some-register/imm32/outputs +5468 "21/and-with"/imm32/subx-name +5469 3/imm32/rm32-is-first-output +5470 1/imm32/r32-is-first-inout +5471 0/imm32/no-imm32 +5472 0/imm32/no-disp32 +5473 0/imm32/output-is-write-only +5474 _Primitive-and-reg-with-mem/imm32/next +5475 _Primitive-and-reg-with-mem: +5476 # and-with var1 var2/reg => 21/and-with var1 var2/r32 +5477 "and-with"/imm32/name +5478 Two-args-int-stack-int-reg/imm32/inouts +5479 0/imm32/outputs +5480 "21/and-with"/imm32/subx-name +5481 1/imm32/rm32-is-first-inout +5482 2/imm32/r32-is-second-inout +5483 0/imm32/no-imm32 +5484 0/imm32/no-disp32 +5485 0/imm32/output-is-write-only +5486 _Primitive-and-mem-with-reg/imm32/next +5487 _Primitive-and-mem-with-reg: +5488 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 +5489 "and"/imm32/name +5490 Single-int-var-on-stack/imm32/inouts +5491 Single-int-var-in-some-register/imm32/outputs +5492 "23/and"/imm32/subx-name +5493 1/imm32/rm32-is-first-inout +5494 3/imm32/r32-is-first-output +5495 0/imm32/no-imm32 +5496 0/imm32/no-disp32 +5497 0/imm32/output-is-write-only +5498 _Primitive-and-lit-with-reg/imm32/next +5499 _Primitive-and-lit-with-reg: +5500 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 +5501 "and"/imm32/name +5502 Single-lit-var/imm32/inouts +5503 Single-int-var-in-some-register/imm32/outputs +5504 "81 4/subop/and"/imm32/subx-name +5505 3/imm32/rm32-is-first-output +5506 0/imm32/no-r32 +5507 1/imm32/imm32-is-first-inout +5508 0/imm32/no-disp32 +5509 0/imm32/output-is-write-only +5510 _Primitive-and-lit-with-mem/imm32/next +5511 _Primitive-and-lit-with-mem: +5512 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 +5513 "and-with"/imm32/name +5514 Int-var-and-literal/imm32/inouts +5515 0/imm32/outputs +5516 "81 4/subop/and"/imm32/subx-name +5517 1/imm32/rm32-is-first-inout +5518 0/imm32/no-r32 +5519 2/imm32/imm32-is-first-inout +5520 0/imm32/no-disp32 +5521 0/imm32/output-is-write-only +5522 _Primitive-or-with-eax/imm32/next +5523 # - or +5524 _Primitive-or-with-eax: +5525 # var/eax <- or lit => 0d/or-with-eax lit/imm32 +5526 "or"/imm32/name +5527 Single-lit-var/imm32/inouts +5528 Single-int-var-in-eax/imm32/outputs +5529 "0d/or-with-eax"/imm32/subx-name +5530 0/imm32/no-rm32 +5531 0/imm32/no-r32 +5532 1/imm32/imm32-is-first-inout +5533 0/imm32/no-disp32 +5534 0/imm32/output-is-write-only +5535 _Primitive-or-reg-with-reg/imm32/next +5536 _Primitive-or-reg-with-reg: +5537 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 +5538 "or"/imm32/name +5539 Single-int-var-in-some-register/imm32/inouts +5540 Single-int-var-in-some-register/imm32/outputs +5541 "09/or-with"/imm32/subx-name +5542 3/imm32/rm32-is-first-output +5543 1/imm32/r32-is-first-inout +5544 0/imm32/no-imm32 +5545 0/imm32/no-disp32 +5546 0/imm32/output-is-write-only +5547 _Primitive-or-reg-with-mem/imm32/next +5548 _Primitive-or-reg-with-mem: +5549 # or-with var1 var2/reg => 09/or-with var1 var2/r32 +5550 "or-with"/imm32/name +5551 Two-args-int-stack-int-reg/imm32/inouts +5552 0/imm32/outputs +5553 "09/or-with"/imm32/subx-name +5554 1/imm32/rm32-is-first-inout +5555 2/imm32/r32-is-second-inout +5556 0/imm32/no-imm32 +5557 0/imm32/no-disp32 +5558 0/imm32/output-is-write-only +5559 _Primitive-or-mem-with-reg/imm32/next +5560 _Primitive-or-mem-with-reg: +5561 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 +5562 "or"/imm32/name +5563 Single-int-var-on-stack/imm32/inouts +5564 Single-int-var-in-some-register/imm32/outputs +5565 "0b/or"/imm32/subx-name +5566 1/imm32/rm32-is-first-inout +5567 3/imm32/r32-is-first-output +5568 0/imm32/no-imm32 +5569 0/imm32/no-disp32 +5570 0/imm32/output-is-write-only +5571 _Primitive-or-lit-with-reg/imm32/next +5572 _Primitive-or-lit-with-reg: +5573 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 +5574 "or"/imm32/name +5575 Single-lit-var/imm32/inouts +5576 Single-int-var-in-some-register/imm32/outputs +5577 "81 1/subop/or"/imm32/subx-name +5578 3/imm32/rm32-is-first-output +5579 0/imm32/no-r32 +5580 1/imm32/imm32-is-first-inout +5581 0/imm32/no-disp32 +5582 0/imm32/output-is-write-only +5583 _Primitive-or-lit-with-mem/imm32/next +5584 _Primitive-or-lit-with-mem: +5585 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 +5586 "or-with"/imm32/name +5587 Int-var-and-literal/imm32/inouts +5588 0/imm32/outputs +5589 "81 1/subop/or"/imm32/subx-name +5590 1/imm32/rm32-is-first-inout +5591 0/imm32/no-r32 +5592 2/imm32/imm32-is-second-inout +5593 0/imm32/no-disp32 +5594 0/imm32/output-is-write-only +5595 _Primitive-xor-with-eax/imm32/next +5596 # - xor +5597 _Primitive-xor-with-eax: +5598 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 +5599 "xor"/imm32/name +5600 Single-lit-var/imm32/inouts +5601 Single-int-var-in-eax/imm32/outputs +5602 "35/xor-with-eax"/imm32/subx-name +5603 0/imm32/no-rm32 +5604 0/imm32/no-r32 +5605 1/imm32/imm32-is-first-inout +5606 0/imm32/no-disp32 +5607 0/imm32/output-is-write-only +5608 _Primitive-xor-reg-with-reg/imm32/next +5609 _Primitive-xor-reg-with-reg: +5610 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 +5611 "xor"/imm32/name +5612 Single-int-var-in-some-register/imm32/inouts +5613 Single-int-var-in-some-register/imm32/outputs +5614 "31/xor-with"/imm32/subx-name +5615 3/imm32/rm32-is-first-output +5616 1/imm32/r32-is-first-inout +5617 0/imm32/no-imm32 +5618 0/imm32/no-disp32 +5619 0/imm32/output-is-write-only +5620 _Primitive-xor-reg-with-mem/imm32/next +5621 _Primitive-xor-reg-with-mem: +5622 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 +5623 "xor-with"/imm32/name +5624 Two-args-int-stack-int-reg/imm32/inouts +5625 0/imm32/outputs +5626 "31/xor-with"/imm32/subx-name +5627 1/imm32/rm32-is-first-inout +5628 2/imm32/r32-is-second-inout +5629 0/imm32/no-imm32 +5630 0/imm32/no-disp32 +5631 0/imm32/output-is-write-only +5632 _Primitive-xor-mem-with-reg/imm32/next +5633 _Primitive-xor-mem-with-reg: +5634 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 +5635 "xor"/imm32/name +5636 Single-int-var-on-stack/imm32/inouts +5637 Single-int-var-in-some-register/imm32/outputs +5638 "33/xor"/imm32/subx-name +5639 1/imm32/rm32-is-first-inout +5640 3/imm32/r32-is-first-output +5641 0/imm32/no-imm32 +5642 0/imm32/no-disp32 +5643 0/imm32/output-is-write-only +5644 _Primitive-xor-lit-with-reg/imm32/next +5645 _Primitive-xor-lit-with-reg: +5646 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 +5647 "xor"/imm32/name +5648 Single-lit-var/imm32/inouts +5649 Single-int-var-in-some-register/imm32/outputs +5650 "81 6/subop/xor"/imm32/subx-name +5651 3/imm32/rm32-is-first-output +5652 0/imm32/no-r32 +5653 1/imm32/imm32-is-first-inout +5654 0/imm32/no-disp32 +5655 0/imm32/output-is-write-only +5656 _Primitive-xor-lit-with-mem/imm32/next +5657 _Primitive-xor-lit-with-mem: +5658 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 +5659 "xor-with"/imm32/name +5660 Int-var-and-literal/imm32/inouts +5661 0/imm32/outputs +5662 "81 6/subop/xor"/imm32/subx-name +5663 1/imm32/rm32-is-first-inout +5664 0/imm32/no-r32 +5665 2/imm32/imm32-is-first-inout +5666 0/imm32/no-disp32 +5667 0/imm32/output-is-write-only +5668 _Primitive-copy-to-eax/imm32/next +5669 # - copy +5670 _Primitive-copy-to-eax: +5671 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 +5672 "copy"/imm32/name +5673 Single-lit-var/imm32/inouts +5674 Single-int-var-in-eax/imm32/outputs +5675 "b8/copy-to-eax"/imm32/subx-name +5676 0/imm32/no-rm32 +5677 0/imm32/no-r32 +5678 1/imm32/imm32-is-first-inout +5679 0/imm32/no-disp32 +5680 1/imm32/output-is-write-only +5681 _Primitive-copy-to-ecx/imm32/next +5682 _Primitive-copy-to-ecx: +5683 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 +5684 "copy"/imm32/name +5685 Single-lit-var/imm32/inouts +5686 Single-int-var-in-ecx/imm32/outputs +5687 "b9/copy-to-ecx"/imm32/subx-name +5688 0/imm32/no-rm32 +5689 0/imm32/no-r32 +5690 1/imm32/imm32-is-first-inout +5691 0/imm32/no-disp32 +5692 1/imm32/output-is-write-only +5693 _Primitive-copy-to-edx/imm32/next +5694 _Primitive-copy-to-edx: +5695 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 +5696 "copy"/imm32/name +5697 Single-lit-var/imm32/inouts +5698 Single-int-var-in-edx/imm32/outputs +5699 "ba/copy-to-edx"/imm32/subx-name +5700 0/imm32/no-rm32 +5701 0/imm32/no-r32 +5702 1/imm32/imm32-is-first-inout +5703 0/imm32/no-disp32 +5704 1/imm32/output-is-write-only +5705 _Primitive-copy-to-ebx/imm32/next +5706 _Primitive-copy-to-ebx: +5707 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 +5708 "copy"/imm32/name +5709 Single-lit-var/imm32/inouts +5710 Single-int-var-in-ebx/imm32/outputs +5711 "bb/copy-to-ebx"/imm32/subx-name +5712 0/imm32/no-rm32 +5713 0/imm32/no-r32 +5714 1/imm32/imm32-is-first-inout +5715 0/imm32/no-disp32 +5716 1/imm32/output-is-write-only +5717 _Primitive-copy-to-esi/imm32/next +5718 _Primitive-copy-to-esi: +5719 # var/esi <- copy lit => be/copy-to-esi lit/imm32 +5720 "copy"/imm32/name +5721 Single-lit-var/imm32/inouts +5722 Single-int-var-in-esi/imm32/outputs +5723 "be/copy-to-esi"/imm32/subx-name +5724 0/imm32/no-rm32 +5725 0/imm32/no-r32 +5726 1/imm32/imm32-is-first-inout +5727 0/imm32/no-disp32 +5728 1/imm32/output-is-write-only +5729 _Primitive-copy-to-edi/imm32/next +5730 _Primitive-copy-to-edi: +5731 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 +5732 "copy"/imm32/name +5733 Single-lit-var/imm32/inouts +5734 Single-int-var-in-edi/imm32/outputs +5735 "bf/copy-to-edi"/imm32/subx-name +5736 0/imm32/no-rm32 +5737 0/imm32/no-r32 +5738 1/imm32/imm32-is-first-inout +5739 0/imm32/no-disp32 +5740 1/imm32/output-is-write-only +5741 _Primitive-copy-reg-to-reg/imm32/next +5742 _Primitive-copy-reg-to-reg: +5743 # var1/reg <- copy var2/reg => 89/copy-to var1/rm32 var2/r32 +5744 "copy"/imm32/name +5745 Single-int-var-in-some-register/imm32/inouts +5746 Single-int-var-in-some-register/imm32/outputs +5747 "89/copy-to"/imm32/subx-name +5748 3/imm32/rm32-is-first-output +5749 1/imm32/r32-is-first-inout +5750 0/imm32/no-imm32 +5751 0/imm32/no-disp32 +5752 1/imm32/output-is-write-only +5753 _Primitive-copy-reg-to-mem/imm32/next +5754 _Primitive-copy-reg-to-mem: +5755 # copy-to var1 var2/reg => 89/copy-to var1 var2/r32 +5756 "copy-to"/imm32/name +5757 Two-args-int-stack-int-reg/imm32/inouts +5758 0/imm32/outputs +5759 "89/copy-to"/imm32/subx-name +5760 1/imm32/rm32-is-first-inout +5761 2/imm32/r32-is-second-inout +5762 0/imm32/no-imm32 +5763 0/imm32/no-disp32 +5764 1/imm32/output-is-write-only +5765 _Primitive-copy-mem-to-reg/imm32/next +5766 _Primitive-copy-mem-to-reg: +5767 # var1/reg <- copy var2 => 8b/copy-from var2/rm32 var1/r32 +5768 "copy"/imm32/name +5769 Single-int-var-on-stack/imm32/inouts +5770 Single-int-var-in-some-register/imm32/outputs +5771 "8b/copy-from"/imm32/subx-name +5772 1/imm32/rm32-is-first-inout +5773 3/imm32/r32-is-first-output +5774 0/imm32/no-imm32 +5775 0/imm32/no-disp32 +5776 1/imm32/output-is-write-only +5777 _Primitive-copy-lit-to-reg/imm32/next +5778 _Primitive-copy-lit-to-reg: +5779 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 +5780 "copy"/imm32/name +5781 Single-lit-var/imm32/inouts +5782 Single-int-var-in-some-register/imm32/outputs +5783 "c7 0/subop/copy"/imm32/subx-name +5784 3/imm32/rm32-is-first-output +5785 0/imm32/no-r32 +5786 1/imm32/imm32-is-first-inout +5787 0/imm32/no-disp32 +5788 1/imm32/output-is-write-only +5789 _Primitive-copy-lit-to-mem/imm32/next +5790 _Primitive-copy-lit-to-mem: +5791 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 +5792 "copy-to"/imm32/name +5793 Int-var-and-literal/imm32/inouts +5794 0/imm32/outputs +5795 "c7 0/subop/copy"/imm32/subx-name +5796 1/imm32/rm32-is-first-inout +5797 0/imm32/no-r32 +5798 2/imm32/imm32-is-first-inout +5799 0/imm32/no-disp32 +5800 1/imm32/output-is-write-only +5801 _Primitive-compare-mem-with-reg/imm32/next +5802 # - compare +5803 _Primitive-compare-mem-with-reg: +5804 # compare var1 var2/reg => 39/compare-> var1/rm32 var2/r32 +5805 "compare"/imm32/name +5806 Two-args-int-stack-int-reg/imm32/inouts +5807 0/imm32/outputs +5808 "39/compare->"/imm32/subx-name +5809 1/imm32/rm32-is-first-inout +5810 2/imm32/r32-is-second-inout +5811 0/imm32/no-imm32 +5812 0/imm32/no-disp32 +5813 0/imm32/output-is-write-only +5814 _Primitive-compare-reg-with-mem/imm32/next +5815 _Primitive-compare-reg-with-mem: +5816 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 +5817 "compare"/imm32/name +5818 Two-args-int-reg-int-stack/imm32/inouts +5819 0/imm32/outputs +5820 "3b/compare<-"/imm32/subx-name +5821 2/imm32/rm32-is-second-inout +5822 1/imm32/r32-is-first-inout +5823 0/imm32/no-imm32 +5824 0/imm32/no-disp32 +5825 0/imm32/output-is-write-only +5826 _Primitive-compare-eax-with-literal/imm32/next +5827 _Primitive-compare-eax-with-literal: +5828 # compare var1/eax n => 3d/compare-eax-with n/imm32 +5829 "compare"/imm32/name +5830 Two-args-int-eax-int-literal/imm32/inouts +5831 0/imm32/outputs +5832 "3d/compare-eax-with"/imm32/subx-name +5833 0/imm32/no-rm32 +5834 0/imm32/no-r32 +5835 2/imm32/imm32-is-second-inout +5836 0/imm32/no-disp32 +5837 0/imm32/output-is-write-only +5838 _Primitive-compare-regmem-with-literal/imm32/next +5839 _Primitive-compare-regmem-with-literal: +5840 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 +5841 "compare"/imm32/name +5842 Int-var-and-literal/imm32/inouts +5843 0/imm32/outputs +5844 "81 7/subop/compare"/imm32/subx-name +5845 1/imm32/rm32-is-first-inout +5846 0/imm32/no-r32 +5847 2/imm32/imm32-is-second-inout +5848 0/imm32/no-disp32 +5849 0/imm32/output-is-write-only +5850 _Primitive-multiply-reg-by-mem/imm32/next +5851 # - multiply +5852 _Primitive-multiply-reg-by-mem: +5853 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 +5854 "multiply"/imm32/name +5855 Single-int-var-on-stack/imm32/inouts +5856 Single-int-var-in-some-register/imm32/outputs +5857 "0f af/multiply"/imm32/subx-name +5858 1/imm32/rm32-is-first-inout +5859 3/imm32/r32-is-first-output +5860 0/imm32/no-imm32 +5861 0/imm32/no-disp32 +5862 0/imm32/output-is-write-only +5863 _Primitive-break-if-addr</imm32/next +5864 # - branches +5865 _Primitive-break-if-addr<: +5866 "break-if-addr<"/imm32/name +5867 0/imm32/inouts +5868 0/imm32/outputs +5869 "0f 82/jump-if-addr< break/disp32"/imm32/subx-name +5870 0/imm32/no-rm32 +5871 0/imm32/no-r32 +5872 0/imm32/no-imm32 +5873 0/imm32/no-disp32 +5874 0/imm32/no-output +5875 _Primitive-break-if-addr>=/imm32/next +5876 _Primitive-break-if-addr>=: +5877 "break-if-addr>="/imm32/name +5878 0/imm32/inouts +5879 0/imm32/outputs +5880 "0f 83/jump-if-addr>= break/disp32"/imm32/subx-name +5881 0/imm32/no-rm32 +5882 0/imm32/no-r32 +5883 0/imm32/no-imm32 +5884 0/imm32/no-disp32 +5885 0/imm32/no-output +5886 _Primitive-break-if-=/imm32/next +5887 _Primitive-break-if-=: +5888 "break-if-="/imm32/name +5889 0/imm32/inouts +5890 0/imm32/outputs +5891 "0f 84/jump-if-= break/disp32"/imm32/subx-name +5892 0/imm32/no-rm32 +5893 0/imm32/no-r32 +5894 0/imm32/no-imm32 +5895 0/imm32/no-disp32 +5896 0/imm32/no-output +5897 _Primitive-break-if-!=/imm32/next +5898 _Primitive-break-if-!=: +5899 "break-if-!="/imm32/name +5900 0/imm32/inouts +5901 0/imm32/outputs +5902 "0f 85/jump-if-!= break/disp32"/imm32/subx-name +5903 0/imm32/no-rm32 +5904 0/imm32/no-r32 +5905 0/imm32/no-imm32 +5906 0/imm32/no-disp32 +5907 0/imm32/no-output +5908 _Primitive-break-if-addr<=/imm32/next +5909 _Primitive-break-if-addr<=: +5910 "break-if-addr<="/imm32/name +5911 0/imm32/inouts +5912 0/imm32/outputs +5913 "0f 86/jump-if-addr<= break/disp32"/imm32/subx-name +5914 0/imm32/no-rm32 +5915 0/imm32/no-r32 +5916 0/imm32/no-imm32 +5917 0/imm32/no-disp32 +5918 0/imm32/no-output +5919 _Primitive-break-if-addr>/imm32/next +5920 _Primitive-break-if-addr>: +5921 "break-if-addr>"/imm32/name +5922 0/imm32/inouts +5923 0/imm32/outputs +5924 "0f 87/jump-if-addr> break/disp32"/imm32/subx-name +5925 0/imm32/no-rm32 +5926 0/imm32/no-r32 +5927 0/imm32/no-imm32 +5928 0/imm32/no-disp32 +5929 0/imm32/no-output +5930 _Primitive-break-if-</imm32/next +5931 _Primitive-break-if-<: +5932 "break-if-<"/imm32/name +5933 0/imm32/inouts +5934 0/imm32/outputs +5935 "0f 8c/jump-if-< break/disp32"/imm32/subx-name +5936 0/imm32/no-rm32 +5937 0/imm32/no-r32 +5938 0/imm32/no-imm32 +5939 0/imm32/no-disp32 +5940 0/imm32/no-output +5941 _Primitive-break-if->=/imm32/next +5942 _Primitive-break-if->=: +5943 "break-if->="/imm32/name +5944 0/imm32/inouts 5945 0/imm32/outputs -5946 "81 7/subop/compare"/imm32/subx-name -5947 1/imm32/rm32-is-first-inout +5946 "0f 8d/jump-if->= break/disp32"/imm32/subx-name +5947 0/imm32/no-rm32 5948 0/imm32/no-r32 -5949 2/imm32/imm32-is-second-inout +5949 0/imm32/no-imm32 5950 0/imm32/no-disp32 -5951 0/imm32/output-is-write-only -5952 _Primitive-multiply-reg-by-mem/imm32/next -5953 # - multiply -5954 _Primitive-multiply-reg-by-mem: -5955 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 -5956 "multiply"/imm32/name -5957 Single-int-var-on-stack/imm32/inouts -5958 Single-int-var-in-some-register/imm32/outputs -5959 "0f af/multiply"/imm32/subx-name -5960 1/imm32/rm32-is-first-inout -5961 3/imm32/r32-is-first-output -5962 0/imm32/no-imm32 -5963 0/imm32/no-disp32 -5964 0/imm32/output-is-write-only -5965 _Primitive-break-if-addr</imm32/next -5966 # - branches -5967 _Primitive-break-if-addr<: -5968 "break-if-addr<"/imm32/name -5969 0/imm32/inouts -5970 0/imm32/outputs -5971 "0f 82/jump-if-addr< break/disp32"/imm32/subx-name -5972 0/imm32/no-rm32 -5973 0/imm32/no-r32 -5974 0/imm32/no-imm32 -5975 0/imm32/no-disp32 -5976 0/imm32/no-output -5977 _Primitive-break-if-addr>=/imm32/next -5978 _Primitive-break-if-addr>=: -5979 "break-if-addr>="/imm32/name -5980 0/imm32/inouts -5981 0/imm32/outputs -5982 "0f 83/jump-if-addr>= break/disp32"/imm32/subx-name -5983 0/imm32/no-rm32 -5984 0/imm32/no-r32 -5985 0/imm32/no-imm32 -5986 0/imm32/no-disp32 -5987 0/imm32/no-output -5988 _Primitive-break-if-=/imm32/next -5989 _Primitive-break-if-=: -5990 "break-if-="/imm32/name -5991 0/imm32/inouts -5992 0/imm32/outputs -5993 "0f 84/jump-if-= break/disp32"/imm32/subx-name -5994 0/imm32/no-rm32 -5995 0/imm32/no-r32 -5996 0/imm32/no-imm32 -5997 0/imm32/no-disp32 -5998 0/imm32/no-output -5999 _Primitive-break-if-!=/imm32/next -6000 _Primitive-break-if-!=: -6001 "break-if-!="/imm32/name -6002 0/imm32/inouts -6003 0/imm32/outputs -6004 "0f 85/jump-if-!= break/disp32"/imm32/subx-name -6005 0/imm32/no-rm32 -6006 0/imm32/no-r32 -6007 0/imm32/no-imm32 -6008 0/imm32/no-disp32 -6009 0/imm32/no-output -6010 _Primitive-break-if-addr<=/imm32/next -6011 _Primitive-break-if-addr<=: -6012 "break-if-addr<="/imm32/name -6013 0/imm32/inouts -6014 0/imm32/outputs -6015 "0f 86/jump-if-addr<= break/disp32"/imm32/subx-name -6016 0/imm32/no-rm32 -6017 0/imm32/no-r32 -6018 0/imm32/no-imm32 -6019 0/imm32/no-disp32 -6020 0/imm32/no-output -6021 _Primitive-break-if-addr>/imm32/next -6022 _Primitive-break-if-addr>: -6023 "break-if-addr>"/imm32/name -6024 0/imm32/inouts -6025 0/imm32/outputs -6026 "0f 87/jump-if-addr> break/disp32"/imm32/subx-name -6027 0/imm32/no-rm32 -6028 0/imm32/no-r32 -6029 0/imm32/no-imm32 -6030 0/imm32/no-disp32 -6031 0/imm32/no-output -6032 _Primitive-break-if-</imm32/next -6033 _Primitive-break-if-<: -6034 "break-if-<"/imm32/name -6035 0/imm32/inouts -6036 0/imm32/outputs -6037 "0f 8c/jump-if-< break/disp32"/imm32/subx-name -6038 0/imm32/no-rm32 -6039 0/imm32/no-r32 -6040 0/imm32/no-imm32 -6041 0/imm32/no-disp32 -6042 0/imm32/no-output -6043 _Primitive-break-if->=/imm32/next -6044 _Primitive-break-if->=: -6045 "break-if->="/imm32/name -6046 0/imm32/inouts -6047 0/imm32/outputs -6048 "0f 8d/jump-if->= break/disp32"/imm32/subx-name -6049 0/imm32/no-rm32 -6050 0/imm32/no-r32 -6051 0/imm32/no-imm32 -6052 0/imm32/no-disp32 -6053 0/imm32/no-output -6054 _Primitive-break-if-<=/imm32/next -6055 _Primitive-break-if-<=: -6056 "break-if-<="/imm32/name -6057 0/imm32/inouts -6058 0/imm32/outputs -6059 "0f 8e/jump-if-<= break/disp32"/imm32/subx-name -6060 0/imm32/no-rm32 -6061 0/imm32/no-r32 -6062 0/imm32/no-imm32 -6063 0/imm32/no-disp32 -6064 0/imm32/no-output -6065 _Primitive-break-if->/imm32/next -6066 _Primitive-break-if->: -6067 "break-if->"/imm32/name -6068 0/imm32/inouts -6069 0/imm32/outputs -6070 "0f 8f/jump-if-> break/disp32"/imm32/subx-name -6071 0/imm32/no-rm32 -6072 0/imm32/no-r32 -6073 0/imm32/no-imm32 -6074 0/imm32/no-disp32 -6075 0/imm32/no-output -6076 _Primitive-loop-if-addr</imm32/next -6077 _Primitive-loop-if-addr<: -6078 "loop-if-addr<"/imm32/name -6079 0/imm32/inouts -6080 0/imm32/outputs -6081 "0f 82/jump-if-addr< loop/disp32"/imm32/subx-name -6082 0/imm32/no-rm32 -6083 0/imm32/no-r32 -6084 0/imm32/no-imm32 -6085 0/imm32/no-disp32 -6086 0/imm32/no-output -6087 _Primitive-loop-if-addr>=/imm32/next -6088 _Primitive-loop-if-addr>=: -6089 "loop-if-addr>="/imm32/name -6090 0/imm32/inouts -6091 0/imm32/outputs -6092 "0f 83/jump-if-addr>= loop/disp32"/imm32/subx-name -6093 0/imm32/no-rm32 -6094 0/imm32/no-r32 -6095 0/imm32/no-imm32 -6096 0/imm32/no-disp32 -6097 0/imm32/no-output -6098 _Primitive-loop-if-=/imm32/next -6099 _Primitive-loop-if-=: -6100 "loop-if-="/imm32/name -6101 0/imm32/inouts -6102 0/imm32/outputs -6103 "0f 84/jump-if-= loop/disp32"/imm32/subx-name -6104 0/imm32/no-rm32 -6105 0/imm32/no-r32 -6106 0/imm32/no-imm32 -6107 0/imm32/no-disp32 -6108 0/imm32/no-output -6109 _Primitive-loop-if-!=/imm32/next -6110 _Primitive-loop-if-!=: -6111 "loop-if-!="/imm32/name -6112 0/imm32/inouts -6113 0/imm32/outputs -6114 "0f 85/jump-if-!= loop/disp32"/imm32/subx-name -6115 0/imm32/no-rm32 -6116 0/imm32/no-r32 -6117 0/imm32/no-imm32 -6118 0/imm32/no-disp32 -6119 0/imm32/no-output -6120 _Primitive-loop-if-addr<=/imm32/next -6121 _Primitive-loop-if-addr<=: -6122 "loop-if-addr<="/imm32/name -6123 0/imm32/inouts -6124 0/imm32/outputs -6125 "0f 86/jump-if-addr<= loop/disp32"/imm32/subx-name -6126 0/imm32/no-rm32 -6127 0/imm32/no-r32 -6128 0/imm32/no-imm32 -6129 0/imm32/no-disp32 -6130 0/imm32/no-output -6131 _Primitive-loop-if-addr>/imm32/next -6132 _Primitive-loop-if-addr>: -6133 "loop-if-addr>"/imm32/name -6134 0/imm32/inouts -6135 0/imm32/outputs -6136 "0f 87/jump-if-addr> loop/disp32"/imm32/subx-name -6137 0/imm32/no-rm32 -6138 0/imm32/no-r32 -6139 0/imm32/no-imm32 -6140 0/imm32/no-disp32 -6141 0/imm32/no-output -6142 _Primitive-loop-if-</imm32/next -6143 _Primitive-loop-if-<: -6144 "loop-if-<"/imm32/name -6145 0/imm32/inouts -6146 0/imm32/outputs -6147 "0f 8c/jump-if-< loop/disp32"/imm32/subx-name -6148 0/imm32/no-rm32 -6149 0/imm32/no-r32 -6150 0/imm32/no-imm32 -6151 0/imm32/no-disp32 -6152 0/imm32/no-output -6153 _Primitive-loop-if->=/imm32/next -6154 _Primitive-loop-if->=: -6155 "loop-if->="/imm32/name -6156 0/imm32/inouts -6157 0/imm32/outputs -6158 "0f 8d/jump-if->= loop/disp32"/imm32/subx-name -6159 0/imm32/no-rm32 -6160 0/imm32/no-r32 -6161 0/imm32/no-imm32 -6162 0/imm32/no-disp32 -6163 0/imm32/no-output -6164 _Primitive-loop-if-<=/imm32/next -6165 _Primitive-loop-if-<=: -6166 "loop-if-<="/imm32/name -6167 0/imm32/inouts -6168 0/imm32/outputs -6169 "0f 8e/jump-if-<= loop/disp32"/imm32/subx-name -6170 0/imm32/no-rm32 -6171 0/imm32/no-r32 -6172 0/imm32/no-imm32 -6173 0/imm32/no-disp32 -6174 0/imm32/no-output -6175 _Primitive-loop-if->/imm32/next -6176 _Primitive-loop-if->: -6177 "loop-if->"/imm32/name -6178 0/imm32/inouts -6179 0/imm32/outputs -6180 "0f 8f/jump-if-> loop/disp32"/imm32/subx-name -6181 0/imm32/no-rm32 -6182 0/imm32/no-r32 -6183 0/imm32/no-imm32 -6184 0/imm32/no-disp32 -6185 0/imm32/no-output -6186 _Primitive-loop/imm32/next # we probably don't need an unconditional break -6187 _Primitive-loop: -6188 "loop"/imm32/name -6189 0/imm32/inouts -6190 0/imm32/outputs -6191 "e9/jump loop/disp32"/imm32/subx-name -6192 0/imm32/no-rm32 -6193 0/imm32/no-r32 -6194 0/imm32/no-imm32 -6195 0/imm32/no-disp32 -6196 0/imm32/no-output -6197 _Primitive-break-if-addr<-named/imm32/next -6198 # - branches to named blocks -6199 _Primitive-break-if-addr<-named: -6200 "break-if-addr<"/imm32/name -6201 Single-lit-var/imm32/inouts -6202 0/imm32/outputs -6203 "0f 82/jump-if-addr<"/imm32/subx-name -6204 0/imm32/no-rm32 -6205 0/imm32/no-r32 -6206 0/imm32/no-imm32 -6207 1/imm32/disp32-is-first-inout -6208 0/imm32/no-output -6209 _Primitive-break-if-addr>=-named/imm32/next -6210 _Primitive-break-if-addr>=-named: -6211 "break-if-addr>="/imm32/name -6212 Single-lit-var/imm32/inouts -6213 0/imm32/outputs -6214 "0f 83/jump-if-addr>="/imm32/subx-name -6215 0/imm32/no-rm32 -6216 0/imm32/no-r32 -6217 0/imm32/no-imm32 -6218 1/imm32/disp32-is-first-inout -6219 0/imm32/no-output -6220 _Primitive-break-if-=-named/imm32/next -6221 _Primitive-break-if-=-named: -6222 "break-if-="/imm32/name -6223 Single-lit-var/imm32/inouts -6224 0/imm32/outputs -6225 "0f 84/jump-if-="/imm32/subx-name -6226 0/imm32/no-rm32 -6227 0/imm32/no-r32 -6228 0/imm32/no-imm32 -6229 1/imm32/disp32-is-first-inout -6230 0/imm32/no-output -6231 _Primitive-break-if-!=-named/imm32/next -6232 _Primitive-break-if-!=-named: -6233 "break-if-!="/imm32/name -6234 Single-lit-var/imm32/inouts -6235 0/imm32/outputs -6236 "0f 85/jump-if-!="/imm32/subx-name -6237 0/imm32/no-rm32 -6238 0/imm32/no-r32 -6239 0/imm32/no-imm32 -6240 1/imm32/disp32-is-first-inout -6241 0/imm32/no-output -6242 _Primitive-break-if-addr<=-named/imm32/next -6243 _Primitive-break-if-addr<=-named: -6244 "break-if-addr<="/imm32/name -6245 Single-lit-var/imm32/inouts -6246 0/imm32/outputs -6247 "0f 86/jump-if-addr<="/imm32/subx-name -6248 0/imm32/no-rm32 -6249 0/imm32/no-r32 -6250 0/imm32/no-imm32 -6251 1/imm32/disp32-is-first-inout -6252 0/imm32/no-output -6253 _Primitive-break-if-addr>-named/imm32/next -6254 _Primitive-break-if-addr>-named: -6255 "break-if-addr>"/imm32/name -6256 Single-lit-var/imm32/inouts -6257 0/imm32/outputs -6258 "0f 87/jump-if-addr>"/imm32/subx-name -6259 0/imm32/no-rm32 -6260 0/imm32/no-r32 -6261 0/imm32/no-imm32 -6262 1/imm32/disp32-is-first-inout -6263 0/imm32/no-output -6264 _Primitive-break-if-<-named/imm32/next -6265 _Primitive-break-if-<-named: -6266 "break-if-<"/imm32/name -6267 Single-lit-var/imm32/inouts -6268 0/imm32/outputs -6269 "0f 8c/jump-if-<"/imm32/subx-name -6270 0/imm32/no-rm32 -6271 0/imm32/no-r32 -6272 0/imm32/no-imm32 -6273 1/imm32/disp32-is-first-inout -6274 0/imm32/no-output -6275 _Primitive-break-if->=-named/imm32/next -6276 _Primitive-break-if->=-named: -6277 "break-if->="/imm32/name -6278 Single-lit-var/imm32/inouts -6279 0/imm32/outputs -6280 "0f 8d/jump-if->="/imm32/subx-name -6281 0/imm32/no-rm32 -6282 0/imm32/no-r32 -6283 0/imm32/no-imm32 -6284 1/imm32/disp32-is-first-inout -6285 0/imm32/no-output -6286 _Primitive-break-if-<=-named/imm32/next -6287 _Primitive-break-if-<=-named: -6288 "break-if-<="/imm32/name -6289 Single-lit-var/imm32/inouts -6290 0/imm32/outputs -6291 "0f 8e/jump-if-<="/imm32/subx-name -6292 0/imm32/no-rm32 -6293 0/imm32/no-r32 -6294 0/imm32/no-imm32 -6295 1/imm32/disp32-is-first-inout -6296 0/imm32/no-output -6297 _Primitive-break-if->-named/imm32/next -6298 _Primitive-break-if->-named: -6299 "break-if->"/imm32/name -6300 Single-lit-var/imm32/inouts -6301 0/imm32/outputs -6302 "0f 8f/jump-if->"/imm32/subx-name -6303 0/imm32/no-rm32 -6304 0/imm32/no-r32 -6305 0/imm32/no-imm32 -6306 1/imm32/disp32-is-first-inout -6307 0/imm32/no-output -6308 _Primitive-loop-if-addr<-named/imm32/next -6309 _Primitive-loop-if-addr<-named: -6310 "loop-if-addr<"/imm32/name -6311 Single-lit-var/imm32/inouts -6312 0/imm32/outputs -6313 "0f 82/jump-if-addr<"/imm32/subx-name -6314 0/imm32/no-rm32 -6315 0/imm32/no-r32 -6316 0/imm32/no-imm32 -6317 1/imm32/disp32-is-first-inout -6318 0/imm32/no-output -6319 _Primitive-loop-if-addr>=-named/imm32/next -6320 _Primitive-loop-if-addr>=-named: -6321 "loop-if-addr>="/imm32/name -6322 Single-lit-var/imm32/inouts -6323 0/imm32/outputs -6324 "0f 83/jump-if-addr>="/imm32/subx-name -6325 0/imm32/no-rm32 -6326 0/imm32/no-r32 -6327 0/imm32/no-imm32 -6328 1/imm32/disp32-is-first-inout -6329 0/imm32/no-output -6330 _Primitive-loop-if-=-named/imm32/next -6331 _Primitive-loop-if-=-named: -6332 "loop-if-="/imm32/name -6333 Single-lit-var/imm32/inouts -6334 0/imm32/outputs -6335 "0f 84/jump-if-="/imm32/subx-name -6336 0/imm32/no-rm32 -6337 0/imm32/no-r32 -6338 0/imm32/no-imm32 -6339 1/imm32/disp32-is-first-inout -6340 0/imm32/no-output -6341 _Primitive-loop-if-!=-named/imm32/next -6342 _Primitive-loop-if-!=-named: -6343 "loop-if-!="/imm32/name -6344 Single-lit-var/imm32/inouts -6345 0/imm32/outputs -6346 "0f 85/jump-if-!="/imm32/subx-name -6347 0/imm32/no-rm32 -6348 0/imm32/no-r32 -6349 0/imm32/no-imm32 -6350 1/imm32/disp32-is-first-inout -6351 0/imm32/no-output -6352 _Primitive-loop-if-addr<=-named/imm32/next -6353 _Primitive-loop-if-addr<=-named: -6354 "loop-if-addr<="/imm32/name -6355 Single-lit-var/imm32/inouts -6356 0/imm32/outputs -6357 "0f 86/jump-if-addr<="/imm32/subx-name -6358 0/imm32/no-rm32 -6359 0/imm32/no-r32 -6360 0/imm32/no-imm32 -6361 1/imm32/disp32-is-first-inout -6362 0/imm32/no-output -6363 _Primitive-loop-if-addr>-named/imm32/next -6364 _Primitive-loop-if-addr>-named: -6365 "loop-if-addr>"/imm32/name -6366 Single-lit-var/imm32/inouts -6367 0/imm32/outputs -6368 "0f 87/jump-if-addr>"/imm32/subx-name -6369 0/imm32/no-rm32 -6370 0/imm32/no-r32 -6371 0/imm32/no-imm32 -6372 1/imm32/disp32-is-first-inout -6373 0/imm32/no-output -6374 _Primitive-loop-if-<-named/imm32/next -6375 _Primitive-loop-if-<-named: -6376 "loop-if-<"/imm32/name -6377 Single-lit-var/imm32/inouts -6378 0/imm32/outputs -6379 "0f 8c/jump-if-<"/imm32/subx-name -6380 0/imm32/no-rm32 -6381 0/imm32/no-r32 -6382 0/imm32/no-imm32 -6383 1/imm32/disp32-is-first-inout -6384 0/imm32/no-output -6385 _Primitive-loop-if->=-named/imm32/next -6386 _Primitive-loop-if->=-named: -6387 "loop-if->="/imm32/name -6388 Single-lit-var/imm32/inouts -6389 0/imm32/outputs -6390 "0f 8d/jump-if->="/imm32/subx-name -6391 0/imm32/no-rm32 -6392 0/imm32/no-r32 -6393 0/imm32/no-imm32 -6394 1/imm32/disp32-is-first-inout -6395 0/imm32/no-output -6396 _Primitive-loop-if-<=-named/imm32/next -6397 _Primitive-loop-if-<=-named: -6398 "loop-if-<="/imm32/name -6399 Single-lit-var/imm32/inouts -6400 0/imm32/outputs -6401 "0f 8e/jump-if-<="/imm32/subx-name -6402 0/imm32/no-rm32 -6403 0/imm32/no-r32 -6404 0/imm32/no-imm32 -6405 1/imm32/disp32-is-first-inout -6406 0/imm32/no-output -6407 _Primitive-loop-if->-named/imm32/next -6408 _Primitive-loop-if->-named: -6409 "loop-if->"/imm32/name -6410 Single-lit-var/imm32/inouts -6411 0/imm32/outputs -6412 "0f 8f/jump-if->"/imm32/subx-name -6413 0/imm32/no-rm32 -6414 0/imm32/no-r32 -6415 0/imm32/no-imm32 -6416 1/imm32/disp32-is-first-inout -6417 0/imm32/no-output -6418 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break -6419 _Primitive-loop-named: -6420 "loop"/imm32/name -6421 Single-lit-var/imm32/inouts -6422 0/imm32/outputs -6423 "e9/jump"/imm32/subx-name -6424 0/imm32/no-rm32 -6425 0/imm32/no-r32 -6426 0/imm32/no-imm32 -6427 1/imm32/disp32-is-first-inout -6428 0/imm32/no-output -6429 0/imm32/next -6430 -6431 Single-int-var-on-stack: -6432 Int-var-on-stack/imm32 -6433 0/imm32/next -6434 -6435 Int-var-on-stack: -6436 "arg1"/imm32/name -6437 Type-int/imm32 -6438 1/imm32/some-block-depth -6439 1/imm32/some-stack-offset -6440 0/imm32/no-register -6441 -6442 Two-args-int-stack-int-reg: -6443 Int-var-on-stack/imm32 -6444 Single-int-var-in-some-register/imm32/next -6445 -6446 Two-args-int-reg-int-stack: -6447 Int-var-in-some-register/imm32 -6448 Single-int-var-on-stack/imm32/next -6449 -6450 Two-args-int-eax-int-literal: -6451 Int-var-in-eax/imm32 -6452 Single-lit-var/imm32/next -6453 -6454 Int-var-and-literal: -6455 Int-var-on-stack/imm32 -6456 Single-lit-var/imm32/next -6457 -6458 Single-int-var-in-some-register: -6459 Int-var-in-some-register/imm32 -6460 0/imm32/next -6461 -6462 Int-var-in-some-register: -6463 "arg1"/imm32/name -6464 Type-int/imm32 -6465 1/imm32/some-block-depth -6466 0/imm32/no-stack-offset -6467 "*"/imm32/register -6468 -6469 Single-int-var-in-eax: -6470 Int-var-in-eax/imm32 -6471 0/imm32/next -6472 -6473 Int-var-in-eax: -6474 "arg1"/imm32/name -6475 Type-int/imm32 -6476 1/imm32/some-block-depth -6477 0/imm32/no-stack-offset -6478 "eax"/imm32/register -6479 -6480 Single-int-var-in-ecx: -6481 Int-var-in-ecx/imm32 -6482 0/imm32/next -6483 -6484 Int-var-in-ecx: -6485 "arg1"/imm32/name -6486 Type-int/imm32 -6487 1/imm32/some-block-depth -6488 0/imm32/no-stack-offset -6489 "ecx"/imm32/register -6490 -6491 Single-int-var-in-edx: -6492 Int-var-in-edx/imm32 -6493 0/imm32/next -6494 -6495 Int-var-in-edx: -6496 "arg1"/imm32/name -6497 Type-int/imm32 -6498 1/imm32/some-block-depth -6499 0/imm32/no-stack-offset -6500 "edx"/imm32/register -6501 -6502 Single-int-var-in-ebx: -6503 Int-var-in-ebx/imm32 -6504 0/imm32/next -6505 -6506 Int-var-in-ebx: -6507 "arg1"/imm32/name -6508 Type-int/imm32 -6509 1/imm32/some-block-depth -6510 0/imm32/no-stack-offset -6511 "ebx"/imm32/register -6512 -6513 Single-int-var-in-esi: -6514 Int-var-in-esi/imm32 -6515 0/imm32/next -6516 -6517 Int-var-in-esi: -6518 "arg1"/imm32/name -6519 Type-int/imm32 -6520 1/imm32/some-block-depth -6521 0/imm32/no-stack-offset -6522 "esi"/imm32/register -6523 -6524 Single-int-var-in-edi: -6525 Int-var-in-edi/imm32 -6526 0/imm32/next -6527 -6528 Int-var-in-edi: -6529 "arg1"/imm32/name -6530 Type-int/imm32 -6531 1/imm32/some-block-depth -6532 0/imm32/no-stack-offset -6533 "edi"/imm32/register -6534 -6535 Single-lit-var: -6536 Lit-var/imm32 -6537 0/imm32/next -6538 -6539 Lit-var: -6540 "literal"/imm32/name -6541 Type-literal/imm32 -6542 1/imm32/some-block-depth -6543 0/imm32/no-stack-offset -6544 0/imm32/no-register -6545 -6546 Type-int: -6547 1/imm32/left/int -6548 0/imm32/right/null -6549 -6550 Type-literal: -6551 0/imm32/left/literal -6552 0/imm32/right/null -6553 -6554 == code -6555 emit-subx-primitive: # out: (addr buffered-file), stmt: (handle statement), primitive: (handle function) -6556 # . prologue -6557 55/push-ebp -6558 89/<- %ebp 4/r32/esp -6559 # . save registers -6560 50/push-eax -6561 51/push-ecx -6562 # ecx = primitive -6563 8b/-> *(ebp+0x10) 1/r32/ecx -6564 # emit primitive name -6565 (emit-indent *(ebp+8) *Curr-block-depth) -6566 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name -6567 # emit rm32 if necessary -6568 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt -6569 # emit r32 if necessary -6570 (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt -6571 # emit imm32 if necessary -6572 (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt -6573 # emit disp32 if necessary -6574 (emit-subx-disp32 *(ebp+8) *(ecx+0x1c) *(ebp+0xc)) # out, Primitive-subx-disp32, stmt -6575 (write-buffered *(ebp+8) Newline) -6576 $emit-subx-primitive:end: -6577 # . restore registers -6578 59/pop-to-ecx -6579 58/pop-to-eax -6580 # . epilogue -6581 89/<- %esp 5/r32/ebp -6582 5d/pop-to-ebp -6583 c3/return -6584 -6585 emit-subx-rm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6586 # . prologue -6587 55/push-ebp -6588 89/<- %ebp 4/r32/esp -6589 # . save registers -6590 50/push-eax -6591 # if (l == 0) return -6592 81 7/subop/compare *(ebp+0xc) 0/imm32 -6593 74/jump-if-= $emit-subx-rm32:end/disp8 -6594 # -6595 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -6596 (emit-subx-var-as-rm32 *(ebp+8) %eax) # out, var -6597 $emit-subx-rm32:end: -6598 # . restore registers -6599 58/pop-to-eax -6600 # . epilogue -6601 89/<- %esp 5/r32/ebp -6602 5d/pop-to-ebp -6603 c3/return -6604 -6605 get-stmt-operand-from-arg-location: # stmt: (handle statement), l: arg-location -> var/eax: (handle variable) -6606 # . prologue -6607 55/push-ebp -6608 89/<- %ebp 4/r32/esp -6609 # . save registers -6610 51/push-ecx -6611 # eax = l -6612 8b/-> *(ebp+0xc) 0/r32/eax -6613 # ecx = stmt -6614 8b/-> *(ebp+8) 1/r32/ecx -6615 # if (l == 1) return stmt->inouts->var -6616 { -6617 3d/compare-eax-and 1/imm32 -6618 75/jump-if-!= break/disp8 -6619 $get-stmt-operand-from-arg-location:1: -6620 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts -6621 8b/-> *eax 0/r32/eax # Operand-var -6622 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -6623 } -6624 # if (l == 2) return stmt->inouts->next->var -6625 { -6626 3d/compare-eax-and 2/imm32 -6627 75/jump-if-!= break/disp8 -6628 $get-stmt-operand-from-arg-location:2: -6629 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts -6630 8b/-> *(eax+4) 0/r32/eax # Operand-next -6631 8b/-> *eax 0/r32/eax # Operand-var -6632 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -6633 } -6634 # if (l == 3) return stmt->outputs -6635 { -6636 3d/compare-eax-and 3/imm32 -6637 75/jump-if-!= break/disp8 -6638 $get-stmt-operand-from-arg-location:3: -6639 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs -6640 8b/-> *eax 0/r32/eax # Operand-var -6641 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +5951 0/imm32/no-output +5952 _Primitive-break-if-<=/imm32/next +5953 _Primitive-break-if-<=: +5954 "break-if-<="/imm32/name +5955 0/imm32/inouts +5956 0/imm32/outputs +5957 "0f 8e/jump-if-<= break/disp32"/imm32/subx-name +5958 0/imm32/no-rm32 +5959 0/imm32/no-r32 +5960 0/imm32/no-imm32 +5961 0/imm32/no-disp32 +5962 0/imm32/no-output +5963 _Primitive-break-if->/imm32/next +5964 _Primitive-break-if->: +5965 "break-if->"/imm32/name +5966 0/imm32/inouts +5967 0/imm32/outputs +5968 "0f 8f/jump-if-> break/disp32"/imm32/subx-name +5969 0/imm32/no-rm32 +5970 0/imm32/no-r32 +5971 0/imm32/no-imm32 +5972 0/imm32/no-disp32 +5973 0/imm32/no-output +5974 _Primitive-loop-if-addr</imm32/next +5975 _Primitive-loop-if-addr<: +5976 "loop-if-addr<"/imm32/name +5977 0/imm32/inouts +5978 0/imm32/outputs +5979 "0f 82/jump-if-addr< loop/disp32"/imm32/subx-name +5980 0/imm32/no-rm32 +5981 0/imm32/no-r32 +5982 0/imm32/no-imm32 +5983 0/imm32/no-disp32 +5984 0/imm32/no-output +5985 _Primitive-loop-if-addr>=/imm32/next +5986 _Primitive-loop-if-addr>=: +5987 "loop-if-addr>="/imm32/name +5988 0/imm32/inouts +5989 0/imm32/outputs +5990 "0f 83/jump-if-addr>= loop/disp32"/imm32/subx-name +5991 0/imm32/no-rm32 +5992 0/imm32/no-r32 +5993 0/imm32/no-imm32 +5994 0/imm32/no-disp32 +5995 0/imm32/no-output +5996 _Primitive-loop-if-=/imm32/next +5997 _Primitive-loop-if-=: +5998 "loop-if-="/imm32/name +5999 0/imm32/inouts +6000 0/imm32/outputs +6001 "0f 84/jump-if-= loop/disp32"/imm32/subx-name +6002 0/imm32/no-rm32 +6003 0/imm32/no-r32 +6004 0/imm32/no-imm32 +6005 0/imm32/no-disp32 +6006 0/imm32/no-output +6007 _Primitive-loop-if-!=/imm32/next +6008 _Primitive-loop-if-!=: +6009 "loop-if-!="/imm32/name +6010 0/imm32/inouts +6011 0/imm32/outputs +6012 "0f 85/jump-if-!= loop/disp32"/imm32/subx-name +6013 0/imm32/no-rm32 +6014 0/imm32/no-r32 +6015 0/imm32/no-imm32 +6016 0/imm32/no-disp32 +6017 0/imm32/no-output +6018 _Primitive-loop-if-addr<=/imm32/next +6019 _Primitive-loop-if-addr<=: +6020 "loop-if-addr<="/imm32/name +6021 0/imm32/inouts +6022 0/imm32/outputs +6023 "0f 86/jump-if-addr<= loop/disp32"/imm32/subx-name +6024 0/imm32/no-rm32 +6025 0/imm32/no-r32 +6026 0/imm32/no-imm32 +6027 0/imm32/no-disp32 +6028 0/imm32/no-output +6029 _Primitive-loop-if-addr>/imm32/next +6030 _Primitive-loop-if-addr>: +6031 "loop-if-addr>"/imm32/name +6032 0/imm32/inouts +6033 0/imm32/outputs +6034 "0f 87/jump-if-addr> loop/disp32"/imm32/subx-name +6035 0/imm32/no-rm32 +6036 0/imm32/no-r32 +6037 0/imm32/no-imm32 +6038 0/imm32/no-disp32 +6039 0/imm32/no-output +6040 _Primitive-loop-if-</imm32/next +6041 _Primitive-loop-if-<: +6042 "loop-if-<"/imm32/name +6043 0/imm32/inouts +6044 0/imm32/outputs +6045 "0f 8c/jump-if-< loop/disp32"/imm32/subx-name +6046 0/imm32/no-rm32 +6047 0/imm32/no-r32 +6048 0/imm32/no-imm32 +6049 0/imm32/no-disp32 +6050 0/imm32/no-output +6051 _Primitive-loop-if->=/imm32/next +6052 _Primitive-loop-if->=: +6053 "loop-if->="/imm32/name +6054 0/imm32/inouts +6055 0/imm32/outputs +6056 "0f 8d/jump-if->= loop/disp32"/imm32/subx-name +6057 0/imm32/no-rm32 +6058 0/imm32/no-r32 +6059 0/imm32/no-imm32 +6060 0/imm32/no-disp32 +6061 0/imm32/no-output +6062 _Primitive-loop-if-<=/imm32/next +6063 _Primitive-loop-if-<=: +6064 "loop-if-<="/imm32/name +6065 0/imm32/inouts +6066 0/imm32/outputs +6067 "0f 8e/jump-if-<= loop/disp32"/imm32/subx-name +6068 0/imm32/no-rm32 +6069 0/imm32/no-r32 +6070 0/imm32/no-imm32 +6071 0/imm32/no-disp32 +6072 0/imm32/no-output +6073 _Primitive-loop-if->/imm32/next +6074 _Primitive-loop-if->: +6075 "loop-if->"/imm32/name +6076 0/imm32/inouts +6077 0/imm32/outputs +6078 "0f 8f/jump-if-> loop/disp32"/imm32/subx-name +6079 0/imm32/no-rm32 +6080 0/imm32/no-r32 +6081 0/imm32/no-imm32 +6082 0/imm32/no-disp32 +6083 0/imm32/no-output +6084 _Primitive-loop/imm32/next # we probably don't need an unconditional break +6085 _Primitive-loop: +6086 "loop"/imm32/name +6087 0/imm32/inouts +6088 0/imm32/outputs +6089 "e9/jump loop/disp32"/imm32/subx-name +6090 0/imm32/no-rm32 +6091 0/imm32/no-r32 +6092 0/imm32/no-imm32 +6093 0/imm32/no-disp32 +6094 0/imm32/no-output +6095 _Primitive-break-if-addr<-named/imm32/next +6096 # - branches to named blocks +6097 _Primitive-break-if-addr<-named: +6098 "break-if-addr<"/imm32/name +6099 Single-lit-var/imm32/inouts +6100 0/imm32/outputs +6101 "0f 82/jump-if-addr<"/imm32/subx-name +6102 0/imm32/no-rm32 +6103 0/imm32/no-r32 +6104 0/imm32/no-imm32 +6105 1/imm32/disp32-is-first-inout +6106 0/imm32/no-output +6107 _Primitive-break-if-addr>=-named/imm32/next +6108 _Primitive-break-if-addr>=-named: +6109 "break-if-addr>="/imm32/name +6110 Single-lit-var/imm32/inouts +6111 0/imm32/outputs +6112 "0f 83/jump-if-addr>="/imm32/subx-name +6113 0/imm32/no-rm32 +6114 0/imm32/no-r32 +6115 0/imm32/no-imm32 +6116 1/imm32/disp32-is-first-inout +6117 0/imm32/no-output +6118 _Primitive-break-if-=-named/imm32/next +6119 _Primitive-break-if-=-named: +6120 "break-if-="/imm32/name +6121 Single-lit-var/imm32/inouts +6122 0/imm32/outputs +6123 "0f 84/jump-if-="/imm32/subx-name +6124 0/imm32/no-rm32 +6125 0/imm32/no-r32 +6126 0/imm32/no-imm32 +6127 1/imm32/disp32-is-first-inout +6128 0/imm32/no-output +6129 _Primitive-break-if-!=-named/imm32/next +6130 _Primitive-break-if-!=-named: +6131 "break-if-!="/imm32/name +6132 Single-lit-var/imm32/inouts +6133 0/imm32/outputs +6134 "0f 85/jump-if-!="/imm32/subx-name +6135 0/imm32/no-rm32 +6136 0/imm32/no-r32 +6137 0/imm32/no-imm32 +6138 1/imm32/disp32-is-first-inout +6139 0/imm32/no-output +6140 _Primitive-break-if-addr<=-named/imm32/next +6141 _Primitive-break-if-addr<=-named: +6142 "break-if-addr<="/imm32/name +6143 Single-lit-var/imm32/inouts +6144 0/imm32/outputs +6145 "0f 86/jump-if-addr<="/imm32/subx-name +6146 0/imm32/no-rm32 +6147 0/imm32/no-r32 +6148 0/imm32/no-imm32 +6149 1/imm32/disp32-is-first-inout +6150 0/imm32/no-output +6151 _Primitive-break-if-addr>-named/imm32/next +6152 _Primitive-break-if-addr>-named: +6153 "break-if-addr>"/imm32/name +6154 Single-lit-var/imm32/inouts +6155 0/imm32/outputs +6156 "0f 87/jump-if-addr>"/imm32/subx-name +6157 0/imm32/no-rm32 +6158 0/imm32/no-r32 +6159 0/imm32/no-imm32 +6160 1/imm32/disp32-is-first-inout +6161 0/imm32/no-output +6162 _Primitive-break-if-<-named/imm32/next +6163 _Primitive-break-if-<-named: +6164 "break-if-<"/imm32/name +6165 Single-lit-var/imm32/inouts +6166 0/imm32/outputs +6167 "0f 8c/jump-if-<"/imm32/subx-name +6168 0/imm32/no-rm32 +6169 0/imm32/no-r32 +6170 0/imm32/no-imm32 +6171 1/imm32/disp32-is-first-inout +6172 0/imm32/no-output +6173 _Primitive-break-if->=-named/imm32/next +6174 _Primitive-break-if->=-named: +6175 "break-if->="/imm32/name +6176 Single-lit-var/imm32/inouts +6177 0/imm32/outputs +6178 "0f 8d/jump-if->="/imm32/subx-name +6179 0/imm32/no-rm32 +6180 0/imm32/no-r32 +6181 0/imm32/no-imm32 +6182 1/imm32/disp32-is-first-inout +6183 0/imm32/no-output +6184 _Primitive-break-if-<=-named/imm32/next +6185 _Primitive-break-if-<=-named: +6186 "break-if-<="/imm32/name +6187 Single-lit-var/imm32/inouts +6188 0/imm32/outputs +6189 "0f 8e/jump-if-<="/imm32/subx-name +6190 0/imm32/no-rm32 +6191 0/imm32/no-r32 +6192 0/imm32/no-imm32 +6193 1/imm32/disp32-is-first-inout +6194 0/imm32/no-output +6195 _Primitive-break-if->-named/imm32/next +6196 _Primitive-break-if->-named: +6197 "break-if->"/imm32/name +6198 Single-lit-var/imm32/inouts +6199 0/imm32/outputs +6200 "0f 8f/jump-if->"/imm32/subx-name +6201 0/imm32/no-rm32 +6202 0/imm32/no-r32 +6203 0/imm32/no-imm32 +6204 1/imm32/disp32-is-first-inout +6205 0/imm32/no-output +6206 _Primitive-loop-if-addr<-named/imm32/next +6207 _Primitive-loop-if-addr<-named: +6208 "loop-if-addr<"/imm32/name +6209 Single-lit-var/imm32/inouts +6210 0/imm32/outputs +6211 "0f 82/jump-if-addr<"/imm32/subx-name +6212 0/imm32/no-rm32 +6213 0/imm32/no-r32 +6214 0/imm32/no-imm32 +6215 1/imm32/disp32-is-first-inout +6216 0/imm32/no-output +6217 _Primitive-loop-if-addr>=-named/imm32/next +6218 _Primitive-loop-if-addr>=-named: +6219 "loop-if-addr>="/imm32/name +6220 Single-lit-var/imm32/inouts +6221 0/imm32/outputs +6222 "0f 83/jump-if-addr>="/imm32/subx-name +6223 0/imm32/no-rm32 +6224 0/imm32/no-r32 +6225 0/imm32/no-imm32 +6226 1/imm32/disp32-is-first-inout +6227 0/imm32/no-output +6228 _Primitive-loop-if-=-named/imm32/next +6229 _Primitive-loop-if-=-named: +6230 "loop-if-="/imm32/name +6231 Single-lit-var/imm32/inouts +6232 0/imm32/outputs +6233 "0f 84/jump-if-="/imm32/subx-name +6234 0/imm32/no-rm32 +6235 0/imm32/no-r32 +6236 0/imm32/no-imm32 +6237 1/imm32/disp32-is-first-inout +6238 0/imm32/no-output +6239 _Primitive-loop-if-!=-named/imm32/next +6240 _Primitive-loop-if-!=-named: +6241 "loop-if-!="/imm32/name +6242 Single-lit-var/imm32/inouts +6243 0/imm32/outputs +6244 "0f 85/jump-if-!="/imm32/subx-name +6245 0/imm32/no-rm32 +6246 0/imm32/no-r32 +6247 0/imm32/no-imm32 +6248 1/imm32/disp32-is-first-inout +6249 0/imm32/no-output +6250 _Primitive-loop-if-addr<=-named/imm32/next +6251 _Primitive-loop-if-addr<=-named: +6252 "loop-if-addr<="/imm32/name +6253 Single-lit-var/imm32/inouts +6254 0/imm32/outputs +6255 "0f 86/jump-if-addr<="/imm32/subx-name +6256 0/imm32/no-rm32 +6257 0/imm32/no-r32 +6258 0/imm32/no-imm32 +6259 1/imm32/disp32-is-first-inout +6260 0/imm32/no-output +6261 _Primitive-loop-if-addr>-named/imm32/next +6262 _Primitive-loop-if-addr>-named: +6263 "loop-if-addr>"/imm32/name +6264 Single-lit-var/imm32/inouts +6265 0/imm32/outputs +6266 "0f 87/jump-if-addr>"/imm32/subx-name +6267 0/imm32/no-rm32 +6268 0/imm32/no-r32 +6269 0/imm32/no-imm32 +6270 1/imm32/disp32-is-first-inout +6271 0/imm32/no-output +6272 _Primitive-loop-if-<-named/imm32/next +6273 _Primitive-loop-if-<-named: +6274 "loop-if-<"/imm32/name +6275 Single-lit-var/imm32/inouts +6276 0/imm32/outputs +6277 "0f 8c/jump-if-<"/imm32/subx-name +6278 0/imm32/no-rm32 +6279 0/imm32/no-r32 +6280 0/imm32/no-imm32 +6281 1/imm32/disp32-is-first-inout +6282 0/imm32/no-output +6283 _Primitive-loop-if->=-named/imm32/next +6284 _Primitive-loop-if->=-named: +6285 "loop-if->="/imm32/name +6286 Single-lit-var/imm32/inouts +6287 0/imm32/outputs +6288 "0f 8d/jump-if->="/imm32/subx-name +6289 0/imm32/no-rm32 +6290 0/imm32/no-r32 +6291 0/imm32/no-imm32 +6292 1/imm32/disp32-is-first-inout +6293 0/imm32/no-output +6294 _Primitive-loop-if-<=-named/imm32/next +6295 _Primitive-loop-if-<=-named: +6296 "loop-if-<="/imm32/name +6297 Single-lit-var/imm32/inouts +6298 0/imm32/outputs +6299 "0f 8e/jump-if-<="/imm32/subx-name +6300 0/imm32/no-rm32 +6301 0/imm32/no-r32 +6302 0/imm32/no-imm32 +6303 1/imm32/disp32-is-first-inout +6304 0/imm32/no-output +6305 _Primitive-loop-if->-named/imm32/next +6306 _Primitive-loop-if->-named: +6307 "loop-if->"/imm32/name +6308 Single-lit-var/imm32/inouts +6309 0/imm32/outputs +6310 "0f 8f/jump-if->"/imm32/subx-name +6311 0/imm32/no-rm32 +6312 0/imm32/no-r32 +6313 0/imm32/no-imm32 +6314 1/imm32/disp32-is-first-inout +6315 0/imm32/no-output +6316 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break +6317 _Primitive-loop-named: +6318 "loop"/imm32/name +6319 Single-lit-var/imm32/inouts +6320 0/imm32/outputs +6321 "e9/jump"/imm32/subx-name +6322 0/imm32/no-rm32 +6323 0/imm32/no-r32 +6324 0/imm32/no-imm32 +6325 1/imm32/disp32-is-first-inout +6326 0/imm32/no-output +6327 0/imm32/next +6328 +6329 Single-int-var-on-stack: +6330 Int-var-on-stack/imm32 +6331 0/imm32/next +6332 +6333 Int-var-on-stack: +6334 "arg1"/imm32/name +6335 Type-int/imm32 +6336 1/imm32/some-block-depth +6337 1/imm32/some-stack-offset +6338 0/imm32/no-register +6339 +6340 Two-args-int-stack-int-reg: +6341 Int-var-on-stack/imm32 +6342 Single-int-var-in-some-register/imm32/next +6343 +6344 Two-args-int-reg-int-stack: +6345 Int-var-in-some-register/imm32 +6346 Single-int-var-on-stack/imm32/next +6347 +6348 Two-args-int-eax-int-literal: +6349 Int-var-in-eax/imm32 +6350 Single-lit-var/imm32/next +6351 +6352 Int-var-and-literal: +6353 Int-var-on-stack/imm32 +6354 Single-lit-var/imm32/next +6355 +6356 Single-int-var-in-some-register: +6357 Int-var-in-some-register/imm32 +6358 0/imm32/next +6359 +6360 Int-var-in-some-register: +6361 "arg1"/imm32/name +6362 Type-int/imm32 +6363 1/imm32/some-block-depth +6364 0/imm32/no-stack-offset +6365 "*"/imm32/register +6366 +6367 Single-int-var-in-eax: +6368 Int-var-in-eax/imm32 +6369 0/imm32/next +6370 +6371 Int-var-in-eax: +6372 "arg1"/imm32/name +6373 Type-int/imm32 +6374 1/imm32/some-block-depth +6375 0/imm32/no-stack-offset +6376 "eax"/imm32/register +6377 +6378 Single-int-var-in-ecx: +6379 Int-var-in-ecx/imm32 +6380 0/imm32/next +6381 +6382 Int-var-in-ecx: +6383 "arg1"/imm32/name +6384 Type-int/imm32 +6385 1/imm32/some-block-depth +6386 0/imm32/no-stack-offset +6387 "ecx"/imm32/register +6388 +6389 Single-int-var-in-edx: +6390 Int-var-in-edx/imm32 +6391 0/imm32/next +6392 +6393 Int-var-in-edx: +6394 "arg1"/imm32/name +6395 Type-int/imm32 +6396 1/imm32/some-block-depth +6397 0/imm32/no-stack-offset +6398 "edx"/imm32/register +6399 +6400 Single-int-var-in-ebx: +6401 Int-var-in-ebx/imm32 +6402 0/imm32/next +6403 +6404 Int-var-in-ebx: +6405 "arg1"/imm32/name +6406 Type-int/imm32 +6407 1/imm32/some-block-depth +6408 0/imm32/no-stack-offset +6409 "ebx"/imm32/register +6410 +6411 Single-int-var-in-esi: +6412 Int-var-in-esi/imm32 +6413 0/imm32/next +6414 +6415 Int-var-in-esi: +6416 "arg1"/imm32/name +6417 Type-int/imm32 +6418 1/imm32/some-block-depth +6419 0/imm32/no-stack-offset +6420 "esi"/imm32/register +6421 +6422 Single-int-var-in-edi: +6423 Int-var-in-edi/imm32 +6424 0/imm32/next +6425 +6426 Int-var-in-edi: +6427 "arg1"/imm32/name +6428 Type-int/imm32 +6429 1/imm32/some-block-depth +6430 0/imm32/no-stack-offset +6431 "edi"/imm32/register +6432 +6433 Single-lit-var: +6434 Lit-var/imm32 +6435 0/imm32/next +6436 +6437 Lit-var: +6438 "literal"/imm32/name +6439 Type-literal/imm32 +6440 1/imm32/some-block-depth +6441 0/imm32/no-stack-offset +6442 0/imm32/no-register +6443 +6444 Type-int: +6445 1/imm32/left/int +6446 0/imm32/right/null +6447 +6448 Type-literal: +6449 0/imm32/left/literal +6450 0/imm32/right/null +6451 +6452 == code +6453 emit-subx-primitive: # out: (addr buffered-file), stmt: (handle statement), primitive: (handle function) +6454 # . prologue +6455 55/push-ebp +6456 89/<- %ebp 4/r32/esp +6457 # . save registers +6458 50/push-eax +6459 51/push-ecx +6460 # ecx = primitive +6461 8b/-> *(ebp+0x10) 1/r32/ecx +6462 # emit primitive name +6463 (emit-indent *(ebp+8) *Curr-block-depth) +6464 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name +6465 # emit rm32 if necessary +6466 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt +6467 # emit r32 if necessary +6468 (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt +6469 # emit imm32 if necessary +6470 (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt +6471 # emit disp32 if necessary +6472 (emit-subx-disp32 *(ebp+8) *(ecx+0x1c) *(ebp+0xc)) # out, Primitive-subx-disp32, stmt +6473 (write-buffered *(ebp+8) Newline) +6474 $emit-subx-primitive:end: +6475 # . restore registers +6476 59/pop-to-ecx +6477 58/pop-to-eax +6478 # . epilogue +6479 89/<- %esp 5/r32/ebp +6480 5d/pop-to-ebp +6481 c3/return +6482 +6483 emit-subx-rm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) +6484 # . prologue +6485 55/push-ebp +6486 89/<- %ebp 4/r32/esp +6487 # . save registers +6488 50/push-eax +6489 # if (l == 0) return +6490 81 7/subop/compare *(ebp+0xc) 0/imm32 +6491 74/jump-if-= $emit-subx-rm32:end/disp8 +6492 # +6493 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax +6494 (emit-subx-var-as-rm32 *(ebp+8) %eax) # out, var +6495 $emit-subx-rm32:end: +6496 # . restore registers +6497 58/pop-to-eax +6498 # . epilogue +6499 89/<- %esp 5/r32/ebp +6500 5d/pop-to-ebp +6501 c3/return +6502 +6503 get-stmt-operand-from-arg-location: # stmt: (handle statement), l: arg-location -> var/eax: (handle variable) +6504 # . prologue +6505 55/push-ebp +6506 89/<- %ebp 4/r32/esp +6507 # . save registers +6508 51/push-ecx +6509 # eax = l +6510 8b/-> *(ebp+0xc) 0/r32/eax +6511 # ecx = stmt +6512 8b/-> *(ebp+8) 1/r32/ecx +6513 # if (l == 1) return stmt->inouts->var +6514 { +6515 3d/compare-eax-and 1/imm32 +6516 75/jump-if-!= break/disp8 +6517 $get-stmt-operand-from-arg-location:1: +6518 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts +6519 8b/-> *eax 0/r32/eax # Operand-var +6520 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +6521 } +6522 # if (l == 2) return stmt->inouts->next->var +6523 { +6524 3d/compare-eax-and 2/imm32 +6525 75/jump-if-!= break/disp8 +6526 $get-stmt-operand-from-arg-location:2: +6527 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts +6528 8b/-> *(eax+4) 0/r32/eax # Operand-next +6529 8b/-> *eax 0/r32/eax # Operand-var +6530 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +6531 } +6532 # if (l == 3) return stmt->outputs +6533 { +6534 3d/compare-eax-and 3/imm32 +6535 75/jump-if-!= break/disp8 +6536 $get-stmt-operand-from-arg-location:3: +6537 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs +6538 8b/-> *eax 0/r32/eax # Operand-var +6539 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +6540 } +6541 # abort +6542 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 +6543 $get-stmt-operand-from-arg-location:end: +6544 # . restore registers +6545 59/pop-to-ecx +6546 # . epilogue +6547 89/<- %esp 5/r32/ebp +6548 5d/pop-to-ebp +6549 c3/return +6550 +6551 $get-stmt-operand-from-arg-location:abort: +6552 # error("invalid arg-location " eax) +6553 (write-buffered Stderr "invalid arg-location ") +6554 (print-int32-buffered Stderr %eax) +6555 (write-buffered Stderr Newline) +6556 (flush Stderr) +6557 # . syscall(exit, 1) +6558 bb/copy-to-ebx 1/imm32 +6559 b8/copy-to-eax 1/imm32/exit +6560 cd/syscall 0x80/imm8 +6561 # never gets here +6562 +6563 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) +6564 # . prologue +6565 55/push-ebp +6566 89/<- %ebp 4/r32/esp +6567 # . save registers +6568 50/push-eax +6569 51/push-ecx +6570 # if (location == 0) return +6571 81 7/subop/compare *(ebp+0xc) 0/imm32 +6572 0f 84/jump-if-= $emit-subx-r32:end/disp32 +6573 # +6574 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax +6575 (maybe-get Registers *(eax+0x10) 8) # Var-register => eax: (addr register-index) +6576 (write-buffered *(ebp+8) Space) +6577 (print-int32-buffered *(ebp+8) *eax) +6578 (write-buffered *(ebp+8) "/r32") +6579 $emit-subx-r32:end: +6580 # . restore registers +6581 59/pop-to-ecx +6582 58/pop-to-eax +6583 # . epilogue +6584 89/<- %esp 5/r32/ebp +6585 5d/pop-to-ebp +6586 c3/return +6587 +6588 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) +6589 # . prologue +6590 55/push-ebp +6591 89/<- %ebp 4/r32/esp +6592 # . save registers +6593 50/push-eax +6594 51/push-ecx +6595 # if (location == 0) return +6596 81 7/subop/compare *(ebp+0xc) 0/imm32 +6597 74/jump-if-= $emit-subx-imm32:end/disp8 +6598 # +6599 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax +6600 (write-buffered *(ebp+8) Space) +6601 (write-buffered *(ebp+8) *eax) # Var-name +6602 (write-buffered *(ebp+8) "/imm32") +6603 $emit-subx-imm32:end: +6604 # . restore registers +6605 59/pop-to-ecx +6606 58/pop-to-eax +6607 # . epilogue +6608 89/<- %esp 5/r32/ebp +6609 5d/pop-to-ebp +6610 c3/return +6611 +6612 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) +6613 # . prologue +6614 55/push-ebp +6615 89/<- %ebp 4/r32/esp +6616 # . save registers +6617 50/push-eax +6618 51/push-ecx +6619 # if (location == 0) return +6620 81 7/subop/compare *(ebp+0xc) 0/imm32 +6621 0f 84/jump-if-= $emit-subx-disp32:end/disp32 +6622 # +6623 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax +6624 (write-buffered *(ebp+8) Space) +6625 (write-buffered *(ebp+8) *eax) # Var-name +6626 # hack: if instruction operation starts with "break", emit ":break" +6627 # var name/ecx: (addr array byte) = stmt->operation +6628 8b/-> *(ebp+0x10) 0/r32/eax +6629 8b/-> *(eax+4) 1/r32/ecx +6630 { +6631 (string-starts-with? %ecx "break") # => eax +6632 3d/compare-eax-and 0/imm32 +6633 74/jump-if-= break/disp8 +6634 (write-buffered *(ebp+8) ":break") +6635 } +6636 # hack: if instruction operation starts with "loop", emit ":loop" +6637 { +6638 (string-starts-with? %ecx "loop") # => eax +6639 3d/compare-eax-and 0/imm32 +6640 74/jump-if-= break/disp8 +6641 (write-buffered *(ebp+8) ":loop") 6642 } -6643 # abort -6644 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 -6645 $get-stmt-operand-from-arg-location:end: -6646 # . restore registers -6647 59/pop-to-ecx +6643 (write-buffered *(ebp+8) "/disp32") +6644 $emit-subx-disp32:end: +6645 # . restore registers +6646 59/pop-to-ecx +6647 58/pop-to-eax 6648 # . epilogue 6649 89/<- %esp 5/r32/ebp 6650 5d/pop-to-ebp 6651 c3/return 6652 -6653 $get-stmt-operand-from-arg-location:abort: -6654 # error("invalid arg-location " eax) -6655 (write-buffered Stderr "invalid arg-location ") -6656 (print-int32-buffered Stderr %eax) -6657 (write-buffered Stderr Newline) -6658 (flush Stderr) -6659 # . syscall(exit, 1) -6660 bb/copy-to-ebx 1/imm32 -6661 b8/copy-to-eax 1/imm32/exit -6662 cd/syscall 0x80/imm8 -6663 # never gets here -6664 -6665 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6666 # . prologue -6667 55/push-ebp -6668 89/<- %ebp 4/r32/esp -6669 # . save registers -6670 50/push-eax -6671 51/push-ecx -6672 # if (location == 0) return -6673 81 7/subop/compare *(ebp+0xc) 0/imm32 -6674 0f 84/jump-if-= $emit-subx-r32:end/disp32 -6675 # -6676 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -6677 (maybe-get Registers *(eax+0x10) 8) # Var-register => eax: (addr register-index) -6678 (write-buffered *(ebp+8) Space) -6679 (print-int32-buffered *(ebp+8) *eax) -6680 (write-buffered *(ebp+8) "/r32") -6681 $emit-subx-r32:end: +6653 emit-subx-call: # out: (addr buffered-file), stmt: (handle statement), callee: (handle function) +6654 # . prologue +6655 55/push-ebp +6656 89/<- %ebp 4/r32/esp +6657 # . save registers +6658 51/push-ecx +6659 # +6660 (emit-indent *(ebp+8) *Curr-block-depth) +6661 (write-buffered *(ebp+8) "(") +6662 # - emit function name +6663 8b/-> *(ebp+0x10) 1/r32/ecx +6664 (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name +6665 # - emit arguments +6666 # var curr/ecx: (handle list var) = stmt->inouts +6667 8b/-> *(ebp+0xc) 1/r32/ecx +6668 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts +6669 { +6670 # if (curr == null) break +6671 81 7/subop/compare %ecx 0/imm32 +6672 74/jump-if-= break/disp8 +6673 # +6674 (emit-subx-call-operand *(ebp+8) *ecx) +6675 # curr = curr->next +6676 8b/-> *(ecx+4) 1/r32/ecx +6677 eb/jump loop/disp8 +6678 } +6679 # +6680 (write-buffered *(ebp+8) ")\n") +6681 $emit-subx-call:end: 6682 # . restore registers 6683 59/pop-to-ecx -6684 58/pop-to-eax -6685 # . epilogue -6686 89/<- %esp 5/r32/ebp -6687 5d/pop-to-ebp -6688 c3/return -6689 -6690 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6691 # . prologue -6692 55/push-ebp -6693 89/<- %ebp 4/r32/esp -6694 # . save registers -6695 50/push-eax +6684 # . epilogue +6685 89/<- %esp 5/r32/ebp +6686 5d/pop-to-ebp +6687 c3/return +6688 +6689 # like a function call, except we have no idea what function it is +6690 # we hope it's defined in SubX and that the types are ok +6691 emit-hailmary-call: # out: (addr buffered-file), stmt: (handle statement) +6692 # . prologue +6693 55/push-ebp +6694 89/<- %ebp 4/r32/esp +6695 # . save registers 6696 51/push-ecx -6697 # if (location == 0) return -6698 81 7/subop/compare *(ebp+0xc) 0/imm32 -6699 74/jump-if-= $emit-subx-imm32:end/disp8 -6700 # -6701 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -6702 (write-buffered *(ebp+8) Space) -6703 (write-buffered *(ebp+8) *eax) # Var-name -6704 (write-buffered *(ebp+8) "/imm32") -6705 $emit-subx-imm32:end: -6706 # . restore registers -6707 59/pop-to-ecx -6708 58/pop-to-eax -6709 # . epilogue -6710 89/<- %esp 5/r32/ebp -6711 5d/pop-to-ebp -6712 c3/return -6713 -6714 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6715 # . prologue -6716 55/push-ebp -6717 89/<- %ebp 4/r32/esp -6718 # . save registers -6719 50/push-eax -6720 51/push-ecx -6721 # if (location == 0) return -6722 81 7/subop/compare *(ebp+0xc) 0/imm32 -6723 0f 84/jump-if-= $emit-subx-disp32:end/disp32 -6724 # -6725 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -6726 (write-buffered *(ebp+8) Space) -6727 (write-buffered *(ebp+8) *eax) # Var-name -6728 # hack: if instruction operation starts with "break", emit ":break" -6729 # var name/ecx: (addr array byte) = stmt->operation -6730 8b/-> *(ebp+0x10) 0/r32/eax -6731 8b/-> *(eax+4) 1/r32/ecx -6732 { -6733 (string-starts-with? %ecx "break") # => eax -6734 3d/compare-eax-and 0/imm32 -6735 74/jump-if-= break/disp8 -6736 (write-buffered *(ebp+8) ":break") -6737 } -6738 # hack: if instruction operation starts with "loop", emit ":loop" -6739 { -6740 (string-starts-with? %ecx "loop") # => eax -6741 3d/compare-eax-and 0/imm32 -6742 74/jump-if-= break/disp8 -6743 (write-buffered *(ebp+8) ":loop") +6697 # +6698 (emit-indent *(ebp+8) *Curr-block-depth) +6699 (write-buffered *(ebp+8) "(") +6700 # ecx = stmt +6701 8b/-> *(ebp+0xc) 1/r32/ecx +6702 # - emit function name +6703 (write-buffered *(ebp+8) *(ecx+4)) # Stmt1-operation +6704 # - emit arguments +6705 # var curr/ecx: (handle list var) = stmt->inouts +6706 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts +6707 { +6708 # if (curr == null) break +6709 81 7/subop/compare %ecx 0/imm32 +6710 74/jump-if-= break/disp8 +6711 # +6712 (emit-subx-call-operand *(ebp+8) *ecx) +6713 # curr = curr->next +6714 8b/-> *(ecx+4) 1/r32/ecx +6715 eb/jump loop/disp8 +6716 } +6717 # +6718 (write-buffered *(ebp+8) ")\n") +6719 $emit-hailmary-call:end: +6720 # . restore registers +6721 59/pop-to-ecx +6722 # . epilogue +6723 89/<- %esp 5/r32/ebp +6724 5d/pop-to-ebp +6725 c3/return +6726 +6727 emit-subx-call-operand: # out: (addr buffered-file), operand: (handle variable) +6728 # shares code with emit-subx-var-as-rm32 +6729 # . prologue +6730 55/push-ebp +6731 89/<- %ebp 4/r32/esp +6732 # . save registers +6733 50/push-eax +6734 # eax = operand +6735 8b/-> *(ebp+0xc) 0/r32/eax +6736 # if (operand->register) emit "%__" +6737 { +6738 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register +6739 74/jump-if-= break/disp8 +6740 $emit-subx-call-operand:register: +6741 (write-buffered *(ebp+8) " %") +6742 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register +6743 e9/jump $emit-subx-call-operand:end/disp32 6744 } -6745 (write-buffered *(ebp+8) "/disp32") -6746 $emit-subx-disp32:end: -6747 # . restore registers -6748 59/pop-to-ecx -6749 58/pop-to-eax -6750 # . epilogue -6751 89/<- %esp 5/r32/ebp -6752 5d/pop-to-ebp -6753 c3/return -6754 -6755 emit-subx-call: # out: (addr buffered-file), stmt: (handle statement), callee: (handle function) -6756 # . prologue -6757 55/push-ebp -6758 89/<- %ebp 4/r32/esp -6759 # . save registers -6760 50/push-eax -6761 51/push-ecx -6762 # -6763 (emit-indent *(ebp+8) *Curr-block-depth) -6764 (write-buffered *(ebp+8) "(") -6765 # - emit function name -6766 8b/-> *(ebp+0x10) 1/r32/ecx -6767 (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name -6768 # - emit arguments -6769 # var curr/ecx: (handle list var) = stmt->inouts -6770 8b/-> *(ebp+0xc) 1/r32/ecx -6771 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts -6772 { -6773 # if (curr == null) break -6774 81 7/subop/compare %ecx 0/imm32 -6775 74/jump-if-= break/disp8 -6776 # -6777 (emit-subx-call-operand *(ebp+8) *ecx) -6778 # curr = curr->next -6779 8b/-> *(ecx+4) 1/r32/ecx -6780 eb/jump loop/disp8 -6781 } -6782 # -6783 (write-buffered *(ebp+8) ")\n") -6784 $emit-subx-call:end: -6785 # . restore registers -6786 59/pop-to-ecx -6787 58/pop-to-eax -6788 # . epilogue -6789 89/<- %esp 5/r32/ebp -6790 5d/pop-to-ebp -6791 c3/return -6792 -6793 emit-subx-call-operand: # out: (addr buffered-file), operand: (handle variable) -6794 # shares code with emit-subx-var-as-rm32 -6795 # . prologue -6796 55/push-ebp -6797 89/<- %ebp 4/r32/esp -6798 # . save registers -6799 50/push-eax -6800 # eax = operand -6801 8b/-> *(ebp+0xc) 0/r32/eax -6802 # if (operand->register) emit "%__" -6803 { -6804 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -6805 74/jump-if-= break/disp8 -6806 $emit-subx-call-operand:register: -6807 (write-buffered *(ebp+8) " %") -6808 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register -6809 e9/jump $emit-subx-call-operand:end/disp32 -6810 } -6811 # else if (operand->stack-offset) emit "*(ebp+__)" -6812 { -6813 81 7/subop/compare *(eax+0xc) 0/imm32 # Var-stack-offset -6814 74/jump-if-= break/disp8 -6815 $emit-subx-call-operand:stack: -6816 (write-buffered *(ebp+8) Space) -6817 (write-buffered *(ebp+8) "*(ebp+") -6818 8b/-> *(ebp+0xc) 0/r32/eax -6819 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-stack-offset -6820 (write-buffered *(ebp+8) ")") -6821 e9/jump $emit-subx-call-operand:end/disp32 -6822 } -6823 # else if (operand->type == literal) emit "__" -6824 { -6825 50/push-eax -6826 8b/-> *(eax+4) 0/r32/eax # Var-type -6827 81 7/subop/compare *eax 0/imm32 # Tree-left -6828 58/pop-to-eax -6829 75/jump-if-!= break/disp8 -6830 $emit-subx-call-operand:literal: -6831 (write-buffered *(ebp+8) Space) -6832 (write-buffered *(ebp+8) *eax) -6833 } -6834 $emit-subx-call-operand:end: -6835 # . restore registers -6836 58/pop-to-eax -6837 # . epilogue -6838 89/<- %esp 5/r32/ebp -6839 5d/pop-to-ebp -6840 c3/return -6841 -6842 emit-subx-var-as-rm32: # out: (addr buffered-file), operand: (handle variable) -6843 # . prologue -6844 55/push-ebp -6845 89/<- %ebp 4/r32/esp -6846 # . save registers -6847 50/push-eax -6848 # eax = operand -6849 8b/-> *(ebp+0xc) 0/r32/eax -6850 # if (operand->register) emit "%__" -6851 { -6852 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -6853 74/jump-if-= break/disp8 -6854 $emit-subx-var-as-rm32:register: -6855 (write-buffered *(ebp+8) " %") -6856 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register -6857 } -6858 # else if (operand->stack-offset) emit "*(ebp+__)" -6859 { -6860 81 7/subop/compare *(eax+0xc) 0/imm32 # Var-stack-offset -6861 74/jump-if-= break/disp8 -6862 $emit-subx-var-as-rm32:stack: -6863 (write-buffered *(ebp+8) Space) -6864 (write-buffered *(ebp+8) "*(ebp+") -6865 8b/-> *(ebp+0xc) 0/r32/eax -6866 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-stack-offset -6867 (write-buffered *(ebp+8) ")") -6868 } -6869 $emit-subx-var-as-rm32:end: -6870 # . restore registers -6871 58/pop-to-eax -6872 # . epilogue -6873 89/<- %esp 5/r32/ebp -6874 5d/pop-to-ebp -6875 c3/return -6876 -6877 find-matching-function: # functions: (addr function), stmt: (handle statement) -> result/eax: (handle function) -6878 # . prologue -6879 55/push-ebp -6880 89/<- %ebp 4/r32/esp -6881 # . save registers -6882 51/push-ecx -6883 # var curr/ecx: (handle function) = functions -6884 8b/-> *(ebp+8) 1/r32/ecx -6885 { -6886 # if (curr == null) break -6887 81 7/subop/compare %ecx 0/imm32 -6888 74/jump-if-= break/disp8 -6889 # if match(stmt, curr) return curr -6890 { -6891 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax -6892 3d/compare-eax-and 0/imm32 -6893 74/jump-if-= break/disp8 -6894 89/<- %eax 1/r32/ecx -6895 eb/jump $find-matching-function:end/disp8 -6896 } -6897 # curr = curr->next -6898 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next -6899 eb/jump loop/disp8 -6900 } -6901 # return null -6902 b8/copy-to-eax 0/imm32 -6903 $find-matching-function:end: -6904 # . restore registers -6905 59/pop-to-ecx -6906 # . epilogue -6907 89/<- %esp 5/r32/ebp -6908 5d/pop-to-ebp -6909 c3/return -6910 -6911 find-matching-primitive: # primitives: (handle primitive), stmt: (handle statement) -> result/eax: (handle primitive) -6912 # . prologue -6913 55/push-ebp -6914 89/<- %ebp 4/r32/esp -6915 # . save registers -6916 51/push-ecx -6917 # var curr/ecx: (handle primitive) = primitives -6918 8b/-> *(ebp+8) 1/r32/ecx -6919 { -6920 $find-matching-primitive:loop: -6921 # if (curr == null) break -6922 81 7/subop/compare %ecx 0/imm32 -6923 0f 84/jump-if-= break/disp32 -6924 #? (write-buffered Stderr "prim: ") -6925 #? (write-buffered Stderr *ecx) # Primitive-name -6926 #? (write-buffered Stderr " => ") -6927 #? (write-buffered Stderr *(ecx+0xc)) # Primitive-subx-name -6928 #? (write-buffered Stderr Newline) -6929 #? (flush Stderr) -6930 # if match(curr, stmt) return curr -6931 { -6932 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax -6933 3d/compare-eax-and 0/imm32 -6934 74/jump-if-= break/disp8 -6935 89/<- %eax 1/r32/ecx -6936 eb/jump $find-matching-primitive:end/disp8 -6937 } -6938 $find-matching-primitive:next-primitive: -6939 # curr = curr->next -6940 8b/-> *(ecx+0x24) 1/r32/ecx # Primitive-next -6941 e9/jump loop/disp32 -6942 } -6943 # return null -6944 b8/copy-to-eax 0/imm32 -6945 $find-matching-primitive:end: -6946 # . restore registers -6947 59/pop-to-ecx -6948 # . epilogue -6949 89/<- %esp 5/r32/ebp -6950 5d/pop-to-ebp -6951 c3/return -6952 -6953 mu-stmt-matches-function?: # stmt: (handle statement), function: (handle function) => result/eax: boolean -6954 # . prologue -6955 55/push-ebp -6956 89/<- %ebp 4/r32/esp -6957 # . save registers -6958 51/push-ecx -6959 # return function->name == stmt->operation -6960 8b/-> *(ebp+8) 1/r32/ecx -6961 8b/-> *(ebp+0xc) 0/r32/eax -6962 (string-equal? *(ecx+4) *eax) # Stmt1-operation, Function-name => eax -6963 $mu-stmt-matches-function?:end: -6964 # . restore registers -6965 59/pop-to-ecx -6966 # . epilogue -6967 89/<- %esp 5/r32/ebp -6968 5d/pop-to-ebp -6969 c3/return -6970 -6971 mu-stmt-matches-primitive?: # stmt: (handle statement), primitive: (handle primitive) => result/eax: boolean -6972 # A mu stmt matches a primitive if the name matches, all the inout vars -6973 # match, and all the output vars match. -6974 # Vars match if types match and registers match. -6975 # In addition, a stmt output matches a primitive's output if types match -6976 # and the primitive has a wildcard register. -6977 # . prologue -6978 55/push-ebp -6979 89/<- %ebp 4/r32/esp -6980 # . save registers -6981 51/push-ecx -6982 52/push-edx -6983 53/push-ebx -6984 56/push-esi -6985 57/push-edi -6986 # ecx = stmt -6987 8b/-> *(ebp+8) 1/r32/ecx -6988 # edx = primitive -6989 8b/-> *(ebp+0xc) 2/r32/edx -6990 { -6991 $mu-stmt-matches-primitive?:check-name: -6992 # if (primitive->name != stmt->operation) return false -6993 (string-equal? *(ecx+4) *edx) # Stmt1-operation, Primitive-name => eax -6994 3d/compare-eax-and 0/imm32 -6995 75/jump-if-!= break/disp8 -6996 b8/copy-to-eax 0/imm32 -6997 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6998 } -6999 $mu-stmt-matches-primitive?:check-inouts: -7000 # for (curr/esi in stmt->inouts, curr2/edi in primitive->inouts) -7001 8b/-> *(ecx+8) 6/r32/esi # Stmt1-inouts -7002 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts -7003 { -7004 # if (curr == 0 && curr2 == 0) move on to check outputs -7005 { -7006 81 7/subop/compare %esi 0/imm32 +6745 # else if (operand->stack-offset) emit "*(ebp+__)" +6746 { +6747 81 7/subop/compare *(eax+0xc) 0/imm32 # Var-stack-offset +6748 74/jump-if-= break/disp8 +6749 $emit-subx-call-operand:stack: +6750 (write-buffered *(ebp+8) Space) +6751 (write-buffered *(ebp+8) "*(ebp+") +6752 8b/-> *(ebp+0xc) 0/r32/eax +6753 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-stack-offset +6754 (write-buffered *(ebp+8) ")") +6755 e9/jump $emit-subx-call-operand:end/disp32 +6756 } +6757 # else if (operand->type == literal) emit "__" +6758 { +6759 50/push-eax +6760 8b/-> *(eax+4) 0/r32/eax # Var-type +6761 81 7/subop/compare *eax 0/imm32 # Tree-left +6762 58/pop-to-eax +6763 75/jump-if-!= break/disp8 +6764 $emit-subx-call-operand:literal: +6765 (write-buffered *(ebp+8) Space) +6766 (write-buffered *(ebp+8) *eax) +6767 } +6768 $emit-subx-call-operand:end: +6769 # . restore registers +6770 58/pop-to-eax +6771 # . epilogue +6772 89/<- %esp 5/r32/ebp +6773 5d/pop-to-ebp +6774 c3/return +6775 +6776 emit-subx-var-as-rm32: # out: (addr buffered-file), operand: (handle variable) +6777 # . prologue +6778 55/push-ebp +6779 89/<- %ebp 4/r32/esp +6780 # . save registers +6781 50/push-eax +6782 # eax = operand +6783 8b/-> *(ebp+0xc) 0/r32/eax +6784 # if (operand->register) emit "%__" +6785 { +6786 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register +6787 74/jump-if-= break/disp8 +6788 $emit-subx-var-as-rm32:register: +6789 (write-buffered *(ebp+8) " %") +6790 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register +6791 } +6792 # else if (operand->stack-offset) emit "*(ebp+__)" +6793 { +6794 81 7/subop/compare *(eax+0xc) 0/imm32 # Var-stack-offset +6795 74/jump-if-= break/disp8 +6796 $emit-subx-var-as-rm32:stack: +6797 (write-buffered *(ebp+8) Space) +6798 (write-buffered *(ebp+8) "*(ebp+") +6799 8b/-> *(ebp+0xc) 0/r32/eax +6800 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-stack-offset +6801 (write-buffered *(ebp+8) ")") +6802 } +6803 $emit-subx-var-as-rm32:end: +6804 # . restore registers +6805 58/pop-to-eax +6806 # . epilogue +6807 89/<- %esp 5/r32/ebp +6808 5d/pop-to-ebp +6809 c3/return +6810 +6811 find-matching-function: # functions: (addr function), stmt: (handle statement) -> result/eax: (handle function) +6812 # . prologue +6813 55/push-ebp +6814 89/<- %ebp 4/r32/esp +6815 # . save registers +6816 51/push-ecx +6817 # var curr/ecx: (handle function) = functions +6818 8b/-> *(ebp+8) 1/r32/ecx +6819 { +6820 # if (curr == null) break +6821 81 7/subop/compare %ecx 0/imm32 +6822 74/jump-if-= break/disp8 +6823 # if match(stmt, curr) return curr +6824 { +6825 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax +6826 3d/compare-eax-and 0/imm32 +6827 74/jump-if-= break/disp8 +6828 89/<- %eax 1/r32/ecx +6829 eb/jump $find-matching-function:end/disp8 +6830 } +6831 # curr = curr->next +6832 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next +6833 eb/jump loop/disp8 +6834 } +6835 # return null +6836 b8/copy-to-eax 0/imm32 +6837 $find-matching-function:end: +6838 # . restore registers +6839 59/pop-to-ecx +6840 # . epilogue +6841 89/<- %esp 5/r32/ebp +6842 5d/pop-to-ebp +6843 c3/return +6844 +6845 find-matching-primitive: # primitives: (handle primitive), stmt: (handle statement) -> result/eax: (handle primitive) +6846 # . prologue +6847 55/push-ebp +6848 89/<- %ebp 4/r32/esp +6849 # . save registers +6850 51/push-ecx +6851 # var curr/ecx: (handle primitive) = primitives +6852 8b/-> *(ebp+8) 1/r32/ecx +6853 { +6854 $find-matching-primitive:loop: +6855 # if (curr == null) break +6856 81 7/subop/compare %ecx 0/imm32 +6857 0f 84/jump-if-= break/disp32 +6858 #? (write-buffered Stderr "prim: ") +6859 #? (write-buffered Stderr *ecx) # Primitive-name +6860 #? (write-buffered Stderr " => ") +6861 #? (write-buffered Stderr *(ecx+0xc)) # Primitive-subx-name +6862 #? (write-buffered Stderr Newline) +6863 #? (flush Stderr) +6864 # if match(curr, stmt) return curr +6865 { +6866 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax +6867 3d/compare-eax-and 0/imm32 +6868 74/jump-if-= break/disp8 +6869 89/<- %eax 1/r32/ecx +6870 eb/jump $find-matching-primitive:end/disp8 +6871 } +6872 $find-matching-primitive:next-primitive: +6873 # curr = curr->next +6874 8b/-> *(ecx+0x24) 1/r32/ecx # Primitive-next +6875 e9/jump loop/disp32 +6876 } +6877 # return null +6878 b8/copy-to-eax 0/imm32 +6879 $find-matching-primitive:end: +6880 # . restore registers +6881 59/pop-to-ecx +6882 # . epilogue +6883 89/<- %esp 5/r32/ebp +6884 5d/pop-to-ebp +6885 c3/return +6886 +6887 mu-stmt-matches-function?: # stmt: (handle statement), function: (handle function) => result/eax: boolean +6888 # . prologue +6889 55/push-ebp +6890 89/<- %ebp 4/r32/esp +6891 # . save registers +6892 51/push-ecx +6893 # return function->name == stmt->operation +6894 8b/-> *(ebp+8) 1/r32/ecx +6895 8b/-> *(ebp+0xc) 0/r32/eax +6896 (string-equal? *(ecx+4) *eax) # Stmt1-operation, Function-name => eax +6897 $mu-stmt-matches-function?:end: +6898 # . restore registers +6899 59/pop-to-ecx +6900 # . epilogue +6901 89/<- %esp 5/r32/ebp +6902 5d/pop-to-ebp +6903 c3/return +6904 +6905 mu-stmt-matches-primitive?: # stmt: (handle statement), primitive: (handle primitive) => result/eax: boolean +6906 # A mu stmt matches a primitive if the name matches, all the inout vars +6907 # match, and all the output vars match. +6908 # Vars match if types match and registers match. +6909 # In addition, a stmt output matches a primitive's output if types match +6910 # and the primitive has a wildcard register. +6911 # . prologue +6912 55/push-ebp +6913 89/<- %ebp 4/r32/esp +6914 # . save registers +6915 51/push-ecx +6916 52/push-edx +6917 53/push-ebx +6918 56/push-esi +6919 57/push-edi +6920 # ecx = stmt +6921 8b/-> *(ebp+8) 1/r32/ecx +6922 # edx = primitive +6923 8b/-> *(ebp+0xc) 2/r32/edx +6924 { +6925 $mu-stmt-matches-primitive?:check-name: +6926 # if (primitive->name != stmt->operation) return false +6927 (string-equal? *(ecx+4) *edx) # Stmt1-operation, Primitive-name => eax +6928 3d/compare-eax-and 0/imm32 +6929 75/jump-if-!= break/disp8 +6930 b8/copy-to-eax 0/imm32 +6931 e9/jump $mu-stmt-matches-primitive?:end/disp32 +6932 } +6933 $mu-stmt-matches-primitive?:check-inouts: +6934 # for (curr/esi in stmt->inouts, curr2/edi in primitive->inouts) +6935 8b/-> *(ecx+8) 6/r32/esi # Stmt1-inouts +6936 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts +6937 { +6938 # if (curr == 0 && curr2 == 0) move on to check outputs +6939 { +6940 81 7/subop/compare %esi 0/imm32 +6941 75/jump-if-!= break/disp8 +6942 $mu-stmt-matches-primitive?:stmt-inout-is-null: +6943 { +6944 81 7/subop/compare %edi 0/imm32 +6945 75/jump-if-!= break/disp8 +6946 # +6947 e9/jump $mu-stmt-matches-primitive?:check-outputs/disp32 +6948 } +6949 # return false +6950 b8/copy-to-eax 0/imm32/false +6951 e9/jump $mu-stmt-matches-primitive?:end/disp32 +6952 } +6953 # if (curr2 == 0) return false +6954 { +6955 81 7/subop/compare %edi 0/imm32 +6956 75/jump-if-!= break/disp8 +6957 $mu-stmt-matches-primitive?:prim-inout-is-null: +6958 b8/copy-to-eax 0/imm32/false +6959 e9/jump $mu-stmt-matches-primitive?:end/disp32 +6960 } +6961 # if (curr != curr2) return false +6962 { +6963 (operand-matches-primitive? *esi *edi) # => eax +6964 3d/compare-eax-and 0/imm32 +6965 75/jump-if-!= break/disp8 +6966 b8/copy-to-eax 0/imm32/false +6967 e9/jump $mu-stmt-matches-primitive?:end/disp32 +6968 } +6969 # curr=curr->next +6970 8b/-> *(esi+4) 6/r32/esi # Operand-next +6971 # curr2=curr2->next +6972 8b/-> *(edi+4) 7/r32/edi # Operand-next +6973 eb/jump loop/disp8 +6974 } +6975 $mu-stmt-matches-primitive?:check-outputs: +6976 # for (curr/esi in stmt->outputs, curr2/edi in primitive->outputs) +6977 8b/-> *(ecx+0xc) 6/r32/esi # Stmt1-outputs +6978 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs +6979 { +6980 # if (curr == 0) return (curr2 == 0) +6981 { +6982 $mu-stmt-matches-primitive?:check-output: +6983 81 7/subop/compare %esi 0/imm32 +6984 75/jump-if-!= break/disp8 +6985 { +6986 81 7/subop/compare %edi 0/imm32 +6987 75/jump-if-!= break/disp8 +6988 # return true +6989 b8/copy-to-eax 1/imm32 +6990 e9/jump $mu-stmt-matches-primitive?:end/disp32 +6991 } +6992 # return false +6993 b8/copy-to-eax 0/imm32 +6994 e9/jump $mu-stmt-matches-primitive?:end/disp32 +6995 } +6996 # if (curr2 == 0) return false +6997 { +6998 81 7/subop/compare %edi 0/imm32 +6999 75/jump-if-!= break/disp8 +7000 b8/copy-to-eax 0/imm32 +7001 e9/jump $mu-stmt-matches-primitive?:end/disp32 +7002 } +7003 # if (curr != curr2) return false +7004 { +7005 (operand-matches-primitive? *esi *edi) # List-value List-value => eax +7006 3d/compare-eax-and 0/imm32 7007 75/jump-if-!= break/disp8 -7008 $mu-stmt-matches-primitive?:stmt-inout-is-null: -7009 { -7010 81 7/subop/compare %edi 0/imm32 -7011 75/jump-if-!= break/disp8 -7012 # -7013 e9/jump $mu-stmt-matches-primitive?:check-outputs/disp32 -7014 } -7015 # return false -7016 b8/copy-to-eax 0/imm32/false -7017 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7018 } -7019 # if (curr2 == 0) return false -7020 { -7021 81 7/subop/compare %edi 0/imm32 -7022 75/jump-if-!= break/disp8 -7023 $mu-stmt-matches-primitive?:prim-inout-is-null: -7024 b8/copy-to-eax 0/imm32/false -7025 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7026 } -7027 # if (curr != curr2) return false -7028 { -7029 (operand-matches-primitive? *esi *edi) # => eax -7030 3d/compare-eax-and 0/imm32 -7031 75/jump-if-!= break/disp8 -7032 b8/copy-to-eax 0/imm32/false -7033 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7034 } -7035 # curr=curr->next -7036 8b/-> *(esi+4) 6/r32/esi # Operand-next -7037 # curr2=curr2->next -7038 8b/-> *(edi+4) 7/r32/edi # Operand-next -7039 eb/jump loop/disp8 -7040 } -7041 $mu-stmt-matches-primitive?:check-outputs: -7042 # for (curr/esi in stmt->outputs, curr2/edi in primitive->outputs) -7043 8b/-> *(ecx+0xc) 6/r32/esi # Stmt1-outputs -7044 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs -7045 { -7046 # if (curr == 0) return (curr2 == 0) -7047 { -7048 $mu-stmt-matches-primitive?:check-output: -7049 81 7/subop/compare %esi 0/imm32 -7050 75/jump-if-!= break/disp8 -7051 { -7052 81 7/subop/compare %edi 0/imm32 -7053 75/jump-if-!= break/disp8 -7054 # return true -7055 b8/copy-to-eax 1/imm32 -7056 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7057 } -7058 # return false -7059 b8/copy-to-eax 0/imm32 -7060 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7061 } -7062 # if (curr2 == 0) return false -7063 { -7064 81 7/subop/compare %edi 0/imm32 -7065 75/jump-if-!= break/disp8 -7066 b8/copy-to-eax 0/imm32 -7067 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7068 } -7069 # if (curr != curr2) return false -7070 { -7071 (operand-matches-primitive? *esi *edi) # List-value List-value => eax -7072 3d/compare-eax-and 0/imm32 -7073 75/jump-if-!= break/disp8 -7074 b8/copy-to-eax 0/imm32 -7075 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7076 } -7077 # curr=curr->next -7078 8b/-> *(esi+4) 6/r32/esi # Operand-next -7079 # curr2=curr2->next -7080 8b/-> *(edi+4) 7/r32/edi # Operand-next -7081 eb/jump loop/disp8 -7082 } -7083 $mu-stmt-matches-primitive?:return-true: -7084 b8/copy-to-eax 1/imm32 -7085 $mu-stmt-matches-primitive?:end: -7086 # . restore registers -7087 5f/pop-to-edi -7088 5e/pop-to-esi -7089 5b/pop-to-ebx -7090 5a/pop-to-edx -7091 59/pop-to-ecx -7092 # . epilogue -7093 89/<- %esp 5/r32/ebp -7094 5d/pop-to-ebp -7095 c3/return -7096 -7097 operand-matches-primitive?: # var: (handle var), prim-var: (handle var) => result/eax: boolean -7098 # . prologue -7099 55/push-ebp -7100 89/<- %ebp 4/r32/esp -7101 # . save registers -7102 56/push-esi -7103 57/push-edi -7104 # esi = var -7105 8b/-> *(ebp+8) 6/r32/esi -7106 # edi = prim-var -7107 8b/-> *(ebp+0xc) 7/r32/edi -7108 # if (var->type != prim-var->type) return false -7109 (type-equal? *(esi+4) *(edi+4)) # Var-type, Var-type => eax -7110 3d/compare-eax-and 0/imm32 -7111 b8/copy-to-eax 0/imm32/false -7112 74/jump-if-= $operand-matches-primitive?:end/disp8 -7113 # return false if var->register doesn't match prim-var->register -7114 { -7115 # if addresses are equal, don't return here -7116 8b/-> *(esi+0x10) 0/r32/eax -7117 39/compare *(edi+0x10) 0/r32/eax -7118 74/jump-if-= break/disp8 -7119 # if either address is 0, return false -7120 3d/compare-eax-and 0/imm32 -7121 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result -7122 81 7/subop/compare *(edi+0x10) 0/imm32 -7123 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result -7124 # if prim-var->register is "*", return true -7125 (string-equal? *(edi+0x10) "*") # Var-register -7126 3d/compare-eax-and 0/imm32 -7127 b8/copy-to-eax 1/imm32/true -7128 75/jump-if-!= $operand-matches-primitive?:end/disp8 -7129 # if string contents don't match, return false -7130 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register -7131 3d/compare-eax-and 0/imm32 -7132 b8/copy-to-eax 0/imm32/false -7133 74/jump-if-= $operand-matches-primitive?:end/disp8 -7134 } -7135 # return true -7136 b8/copy-to-eax 1/imm32/true -7137 $operand-matches-primitive?:end: -7138 # . restore registers -7139 5f/pop-to-edi -7140 5e/pop-to-esi -7141 # . epilogue -7142 89/<- %esp 5/r32/ebp -7143 5d/pop-to-ebp -7144 c3/return -7145 -7146 type-equal?: # a: (handle tree type-id), b: (handle tree type-id) => result/eax: boolean -7147 # . prologue -7148 55/push-ebp -7149 89/<- %ebp 4/r32/esp -7150 # . save registers +7008 b8/copy-to-eax 0/imm32 +7009 e9/jump $mu-stmt-matches-primitive?:end/disp32 +7010 } +7011 # curr=curr->next +7012 8b/-> *(esi+4) 6/r32/esi # Operand-next +7013 # curr2=curr2->next +7014 8b/-> *(edi+4) 7/r32/edi # Operand-next +7015 eb/jump loop/disp8 +7016 } +7017 $mu-stmt-matches-primitive?:return-true: +7018 b8/copy-to-eax 1/imm32 +7019 $mu-stmt-matches-primitive?:end: +7020 # . restore registers +7021 5f/pop-to-edi +7022 5e/pop-to-esi +7023 5b/pop-to-ebx +7024 5a/pop-to-edx +7025 59/pop-to-ecx +7026 # . epilogue +7027 89/<- %esp 5/r32/ebp +7028 5d/pop-to-ebp +7029 c3/return +7030 +7031 operand-matches-primitive?: # var: (handle var), prim-var: (handle var) => result/eax: boolean +7032 # . prologue +7033 55/push-ebp +7034 89/<- %ebp 4/r32/esp +7035 # . save registers +7036 56/push-esi +7037 57/push-edi +7038 # esi = var +7039 8b/-> *(ebp+8) 6/r32/esi +7040 # edi = prim-var +7041 8b/-> *(ebp+0xc) 7/r32/edi +7042 # if (var->type != prim-var->type) return false +7043 (type-equal? *(esi+4) *(edi+4)) # Var-type, Var-type => eax +7044 3d/compare-eax-and 0/imm32 +7045 b8/copy-to-eax 0/imm32/false +7046 74/jump-if-= $operand-matches-primitive?:end/disp8 +7047 # return false if var->register doesn't match prim-var->register +7048 { +7049 # if addresses are equal, don't return here +7050 8b/-> *(esi+0x10) 0/r32/eax +7051 39/compare *(edi+0x10) 0/r32/eax +7052 74/jump-if-= break/disp8 +7053 # if either address is 0, return false +7054 3d/compare-eax-and 0/imm32 +7055 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result +7056 81 7/subop/compare *(edi+0x10) 0/imm32 +7057 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result +7058 # if prim-var->register is "*", return true +7059 (string-equal? *(edi+0x10) "*") # Var-register +7060 3d/compare-eax-and 0/imm32 +7061 b8/copy-to-eax 1/imm32/true +7062 75/jump-if-!= $operand-matches-primitive?:end/disp8 +7063 # if string contents don't match, return false +7064 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register +7065 3d/compare-eax-and 0/imm32 +7066 b8/copy-to-eax 0/imm32/false +7067 74/jump-if-= $operand-matches-primitive?:end/disp8 +7068 } +7069 # return true +7070 b8/copy-to-eax 1/imm32/true +7071 $operand-matches-primitive?:end: +7072 # . restore registers +7073 5f/pop-to-edi +7074 5e/pop-to-esi +7075 # . epilogue +7076 89/<- %esp 5/r32/ebp +7077 5d/pop-to-ebp +7078 c3/return +7079 +7080 type-equal?: # a: (handle tree type-id), b: (handle tree type-id) => result/eax: boolean +7081 # . prologue +7082 55/push-ebp +7083 89/<- %ebp 4/r32/esp +7084 # . save registers +7085 51/push-ecx +7086 52/push-edx +7087 # ecx = a +7088 8b/-> *(ebp+8) 1/r32/ecx +7089 # edx = b +7090 8b/-> *(ebp+0xc) 2/r32/edx +7091 # if (a == b) return true +7092 8b/-> %ecx 0/r32/eax # Var-type +7093 39/compare %edx 0/r32/eax # Var-type +7094 b8/copy-to-eax 1/imm32/true +7095 74/jump-if-= $type-equal?:end/disp8 +7096 # if (a < MAX_TYPE_ID) return false +7097 81 7/subop/compare %ecx 0x10000/imm32 +7098 b8/copy-to-eax 0/imm32/false +7099 72/jump-if-addr< $type-equal?:end/disp8 +7100 # if (b < MAX_TYPE_ID) return false +7101 81 7/subop/compare %edx 0x10000/imm32 +7102 b8/copy-to-eax 0/imm32/false +7103 72/jump-if-addr< $type-equal?:end/disp8 +7104 # if (!type-equal?(a->left, b->left)) return false +7105 (type-equal? *ecx *edx) # Tree-left, Tree-left => eax +7106 3d/compare-eax-and 0/imm32 +7107 74/jump-if-= $type-equal?:end/disp8 +7108 # return type-equal?(a->right, b->right) +7109 (type-equal? *(ecx+4) *(edx+4)) # Tree-right, Tree-right => eax +7110 $type-equal?:end: +7111 # . restore registers +7112 5a/pop-to-edx +7113 59/pop-to-ecx +7114 # . epilogue +7115 89/<- %esp 5/r32/ebp +7116 5d/pop-to-ebp +7117 c3/return +7118 +7119 test-emit-subx-statement-primitive: +7120 # Primitive operation on a variable on the stack. +7121 # increment foo +7122 # => +7123 # ff 0/subop/increment *(ebp-8) +7124 # +7125 # There's a variable on the var stack as follows: +7126 # name: 'foo' +7127 # type: int +7128 # stack-offset: -8 +7129 # +7130 # There's a primitive with this info: +7131 # name: 'increment' +7132 # inouts: int/mem +7133 # value: 'ff 0/subop/increment' +7134 # +7135 # There's nothing in functions. +7136 # +7137 # . prologue +7138 55/push-ebp +7139 89/<- %ebp 4/r32/esp +7140 # setup +7141 (clear-stream _test-output-stream) +7142 (clear-stream $_test-output-buffered-file->buffer) +7143 # var type/ecx: (handle tree type-id) = int +7144 68/push 0/imm32/right/null +7145 68/push 1/imm32/left/int +7146 89/<- %ecx 4/r32/esp +7147 # var var-foo/ecx: var +7148 68/push 0/imm32/no-register +7149 68/push -8/imm32/stack-offset +7150 68/push 1/imm32/block-depth 7151 51/push-ecx -7152 52/push-edx -7153 # ecx = a -7154 8b/-> *(ebp+8) 1/r32/ecx -7155 # edx = b -7156 8b/-> *(ebp+0xc) 2/r32/edx -7157 # if (a == b) return true -7158 8b/-> %ecx 0/r32/eax # Var-type -7159 39/compare %edx 0/r32/eax # Var-type -7160 b8/copy-to-eax 1/imm32/true -7161 74/jump-if-= $type-equal?:end/disp8 -7162 # if (a < MAX_TYPE_ID) return false -7163 81 7/subop/compare %ecx 0x10000/imm32 -7164 b8/copy-to-eax 0/imm32/false -7165 72/jump-if-addr< $type-equal?:end/disp8 -7166 # if (b < MAX_TYPE_ID) return false -7167 81 7/subop/compare %edx 0x10000/imm32 -7168 b8/copy-to-eax 0/imm32/false -7169 72/jump-if-addr< $type-equal?:end/disp8 -7170 # if (!type-equal?(a->left, b->left)) return false -7171 (type-equal? *ecx *edx) # Tree-left, Tree-left => eax -7172 3d/compare-eax-and 0/imm32 -7173 74/jump-if-= $type-equal?:end/disp8 -7174 # return type-equal?(a->right, b->right) -7175 (type-equal? *(ecx+4) *(edx+4)) # Tree-right, Tree-right => eax -7176 $type-equal?:end: -7177 # . restore registers -7178 5a/pop-to-edx -7179 59/pop-to-ecx -7180 # . epilogue -7181 89/<- %esp 5/r32/ebp -7182 5d/pop-to-ebp -7183 c3/return -7184 -7185 test-emit-subx-statement-primitive: -7186 # Primitive operation on a variable on the stack. -7187 # increment foo -7188 # => -7189 # ff 0/subop/increment *(ebp-8) -7190 # -7191 # There's a variable on the var stack as follows: -7192 # name: 'foo' -7193 # type: int -7194 # stack-offset: -8 -7195 # -7196 # There's a primitive with this info: -7197 # name: 'increment' -7198 # inouts: int/mem -7199 # value: 'ff 0/subop/increment' -7200 # -7201 # There's nothing in functions. -7202 # -7203 # . prologue -7204 55/push-ebp -7205 89/<- %ebp 4/r32/esp -7206 # setup -7207 (clear-stream _test-output-stream) -7208 (clear-stream $_test-output-buffered-file->buffer) -7209 # var type/ecx: (handle tree type-id) = int -7210 68/push 0/imm32/right/null -7211 68/push 1/imm32/left/int -7212 89/<- %ecx 4/r32/esp -7213 # var var-foo/ecx: var -7214 68/push 0/imm32/no-register -7215 68/push -8/imm32/stack-offset -7216 68/push 1/imm32/block-depth -7217 51/push-ecx -7218 68/push "foo"/imm32 -7219 89/<- %ecx 4/r32/esp -7220 # var operand/ebx: (list var) -7221 68/push 0/imm32/next -7222 51/push-ecx/var-foo -7223 89/<- %ebx 4/r32/esp -7224 # var stmt/esi: statement -7225 68/push 0/imm32/next -7226 68/push 0/imm32/outputs -7227 53/push-ebx/operands -7228 68/push "increment"/imm32/operation -7229 68/push 1/imm32 -7230 89/<- %esi 4/r32/esp -7231 # var primitives/ebx: primitive -7232 68/push 0/imm32/next -7233 68/push 0/imm32/output-is-write-only -7234 68/push 0/imm32/no-disp32 -7235 68/push 0/imm32/no-imm32 -7236 68/push 0/imm32/no-r32 -7237 68/push 1/imm32/rm32-is-first-inout -7238 68/push "ff 0/subop/increment"/imm32/subx-name -7239 68/push 0/imm32/outputs -7240 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call -7241 68/push "increment"/imm32/name -7242 89/<- %ebx 4/r32/esp -7243 # convert -7244 c7 0/subop/copy *Curr-block-depth 0/imm32 -7245 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -7246 (flush _test-output-buffered-file) -7247 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7253 # check output -7254 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-statement-primitive") -7255 # . epilogue -7256 89/<- %esp 5/r32/ebp -7257 5d/pop-to-ebp -7258 c3/return -7259 -7260 test-emit-subx-statement-primitive-register: -7261 # Primitive operation on a variable in a register. -7262 # foo <- increment -7263 # => -7264 # ff 0/subop/increment %eax # sub-optimal, but should suffice -7265 # -7266 # There's a variable on the var stack as follows: -7267 # name: 'foo' -7268 # type: int -7269 # register: 'eax' -7270 # -7271 # There's a primitive with this info: -7272 # name: 'increment' -7273 # out: int/reg -7274 # value: 'ff 0/subop/increment' -7275 # -7276 # There's nothing in functions. -7277 # -7278 # . prologue -7279 55/push-ebp -7280 89/<- %ebp 4/r32/esp -7281 # setup -7282 (clear-stream _test-output-stream) -7283 (clear-stream $_test-output-buffered-file->buffer) -7284 # var type/ecx: (handle tree type-id) = int -7285 68/push 0/imm32/right/null -7286 68/push 1/imm32/left/int -7287 89/<- %ecx 4/r32/esp -7288 # var var-foo/ecx: var in eax -7289 68/push "eax"/imm32/register -7290 68/push 0/imm32/no-stack-offset -7291 68/push 1/imm32/block-depth -7292 51/push-ecx -7293 68/push "foo"/imm32 -7294 89/<- %ecx 4/r32/esp -7295 # var operand/ebx: (list var) -7296 68/push 0/imm32/next -7297 51/push-ecx/var-foo -7298 89/<- %ebx 4/r32/esp -7299 # var stmt/esi: statement -7300 68/push 0/imm32/next -7301 53/push-ebx/outputs -7302 68/push 0/imm32/inouts -7303 68/push "increment"/imm32/operation -7304 68/push 1/imm32 -7305 89/<- %esi 4/r32/esp -7306 # var formal-var/ebx: var in any register -7307 68/push Any-register/imm32 -7308 68/push 0/imm32/no-stack-offset -7309 68/push 1/imm32/block-depth -7310 ff 6/subop/push *(ecx+4) # Var-type -7311 68/push "dummy"/imm32 -7312 89/<- %ebx 4/r32/esp -7313 # var operand/ebx: (list var) -7314 68/push 0/imm32/next -7315 53/push-ebx/formal-var -7316 89/<- %ebx 4/r32/esp -7317 # var primitives/ebx: primitive -7318 68/push 0/imm32/next -7319 68/push 0/imm32/output-is-write-only -7320 68/push 0/imm32/no-disp32 -7321 68/push 0/imm32/no-imm32 -7322 68/push 0/imm32/no-r32 -7323 68/push 3/imm32/rm32-in-first-output -7324 68/push "ff 0/subop/increment"/imm32/subx-name -7325 53/push-ebx/outputs -7326 68/push 0/imm32/inouts -7327 68/push "increment"/imm32/name -7328 89/<- %ebx 4/r32/esp -7329 # convert -7330 c7 0/subop/copy *Curr-block-depth 0/imm32 -7331 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -7332 (flush _test-output-buffered-file) -7333 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7339 # check output -7340 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-primitive-register") -7341 # . epilogue -7342 89/<- %esp 5/r32/ebp -7343 5d/pop-to-ebp -7344 c3/return -7345 -7346 test-emit-subx-statement-select-primitive: -7347 # Select the right primitive between overloads. -7348 # foo <- increment -7349 # => -7350 # ff 0/subop/increment %eax # sub-optimal, but should suffice -7351 # -7352 # There's a variable on the var stack as follows: -7353 # name: 'foo' -7354 # type: int -7355 # register: 'eax' -7356 # -7357 # There's two primitives, as follows: -7358 # - name: 'increment' -7359 # out: int/reg -7360 # value: 'ff 0/subop/increment' -7361 # - name: 'increment' -7362 # inout: int/mem -7363 # value: 'ff 0/subop/increment' -7364 # -7365 # There's nothing in functions. -7366 # -7367 # . prologue -7368 55/push-ebp -7369 89/<- %ebp 4/r32/esp -7370 # setup -7371 (clear-stream _test-output-stream) -7372 (clear-stream $_test-output-buffered-file->buffer) -7373 # var type/ecx: (handle tree type-id) = int -7374 68/push 0/imm32/right/null -7375 68/push 1/imm32/left/int -7376 89/<- %ecx 4/r32/esp -7377 # var var-foo/ecx: var in eax -7378 68/push "eax"/imm32/register -7379 68/push 0/imm32/no-stack-offset -7380 68/push 1/imm32/block-depth -7381 51/push-ecx -7382 68/push "foo"/imm32 -7383 89/<- %ecx 4/r32/esp -7384 # var real-outputs/edi: (list var) -7385 68/push 0/imm32/next -7386 51/push-ecx/var-foo -7387 89/<- %edi 4/r32/esp -7388 # var stmt/esi: statement -7389 68/push 0/imm32/next -7390 57/push-edi/outputs -7391 68/push 0/imm32/inouts -7392 68/push "increment"/imm32/operation -7393 68/push 1/imm32 -7394 89/<- %esi 4/r32/esp -7395 # var formal-var/ebx: var in any register -7396 68/push Any-register/imm32 -7397 68/push 0/imm32/no-stack-offset -7398 68/push 1/imm32/block-depth -7399 ff 6/subop/push *(ecx+4) # Var-type -7400 68/push "dummy"/imm32 -7401 89/<- %ebx 4/r32/esp -7402 # var formal-outputs/ebx: (list var) = {formal-var, 0} -7403 68/push 0/imm32/next -7404 53/push-ebx/formal-var -7405 89/<- %ebx 4/r32/esp -7406 # var primitive1/ebx: primitive -7407 68/push 0/imm32/next -7408 68/push 0/imm32/output-is-write-only -7409 68/push 0/imm32/no-disp32 -7410 68/push 0/imm32/no-imm32 -7411 68/push 0/imm32/no-r32 -7412 68/push 3/imm32/rm32-in-first-output -7413 68/push "ff 0/subop/increment"/imm32/subx-name -7414 53/push-ebx/outputs/formal-outputs -7415 68/push 0/imm32/inouts -7416 68/push "increment"/imm32/name -7417 89/<- %ebx 4/r32/esp -7418 # var primitives/ebx: primitive -7419 53/push-ebx/next -7420 68/push 0/imm32/output-is-write-only -7421 68/push 0/imm32/no-disp32 -7422 68/push 0/imm32/no-imm32 -7423 68/push 0/imm32/no-r32 -7424 68/push 1/imm32/rm32-is-first-inout -7425 68/push "ff 0/subop/increment"/imm32/subx-name -7426 68/push 0/imm32/outputs -7427 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -7428 68/push "increment"/imm32/name -7429 89/<- %ebx 4/r32/esp -7430 # convert -7431 c7 0/subop/copy *Curr-block-depth 0/imm32 -7432 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -7433 (flush _test-output-buffered-file) -7434 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7440 # check output -7441 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive") -7442 # . epilogue -7443 89/<- %esp 5/r32/ebp -7444 5d/pop-to-ebp -7445 c3/return -7446 -7447 test-emit-subx-statement-select-primitive-2: -7448 # Select the right primitive between overloads. -7449 # foo <- increment -7450 # => -7451 # ff 0/subop/increment %eax # sub-optimal, but should suffice -7452 # -7453 # There's a variable on the var stack as follows: -7454 # name: 'foo' -7455 # type: int -7456 # register: 'eax' -7457 # -7458 # There's two primitives, as follows: -7459 # - name: 'increment' -7460 # out: int/reg -7461 # value: 'ff 0/subop/increment' -7462 # - name: 'increment' -7463 # inout: int/mem -7464 # value: 'ff 0/subop/increment' -7465 # -7466 # There's nothing in functions. -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-foo/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 "foo"/imm32 -7484 89/<- %ecx 4/r32/esp -7485 # var inouts/edi: (list var) -7486 68/push 0/imm32/next -7487 51/push-ecx/var-foo -7488 89/<- %edi 4/r32/esp -7489 # var stmt/esi: statement -7490 68/push 0/imm32/next -7491 68/push 0/imm32/outputs -7492 57/push-edi/inouts -7493 68/push "increment"/imm32/operation -7494 68/push 1/imm32 -7495 89/<- %esi 4/r32/esp -7496 # var formal-var/ebx: var in any register -7497 68/push Any-register/imm32 -7498 68/push 0/imm32/no-stack-offset -7499 68/push 1/imm32/block-depth -7500 ff 6/subop/push *(ecx+4) # Var-type -7501 68/push "dummy"/imm32 -7502 89/<- %ebx 4/r32/esp -7503 # var operand/ebx: (list var) -7504 68/push 0/imm32/next -7505 53/push-ebx/formal-var -7506 89/<- %ebx 4/r32/esp -7507 # var primitive1/ebx: primitive -7508 68/push 0/imm32/next -7509 68/push 0/imm32/output-is-write-only -7510 68/push 0/imm32/no-disp32 -7511 68/push 0/imm32/no-imm32 -7512 68/push 0/imm32/no-r32 -7513 68/push 3/imm32/rm32-in-first-output -7514 68/push "ff 0/subop/increment"/imm32/subx-name -7515 53/push-ebx/outputs/formal-outputs -7516 68/push 0/imm32/inouts -7517 68/push "increment"/imm32/name -7518 89/<- %ebx 4/r32/esp -7519 # var primitives/ebx: primitive -7520 53/push-ebx/next -7521 68/push 0/imm32/output-is-write-only -7522 68/push 0/imm32/no-disp32 -7523 68/push 0/imm32/no-imm32 -7524 68/push 0/imm32/no-r32 -7525 68/push 1/imm32/rm32-is-first-inout -7526 68/push "ff 0/subop/increment"/imm32/subx-name -7527 68/push 0/imm32/outputs -7528 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -7529 68/push "increment"/imm32/name -7530 89/<- %ebx 4/r32/esp -7531 # convert -7532 c7 0/subop/copy *Curr-block-depth 0/imm32 -7533 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -7534 (flush _test-output-buffered-file) -7535 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7541 # check output -7542 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2") -7543 # . epilogue -7544 89/<- %esp 5/r32/ebp -7545 5d/pop-to-ebp -7546 c3/return -7547 -7548 test-increment-register: -7549 # Select the right register between overloads. -7550 # foo <- increment -7551 # => -7552 # 50/increment-eax -7553 # -7554 # There's a variable on the var stack as follows: -7555 # name: 'foo' -7556 # type: int -7557 # register: 'eax' -7558 # -7559 # Primitives are the global definitions. -7560 # -7561 # There are no functions defined. -7562 # -7563 # . prologue -7564 55/push-ebp -7565 89/<- %ebp 4/r32/esp -7566 # setup -7567 (clear-stream _test-output-stream) -7568 (clear-stream $_test-output-buffered-file->buffer) -7569 # var type/ecx: (handle tree type-id) = int -7570 68/push 0/imm32/right/null -7571 68/push 1/imm32/left/int -7572 89/<- %ecx 4/r32/esp -7573 # var var-foo/ecx: var in eax -7574 68/push "eax"/imm32/register -7575 68/push 0/imm32/no-stack-offset -7576 68/push 1/imm32/block-depth -7577 51/push-ecx -7578 68/push "foo"/imm32 -7579 89/<- %ecx 4/r32/esp -7580 # var real-outputs/edi: (list var) -7581 68/push 0/imm32/next -7582 51/push-ecx/var-foo -7583 89/<- %edi 4/r32/esp -7584 # var stmt/esi: statement -7585 68/push 0/imm32/next -7586 57/push-edi/outputs -7587 68/push 0/imm32/inouts -7588 68/push "increment"/imm32/operation -7589 68/push 1/imm32/regular-statement -7590 89/<- %esi 4/r32/esp -7591 # convert -7592 c7 0/subop/copy *Curr-block-depth 0/imm32 -7593 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7594 (flush _test-output-buffered-file) -7595 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7601 # check output -7602 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") -7603 # . epilogue -7604 89/<- %esp 5/r32/ebp -7605 5d/pop-to-ebp -7606 c3/return -7607 -7608 test-increment-var: -7609 # Select the right primitive between overloads. -7610 # foo <- increment -7611 # => -7612 # ff 0/subop/increment %eax # sub-optimal, but should suffice -7613 # -7614 # There's a variable on the var stack as follows: -7615 # name: 'foo' -7616 # type: int -7617 # register: 'eax' -7618 # -7619 # Primitives are the global definitions. -7620 # -7621 # There are no functions defined. -7622 # -7623 # . prologue -7624 55/push-ebp -7625 89/<- %ebp 4/r32/esp -7626 # setup -7627 (clear-stream _test-output-stream) -7628 (clear-stream $_test-output-buffered-file->buffer) -7629 # var type/ecx: (handle tree type-id) = int -7630 68/push 0/imm32/right/null -7631 68/push 1/imm32/left/int -7632 89/<- %ecx 4/r32/esp -7633 # var var-foo/ecx: var in eax -7634 68/push "eax"/imm32/register -7635 68/push 0/imm32/no-stack-offset -7636 68/push 1/imm32/block-depth -7637 51/push-ecx -7638 68/push "foo"/imm32 -7639 89/<- %ecx 4/r32/esp -7640 # var inouts/edi: (list var) -7641 68/push 0/imm32/next -7642 51/push-ecx/var-foo -7643 89/<- %edi 4/r32/esp -7644 # var stmt/esi: statement -7645 68/push 0/imm32/next -7646 68/push 0/imm32/outputs -7647 57/push-edi/inouts -7648 68/push "increment"/imm32/operation -7649 68/push 1/imm32 -7650 89/<- %esi 4/r32/esp -7651 # convert -7652 c7 0/subop/copy *Curr-block-depth 0/imm32 -7653 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7654 (flush _test-output-buffered-file) -7655 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7661 # check output -7662 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-increment-var") -7663 # . epilogue -7664 89/<- %esp 5/r32/ebp -7665 5d/pop-to-ebp -7666 c3/return -7667 -7668 test-add-reg-to-reg: -7669 # var1/reg <- add var2/reg -7670 # => -7671 # 01/add %var1 var2 -7672 # -7673 # . prologue -7674 55/push-ebp -7675 89/<- %ebp 4/r32/esp -7676 # setup -7677 (clear-stream _test-output-stream) -7678 (clear-stream $_test-output-buffered-file->buffer) -7679 # var type/ecx: (handle tree type-id) = int -7680 68/push 0/imm32/right/null -7681 68/push 1/imm32/left/int -7682 89/<- %ecx 4/r32/esp -7683 # var var-var1/ecx: var in eax -7684 68/push "eax"/imm32/register -7685 68/push 0/imm32/no-stack-offset -7686 68/push 1/imm32/block-depth -7687 51/push-ecx -7688 68/push "var1"/imm32 -7689 89/<- %ecx 4/r32/esp -7690 # var var-var2/edx: var in ecx -7691 68/push "ecx"/imm32/register -7692 68/push 0/imm32/no-stack-offset -7693 68/push 1/imm32/block-depth -7694 ff 6/subop/push *(ecx+4) # Var-type -7695 68/push "var2"/imm32 -7696 89/<- %edx 4/r32/esp -7697 # var inouts/esi: (list var2) -7698 68/push 0/imm32/next -7699 52/push-edx/var-var2 -7700 89/<- %esi 4/r32/esp -7701 # var outputs/edi: (list var1) -7702 68/push 0/imm32/next -7703 51/push-ecx/var-var1 -7704 89/<- %edi 4/r32/esp -7705 # var stmt/esi: statement -7706 68/push 0/imm32/next -7707 57/push-edi/outputs -7708 56/push-esi/inouts -7709 68/push "add"/imm32/operation -7710 68/push 1/imm32 -7711 89/<- %esi 4/r32/esp -7712 # convert -7713 c7 0/subop/copy *Curr-block-depth 0/imm32 -7714 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7715 (flush _test-output-buffered-file) -7716 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7722 # check output -7723 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") -7724 # . epilogue -7725 89/<- %esp 5/r32/ebp -7726 5d/pop-to-ebp -7727 c3/return -7728 -7729 test-add-reg-to-mem: -7730 # add-to var1 var2/reg -7731 # => -7732 # 01/add *(ebp+__) var2 -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-var1/ecx: var -7745 68/push 0/imm32/no-register -7746 68/push 8/imm32/stack-offset -7747 68/push 1/imm32/block-depth -7748 51/push-ecx -7749 68/push "var1"/imm32 -7750 89/<- %ecx 4/r32/esp -7751 # var var-var2/edx: var in ecx -7752 68/push "ecx"/imm32/register -7753 68/push 0/imm32/no-stack-offset -7754 68/push 1/imm32/block-depth -7755 ff 6/subop/push *(ecx+4) # Var-type -7756 68/push "var2"/imm32 -7757 89/<- %edx 4/r32/esp -7758 # var inouts/esi: (list var2) -7759 68/push 0/imm32/next -7760 52/push-edx/var-var2 -7761 89/<- %esi 4/r32/esp -7762 # var inouts = (list var1 var2) -7763 56/push-esi/next -7764 51/push-ecx/var-var1 -7765 89/<- %esi 4/r32/esp -7766 # var stmt/esi: statement -7767 68/push 0/imm32/next -7768 68/push 0/imm32/outputs -7769 56/push-esi/inouts -7770 68/push "add-to"/imm32/operation -7771 68/push 1/imm32 -7772 89/<- %esi 4/r32/esp -7773 # convert -7774 c7 0/subop/copy *Curr-block-depth 0/imm32 -7775 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7776 (flush _test-output-buffered-file) -7777 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7783 # check output -7784 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") -7785 # . epilogue -7786 89/<- %esp 5/r32/ebp -7787 5d/pop-to-ebp -7788 c3/return -7789 -7790 test-add-mem-to-reg: -7791 # var1/reg <- add var2 -7792 # => -7793 # 03/add *(ebp+__) var1 -7794 # -7795 # . prologue -7796 55/push-ebp -7797 89/<- %ebp 4/r32/esp -7798 # setup -7799 (clear-stream _test-output-stream) -7800 (clear-stream $_test-output-buffered-file->buffer) -7801 # var type/ecx: (handle tree type-id) = int -7802 68/push 0/imm32/right/null -7803 68/push 1/imm32/left/int -7804 89/<- %ecx 4/r32/esp -7805 # var var-var1/ecx: var in eax -7806 68/push "eax"/imm32/register -7807 68/push 0/imm32/no-stack-offset -7808 68/push 1/imm32/block-depth -7809 51/push-ecx -7810 68/push "var1"/imm32 -7811 89/<- %ecx 4/r32/esp -7812 # var var-var2/edx: var -7813 68/push 0/imm32/no-register -7814 68/push 8/imm32/stack-offset -7815 68/push 1/imm32/block-depth -7816 ff 6/subop/push *(ecx+4) # Var-type -7817 68/push "var2"/imm32 -7818 89/<- %edx 4/r32/esp -7819 # var inouts/esi: (list var2) -7820 68/push 0/imm32/next -7821 52/push-edx/var-var2 -7822 89/<- %esi 4/r32/esp -7823 # var outputs/edi: (list var1) -7824 68/push 0/imm32/next -7825 51/push-ecx/var-var1 -7826 89/<- %edi 4/r32/esp -7827 # var stmt/esi: statement -7828 68/push 0/imm32/next -7829 57/push-edi/outputs -7830 56/push-esi/inouts -7831 68/push "add"/imm32/operation -7832 68/push 1/imm32 -7833 89/<- %esi 4/r32/esp -7834 # convert -7835 c7 0/subop/copy *Curr-block-depth 0/imm32 -7836 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7837 (flush _test-output-buffered-file) -7838 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7844 # check output -7845 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") -7846 # . epilogue -7847 89/<- %esp 5/r32/ebp -7848 5d/pop-to-ebp -7849 c3/return -7850 -7851 test-add-literal-to-eax: -7852 # var1/eax <- add 0x34 -7853 # => -7854 # 05/add-to-eax 0x34/imm32 -7855 # -7856 # . prologue -7857 55/push-ebp -7858 89/<- %ebp 4/r32/esp -7859 # setup -7860 (clear-stream _test-output-stream) -7861 (clear-stream $_test-output-buffered-file->buffer) -7862 # var type/ecx: (handle tree type-id) = int -7863 68/push 0/imm32/right/null -7864 68/push 1/imm32/left/int -7865 89/<- %ecx 4/r32/esp -7866 # var var-var1/ecx: var in eax -7867 68/push "eax"/imm32/register -7868 68/push 0/imm32/no-stack-offset -7869 68/push 1/imm32/block-depth -7870 51/push-ecx -7871 68/push "var1"/imm32 -7872 89/<- %ecx 4/r32/esp -7873 # var type/edx: (handle tree type-id) = literal -7874 68/push 0/imm32/right/null -7875 68/push 0/imm32/left/literal -7876 89/<- %edx 4/r32/esp -7877 # var var-var2/edx: var literal -7878 68/push 0/imm32/no-register -7879 68/push 0/imm32/no-stack-offset -7880 68/push 1/imm32/block-depth -7881 52/push-edx -7882 68/push "0x34"/imm32 -7883 89/<- %edx 4/r32/esp -7884 # var inouts/esi: (list var2) -7885 68/push 0/imm32/next -7886 52/push-edx/var-var2 -7887 89/<- %esi 4/r32/esp -7888 # var outputs/edi: (list var1) -7889 68/push 0/imm32/next -7890 51/push-ecx/var-var1 -7891 89/<- %edi 4/r32/esp -7892 # var stmt/esi: statement -7893 68/push 0/imm32/next -7894 57/push-edi/outputs -7895 56/push-esi/inouts -7896 68/push "add"/imm32/operation -7897 68/push 1/imm32 -7898 89/<- %esi 4/r32/esp -7899 # convert -7900 c7 0/subop/copy *Curr-block-depth 0/imm32 -7901 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7902 (flush _test-output-buffered-file) -7903 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7909 # check output -7910 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") -7911 # . epilogue -7912 89/<- %esp 5/r32/ebp -7913 5d/pop-to-ebp -7914 c3/return -7915 -7916 test-add-literal-to-reg: -7917 # var1/ecx <- add 0x34 -7918 # => -7919 # 81 0/subop/add %ecx 0x34/imm32 -7920 # -7921 # . prologue -7922 55/push-ebp -7923 89/<- %ebp 4/r32/esp -7924 # setup -7925 (clear-stream _test-output-stream) -7926 (clear-stream $_test-output-buffered-file->buffer) -7927 # var type/ecx: (handle tree type-id) = int -7928 68/push 0/imm32/right/null -7929 68/push 1/imm32/left/int -7930 89/<- %ecx 4/r32/esp -7931 # var var-var1/ecx: var in ecx -7932 68/push "ecx"/imm32/register -7933 68/push 0/imm32/no-stack-offset -7934 68/push 1/imm32/block-depth -7935 51/push-ecx -7936 68/push "var1"/imm32 -7937 89/<- %ecx 4/r32/esp -7938 # var type/edx: (handle tree type-id) = literal -7939 68/push 0/imm32/right/null -7940 68/push 0/imm32/left/literal -7941 89/<- %edx 4/r32/esp -7942 # var var-var2/edx: var literal -7943 68/push 0/imm32/no-register -7944 68/push 0/imm32/no-stack-offset -7945 68/push 1/imm32/block-depth -7946 52/push-edx -7947 68/push "0x34"/imm32 -7948 89/<- %edx 4/r32/esp -7949 # var inouts/esi: (list var2) -7950 68/push 0/imm32/next -7951 52/push-edx/var-var2 -7952 89/<- %esi 4/r32/esp -7953 # var outputs/edi: (list var1) -7954 68/push 0/imm32/next -7955 51/push-ecx/var-var1 -7956 89/<- %edi 4/r32/esp -7957 # var stmt/esi: statement -7958 68/push 0/imm32/next -7959 57/push-edi/outputs -7960 56/push-esi/inouts -7961 68/push "add"/imm32/operation -7962 68/push 1/imm32 -7963 89/<- %esi 4/r32/esp -7964 # convert -7965 c7 0/subop/copy *Curr-block-depth 0/imm32 -7966 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7967 (flush _test-output-buffered-file) -7968 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7974 # check output -7975 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") -7976 # . epilogue -7977 89/<- %esp 5/r32/ebp -7978 5d/pop-to-ebp -7979 c3/return -7980 -7981 test-add-literal-to-mem: -7982 # add-to var1, 0x34 -7983 # => -7984 # 81 0/subop/add %eax 0x34/imm32 -7985 # -7986 # . prologue -7987 55/push-ebp -7988 89/<- %ebp 4/r32/esp -7989 # setup -7990 (clear-stream _test-output-stream) -7991 (clear-stream $_test-output-buffered-file->buffer) -7992 # var type/ecx: (handle tree type-id) = int -7993 68/push 0/imm32/right/null -7994 68/push 1/imm32/left/int -7995 89/<- %ecx 4/r32/esp -7996 # var var-var1/ecx: var -7997 68/push 0/imm32/no-register -7998 68/push 8/imm32/stack-offset -7999 68/push 1/imm32/block-depth -8000 51/push-ecx -8001 68/push "var1"/imm32 -8002 89/<- %ecx 4/r32/esp -8003 # var type/edx: (handle tree type-id) = literal -8004 68/push 0/imm32/right/null -8005 68/push 0/imm32/left/literal -8006 89/<- %edx 4/r32/esp -8007 # var var-var2/edx: var literal -8008 68/push 0/imm32/no-register -8009 68/push 0/imm32/no-stack-offset -8010 68/push 1/imm32/block-depth -8011 52/push-edx -8012 68/push "0x34"/imm32 -8013 89/<- %edx 4/r32/esp -8014 # var inouts/esi: (list var2) -8015 68/push 0/imm32/next -8016 52/push-edx/var-var2 -8017 89/<- %esi 4/r32/esp -8018 # var inouts = (list var1 inouts) -8019 56/push-esi/next -8020 51/push-ecx/var-var1 -8021 89/<- %esi 4/r32/esp -8022 # var stmt/esi: statement -8023 68/push 0/imm32/next -8024 68/push 0/imm32/outputs -8025 56/push-esi/inouts -8026 68/push "add-to"/imm32/operation -8027 68/push 1/imm32 -8028 89/<- %esi 4/r32/esp -8029 # convert -8030 c7 0/subop/copy *Curr-block-depth 0/imm32 -8031 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8032 (flush _test-output-buffered-file) -8033 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -8039 # check output -8040 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") -8041 # . epilogue -8042 89/<- %esp 5/r32/ebp -8043 5d/pop-to-ebp -8044 c3/return -8045 -8046 test-compare-mem-with-reg: -8047 # compare var1, var2/eax -8048 # => -8049 # 39/compare *(ebp+___) 0/r32/eax -8050 # -8051 # . prologue -8052 55/push-ebp -8053 89/<- %ebp 4/r32/esp -8054 # setup -8055 (clear-stream _test-output-stream) -8056 (clear-stream $_test-output-buffered-file->buffer) -8057 # var type/ecx: (handle tree type-id) = int -8058 68/push 0/imm32/right/null -8059 68/push 1/imm32/left/int -8060 89/<- %ecx 4/r32/esp -8061 # var var-var2/ecx: var in eax -8062 68/push "eax"/imm32/register -8063 68/push 0/imm32/no-stack-offset -8064 68/push 1/imm32/block-depth -8065 51/push-ecx -8066 68/push "var2"/imm32 -8067 89/<- %ecx 4/r32/esp -8068 # var var-var1/edx: var -8069 68/push 0/imm32/no-register -8070 68/push 8/imm32/stack-offset -8071 68/push 1/imm32/block-depth -8072 ff 6/subop/push *(ecx+4) # Var-type -8073 68/push "var1"/imm32 -8074 89/<- %edx 4/r32/esp -8075 # var inouts/esi: (list var1 var2) -8076 68/push 0/imm32/next -8077 51/push-ecx/var-var2 -8078 89/<- %esi 4/r32/esp -8079 56/push-esi -8080 52/push-edx/var-var1 -8081 89/<- %esi 4/r32/esp -8082 # var stmt/esi: statement -8083 68/push 0/imm32/next -8084 68/push 0/imm32/outputs -8085 56/push-esi/inouts -8086 68/push "compare"/imm32/operation -8087 68/push 1/imm32 -8088 89/<- %esi 4/r32/esp -8089 # convert -8090 c7 0/subop/copy *Curr-block-depth 0/imm32 -8091 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8092 (flush _test-output-buffered-file) -8093 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -8099 # check output -8100 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") -8101 # . epilogue -8102 89/<- %esp 5/r32/ebp -8103 5d/pop-to-ebp -8104 c3/return -8105 -8106 test-compare-reg-with-mem: -8107 # compare var1/eax, var2 -8108 # => -8109 # 3b/compare *(ebp+___) 0/r32/eax -8110 # -8111 # . prologue -8112 55/push-ebp -8113 89/<- %ebp 4/r32/esp -8114 # setup -8115 (clear-stream _test-output-stream) -8116 (clear-stream $_test-output-buffered-file->buffer) -8117 # var type/ecx: (handle tree type-id) = int -8118 68/push 0/imm32/right/null -8119 68/push 1/imm32/left/int -8120 89/<- %ecx 4/r32/esp -8121 # var var-var1/ecx: var in eax -8122 68/push "eax"/imm32/register -8123 68/push 0/imm32/no-stack-offset -8124 68/push 1/imm32/block-depth -8125 51/push-ecx -8126 68/push "var1"/imm32 -8127 89/<- %ecx 4/r32/esp -8128 # var var-var2/edx: var -8129 68/push 0/imm32/no-register -8130 68/push 8/imm32/stack-offset -8131 68/push 1/imm32/block-depth -8132 ff 6/subop/push *(ecx+4) # Var-type -8133 68/push "var2"/imm32 -8134 89/<- %edx 4/r32/esp -8135 # var inouts/esi: (list var1 var2) -8136 68/push 0/imm32/next -8137 52/push-edx/var-var2 -8138 89/<- %esi 4/r32/esp -8139 56/push-esi -8140 51/push-ecx/var-var1 -8141 89/<- %esi 4/r32/esp -8142 # var stmt/esi: statement -8143 68/push 0/imm32/next -8144 68/push 0/imm32/outputs -8145 56/push-esi/inouts -8146 68/push "compare"/imm32/operation -8147 68/push 1/imm32 -8148 89/<- %esi 4/r32/esp -8149 # convert -8150 c7 0/subop/copy *Curr-block-depth 0/imm32 -8151 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8152 (flush _test-output-buffered-file) -8153 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -8159 # check output -8160 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") -8161 # . epilogue -8162 89/<- %esp 5/r32/ebp -8163 5d/pop-to-ebp -8164 c3/return -8165 -8166 test-compare-mem-with-literal: -8167 # compare var1, 0x34 -8168 # => -8169 # 81 7/subop/compare *(ebp+___) 0x34/imm32 -8170 # -8171 # . prologue -8172 55/push-ebp -8173 89/<- %ebp 4/r32/esp -8174 # setup -8175 (clear-stream _test-output-stream) -8176 (clear-stream $_test-output-buffered-file->buffer) -8177 # var type/ecx: (handle tree type-id) = int -8178 68/push 0/imm32/right/null -8179 68/push 1/imm32/left/int -8180 89/<- %ecx 4/r32/esp -8181 # var var-var1/ecx: var -8182 68/push 0/imm32/no-register -8183 68/push 8/imm32/stack-offset -8184 68/push 1/imm32/block-depth -8185 51/push-ecx -8186 68/push "var1"/imm32 -8187 89/<- %ecx 4/r32/esp -8188 # var type/edx: (handle tree type-id) = literal -8189 68/push 0/imm32/right/null -8190 68/push 0/imm32/left/literal -8191 89/<- %edx 4/r32/esp -8192 # var var-var2/edx: var literal -8193 68/push 0/imm32/no-register -8194 68/push 0/imm32/no-stack-offset -8195 68/push 1/imm32/block-depth -8196 52/push-edx -8197 68/push "0x34"/imm32 -8198 89/<- %edx 4/r32/esp -8199 # var inouts/esi: (list var2) -8200 68/push 0/imm32/next -8201 52/push-edx/var-var2 -8202 89/<- %esi 4/r32/esp -8203 # var inouts = (list var1 inouts) -8204 56/push-esi/next -8205 51/push-ecx/var-var1 -8206 89/<- %esi 4/r32/esp -8207 # var stmt/esi: statement -8208 68/push 0/imm32/next -8209 68/push 0/imm32/outputs -8210 56/push-esi/inouts -8211 68/push "compare"/imm32/operation -8212 68/push 1/imm32 -8213 89/<- %esi 4/r32/esp -8214 # convert -8215 c7 0/subop/copy *Curr-block-depth 0/imm32 -8216 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8217 (flush _test-output-buffered-file) -8218 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -8224 # check output -8225 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") -8226 # . epilogue -8227 89/<- %esp 5/r32/ebp -8228 5d/pop-to-ebp -8229 c3/return -8230 -8231 test-compare-eax-with-literal: -8232 # compare var1/eax 0x34 -8233 # => -8234 # 3d/compare-eax-with 0x34/imm32 -8235 # -8236 # . prologue -8237 55/push-ebp -8238 89/<- %ebp 4/r32/esp -8239 # setup -8240 (clear-stream _test-output-stream) -8241 (clear-stream $_test-output-buffered-file->buffer) -8242 # var type/ecx: (handle tree type-id) = int -8243 68/push 0/imm32/right/null -8244 68/push 1/imm32/left/int -8245 89/<- %ecx 4/r32/esp -8246 # var var-var1/ecx: var in eax -8247 68/push "eax"/imm32/register -8248 68/push 0/imm32/no-stack-offset -8249 68/push 1/imm32/block-depth -8250 51/push-ecx -8251 68/push "var1"/imm32 -8252 89/<- %ecx 4/r32/esp -8253 # var type/edx: (handle tree type-id) = literal -8254 68/push 0/imm32/right/null -8255 68/push 0/imm32/left/literal -8256 89/<- %edx 4/r32/esp -8257 # var var-var2/edx: var literal -8258 68/push 0/imm32/no-register -8259 68/push 0/imm32/no-stack-offset -8260 68/push 1/imm32/block-depth -8261 52/push-edx -8262 68/push "0x34"/imm32 -8263 89/<- %edx 4/r32/esp -8264 # var inouts/esi: (list var2) -8265 68/push 0/imm32/next -8266 52/push-edx/var-var2 -8267 89/<- %esi 4/r32/esp -8268 # var inouts = (list var1 inouts) -8269 56/push-esi/next -8270 51/push-ecx/var-var1 -8271 89/<- %esi 4/r32/esp -8272 # var stmt/esi: statement -8273 68/push 0/imm32/next -8274 68/push 0/imm32/outputs -8275 56/push-esi/inouts -8276 68/push "compare"/imm32/operation -8277 68/push 1/imm32/regular-stmt -8278 89/<- %esi 4/r32/esp -8279 # convert -8280 c7 0/subop/copy *Curr-block-depth 0/imm32 -8281 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8282 (flush _test-output-buffered-file) -8283 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -8289 # check output -8290 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") -8291 # . epilogue -8292 89/<- %esp 5/r32/ebp -8293 5d/pop-to-ebp -8294 c3/return -8295 -8296 test-compare-reg-with-literal: -8297 # compare var1/ecx 0x34 +7152 68/push "foo"/imm32 +7153 89/<- %ecx 4/r32/esp +7154 # var operand/ebx: (list var) +7155 68/push 0/imm32/next +7156 51/push-ecx/var-foo +7157 89/<- %ebx 4/r32/esp +7158 # var stmt/esi: statement +7159 68/push 0/imm32/next +7160 68/push 0/imm32/outputs +7161 53/push-ebx/operands +7162 68/push "increment"/imm32/operation +7163 68/push 1/imm32 +7164 89/<- %esi 4/r32/esp +7165 # var primitives/ebx: primitive +7166 68/push 0/imm32/next +7167 68/push 0/imm32/output-is-write-only +7168 68/push 0/imm32/no-disp32 +7169 68/push 0/imm32/no-imm32 +7170 68/push 0/imm32/no-r32 +7171 68/push 1/imm32/rm32-is-first-inout +7172 68/push "ff 0/subop/increment"/imm32/subx-name +7173 68/push 0/imm32/outputs +7174 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call +7175 68/push "increment"/imm32/name +7176 89/<- %ebx 4/r32/esp +7177 # convert +7178 c7 0/subop/copy *Curr-block-depth 0/imm32 +7179 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) +7180 (flush _test-output-buffered-file) +7181 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +7187 # check output +7188 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-statement-primitive") +7189 # . epilogue +7190 89/<- %esp 5/r32/ebp +7191 5d/pop-to-ebp +7192 c3/return +7193 +7194 test-emit-subx-statement-primitive-register: +7195 # Primitive operation on a variable in a register. +7196 # foo <- increment +7197 # => +7198 # ff 0/subop/increment %eax # sub-optimal, but should suffice +7199 # +7200 # There's a variable on the var stack as follows: +7201 # name: 'foo' +7202 # type: int +7203 # register: 'eax' +7204 # +7205 # There's a primitive with this info: +7206 # name: 'increment' +7207 # out: int/reg +7208 # value: 'ff 0/subop/increment' +7209 # +7210 # There's nothing in functions. +7211 # +7212 # . prologue +7213 55/push-ebp +7214 89/<- %ebp 4/r32/esp +7215 # setup +7216 (clear-stream _test-output-stream) +7217 (clear-stream $_test-output-buffered-file->buffer) +7218 # var type/ecx: (handle tree type-id) = int +7219 68/push 0/imm32/right/null +7220 68/push 1/imm32/left/int +7221 89/<- %ecx 4/r32/esp +7222 # var var-foo/ecx: var in eax +7223 68/push "eax"/imm32/register +7224 68/push 0/imm32/no-stack-offset +7225 68/push 1/imm32/block-depth +7226 51/push-ecx +7227 68/push "foo"/imm32 +7228 89/<- %ecx 4/r32/esp +7229 # var operand/ebx: (list var) +7230 68/push 0/imm32/next +7231 51/push-ecx/var-foo +7232 89/<- %ebx 4/r32/esp +7233 # var stmt/esi: statement +7234 68/push 0/imm32/next +7235 53/push-ebx/outputs +7236 68/push 0/imm32/inouts +7237 68/push "increment"/imm32/operation +7238 68/push 1/imm32 +7239 89/<- %esi 4/r32/esp +7240 # var formal-var/ebx: var in any register +7241 68/push Any-register/imm32 +7242 68/push 0/imm32/no-stack-offset +7243 68/push 1/imm32/block-depth +7244 ff 6/subop/push *(ecx+4) # Var-type +7245 68/push "dummy"/imm32 +7246 89/<- %ebx 4/r32/esp +7247 # var operand/ebx: (list var) +7248 68/push 0/imm32/next +7249 53/push-ebx/formal-var +7250 89/<- %ebx 4/r32/esp +7251 # var primitives/ebx: primitive +7252 68/push 0/imm32/next +7253 68/push 0/imm32/output-is-write-only +7254 68/push 0/imm32/no-disp32 +7255 68/push 0/imm32/no-imm32 +7256 68/push 0/imm32/no-r32 +7257 68/push 3/imm32/rm32-in-first-output +7258 68/push "ff 0/subop/increment"/imm32/subx-name +7259 53/push-ebx/outputs +7260 68/push 0/imm32/inouts +7261 68/push "increment"/imm32/name +7262 89/<- %ebx 4/r32/esp +7263 # convert +7264 c7 0/subop/copy *Curr-block-depth 0/imm32 +7265 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) +7266 (flush _test-output-buffered-file) +7267 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +7273 # check output +7274 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-primitive-register") +7275 # . epilogue +7276 89/<- %esp 5/r32/ebp +7277 5d/pop-to-ebp +7278 c3/return +7279 +7280 test-emit-subx-statement-select-primitive: +7281 # Select the right primitive between overloads. +7282 # foo <- increment +7283 # => +7284 # ff 0/subop/increment %eax # sub-optimal, but should suffice +7285 # +7286 # There's a variable on the var stack as follows: +7287 # name: 'foo' +7288 # type: int +7289 # register: 'eax' +7290 # +7291 # There's two primitives, as follows: +7292 # - name: 'increment' +7293 # out: int/reg +7294 # value: 'ff 0/subop/increment' +7295 # - name: 'increment' +7296 # inout: int/mem +7297 # value: 'ff 0/subop/increment' +7298 # +7299 # There's nothing in functions. +7300 # +7301 # . prologue +7302 55/push-ebp +7303 89/<- %ebp 4/r32/esp +7304 # setup +7305 (clear-stream _test-output-stream) +7306 (clear-stream $_test-output-buffered-file->buffer) +7307 # var type/ecx: (handle tree type-id) = int +7308 68/push 0/imm32/right/null +7309 68/push 1/imm32/left/int +7310 89/<- %ecx 4/r32/esp +7311 # var var-foo/ecx: var in eax +7312 68/push "eax"/imm32/register +7313 68/push 0/imm32/no-stack-offset +7314 68/push 1/imm32/block-depth +7315 51/push-ecx +7316 68/push "foo"/imm32 +7317 89/<- %ecx 4/r32/esp +7318 # var real-outputs/edi: (list var) +7319 68/push 0/imm32/next +7320 51/push-ecx/var-foo +7321 89/<- %edi 4/r32/esp +7322 # var stmt/esi: statement +7323 68/push 0/imm32/next +7324 57/push-edi/outputs +7325 68/push 0/imm32/inouts +7326 68/push "increment"/imm32/operation +7327 68/push 1/imm32 +7328 89/<- %esi 4/r32/esp +7329 # var formal-var/ebx: var in any register +7330 68/push Any-register/imm32 +7331 68/push 0/imm32/no-stack-offset +7332 68/push 1/imm32/block-depth +7333 ff 6/subop/push *(ecx+4) # Var-type +7334 68/push "dummy"/imm32 +7335 89/<- %ebx 4/r32/esp +7336 # var formal-outputs/ebx: (list var) = {formal-var, 0} +7337 68/push 0/imm32/next +7338 53/push-ebx/formal-var +7339 89/<- %ebx 4/r32/esp +7340 # var primitive1/ebx: primitive +7341 68/push 0/imm32/next +7342 68/push 0/imm32/output-is-write-only +7343 68/push 0/imm32/no-disp32 +7344 68/push 0/imm32/no-imm32 +7345 68/push 0/imm32/no-r32 +7346 68/push 3/imm32/rm32-in-first-output +7347 68/push "ff 0/subop/increment"/imm32/subx-name +7348 53/push-ebx/outputs/formal-outputs +7349 68/push 0/imm32/inouts +7350 68/push "increment"/imm32/name +7351 89/<- %ebx 4/r32/esp +7352 # var primitives/ebx: primitive +7353 53/push-ebx/next +7354 68/push 0/imm32/output-is-write-only +7355 68/push 0/imm32/no-disp32 +7356 68/push 0/imm32/no-imm32 +7357 68/push 0/imm32/no-r32 +7358 68/push 1/imm32/rm32-is-first-inout +7359 68/push "ff 0/subop/increment"/imm32/subx-name +7360 68/push 0/imm32/outputs +7361 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call +7362 68/push "increment"/imm32/name +7363 89/<- %ebx 4/r32/esp +7364 # convert +7365 c7 0/subop/copy *Curr-block-depth 0/imm32 +7366 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) +7367 (flush _test-output-buffered-file) +7368 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +7374 # check output +7375 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive") +7376 # . epilogue +7377 89/<- %esp 5/r32/ebp +7378 5d/pop-to-ebp +7379 c3/return +7380 +7381 test-emit-subx-statement-select-primitive-2: +7382 # Select the right primitive between overloads. +7383 # foo <- increment +7384 # => +7385 # ff 0/subop/increment %eax # sub-optimal, but should suffice +7386 # +7387 # There's a variable on the var stack as follows: +7388 # name: 'foo' +7389 # type: int +7390 # register: 'eax' +7391 # +7392 # There's two primitives, as follows: +7393 # - name: 'increment' +7394 # out: int/reg +7395 # value: 'ff 0/subop/increment' +7396 # - name: 'increment' +7397 # inout: int/mem +7398 # value: 'ff 0/subop/increment' +7399 # +7400 # There's nothing in functions. +7401 # +7402 # . prologue +7403 55/push-ebp +7404 89/<- %ebp 4/r32/esp +7405 # setup +7406 (clear-stream _test-output-stream) +7407 (clear-stream $_test-output-buffered-file->buffer) +7408 # var type/ecx: (handle tree type-id) = int +7409 68/push 0/imm32/right/null +7410 68/push 1/imm32/left/int +7411 89/<- %ecx 4/r32/esp +7412 # var var-foo/ecx: var in eax +7413 68/push "eax"/imm32/register +7414 68/push 0/imm32/no-stack-offset +7415 68/push 1/imm32/block-depth +7416 51/push-ecx +7417 68/push "foo"/imm32 +7418 89/<- %ecx 4/r32/esp +7419 # var inouts/edi: (list var) +7420 68/push 0/imm32/next +7421 51/push-ecx/var-foo +7422 89/<- %edi 4/r32/esp +7423 # var stmt/esi: statement +7424 68/push 0/imm32/next +7425 68/push 0/imm32/outputs +7426 57/push-edi/inouts +7427 68/push "increment"/imm32/operation +7428 68/push 1/imm32 +7429 89/<- %esi 4/r32/esp +7430 # var formal-var/ebx: var in any register +7431 68/push Any-register/imm32 +7432 68/push 0/imm32/no-stack-offset +7433 68/push 1/imm32/block-depth +7434 ff 6/subop/push *(ecx+4) # Var-type +7435 68/push "dummy"/imm32 +7436 89/<- %ebx 4/r32/esp +7437 # var operand/ebx: (list var) +7438 68/push 0/imm32/next +7439 53/push-ebx/formal-var +7440 89/<- %ebx 4/r32/esp +7441 # var primitive1/ebx: primitive +7442 68/push 0/imm32/next +7443 68/push 0/imm32/output-is-write-only +7444 68/push 0/imm32/no-disp32 +7445 68/push 0/imm32/no-imm32 +7446 68/push 0/imm32/no-r32 +7447 68/push 3/imm32/rm32-in-first-output +7448 68/push "ff 0/subop/increment"/imm32/subx-name +7449 53/push-ebx/outputs/formal-outputs +7450 68/push 0/imm32/inouts +7451 68/push "increment"/imm32/name +7452 89/<- %ebx 4/r32/esp +7453 # var primitives/ebx: primitive +7454 53/push-ebx/next +7455 68/push 0/imm32/output-is-write-only +7456 68/push 0/imm32/no-disp32 +7457 68/push 0/imm32/no-imm32 +7458 68/push 0/imm32/no-r32 +7459 68/push 1/imm32/rm32-is-first-inout +7460 68/push "ff 0/subop/increment"/imm32/subx-name +7461 68/push 0/imm32/outputs +7462 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call +7463 68/push "increment"/imm32/name +7464 89/<- %ebx 4/r32/esp +7465 # convert +7466 c7 0/subop/copy *Curr-block-depth 0/imm32 +7467 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) +7468 (flush _test-output-buffered-file) +7469 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +7475 # check output +7476 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2") +7477 # . epilogue +7478 89/<- %esp 5/r32/ebp +7479 5d/pop-to-ebp +7480 c3/return +7481 +7482 test-increment-register: +7483 # Select the right register between overloads. +7484 # foo <- increment +7485 # => +7486 # 50/increment-eax +7487 # +7488 # There's a variable on the var stack as follows: +7489 # name: 'foo' +7490 # type: int +7491 # register: 'eax' +7492 # +7493 # Primitives are the global definitions. +7494 # +7495 # There are no functions defined. +7496 # +7497 # . prologue +7498 55/push-ebp +7499 89/<- %ebp 4/r32/esp +7500 # setup +7501 (clear-stream _test-output-stream) +7502 (clear-stream $_test-output-buffered-file->buffer) +7503 # var type/ecx: (handle tree type-id) = int +7504 68/push 0/imm32/right/null +7505 68/push 1/imm32/left/int +7506 89/<- %ecx 4/r32/esp +7507 # var var-foo/ecx: var in eax +7508 68/push "eax"/imm32/register +7509 68/push 0/imm32/no-stack-offset +7510 68/push 1/imm32/block-depth +7511 51/push-ecx +7512 68/push "foo"/imm32 +7513 89/<- %ecx 4/r32/esp +7514 # var real-outputs/edi: (list var) +7515 68/push 0/imm32/next +7516 51/push-ecx/var-foo +7517 89/<- %edi 4/r32/esp +7518 # var stmt/esi: statement +7519 68/push 0/imm32/next +7520 57/push-edi/outputs +7521 68/push 0/imm32/inouts +7522 68/push "increment"/imm32/operation +7523 68/push 1/imm32/regular-statement +7524 89/<- %esi 4/r32/esp +7525 # convert +7526 c7 0/subop/copy *Curr-block-depth 0/imm32 +7527 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +7528 (flush _test-output-buffered-file) +7529 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +7535 # check output +7536 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") +7537 # . epilogue +7538 89/<- %esp 5/r32/ebp +7539 5d/pop-to-ebp +7540 c3/return +7541 +7542 test-increment-var: +7543 # Select the right primitive between overloads. +7544 # foo <- increment +7545 # => +7546 # ff 0/subop/increment %eax # sub-optimal, but should suffice +7547 # +7548 # There's a variable on the var stack as follows: +7549 # name: 'foo' +7550 # type: int +7551 # register: 'eax' +7552 # +7553 # Primitives are the global definitions. +7554 # +7555 # There are no functions defined. +7556 # +7557 # . prologue +7558 55/push-ebp +7559 89/<- %ebp 4/r32/esp +7560 # setup +7561 (clear-stream _test-output-stream) +7562 (clear-stream $_test-output-buffered-file->buffer) +7563 # var type/ecx: (handle tree type-id) = int +7564 68/push 0/imm32/right/null +7565 68/push 1/imm32/left/int +7566 89/<- %ecx 4/r32/esp +7567 # var var-foo/ecx: var in eax +7568 68/push "eax"/imm32/register +7569 68/push 0/imm32/no-stack-offset +7570 68/push 1/imm32/block-depth +7571 51/push-ecx +7572 68/push "foo"/imm32 +7573 89/<- %ecx 4/r32/esp +7574 # var inouts/edi: (list var) +7575 68/push 0/imm32/next +7576 51/push-ecx/var-foo +7577 89/<- %edi 4/r32/esp +7578 # var stmt/esi: statement +7579 68/push 0/imm32/next +7580 68/push 0/imm32/outputs +7581 57/push-edi/inouts +7582 68/push "increment"/imm32/operation +7583 68/push 1/imm32 +7584 89/<- %esi 4/r32/esp +7585 # convert +7586 c7 0/subop/copy *Curr-block-depth 0/imm32 +7587 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +7588 (flush _test-output-buffered-file) +7589 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +7595 # check output +7596 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-increment-var") +7597 # . epilogue +7598 89/<- %esp 5/r32/ebp +7599 5d/pop-to-ebp +7600 c3/return +7601 +7602 test-add-reg-to-reg: +7603 # var1/reg <- add var2/reg +7604 # => +7605 # 01/add %var1 var2 +7606 # +7607 # . prologue +7608 55/push-ebp +7609 89/<- %ebp 4/r32/esp +7610 # setup +7611 (clear-stream _test-output-stream) +7612 (clear-stream $_test-output-buffered-file->buffer) +7613 # var type/ecx: (handle tree type-id) = int +7614 68/push 0/imm32/right/null +7615 68/push 1/imm32/left/int +7616 89/<- %ecx 4/r32/esp +7617 # var var-var1/ecx: var in eax +7618 68/push "eax"/imm32/register +7619 68/push 0/imm32/no-stack-offset +7620 68/push 1/imm32/block-depth +7621 51/push-ecx +7622 68/push "var1"/imm32 +7623 89/<- %ecx 4/r32/esp +7624 # var var-var2/edx: var in ecx +7625 68/push "ecx"/imm32/register +7626 68/push 0/imm32/no-stack-offset +7627 68/push 1/imm32/block-depth +7628 ff 6/subop/push *(ecx+4) # Var-type +7629 68/push "var2"/imm32 +7630 89/<- %edx 4/r32/esp +7631 # var inouts/esi: (list var2) +7632 68/push 0/imm32/next +7633 52/push-edx/var-var2 +7634 89/<- %esi 4/r32/esp +7635 # var outputs/edi: (list var1) +7636 68/push 0/imm32/next +7637 51/push-ecx/var-var1 +7638 89/<- %edi 4/r32/esp +7639 # var stmt/esi: statement +7640 68/push 0/imm32/next +7641 57/push-edi/outputs +7642 56/push-esi/inouts +7643 68/push "add"/imm32/operation +7644 68/push 1/imm32 +7645 89/<- %esi 4/r32/esp +7646 # convert +7647 c7 0/subop/copy *Curr-block-depth 0/imm32 +7648 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +7649 (flush _test-output-buffered-file) +7650 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +7656 # check output +7657 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") +7658 # . epilogue +7659 89/<- %esp 5/r32/ebp +7660 5d/pop-to-ebp +7661 c3/return +7662 +7663 test-add-reg-to-mem: +7664 # add-to var1 var2/reg +7665 # => +7666 # 01/add *(ebp+__) var2 +7667 # +7668 # . prologue +7669 55/push-ebp +7670 89/<- %ebp 4/r32/esp +7671 # setup +7672 (clear-stream _test-output-stream) +7673 (clear-stream $_test-output-buffered-file->buffer) +7674 # var type/ecx: (handle tree type-id) = int +7675 68/push 0/imm32/right/null +7676 68/push 1/imm32/left/int +7677 89/<- %ecx 4/r32/esp +7678 # var var-var1/ecx: var +7679 68/push 0/imm32/no-register +7680 68/push 8/imm32/stack-offset +7681 68/push 1/imm32/block-depth +7682 51/push-ecx +7683 68/push "var1"/imm32 +7684 89/<- %ecx 4/r32/esp +7685 # var var-var2/edx: var in ecx +7686 68/push "ecx"/imm32/register +7687 68/push 0/imm32/no-stack-offset +7688 68/push 1/imm32/block-depth +7689 ff 6/subop/push *(ecx+4) # Var-type +7690 68/push "var2"/imm32 +7691 89/<- %edx 4/r32/esp +7692 # var inouts/esi: (list var2) +7693 68/push 0/imm32/next +7694 52/push-edx/var-var2 +7695 89/<- %esi 4/r32/esp +7696 # var inouts = (list var1 var2) +7697 56/push-esi/next +7698 51/push-ecx/var-var1 +7699 89/<- %esi 4/r32/esp +7700 # var stmt/esi: statement +7701 68/push 0/imm32/next +7702 68/push 0/imm32/outputs +7703 56/push-esi/inouts +7704 68/push "add-to"/imm32/operation +7705 68/push 1/imm32 +7706 89/<- %esi 4/r32/esp +7707 # convert +7708 c7 0/subop/copy *Curr-block-depth 0/imm32 +7709 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +7710 (flush _test-output-buffered-file) +7711 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +7717 # check output +7718 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") +7719 # . epilogue +7720 89/<- %esp 5/r32/ebp +7721 5d/pop-to-ebp +7722 c3/return +7723 +7724 test-add-mem-to-reg: +7725 # var1/reg <- add var2 +7726 # => +7727 # 03/add *(ebp+__) var1 +7728 # +7729 # . prologue +7730 55/push-ebp +7731 89/<- %ebp 4/r32/esp +7732 # setup +7733 (clear-stream _test-output-stream) +7734 (clear-stream $_test-output-buffered-file->buffer) +7735 # var type/ecx: (handle tree type-id) = int +7736 68/push 0/imm32/right/null +7737 68/push 1/imm32/left/int +7738 89/<- %ecx 4/r32/esp +7739 # var var-var1/ecx: var in eax +7740 68/push "eax"/imm32/register +7741 68/push 0/imm32/no-stack-offset +7742 68/push 1/imm32/block-depth +7743 51/push-ecx +7744 68/push "var1"/imm32 +7745 89/<- %ecx 4/r32/esp +7746 # var var-var2/edx: var +7747 68/push 0/imm32/no-register +7748 68/push 8/imm32/stack-offset +7749 68/push 1/imm32/block-depth +7750 ff 6/subop/push *(ecx+4) # Var-type +7751 68/push "var2"/imm32 +7752 89/<- %edx 4/r32/esp +7753 # var inouts/esi: (list var2) +7754 68/push 0/imm32/next +7755 52/push-edx/var-var2 +7756 89/<- %esi 4/r32/esp +7757 # var outputs/edi: (list var1) +7758 68/push 0/imm32/next +7759 51/push-ecx/var-var1 +7760 89/<- %edi 4/r32/esp +7761 # var stmt/esi: statement +7762 68/push 0/imm32/next +7763 57/push-edi/outputs +7764 56/push-esi/inouts +7765 68/push "add"/imm32/operation +7766 68/push 1/imm32 +7767 89/<- %esi 4/r32/esp +7768 # convert +7769 c7 0/subop/copy *Curr-block-depth 0/imm32 +7770 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +7771 (flush _test-output-buffered-file) +7772 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +7778 # check output +7779 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") +7780 # . epilogue +7781 89/<- %esp 5/r32/ebp +7782 5d/pop-to-ebp +7783 c3/return +7784 +7785 test-add-literal-to-eax: +7786 # var1/eax <- add 0x34 +7787 # => +7788 # 05/add-to-eax 0x34/imm32 +7789 # +7790 # . prologue +7791 55/push-ebp +7792 89/<- %ebp 4/r32/esp +7793 # setup +7794 (clear-stream _test-output-stream) +7795 (clear-stream $_test-output-buffered-file->buffer) +7796 # var type/ecx: (handle tree type-id) = int +7797 68/push 0/imm32/right/null +7798 68/push 1/imm32/left/int +7799 89/<- %ecx 4/r32/esp +7800 # var var-var1/ecx: var in eax +7801 68/push "eax"/imm32/register +7802 68/push 0/imm32/no-stack-offset +7803 68/push 1/imm32/block-depth +7804 51/push-ecx +7805 68/push "var1"/imm32 +7806 89/<- %ecx 4/r32/esp +7807 # var type/edx: (handle tree type-id) = literal +7808 68/push 0/imm32/right/null +7809 68/push 0/imm32/left/literal +7810 89/<- %edx 4/r32/esp +7811 # var var-var2/edx: var literal +7812 68/push 0/imm32/no-register +7813 68/push 0/imm32/no-stack-offset +7814 68/push 1/imm32/block-depth +7815 52/push-edx +7816 68/push "0x34"/imm32 +7817 89/<- %edx 4/r32/esp +7818 # var inouts/esi: (list var2) +7819 68/push 0/imm32/next +7820 52/push-edx/var-var2 +7821 89/<- %esi 4/r32/esp +7822 # var outputs/edi: (list var1) +7823 68/push 0/imm32/next +7824 51/push-ecx/var-var1 +7825 89/<- %edi 4/r32/esp +7826 # var stmt/esi: statement +7827 68/push 0/imm32/next +7828 57/push-edi/outputs +7829 56/push-esi/inouts +7830 68/push "add"/imm32/operation +7831 68/push 1/imm32 +7832 89/<- %esi 4/r32/esp +7833 # convert +7834 c7 0/subop/copy *Curr-block-depth 0/imm32 +7835 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +7836 (flush _test-output-buffered-file) +7837 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +7843 # check output +7844 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") +7845 # . epilogue +7846 89/<- %esp 5/r32/ebp +7847 5d/pop-to-ebp +7848 c3/return +7849 +7850 test-add-literal-to-reg: +7851 # var1/ecx <- add 0x34 +7852 # => +7853 # 81 0/subop/add %ecx 0x34/imm32 +7854 # +7855 # . prologue +7856 55/push-ebp +7857 89/<- %ebp 4/r32/esp +7858 # setup +7859 (clear-stream _test-output-stream) +7860 (clear-stream $_test-output-buffered-file->buffer) +7861 # var type/ecx: (handle tree type-id) = int +7862 68/push 0/imm32/right/null +7863 68/push 1/imm32/left/int +7864 89/<- %ecx 4/r32/esp +7865 # var var-var1/ecx: var in ecx +7866 68/push "ecx"/imm32/register +7867 68/push 0/imm32/no-stack-offset +7868 68/push 1/imm32/block-depth +7869 51/push-ecx +7870 68/push "var1"/imm32 +7871 89/<- %ecx 4/r32/esp +7872 # var type/edx: (handle tree type-id) = literal +7873 68/push 0/imm32/right/null +7874 68/push 0/imm32/left/literal +7875 89/<- %edx 4/r32/esp +7876 # var var-var2/edx: var literal +7877 68/push 0/imm32/no-register +7878 68/push 0/imm32/no-stack-offset +7879 68/push 1/imm32/block-depth +7880 52/push-edx +7881 68/push "0x34"/imm32 +7882 89/<- %edx 4/r32/esp +7883 # var inouts/esi: (list var2) +7884 68/push 0/imm32/next +7885 52/push-edx/var-var2 +7886 89/<- %esi 4/r32/esp +7887 # var outputs/edi: (list var1) +7888 68/push 0/imm32/next +7889 51/push-ecx/var-var1 +7890 89/<- %edi 4/r32/esp +7891 # var stmt/esi: statement +7892 68/push 0/imm32/next +7893 57/push-edi/outputs +7894 56/push-esi/inouts +7895 68/push "add"/imm32/operation +7896 68/push 1/imm32 +7897 89/<- %esi 4/r32/esp +7898 # convert +7899 c7 0/subop/copy *Curr-block-depth 0/imm32 +7900 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +7901 (flush _test-output-buffered-file) +7902 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +7908 # check output +7909 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") +7910 # . epilogue +7911 89/<- %esp 5/r32/ebp +7912 5d/pop-to-ebp +7913 c3/return +7914 +7915 test-add-literal-to-mem: +7916 # add-to var1, 0x34 +7917 # => +7918 # 81 0/subop/add %eax 0x34/imm32 +7919 # +7920 # . prologue +7921 55/push-ebp +7922 89/<- %ebp 4/r32/esp +7923 # setup +7924 (clear-stream _test-output-stream) +7925 (clear-stream $_test-output-buffered-file->buffer) +7926 # var type/ecx: (handle tree type-id) = int +7927 68/push 0/imm32/right/null +7928 68/push 1/imm32/left/int +7929 89/<- %ecx 4/r32/esp +7930 # var var-var1/ecx: var +7931 68/push 0/imm32/no-register +7932 68/push 8/imm32/stack-offset +7933 68/push 1/imm32/block-depth +7934 51/push-ecx +7935 68/push "var1"/imm32 +7936 89/<- %ecx 4/r32/esp +7937 # var type/edx: (handle tree type-id) = literal +7938 68/push 0/imm32/right/null +7939 68/push 0/imm32/left/literal +7940 89/<- %edx 4/r32/esp +7941 # var var-var2/edx: var literal +7942 68/push 0/imm32/no-register +7943 68/push 0/imm32/no-stack-offset +7944 68/push 1/imm32/block-depth +7945 52/push-edx +7946 68/push "0x34"/imm32 +7947 89/<- %edx 4/r32/esp +7948 # var inouts/esi: (list var2) +7949 68/push 0/imm32/next +7950 52/push-edx/var-var2 +7951 89/<- %esi 4/r32/esp +7952 # var inouts = (list var1 inouts) +7953 56/push-esi/next +7954 51/push-ecx/var-var1 +7955 89/<- %esi 4/r32/esp +7956 # var stmt/esi: statement +7957 68/push 0/imm32/next +7958 68/push 0/imm32/outputs +7959 56/push-esi/inouts +7960 68/push "add-to"/imm32/operation +7961 68/push 1/imm32 +7962 89/<- %esi 4/r32/esp +7963 # convert +7964 c7 0/subop/copy *Curr-block-depth 0/imm32 +7965 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +7966 (flush _test-output-buffered-file) +7967 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +7973 # check output +7974 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") +7975 # . epilogue +7976 89/<- %esp 5/r32/ebp +7977 5d/pop-to-ebp +7978 c3/return +7979 +7980 test-compare-mem-with-reg: +7981 # compare var1, var2/eax +7982 # => +7983 # 39/compare *(ebp+___) 0/r32/eax +7984 # +7985 # . prologue +7986 55/push-ebp +7987 89/<- %ebp 4/r32/esp +7988 # setup +7989 (clear-stream _test-output-stream) +7990 (clear-stream $_test-output-buffered-file->buffer) +7991 # var type/ecx: (handle tree type-id) = int +7992 68/push 0/imm32/right/null +7993 68/push 1/imm32/left/int +7994 89/<- %ecx 4/r32/esp +7995 # var var-var2/ecx: var in eax +7996 68/push "eax"/imm32/register +7997 68/push 0/imm32/no-stack-offset +7998 68/push 1/imm32/block-depth +7999 51/push-ecx +8000 68/push "var2"/imm32 +8001 89/<- %ecx 4/r32/esp +8002 # var var-var1/edx: var +8003 68/push 0/imm32/no-register +8004 68/push 8/imm32/stack-offset +8005 68/push 1/imm32/block-depth +8006 ff 6/subop/push *(ecx+4) # Var-type +8007 68/push "var1"/imm32 +8008 89/<- %edx 4/r32/esp +8009 # var inouts/esi: (list var1 var2) +8010 68/push 0/imm32/next +8011 51/push-ecx/var-var2 +8012 89/<- %esi 4/r32/esp +8013 56/push-esi +8014 52/push-edx/var-var1 +8015 89/<- %esi 4/r32/esp +8016 # var stmt/esi: statement +8017 68/push 0/imm32/next +8018 68/push 0/imm32/outputs +8019 56/push-esi/inouts +8020 68/push "compare"/imm32/operation +8021 68/push 1/imm32 +8022 89/<- %esi 4/r32/esp +8023 # convert +8024 c7 0/subop/copy *Curr-block-depth 0/imm32 +8025 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8026 (flush _test-output-buffered-file) +8027 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8033 # check output +8034 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") +8035 # . epilogue +8036 89/<- %esp 5/r32/ebp +8037 5d/pop-to-ebp +8038 c3/return +8039 +8040 test-compare-reg-with-mem: +8041 # compare var1/eax, var2 +8042 # => +8043 # 3b/compare *(ebp+___) 0/r32/eax +8044 # +8045 # . prologue +8046 55/push-ebp +8047 89/<- %ebp 4/r32/esp +8048 # setup +8049 (clear-stream _test-output-stream) +8050 (clear-stream $_test-output-buffered-file->buffer) +8051 # var type/ecx: (handle tree type-id) = int +8052 68/push 0/imm32/right/null +8053 68/push 1/imm32/left/int +8054 89/<- %ecx 4/r32/esp +8055 # var var-var1/ecx: var in eax +8056 68/push "eax"/imm32/register +8057 68/push 0/imm32/no-stack-offset +8058 68/push 1/imm32/block-depth +8059 51/push-ecx +8060 68/push "var1"/imm32 +8061 89/<- %ecx 4/r32/esp +8062 # var var-var2/edx: var +8063 68/push 0/imm32/no-register +8064 68/push 8/imm32/stack-offset +8065 68/push 1/imm32/block-depth +8066 ff 6/subop/push *(ecx+4) # Var-type +8067 68/push "var2"/imm32 +8068 89/<- %edx 4/r32/esp +8069 # var inouts/esi: (list var1 var2) +8070 68/push 0/imm32/next +8071 52/push-edx/var-var2 +8072 89/<- %esi 4/r32/esp +8073 56/push-esi +8074 51/push-ecx/var-var1 +8075 89/<- %esi 4/r32/esp +8076 # var stmt/esi: statement +8077 68/push 0/imm32/next +8078 68/push 0/imm32/outputs +8079 56/push-esi/inouts +8080 68/push "compare"/imm32/operation +8081 68/push 1/imm32 +8082 89/<- %esi 4/r32/esp +8083 # convert +8084 c7 0/subop/copy *Curr-block-depth 0/imm32 +8085 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8086 (flush _test-output-buffered-file) +8087 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8093 # check output +8094 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") +8095 # . epilogue +8096 89/<- %esp 5/r32/ebp +8097 5d/pop-to-ebp +8098 c3/return +8099 +8100 test-compare-mem-with-literal: +8101 # compare var1, 0x34 +8102 # => +8103 # 81 7/subop/compare *(ebp+___) 0x34/imm32 +8104 # +8105 # . prologue +8106 55/push-ebp +8107 89/<- %ebp 4/r32/esp +8108 # setup +8109 (clear-stream _test-output-stream) +8110 (clear-stream $_test-output-buffered-file->buffer) +8111 # var type/ecx: (handle tree type-id) = int +8112 68/push 0/imm32/right/null +8113 68/push 1/imm32/left/int +8114 89/<- %ecx 4/r32/esp +8115 # var var-var1/ecx: var +8116 68/push 0/imm32/no-register +8117 68/push 8/imm32/stack-offset +8118 68/push 1/imm32/block-depth +8119 51/push-ecx +8120 68/push "var1"/imm32 +8121 89/<- %ecx 4/r32/esp +8122 # var type/edx: (handle tree type-id) = literal +8123 68/push 0/imm32/right/null +8124 68/push 0/imm32/left/literal +8125 89/<- %edx 4/r32/esp +8126 # var var-var2/edx: var literal +8127 68/push 0/imm32/no-register +8128 68/push 0/imm32/no-stack-offset +8129 68/push 1/imm32/block-depth +8130 52/push-edx +8131 68/push "0x34"/imm32 +8132 89/<- %edx 4/r32/esp +8133 # var inouts/esi: (list var2) +8134 68/push 0/imm32/next +8135 52/push-edx/var-var2 +8136 89/<- %esi 4/r32/esp +8137 # var inouts = (list var1 inouts) +8138 56/push-esi/next +8139 51/push-ecx/var-var1 +8140 89/<- %esi 4/r32/esp +8141 # var stmt/esi: statement +8142 68/push 0/imm32/next +8143 68/push 0/imm32/outputs +8144 56/push-esi/inouts +8145 68/push "compare"/imm32/operation +8146 68/push 1/imm32 +8147 89/<- %esi 4/r32/esp +8148 # convert +8149 c7 0/subop/copy *Curr-block-depth 0/imm32 +8150 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8151 (flush _test-output-buffered-file) +8152 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8158 # check output +8159 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") +8160 # . epilogue +8161 89/<- %esp 5/r32/ebp +8162 5d/pop-to-ebp +8163 c3/return +8164 +8165 test-compare-eax-with-literal: +8166 # compare var1/eax 0x34 +8167 # => +8168 # 3d/compare-eax-with 0x34/imm32 +8169 # +8170 # . prologue +8171 55/push-ebp +8172 89/<- %ebp 4/r32/esp +8173 # setup +8174 (clear-stream _test-output-stream) +8175 (clear-stream $_test-output-buffered-file->buffer) +8176 # var type/ecx: (handle tree type-id) = int +8177 68/push 0/imm32/right/null +8178 68/push 1/imm32/left/int +8179 89/<- %ecx 4/r32/esp +8180 # var var-var1/ecx: var in eax +8181 68/push "eax"/imm32/register +8182 68/push 0/imm32/no-stack-offset +8183 68/push 1/imm32/block-depth +8184 51/push-ecx +8185 68/push "var1"/imm32 +8186 89/<- %ecx 4/r32/esp +8187 # var type/edx: (handle tree type-id) = literal +8188 68/push 0/imm32/right/null +8189 68/push 0/imm32/left/literal +8190 89/<- %edx 4/r32/esp +8191 # var var-var2/edx: var literal +8192 68/push 0/imm32/no-register +8193 68/push 0/imm32/no-stack-offset +8194 68/push 1/imm32/block-depth +8195 52/push-edx +8196 68/push "0x34"/imm32 +8197 89/<- %edx 4/r32/esp +8198 # var inouts/esi: (list var2) +8199 68/push 0/imm32/next +8200 52/push-edx/var-var2 +8201 89/<- %esi 4/r32/esp +8202 # var inouts = (list var1 inouts) +8203 56/push-esi/next +8204 51/push-ecx/var-var1 +8205 89/<- %esi 4/r32/esp +8206 # var stmt/esi: statement +8207 68/push 0/imm32/next +8208 68/push 0/imm32/outputs +8209 56/push-esi/inouts +8210 68/push "compare"/imm32/operation +8211 68/push 1/imm32/regular-stmt +8212 89/<- %esi 4/r32/esp +8213 # convert +8214 c7 0/subop/copy *Curr-block-depth 0/imm32 +8215 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8216 (flush _test-output-buffered-file) +8217 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8223 # check output +8224 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") +8225 # . epilogue +8226 89/<- %esp 5/r32/ebp +8227 5d/pop-to-ebp +8228 c3/return +8229 +8230 test-compare-reg-with-literal: +8231 # compare var1/ecx 0x34 +8232 # => +8233 # 81 7/subop/compare %ecx 0x34/imm32 +8234 # +8235 # . prologue +8236 55/push-ebp +8237 89/<- %ebp 4/r32/esp +8238 # setup +8239 (clear-stream _test-output-stream) +8240 (clear-stream $_test-output-buffered-file->buffer) +8241 # var type/ecx: (handle tree type-id) = int +8242 68/push 0/imm32/right/null +8243 68/push 1/imm32/left/int +8244 89/<- %ecx 4/r32/esp +8245 # var var-var1/ecx: var in ecx +8246 68/push "ecx"/imm32/register +8247 68/push 0/imm32/no-stack-offset +8248 68/push 1/imm32/block-depth +8249 51/push-ecx +8250 68/push "var1"/imm32 +8251 89/<- %ecx 4/r32/esp +8252 # var type/edx: (handle tree type-id) = literal +8253 68/push 0/imm32/right/null +8254 68/push 0/imm32/left/literal +8255 89/<- %edx 4/r32/esp +8256 # var var-var2/edx: var literal +8257 68/push 0/imm32/no-register +8258 68/push 0/imm32/no-stack-offset +8259 68/push 1/imm32/block-depth +8260 52/push-edx +8261 68/push "0x34"/imm32 +8262 89/<- %edx 4/r32/esp +8263 # var inouts/esi: (list var2) +8264 68/push 0/imm32/next +8265 52/push-edx/var-var2 +8266 89/<- %esi 4/r32/esp +8267 # var inouts = (list var1 inouts) +8268 56/push-esi/next +8269 51/push-ecx/var-var1 +8270 89/<- %esi 4/r32/esp +8271 # var stmt/esi: statement +8272 68/push 0/imm32/next +8273 68/push 0/imm32/outputs +8274 56/push-esi/inouts +8275 68/push "compare"/imm32/operation +8276 68/push 1/imm32/regular-stmt +8277 89/<- %esi 4/r32/esp +8278 # convert +8279 c7 0/subop/copy *Curr-block-depth 0/imm32 +8280 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8281 (flush _test-output-buffered-file) +8282 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8288 # check output +8289 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") +8290 # . epilogue +8291 89/<- %esp 5/r32/ebp +8292 5d/pop-to-ebp +8293 c3/return +8294 +8295 test-emit-subx-statement-function-call: +8296 # Call a function on a variable on the stack. +8297 # f foo 8298 # => -8299 # 81 7/subop/compare %ecx 0x34/imm32 -8300 # -8301 # . prologue -8302 55/push-ebp -8303 89/<- %ebp 4/r32/esp -8304 # setup -8305 (clear-stream _test-output-stream) -8306 (clear-stream $_test-output-buffered-file->buffer) -8307 # var type/ecx: (handle tree type-id) = int -8308 68/push 0/imm32/right/null -8309 68/push 1/imm32/left/int -8310 89/<- %ecx 4/r32/esp -8311 # var var-var1/ecx: var in ecx -8312 68/push "ecx"/imm32/register -8313 68/push 0/imm32/no-stack-offset -8314 68/push 1/imm32/block-depth -8315 51/push-ecx -8316 68/push "var1"/imm32 -8317 89/<- %ecx 4/r32/esp -8318 # var type/edx: (handle tree type-id) = literal -8319 68/push 0/imm32/right/null -8320 68/push 0/imm32/left/literal -8321 89/<- %edx 4/r32/esp -8322 # var var-var2/edx: var literal -8323 68/push 0/imm32/no-register -8324 68/push 0/imm32/no-stack-offset -8325 68/push 1/imm32/block-depth -8326 52/push-edx -8327 68/push "0x34"/imm32 -8328 89/<- %edx 4/r32/esp -8329 # var inouts/esi: (list var2) -8330 68/push 0/imm32/next -8331 52/push-edx/var-var2 -8332 89/<- %esi 4/r32/esp -8333 # var inouts = (list var1 inouts) -8334 56/push-esi/next -8335 51/push-ecx/var-var1 -8336 89/<- %esi 4/r32/esp -8337 # var stmt/esi: statement -8338 68/push 0/imm32/next -8339 68/push 0/imm32/outputs -8340 56/push-esi/inouts -8341 68/push "compare"/imm32/operation -8342 68/push 1/imm32/regular-stmt -8343 89/<- %esi 4/r32/esp -8344 # convert -8345 c7 0/subop/copy *Curr-block-depth 0/imm32 -8346 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8347 (flush _test-output-buffered-file) -8348 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -8354 # check output -8355 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") -8356 # . epilogue -8357 89/<- %esp 5/r32/ebp -8358 5d/pop-to-ebp -8359 c3/return -8360 -8361 test-emit-subx-statement-function-call: -8362 # Call a function on a variable on the stack. -8363 # f foo -8364 # => -8365 # (f2 *(ebp-8)) -8366 # (Changing the function name supports overloading in general, but here it -8367 # just serves to help disambiguate things.) -8368 # -8369 # There's a variable on the var stack as follows: -8370 # name: 'foo' -8371 # type: int -8372 # stack-offset: -8 +8299 # (f2 *(ebp-8)) +8300 # (Changing the function name supports overloading in general, but here it +8301 # just serves to help disambiguate things.) +8302 # +8303 # There's a variable on the var stack as follows: +8304 # name: 'foo' +8305 # type: int +8306 # stack-offset: -8 +8307 # +8308 # There's nothing in primitives. +8309 # +8310 # There's a function with this info: +8311 # name: 'f' +8312 # inout: int/mem +8313 # value: 'f2' +8314 # +8315 # . prologue +8316 55/push-ebp +8317 89/<- %ebp 4/r32/esp +8318 # setup +8319 (clear-stream _test-output-stream) +8320 (clear-stream $_test-output-buffered-file->buffer) +8321 # var type/ecx: (handle tree type-id) = int +8322 68/push 0/imm32/right/null +8323 68/push 1/imm32/left/int +8324 89/<- %ecx 4/r32/esp +8325 # var var-foo/ecx: var +8326 68/push 0/imm32/no-register +8327 68/push -8/imm32/stack-offset +8328 68/push 0/imm32/block-depth +8329 51/push-ecx +8330 68/push "foo"/imm32 +8331 89/<- %ecx 4/r32/esp +8332 # var operands/esi: (list var) +8333 68/push 0/imm32/next +8334 51/push-ecx/var-foo +8335 89/<- %esi 4/r32/esp +8336 # var stmt/esi: statement +8337 68/push 0/imm32/next +8338 68/push 0/imm32/outputs +8339 56/push-esi/inouts +8340 68/push "f"/imm32/operation +8341 68/push 1/imm32 +8342 89/<- %esi 4/r32/esp +8343 # var functions/ebx: function +8344 68/push 0/imm32/next +8345 68/push 0/imm32/body +8346 68/push 0/imm32/outputs +8347 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call +8348 68/push "f2"/imm32/subx-name +8349 68/push "f"/imm32/name +8350 89/<- %ebx 4/r32/esp +8351 # convert +8352 c7 0/subop/copy *Curr-block-depth 0/imm32 +8353 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) +8354 (flush _test-output-buffered-file) +8355 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8361 # check output +8362 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-statement-function-call") +8363 # . epilogue +8364 89/<- %esp 5/r32/ebp +8365 5d/pop-to-ebp +8366 c3/return +8367 +8368 test-emit-subx-statement-function-call-with-literal-arg: +8369 # Call a function on a literal. +8370 # f 34 +8371 # => +8372 # (f2 34) 8373 # -8374 # There's nothing in primitives. -8375 # -8376 # There's a function with this info: -8377 # name: 'f' -8378 # inout: int/mem -8379 # value: 'f2' -8380 # -8381 # . prologue -8382 55/push-ebp -8383 89/<- %ebp 4/r32/esp -8384 # setup -8385 (clear-stream _test-output-stream) -8386 (clear-stream $_test-output-buffered-file->buffer) -8387 # var type/ecx: (handle tree type-id) = int -8388 68/push 0/imm32/right/null -8389 68/push 1/imm32/left/int +8374 # . prologue +8375 55/push-ebp +8376 89/<- %ebp 4/r32/esp +8377 # setup +8378 (clear-stream _test-output-stream) +8379 (clear-stream $_test-output-buffered-file->buffer) +8380 # var type/ecx: (handle tree type-id) = literal +8381 68/push 0/imm32/right/null +8382 68/push 0/imm32/left/literal +8383 89/<- %ecx 4/r32/esp +8384 # var var-foo/ecx: var literal +8385 68/push 0/imm32/no-register +8386 68/push 0/imm32/no-stack-offset +8387 68/push 0/imm32/block-depth +8388 51/push-ecx +8389 68/push "34"/imm32 8390 89/<- %ecx 4/r32/esp -8391 # var var-foo/ecx: var -8392 68/push 0/imm32/no-register -8393 68/push -8/imm32/stack-offset -8394 68/push 0/imm32/block-depth -8395 51/push-ecx -8396 68/push "foo"/imm32 -8397 89/<- %ecx 4/r32/esp -8398 # var operands/esi: (list var) -8399 68/push 0/imm32/next -8400 51/push-ecx/var-foo +8391 # var operands/esi: (list var) +8392 68/push 0/imm32/next +8393 51/push-ecx/var-foo +8394 89/<- %esi 4/r32/esp +8395 # var stmt/esi: statement +8396 68/push 0/imm32/next +8397 68/push 0/imm32/outputs +8398 56/push-esi/inouts +8399 68/push "f"/imm32/operation +8400 68/push 1/imm32 8401 89/<- %esi 4/r32/esp -8402 # var stmt/esi: statement +8402 # var functions/ebx: function 8403 68/push 0/imm32/next -8404 68/push 0/imm32/outputs -8405 56/push-esi/inouts -8406 68/push "f"/imm32/operation -8407 68/push 1/imm32 -8408 89/<- %esi 4/r32/esp -8409 # var functions/ebx: function -8410 68/push 0/imm32/next -8411 68/push 0/imm32/body -8412 68/push 0/imm32/outputs -8413 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -8414 68/push "f2"/imm32/subx-name -8415 68/push "f"/imm32/name -8416 89/<- %ebx 4/r32/esp -8417 # convert -8418 c7 0/subop/copy *Curr-block-depth 0/imm32 -8419 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) -8420 (flush _test-output-buffered-file) -8421 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -8427 # check output -8428 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-statement-function-call") -8429 # . epilogue -8430 89/<- %esp 5/r32/ebp -8431 5d/pop-to-ebp -8432 c3/return -8433 -8434 test-emit-subx-statement-function-call-with-literal-arg: -8435 # Call a function on a literal. -8436 # f 34 -8437 # => -8438 # (f2 34) -8439 # -8440 # . prologue -8441 55/push-ebp -8442 89/<- %ebp 4/r32/esp -8443 # setup -8444 (clear-stream _test-output-stream) -8445 (clear-stream $_test-output-buffered-file->buffer) -8446 # var type/ecx: (handle tree type-id) = literal -8447 68/push 0/imm32/right/null -8448 68/push 0/imm32/left/literal -8449 89/<- %ecx 4/r32/esp -8450 # var var-foo/ecx: var literal -8451 68/push 0/imm32/no-register -8452 68/push 0/imm32/no-stack-offset -8453 68/push 0/imm32/block-depth -8454 51/push-ecx -8455 68/push "34"/imm32 -8456 89/<- %ecx 4/r32/esp -8457 # var operands/esi: (list var) -8458 68/push 0/imm32/next -8459 51/push-ecx/var-foo -8460 89/<- %esi 4/r32/esp -8461 # var stmt/esi: statement -8462 68/push 0/imm32/next -8463 68/push 0/imm32/outputs -8464 56/push-esi/inouts -8465 68/push "f"/imm32/operation -8466 68/push 1/imm32 -8467 89/<- %esi 4/r32/esp -8468 # var functions/ebx: function -8469 68/push 0/imm32/next -8470 68/push 0/imm32/body -8471 68/push 0/imm32/outputs -8472 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -8473 68/push "f2"/imm32/subx-name -8474 68/push "f"/imm32/name -8475 89/<- %ebx 4/r32/esp -8476 # convert -8477 c7 0/subop/copy *Curr-block-depth 0/imm32 -8478 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) -8479 (flush _test-output-buffered-file) -8480 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -8486 # check output -8487 (check-next-stream-line-equal _test-output-stream "(f2 34)" "F - test-emit-subx-statement-function-call-with-literal-arg") -8488 # . epilogue -8489 89/<- %esp 5/r32/ebp -8490 5d/pop-to-ebp -8491 c3/return -8492 -8493 emit-indent: # out: (addr buffered-file), n: int -8494 # . prologue -8495 55/push-ebp -8496 89/<- %ebp 4/r32/esp -8497 # . save registers -8498 50/push-eax -8499 # var i/eax: int = n -8500 8b/-> *(ebp+0xc) 0/r32/eax -8501 { -8502 # if (i <= 0) break -8503 3d/compare-eax-with 0/imm32 -8504 7e/jump-if-<= break/disp8 -8505 (write-buffered *(ebp+8) " ") -8506 48/decrement-eax -8507 eb/jump loop/disp8 -8508 } -8509 $emit-indent:end: -8510 # . restore registers -8511 58/pop-to-eax -8512 # . epilogue -8513 89/<- %esp 5/r32/ebp -8514 5d/pop-to-ebp -8515 c3/return -8516 -8517 emit-subx-prologue: # out: (addr buffered-file) -8518 # . prologue -8519 55/push-ebp -8520 89/<- %ebp 4/r32/esp -8521 # -8522 (write-buffered *(ebp+8) " # . prologue\n") -8523 (write-buffered *(ebp+8) " 55/push-ebp\n") -8524 (write-buffered *(ebp+8) " 89/<- %ebp 4/r32/esp\n") -8525 $emit-subx-prologue:end: -8526 # . epilogue -8527 89/<- %esp 5/r32/ebp -8528 5d/pop-to-ebp -8529 c3/return -8530 -8531 emit-subx-epilogue: # out: (addr buffered-file) -8532 # . prologue -8533 55/push-ebp -8534 89/<- %ebp 4/r32/esp -8535 # -8536 (write-buffered *(ebp+8) " # . epilogue\n") -8537 (write-buffered *(ebp+8) " 89/<- %esp 5/r32/ebp\n") -8538 (write-buffered *(ebp+8) " 5d/pop-to-ebp\n") -8539 (write-buffered *(ebp+8) " c3/return\n") -8540 $emit-subx-epilogue:end: -8541 # . epilogue -8542 89/<- %esp 5/r32/ebp -8543 5d/pop-to-ebp -8544 c3/return +8404 68/push 0/imm32/body +8405 68/push 0/imm32/outputs +8406 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call +8407 68/push "f2"/imm32/subx-name +8408 68/push "f"/imm32/name +8409 89/<- %ebx 4/r32/esp +8410 # convert +8411 c7 0/subop/copy *Curr-block-depth 0/imm32 +8412 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) +8413 (flush _test-output-buffered-file) +8414 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8420 # check output +8421 (check-next-stream-line-equal _test-output-stream "(f2 34)" "F - test-emit-subx-statement-function-call-with-literal-arg") +8422 # . epilogue +8423 89/<- %esp 5/r32/ebp +8424 5d/pop-to-ebp +8425 c3/return +8426 +8427 emit-indent: # out: (addr buffered-file), n: int +8428 # . prologue +8429 55/push-ebp +8430 89/<- %ebp 4/r32/esp +8431 # . save registers +8432 50/push-eax +8433 # var i/eax: int = n +8434 8b/-> *(ebp+0xc) 0/r32/eax +8435 { +8436 # if (i <= 0) break +8437 3d/compare-eax-with 0/imm32 +8438 7e/jump-if-<= break/disp8 +8439 (write-buffered *(ebp+8) " ") +8440 48/decrement-eax +8441 eb/jump loop/disp8 +8442 } +8443 $emit-indent:end: +8444 # . restore registers +8445 58/pop-to-eax +8446 # . epilogue +8447 89/<- %esp 5/r32/ebp +8448 5d/pop-to-ebp +8449 c3/return +8450 +8451 emit-subx-prologue: # out: (addr buffered-file) +8452 # . prologue +8453 55/push-ebp +8454 89/<- %ebp 4/r32/esp +8455 # +8456 (write-buffered *(ebp+8) " # . prologue\n") +8457 (write-buffered *(ebp+8) " 55/push-ebp\n") +8458 (write-buffered *(ebp+8) " 89/<- %ebp 4/r32/esp\n") +8459 $emit-subx-prologue:end: +8460 # . epilogue +8461 89/<- %esp 5/r32/ebp +8462 5d/pop-to-ebp +8463 c3/return +8464 +8465 emit-subx-epilogue: # out: (addr buffered-file) +8466 # . prologue +8467 55/push-ebp +8468 89/<- %ebp 4/r32/esp +8469 # +8470 (write-buffered *(ebp+8) " # . epilogue\n") +8471 (write-buffered *(ebp+8) " 89/<- %esp 5/r32/ebp\n") +8472 (write-buffered *(ebp+8) " 5d/pop-to-ebp\n") +8473 (write-buffered *(ebp+8) " c3/return\n") +8474 $emit-subx-epilogue:end: +8475 # . epilogue +8476 89/<- %esp 5/r32/ebp +8477 5d/pop-to-ebp +8478 c3/return -- cgit 1.4.1-2-gfad0