From 3dad94263f9b5bcbed576d27f61714100fbfae18 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sun, 9 Feb 2020 20:49:38 -0800 Subject: 6001 --- html/apps/assort.subx.html | 4 +- html/apps/braces.subx.html | 12 +- html/apps/calls.subx.html | 8 +- html/apps/crenshaw2-1.subx.html | 8 +- html/apps/crenshaw2-1b.subx.html | 16 +- html/apps/dquotes.subx.html | 28 +- html/apps/hex.subx.html | 44 +- html/apps/mu.subx.html | 13993 +++++++++++++++++++------------------ html/apps/pack.subx.html | 168 +- html/apps/sigils.subx.html | 76 +- html/apps/subx-params.subx.html | 2 +- html/apps/survey.subx.html | 14 +- 12 files changed, 7290 insertions(+), 7083 deletions(-) (limited to 'html/apps') diff --git a/html/apps/assort.subx.html b/html/apps/assort.subx.html index 6f2c21bd..bc77a2c4 100644 --- a/html/apps/assort.subx.html +++ b/html/apps/assort.subx.html @@ -364,7 +364,7 @@ if ('onhashchange' in window) { 318 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 319 # subx-assort(_test-input-buffered-file, _test-output-buffered-file) 320 # . . push args -321 68/push _test-output-buffered-file/imm32 +321 68/push _test-output-buffered-file/imm32 322 68/push _test-input-buffered-file/imm32 323 # . . call 324 e8/call subx-assort/disp32 @@ -372,7 +372,7 @@ if ('onhashchange' in window) { 326 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 327 # . flush(_test-output-buffered-file) 328 # . . push args -329 68/push _test-output-buffered-file/imm32 +329 68/push _test-output-buffered-file/imm32 330 # . . call 331 e8/call flush/disp32 332 # . . discard args diff --git a/html/apps/braces.subx.html b/html/apps/braces.subx.html index abd83f69..3d33c79e 100644 --- a/html/apps/braces.subx.html +++ b/html/apps/braces.subx.html @@ -326,9 +326,9 @@ if ('onhashchange' in window) { 267 (clear-stream $_test-output-buffered-file->buffer) 268 # test 269 (write _test-input-stream "== abcd 0x1") -270 (subx-braces _test-input-buffered-file _test-output-buffered-file) +270 (subx-braces _test-input-buffered-file _test-output-buffered-file) 271 # check that the line just passed through -272 (flush _test-output-buffered-file) +272 (flush _test-output-buffered-file) 273 +-- 5 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- 278 (check-stream-equal _test-output-stream "== abcd 0x1 \n" "F - test-subx-braces-passes-most-words-through") 279 # . epilogue @@ -359,9 +359,9 @@ if ('onhashchange' in window) { 304 (clear-stream $_test-output-buffered-file->buffer) 305 # test 306 (write _test-input-stream "{\nab break/imm32\ncd loop/imm32\n}") -307 (subx-braces _test-input-buffered-file _test-output-buffered-file) +307 (subx-braces _test-input-buffered-file _test-output-buffered-file) 308 # check that the line just passed through -309 (flush _test-output-buffered-file) +309 (flush _test-output-buffered-file) 310 +-- 5 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- 315 (check-stream-equal _test-output-stream "_loop0x00000001:\nab _break0x00000001/imm32 \ncd _loop0x00000001/imm32 \n_break0x00000001:\n" "F - test-subx-braces-1") 316 # . epilogue @@ -396,9 +396,9 @@ if ('onhashchange' in window) { 345 (clear-stream $_test-output-buffered-file->buffer) 346 # test 347 (write _test-input-stream "{\n{\nab break/imm32\n}\ncd loop/imm32\n}") -348 (subx-braces _test-input-buffered-file _test-output-buffered-file) +348 (subx-braces _test-input-buffered-file _test-output-buffered-file) 349 # check that the line just passed through -350 (flush _test-output-buffered-file) +350 (flush _test-output-buffered-file) 351 +-- 5 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- 356 (check-stream-equal _test-output-stream "_loop0x00000001:\n_loop0x00000002:\nab _break0x00000002/imm32 \n_break0x00000002:\ncd _loop0x00000001/imm32 \n_break0x00000001:\n" "F - test-subx-braces-2") 357 # . epilogue diff --git a/html/apps/calls.subx.html b/html/apps/calls.subx.html index e23c2d8b..50e2d54f 100644 --- a/html/apps/calls.subx.html +++ b/html/apps/calls.subx.html @@ -605,7 +605,7 @@ if ('onhashchange' in window) { 583 81 0/subop/add %esp 8/imm32 584 # subx-calls(_test-input-buffered-file, _test-output-buffered-file) 585 # . . push args - 586 68/push _test-output-buffered-file/imm32 + 586 68/push _test-output-buffered-file/imm32 587 68/push _test-input-buffered-file/imm32 588 # . . call 589 e8/call subx-calls/disp32 @@ -614,7 +614,7 @@ if ('onhashchange' in window) { 592 # check that the line just passed through 593 # . flush(_test-output-buffered-file) 594 # . . push args - 595 68/push _test-output-buffered-file/imm32 + 595 68/push _test-output-buffered-file/imm32 596 # . . call 597 e8/call flush/disp32 598 # . . discard args @@ -676,7 +676,7 @@ if ('onhashchange' in window) { 654 81 0/subop/add %esp 8/imm32 655 # subx-calls(_test-input-buffered-file, _test-output-buffered-file) 656 # . . push args - 657 68/push _test-output-buffered-file/imm32 + 657 68/push _test-output-buffered-file/imm32 658 68/push _test-input-buffered-file/imm32 659 # . . call 660 e8/call subx-calls/disp32 @@ -685,7 +685,7 @@ if ('onhashchange' in window) { 663 # check that the line just passed through 664 # . flush(_test-output-buffered-file) 665 # . . push args - 666 68/push _test-output-buffered-file/imm32 + 666 68/push _test-output-buffered-file/imm32 667 # . . call 668 e8/call flush/disp32 669 # . . discard args diff --git a/html/apps/crenshaw2-1.subx.html b/html/apps/crenshaw2-1.subx.html index 3f26523a..1c9ae904 100644 --- a/html/apps/crenshaw2-1.subx.html +++ b/html/apps/crenshaw2-1.subx.html @@ -385,7 +385,7 @@ if ('onhashchange' in window) { 324 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 325 # . clear-stream(_test-error-stream) 326 # . . push args -327 68/push _test-error-stream/imm32 +327 68/push _test-error-stream/imm32 328 # . . call 329 e8/call clear-stream/disp32 330 # . . discard args @@ -422,7 +422,7 @@ if ('onhashchange' in window) { 361 # get-num(in, out, err, ed) 362 # . . push args 363 50/push-eax/ed -364 68/push _test-error-stream/imm32 +364 68/push _test-error-stream/imm32 365 68/push _test-output-stream/imm32 366 68/push _test-buffered-file/imm32 367 # . . call @@ -474,7 +474,7 @@ if ('onhashchange' in window) { 413 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 414 # . clear-stream(_test-error-stream) 415 # . . push args -416 68/push _test-error-stream/imm32 +416 68/push _test-error-stream/imm32 417 # . . call 418 e8/call clear-stream/disp32 419 # . . discard args @@ -504,7 +504,7 @@ if ('onhashchange' in window) { 443 # get-num(in, out, err, ed) 444 # . . push args 445 50/push-eax/ed -446 68/push _test-error-stream/imm32 +446 68/push _test-error-stream/imm32 447 68/push _test-output-stream/imm32 448 68/push _test-buffered-file/imm32 449 # . . call diff --git a/html/apps/crenshaw2-1b.subx.html b/html/apps/crenshaw2-1b.subx.html index c4022fd8..01b29a6a 100644 --- a/html/apps/crenshaw2-1b.subx.html +++ b/html/apps/crenshaw2-1b.subx.html @@ -401,7 +401,7 @@ if ('onhashchange' in window) { 340 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 341 # . clear-stream(_test-error-stream) 342 # . . push args -343 68/push _test-error-stream/imm32 +343 68/push _test-error-stream/imm32 344 # . . call 345 e8/call clear-stream/disp32 346 # . . discard args @@ -438,7 +438,7 @@ if ('onhashchange' in window) { 377 # get-num(in, out, err, ed) 378 # . . push args 379 50/push-eax/ed -380 68/push _test-error-stream/imm32 +380 68/push _test-error-stream/imm32 381 68/push _test-output-stream/imm32 382 68/push _test-buffered-file/imm32 383 # . . call @@ -490,7 +490,7 @@ if ('onhashchange' in window) { 429 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 430 # . clear-stream(_test-error-stream) 431 # . . push args -432 68/push _test-error-stream/imm32 +432 68/push _test-error-stream/imm32 433 # . . call 434 e8/call clear-stream/disp32 435 # . . discard args @@ -520,7 +520,7 @@ if ('onhashchange' in window) { 459 # get-num(in, out, err, ed) 460 # . . push args 461 50/push-eax/ed -462 68/push _test-error-stream/imm32 +462 68/push _test-error-stream/imm32 463 68/push _test-output-stream/imm32 464 68/push _test-buffered-file/imm32 465 # . . call @@ -573,7 +573,7 @@ if ('onhashchange' in window) { 512 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 513 # . clear-stream(_test-error-stream) 514 # . . push args -515 68/push _test-error-stream/imm32 +515 68/push _test-error-stream/imm32 516 # . . call 517 e8/call clear-stream/disp32 518 # . . discard args @@ -610,7 +610,7 @@ if ('onhashchange' in window) { 549 # get-num(in, out, err, ed) 550 # . . push args 551 50/push-eax/ed -552 68/push _test-error-stream/imm32 +552 68/push _test-error-stream/imm32 553 68/push _test-output-stream/imm32 554 68/push _test-buffered-file/imm32 555 # . . call @@ -662,7 +662,7 @@ if ('onhashchange' in window) { 601 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 602 # . clear-stream(_test-error-stream) 603 # . . push args -604 68/push _test-error-stream/imm32 +604 68/push _test-error-stream/imm32 605 # . . call 606 e8/call clear-stream/disp32 607 # . . discard args @@ -699,7 +699,7 @@ if ('onhashchange' in window) { 638 # get-num(in, out, err, ed) 639 # . . push args 640 50/push-eax/ed -641 68/push _test-error-stream/imm32 +641 68/push _test-error-stream/imm32 642 68/push _test-output-stream/imm32 643 68/push _test-buffered-file/imm32 644 # . . call diff --git a/html/apps/dquotes.subx.html b/html/apps/dquotes.subx.html index aeefeaf7..17242e74 100644 --- a/html/apps/dquotes.subx.html +++ b/html/apps/dquotes.subx.html @@ -572,7 +572,7 @@ if ('onhashchange' in window) { 509 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 510 # subx-dquotes(_test-input-buffered-file, _test-output-buffered-file) 511 # . . push args - 512 68/push _test-output-buffered-file/imm32 + 512 68/push _test-output-buffered-file/imm32 513 68/push _test-input-buffered-file/imm32 514 # . . call 515 e8/call subx-dquotes/disp32 @@ -580,7 +580,7 @@ if ('onhashchange' in window) { 517 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 518 # . flush(_test-output-buffered-file) 519 # . . push args - 520 68/push _test-output-buffered-file/imm32 + 520 68/push _test-output-buffered-file/imm32 521 # . . call 522 e8/call flush/disp32 523 # . . discard args @@ -744,7 +744,7 @@ if ('onhashchange' in window) { 706 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 707 # subx-dquotes(_test-input-buffered-file, _test-output-buffered-file) 708 # . . push args - 709 68/push _test-output-buffered-file/imm32 + 709 68/push _test-output-buffered-file/imm32 710 68/push _test-input-buffered-file/imm32 711 # . . call 712 e8/call subx-dquotes/disp32 @@ -752,7 +752,7 @@ if ('onhashchange' in window) { 714 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 715 # . flush(_test-output-buffered-file) 716 # . . push args - 717 68/push _test-output-buffered-file/imm32 + 717 68/push _test-output-buffered-file/imm32 718 # . . call 719 e8/call flush/disp32 720 # . . discard args @@ -1382,14 +1382,14 @@ if ('onhashchange' in window) { 1501 # emit-metadata(_test-output-buffered-file, slice) 1502 # . . push args 1503 51/push-ecx -1504 68/push _test-output-buffered-file/imm32 +1504 68/push _test-output-buffered-file/imm32 1505 # . . call 1506 e8/call emit-metadata/disp32 1507 # . . discard args 1508 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1509 # flush(_test-output-buffered-file) 1510 # . . push args -1511 68/push _test-output-buffered-file/imm32 +1511 68/push _test-output-buffered-file/imm32 1512 # . . call 1513 e8/call flush/disp32 1514 # . . discard args @@ -1439,14 +1439,14 @@ if ('onhashchange' in window) { 1558 # emit-metadata(_test-output-buffered-file, slice) 1559 # . . push args 1560 51/push-ecx -1561 68/push _test-output-buffered-file/imm32 +1561 68/push _test-output-buffered-file/imm32 1562 # . . call 1563 e8/call emit-metadata/disp32 1564 # . . discard args 1565 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1566 # flush(_test-output-buffered-file) 1567 # . . push args -1568 68/push _test-output-buffered-file/imm32 +1568 68/push _test-output-buffered-file/imm32 1569 # . . call 1570 e8/call flush/disp32 1571 # . . discard args @@ -1496,14 +1496,14 @@ if ('onhashchange' in window) { 1615 # emit-metadata(_test-output-buffered-file, slice) 1616 # . . push args 1617 51/push-ecx -1618 68/push _test-output-buffered-file/imm32 +1618 68/push _test-output-buffered-file/imm32 1619 # . . call 1620 e8/call emit-metadata/disp32 1621 # . . discard args 1622 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1623 # flush(_test-output-buffered-file) 1624 # . . push args -1625 68/push _test-output-buffered-file/imm32 +1625 68/push _test-output-buffered-file/imm32 1626 # . . call 1627 e8/call flush/disp32 1628 # . . discard args @@ -1555,14 +1555,14 @@ if ('onhashchange' in window) { 1674 # emit-metadata(_test-output-buffered-file, slice) 1675 # . . push args 1676 51/push-ecx -1677 68/push _test-output-buffered-file/imm32 +1677 68/push _test-output-buffered-file/imm32 1678 # . . call 1679 e8/call emit-metadata/disp32 1680 # . . discard args 1681 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1682 # flush(_test-output-buffered-file) 1683 # . . push args -1684 68/push _test-output-buffered-file/imm32 +1684 68/push _test-output-buffered-file/imm32 1685 # . . call 1686 e8/call flush/disp32 1687 # . . discard args @@ -1607,14 +1607,14 @@ if ('onhashchange' in window) { 1726 # emit-metadata(_test-output-buffered-file, slice) 1727 # . . push args 1728 51/push-ecx -1729 68/push _test-output-buffered-file/imm32 +1729 68/push _test-output-buffered-file/imm32 1730 # . . call 1731 e8/call emit-metadata/disp32 1732 # . . discard args 1733 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1734 # flush(_test-output-buffered-file) 1735 # . . push args -1736 68/push _test-output-buffered-file/imm32 +1736 68/push _test-output-buffered-file/imm32 1737 # . . call 1738 e8/call flush/disp32 1739 # . . discard args diff --git a/html/apps/hex.subx.html b/html/apps/hex.subx.html index f9dfea23..dc2e9b88 100644 --- a/html/apps/hex.subx.html +++ b/html/apps/hex.subx.html @@ -286,7 +286,7 @@ if ('onhashchange' in window) { 225 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 226 # . clear-stream(_test-error-stream) 227 # . . push args - 228 68/push _test-error-stream/imm32 + 228 68/push _test-error-stream/imm32 229 # . . call 230 e8/call clear-stream/disp32 231 # . . discard args @@ -322,7 +322,7 @@ if ('onhashchange' in window) { 261 # eax = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed) 262 # . . push args 263 51/push-ecx/ed - 264 68/push _test-error-buffered-file/imm32 + 264 68/push _test-error-buffered-file/imm32 265 68/push _test-buffered-file/imm32 266 # . . call 267 e8/call convert-next-octet/disp32 @@ -384,7 +384,7 @@ if ('onhashchange' in window) { 323 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 324 # . clear-stream(_test-error-stream) 325 # . . push args - 326 68/push _test-error-stream/imm32 + 326 68/push _test-error-stream/imm32 327 # . . call 328 e8/call clear-stream/disp32 329 # . . discard args @@ -412,7 +412,7 @@ if ('onhashchange' in window) { 351 # eax = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed) 352 # . . push args 353 51/push-ecx/ed - 354 68/push _test-error-buffered-file/imm32 + 354 68/push _test-error-buffered-file/imm32 355 68/push _test-buffered-file/imm32 356 # . . call 357 e8/call convert-next-octet/disp32 @@ -474,7 +474,7 @@ if ('onhashchange' in window) { 413 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 414 # . clear-stream(_test-error-stream) 415 # . . push args - 416 68/push _test-error-stream/imm32 + 416 68/push _test-error-stream/imm32 417 # . . call 418 e8/call clear-stream/disp32 419 # . . discard args @@ -510,7 +510,7 @@ if ('onhashchange' in window) { 449 # eax = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed) 450 # . . push args 451 51/push-ecx/ed - 452 68/push _test-error-buffered-file/imm32 + 452 68/push _test-error-buffered-file/imm32 453 68/push _test-buffered-file/imm32 454 # . . call 455 e8/call convert-next-octet/disp32 @@ -643,7 +643,7 @@ if ('onhashchange' in window) { 582 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 583 # . clear-stream(_test-error-stream) 584 # . . push args - 585 68/push _test-error-stream/imm32 + 585 68/push _test-error-stream/imm32 586 # . . call 587 e8/call clear-stream/disp32 588 # . . discard args @@ -679,7 +679,7 @@ if ('onhashchange' in window) { 618 # eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) 619 # . . push args 620 51/push-ecx/ed - 621 68/push _test-error-buffered-file/imm32 + 621 68/push _test-error-buffered-file/imm32 622 68/push _test-buffered-file/imm32 623 # . . call 624 e8/call scan-next-byte/disp32 @@ -741,7 +741,7 @@ if ('onhashchange' in window) { 680 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 681 # . clear-stream(_test-error-stream) 682 # . . push args - 683 68/push _test-error-stream/imm32 + 683 68/push _test-error-stream/imm32 684 # . . call 685 e8/call clear-stream/disp32 686 # . . discard args @@ -777,7 +777,7 @@ if ('onhashchange' in window) { 716 # eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) 717 # . . push args 718 51/push-ecx/ed - 719 68/push _test-error-buffered-file/imm32 + 719 68/push _test-error-buffered-file/imm32 720 68/push _test-buffered-file/imm32 721 # . . call 722 e8/call scan-next-byte/disp32 @@ -839,7 +839,7 @@ if ('onhashchange' in window) { 778 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 779 # . clear-stream(_test-error-stream) 780 # . . push args - 781 68/push _test-error-stream/imm32 + 781 68/push _test-error-stream/imm32 782 # . . call 783 e8/call clear-stream/disp32 784 # . . discard args @@ -883,7 +883,7 @@ if ('onhashchange' in window) { 822 # eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) 823 # . . push args 824 51/push-ecx/ed - 825 68/push _test-error-buffered-file/imm32 + 825 68/push _test-error-buffered-file/imm32 826 68/push _test-buffered-file/imm32 827 # . . call 828 e8/call scan-next-byte/disp32 @@ -945,7 +945,7 @@ if ('onhashchange' in window) { 884 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 885 # . clear-stream(_test-error-stream) 886 # . . push args - 887 68/push _test-error-stream/imm32 + 887 68/push _test-error-stream/imm32 888 # . . call 889 e8/call clear-stream/disp32 890 # . . discard args @@ -989,7 +989,7 @@ if ('onhashchange' in window) { 928 # eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) 929 # . . push args 930 51/push-ecx/ed - 931 68/push _test-error-buffered-file/imm32 + 931 68/push _test-error-buffered-file/imm32 932 68/push _test-buffered-file/imm32 933 # . . call 934 e8/call scan-next-byte/disp32 @@ -1053,7 +1053,7 @@ if ('onhashchange' in window) { 992 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 993 # . clear-stream(_test-error-stream) 994 # . . push args - 995 68/push _test-error-stream/imm32 + 995 68/push _test-error-stream/imm32 996 # . . call 997 e8/call clear-stream/disp32 998 # . . discard args @@ -1097,7 +1097,7 @@ if ('onhashchange' in window) { 1036 # eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) 1037 # . . push args 1038 51/push-ecx/ed -1039 68/push _test-error-buffered-file/imm32 +1039 68/push _test-error-buffered-file/imm32 1040 68/push _test-buffered-file/imm32 1041 # . . call 1042 e8/call scan-next-byte/disp32 @@ -1159,7 +1159,7 @@ if ('onhashchange' in window) { 1098 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1099 # . clear-stream(_test-error-stream) 1100 # . . push args -1101 68/push _test-error-stream/imm32 +1101 68/push _test-error-stream/imm32 1102 # . . call 1103 e8/call clear-stream/disp32 1104 # . . discard args @@ -1195,7 +1195,7 @@ if ('onhashchange' in window) { 1134 # eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) 1135 # . . push args 1136 51/push-ecx/ed -1137 68/push _test-error-buffered-file/imm32 +1137 68/push _test-error-buffered-file/imm32 1138 68/push _test-buffered-file/imm32 1139 # . . call 1140 e8/call scan-next-byte/disp32 @@ -1257,7 +1257,7 @@ if ('onhashchange' in window) { 1196 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1197 # . clear-stream(_test-error-stream) 1198 # . . push args -1199 68/push _test-error-stream/imm32 +1199 68/push _test-error-stream/imm32 1200 # . . call 1201 e8/call clear-stream/disp32 1202 # . . discard args @@ -1285,7 +1285,7 @@ if ('onhashchange' in window) { 1224 # eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) 1225 # . . push args 1226 51/push-ecx/ed -1227 68/push _test-error-buffered-file/imm32 +1227 68/push _test-error-buffered-file/imm32 1228 68/push _test-buffered-file/imm32 1229 # . . call 1230 e8/call scan-next-byte/disp32 @@ -1347,7 +1347,7 @@ if ('onhashchange' in window) { 1286 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1287 # . clear-stream(_test-error-stream) 1288 # . . push args -1289 68/push _test-error-stream/imm32 +1289 68/push _test-error-stream/imm32 1290 # . . call 1291 e8/call clear-stream/disp32 1292 # . . discard args @@ -1383,7 +1383,7 @@ if ('onhashchange' in window) { 1322 # eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) 1323 # . . push args 1324 51/push-ecx/ed -1325 68/push _test-error-buffered-file/imm32 +1325 68/push _test-error-buffered-file/imm32 1326 68/push _test-buffered-file/imm32 1327 # . . call 1328 e8/call scan-next-byte/disp32 diff --git a/html/apps/mu.subx.html b/html/apps/mu.subx.html index 688c2b68..92d08cf4 100644 --- a/html/apps/mu.subx.html +++ b/html/apps/mu.subx.html @@ -450,9 +450,9 @@ if ('onhashchange' in window) { 388 55/push-ebp 389 89/<- %ebp 4/r32/esp 390 # - 391 (parse-mu *(ebp+8)) - 392 (check-mu-types) - 393 (emit-subx *(ebp+0xc)) + 391 (parse-mu *(ebp+8)) + 392 (check-mu-types) + 393 (emit-subx *(ebp+0xc)) 394 $convert-mu:end: 395 # . epilogue 396 89/<- %esp 5/r32/ebp @@ -470,8 +470,8 @@ if ('onhashchange' in window) { 408 (clear-stream _test-output-stream) 409 (clear-stream $_test-output-buffered-file->buffer) 410 # - 411 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 412 (flush _test-output-buffered-file) + 411 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 412 (flush _test-output-buffered-file) 413 (check-stream-equal _test-output-stream "" "F - test-convert-empty-input") 414 # . epilogue 415 89/<- %esp 5/r32/ebp @@ -491,8 +491,8 @@ if ('onhashchange' in window) { 429 (write _test-input-stream "fn foo {\n") 430 (write _test-input-stream "}\n") 431 # convert - 432 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 433 (flush _test-output-buffered-file) + 432 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 433 (flush _test-output-buffered-file) 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") @@ -523,8 +523,8 @@ if ('onhashchange' in window) { 466 (write _test-input-stream "fn bar {\n") 467 (write _test-input-stream "}\n") 468 # convert - 469 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 470 (flush _test-output-buffered-file) + 469 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 470 (flush _test-output-buffered-file) 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") @@ -562,8 +562,8 @@ if ('onhashchange' in window) { 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) + 513 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 514 (flush _test-output-buffered-file) 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") @@ -588,14 +588,14 @@ 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") 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) + 550 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 551 (flush _test-output-buffered-file) 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") @@ -625,14 +625,14 @@ 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") 590 (write _test-input-stream "}\n") 591 # convert - 592 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 593 (flush _test-output-buffered-file) + 592 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 593 (flush _test-output-buffered-file) 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") @@ -662,15 +662,15 @@ 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") 632 (write _test-input-stream " result <- increment\n") 633 (write _test-input-stream "}\n") 634 # convert - 635 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 636 (flush _test-output-buffered-file) + 635 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 636 (flush _test-output-buffered-file) 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") @@ -701,15 +701,15 @@ 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") 676 (write _test-input-stream " result <- add 1\n") 677 (write _test-input-stream "}\n") 678 # convert - 679 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 680 (flush _test-output-buffered-file) + 679 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 680 (flush _test-output-buffered-file) 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") @@ -740,15 +740,15 @@ 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") 720 (write _test-input-stream " result <- add 1\n") 721 (write _test-input-stream "}\n") 722 # convert - 723 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 724 (flush _test-output-buffered-file) + 723 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 724 (flush _test-output-buffered-file) 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") @@ -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") @@ -789,8 +789,8 @@ if ('onhashchange' in window) { 767 (write _test-input-stream " result <- add b\n") 768 (write _test-input-stream "}\n") 769 # convert - 770 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 771 (flush _test-output-buffered-file) + 770 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 771 (flush _test-output-buffered-file) 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") @@ -834,15 +834,15 @@ 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") 824 (write _test-input-stream " increment x\n") 825 (write _test-input-stream "}\n") 826 # convert - 827 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 828 (flush _test-output-buffered-file) + 827 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 828 (flush _test-output-buffered-file) 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") @@ -874,15 +874,15 @@ 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") 869 (write _test-input-stream " x <- increment\n") 870 (write _test-input-stream "}\n") 871 # convert - 872 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 873 (flush _test-output-buffered-file) + 872 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 873 (flush _test-output-buffered-file) 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") @@ -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") @@ -924,8 +924,8 @@ if ('onhashchange' in window) { 917 (write _test-input-stream " }\n") 918 (write _test-input-stream "}\n") 919 # convert - 920 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 921 (flush _test-output-buffered-file) + 920 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 921 (flush _test-output-buffered-file) 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") @@ -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") @@ -970,8 +970,8 @@ if ('onhashchange' in window) { 968 (write _test-input-stream " }\n") 969 (write _test-input-stream "}\n") 970 # convert - 971 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 972 (flush _test-output-buffered-file) + 971 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 972 (flush _test-output-buffered-file) 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") @@ -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") @@ -1018,8 +1018,8 @@ if ('onhashchange' in window) { 1021 (write _test-input-stream " }\n") 1022 (write _test-input-stream "}\n") 1023 # convert -1024 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1025 (flush _test-output-buffered-file) +1024 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1025 (flush _test-output-buffered-file) 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") @@ -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") @@ -1067,8 +1067,8 @@ if ('onhashchange' in window) { 1075 (write _test-input-stream " }\n") 1076 (write _test-input-stream "}\n") 1077 # convert -1078 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1079 (flush _test-output-buffered-file) +1078 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1079 (flush _test-output-buffered-file) 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") @@ -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") @@ -1116,8 +1116,8 @@ if ('onhashchange' in window) { 1129 (write _test-input-stream " }\n") 1130 (write _test-input-stream "}\n") 1131 # convert -1132 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1133 (flush _test-output-buffered-file) +1132 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1133 (flush _test-output-buffered-file) 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") @@ -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") @@ -1169,8 +1169,8 @@ if ('onhashchange' in window) { 1187 (write _test-input-stream " }\n") 1188 (write _test-input-stream "}\n") 1189 # convert -1190 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1191 (flush _test-output-buffered-file) +1190 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1191 (flush _test-output-buffered-file) 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") @@ -1205,6886 +1205,7093 @@ if ('onhashchange' in window) { 1228 c3/return 1229 1230 test-convert-function-with-branches-and-local-vars: -1231 # A 'break' after a 'var' in a block creates a nested block for the remaining statements. -1232 # That way we always clean up all the 'var's. -1233 # . prologue -1234 55/push-ebp -1235 89/<- %ebp 4/r32/esp -1236 # setup -1237 (clear-stream _test-input-stream) -1238 (clear-stream $_test-input-buffered-file->buffer) -1239 (clear-stream _test-output-stream) -1240 (clear-stream $_test-output-buffered-file->buffer) -1241 c7 0/subop/copy *Next-block-index 1/imm32 -1242 # -1243 (write _test-input-stream "fn foo {\n") -1244 (write _test-input-stream " {\n") -1245 (write _test-input-stream " var x: int\n") -1246 (write _test-input-stream " break-if->=\n") -1247 (write _test-input-stream " increment x\n") -1248 (write _test-input-stream " }\n") -1249 (write _test-input-stream "}\n") -1250 # convert -1251 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1252 (flush _test-output-buffered-file) -1253 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1259 # check output -1260 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-local-vars/0") -1261 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-local-vars/1") -1262 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-local-vars/2") -1263 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-and-local-vars/3") -1264 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/4") -1265 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-and-local-vars/5") -1266 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/6") -1267 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-and-local-vars/7") -1268 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-local-vars/8") -1269 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/9") -1270 (check-next-stream-line-equal _test-output-stream " 0f 8d/jump-if->= break/disp32" "F - test-convert-function-with-branches-and-local-vars/10") -1271 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-branches-and-local-vars/11") -1272 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/12") -1273 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-branches-and-local-vars/13") -1274 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/14") -1275 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-and-local-vars/15") -1276 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/16") -1277 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-and-local-vars/17") -1278 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-local-vars/18") -1279 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-and-local-vars/19") -1280 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-local-vars/20") -1281 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-local-vars/21") -1282 # . epilogue -1283 89/<- %esp 5/r32/ebp -1284 5d/pop-to-ebp -1285 c3/return -1286 -1287 test-convert-function-with-loops-and-local-vars: -1288 # A 'loop' after a 'var' in a block is converted into a block that -1289 # performs all necessary cleanup before jumping. This results in some ugly -1290 # code duplication. -1291 # . prologue -1292 55/push-ebp -1293 89/<- %ebp 4/r32/esp -1294 # setup -1295 (clear-stream _test-input-stream) -1296 (clear-stream $_test-input-buffered-file->buffer) -1297 (clear-stream _test-output-stream) -1298 (clear-stream $_test-output-buffered-file->buffer) -1299 c7 0/subop/copy *Next-block-index 1/imm32 -1300 # -1301 (write _test-input-stream "fn foo {\n") -1302 (write _test-input-stream " {\n") -1303 (write _test-input-stream " var x: int\n") -1304 (write _test-input-stream " loop-if->=\n") -1305 (write _test-input-stream " increment x\n") -1306 (write _test-input-stream " }\n") -1307 (write _test-input-stream "}\n") -1308 # convert -1309 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1310 (flush _test-output-buffered-file) -1311 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1317 # check output -1318 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-loops-and-local-vars/0") -1319 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-loops-and-local-vars/1") -1320 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-loops-and-local-vars/2") -1321 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-loops-and-local-vars/3") -1322 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-loops-and-local-vars/4") -1323 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-loops-and-local-vars/5") -1324 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-loops-and-local-vars/6") -1325 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-loops-and-local-vars/7") -1326 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-loops-and-local-vars/8") -1327 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-loops-and-local-vars/9") -1328 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-loops-and-local-vars/10") -1329 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-loops-and-local-vars/11") -1330 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:loop/disp32" "F - test-convert-function-with-loops-and-local-vars/12") -1331 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-loops-and-local-vars/13") -1332 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-loops-and-local-vars/14") -1333 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-loops-and-local-vars/15") -1334 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-loops-and-local-vars/16") -1335 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-loops-and-local-vars/17") -1336 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-loops-and-local-vars/18") -1337 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-loops-and-local-vars/19") -1338 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-loops-and-local-vars/20") -1339 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-loops-and-local-vars/21") -1340 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-loops-and-local-vars/22") -1341 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-loops-and-local-vars/23") -1342 # . epilogue -1343 89/<- %esp 5/r32/ebp -1344 5d/pop-to-ebp -1345 c3/return -1346 -1347 ####################################################### -1348 # Parsing -1349 ####################################################### -1350 -1351 parse-mu: # in: (addr buffered-file) -1352 # pseudocode -1353 # var curr-function: (addr (handle function)) = Program -1354 # var line: (stream byte 512) -1355 # var word-slice: slice -1356 # while true # line loop -1357 # clear-stream(line) -1358 # read-line-buffered(in, line) -1359 # if (line->write == 0) break # end of file -1360 # word-slice = next-mu-token(line) -1361 # if slice-empty?(word-slice) # end of line -1362 # continue -1363 # else if slice-starts-with?(word-slice, "#") # comment -1364 # continue # end of line -1365 # else if slice-equal(word-slice, "fn") -1366 # var new-function: (handle function) = allocate(function) -1367 # var vars: (stack (addr var) 256) -1368 # populate-mu-function-header(in, new-function, vars) -1369 # populate-mu-function-body(in, new-function, vars) -1370 # assert(vars->top == 0) -1371 # *curr-function = new-function -1372 # curr-function = &new-function->next -1373 # else -1374 # abort() -1375 # -1376 # . prologue -1377 55/push-ebp -1378 89/<- %ebp 4/r32/esp -1379 # . save registers -1380 50/push-eax -1381 51/push-ecx -1382 52/push-edx -1383 53/push-ebx -1384 57/push-edi -1385 # var line/ecx: (stream byte 512) -1386 81 5/subop/subtract %esp 0x200/imm32 -1387 68/push 0x200/imm32/length -1388 68/push 0/imm32/read -1389 68/push 0/imm32/write -1390 89/<- %ecx 4/r32/esp -1391 # var word-slice/edx: slice -1392 68/push 0/imm32/end -1393 68/push 0/imm32/start -1394 89/<- %edx 4/r32/esp -1395 # var curr-function/edi: (addr (handle function)) = Program -1396 bf/copy-to-edi Program/imm32 -1397 # var vars/ebx: (stack (addr var) 256) -1398 81 5/subop/subtract %esp 0x400/imm32 -1399 68/push 0x400/imm32/length -1400 68/push 0/imm32/top -1401 89/<- %ebx 4/r32/esp -1402 { -1403 $parse-mu:line-loop: -1404 (clear-stream %ecx) -1405 (read-line-buffered *(ebp+8) %ecx) -1406 # if (line->write == 0) break -1407 81 7/subop/compare *ecx 0/imm32 -1408 0f 84/jump-if-= break/disp32 -1409 +-- 6 lines: #? # dump line --------------------------------------------------------------------------------------------------------------------------- -1415 (next-mu-token %ecx %edx) -1416 # if slice-empty?(word-slice) continue -1417 (slice-empty? %edx) -1418 3d/compare-eax-and 0/imm32 -1419 0f 85/jump-if-!= loop/disp32 -1420 # if (*word-slice->start == "#") continue -1421 # . eax = *word-slice->start -1422 8b/-> *edx 0/r32/eax -1423 8a/copy-byte *eax 0/r32/AL -1424 81 4/subop/and %eax 0xff/imm32 -1425 # . if (eax == '#') continue -1426 3d/compare-eax-and 0x23/imm32/hash -1427 0f 84/jump-if-= loop/disp32 -1428 # if (slice-equal?(word-slice, "fn")) parse a function -1429 { -1430 $parse-mu:fn: -1431 (slice-equal? %edx "fn") -1432 3d/compare-eax-and 0/imm32 -1433 0f 84/jump-if-= break/disp32 -1434 # var new-function/eax: (handle function) = populate-mu-function(in, new-function, vars) -1435 (allocate Heap *Function-size) # => eax -1436 (zero-out %eax *Function-size) -1437 (clear-stack %ebx) -1438 (populate-mu-function-header %ecx %eax %ebx) -1439 (populate-mu-function-body *(ebp+8) %eax %ebx) -1440 # *curr-function = new-function -1441 89/<- *edi 0/r32/eax -1442 # curr-function = &new-function->next -1443 8d/address-> *(eax+0x14) 7/r32/edi # Function-next -1444 e9/jump $parse-mu:line-loop/disp32 -1445 } -1446 # otherwise abort -1447 e9/jump $parse-mu:error1/disp32 -1448 } # end line loop -1449 $parse-mu:end: -1450 # . reclaim locals -1451 81 0/subop/add %esp 0x630/imm32 -1452 # . restore registers -1453 5f/pop-to-edi -1454 5b/pop-to-ebx -1455 5a/pop-to-edx -1456 59/pop-to-ecx -1457 58/pop-to-eax -1458 # . epilogue -1459 89/<- %esp 5/r32/ebp -1460 5d/pop-to-ebp -1461 c3/return -1462 -1463 $parse-mu:error1: -1464 # error("unexpected top-level command: " word-slice "\n") -1465 (write-buffered Stderr "unexpected top-level command: ") -1466 (write-slice-buffered Stderr %edx) -1467 (write-buffered Stderr "\n") -1468 (flush Stderr) -1469 # . syscall(exit, 1) -1470 bb/copy-to-ebx 1/imm32 -1471 b8/copy-to-eax 1/imm32/exit -1472 cd/syscall 0x80/imm8 -1473 # never gets here -1474 -1475 $parse-mu:error2: -1476 # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n") -1477 (print-int32-buffered Stderr *ebx) -1478 (write-buffered Stderr " vars not reclaimed after fn '") -1479 (write-slice-buffered Stderr *eax) # Function-name -1480 (write-buffered Stderr "'\n") -1481 (flush Stderr) -1482 # . syscall(exit, 1) -1483 bb/copy-to-ebx 1/imm32 -1484 b8/copy-to-eax 1/imm32/exit -1485 cd/syscall 0x80/imm8 -1486 # never gets here -1487 -1488 # scenarios considered: -1489 # ✗ fn foo # no block -1490 # ✓ fn foo { -1491 # ✗ fn foo { { -1492 # ✗ fn foo { } -1493 # ✗ fn foo { } { -1494 # ✗ fn foo x { -1495 # ✗ fn foo x: { -1496 # ✓ fn foo x: int { -1497 # ✓ fn foo x: int { -1498 # ✓ fn foo x: int -> y/eax: int { -1499 populate-mu-function-header: # first-line: (addr stream byte), out: (handle function), vars: (addr stack (handle var)) -1500 # pseudocode: -1501 # var name: slice -1502 # next-word(first-line, name) -1503 # assert(name not in '{' '}' '->') -1504 # out->name = slice-to-string(name) -1505 # var next-offset: int = 8 -1506 # ## inouts -1507 # while true -1508 # ## name -1509 # name = next-word(first-line) -1510 # if (name == '{') goto done -1511 # if (name == '->') break -1512 # assert(name != '}') -1513 # var v: (handle var) = parse-var-with-type(name, first-line) -1514 # assert(v->register == null) -1515 # v->stack-offset = next-offset -1516 # next-offset += size-of(v) -1517 # # v->block-depth is implicitly 0 -1518 # out->inouts = append(out->inouts, v) -1519 # push(vars, v) -1520 # ## outputs -1521 # while true -1522 # ## name -1523 # name = next-word(first-line) -1524 # assert(name not in '{' '}' '->') -1525 # var v: (handle var) = parse-var-with-type(name, first-line) -1526 # assert(v->register != null) -1527 # out->outputs = append(out->outputs, v) -1528 # done: -1529 # -1530 # . prologue -1531 55/push-ebp -1532 89/<- %ebp 4/r32/esp -1533 # . save registers -1534 50/push-eax -1535 51/push-ecx -1536 52/push-edx -1537 53/push-ebx -1538 57/push-edi -1539 # edi = out -1540 8b/-> *(ebp+0xc) 7/r32/edi -1541 # var word-slice/ecx: slice -1542 68/push 0/imm32/end -1543 68/push 0/imm32/start -1544 89/<- %ecx 4/r32/esp -1545 # var next-offset/edx = 8 -1546 ba/copy-to-edx 8/imm32 -1547 # read function name -1548 (next-word *(ebp+8) %ecx) -1549 # error checking -1550 # TODO: error if name starts with 'break' or 'loop' -1551 # if (word-slice == '{') abort -1552 (slice-equal? %ecx "{") # => eax -1553 3d/compare-eax-and 0/imm32 -1554 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1555 # if (word-slice == '->') abort -1556 (slice-equal? %ecx "->") # => eax -1557 3d/compare-eax-and 0/imm32 -1558 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1559 # if (word-slice == '}') abort -1560 (slice-equal? %ecx "}") # => eax -1561 3d/compare-eax-and 0/imm32 -1562 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1563 # save function name -1564 (slice-to-string Heap %ecx) # => eax -1565 89/<- *edi 0/r32/eax # Function-name -1566 # initialize default subx-name as well -1567 89/<- *(edi+4) 0/r32/eax # Function-subx-name -1568 # save function inouts -1569 { -1570 $populate-mu-function-header:check-for-inout: -1571 (next-word *(ebp+8) %ecx) -1572 # if (word-slice == '{') goto done -1573 (slice-equal? %ecx "{") # => eax -1574 3d/compare-eax-and 0/imm32 -1575 0f 85/jump-if-!= $populate-mu-function-header:done/disp32 -1576 # if (word-slice == '->') break -1577 (slice-equal? %ecx "->") # => eax -1578 3d/compare-eax-and 0/imm32 -1579 0f 85/jump-if-!= break/disp32 -1580 # if (word-slice == '}') abort -1581 (slice-equal? %ecx "}") # => eax -1582 3d/compare-eax-and 0/imm32 -1583 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1584 # var v/ebx: (handle var) = parse-var-with-type(word-slice, first-line) -1585 (parse-var-with-type %ecx *(ebp+8)) # => eax -1586 89/<- %ebx 0/r32/eax -1587 # assert(v->register == null) -1588 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -1589 0f 85/jump-if-!= $populate-mu-function-header:error2/disp32 -1590 # v->stack-offset = next-offset -1591 89/<- *(ebx+0xc) 2/r32/edx # Var-stack-offset -1592 # next-offset += size-of(v) -1593 (size-of %ebx) # => eax -1594 01/add %edx 0/r32/eax -1595 # v->block-depth is implicitly 0 -1596 # -1597 (append-list Heap %ebx *(edi+8)) # Function-inouts => eax -1598 89/<- *(edi+8) 0/r32/eax # Function-inouts -1599 (push *(ebp+0x10) %ebx) -1600 # -1601 e9/jump loop/disp32 -1602 } -1603 # save function outputs -1604 { -1605 $parse-var-with-type:check-for-out: -1606 (next-word *(ebp+8) %ecx) -1607 # if (word-slice == '{') break -1608 (slice-equal? %ecx "{") # => eax -1609 3d/compare-eax-and 0/imm32 -1610 0f 85/jump-if-!= break/disp32 -1611 # if (word-slice == '->') abort -1612 (slice-equal? %ecx "->") # => eax -1613 3d/compare-eax-and 0/imm32 -1614 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1615 # if (word-slice == '}') abort -1616 (slice-equal? %ecx "}") # => eax -1617 3d/compare-eax-and 0/imm32 -1618 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1619 # -1620 (parse-var-with-type %ecx *(ebp+8)) # => eax -1621 89/<- %ebx 0/r32/eax -1622 # assert(var->register != null) -1623 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -1624 0f 84/jump-if-= $populate-mu-function-header:error3/disp32 -1625 (append-list Heap %ebx *(edi+0xc)) # Function-outputs => eax -1626 89/<- *(edi+0xc) 0/r32/eax # Function-outputs -1627 e9/jump loop/disp32 -1628 } -1629 $populate-mu-function-header:done: -1630 (check-no-tokens-left *(ebp+8)) -1631 $populate-mu-function-header:end: -1632 # . reclaim locals -1633 81 0/subop/add %esp 8/imm32 -1634 # . restore registers -1635 5f/pop-to-edi -1636 5b/pop-to-ebx -1637 5a/pop-to-edx -1638 59/pop-to-ecx -1639 58/pop-to-eax -1640 # . epilogue -1641 89/<- %esp 5/r32/ebp -1642 5d/pop-to-ebp -1643 c3/return -1644 -1645 $populate-mu-function-header:error1: -1646 # error("function header not in form 'fn <name> {'") -1647 (write-buffered Stderr "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '") -1648 (flush Stderr) -1649 (rewind-stream *(ebp+8)) -1650 (write-stream 2 *(ebp+8)) -1651 (write-buffered Stderr "'\n") -1652 (flush Stderr) -1653 # . syscall(exit, 1) -1654 bb/copy-to-ebx 1/imm32 -1655 b8/copy-to-eax 1/imm32/exit -1656 cd/syscall 0x80/imm8 -1657 # never gets here -1658 -1659 $populate-mu-function-header:error2: -1660 # error("function input '" var "' cannot be in a register") -1661 (write-buffered Stderr "function input '") -1662 (write-buffered Stderr *ebx) # Var-name -1663 (write-buffered Stderr "' cannot be in a register") -1664 (flush Stderr) -1665 # . syscall(exit, 1) -1666 bb/copy-to-ebx 1/imm32 -1667 b8/copy-to-eax 1/imm32/exit -1668 cd/syscall 0x80/imm8 -1669 # never gets here -1670 -1671 $populate-mu-function-header:error3: -1672 # error("function input '" var "' must be in a register") -1673 (write-buffered Stderr "function input '") -1674 (write-buffered Stderr *eax) # Var-name -1675 (write-buffered Stderr " must be in a register'") -1676 (flush Stderr) -1677 (rewind-stream *(ebp+8)) -1678 (write-stream 2 *(ebp+8)) -1679 (write-buffered Stderr "'\n") -1680 (flush Stderr) -1681 # . syscall(exit, 1) -1682 bb/copy-to-ebx 1/imm32 -1683 b8/copy-to-eax 1/imm32/exit -1684 cd/syscall 0x80/imm8 -1685 # never gets here -1686 -1687 test-function-header-with-arg: -1688 # . prologue -1689 55/push-ebp -1690 89/<- %ebp 4/r32/esp -1691 # setup -1692 (clear-stream _test-input-stream) -1693 (write _test-input-stream "foo n : int {\n") -1694 # var result/ecx: function -1695 2b/subtract-> *Function-size 4/r32/esp -1696 89/<- %ecx 4/r32/esp -1697 (zero-out %ecx *Function-size) -1698 # var vars/ebx: (stack (addr var) 16) -1699 81 5/subop/subtract %esp 0x10/imm32 -1700 68/push 0x10/imm32/length -1701 68/push 0/imm32/top -1702 89/<- %ebx 4/r32/esp -1703 # convert -1704 (populate-mu-function-header _test-input-stream %ecx %ebx) -1705 # check result -1706 (check-strings-equal *ecx "foo" "F - test-function-header-with-arg/name") # Function-name -1707 # edx: (handle list var) = result->inouts -1708 8b/-> *(ecx+8) 2/r32/edx # Function-inouts -1709 # ebx: (handle var) = result->inouts->value -1710 8b/-> *edx 3/r32/ebx # List-value -1711 (check-strings-equal *ebx "n" "F - test-function-header-with-arg/inout:0") # Var-name -1712 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1713 (check-ints-equal *ebx 1 "F - test-function-header-with-arg/inout:0/type:0") # Tree-left -1714 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-arg/inout:0/type:1") # Tree-right -1715 # . epilogue -1716 89/<- %esp 5/r32/ebp -1717 5d/pop-to-ebp -1718 c3/return -1719 -1720 test-function-header-with-multiple-args: -1721 # . prologue -1722 55/push-ebp -1723 89/<- %ebp 4/r32/esp -1724 # setup -1725 (clear-stream _test-input-stream) -1726 (write _test-input-stream "foo a: int, b: int c: int {\n") -1727 # result/ecx: (handle function) -1728 2b/subtract-> *Function-size 4/r32/esp -1729 89/<- %ecx 4/r32/esp -1730 (zero-out %ecx *Function-size) -1731 # var vars/ebx: (stack (addr var) 16) -1732 81 5/subop/subtract %esp 0x10/imm32 -1733 68/push 0x10/imm32/length -1734 68/push 0/imm32/top -1735 89/<- %ebx 4/r32/esp -1736 # convert -1737 (populate-mu-function-header _test-input-stream %ecx %ebx) -1738 # check result -1739 (check-strings-equal *ecx "foo") # Function-name -1740 # edx: (handle list var) = result->inouts -1741 8b/-> *(ecx+8) 2/r32/edx # Function-inouts -1742 $test-function-header-with-multiple-args:inout0: -1743 # ebx: (handle var) = result->inouts->value -1744 8b/-> *edx 3/r32/ebx # List-value -1745 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name -1746 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1747 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:0/type:0") # Tree-left -1748 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:0/type:1") # Tree-right -1749 # edx = result->inouts->next -1750 8b/-> *(edx+4) 2/r32/edx # List-next -1751 $test-function-header-with-multiple-args:inout1: -1752 # ebx = result->inouts->next->value -1753 8b/-> *edx 3/r32/ebx # List-value -1754 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args/inout:1") # Var-name -1755 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1756 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:1/type:0") # Tree-left -1757 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:1/type:1") # Tree-right -1758 # edx = result->inouts->next->next -1759 8b/-> *(edx+4) 2/r32/edx # List-next -1760 $test-function-header-with-multiple-args:inout2: -1761 # ebx = result->inouts->next->next->value -1762 8b/-> *edx 3/r32/ebx # List-value -1763 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args/inout:2") # Var-name -1764 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1765 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:2/type:0") # Tree-left -1766 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:2/type:1") # Tree-right -1767 # . epilogue -1768 89/<- %esp 5/r32/ebp -1769 5d/pop-to-ebp -1770 c3/return -1771 -1772 test-function-with-multiple-args-and-outputs: -1773 # . prologue -1774 55/push-ebp -1775 89/<- %ebp 4/r32/esp -1776 # setup -1777 (clear-stream _test-input-stream) -1778 (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx: int {\n") -1779 # result/ecx: (handle function) -1780 2b/subtract-> *Function-size 4/r32/esp -1781 89/<- %ecx 4/r32/esp -1782 (zero-out %ecx *Function-size) -1783 # var vars/ebx: (stack (addr var) 16) -1784 81 5/subop/subtract %esp 0x10/imm32 -1785 68/push 0x10/imm32/length -1786 68/push 0/imm32/top -1787 89/<- %ebx 4/r32/esp -1788 # convert -1789 (populate-mu-function-header _test-input-stream %ecx %ebx) -1790 # check result -1791 (check-strings-equal *ecx "foo") # Function-name -1792 # edx: (handle list var) = result->inouts -1793 8b/-> *(ecx+8) 2/r32/edx # Function-inouts -1794 # ebx: (handle var) = result->inouts->value -1795 8b/-> *edx 3/r32/ebx # List-value -1796 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0") # Var-name -1797 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1798 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0") # Tree-left -1799 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1") # Tree-right -1800 # edx = result->inouts->next -1801 8b/-> *(edx+4) 2/r32/edx # List-next -1802 # ebx = result->inouts->next->value -1803 8b/-> *edx 3/r32/ebx # List-value -1804 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1") # Var-name -1805 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1806 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0") # Tree-left -1807 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1") # Tree-right -1808 # edx = result->inouts->next->next -1809 8b/-> *(edx+4) 2/r32/edx # List-next -1810 # ebx = result->inouts->next->next->value -1811 8b/-> *edx 3/r32/ebx # List-value -1812 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2") # Var-name -1813 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1814 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0") # Tree-left -1815 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1") # Tree-right -1816 # edx: (handle list var) = result->outputs -1817 8b/-> *(ecx+0xc) 2/r32/edx # Function-outputs -1818 # ebx: (handle var) = result->outputs->value -1819 8b/-> *edx 3/r32/ebx # List-value -1820 (check-strings-equal *ebx "x" "F - test-function-header-with-multiple-args-and-outputs/output:0") # Var-name -1821 (check-strings-equal *(ebx+0x10) "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register -1822 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1823 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-left -1824 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-right -1825 # edx = result->outputs->next -1826 8b/-> *(edx+4) 2/r32/edx # List-next -1827 # ebx = result->outputs->next->value -1828 8b/-> *edx 3/r32/ebx # List-value -1829 (check-strings-equal *ebx "y" "F - test-function-header-with-multiple-args-and-outputs/output:1") # Var-name -1830 (check-strings-equal *(ebx+0x10) "edx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register -1831 8b/-> *(ebx+4) 3/r32/ebx # Var-type -1832 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-left -1833 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-right -1834 # . epilogue -1835 89/<- %esp 5/r32/ebp -1836 5d/pop-to-ebp -1837 c3/return -1838 -1839 # format for variables with types -1840 # x: int -1841 # x: int -1842 # x: int, -1843 # ignores at most one trailing colon or comma -1844 parse-var-with-type: # name: (addr slice), first-line: (addr stream byte) -> result/eax: (handle var) -1845 # pseudocode: -1846 # var v: (handle var) = allocate(Heap, Var-size) -1847 # var s: slice -1848 # next-token-from-slice(name->start, name->end, '/', s) -1849 # var end: (addr byte) = s->end -1850 # if (slice-ends-with(s, ":")) -1851 # decrement s->end -1852 # if (slice-ends-with(s, ",")) -1853 # decrement s->end -1854 # v->name = slice-to-string(s) -1855 # ## register -1856 # next-token-from-slice(end, name->end, '/', s) -1857 # if (slice-ends-with(s, ":")) -1858 # decrement s->end -1859 # if (slice-ends-with(s, ",")) -1860 # decrement s->end -1861 # if (!slice-empty?(s)) -1862 # v->register = slice-to-string(s) -1863 # ## type -1864 # var type: (handle tree type-id) = parse-type(first-line) -1865 # v->type = type -1866 # return v -1867 # -1868 # . prologue -1869 55/push-ebp -1870 89/<- %ebp 4/r32/esp -1871 # . save registers -1872 51/push-ecx -1873 52/push-edx -1874 53/push-ebx -1875 56/push-esi -1876 57/push-edi -1877 # var result/edi: (handle var) = allocate(Heap, Var-size) -1878 (allocate Heap *Var-size) # => eax -1879 (zero-out %eax *Var-size) -1880 89/<- %edi 0/r32/eax -1881 # esi = name -1882 8b/-> *(ebp+8) 6/r32/esi -1883 # var s/ecx: slice -1884 68/push 0/imm32/end -1885 68/push 0/imm32/start -1886 89/<- %ecx 4/r32/esp -1887 $parse-var-with-type:save-name: -1888 # save v->name -1889 (next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/' -1890 # . end/edx = s->end -1891 8b/-> *(ecx+4) 2/r32/edx -1892 # . if s ends with ':', decrement s->end -1893 { -1894 8b/-> *(ecx+4) 0/r32/eax -1895 48/decrement-eax -1896 8a/copy-byte *eax 3/r32/BL -1897 81 4/subop/and %ebx 0xff/imm32 -1898 81 7/subop/compare %ebx 0x3a/imm32/colon -1899 75/jump-if-!= break/disp8 -1900 89/<- *(ecx+4) 0/r32/eax -1901 } -1902 # . if s ends with ',', decrement s->end -1903 { -1904 8b/-> *(ecx+4) 0/r32/eax -1905 48/decrement-eax -1906 8a/copy-byte *eax 3/r32/BL -1907 81 4/subop/and %ebx 0xff/imm32 -1908 81 7/subop/compare %ebx 0x2c/imm32/comma -1909 75/jump-if-!= break/disp8 -1910 89/<- *(ecx+4) 0/r32/eax -1911 } -1912 $parse-var-with-type:write-name: -1913 (slice-to-string Heap %ecx) # => eax -1914 89/<- *edi 0/r32/eax # Var-name -1915 # save v->register -1916 $parse-var-with-type:save-register: -1917 (next-token-from-slice %edx *(esi+4) 0x2f %ecx) # end, name->end, '/' -1918 # . if s ends with ':', decrement s->end -1919 { -1920 8b/-> *(ecx+4) 0/r32/eax -1921 48/decrement-eax -1922 8a/copy-byte *eax 3/r32/BL -1923 81 4/subop/and %ebx 0xff/imm32 -1924 81 7/subop/compare %ebx 0x3a/imm32/colon -1925 75/jump-if-!= break/disp8 -1926 89/<- *(ecx+4) 0/r32/eax -1927 } -1928 # . if s ends with ',', decrement s->end -1929 { -1930 8b/-> *(ecx+4) 0/r32/eax -1931 48/decrement-eax -1932 8a/copy-byte *eax 3/r32/BL -1933 81 4/subop/and %ebx 0xff/imm32 -1934 81 7/subop/compare %ebx 0x2c/imm32/comma -1935 75/jump-if-!= break/disp8 -1936 89/<- *(ecx+4) 0/r32/eax -1937 } -1938 # if (!slice-empty?(s)) v->register = slice-to-string(s) -1939 { -1940 $parse-var-with-type:write-register: -1941 # HACK: s->end can be less than s->start with all the decrements above -1942 # That's probably a sign we have the wrong algorithm for this function. -1943 8b/-> *ecx 0/r32/eax -1944 39/compare *(ecx+4) 0/r32/eax # Slice-end -1945 76/jump-if-<= break/disp8 -1946 (slice-to-string Heap %ecx) -1947 89/<- *(edi+0x10) 0/r32/eax # Var-register -1948 } -1949 $parse-var-with-type:save-type: -1950 (parse-type Heap *(ebp+0xc)) # => eax -1951 89/<- *(edi+4) 0/r32/eax # Var-type -1952 $parse-var-with-type:end: -1953 # return result -1954 89/<- %eax 7/r32/edi -1955 # . reclaim locals -1956 81 0/subop/add %esp 8/imm32 -1957 # . restore registers -1958 5f/pop-to-edi -1959 5e/pop-to-esi -1960 5b/pop-to-ebx -1961 5a/pop-to-edx -1962 59/pop-to-ecx -1963 # . epilogue -1964 89/<- %esp 5/r32/ebp -1965 5d/pop-to-ebp -1966 c3/return -1967 -1968 $parse-var-with-type:abort: -1969 # error("function header not in form 'fn <name> {'") -1970 (write-buffered Stderr "var should have form 'name: type' in '") -1971 (flush Stderr) -1972 (rewind-stream *(ebp+0xc)) -1973 (write-stream 2 *(ebp+0xc)) -1974 (write-buffered Stderr "'\n") -1975 (flush Stderr) -1976 # . syscall(exit, 1) -1977 bb/copy-to-ebx 1/imm32 -1978 b8/copy-to-eax 1/imm32/exit -1979 cd/syscall 0x80/imm8 -1980 # never gets here -1981 -1982 parse-type: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) -1983 # pseudocode: -1984 # var s: slice = next-mu-token(in) -1985 # assert s != "" -1986 # assert s != "->" -1987 # assert s != "{" -1988 # assert s != "}" -1989 # if s == ")" -1990 # return 0 -1991 # result = allocate(Tree) -1992 # zero-out(result, *Tree-size) -1993 # if s != "(" -1994 # result->left = pos-slice(Type-id, s) -1995 # return -1996 # result->left = parse-type(ad, in) -1997 # result->right = parse-type-tree(ad, in) -1998 # -1999 # . prologue -2000 55/push-ebp -2001 89/<- %ebp 4/r32/esp -2002 # . save registers -2003 51/push-ecx -2004 52/push-edx -2005 # var s/ecx: slice -2006 68/push 0/imm32 -2007 68/push 0/imm32 -2008 89/<- %ecx 4/r32/esp -2009 # s = next-mu-token(in) -2010 (next-mu-token *(ebp+0xc) %ecx) -2011 #? (write-buffered Stderr "tok: ") -2012 #? (write-slice-buffered Stderr %ecx) -2013 #? (write-buffered Stderr "$\n") -2014 #? (flush Stderr) -2015 # assert s != "" -2016 (slice-equal? %ecx "") -2017 3d/compare-eax-and 0/imm32 -2018 0f 85/jump-if-!= $parse-type:abort/disp32 -2019 # assert s != "{" -2020 (slice-equal? %ecx "{") -2021 3d/compare-eax-and 0/imm32 -2022 0f 85/jump-if-!= $parse-type:abort/disp32 -2023 # assert s != "}" -2024 (slice-equal? %ecx "}") -2025 3d/compare-eax-and 0/imm32 -2026 0f 85/jump-if-!= $parse-type:abort/disp32 -2027 # assert s != "->" -2028 (slice-equal? %ecx "->") -2029 3d/compare-eax-and 0/imm32 -2030 0f 85/jump-if-!= $parse-type:abort/disp32 -2031 # if (s == ")") return 0 -2032 (slice-equal? %ecx ")") -2033 3d/compare-eax-and 0/imm32 -2034 b8/copy-to-eax 0/imm32 -2035 0f 85/jump-if-!= $parse-type:end/disp32 -2036 # var result/edx: (handle tree type-id) -2037 (allocate *(ebp+8) *Tree-size) # => eax -2038 (zero-out %eax *Tree-size) -2039 89/<- %edx 0/r32/eax -2040 { -2041 # if (s != "(") break -2042 (slice-equal? %ecx "(") -2043 3d/compare-eax-and 0/imm32 -2044 75/jump-if-!= break/disp8 -2045 # result->left = pos-slice(Type-id, s) -2046 (pos-slice Type-id %ecx) -2047 #? (write-buffered Stderr "=> {") -2048 #? (print-int32-buffered Stderr %eax) -2049 #? (write-buffered Stderr ", 0}\n") -2050 #? (flush Stderr) -2051 89/<- *edx 0/r32/eax # Tree-left -2052 e9/jump $parse-type:return-edx/disp32 -2053 } -2054 # otherwise s == "(" -2055 # result->left = parse-type(ad, in) -2056 (parse-type *(ebp+8) *(ebp+0xc)) -2057 #? (write-buffered Stderr "=> {") -2058 #? (print-int32-buffered Stderr %eax) -2059 89/<- *edx 0/r32/eax # Tree-left -2060 # result->right = parse-type-tree(ad, in) -2061 (parse-type-tree *(ebp+8) *(ebp+0xc)) -2062 #? (write-buffered Stderr Space) -2063 #? (print-int32-buffered Stderr %eax) -2064 #? (write-buffered Stderr "}\n") -2065 #? (flush Stderr) -2066 89/<- *(edx+4) 0/r32/eax # Tree-right -2067 $parse-type:return-edx: -2068 89/<- %eax 2/r32/edx -2069 $parse-type:end: -2070 # . reclaim locals -2071 81 0/subop/add %esp 8/imm32 -2072 # . restore registers -2073 5a/pop-to-edx -2074 59/pop-to-ecx -2075 # . epilogue -2076 89/<- %esp 5/r32/ebp -2077 5d/pop-to-ebp -2078 c3/return -2079 -2080 $parse-type:abort: -2081 # error("unexpected token when parsing type: '" s "'\n") -2082 (write-buffered Stderr "unexpected token when parsing type: '") -2083 (write-slice-buffered Stderr %ecx) -2084 (write-buffered Stderr "'\n") -2085 (flush Stderr) -2086 # . syscall(exit, 1) -2087 bb/copy-to-ebx 1/imm32 -2088 b8/copy-to-eax 1/imm32/exit -2089 cd/syscall 0x80/imm8 -2090 # never gets here -2091 -2092 parse-type-tree: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) -2093 # pseudocode: -2094 # var tmp: (handle tree type-id) = parse-type(ad, in) -2095 # if tmp == 0 -2096 # return 0 -2097 # result = allocate(Tree) -2098 # zero-out(result, *Tree-size) -2099 # result->left = tmp -2100 # result->right = parse-type-tree(ad, in) -2101 # -2102 # . prologue -2103 55/push-ebp -2104 89/<- %ebp 4/r32/esp -2105 # . save registers -2106 51/push-ecx -2107 52/push-edx -2108 # var tmp/eax: (handle tree type-id) = parse-type(ad, in) -2109 (parse-type *(ebp+8) *(ebp+0xc)) -2110 # if (tmp == 0) return tmp -2111 3d/compare-eax-and 0/imm32 -2112 74/jump-if-= $parse-type-tree:end/disp8 -2113 # var tmp2/ecx = tmp -2114 89/<- %ecx 0/r32/eax -2115 # var result/edx: (handle tree type-id) -2116 (allocate *(ebp+8) *Tree-size) # => eax -2117 (zero-out %eax *Tree-size) -2118 89/<- %edx 0/r32/eax -2119 # result->left = tmp2 -2120 89/<- *edx 1/r32/ecx # Tree-left -2121 # result->right = parse-type-tree(ad, in) -2122 (parse-type-tree *(ebp+8) *(ebp+0xc)) -2123 89/<- *(edx+4) 0/r32/eax # Tree-right -2124 $parse-type-tree:return-edx: -2125 89/<- %eax 2/r32/edx -2126 $parse-type-tree:end: -2127 # . restore registers -2128 5a/pop-to-edx -2129 59/pop-to-ecx -2130 # . epilogue -2131 89/<- %esp 5/r32/ebp -2132 5d/pop-to-ebp -2133 c3/return -2134 -2135 next-mu-token: # in: (addr stream byte), out: (addr slice) -2136 # pseudocode: -2137 # start: -2138 # skip-chars-matching-whitespace(in) -2139 # if in->read >= in->write # end of in -2140 # out = {0, 0} -2141 # return -2142 # out->start = &in->data[in->read] -2143 # var curr-byte/eax: byte = in->data[in->read] -2144 # if curr->byte == ':' # comment token -2145 # ++in->read -2146 # goto start -2147 # if curr->byte == ',' # comment token -2148 # ++in->read -2149 # goto start -2150 # if curr-byte == '#' # comment -2151 # in->read = in->write # skip to end of in -2152 # goto done -2153 # if curr-byte == '"' # string literal -2154 # skip-string(in) -2155 # goto done # no metadata -2156 # if curr-byte == '(' -2157 # ++in->read -2158 # goto done -2159 # if curr-byte == ')' -2160 # ++in->read -2161 # goto done -2162 # # read a word -2163 # while true -2164 # if in->read >= in->write -2165 # break -2166 # curr-byte = in->data[in->read] -2167 # if curr-byte == ' ' -2168 # break -2169 # if curr-byte == '\r' -2170 # break -2171 # if curr-byte == '\n' -2172 # break -2173 # if curr-byte == '(' -2174 # break -2175 # if curr-byte == ')' -2176 # break -2177 # if curr-byte == ':' -2178 # break -2179 # if curr-byte == ',' -2180 # break -2181 # ++in->read -2182 # done: -2183 # out->end = &in->data[in->read] -2184 # # hack: skip a few trailing delimiters, because we don't always use -2185 # # this correct tokenizer in later tokens -2186 # while true -2187 # if in->read >= in->write -2188 # break -2189 # curr-byte = in->data[in->read] -2190 # if curr-byte == ':' -2191 # ++in->read -2192 # else if curr-byte == ',' -2193 # ++in->read -2194 # else -2195 # break -2196 # -2197 # . prologue -2198 55/push-ebp -2199 89/<- %ebp 4/r32/esp -2200 # . save registers -2201 50/push-eax -2202 51/push-ecx -2203 56/push-esi -2204 57/push-edi -2205 # esi = in -2206 8b/-> *(ebp+8) 6/r32/esi -2207 # edi = out -2208 8b/-> *(ebp+0xc) 7/r32/edi -2209 $next-mu-token:start: -2210 (skip-chars-matching-whitespace %esi) -2211 $next-mu-token:check0: -2212 # if (in->read >= in->write) return out = {0, 0} -2213 # . ecx = in->read -2214 8b/-> *(esi+4) 1/r32/ecx -2215 # . if (ecx >= in->write) return out = {0, 0} -2216 3b/compare 1/r32/ecx *esi -2217 c7 0/subop/copy *edi 0/imm32 -2218 c7 0/subop/copy *(edi+4) 0/imm32 -2219 0f 8d/jump-if->= $next-mu-token:end/disp32 -2220 # out->start = &in->data[in->read] -2221 8d/copy-address *(esi+ecx+0xc) 0/r32/eax -2222 89/<- *edi 0/r32/eax -2223 # var curr-byte/eax: byte = in->data[in->read] -2224 31/xor %eax 0/r32/eax -2225 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -2226 { -2227 $next-mu-token:check-for-colon: -2228 # if (curr-byte != ':') break -2229 3d/compare-eax-and 0x3a/imm32/colon -2230 75/jump-if-!= break/disp8 -2231 # ++in->read -2232 ff 0/subop/increment *(esi+4) -2233 # restart -2234 e9/jump $next-mu-token:start/disp32 -2235 } -2236 { -2237 $next-mu-token:check-for-comma: -2238 # if (curr-byte != ',') break -2239 3d/compare-eax-and 0x2c/imm32/comma -2240 75/jump-if-!= break/disp8 -2241 # ++in->read -2242 ff 0/subop/increment *(esi+4) -2243 # restart -2244 e9/jump $next-mu-token:start/disp32 -2245 } -2246 { -2247 $next-mu-token:check-for-comment: -2248 # if (curr-byte != '#') break -2249 3d/compare-eax-and 0x23/imm32/pound -2250 75/jump-if-!= break/disp8 -2251 # in->read = in->write # skip rest of in -2252 8b/-> *esi 0/r32/eax -2253 89/<- *(esi+4) 0/r32/eax -2254 # return -2255 e9/jump $next-mu-token:done/disp32 -2256 } -2257 { -2258 $next-mu-token:check-for-string-literal: -2259 # if (curr-byte != '"') break -2260 3d/compare-eax-and 0x22/imm32/dquote -2261 75/jump-if-!= break/disp8 -2262 (skip-string %esi) -2263 # return -2264 e9/jump $next-mu-token:done/disp32 -2265 } -2266 { -2267 $next-mu-token:check-for-open-paren: -2268 # if (curr-byte != '(') break -2269 3d/compare-eax-and 0x28/imm32/open-paren -2270 75/jump-if-!= break/disp8 -2271 # ++in->read -2272 ff 0/subop/increment *(esi+4) -2273 # return -2274 e9/jump $next-mu-token:done/disp32 -2275 } -2276 { -2277 $next-mu-token:check-for-close-paren: -2278 # if (curr-byte != ')') break -2279 3d/compare-eax-and 0x29/imm32/close-paren -2280 75/jump-if-!= break/disp8 -2281 # ++in->read -2282 ff 0/subop/increment *(esi+4) -2283 # return -2284 e9/jump $next-mu-token:done/disp32 -2285 } -2286 { -2287 $next-mu-token:regular-word-without-metadata: -2288 # if (in->read >= in->write) break -2289 # . ecx = in->read -2290 8b/-> *(esi+4) 1/r32/ecx -2291 # . if (ecx >= in->write) break -2292 3b/compare *esi 1/r32/ecx -2293 7d/jump-if->= break/disp8 -2294 # var c/eax: byte = in->data[in->read] -2295 31/xor %eax 0/r32/eax -2296 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -2297 # if (c == ' ') break -2298 3d/compare-eax-and 0x20/imm32/space -2299 74/jump-if-= break/disp8 -2300 # if (c == '\r') break -2301 3d/compare-eax-and 0xd/imm32/carriage-return -2302 74/jump-if-= break/disp8 -2303 # if (c == '\n') break -2304 3d/compare-eax-and 0xa/imm32/newline -2305 74/jump-if-= break/disp8 -2306 # if (c == '(') break -2307 3d/compare-eax-and 0x28/imm32/open-paren -2308 0f 84/jump-if-= break/disp32 -2309 # if (c == ')') break -2310 3d/compare-eax-and 0x29/imm32/close-paren -2311 0f 84/jump-if-= break/disp32 -2312 # if (c == ':') break -2313 3d/compare-eax-and 0x3a/imm32/colon -2314 0f 84/jump-if-= break/disp32 -2315 # if (c == ',') break -2316 3d/compare-eax-and 0x2c/imm32/comma -2317 0f 84/jump-if-= break/disp32 -2318 # ++in->read -2319 ff 0/subop/increment *(esi+4) -2320 # -2321 e9/jump loop/disp32 -2322 } -2323 $next-mu-token:done: -2324 # out->end = &in->data[in->read] -2325 8b/-> *(esi+4) 1/r32/ecx -2326 8d/copy-address *(esi+ecx+0xc) 0/r32/eax -2327 89/<- *(edi+4) 0/r32/eax -2328 { -2329 $next-mu-token:skip-trailing-delimiters: -2330 # if (in->read >= in->write) break -2331 # . ecx = in->read -2332 8b/-> *(esi+4) 1/r32/ecx -2333 # . if (ecx >= in->write) break -2334 3b/compare *esi 1/r32/ecx -2335 7d/jump-if->= break/disp8 -2336 # var c/eax: byte = in->data[in->read] -2337 31/xor %eax 0/r32/eax -2338 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -2339 # if (c == ':') ++in->read and loop -2340 { -2341 3d/compare-eax-and 0x3a/imm32/colon -2342 75/jump-if-!= break/disp8 -2343 # ++in->read -2344 ff 0/subop/increment *(esi+4) -2345 # -2346 eb/jump $next-mu-token:skip-trailing-delimiters/disp8 -2347 } -2348 # if (c == ',') ++in->read and loop -2349 { -2350 3d/compare-eax-and 0x2c/imm32/comma -2351 75/jump-if-!= break/disp8 -2352 # ++in->read -2353 ff 0/subop/increment *(esi+4) -2354 # -2355 eb/jump $next-mu-token:skip-trailing-delimiters/disp8 -2356 } -2357 # else break -2358 } -2359 $next-mu-token:end: -2360 # . restore registers -2361 5f/pop-to-edi -2362 5e/pop-to-esi -2363 59/pop-to-ecx -2364 58/pop-to-eax -2365 # . epilogue -2366 89/<- %esp 5/r32/ebp -2367 5d/pop-to-ebp -2368 c3/return -2369 -2370 # return the index in an array of strings matching 's' -2371 # index is denominated in elements, not bytes -2372 pos-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int -2373 # . prologue -2374 55/push-ebp -2375 89/<- %ebp 4/r32/esp -2376 # . save registers -2377 51/push-ecx -2378 52/push-edx -2379 53/push-ebx -2380 56/push-esi -2381 #? (write-buffered Stderr "pos-slice: ") -2382 #? (write-slice-buffered Stderr *(ebp+0xc)) -2383 #? (write-buffered Stderr "\n") -2384 #? (flush Stderr) -2385 # esi = arr -2386 8b/-> *(ebp+8) 6/r32/esi -2387 # var index/ecx: int = 0 -2388 b9/copy-to-ecx 0/imm32 -2389 # var curr/edx: (addr (addr array byte)) = arr->data -2390 8d/copy-address *(esi+0xc) 2/r32/edx -2391 # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write] -2392 8b/-> *esi 3/r32/ebx -2393 8d/copy-address *(esi+ebx+0xc) 3/r32/ebx -2394 { -2395 #? (write-buffered Stderr " ") -2396 #? (print-int32-buffered Stderr %ecx) -2397 #? (write-buffered Stderr "\n") -2398 #? (flush Stderr) -2399 # if (curr >= max) return -1 -2400 39/compare %edx 3/r32/ebx -2401 b8/copy-to-eax -1/imm32 -2402 73/jump-if-addr>= $pos-slice:end/disp8 -2403 # if (slice-equal?(s, *curr)) break -2404 (slice-equal? *(ebp+0xc) *edx) # => eax -2405 3d/compare-eax-and 0/imm32 -2406 75/jump-if-!= break/disp8 -2407 # ++index -2408 41/increment-ecx -2409 # curr += 4 -2410 81 0/subop/add %edx 4/imm32 -2411 # -2412 eb/jump loop/disp8 -2413 } -2414 # return index -2415 89/<- %eax 1/r32/ecx -2416 $pos-slice:end: -2417 #? (write-buffered Stderr "=> ") -2418 #? (print-int32-buffered Stderr %eax) -2419 #? (write-buffered Stderr "\n") -2420 # . restore registers -2421 5e/pop-to-esi -2422 5b/pop-to-ebx -2423 5a/pop-to-edx -2424 59/pop-to-ecx -2425 # . epilogue -2426 89/<- %esp 5/r32/ebp -2427 5d/pop-to-ebp -2428 c3/return -2429 -2430 == data -2431 -2432 Type-id: # (stream (address array byte)) -2433 0x18/imm32/write -2434 0/imm32/read -2435 0x100/imm32/length -2436 # data -2437 "literal"/imm32 # 0 -2438 "int"/imm32 # 1 -2439 "addr"/imm32 # 2 -2440 "array"/imm32 # 3 -2441 "handle"/imm32 # 4 -2442 "bool"/imm32 # 5 -2443 0/imm32 -2444 0/imm32 -2445 # 0x20 -2446 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2447 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2448 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2449 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2450 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2451 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2452 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2453 -2454 == code -2455 -2456 test-parse-var-with-type: -2457 # . prologue -2458 55/push-ebp -2459 89/<- %ebp 4/r32/esp -2460 # (eax..ecx) = "x:" -2461 b8/copy-to-eax "x:"/imm32 -2462 8b/-> *eax 1/r32/ecx -2463 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2464 05/add-to-eax 4/imm32 -2465 # var slice/ecx: slice = {eax, ecx} -2466 51/push-ecx -2467 50/push-eax -2468 89/<- %ecx 4/r32/esp -2469 # _test-input-stream contains "int" -2470 (clear-stream _test-input-stream) -2471 (write _test-input-stream "int") -2472 # -2473 (parse-var-with-type %ecx _test-input-stream) -2474 8b/-> *eax 2/r32/edx # Var-name -2475 (check-strings-equal %edx "x" "F - test-var-with-type/name") -2476 8b/-> *(eax+4) 2/r32/edx # Var-type -2477 (check-ints-equal *edx 1 "F - test-var-with-type/type") -2478 (check-ints-equal *(edx+4) 0 "F - test-var-with-type/type") -2479 # . epilogue -2480 89/<- %esp 5/r32/ebp -2481 5d/pop-to-ebp -2482 c3/return -2483 -2484 test-parse-var-with-type-and-register: -2485 # . prologue -2486 55/push-ebp -2487 89/<- %ebp 4/r32/esp -2488 # (eax..ecx) = "x/eax" -2489 b8/copy-to-eax "x/eax"/imm32 -2490 8b/-> *eax 1/r32/ecx -2491 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2492 05/add-to-eax 4/imm32 -2493 # var slice/ecx: slice = {eax, ecx} -2494 51/push-ecx -2495 50/push-eax -2496 89/<- %ecx 4/r32/esp -2497 # _test-input-stream contains ": int" -2498 (clear-stream _test-input-stream) -2499 (write _test-input-stream ": int") -2500 # -2501 (parse-var-with-type %ecx _test-input-stream) -2502 8b/-> *eax 2/r32/edx # Var-name -2503 (check-strings-equal %edx "x" "F - test-var-with-type-and-register/name") -2504 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2505 (check-strings-equal %edx "eax" "F - test-var-with-type-and-register/register") -2506 8b/-> *(eax+4) 2/r32/edx # Var-type -2507 (check-ints-equal *edx 1 "F - test-var-with-type-and-register/type") -2508 (check-ints-equal *(edx+4) 0 "F - test-var-with-type-and-register/type") -2509 # . epilogue -2510 89/<- %esp 5/r32/ebp -2511 5d/pop-to-ebp -2512 c3/return -2513 -2514 test-parse-var-with-trailing-characters: -2515 # . prologue -2516 55/push-ebp -2517 89/<- %ebp 4/r32/esp -2518 # (eax..ecx) = "x:" -2519 b8/copy-to-eax "x:"/imm32 -2520 8b/-> *eax 1/r32/ecx -2521 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2522 05/add-to-eax 4/imm32 -2523 # var slice/ecx: slice = {eax, ecx} -2524 51/push-ecx -2525 50/push-eax -2526 89/<- %ecx 4/r32/esp -2527 # _test-input-stream contains "int," -2528 (clear-stream _test-input-stream) -2529 (write _test-input-stream "int,") -2530 # -2531 (parse-var-with-type %ecx _test-input-stream) -2532 8b/-> *eax 2/r32/edx # Var-name -2533 (check-strings-equal %edx "x" "F - test-var-with-trailing-characters/name") -2534 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2535 (check-ints-equal %edx 0 "F - test-var-with-trailing-characters/register") -2536 8b/-> *(eax+4) 2/r32/edx # Var-type -2537 (check-ints-equal *edx 1 "F - test-var-with-trailing-characters/type") -2538 (check-ints-equal *(edx+4) 0 "F - test-var-with-trailing-characters/type") -2539 # . epilogue -2540 89/<- %esp 5/r32/ebp -2541 5d/pop-to-ebp -2542 c3/return -2543 -2544 test-parse-var-with-register-and-trailing-characters: -2545 # . prologue -2546 55/push-ebp -2547 89/<- %ebp 4/r32/esp -2548 # (eax..ecx) = "x/eax:" -2549 b8/copy-to-eax "x/eax:"/imm32 -2550 8b/-> *eax 1/r32/ecx -2551 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2552 05/add-to-eax 4/imm32 -2553 # var slice/ecx: slice = {eax, ecx} -2554 51/push-ecx -2555 50/push-eax -2556 89/<- %ecx 4/r32/esp -2557 # _test-input-stream contains "int," -2558 (clear-stream _test-input-stream) -2559 (write _test-input-stream "int,") -2560 # -2561 (parse-var-with-type %ecx _test-input-stream) -2562 8b/-> *eax 2/r32/edx # Var-name -2563 (check-strings-equal %edx "x" "F - test-var-with-register-and-trailing-characters/name") -2564 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2565 (check-strings-equal %edx "eax" "F - test-var-with-register-and-trailing-characters/register") -2566 8b/-> *(eax+4) 2/r32/edx # Var-type -2567 (check-ints-equal *edx 1 "F - test-var-with-register-and-trailing-characters/type") -2568 (check-ints-equal *(edx+4) 0 "F - test-var-with-register-and-trailing-characters/type") -2569 # . epilogue -2570 89/<- %esp 5/r32/ebp -2571 5d/pop-to-ebp -2572 c3/return -2573 -2574 test-parse-var-with-compound-type: -2575 # . prologue -2576 55/push-ebp -2577 89/<- %ebp 4/r32/esp -2578 # (eax..ecx) = "x:" -2579 b8/copy-to-eax "x:"/imm32 -2580 8b/-> *eax 1/r32/ecx -2581 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2582 05/add-to-eax 4/imm32 -2583 # var slice/ecx: slice = {eax, ecx} -2584 51/push-ecx -2585 50/push-eax -2586 89/<- %ecx 4/r32/esp -2587 # _test-input-stream contains "(addr int)" -2588 (clear-stream _test-input-stream) -2589 (write _test-input-stream "(addr int)") -2590 # -2591 (parse-var-with-type %ecx _test-input-stream) -2592 8b/-> *eax 2/r32/edx # Var-name -2593 (check-strings-equal %edx "x" "F - test-var-with-compound-type/name") -2594 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2595 (check-ints-equal %edx 0 "F - test-var-with-compound-type/register") -2596 # var type/edx: (handle tree type-id) = var->type -2597 8b/-> *(eax+4) 2/r32/edx # Var-type -2598 # type->left == atom(addr) -2599 8b/-> *edx 0/r32/eax # Atom-value -2600 (check-ints-equal *eax 2 "F - test-var-with-compound-type/type:0") # Tree-left -2601 # type->right->left == atom(int) -2602 8b/-> *(edx+4) 2/r32/edx # Tree-right -2603 8b/-> *edx 0/r32/eax # Tree-left -2604 (check-ints-equal *eax 1 "F - test-var-with-compound-type/type:1") # Atom-value -2605 # type->right->right == null -2606 (check-ints-equal *(edx+4) 0 "F - test-var-with-compound-type/type:2") # Tree-right -2607 # . epilogue -2608 89/<- %esp 5/r32/ebp -2609 5d/pop-to-ebp -2610 c3/return -2611 -2612 # identifier starts with a letter or '$' or '_' -2613 # no constraints at the moment on later letters -2614 # all we really want to do so far is exclude '{', '}' and '->' -2615 is-identifier?: # in: (addr slice) -> result/eax: boolean -2616 # . prologue -2617 55/push-ebp -2618 89/<- %ebp 4/r32/esp -2619 # if (slice-empty?(in)) return false -2620 (slice-empty? *(ebp+8)) # => eax -2621 3d/compare-eax-and 0/imm32 -2622 75/jump-if-!= $is-identifier?:false/disp8 -2623 # var c/eax: byte = *in->start -2624 8b/-> *(ebp+8) 0/r32/eax -2625 8b/-> *eax 0/r32/eax -2626 8a/copy-byte *eax 0/r32/AL -2627 81 4/subop/and %eax 0xff/imm32 -2628 # if (c == '$') return true -2629 3d/compare-eax-and 0x24/imm32/$ -2630 74/jump-if-= $is-identifier?:true/disp8 -2631 # if (c == '_') return true -2632 3d/compare-eax-and 0x5f/imm32/_ -2633 74/jump-if-= $is-identifier?:true/disp8 -2634 # drop case -2635 25/and-eax-with 0x5f/imm32 -2636 # if (c < 'A') return false -2637 3d/compare-eax-and 0x41/imm32/A -2638 7c/jump-if-< $is-identifier?:false/disp8 -2639 # if (c > 'Z') return false -2640 3d/compare-eax-and 0x5a/imm32/Z -2641 7f/jump-if-> $is-identifier?:false/disp8 -2642 # otherwise return true -2643 $is-identifier?:true: -2644 b8/copy-to-eax 1/imm32/true -2645 eb/jump $is-identifier?:end/disp8 -2646 $is-identifier?:false: -2647 b8/copy-to-eax 0/imm32/false -2648 $is-identifier?:end: -2649 # . epilogue -2650 89/<- %esp 5/r32/ebp -2651 5d/pop-to-ebp -2652 c3/return -2653 -2654 test-is-identifier-dollar: -2655 # . prologue -2656 55/push-ebp -2657 89/<- %ebp 4/r32/esp -2658 # (eax..ecx) = "$a" -2659 b8/copy-to-eax "$a"/imm32 -2660 8b/-> *eax 1/r32/ecx -2661 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2662 05/add-to-eax 4/imm32 -2663 # var slice/ecx: slice = {eax, ecx} -2664 51/push-ecx -2665 50/push-eax -2666 89/<- %ecx 4/r32/esp -2667 # -2668 (is-identifier? %ecx) -2669 (check-ints-equal %eax 1 "F - test-is-identifier-dollar") -2670 # . epilogue -2671 89/<- %esp 5/r32/ebp -2672 5d/pop-to-ebp -2673 c3/return -2674 -2675 test-is-identifier-underscore: -2676 # . prologue -2677 55/push-ebp -2678 89/<- %ebp 4/r32/esp -2679 # (eax..ecx) = "_a" -2680 b8/copy-to-eax "_a"/imm32 -2681 8b/-> *eax 1/r32/ecx -2682 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2683 05/add-to-eax 4/imm32 -2684 # var slice/ecx: slice = {eax, ecx} -2685 51/push-ecx -2686 50/push-eax -2687 89/<- %ecx 4/r32/esp -2688 # -2689 (is-identifier? %ecx) -2690 (check-ints-equal %eax 1 "F - test-is-identifier-underscore") -2691 # . epilogue -2692 89/<- %esp 5/r32/ebp -2693 5d/pop-to-ebp -2694 c3/return -2695 -2696 test-is-identifier-a: -2697 # . prologue -2698 55/push-ebp -2699 89/<- %ebp 4/r32/esp -2700 # (eax..ecx) = "a$" -2701 b8/copy-to-eax "a$"/imm32 -2702 8b/-> *eax 1/r32/ecx -2703 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2704 05/add-to-eax 4/imm32 -2705 # var slice/ecx: slice = {eax, ecx} -2706 51/push-ecx -2707 50/push-eax -2708 89/<- %ecx 4/r32/esp -2709 # -2710 (is-identifier? %ecx) -2711 (check-ints-equal %eax 1 "F - test-is-identifier-a") -2712 # . epilogue -2713 89/<- %esp 5/r32/ebp -2714 5d/pop-to-ebp -2715 c3/return -2716 -2717 test-is-identifier-z: -2718 # . prologue -2719 55/push-ebp -2720 89/<- %ebp 4/r32/esp -2721 # (eax..ecx) = "z$" -2722 b8/copy-to-eax "z$"/imm32 -2723 8b/-> *eax 1/r32/ecx -2724 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2725 05/add-to-eax 4/imm32 -2726 # var slice/ecx: slice = {eax, ecx} -2727 51/push-ecx -2728 50/push-eax -2729 89/<- %ecx 4/r32/esp -2730 # -2731 (is-identifier? %ecx) -2732 (check-ints-equal %eax 1 "F - test-is-identifier-z") -2733 # . epilogue -2734 89/<- %esp 5/r32/ebp -2735 5d/pop-to-ebp -2736 c3/return -2737 -2738 test-is-identifier-A: -2739 # . prologue -2740 55/push-ebp -2741 89/<- %ebp 4/r32/esp -2742 # (eax..ecx) = "A$" -2743 b8/copy-to-eax "A$"/imm32 -2744 8b/-> *eax 1/r32/ecx -2745 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2746 05/add-to-eax 4/imm32 -2747 # var slice/ecx: slice = {eax, ecx} -2748 51/push-ecx -2749 50/push-eax -2750 89/<- %ecx 4/r32/esp -2751 # -2752 (is-identifier? %ecx) -2753 (check-ints-equal %eax 1 "F - test-is-identifier-A") -2754 # . epilogue -2755 89/<- %esp 5/r32/ebp -2756 5d/pop-to-ebp -2757 c3/return -2758 -2759 test-is-identifier-Z: -2760 # . prologue -2761 55/push-ebp -2762 89/<- %ebp 4/r32/esp -2763 # (eax..ecx) = "Z$" -2764 b8/copy-to-eax "Z$"/imm32 -2765 8b/-> *eax 1/r32/ecx -2766 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2767 05/add-to-eax 4/imm32 -2768 # var slice/ecx: slice = {eax, ecx} -2769 51/push-ecx -2770 50/push-eax -2771 89/<- %ecx 4/r32/esp -2772 # -2773 (is-identifier? %ecx) -2774 (check-ints-equal %eax 1 "F - test-is-identifier-Z") -2775 # . epilogue -2776 89/<- %esp 5/r32/ebp -2777 5d/pop-to-ebp -2778 c3/return -2779 -2780 test-is-identifier-@: -2781 # character before 'A' is invalid -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 0 "F - test-is-identifier-@") -2797 # . epilogue -2798 89/<- %esp 5/r32/ebp -2799 5d/pop-to-ebp -2800 c3/return -2801 -2802 test-is-identifier-square-bracket: -2803 # character after 'Z' is invalid -2804 # . prologue -2805 55/push-ebp -2806 89/<- %ebp 4/r32/esp -2807 # (eax..ecx) = "[a" -2808 b8/copy-to-eax "[a"/imm32 -2809 8b/-> *eax 1/r32/ecx -2810 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2811 05/add-to-eax 4/imm32 -2812 # var slice/ecx: slice = {eax, ecx} -2813 51/push-ecx -2814 50/push-eax -2815 89/<- %ecx 4/r32/esp -2816 # -2817 (is-identifier? %ecx) -2818 (check-ints-equal %eax 0 "F - test-is-identifier-@") -2819 # . epilogue -2820 89/<- %esp 5/r32/ebp -2821 5d/pop-to-ebp -2822 c3/return -2823 -2824 test-is-identifier-backtick: -2825 # character before 'a' is invalid -2826 # . prologue -2827 55/push-ebp -2828 89/<- %ebp 4/r32/esp -2829 # (eax..ecx) = "`a" -2830 b8/copy-to-eax "`a"/imm32 -2831 8b/-> *eax 1/r32/ecx -2832 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2833 05/add-to-eax 4/imm32 -2834 # var slice/ecx: slice = {eax, ecx} -2835 51/push-ecx -2836 50/push-eax -2837 89/<- %ecx 4/r32/esp -2838 # -2839 (is-identifier? %ecx) -2840 (check-ints-equal %eax 0 "F - test-is-identifier-backtick") -2841 # . epilogue -2842 89/<- %esp 5/r32/ebp -2843 5d/pop-to-ebp -2844 c3/return -2845 -2846 test-is-identifier-curly-brace-open: -2847 # character after 'z' is invalid; also used for blocks -2848 # . prologue -2849 55/push-ebp -2850 89/<- %ebp 4/r32/esp -2851 # (eax..ecx) = "{a" -2852 b8/copy-to-eax "{a"/imm32 -2853 8b/-> *eax 1/r32/ecx -2854 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2855 05/add-to-eax 4/imm32 -2856 # var slice/ecx: slice = {eax, ecx} -2857 51/push-ecx -2858 50/push-eax -2859 89/<- %ecx 4/r32/esp -2860 # -2861 (is-identifier? %ecx) -2862 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open") -2863 # . epilogue -2864 89/<- %esp 5/r32/ebp -2865 5d/pop-to-ebp -2866 c3/return -2867 -2868 test-is-identifier-curly-brace-close: -2869 # . prologue -2870 55/push-ebp -2871 89/<- %ebp 4/r32/esp -2872 # (eax..ecx) = "}a" -2873 b8/copy-to-eax "}a"/imm32 -2874 8b/-> *eax 1/r32/ecx -2875 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2876 05/add-to-eax 4/imm32 -2877 # var slice/ecx: slice = {eax, ecx} -2878 51/push-ecx -2879 50/push-eax -2880 89/<- %ecx 4/r32/esp -2881 # -2882 (is-identifier? %ecx) -2883 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close") -2884 # . epilogue -2885 89/<- %esp 5/r32/ebp -2886 5d/pop-to-ebp -2887 c3/return -2888 -2889 test-is-identifier-hyphen: -2890 # disallow leading '-' since '->' has special meaning -2891 # . prologue -2892 55/push-ebp -2893 89/<- %ebp 4/r32/esp -2894 # (eax..ecx) = "-a" -2895 b8/copy-to-eax "-a"/imm32 -2896 8b/-> *eax 1/r32/ecx -2897 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2898 05/add-to-eax 4/imm32 -2899 # var slice/ecx: slice = {eax, ecx} -2900 51/push-ecx -2901 50/push-eax -2902 89/<- %ecx 4/r32/esp -2903 # -2904 (is-identifier? %ecx) -2905 (check-ints-equal %eax 0 "F - test-is-identifier-hyphen") -2906 # . epilogue -2907 89/<- %esp 5/r32/ebp -2908 5d/pop-to-ebp -2909 c3/return -2910 -2911 populate-mu-function-body: # in: (addr buffered-file), out: (handle function), vars: (addr stack (handle var)) -2912 # . prologue -2913 55/push-ebp -2914 89/<- %ebp 4/r32/esp -2915 # . save registers -2916 50/push-eax -2917 56/push-esi -2918 57/push-edi -2919 # esi = in -2920 8b/-> *(ebp+8) 6/r32/esi -2921 # edi = out -2922 8b/-> *(ebp+0xc) 7/r32/edi -2923 # initialize some global state -2924 c7 0/subop/copy *Curr-block-depth 1/imm32 -2925 c7 0/subop/copy *Next-local-stack-offset -4/imm32 -2926 # var eax: (handle block) = parse-mu-block(in, vars, fn) -2927 (parse-mu-block %esi *(ebp+0x10) %edi) # => eax -2928 # out->body = eax -2929 89/<- *(edi+0x10) 0/r32/eax # Function-body -2930 $populate-mu-function-body:end: -2931 # . restore registers -2932 5f/pop-to-edi -2933 5e/pop-to-esi -2934 58/pop-to-eax -2935 # . epilogue -2936 89/<- %esp 5/r32/ebp -2937 5d/pop-to-ebp -2938 c3/return -2939 -2940 == data -2941 -2942 # Global state added to each var record when parsing a function -2943 -2944 Curr-block-depth: # (addr int) -2945 0/imm32 -2946 Next-local-stack-offset: # (addr int) -2947 -4/imm32 -2948 -2949 Next-block-index: # (addr int) -2950 1/imm32 -2951 -2952 == code -2953 -2954 # parses a block, assuming that the leading '{' has already been read by the caller -2955 parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle block) -2956 # pseudocode: -2957 # var line: (stream byte 512) -2958 # var word-slice: slice -2959 # increment *Curr-block-depth -2960 # result/eax = allocate(Heap, Stmt-size) -2961 # result->tag = 0/block -2962 # result->name = some unique name -2963 # while true # line loop -2964 # clear-stream(line) -2965 # read-line-buffered(in, line) -2966 # if (line->write == 0) break # end of file -2967 # word-slice = next-word(line) -2968 # if slice-empty?(word-slice) # end of line -2969 # continue -2970 # else if slice-starts-with?(word-slice, "#") -2971 # continue -2972 # else if slice-equal?(word-slice, "{") -2973 # assert(no-tokens-in(line)) -2974 # block = parse-mu-block(in, vars, fn) -2975 # append-to-block(result, block) -2976 # else if slice-equal?(word-slice, "}") -2977 # break -2978 # else if slice-ends-with?(word-slice, ":") -2979 # # TODO: error-check the rest of 'line' -2980 # --word-slice->end to skip ':' -2981 # named-block = parse-mu-named-block(word-slice, in, vars, fn) -2982 # append-to-block(result, named-block) -2983 # else if slice-equal?(word-slice, "var") -2984 # var-def = parse-mu-var-def(line, vars) -2985 # append-to-block(result, var-def) -2986 # else -2987 # stmt = parse-mu-stmt(line, vars, fn) -2988 # append-to-block(result, stmt) -2989 # decrement *Curr-block-depth -2990 # return result -2991 # -2992 # . prologue -2993 55/push-ebp -2994 89/<- %ebp 4/r32/esp -2995 # . save registers -2996 51/push-ecx -2997 52/push-edx -2998 53/push-ebx -2999 57/push-edi -3000 # var line/ecx: (stream byte 512) -3001 81 5/subop/subtract %esp 0x200/imm32 -3002 68/push 0x200/imm32/length -3003 68/push 0/imm32/read -3004 68/push 0/imm32/write -3005 89/<- %ecx 4/r32/esp -3006 # var word-slice/edx: slice -3007 68/push 0/imm32/end -3008 68/push 0/imm32/start -3009 89/<- %edx 4/r32/esp -3010 # edi = result -3011 (allocate Heap *Stmt-size) # => eax -3012 (zero-out %eax *Stmt-size) -3013 89/<- %edi 0/r32/eax -3014 # set result->tag -3015 c7 0/subop/copy *edi 0/imm32/block # Stmt-tag -3016 # set result->var -3017 (new-block-name *(ebp+0x10)) # => eax -3018 89/<- *(edi+8) 0/r32/eax # Block-var -3019 # push result->var to vars -3020 (push *(ebp+0xc) %eax) -3021 # increment *Curr-block-depth -3022 ff 0/subop/increment *Curr-block-depth -3023 { -3024 $parse-mu-block:line-loop: -3025 # line = read-line-buffered(in) -3026 (clear-stream %ecx) -3027 (read-line-buffered *(ebp+8) %ecx) -3028 #? (write-buffered Stderr "line: ") -3029 #? (write-stream-data Stderr %ecx) -3030 #? (write-buffered Stderr Newline) -3031 #? (flush Stderr) -3032 # if (line->write == 0) break -3033 81 7/subop/compare *ecx 0/imm32 -3034 0f 84/jump-if-= break/disp32 -3035 # word-slice = next-word(line) -3036 (next-word %ecx %edx) -3037 #? (write-buffered Stderr "word: ") -3038 #? (write-slice-buffered Stderr %edx) -3039 #? (write-buffered Stderr Newline) -3040 #? (flush Stderr) -3041 # if slice-empty?(word-slice) continue -3042 (slice-empty? %edx) -3043 3d/compare-eax-and 0/imm32 -3044 0f 85/jump-if-!= loop/disp32 -3045 # if (slice-starts-with?(word-slice, '#') continue -3046 # . eax = *word-slice->start -3047 8b/-> *edx 0/r32/eax -3048 8a/copy-byte *eax 0/r32/AL -3049 81 4/subop/and %eax 0xff/imm32 -3050 # . if (eax == '#') continue -3051 3d/compare-eax-and 0x23/imm32/hash -3052 0f 84/jump-if-= loop/disp32 -3053 # if slice-equal?(word-slice, "{") -3054 { -3055 $parse-mu-block:check-for-block: -3056 (slice-equal? %edx "{") -3057 3d/compare-eax-and 0/imm32 -3058 74/jump-if-= break/disp8 -3059 (check-no-tokens-left %ecx) -3060 # parse new block and append -3061 (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax -3062 (append-to-block Heap %edi %eax) -3063 e9/jump $parse-mu-block:line-loop/disp32 -3064 } -3065 # if slice-equal?(word-slice, "}") break -3066 $parse-mu-block:check-for-end: -3067 (slice-equal? %edx "}") -3068 3d/compare-eax-and 0/imm32 -3069 0f 85/jump-if-!= break/disp32 -3070 # if slice-ends-with?(word-slice, ":") parse named block and append -3071 { -3072 $parse-mu-block:check-for-named-block: -3073 # . eax = *(word-slice->end-1) -3074 8b/-> *(edx+4) 0/r32/eax -3075 48/decrement-eax -3076 8a/copy-byte *eax 0/r32/AL -3077 81 4/subop/and %eax 0xff/imm32 -3078 # . if (eax != ':') break -3079 3d/compare-eax-and 0x3a/imm32/colon -3080 0f 85/jump-if-!= break/disp32 -3081 # TODO: error-check the rest of 'line' -3082 # -3083 # skip ':' -3084 ff 1/subop/decrement *(edx+4) # Slice-end -3085 # -3086 (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax -3087 (append-to-block Heap %edi %eax) -3088 e9/jump $parse-mu-block:line-loop/disp32 -3089 } -3090 # if slice-equal?(word-slice, "var") -3091 { -3092 $parse-mu-block:check-for-var: -3093 (slice-equal? %edx "var") -3094 3d/compare-eax-and 0/imm32 -3095 74/jump-if-= break/disp8 -3096 # -3097 (parse-mu-var-def %ecx *(ebp+0xc)) # => eax -3098 (append-to-block Heap %edi %eax) -3099 e9/jump $parse-mu-block:line-loop/disp32 -3100 } -3101 $parse-mu-block:regular-stmt: -3102 # otherwise -3103 (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10)) # => eax -3104 (append-to-block Heap %edi %eax) -3105 e9/jump loop/disp32 -3106 } # end line loop -3107 # decrement *Curr-block-depth -3108 ff 1/subop/decrement *Curr-block-depth -3109 # -3110 (pop *(ebp+0xc)) # => eax -3111 # return result -3112 89/<- %eax 7/r32/edi -3113 $parse-mu-block:end: -3114 # . reclaim locals -3115 81 0/subop/add %esp 0x214/imm32 -3116 # . restore registers -3117 5f/pop-to-edi -3118 5b/pop-to-ebx -3119 5a/pop-to-edx -3120 59/pop-to-ecx -3121 # . epilogue -3122 89/<- %esp 5/r32/ebp -3123 5d/pop-to-ebp -3124 c3/return -3125 -3126 $parse-mu-block:abort: -3127 # error("'{' or '}' should be on its own line, but got '") -3128 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") -3129 (rewind-stream %ecx) -3130 (write-stream 2 %ecx) -3131 (write-buffered Stderr "'\n") -3132 (flush Stderr) -3133 # . syscall(exit, 1) -3134 bb/copy-to-ebx 1/imm32 -3135 b8/copy-to-eax 1/imm32/exit -3136 cd/syscall 0x80/imm8 -3137 # never gets here +1231 # A conditional 'break' after a 'var' in a block is converted into a +1232 # nested block that performs all necessary cleanup before jumping. This +1233 # results in some ugly code duplication. +1234 # . prologue +1235 55/push-ebp +1236 89/<- %ebp 4/r32/esp +1237 # setup +1238 (clear-stream _test-input-stream) +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 +1243 # +1244 (write _test-input-stream "fn foo {\n") +1245 (write _test-input-stream " {\n") +1246 (write _test-input-stream " var x: int\n") +1247 (write _test-input-stream " break-if->=\n") +1248 (write _test-input-stream " increment x\n") +1249 (write _test-input-stream " }\n") +1250 (write _test-input-stream "}\n") +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 -------------------------------------------------------------------------------------------------------------- +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") +1263 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-local-vars/2") +1264 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-and-local-vars/3") +1265 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/4") +1266 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-and-local-vars/5") +1267 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/6") +1268 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-and-local-vars/7") +1269 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-local-vars/8") +1270 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/9") +1271 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-branches-and-local-vars/10") +1272 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-branches-and-local-vars/11") +1273 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:break/disp32" "F - test-convert-function-with-branches-and-local-vars/12") +1274 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/13") +1275 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-branches-and-local-vars/14") +1276 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-branches-and-local-vars/15") +1277 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/16") +1278 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-and-local-vars/17") +1279 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/18") +1280 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-and-local-vars/19") +1281 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-local-vars/20") +1282 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-and-local-vars/21") +1283 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-local-vars/22") +1284 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-local-vars/23") +1285 # . epilogue +1286 89/<- %esp 5/r32/ebp +1287 5d/pop-to-ebp +1288 c3/return +1289 +1290 test-convert-function-with-conditional-loops-and-local-vars: +1291 # A conditional 'loop' after a 'var' in a block is converted into a nested +1292 # block that performs all necessary cleanup before jumping. This results +1293 # in some ugly code duplication. +1294 # . prologue +1295 55/push-ebp +1296 89/<- %ebp 4/r32/esp +1297 # setup +1298 (clear-stream _test-input-stream) +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 +1303 # +1304 (write _test-input-stream "fn foo {\n") +1305 (write _test-input-stream " {\n") +1306 (write _test-input-stream " var x: int\n") +1307 (write _test-input-stream " loop-if->=\n") +1308 (write _test-input-stream " increment x\n") +1309 (write _test-input-stream " }\n") +1310 (write _test-input-stream "}\n") +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 -------------------------------------------------------------------------------------------------------------- +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") +1323 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/2") +1324 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-conditional-loops-and-local-vars/3") +1325 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/4") +1326 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-conditional-loops-and-local-vars/5") +1327 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/6") +1328 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-conditional-loops-and-local-vars/7") +1329 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-conditional-loops-and-local-vars/8") +1330 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/9") +1331 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-conditional-loops-and-local-vars/10") +1332 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-conditional-loops-and-local-vars/11") +1333 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:loop/disp32" "F - test-convert-function-with-conditional-loops-and-local-vars/12") +1334 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/13") +1335 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-conditional-loops-and-local-vars/14") +1336 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-conditional-loops-and-local-vars/15") +1337 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/16") +1338 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-conditional-loops-and-local-vars/17") +1339 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/18") +1340 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-conditional-loops-and-local-vars/19") +1341 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-conditional-loops-and-local-vars/20") +1342 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/21") +1343 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/22") +1344 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-conditional-loops-and-local-vars/23") +1345 # . epilogue +1346 89/<- %esp 5/r32/ebp +1347 5d/pop-to-ebp +1348 c3/return +1349 +1350 test-convert-function-with-unconditional-loops-and-local-vars: +1351 # An unconditional 'loop' after a 'var' in a block is emitted _after_ the +1352 # regular block cleanup. Any instructions after 'loop' are dead and +1353 # therefore skipped. +1354 # . prologue +1355 55/push-ebp +1356 89/<- %ebp 4/r32/esp +1357 # setup +1358 (clear-stream _test-input-stream) +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 +1363 # +1364 (write _test-input-stream "fn foo {\n") +1365 (write _test-input-stream " {\n") +1366 (write _test-input-stream " var x: int\n") +1367 (write _test-input-stream " loop\n") +1368 (write _test-input-stream " increment x\n") +1369 (write _test-input-stream " }\n") +1370 (write _test-input-stream "}\n") +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 -------------------------------------------------------------------------------------------------------------- +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") +1383 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/2") +1384 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-unconditional-loops-and-local-vars/3") +1385 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-loops-and-local-vars/4") +1386 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-unconditional-loops-and-local-vars/5") +1387 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-loops-and-local-vars/6") +1388 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-unconditional-loops-and-local-vars/7") +1389 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-loops-and-local-vars/8") +1390 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-unconditional-loops-and-local-vars/9") +1391 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-unconditional-loops-and-local-vars/10") +1392 # not emitted: ff 0/subop/increment *(ebp+0xfffffffc) +1393 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-loops-and-local-vars/11") +1394 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-unconditional-loops-and-local-vars/12") +1395 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-loops-and-local-vars/13") +1396 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-unconditional-loops-and-local-vars/14") +1397 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-unconditional-loops-and-local-vars/15") +1398 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/16") +1399 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/17") +1400 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-unconditional-loops-and-local-vars/18") +1401 # . epilogue +1402 89/<- %esp 5/r32/ebp +1403 5d/pop-to-ebp +1404 c3/return +1405 +1406 test-convert-function-with-branches-and-loops-and-local-vars: +1407 # . prologue +1408 55/push-ebp +1409 89/<- %ebp 4/r32/esp +1410 # setup +1411 (clear-stream _test-input-stream) +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 +1416 # +1417 (write _test-input-stream "fn foo {\n") +1418 (write _test-input-stream " {\n") +1419 (write _test-input-stream " var x: int\n") +1420 (write _test-input-stream " break-if->=\n") +1421 (write _test-input-stream " increment x\n") +1422 (write _test-input-stream " loop\n") +1423 (write _test-input-stream " }\n") +1424 (write _test-input-stream "}\n") +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 -------------------------------------------------------------------------------------------------------------- +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") +1437 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/2") +1438 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-and-loops-and-local-vars/3") +1439 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/4") +1440 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-and-loops-and-local-vars/5") +1441 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/6") +1442 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-and-loops-and-local-vars/7") +1443 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-loops-and-local-vars/8") +1444 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/9") +1445 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-branches-and-loops-and-local-vars/10") +1446 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-branches-and-loops-and-local-vars/11") +1447 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:break/disp32" "F - test-convert-function-with-branches-and-loops-and-local-vars/12") +1448 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/13") +1449 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-branches-and-loops-and-local-vars/14") +1450 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-branches-and-loops-and-local-vars/15") +1451 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-and-loops-and-local-vars/16") +1452 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/17") +1453 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-and-loops-and-local-vars/18") +1454 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/19") +1455 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-and-loops-and-local-vars/20") +1456 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-loops-and-local-vars/21") +1457 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/22") +1458 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/23") +1459 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-loops-and-local-vars/24") +1460 # . epilogue +1461 89/<- %esp 5/r32/ebp +1462 5d/pop-to-ebp +1463 c3/return +1464 +1465 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars: +1466 # . prologue +1467 55/push-ebp +1468 89/<- %ebp 4/r32/esp +1469 # setup +1470 (clear-stream _test-input-stream) +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 +1475 # +1476 (write _test-input-stream "fn foo {\n") +1477 (write _test-input-stream " a: {\n") +1478 (write _test-input-stream " var x: int\n") +1479 (write _test-input-stream " {\n") +1480 (write _test-input-stream " var y: int\n") +1481 (write _test-input-stream " break-if->= a\n") +1482 (write _test-input-stream " increment x\n") +1483 (write _test-input-stream " loop\n") +1484 (write _test-input-stream " }\n") +1485 (write _test-input-stream " }\n") +1486 (write _test-input-stream "}\n") +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 -------------------------------------------------------------------------------------------------------------- +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") +1499 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2") +1500 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/3") +1501 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4") +1502 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5") +1503 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6") +1504 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7") +1505 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/8") +1506 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9") +1507 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10") +1508 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/11") +1509 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12") +1510 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/13") +1511 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/14") +1512 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/15") +1513 (check-next-stream-line-equal _test-output-stream " e9/jump a:break/disp32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/16") +1514 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17") +1515 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/18") +1516 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/19") +1517 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/20") +1518 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21") +1519 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22") +1520 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/23") +1521 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24") +1522 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25") +1523 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26") +1524 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27") +1525 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28") +1526 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/29") +1527 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/30") +1528 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31") +1529 # . epilogue +1530 89/<- %esp 5/r32/ebp +1531 5d/pop-to-ebp +1532 c3/return +1533 +1534 ####################################################### +1535 # Parsing +1536 ####################################################### +1537 +1538 parse-mu: # in: (addr buffered-file) +1539 # pseudocode +1540 # var curr-function: (addr (handle function)) = Program +1541 # var line: (stream byte 512) +1542 # var word-slice: slice +1543 # while true # line loop +1544 # clear-stream(line) +1545 # read-line-buffered(in, line) +1546 # if (line->write == 0) break # end of file +1547 # word-slice = next-mu-token(line) +1548 # if slice-empty?(word-slice) # end of line +1549 # continue +1550 # else if slice-starts-with?(word-slice, "#") # comment +1551 # continue # end of line +1552 # else if slice-equal(word-slice, "fn") +1553 # var new-function: (handle function) = allocate(function) +1554 # var vars: (stack (addr var) 256) +1555 # populate-mu-function-header(in, new-function, vars) +1556 # populate-mu-function-body(in, new-function, vars) +1557 # assert(vars->top == 0) +1558 # *curr-function = new-function +1559 # curr-function = &new-function->next +1560 # else +1561 # abort() +1562 # +1563 # . prologue +1564 55/push-ebp +1565 89/<- %ebp 4/r32/esp +1566 # . save registers +1567 50/push-eax +1568 51/push-ecx +1569 52/push-edx +1570 53/push-ebx +1571 57/push-edi +1572 # var line/ecx: (stream byte 512) +1573 81 5/subop/subtract %esp 0x200/imm32 +1574 68/push 0x200/imm32/length +1575 68/push 0/imm32/read +1576 68/push 0/imm32/write +1577 89/<- %ecx 4/r32/esp +1578 # var word-slice/edx: slice +1579 68/push 0/imm32/end +1580 68/push 0/imm32/start +1581 89/<- %edx 4/r32/esp +1582 # var curr-function/edi: (addr (handle function)) = Program +1583 bf/copy-to-edi Program/imm32 +1584 # var vars/ebx: (stack (addr var) 256) +1585 81 5/subop/subtract %esp 0x400/imm32 +1586 68/push 0x400/imm32/length +1587 68/push 0/imm32/top +1588 89/<- %ebx 4/r32/esp +1589 { +1590 $parse-mu:line-loop: +1591 (clear-stream %ecx) +1592 (read-line-buffered *(ebp+8) %ecx) +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) +1603 # if slice-empty?(word-slice) continue +1604 (slice-empty? %edx) +1605 3d/compare-eax-and 0/imm32 +1606 0f 85/jump-if-!= loop/disp32 +1607 # if (*word-slice->start == "#") continue +1608 # . eax = *word-slice->start +1609 8b/-> *edx 0/r32/eax +1610 8a/copy-byte *eax 0/r32/AL +1611 81 4/subop/and %eax 0xff/imm32 +1612 # . if (eax == '#') continue +1613 3d/compare-eax-and 0x23/imm32/hash +1614 0f 84/jump-if-= loop/disp32 +1615 # if (slice-equal?(word-slice, "fn")) parse a function +1616 { +1617 $parse-mu:fn: +1618 (slice-equal? %edx "fn") +1619 3d/compare-eax-and 0/imm32 +1620 0f 84/jump-if-= break/disp32 +1621 # var new-function/eax: (handle function) = populate-mu-function(in, new-function, vars) +1622 (allocate Heap *Function-size) # => eax +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) +1627 # *curr-function = new-function +1628 89/<- *edi 0/r32/eax +1629 # curr-function = &new-function->next +1630 8d/address-> *(eax+0x14) 7/r32/edi # Function-next +1631 e9/jump $parse-mu:line-loop/disp32 +1632 } +1633 # otherwise abort +1634 e9/jump $parse-mu:error1/disp32 +1635 } # end line loop +1636 $parse-mu:end: +1637 # . reclaim locals +1638 81 0/subop/add %esp 0x630/imm32 +1639 # . restore registers +1640 5f/pop-to-edi +1641 5b/pop-to-ebx +1642 5a/pop-to-edx +1643 59/pop-to-ecx +1644 58/pop-to-eax +1645 # . epilogue +1646 89/<- %esp 5/r32/ebp +1647 5d/pop-to-ebp +1648 c3/return +1649 +1650 $parse-mu:error1: +1651 # error("unexpected top-level command: " word-slice "\n") +1652 (write-buffered Stderr "unexpected top-level command: ") +1653 (write-slice-buffered Stderr %edx) +1654 (write-buffered Stderr "\n") +1655 (flush Stderr) +1656 # . syscall(exit, 1) +1657 bb/copy-to-ebx 1/imm32 +1658 b8/copy-to-eax 1/imm32/exit +1659 cd/syscall 0x80/imm8 +1660 # never gets here +1661 +1662 $parse-mu:error2: +1663 # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n") +1664 (print-int32-buffered Stderr *ebx) +1665 (write-buffered Stderr " vars not reclaimed after fn '") +1666 (write-slice-buffered Stderr *eax) # Function-name +1667 (write-buffered Stderr "'\n") +1668 (flush Stderr) +1669 # . syscall(exit, 1) +1670 bb/copy-to-ebx 1/imm32 +1671 b8/copy-to-eax 1/imm32/exit +1672 cd/syscall 0x80/imm8 +1673 # never gets here +1674 +1675 # scenarios considered: +1676 # ✗ fn foo # no block +1677 # ✓ fn foo { +1678 # ✗ fn foo { { +1679 # ✗ fn foo { } +1680 # ✗ fn foo { } { +1681 # ✗ fn foo x { +1682 # ✗ fn foo x: { +1683 # ✓ fn foo x: int { +1684 # ✓ fn foo x: int { +1685 # ✓ fn foo x: int -> y/eax: int { +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) +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) +1697 # if (name == '{') goto done +1698 # if (name == '->') break +1699 # assert(name != '}') +1700 # var v: (handle var) = parse-var-with-type(name, first-line) +1701 # assert(v->register == null) +1702 # v->stack-offset = next-offset +1703 # next-offset += size-of(v) +1704 # # v->block-depth is implicitly 0 +1705 # out->inouts = append(out->inouts, v) +1706 # push(vars, v) +1707 # ## outputs +1708 # while true +1709 # ## name +1710 # name = next-word(first-line) +1711 # assert(name not in '{' '}' '->') +1712 # var v: (handle var) = parse-var-with-type(name, first-line) +1713 # assert(v->register != null) +1714 # out->outputs = append(out->outputs, v) +1715 # done: +1716 # +1717 # . prologue +1718 55/push-ebp +1719 89/<- %ebp 4/r32/esp +1720 # . save registers +1721 50/push-eax +1722 51/push-ecx +1723 52/push-edx +1724 53/push-ebx +1725 57/push-edi +1726 # edi = out +1727 8b/-> *(ebp+0xc) 7/r32/edi +1728 # var word-slice/ecx: slice +1729 68/push 0/imm32/end +1730 68/push 0/imm32/start +1731 89/<- %ecx 4/r32/esp +1732 # var next-offset/edx = 8 +1733 ba/copy-to-edx 8/imm32 +1734 # read function name +1735 (next-word *(ebp+8) %ecx) +1736 # error checking +1737 # TODO: error if name starts with 'break' or 'loop' +1738 # if (word-slice == '{') abort +1739 (slice-equal? %ecx "{") # => eax +1740 3d/compare-eax-and 0/imm32 +1741 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +1742 # if (word-slice == '->') abort +1743 (slice-equal? %ecx "->") # => eax +1744 3d/compare-eax-and 0/imm32 +1745 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +1746 # if (word-slice == '}') abort +1747 (slice-equal? %ecx "}") # => eax +1748 3d/compare-eax-and 0/imm32 +1749 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +1750 # save function name +1751 (slice-to-string Heap %ecx) # => eax +1752 89/<- *edi 0/r32/eax # Function-name +1753 # initialize default subx-name as well +1754 89/<- *(edi+4) 0/r32/eax # Function-subx-name +1755 # save function inouts +1756 { +1757 $populate-mu-function-header:check-for-inout: +1758 (next-word *(ebp+8) %ecx) +1759 # if (word-slice == '{') goto done +1760 (slice-equal? %ecx "{") # => eax +1761 3d/compare-eax-and 0/imm32 +1762 0f 85/jump-if-!= $populate-mu-function-header:done/disp32 +1763 # if (word-slice == '->') break +1764 (slice-equal? %ecx "->") # => eax +1765 3d/compare-eax-and 0/imm32 +1766 0f 85/jump-if-!= break/disp32 +1767 # if (word-slice == '}') abort +1768 (slice-equal? %ecx "}") # => eax +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 +1773 89/<- %ebx 0/r32/eax +1774 # assert(v->register == null) +1775 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register +1776 0f 85/jump-if-!= $populate-mu-function-header:error2/disp32 +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 +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 +1785 89/<- *(edi+8) 0/r32/eax # Function-inouts +1786 (push *(ebp+0x10) %ebx) +1787 # +1788 e9/jump loop/disp32 +1789 } +1790 # save function outputs +1791 { +1792 $parse-var-with-type:check-for-out: +1793 (next-word *(ebp+8) %ecx) +1794 # if (word-slice == '{') break +1795 (slice-equal? %ecx "{") # => eax +1796 3d/compare-eax-and 0/imm32 +1797 0f 85/jump-if-!= break/disp32 +1798 # if (word-slice == '->') abort +1799 (slice-equal? %ecx "->") # => eax +1800 3d/compare-eax-and 0/imm32 +1801 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +1802 # if (word-slice == '}') abort +1803 (slice-equal? %ecx "}") # => eax +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 +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 +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)) +1818 $populate-mu-function-header:end: +1819 # . reclaim locals +1820 81 0/subop/add %esp 8/imm32 +1821 # . restore registers +1822 5f/pop-to-edi +1823 5b/pop-to-ebx +1824 5a/pop-to-edx +1825 59/pop-to-ecx +1826 58/pop-to-eax +1827 # . epilogue +1828 89/<- %esp 5/r32/ebp +1829 5d/pop-to-ebp +1830 c3/return +1831 +1832 $populate-mu-function-header:error1: +1833 # error("function header not in form 'fn <name> {'") +1834 (write-buffered Stderr "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '") +1835 (flush Stderr) +1836 (rewind-stream *(ebp+8)) +1837 (write-stream 2 *(ebp+8)) +1838 (write-buffered Stderr "'\n") +1839 (flush Stderr) +1840 # . syscall(exit, 1) +1841 bb/copy-to-ebx 1/imm32 +1842 b8/copy-to-eax 1/imm32/exit +1843 cd/syscall 0x80/imm8 +1844 # never gets here +1845 +1846 $populate-mu-function-header:error2: +1847 # error("function input '" var "' cannot be in a register") +1848 (write-buffered Stderr "function input '") +1849 (write-buffered Stderr *ebx) # Var-name +1850 (write-buffered Stderr "' cannot be in a register") +1851 (flush Stderr) +1852 # . syscall(exit, 1) +1853 bb/copy-to-ebx 1/imm32 +1854 b8/copy-to-eax 1/imm32/exit +1855 cd/syscall 0x80/imm8 +1856 # never gets here +1857 +1858 $populate-mu-function-header:error3: +1859 # error("function input '" var "' must be in a register") +1860 (write-buffered Stderr "function input '") +1861 (write-buffered Stderr *eax) # Var-name +1862 (write-buffered Stderr " must be in a register'") +1863 (flush Stderr) +1864 (rewind-stream *(ebp+8)) +1865 (write-stream 2 *(ebp+8)) +1866 (write-buffered Stderr "'\n") +1867 (flush Stderr) +1868 # . syscall(exit, 1) +1869 bb/copy-to-ebx 1/imm32 +1870 b8/copy-to-eax 1/imm32/exit +1871 cd/syscall 0x80/imm8 +1872 # never gets here +1873 +1874 test-function-header-with-arg: +1875 # . prologue +1876 55/push-ebp +1877 89/<- %ebp 4/r32/esp +1878 # setup +1879 (clear-stream _test-input-stream) +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 +1884 (zero-out %ecx *Function-size) +1885 # var vars/ebx: (stack (addr var) 16) +1886 81 5/subop/subtract %esp 0x10/imm32 +1887 68/push 0x10/imm32/length +1888 68/push 0/imm32/top +1889 89/<- %ebx 4/r32/esp +1890 # convert +1891 (populate-mu-function-header _test-input-stream %ecx %ebx) +1892 # check result +1893 (check-strings-equal *ecx "foo" "F - test-function-header-with-arg/name") # Function-name +1894 # edx: (handle list var) = result->inouts +1895 8b/-> *(ecx+8) 2/r32/edx # Function-inouts +1896 # ebx: (handle var) = result->inouts->value +1897 8b/-> *edx 3/r32/ebx # List-value +1898 (check-strings-equal *ebx "n" "F - test-function-header-with-arg/inout:0") # Var-name +1899 8b/-> *(ebx+4) 3/r32/ebx # Var-type +1900 (check-ints-equal *ebx 1 "F - test-function-header-with-arg/inout:0/type:0") # Tree-left +1901 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-arg/inout:0/type:1") # Tree-right +1902 # . epilogue +1903 89/<- %esp 5/r32/ebp +1904 5d/pop-to-ebp +1905 c3/return +1906 +1907 test-function-header-with-multiple-args: +1908 # . prologue +1909 55/push-ebp +1910 89/<- %ebp 4/r32/esp +1911 # setup +1912 (clear-stream _test-input-stream) +1913 (write _test-input-stream "foo a: int, b: int c: int {\n") +1914 # result/ecx: (handle function) +1915 2b/subtract-> *Function-size 4/r32/esp +1916 89/<- %ecx 4/r32/esp +1917 (zero-out %ecx *Function-size) +1918 # var vars/ebx: (stack (addr var) 16) +1919 81 5/subop/subtract %esp 0x10/imm32 +1920 68/push 0x10/imm32/length +1921 68/push 0/imm32/top +1922 89/<- %ebx 4/r32/esp +1923 # convert +1924 (populate-mu-function-header _test-input-stream %ecx %ebx) +1925 # check result +1926 (check-strings-equal *ecx "foo") # Function-name +1927 # edx: (handle list var) = result->inouts +1928 8b/-> *(ecx+8) 2/r32/edx # Function-inouts +1929 $test-function-header-with-multiple-args:inout0: +1930 # ebx: (handle var) = result->inouts->value +1931 8b/-> *edx 3/r32/ebx # List-value +1932 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name +1933 8b/-> *(ebx+4) 3/r32/ebx # Var-type +1934 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:0/type:0") # Tree-left +1935 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:0/type:1") # Tree-right +1936 # edx = result->inouts->next +1937 8b/-> *(edx+4) 2/r32/edx # List-next +1938 $test-function-header-with-multiple-args:inout1: +1939 # ebx = result->inouts->next->value +1940 8b/-> *edx 3/r32/ebx # List-value +1941 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args/inout:1") # Var-name +1942 8b/-> *(ebx+4) 3/r32/ebx # Var-type +1943 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:1/type:0") # Tree-left +1944 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:1/type:1") # Tree-right +1945 # edx = result->inouts->next->next +1946 8b/-> *(edx+4) 2/r32/edx # List-next +1947 $test-function-header-with-multiple-args:inout2: +1948 # ebx = result->inouts->next->next->value +1949 8b/-> *edx 3/r32/ebx # List-value +1950 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args/inout:2") # Var-name +1951 8b/-> *(ebx+4) 3/r32/ebx # Var-type +1952 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:2/type:0") # Tree-left +1953 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:2/type:1") # Tree-right +1954 # . epilogue +1955 89/<- %esp 5/r32/ebp +1956 5d/pop-to-ebp +1957 c3/return +1958 +1959 test-function-with-multiple-args-and-outputs: +1960 # . prologue +1961 55/push-ebp +1962 89/<- %ebp 4/r32/esp +1963 # setup +1964 (clear-stream _test-input-stream) +1965 (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx: int {\n") +1966 # result/ecx: (handle function) +1967 2b/subtract-> *Function-size 4/r32/esp +1968 89/<- %ecx 4/r32/esp +1969 (zero-out %ecx *Function-size) +1970 # var vars/ebx: (stack (addr var) 16) +1971 81 5/subop/subtract %esp 0x10/imm32 +1972 68/push 0x10/imm32/length +1973 68/push 0/imm32/top +1974 89/<- %ebx 4/r32/esp +1975 # convert +1976 (populate-mu-function-header _test-input-stream %ecx %ebx) +1977 # check result +1978 (check-strings-equal *ecx "foo") # Function-name +1979 # edx: (handle list var) = result->inouts +1980 8b/-> *(ecx+8) 2/r32/edx # Function-inouts +1981 # ebx: (handle var) = result->inouts->value +1982 8b/-> *edx 3/r32/ebx # List-value +1983 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0") # Var-name +1984 8b/-> *(ebx+4) 3/r32/ebx # Var-type +1985 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0") # Tree-left +1986 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1") # Tree-right +1987 # edx = result->inouts->next +1988 8b/-> *(edx+4) 2/r32/edx # List-next +1989 # ebx = result->inouts->next->value +1990 8b/-> *edx 3/r32/ebx # List-value +1991 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1") # Var-name +1992 8b/-> *(ebx+4) 3/r32/ebx # Var-type +1993 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0") # Tree-left +1994 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1") # Tree-right +1995 # edx = result->inouts->next->next +1996 8b/-> *(edx+4) 2/r32/edx # List-next +1997 # ebx = result->inouts->next->next->value +1998 8b/-> *edx 3/r32/ebx # List-value +1999 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2") # Var-name +2000 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2001 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0") # Tree-left +2002 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1") # Tree-right +2003 # edx: (handle list var) = result->outputs +2004 8b/-> *(ecx+0xc) 2/r32/edx # Function-outputs +2005 # ebx: (handle var) = result->outputs->value +2006 8b/-> *edx 3/r32/ebx # List-value +2007 (check-strings-equal *ebx "x" "F - test-function-header-with-multiple-args-and-outputs/output:0") # Var-name +2008 (check-strings-equal *(ebx+0x10) "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register +2009 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2010 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-left +2011 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-right +2012 # edx = result->outputs->next +2013 8b/-> *(edx+4) 2/r32/edx # List-next +2014 # ebx = result->outputs->next->value +2015 8b/-> *edx 3/r32/ebx # List-value +2016 (check-strings-equal *ebx "y" "F - test-function-header-with-multiple-args-and-outputs/output:1") # Var-name +2017 (check-strings-equal *(ebx+0x10) "edx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register +2018 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2019 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-left +2020 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-right +2021 # . epilogue +2022 89/<- %esp 5/r32/ebp +2023 5d/pop-to-ebp +2024 c3/return +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 +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 +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 +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 +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 new-block-name: # fn: (handle function) -> result/eax: (handle var) -3140 # . prologue -3141 55/push-ebp -3142 89/<- %ebp 4/r32/esp -3143 # . save registers -3144 51/push-ecx -3145 52/push-edx -3146 # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:' -3147 8b/-> *(ebp+8) 0/r32/eax -3148 8b/-> *eax 0/r32/eax # Function-name -3149 8b/-> *eax 0/r32/eax # String-length -3150 05/add-to-eax 0xd/imm32 # 10 + 2 for '$:' -3151 89/<- %ecx 0/r32/eax -3152 # var name/edx: (stream byte n) -3153 29/subtract %esp 1/r32/ecx -3154 ff 6/subop/push %ecx -3155 68/push 0/imm32/read -3156 68/push 0/imm32/write -3157 89/<- %edx 4/r32/esp -3158 (clear-stream %edx) -3159 # eax = fn->name -3160 8b/-> *(ebp+8) 0/r32/eax -3161 8b/-> *eax 0/r32/eax # Function-name -3162 # construct result using Next-block-index (and increment it) -3163 (write %edx "$") -3164 (write %edx %eax) -3165 (write %edx ":") -3166 (print-int32 %edx *Next-block-index) -3167 ff 0/subop/increment *Next-block-index -3168 # var s/eax: slice = {name->data, name->data + name->write} (clobbering edx) -3169 # . eax = name->write -3170 8b/-> *edx 0/r32/eax -3171 # . edx = name->data -3172 8d/copy-address *(edx+0xc) 2/r32/edx -3173 # . eax = name->write + name->data -3174 01/add %eax 2/r32/edx -3175 # . push {edx, eax} -3176 ff 6/subop/push %eax -3177 ff 6/subop/push %edx -3178 89/<- %eax 4/r32/esp -3179 # var final-name/edx : (addr array byte) = slice-to-string(s) -3180 (slice-to-string Heap %eax) # => eax -3181 89/<- %edx 0/r32/eax -3182 # set result->var -3183 # . var type/eax: (handle tree type-id) = literal -3184 (allocate Heap *Tree-size) # => eax -3185 (zero-out %eax *Tree-size) # default type is 'literal' -3186 # . var result/eax: (handle var) = new-var(final-name, type) -3187 (new-var Heap %edx %eax *Curr-block-depth 0 0) # => eax -3188 $new-block-name:end: -3189 # . reclaim locals -3190 81 0/subop/add %ecx 0xc/imm32 # name.{read/write/len} -3191 81 0/subop/add %ecx 8/imm32 # slice -3192 01/add %esp 1/r32/ecx -3193 # . restore registers -3194 5a/pop-to-edx -3195 59/pop-to-ecx -3196 # . epilogue -3197 89/<- %esp 5/r32/ebp -3198 5d/pop-to-ebp -3199 c3/return -3200 -3201 check-no-tokens-left: # line: (addr stream byte) -3202 # . prologue -3203 55/push-ebp -3204 89/<- %ebp 4/r32/esp -3205 # . save registers -3206 50/push-eax -3207 51/push-ecx -3208 # var s/ecx: slice -3209 68/push 0/imm32/end -3210 68/push 0/imm32/start -3211 89/<- %ecx 4/r32/esp -3212 # -3213 (next-word *(ebp+8) %ecx) -3214 # if slice-empty?(s) return -3215 (slice-empty? %ecx) -3216 3d/compare-eax-and 0/imm32 -3217 75/jump-if-!= $check-no-tokens-left:end/disp8 -3218 # if (slice-starts-with?(s, '#') return -3219 # . eax = *s->start -3220 8b/-> *edx 0/r32/eax -3221 8a/copy-byte *eax 0/r32/AL -3222 81 4/subop/and %eax 0xff/imm32 -3223 # . if (eax == '#') continue -3224 3d/compare-eax-and 0x23/imm32/hash -3225 74/jump-if-= $check-no-tokens-left:end/disp8 -3226 # abort -3227 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") -3228 (rewind-stream %ecx) -3229 (write-stream 2 %ecx) -3230 (write-buffered Stderr "'\n") -3231 (flush Stderr) -3232 # . syscall(exit, 1) -3233 bb/copy-to-ebx 1/imm32 -3234 b8/copy-to-eax 1/imm32/exit -3235 cd/syscall 0x80/imm8 -3236 # never gets here -3237 $check-no-tokens-left:end: -3238 # . reclaim locals -3239 81 0/subop/add %esp 8/imm32 -3240 # . restore registers -3241 59/pop-to-ecx -3242 58/pop-to-eax -3243 # . epilogue -3244 89/<- %esp 5/r32/ebp -3245 5d/pop-to-ebp -3246 c3/return -3247 -3248 parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) -3249 # pseudocode: -3250 # var s: (addr array byte) = slice-to-string(name) -3251 # var v: (handle var) = new-var(s, 0) -3252 # v->block-depth = *Curr-block-depth # containing block depth -3253 # push(vars, v) -3254 # result = parse-mu-block(in, vars, fn) -3255 # pop(vars) -3256 # result->name = s -3257 # return result -3258 # -3259 # . prologue -3260 55/push-ebp -3261 89/<- %ebp 4/r32/esp -3262 # . save registers -3263 51/push-ecx -3264 # var s/ecx: (addr array byte) = slice-to-string(name) -3265 (slice-to-string Heap *(ebp+8)) # => eax -3266 89/<- %ecx 0/r32/eax -3267 # var type/eax: (handle tree type-id) = literal -3268 (allocate Heap *Tree-size) # => eax -3269 (zero-out %eax *Tree-size) # default type is 'literal' -3270 # var v/ecx: (handle var) = new-var(s, type) -3271 (new-var Heap %ecx %eax *Curr-block-depth 0 0) # => eax -3272 89/<- %ecx 0/r32/eax -3273 # push(vars, v) -3274 (push *(ebp+0x10) %ecx) -3275 # eax = result -3276 (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) # => eax -3277 # pop the var -3278 50/push-eax -3279 (pop *(ebp+0x10)) # => eax -3280 58/pop-to-eax -3281 # result->tag = named-block -3282 c7 0/subop/copy *eax 0/imm32/block # Stmt-tag -3283 # result->var = v -3284 89/<- *(eax+8) 1/r32/ecx # Block-var -3285 $parse-mu-named-block:end: -3286 # . restore registers -3287 59/pop-to-ecx -3288 # . epilogue -3289 89/<- %esp 5/r32/ebp -3290 5d/pop-to-ebp -3291 c3/return -3292 -3293 parse-mu-var-def: # line: (addr stream byte), vars: (addr stack (handle var)) -> result/eax: (handle stmt) -3294 # . prologue -3295 55/push-ebp -3296 89/<- %ebp 4/r32/esp -3297 # . save registers -3298 51/push-ecx -3299 52/push-edx -3300 # var word-slice/ecx: slice -3301 68/push 0/imm32/end -3302 68/push 0/imm32/start -3303 89/<- %ecx 4/r32/esp -3304 # var v/edx: (handle var) = parse-var-with-type(line) -3305 (next-word *(ebp+8) %ecx) -3306 (parse-var-with-type %ecx *(ebp+8)) # => eax -3307 89/<- %edx 0/r32/eax -3308 # v->stack-offset = *Next-local-stack-offset -3309 8b/-> *Next-local-stack-offset 0/r32/eax -3310 89/<- *(edx+0xc) 0/r32/eax # Var-stack-offset -3311 # *Next-local-stack-offset -= size-of(v) -3312 (size-of %edx) # => eax -3313 29/subtract-from *Next-local-stack-offset 0/r32/eax -3314 # v->block-depth = *Curr-block-depth -3315 8b/-> *Curr-block-depth 0/r32/eax -3316 89/<- *(edx+8) 0/r32/eax -3317 # -3318 (push *(ebp+0xc) %edx) -3319 # either v has no register and there's no more to this line -3320 8b/-> *(edx+0x10) 0/r32/eax # Var-register -3321 3d/compare-eax-and 0/imm32 -3322 { -3323 75/jump-if-!= break/disp8 -3324 # TODO: ensure that there's nothing else on this line -3325 (new-vardef Heap %edx) # => eax -3326 eb/jump $parse-mu-var-def:end/disp8 -3327 } -3328 # or v has a register and there's more to this line -3329 { -3330 74/jump-if-= break/disp8 -3331 # ensure that the next word is '<-' -3332 (next-word *(ebp+8) %ecx) -3333 (slice-equal? %ecx "<-") # => eax -3334 3d/compare-eax-and 0/imm32 -3335 74/jump-if-= $parse-mu-var-def:abort/disp8 -3336 # -3337 (new-regvardef Heap %edx) # => eax -3338 (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc)) -3339 } -3340 $parse-mu-var-def:end: -3341 # . reclaim locals -3342 81 0/subop/add %esp 8/imm32 -3343 # . restore registers -3344 5a/pop-to-edx -3345 59/pop-to-ecx -3346 # . epilogue -3347 89/<- %esp 5/r32/ebp -3348 5d/pop-to-ebp -3349 c3/return -3350 -3351 $parse-mu-var-def:abort: -3352 (rewind-stream *(ebp+8)) -3353 # error("register variable requires a valid instruction to initialize but got '" line "'\n") -3354 (write-buffered Stderr "register variable requires a valid instruction to initialize but got '") -3355 (flush Stderr) -3356 (write-stream 2 *(ebp+8)) -3357 (write-buffered Stderr "'\n") -3358 (flush Stderr) -3359 # . syscall(exit, 1) -3360 bb/copy-to-ebx 1/imm32 -3361 b8/copy-to-eax 1/imm32/exit -3362 cd/syscall 0x80/imm8 -3363 # never gets here -3364 -3365 test-parse-mu-var-def: -3366 # 'var n: int' -3367 # . prologue -3368 55/push-ebp -3369 89/<- %ebp 4/r32/esp -3370 # setup -3371 (clear-stream _test-input-stream) -3372 (write _test-input-stream "n: int\n") # caller has consumed the 'var' -3373 # var vars/ecx: (stack (addr var) 4) -3374 81 5/subop/subtract %esp 0x10/imm32 -3375 68/push 0x10/imm32/length -3376 68/push 0/imm32/top -3377 89/<- %ecx 4/r32/esp -3378 (clear-stack %ecx) -3379 # convert -3380 (parse-mu-var-def _test-input-stream %ecx) # => eax -3381 # check result -3382 (check-ints-equal *eax 2 "F - test-parse-mu-var-def/tag") # Stmt-tag is vardef -3383 8b/-> *(eax+4) 0/r32/eax # Vardef-var -3384 (check-strings-equal *eax "n" "F - test-parse-mu-var-def/var-name") # Var-name -3385 (check-ints-equal *(eax+0x10) 0 "F - test-parse-mu-var-def/var-register") # Var-register -3386 # TODO: ensure stack-offset is -4 -3387 # TODO: ensure block-depth is 1 -3388 # ensure type is int -3389 8b/-> *(eax+4) 0/r32/eax # Var-type -3390 (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0") # Tree-left -3391 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-var-def/var-type:0") # Tree-right -3392 # . epilogue -3393 89/<- %esp 5/r32/ebp -3394 5d/pop-to-ebp -3395 c3/return -3396 -3397 test-parse-mu-reg-var-def: -3398 # 'var n/eax: int <- copy 0' -3399 # . prologue -3400 55/push-ebp -3401 89/<- %ebp 4/r32/esp -3402 # setup -3403 (clear-stream _test-input-stream) -3404 (write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var' -3405 # var vars/ecx: (stack (addr var) 4) -3406 81 5/subop/subtract %esp 0x10/imm32 -3407 68/push 0x10/imm32/length -3408 68/push 0/imm32/top -3409 89/<- %ecx 4/r32/esp -3410 (clear-stack %ecx) -3411 # convert -3412 (parse-mu-var-def _test-input-stream %ecx) # => eax -3413 # check result -3414 (check-ints-equal *eax 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is regvardef -3415 8b/-> *(eax+0xc) 0/r32/eax # Regvardef-outputs -3416 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/single-output") # List-next -3417 8b/-> *eax 0/r32/eax # List-value -3418 (check-strings-equal *eax "n" "F - test-parse-mu-reg-var-def/output-name") # Var-name -3419 (check-strings-equal *(eax+0x10) "eax" "F - test-parse-mu-reg-var-def/output-register") # Var-register -3420 # TODO: ensure stack-offset is -4 -3421 # TODO: ensure block-depth is 1 -3422 # ensure type is int -3423 8b/-> *(eax+4) 0/r32/eax # Var-type -3424 (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-left -3425 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-right -3426 # . epilogue -3427 89/<- %esp 5/r32/ebp -3428 5d/pop-to-ebp -3429 c3/return -3430 -3431 parse-mu-stmt: # line: (addr stream byte), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) -3432 # pseudocode: -3433 # var name: slice -3434 # result = allocate(Heap, Stmt-size) -3435 # if stmt-has-outputs?(line) -3436 # while true -3437 # name = next-mu-token(line) -3438 # if (name == '<-') break -3439 # assert(is-identifier?(name)) -3440 # var v: (handle var) = lookup-or-define-var(name, vars, fn) # regular stmts may define vars in fn outputs -3441 # result->outputs = append(result->outputs, v) -3442 # add-operation-and-inputs-to-stmt(result, line, vars) -3443 # -3444 # . prologue -3445 55/push-ebp -3446 89/<- %ebp 4/r32/esp -3447 # . save registers -3448 51/push-ecx -3449 57/push-edi -3450 # var name/ecx: slice -3451 68/push 0/imm32/end -3452 68/push 0/imm32/start -3453 89/<- %ecx 4/r32/esp -3454 # result/edi: (handle stmt) -3455 (allocate Heap *Stmt-size) # => eax -3456 (zero-out %eax *Stmt-size) -3457 89/<- %edi 0/r32/eax -3458 # result->tag = 1/stmt -3459 c7 0/subop/copy *edi 1/imm32/stmt1 # Stmt-tag -3460 { -3461 (stmt-has-outputs? *(ebp+8)) -3462 3d/compare-eax-and 0/imm32 -3463 0f 84/jump-if-= break/disp32 -3464 { -3465 $parse-mu-stmt:read-outputs: -3466 # name = next-mu-token(line) -3467 (next-mu-token *(ebp+8) %ecx) -3468 # if slice-empty?(word-slice) break -3469 (slice-empty? %ecx) -3470 3d/compare-eax-and 0/imm32 -3471 0f 85/jump-if-!= break/disp32 -3472 # if (name == "<-") break -3473 (slice-equal? %ecx "<-") -3474 3d/compare-eax-and 0/imm32 -3475 75/jump-if-!= break/disp8 -3476 # assert(is-identifier?(name)) -3477 (is-identifier? %ecx) -3478 3d/compare-eax-and 0/imm32 -3479 0f 84/jump-if-= $parse-mu-stmt:abort/disp32 -3480 # -3481 (lookup-or-define-var %ecx *(ebp+0xc) *(ebp+0x10)) # => eax -3482 (append-list Heap %eax *(edi+0xc)) # Stmt1-outputs => eax -3483 89/<- *(edi+0xc) 0/r32/eax # Stmt1-outputs -3484 e9/jump loop/disp32 -3485 } -3486 } -3487 (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc)) -3488 $parse-mu-stmt:end: -3489 # return result -3490 89/<- %eax 7/r32/edi -3491 # . reclaim locals -3492 81 0/subop/add %esp 8/imm32 -3493 # . restore registers -3494 5f/pop-to-edi -3495 59/pop-to-ecx -3496 # . epilogue -3497 89/<- %esp 5/r32/ebp -3498 5d/pop-to-ebp -3499 c3/return -3500 -3501 $parse-mu-stmt:abort: -3502 # error("invalid identifier '" name "'\n") -3503 (write-buffered Stderr "invalid identifier '") -3504 (write-slice-buffered Stderr %ecx) -3505 (write-buffered Stderr "'\n") -3506 (flush Stderr) -3507 # . syscall(exit, 1) -3508 bb/copy-to-ebx 1/imm32 -3509 b8/copy-to-eax 1/imm32/exit -3510 cd/syscall 0x80/imm8 -3511 # never gets here -3512 -3513 add-operation-and-inputs-to-stmt: # stmt: (handle stmt), line: (addr stream byte), vars: (addr stack (handle var)) -3514 # pseudocode: -3515 # stmt->name = slice-to-string(next-mu-token(line)) -3516 # while true -3517 # name = next-mu-token(line) -3518 # v = lookup-var-or-literal(name) -3519 # stmt->inouts = append(stmt->inouts, v) -3520 # -3521 # . prologue -3522 55/push-ebp -3523 89/<- %ebp 4/r32/esp -3524 # . save registers -3525 50/push-eax -3526 51/push-ecx -3527 57/push-edi -3528 # edi = stmt -3529 8b/-> *(ebp+8) 7/r32/edi -3530 # var name/ecx: slice -3531 68/push 0/imm32/end -3532 68/push 0/imm32/start -3533 89/<- %ecx 4/r32/esp -3534 $add-operation-and-inputs-to-stmt:read-operation: -3535 (next-mu-token *(ebp+0xc) %ecx) -3536 (slice-to-string Heap %ecx) # => eax -3537 89/<- *(edi+4) 0/r32/eax # Stmt1-operation or Regvardef-operation -3538 { -3539 $add-operation-and-inputs-to-stmt:read-inouts: -3540 # name = next-mu-token(line) -3541 (next-mu-token *(ebp+0xc) %ecx) -3542 # if slice-empty?(word-slice) break -3543 (slice-empty? %ecx) # => eax -3544 3d/compare-eax-and 0/imm32 -3545 0f 85/jump-if-!= break/disp32 -3546 # if (name == "<-") abort -3547 (slice-equal? %ecx "<-") -3548 3d/compare-eax-and 0/imm32 -3549 0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32 -3550 # -3551 (lookup-var-or-literal %ecx *(ebp+0x10)) # => eax -3552 (append-list Heap %eax *(edi+8)) # Stmt1-inouts or Regvardef-inouts => eax -3553 89/<- *(edi+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts -3554 e9/jump loop/disp32 -3555 } -3556 $add-operation-and-inputs-to-stmt:end: -3557 # . reclaim locals -3558 81 0/subop/add %esp 8/imm32 -3559 # . restore registers -3560 5f/pop-to-edi -3561 59/pop-to-ecx -3562 58/pop-to-eax -3563 # . epilogue -3564 89/<- %esp 5/r32/ebp -3565 5d/pop-to-ebp -3566 c3/return -3567 -3568 $add-operation-and-inputs-to-stmt:abort: -3569 # error("invalid statement '" line "'\n") -3570 (rewind-stream *(ebp+8)) -3571 (write-buffered Stderr "invalid identifier '") -3572 (flush Stderr) -3573 (write-stream 2 *(ebp+8)) -3574 (write-buffered Stderr "'\n") -3575 (flush Stderr) -3576 # . syscall(exit, 1) -3577 bb/copy-to-ebx 1/imm32 -3578 b8/copy-to-eax 1/imm32/exit -3579 cd/syscall 0x80/imm8 -3580 # never gets here -3581 -3582 stmt-has-outputs?: # line: (addr stream byte) -> result/eax: boolean -3583 # . prologue -3584 55/push-ebp -3585 89/<- %ebp 4/r32/esp -3586 # . save registers -3587 51/push-ecx -3588 # var word-slice/ecx: slice -3589 68/push 0/imm32/end -3590 68/push 0/imm32/start -3591 89/<- %ecx 4/r32/esp -3592 # result = false -3593 b8/copy-to-eax 0/imm32/false -3594 (rewind-stream *(ebp+8)) -3595 { -3596 (next-mu-token *(ebp+8) %ecx) -3597 # if slice-empty?(word-slice) break -3598 (slice-empty? %ecx) -3599 3d/compare-eax-and 0/imm32 -3600 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) -3601 0f 85/jump-if-!= break/disp32 -3602 # if slice-starts-with?(word-slice, '#') break -3603 # . eax = *word-slice->start -3604 8b/-> *ecx 0/r32/eax -3605 8a/copy-byte *eax 0/r32/AL -3606 81 4/subop/and %eax 0xff/imm32 -3607 # . if (eax == '#') break -3608 3d/compare-eax-and 0x23/imm32/hash -3609 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) -3610 0f 84/jump-if-= break/disp32 -3611 # if slice-equal?(word-slice, '<-') return true -3612 (slice-equal? %ecx "<-") -3613 3d/compare-eax-and 0/imm32 -3614 74/jump-if-= loop/disp8 -3615 b8/copy-to-eax 1/imm32/true -3616 } -3617 $stmt-has-outputs:end: -3618 (rewind-stream *(ebp+8)) -3619 # . reclaim locals -3620 81 0/subop/add %esp 8/imm32 -3621 # . restore registers -3622 59/pop-to-ecx -3623 # . epilogue -3624 89/<- %esp 5/r32/ebp -3625 5d/pop-to-ebp -3626 c3/return -3627 -3628 # if 'name' starts with a digit, create a new literal var for it -3629 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found -3630 lookup-var-or-literal: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) +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 56/push-esi -3637 # esi = name -3638 8b/-> *(ebp+8) 6/r32/esi -3639 # if slice-empty?(name) abort -3640 (slice-empty? %esi) # => eax -3641 3d/compare-eax-and 0/imm32 -3642 0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32 -3643 # var c/ecx: byte = *name->start -3644 8b/-> *esi 1/r32/ecx -3645 8a/copy-byte *ecx 1/r32/CL -3646 81 4/subop/and %ecx 0xff/imm32 -3647 # if is-decimal-digit?(c) return new var(name) -3648 { -3649 (is-decimal-digit? %ecx) # => eax -3650 81 7/subop/compare %eax 0/imm32 -3651 74/jump-if-= break/disp8 -3652 (new-literal-integer Heap %esi) # => eax -3653 eb/jump $lookup-var-or-literal:end/disp8 -3654 } -3655 # else if (c == '"') return new var(name) -3656 { -3657 81 7/subop/compare %ecx 0x22/imm32/dquote -3658 75/jump-if-!= break/disp8 -3659 (new-literal-string Heap %esi) # => eax -3660 eb/jump $lookup-var-or-literal:end/disp8 -3661 } -3662 # otherwise return lookup-var(name, vars) -3663 { -3664 (lookup-var %esi *(ebp+0xc)) # => eax -3665 } -3666 $lookup-var-or-literal:end: -3667 # . restore registers -3668 5e/pop-to-esi -3669 59/pop-to-ecx -3670 # . epilogue -3671 89/<- %esp 5/r32/ebp -3672 5d/pop-to-ebp -3673 c3/return -3674 -3675 $lookup-var-or-literal:abort: -3676 (write-buffered Stderr "empty variable!") -3677 (flush Stderr) -3678 # . syscall(exit, 1) -3679 bb/copy-to-ebx 1/imm32 -3680 b8/copy-to-eax 1/imm32/exit -3681 cd/syscall 0x80/imm8 -3682 # never gets here -3683 -3684 # return first 'name' from the top (back) of 'vars' and abort if not found -3685 lookup-var: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) -3686 # . prologue -3687 55/push-ebp -3688 89/<- %ebp 4/r32/esp -3689 # var target/eax: (handle array byte) = slice-to-string(name) -3690 (slice-to-string Heap *(ebp+8)) # => eax -3691 # -3692 (lookup-var-helper %eax *(ebp+0xc)) # => eax -3693 # if (result == 0) abort -3694 3d/compare-eax-and 0/imm32 -3695 74/jump-if-= $lookup-var:abort/disp8 -3696 $lookup-var:end: -3697 # . epilogue -3698 89/<- %esp 5/r32/ebp -3699 5d/pop-to-ebp -3700 c3/return -3701 -3702 $lookup-var:abort: -3703 (write-buffered Stderr "unknown variable '") -3704 (write-slice-buffered Stderr *(ebp+8)) -3705 (write-buffered Stderr "'\n") -3706 (flush Stderr) -3707 # . syscall(exit, 1) -3708 bb/copy-to-ebx 1/imm32 -3709 b8/copy-to-eax 1/imm32/exit -3710 cd/syscall 0x80/imm8 -3711 # never gets here -3712 -3713 # return first 'name' from the top (back) of 'vars', and 0/null if not found -3714 lookup-var-helper: # name: (addr array byte), vars: (addr stack (handle var)) -> result/eax: (handle var) -3715 # pseudocode: -3716 # var curr: (addr handle var) = &vars->data[vars->top - 4] -3717 # var min = vars->data -3718 # while curr >= min -3719 # var v: (handle var) = *curr -3720 # if v->name == name -3721 # return v -3722 # return 0 -3723 # -3724 # . prologue -3725 55/push-ebp -3726 89/<- %ebp 4/r32/esp -3727 # . save registers -3728 52/push-edx -3729 53/push-ebx -3730 56/push-esi -3731 # esi = vars -3732 8b/-> *(ebp+0xc) 6/r32/esi -3733 # ebx = vars->top -3734 8b/-> *esi 3/r32/ebx -3735 # if (vars->top > vars->length) abort -3736 3b/compare 0/r32/eax *(esi+4) -3737 0f 8f/jump-if-> $lookup-var-helper:error1/disp32 -3738 # var min/edx: (addr handle var) = vars->data -3739 8d/copy-address *(esi+8) 2/r32/edx -3740 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 4] -3741 81 5/subop/subtract %ebx 4/imm32 -3742 8d/copy-address *(esi+ebx+8) 3/r32/ebx -3743 { -3744 # if (curr < min) return 0 -3745 39/compare %ebx 2/r32/edx -3746 b8/copy-to-eax 0/imm32 -3747 0f 82/jump-if-addr< break/disp32 -3748 # var v/eax: (handle var) = *curr -3749 8b/-> *ebx 0/r32/eax -3750 # if (v->name == name) return v -3751 (string-equal? *eax *(ebp+8)) # Var-name -3752 3d/compare-eax-and 0/imm32 -3753 8b/-> *ebx 0/r32/eax -3754 75/jump-if-!= break/disp8 -3755 # curr -= 4 -3756 81 5/subop/subtract %ebx 4/imm32 -3757 e9/jump loop/disp32 -3758 } -3759 $lookup-var-helper:end: -3760 # . restore registers -3761 5e/pop-to-esi -3762 5b/pop-to-ebx -3763 5a/pop-to-edx -3764 # . epilogue -3765 89/<- %esp 5/r32/ebp -3766 5d/pop-to-ebp -3767 c3/return +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") +3762 (flush Stderr) +3763 # . syscall(exit, 1) +3764 bb/copy-to-ebx 1/imm32 +3765 b8/copy-to-eax 1/imm32/exit +3766 cd/syscall 0x80/imm8 +3767 # never gets here 3768 -3769 $lookup-var-helper:error1: -3770 (write-buffered Stderr "malformed stack when looking up '") -3771 (write-slice-buffered Stderr *(ebp+8)) -3772 (write-buffered Stderr "'\n") -3773 (flush Stderr) -3774 # . syscall(exit, 1) -3775 bb/copy-to-ebx 1/imm32 -3776 b8/copy-to-eax 1/imm32/exit -3777 cd/syscall 0x80/imm8 -3778 # never gets here -3779 -3780 # return first 'name' from the top (back) of 'vars' and create a new var for a fn output if not found -3781 lookup-or-define-var: # name: (addr slice), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle var) -3782 # . prologue -3783 55/push-ebp -3784 89/<- %ebp 4/r32/esp -3785 # . save registers -3786 51/push-ecx -3787 # var target/ecx: (handle array byte) = slice-to-string(name) -3788 (slice-to-string Heap *(ebp+8)) # => eax -3789 89/<- %ecx 0/r32/eax -3790 # -3791 (lookup-var-helper %ecx *(ebp+0xc)) # => eax -3792 { -3793 # if (result != 0) return -3794 3d/compare-eax-and 0/imm32 -3795 75/jump-if-!= break/disp8 -3796 # if name is one of fn's outputs, return it -3797 { -3798 (find-in-function-outputs *(ebp+0x10) %ecx) # => eax -3799 3d/compare-eax-and 0/imm32 -3800 # otherwise abort -3801 0f 84/jump-if-!= $lookup-var:abort/disp32 -3802 } +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 $lookup-or-define-var:end: -3805 # . restore registers -3806 59/pop-to-ecx -3807 # . epilogue -3808 89/<- %esp 5/r32/ebp -3809 5d/pop-to-ebp -3810 c3/return -3811 -3812 find-in-function-outputs: # fn: (handle function), name: (handle array byte) => result/eax: (handle var) -3813 # . prologue -3814 55/push-ebp -3815 89/<- %ebp 4/r32/esp -3816 # . save registers -3817 51/push-ecx -3818 # var curr/ecx: (handle list var) = fn->outputs -3819 8b/-> *(ebp+8) 1/r32/ecx -3820 8b/-> *(ecx+0xc) 1/r32/ecx -3821 # while curr != null -3822 { -3823 81 7/subop/compare %ecx 0/imm32 -3824 74/jump-if-= break/disp8 -3825 # var v: (handle var) = *curr -3826 8b/-> *ecx 0/r32/eax # List-value -3827 # if (curr->name == name) return curr -3828 50/push-eax -3829 (string-equal? *eax *(ebp+0xc)) -3830 3d/compare-eax-and 0/imm32 -3831 58/pop-to-eax -3832 75/jump-if-!= $find-in-function-outputs:end/disp8 -3833 # curr = curr->next -3834 8b/-> *(ecx+4) 1/r32/ecx # List-next -3835 eb/jump loop/disp8 -3836 } -3837 b8/copy-to-eax 0/imm32 -3838 $find-in-function-outputs:end: -3839 # . restore registers -3840 59/pop-to-ecx -3841 # . epilogue -3842 89/<- %esp 5/r32/ebp -3843 5d/pop-to-ebp -3844 c3/return -3845 -3846 test-parse-mu-stmt: -3847 # . prologue -3848 55/push-ebp -3849 89/<- %ebp 4/r32/esp -3850 # setup -3851 (clear-stream _test-input-stream) -3852 (write _test-input-stream "increment n\n") -3853 # var vars/ecx: (stack (addr var) 4) -3854 81 5/subop/subtract %esp 0x10/imm32 -3855 68/push 0x10/imm32/length -3856 68/push 0/imm32/top -3857 89/<- %ecx 4/r32/esp -3858 (clear-stack %ecx) -3859 # var v/edx: var -3860 81 5/subop/subtract %esp 0x14/imm32 # Var-size -3861 89/<- %edx 4/r32/esp -3862 (zero-out %edx 0x14) # Var-size -3863 # v->name = "n" -3864 c7 0/subop/copy *edx "n"/imm32 # Var-name -3865 # -3866 (push %ecx %edx) -3867 # convert -3868 (parse-mu-stmt _test-input-stream %ecx) # => eax -3869 # check result -3870 (check-ints-equal *eax 1 "F - test-parse-mu-stmt/tag") # Stmt-tag is Stmt1 -3871 (check-strings-equal *(eax+4) "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation -3872 # edx: (handle list var) = result->inouts -3873 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts -3874 # ebx: (handle var) = result->inouts->value -3875 8b/-> *edx 3/r32/ebx # List-value -3876 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt/inout:0") # Var-name -3877 # . epilogue -3878 89/<- %esp 5/r32/ebp -3879 5d/pop-to-ebp -3880 c3/return -3881 -3882 test-parse-mu-stmt-with-comma: -3883 # . prologue -3884 55/push-ebp -3885 89/<- %ebp 4/r32/esp -3886 # setup -3887 (clear-stream _test-input-stream) -3888 (write _test-input-stream "copy-to n, 3\n") -3889 # var vars/ecx: (stack (addr var) 4) -3890 81 5/subop/subtract %esp 0x10/imm32 -3891 68/push 0x10/imm32/length -3892 68/push 0/imm32/top -3893 89/<- %ecx 4/r32/esp -3894 (clear-stack %ecx) -3895 # var v/edx: var -3896 81 5/subop/subtract %esp 0x14/imm32 # Var-size -3897 89/<- %edx 4/r32/esp -3898 (zero-out %edx 0x14) # Var-size -3899 # v->name = "n" -3900 c7 0/subop/copy *edx "n"/imm32 # Var-name -3901 # -3902 (push %ecx %edx) -3903 # convert -3904 (parse-mu-stmt _test-input-stream %ecx) # => eax -3905 # check result -3906 (check-ints-equal *eax 1 "F - test-parse-mu-stmt-with-comma/tag") # Stmt-tag is Stmt1 -3907 (check-strings-equal *(eax+4) "copy-to" "F - test-parse-mu-stmt-with-comma/name") # Stmt1-operation -3908 # edx: (handle list var) = result->inouts -3909 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts -3910 # ebx: (handle var) = result->inouts->value -3911 8b/-> *edx 3/r32/ebx # List-value -3912 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt-with-comma/inout:0") # Var-name -3913 # . epilogue -3914 89/<- %esp 5/r32/ebp -3915 5d/pop-to-ebp -3916 c3/return -3917 -3918 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) -3919 # . prologue -3920 55/push-ebp -3921 89/<- %ebp 4/r32/esp -3922 # . save registers -3923 51/push-ecx -3924 # -3925 (allocate *(ebp+8) *Function-size) # => eax -3926 8b/-> *(ebp+0xc) 1/r32/ecx -3927 89/<- *eax 1/r32/ecx # Function-name -3928 8b/-> *(ebp+0x10) 1/r32/ecx -3929 89/<- *(eax+4) 1/r32/ecx # Function-subx-name -3930 8b/-> *(ebp+0x14) 1/r32/ecx -3931 89/<- *(eax+8) 1/r32/ecx # Function-inouts -3932 8b/-> *(ebp+0x18) 1/r32/ecx -3933 89/<- *(eax+0xc) 1/r32/ecx # Function-outputs -3934 8b/-> *(ebp+0x1c) 1/r32/ecx -3935 89/<- *(eax+0x10) 1/r32/ecx # Function-body -3936 8b/-> *(ebp+0x20) 1/r32/ecx -3937 89/<- *(eax+0x14) 1/r32/ecx # Function-next -3938 $new-function:end: -3939 # . restore registers -3940 59/pop-to-ecx -3941 # . epilogue -3942 89/<- %esp 5/r32/ebp -3943 5d/pop-to-ebp -3944 c3/return -3945 -3946 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) -3947 # . prologue -3948 55/push-ebp -3949 89/<- %ebp 4/r32/esp -3950 # . save registers -3951 51/push-ecx -3952 # -3953 (allocate *(ebp+8) *Var-size) # => eax -3954 8b/-> *(ebp+0xc) 1/r32/ecx -3955 89/<- *eax 1/r32/ecx # Var-name -3956 8b/-> *(ebp+0x10) 1/r32/ecx -3957 89/<- *(eax+4) 1/r32/ecx # Var-type -3958 8b/-> *(ebp+0x14) 1/r32/ecx -3959 89/<- *(eax+8) 1/r32/ecx # Var-block-depth -3960 8b/-> *(ebp+0x18) 1/r32/ecx -3961 89/<- *(eax+0xc) 1/r32/ecx # Var-stack-offset -3962 8b/-> *(ebp+0x1c) 1/r32/ecx -3963 89/<- *(eax+0x10) 1/r32/ecx # Var-register -3964 $new-var:end: -3965 # . restore registers -3966 59/pop-to-ecx -3967 # . epilogue -3968 89/<- %esp 5/r32/ebp -3969 5d/pop-to-ebp -3970 c3/return -3971 -3972 new-literal-integer: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -3973 # . prologue -3974 55/push-ebp -3975 89/<- %ebp 4/r32/esp -3976 # . save registers -3977 51/push-ecx -3978 # if (!is-hex-int?(name)) abort -3979 (is-hex-int? *(ebp+0xc)) # => eax -3980 3d/compare-eax-and 0/imm32 -3981 0f 84/jump-if-= $new-literal-integer:abort/disp32 -3982 # var s/ecx: (addr array byte) -3983 (slice-to-string Heap *(ebp+0xc)) # => eax -3984 89/<- %ecx 0/r32/eax -3985 # result/ecx = new var(s) -3986 (allocate *(ebp+8) *Var-size) # => eax -3987 (zero-out %eax *Var-size) -3988 89/<- *eax 1/r32/ecx # Var-name -3989 89/<- %ecx 0/r32/eax -3990 # result->type = new type() -3991 (allocate *(ebp+8) *Tree-size) # => eax -3992 (zero-out %eax *Tree-size) # default type is 'literal' -3993 89/<- *(ecx+4) 0/r32/eax # Var-type -3994 # move result to eax -3995 89/<- %eax 1/r32/ecx -3996 $new-literal-integer:end: -3997 # . restore registers -3998 59/pop-to-ecx -3999 # . epilogue -4000 89/<- %esp 5/r32/ebp -4001 5d/pop-to-ebp -4002 c3/return -4003 -4004 $new-literal-integer:abort: -4005 (write-buffered Stderr "variable cannot begin with a digit '") -4006 (write-slice-buffered Stderr *(ebp+0xc)) -4007 (write-buffered Stderr "'\n") -4008 (flush Stderr) -4009 # . syscall(exit, 1) -4010 bb/copy-to-ebx 1/imm32 -4011 b8/copy-to-eax 1/imm32/exit -4012 cd/syscall 0x80/imm8 -4013 # never gets here -4014 -4015 new-literal-string: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -4016 # . prologue -4017 55/push-ebp -4018 89/<- %ebp 4/r32/esp -4019 # . save registers -4020 51/push-ecx -4021 # var s/ecx: (addr array byte) -4022 (slice-to-string Heap *(ebp+0xc)) # => eax -4023 89/<- %ecx 0/r32/eax -4024 # result/ecx = new var(s) -4025 (allocate *(ebp+8) *Var-size) # => eax -4026 (zero-out %eax *Var-size) -4027 89/<- *eax 1/r32/ecx # Var-name -4028 89/<- %ecx 0/r32/eax -4029 # result->type = new type() -4030 (allocate *(ebp+8) *Tree-size) # => eax -4031 (zero-out %eax *Tree-size) # default type is 'literal' -4032 89/<- *(ecx+4) 0/r32/eax # Var-type -4033 # move result to eax -4034 89/<- %eax 1/r32/ecx -4035 $new-literal-string:end: -4036 # . restore registers -4037 59/pop-to-ecx -4038 # . epilogue -4039 89/<- %esp 5/r32/ebp -4040 5d/pop-to-ebp -4041 c3/return -4042 -4043 new-label: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -4044 # . prologue -4045 55/push-ebp -4046 89/<- %ebp 4/r32/esp -4047 # . save registers -4048 51/push-ecx -4049 # var s/ecx: (addr array byte) -4050 (slice-to-string Heap *(ebp+0xc)) # => eax -4051 89/<- %ecx 0/r32/eax +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 +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 (allocate *(ebp+8) *Var-size) # => eax -4054 89/<- *eax 1/r32/ecx # Var-name -4055 89/<- %ecx 0/r32/eax -4056 (allocate *(ebp+8) *Tree-size) # => eax -4057 (zero-out %eax *Tree-size) # labels are literals -4058 89/<- *(ecx+4) 0/r32/eax # Var-type -4059 89/<- %eax 1/r32/ecx -4060 c7 0/subop/copy *(eax+8) 0/imm32 # Var-block-depth -4061 c7 0/subop/copy *(eax+0xc) 0/imm32 # Var-stack-offset -4062 c7 0/subop/copy *(eax+0x10) 0/imm32 # Var-register -4063 $new-label:end: -4064 # . restore registers -4065 59/pop-to-ecx -4066 # . epilogue -4067 89/<- %esp 5/r32/ebp -4068 5d/pop-to-ebp -4069 c3/return -4070 -4071 new-block: # ad: (addr allocation-descriptor), data: (handle list statement) -> result/eax: (handle statement) -4072 # . prologue -4073 55/push-ebp -4074 89/<- %ebp 4/r32/esp -4075 # . save registers -4076 51/push-ecx -4077 # -4078 (allocate *(ebp+8) *Stmt-size) # => eax -4079 (zero-out %eax *Stmt-size) -4080 c7 0/subop/copy *eax 0/imm32/tag/block # Stmt-tag -4081 8b/-> *(ebp+0xc) 1/r32/ecx -4082 89/<- *(eax+4) 1/r32/ecx # Block-statements -4083 $new-block:end: -4084 # . restore registers -4085 59/pop-to-ecx -4086 # . epilogue -4087 89/<- %esp 5/r32/ebp -4088 5d/pop-to-ebp -4089 c3/return -4090 -4091 new-vardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) -4092 # . prologue -4093 55/push-ebp -4094 89/<- %ebp 4/r32/esp -4095 # . save registers -4096 51/push-ecx -4097 # -4098 (allocate *(ebp+8) *Stmt-size) # => eax -4099 (zero-out %eax *Stmt-size) -4100 c7 0/subop/copy *eax 2/imm32/tag/var-on-stack # Stmt-tag -4101 # result->var = var -4102 8b/-> *(ebp+0xc) 1/r32/ecx -4103 89/<- *(eax+4) 1/r32/ecx # Vardef-var -4104 $new-vardef:end: -4105 # . restore registers -4106 59/pop-to-ecx -4107 # . epilogue -4108 89/<- %esp 5/r32/ebp -4109 5d/pop-to-ebp -4110 c3/return -4111 -4112 new-regvardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) -4113 # . prologue -4114 55/push-ebp -4115 89/<- %ebp 4/r32/esp -4116 # . save registers -4117 51/push-ecx -4118 57/push-edi -4119 # ecx = var -4120 8b/-> *(ebp+0xc) 1/r32/ecx -4121 # edi = result -4122 (allocate *(ebp+8) *Stmt-size) # => eax -4123 89/<- %edi 0/r32/eax -4124 (zero-out %edi *Stmt-size) -4125 # set tag -4126 c7 0/subop/copy *edi 3/imm32/tag/var-in-register # Stmt-tag -4127 # set output -4128 (append-list Heap %ecx *(edi+0xc)) # Regvardef-outputs => eax -4129 89/<- *(edi+0xc) 0/r32/eax # Regvardef-outputs -4130 $new-regvardef:end: -4131 89/<- %eax 7/r32/edi -4132 # . restore registers -4133 5f/pop-to-edi -4134 59/pop-to-ecx -4135 # . epilogue -4136 89/<- %esp 5/r32/ebp -4137 5d/pop-to-ebp -4138 c3/return -4139 -4140 new-list: # ad: (addr allocation-descriptor), value: _type, next: (handle list _type) -> result/eax: (handle list _type) -4141 # . prologue -4142 55/push-ebp -4143 89/<- %ebp 4/r32/esp -4144 # . save registers -4145 51/push-ecx -4146 # -4147 (allocate *(ebp+8) *List-size) # => eax -4148 8b/-> *(ebp+0xc) 1/r32/ecx -4149 89/<- *eax 1/r32/ecx # List-value -4150 8b/-> *(ebp+0x10) 1/r32/ecx -4151 89/<- *(eax+4) 1/r32/ecx # List-next -4152 $new-list:end: -4153 # . restore registers -4154 59/pop-to-ecx -4155 # . epilogue -4156 89/<- %esp 5/r32/ebp -4157 5d/pop-to-ebp -4158 c3/return -4159 -4160 append-list: # ad: (addr allocation-descriptor), value: _type, list: (handle list _type) -> result/eax: (handle list _type) -4161 # . prologue -4162 55/push-ebp -4163 89/<- %ebp 4/r32/esp -4164 # . save registers -4165 51/push-ecx -4166 # -4167 (allocate *(ebp+8) *List-size) # => eax -4168 8b/-> *(ebp+0xc) 1/r32/ecx -4169 89/<- *eax 1/r32/ecx # List-value -4170 # if (list == null) return result -4171 81 7/subop/compare *(ebp+0x10) 0/imm32 -4172 74/jump-if-= $new-list:end/disp8 -4173 # otherwise append -4174 # var curr/ecx = list -4175 8b/-> *(ebp+0x10) 1/r32/ecx -4176 # while (curr->next != null) curr = curr->next -4177 { -4178 81 7/subop/compare *(ecx+4) 0/imm32 # List-next -4179 74/jump-if-= break/disp8 -4180 # curr = curr->next -4181 8b/-> *(ecx+4) 1/r32/ecx -4182 eb/jump loop/disp8 -4183 } -4184 # curr->next = result -4185 89/<- *(ecx+4) 0/r32/eax -4186 # return list -4187 8b/-> *(ebp+0x10) 0/r32/eax -4188 $append-list:end: -4189 # . restore registers -4190 59/pop-to-ecx -4191 # . epilogue -4192 89/<- %esp 5/r32/ebp -4193 5d/pop-to-ebp -4194 c3/return -4195 -4196 append-to-block: # ad: (addr allocation-descriptor), block: (handle block), x: (handle stmt) -4197 # . prologue -4198 55/push-ebp -4199 89/<- %ebp 4/r32/esp -4200 # . save registers -4201 56/push-esi -4202 # esi = block -4203 8b/-> *(ebp+0xc) 6/r32/esi -4204 (append-list *(ebp+8) *(ebp+0x10) *(esi+4)) # ad, x, Block-statements -4205 89/<- *(esi+4) 0/r32/eax # Block-statements -4206 $append-to-block:end: -4207 # . restore registers -4208 5e/pop-to-esi -4209 # . epilogue -4210 89/<- %esp 5/r32/ebp -4211 5d/pop-to-ebp -4212 c3/return -4213 -4214 ####################################################### -4215 # Type-checking -4216 ####################################################### -4217 -4218 check-mu-types: -4219 # . prologue -4220 55/push-ebp -4221 89/<- %ebp 4/r32/esp -4222 # -4223 $check-mu-types:end: -4224 # . epilogue -4225 89/<- %esp 5/r32/ebp -4226 5d/pop-to-ebp -4227 c3/return -4228 -4229 size-of: # v: (addr var) -> result/eax: int -4230 # . prologue -4231 55/push-ebp -4232 89/<- %ebp 4/r32/esp -4233 # if v is a literal, return 0 -4234 8b/-> *(ebp+8) 0/r32/eax -4235 8b/-> *(eax+4) 0/r32/eax # Var-type -4236 81 7/subop/compare *eax 0/imm32 # Tree-left -4237 b8/copy-to-eax 0/imm32 -4238 74/jump-if-= $size-of:end/disp8 -4239 # hard-coded since we only support 'int' types for now -4240 b8/copy-to-eax 4/imm32 -4241 $size-of:end: -4242 # . epilogue -4243 89/<- %esp 5/r32/ebp -4244 5d/pop-to-ebp -4245 c3/return -4246 -4247 == data -4248 -4249 # not yet used, but it will be -4250 Type-size: # (stream int) -4251 0x18/imm32/write -4252 0/imm32/read -4253 0x100/imm32/length -4254 # data -4255 4/imm32 # literal -4256 4/imm32 # int -4257 4/imm32 # addr -4258 0/imm32 # array (logic elsewhere) -4259 8/imm32 # handle (fat pointer) -4260 4/imm32 # bool -4261 0/imm32 -4262 0/imm32 -4263 # 0x20 -4264 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4265 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4266 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4267 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4268 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4269 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4270 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4271 -4272 == code -4273 -4274 ####################################################### -4275 # Code-generation -4276 ####################################################### +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 emit-subx: # out: (addr buffered-file) +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 50/push-eax -4284 51/push-ecx -4285 57/push-edi -4286 # edi = out -4287 8b/-> *(ebp+8) 7/r32/edi -4288 # var curr/ecx: (handle function) = *Program -4289 8b/-> *Program 1/r32/ecx -4290 { -4291 # if (curr == null) break -4292 81 7/subop/compare %ecx 0/imm32 -4293 0f 84/jump-if-= break/disp32 -4294 (emit-subx-function %edi %ecx) -4295 # curr = curr->next -4296 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next -4297 e9/jump loop/disp32 -4298 } -4299 $emit-subx:end: -4300 # . restore registers -4301 5f/pop-to-edi -4302 59/pop-to-ecx -4303 58/pop-to-eax -4304 # . epilogue -4305 89/<- %esp 5/r32/ebp -4306 5d/pop-to-ebp -4307 c3/return -4308 -4309 emit-subx-function: # out: (addr buffered-file), f: (handle function) -4310 # . prologue -4311 55/push-ebp -4312 89/<- %ebp 4/r32/esp -4313 # . save registers -4314 50/push-eax -4315 51/push-ecx -4316 52/push-edx -4317 57/push-edi -4318 # edi = out -4319 8b/-> *(ebp+8) 7/r32/edi -4320 # ecx = f -4321 8b/-> *(ebp+0xc) 1/r32/ecx -4322 # var vars/edx: (stack (addr var) 256) -4323 81 5/subop/subtract %esp 0x400/imm32 -4324 68/push 0x400/imm32/length -4325 68/push 0/imm32/top -4326 89/<- %edx 4/r32/esp -4327 # -4328 (write-buffered %edi *ecx) -4329 (write-buffered %edi ":\n") -4330 # Important: each block's depth during code-generation should be identical -4331 # to what it was during parsing. -4332 c7 0/subop/copy *Curr-block-depth 1/imm32 -4333 (emit-subx-prologue %edi) -4334 (emit-subx-block %edi *(ecx+0x10) %edx) # Function-body -4335 (emit-subx-epilogue %edi) -4336 $emit-subx-function:end: -4337 # . reclaim locals -4338 81 0/subop/add %esp 408/imm32 -4339 # . restore registers -4340 5f/pop-to-edi -4341 5a/pop-to-edx -4342 59/pop-to-ecx -4343 58/pop-to-eax -4344 # . epilogue -4345 89/<- %esp 5/r32/ebp -4346 5d/pop-to-ebp -4347 c3/return -4348 -4349 emit-subx-stmt-list: # out: (addr buffered-file), stmts: (handle list stmt), vars: (addr stack (handle var)) -4350 # . prologue -4351 55/push-ebp -4352 89/<- %ebp 4/r32/esp -4353 # . save registers -4354 50/push-eax -4355 51/push-ecx -4356 52/push-edx -4357 56/push-esi -4358 # esi = stmts -4359 8b/-> *(ebp+0xc) 6/r32/esi -4360 # var var-seen?/edx: boolean <- copy false -4361 ba/copy-to-edx 0/imm32/false -4362 # -4363 { -4364 $emit-subx-stmt-list:loop: -4365 81 7/subop/compare %esi 0/imm32 -4366 0f 84/jump-if-= break/disp32 -4367 # var curr-stmt/ecx = stmts->value -4368 8b/-> *esi 1/r32/ecx # List-value -4369 { -4370 $emit-subx-stmt-list:check-for-block: -4371 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag -4372 75/jump-if-!= break/disp8 -4373 $emit-subx-stmt-list:block: -4374 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10)) -4375 } -4376 { -4377 $emit-subx-stmt-list:check-for-stmt: -4378 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag -4379 0f 85/jump-if-!= break/disp32 -4380 { -4381 # if !var-seen? break -4382 81 7/subop/compare %edx 0/imm32/false -4383 0f 84/jump-if-= break/disp32 -4384 $emit-subx-stmt-list:check-for-break: -4385 # if (!string-starts-with?(var->operation, "break")) break -4386 (string-starts-with? *(ecx+4) "break") # Stmt1-operation => eax -4387 3d/compare-eax-and 0/imm32 -4388 0f 84/jump-if-= break/disp32 -4389 81 7/subop/compare *(ecx+8) 0/imm32 # Stmt1-inouts -4390 { -4391 0f 85/jump-if-!= break/disp32 -4392 $emit-subx-stmt-list:zero-arg-break: -4393 # create a new block for the remaining statements -4394 (emit-indent *(ebp+8) *Curr-block-depth) -4395 (write-buffered *(ebp+8) "{\n") -4396 ff 0/subop/increment *Curr-block-depth -4397 (emit-subx-stmt-list *(ebp+8) %esi *(ebp+0x10)) -4398 ff 1/subop/decrement *Curr-block-depth -4399 (emit-indent *(ebp+8) *Curr-block-depth) -4400 (write-buffered *(ebp+8) "}\n") -4401 # return $emit-subx-stmt-list -4402 e9/jump $emit-subx-stmt-list:cleanup/disp32 -4403 } -4404 { -4405 0f 84/jump-if-= break/disp32 -4406 $emit-subx-stmt-list:one-arg-break: -4407 # TODO -4408 # continue -4409 e9/jump $emit-subx-stmt-list:continue/disp32 -4410 } -4411 } -4412 { -4413 # if !var-seen? break -4414 81 7/subop/compare %edx 0/imm32/false -4415 0f 84/jump-if-= break/disp32 -4416 $emit-subx-stmt-list:check-for-loop: -4417 # if (!string-starts-with?(var->operation, "loop")) break -4418 (string-starts-with? *(ecx+4) "loop") # Stmt1-operation => eax -4419 3d/compare-eax-and 0/imm32 -4420 0f 84/jump-if-= break/disp32 -4421 81 7/subop/compare *(ecx+8) 0/imm32 # Stmt1-inouts -4422 { -4423 0f 85/jump-if-!= break/disp32 -4424 $emit-subx-stmt-list:zero-arg-loop: -4425 # var old-block-depth/eax: int = Curr-block-depth - 1 -4426 8b/-> *Curr-block-depth 0/r32/eax -4427 # cleanup prologue -4428 (emit-indent *(ebp+8) *Curr-block-depth) -4429 (write-buffered *(ebp+8) "{\n") -4430 ff 0/subop/increment *Curr-block-depth -4431 # -4432 (emit-reverse-break *(ebp+8) %ecx) -4433 # clean up until old block depth -4434 (emit-cleanup-code *(ebp+8) *(ebp+0x10) %eax) -4435 # var target-block-depth/eax: int = Curr-block-depth - 1 -4436 48/decrement-eax -4437 # emit jump to target block -4438 (emit-unconditional-jump-to-depth *(ebp+8) *(ebp+0x10) %eax) -4439 # cleanup epilogue -4440 ff 1/subop/decrement *Curr-block-depth -4441 (emit-indent *(ebp+8) *Curr-block-depth) -4442 (write-buffered *(ebp+8) "}\n") -4443 # continue -4444 e9/jump $emit-subx-stmt-list:continue/disp32 -4445 } -4446 { -4447 0f 84/jump-if-= break/disp32 -4448 $emit-subx-stmt-list:one-arg-loop: -4449 # TODO -4450 # continue -4451 e9/jump $emit-subx-stmt-list:continue/disp32 -4452 } -4453 } -4454 $emit-subx-stmt-list:stmt: -4455 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) -4456 } -4457 { -4458 $emit-subx-stmt-list:check-for-vardef: -4459 81 7/subop/compare *ecx 2/imm32/vardef # Stmt-tag -4460 75/jump-if-!= break/disp8 -4461 $emit-subx-stmt-list:vardef: -4462 (emit-subx-var-def *(ebp+8) %ecx) -4463 (push *(ebp+0x10) *(ecx+4)) # Vardef-var -4464 # var-seen? = true -4465 ba/copy-to-edx 1/imm32/true -4466 } -4467 { -4468 $emit-subx-stmt-list:check-for-regvardef: -4469 81 7/subop/compare *ecx 3/imm32/regvardef # Stmt-tag -4470 0f 85/jump-if-!= break/disp32 -4471 $emit-subx-stmt-list:regvardef: -4472 # TODO: ensure that there's exactly one output -4473 # var output/eax: (handle var) = curr-stmt->outputs->value -4474 8b/-> *(ecx+0xc) 0/r32/eax -4475 8b/-> *eax 0/r32/eax -4476 # ensure that output is in a register -4477 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -4478 0f 84/jump-if-= $emit-subx-stmt-list:abort-regvardef-without-register/disp32 -4479 # emit spill -4480 (emit-indent *(ebp+8) *Curr-block-depth) -4481 (write-buffered *(ebp+8) "ff 6/subop/push %") -4482 (write-buffered *(ebp+8) *(eax+0x10)) -4483 (write-buffered *(ebp+8) Newline) -4484 # register variable definition -4485 (push *(ebp+0x10) %eax) -4486 # emit the instruction as usual -4487 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) -4488 # var-seen? = true -4489 ba/copy-to-edx 1/imm32/true -4490 } -4491 $emit-subx-stmt-list:continue: -4492 # TODO: raise an error on unrecognized Stmt-tag -4493 8b/-> *(esi+4) 6/r32/esi # List-next -4494 e9/jump loop/disp32 -4495 } -4496 $emit-subx-stmt-list:cleanup: -4497 (emit-cleanup-code *(ebp+8) *(ebp+0x10) *Curr-block-depth) -4498 (clean-up-blocks *(ebp+0x10) *Curr-block-depth) -4499 $emit-subx-stmt-list:end: -4500 # . restore registers -4501 5e/pop-to-esi -4502 5a/pop-to-edx -4503 59/pop-to-ecx -4504 58/pop-to-eax -4505 # . epilogue -4506 89/<- %esp 5/r32/ebp -4507 5d/pop-to-ebp -4508 c3/return -4509 -4510 $emit-subx-stmt-list:abort-regvardef-without-register: -4511 # error("var '" var->name "' initialized from an instruction must live in a register\n") -4512 (write-buffered Stderr "var '") -4513 (write-buffered Stderr *eax) # Var-name -4514 (write-buffered Stderr "' initialized from an instruction must live in a register\n") -4515 (flush Stderr) -4516 # . syscall(exit, 1) -4517 bb/copy-to-ebx 1/imm32 -4518 b8/copy-to-eax 1/imm32/exit -4519 cd/syscall 0x80/imm8 -4520 # never gets here -4521 -4522 emit-reverse-break: # out: (addr buffered-file), stmt: (addr stmt1) -4523 # . prologue -4524 55/push-ebp -4525 89/<- %ebp 4/r32/esp -4526 # . save registers -4527 50/push-eax -4528 # eax = stmt -4529 8b/-> *(ebp+0xc) 0/r32/eax -4530 # -4531 (get Reverse-branch *(eax+4) 8 "reverse-branch: ") # Stmt1-operation => eax: (addr addr array byte) -4532 (emit-indent *(ebp+8) *Curr-block-depth) -4533 (write-buffered *(ebp+8) *eax) -4534 (write-buffered *(ebp+8) " break/disp32\n") -4535 $emit-reverse-break:end: -4536 # . restore registers -4537 58/pop-to-eax -4538 # . epilogue -4539 89/<- %esp 5/r32/ebp -4540 5d/pop-to-ebp -4541 c3/return -4542 -4543 == data -4544 -4545 Reverse-branch: # (table string string) -4546 # a table is a stream -4547 0xa0/imm32/write -4548 0/imm32/read -4549 0xa0/imm32/length -4550 # data -4551 "break-if-="/imm32 "0f 85/jump-if-!="/imm32 -4552 "loop-if-="/imm32 "0f 85/jump-if-!="/imm32 -4553 "break-if-!="/imm32 "0f 84/jump-if-="/imm32 -4554 "loop-if-!="/imm32 "0f 84/jump-if-="/imm32 -4555 "break-if-<"/imm32 "0f 8d/jump-if->="/imm32 -4556 "loop-if-<"/imm32 "0f 8d/jump-if->="/imm32 -4557 "break-if->"/imm32 "0f 8e/jump-if-<="/imm32 -4558 "loop-if->"/imm32 "0f 8e/jump-if-<="/imm32 -4559 "break-if-<="/imm32 "0f 87/jump-if->"/imm32 -4560 "loop-if-<="/imm32 "0f 87/jump-if->"/imm32 -4561 "break-if->="/imm32 "0f 8c/jump-if-<"/imm32 -4562 "loop-if->="/imm32 "0f 8c/jump-if-<"/imm32 -4563 "break-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 -4564 "loop-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 -4565 "break-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 -4566 "loop-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 -4567 "break-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 -4568 "loop-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 -4569 "break-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 -4570 "loop-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 -4571 -4572 == code -4573 -4574 emit-unconditional-jump-to-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), depth: int -4575 # . prologue -4576 55/push-ebp -4577 89/<- %ebp 4/r32/esp -4578 # . save registers -4579 50/push-eax -4580 51/push-ecx -4581 52/push-edx -4582 53/push-ebx -4583 # ecx = vars -4584 8b/-> *(ebp+0xc) 1/r32/ecx -4585 # var eax: int = vars->top -4586 8b/-> *ecx 0/r32/eax -4587 # var min/ecx: (address (handle var)) = vars->data -4588 81 0/subop/add %ecx 8/imm32 -4589 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] -4590 81 5/subop/subtract %eax 4/imm32 -4591 8d/copy-address *(ecx+eax) 0/r32/eax -4592 # edx = depth -4593 8b/-> *(ebp+0x10) 2/r32/edx -4594 { -4595 $emit-unconditional-jump-to-depth:loop: -4596 # if (curr < min) break -4597 39/compare %eax 1/r32/ecx -4598 0f 82/jump-if-addr< break/disp32 -4599 # var v/ebx: (handle var) = *curr -4600 8b/-> *eax 3/r32/ebx -4601 # if (v->block-depth < until-block-depth) break -4602 39/compare *(ebx+8) 2/r32/edx # Var-block-depth -4603 0f 8c/jump-if-< break/disp32 -4604 { -4605 $emit-unconditional-jump-to-depth:check: -4606 # if v->block-depth != until-block-depth, continue -4607 39/compare *(ebx+8) 2/r32/edx # Var-block-depth -4608 75/jump-if-!= break/disp8 -4609 $emit-unconditional-jump-to-depth:depth-found: -4610 # if v is not a literal, continue -4611 # . var eax: int = size-of(v) -4612 50/push-eax -4613 (size-of %ebx) # => eax -4614 # . if (eax != 0) continue -4615 3d/compare-eax-and 0/imm32 -4616 58/pop-to-eax -4617 # -4618 75/jump-if-!= break/disp8 -4619 $emit-unconditional-jump-to-depth:label-found: -4620 # emit unconditional jump, then return -4621 (emit-indent *(ebp+8) *Curr-block-depth) -4622 (write-buffered *(ebp+8) "e9/jump ") -4623 (write-buffered *(ebp+8) *ebx) # Var-name -4624 (write-buffered *(ebp+8) ":loop/disp32\n") # Var-name -4625 eb/jump $emit-unconditional-jump-to-depth:end/disp8 -4626 } -4627 # curr -= 4 -4628 2d/subtract-from-eax 4/imm32 -4629 e9/jump loop/disp32 -4630 } -4631 # TODO: error if no label at 'depth' was found -4632 $emit-unconditional-jump-to-depth:end: -4633 # . restore registers -4634 5b/pop-to-ebx -4635 5a/pop-to-edx -4636 59/pop-to-ecx -4637 58/pop-to-eax -4638 # . epilogue -4639 89/<- %esp 5/r32/ebp -4640 5d/pop-to-ebp -4641 c3/return -4642 -4643 # emit clean-up code for 'vars' until some block depth -4644 # doesn't actually modify 'vars' so we need traverse manually inside the stack -4645 emit-cleanup-code: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-depth: int -4646 # . prologue -4647 55/push-ebp -4648 89/<- %ebp 4/r32/esp -4649 # . save registers -4650 50/push-eax -4651 51/push-ecx -4652 52/push-edx -4653 53/push-ebx -4654 # ecx = vars -4655 8b/-> *(ebp+0xc) 1/r32/ecx -4656 # var eax: int = vars->top -4657 8b/-> *ecx 0/r32/eax -4658 # var min/ecx: (address (handle var)) = vars->data -4659 81 0/subop/add %ecx 8/imm32 -4660 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] -4661 81 5/subop/subtract %eax 4/imm32 -4662 8d/copy-address *(ecx+eax) 0/r32/eax -4663 # edx = until-block-depth -4664 8b/-> *(ebp+0x10) 2/r32/edx -4665 { -4666 $emit-cleanup-code:loop: -4667 # if (curr < min) break -4668 39/compare %eax 1/r32/ecx -4669 0f 82/jump-if-addr< break/disp32 -4670 # var v/ebx: (handle var) = *curr -4671 8b/-> *eax 3/r32/ebx -4672 # if (v->block-depth < until-block-depth) break -4673 39/compare *(ebx+8) 2/r32/edx # Var-block-depth -4674 0f 8c/jump-if-< break/disp32 -4675 # if v is in a register -4676 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -4677 { -4678 74/jump-if-= break/disp8 -4679 $emit-cleanup-code:reclaim-var-in-register: -4680 (emit-indent *(ebp+8) *Curr-block-depth) -4681 (write-buffered *(ebp+8) "8f 0/subop/pop %") -4682 (write-buffered *(ebp+8) *(ebx+0x10)) -4683 (write-buffered *(ebp+8) Newline) -4684 } -4685 # otherwise v is on the stack +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: +4292 # . restore registers +4293 59/pop-to-ecx +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: +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 75/jump-if-!= break/disp8 -4688 $emit-cleanup-code:reclaim-var-on-stack: -4689 50/push-eax -4690 (size-of %ebx) # => eax -4691 # don't emit code for labels -4692 3d/compare-eax-and 0/imm32 -4693 74/jump-if-= break/disp8 -4694 # -4695 (emit-indent *(ebp+8) *Curr-block-depth) -4696 (write-buffered *(ebp+8) "81 0/subop/add %esp ") -4697 (print-int32-buffered *(ebp+8) %eax) -4698 (write-buffered *(ebp+8) "/imm32\n") -4699 58/pop-to-eax -4700 } -4701 # curr -= 4 -4702 2d/subtract-from-eax 4/imm32 -4703 e9/jump loop/disp32 -4704 } -4705 $emit-cleanup-code:end: -4706 # . restore registers -4707 5b/pop-to-ebx -4708 5a/pop-to-edx -4709 59/pop-to-ecx -4710 58/pop-to-eax -4711 # . epilogue -4712 89/<- %esp 5/r32/ebp -4713 5d/pop-to-ebp -4714 c3/return -4715 -4716 # clean up global state for 'vars' until some block depth -4717 clean-up-blocks: # vars: (addr stack (handle var)), until-block-depth: int -4718 # . prologue -4719 55/push-ebp -4720 89/<- %ebp 4/r32/esp -4721 # . save registers -4722 50/push-eax -4723 51/push-ecx -4724 56/push-esi -4725 # esi = vars -4726 8b/-> *(ebp+8) 6/r32/esi -4727 # ecx = until-block-depth -4728 8b/-> *(ebp+0xc) 1/r32/ecx -4729 { -4730 $clean-up-blocks:reclaim-loop: -4731 # if (vars->top <= 0) break -4732 81 7/subop/compare *esi 0/imm32 # Stack-top -4733 7e/jump-if-<= break/disp8 -4734 # var v/eax : (handle var) = top(vars) -4735 (top %esi) # => eax -4736 # if (v->block-depth < until-block-depth) break -4737 39/compare *(eax+8) 1/r32/ecx # Var-block-depth -4738 7c/jump-if-< break/disp8 -4739 # if v is on the stack, update Next-local-stack-offset -4740 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -4741 { -4742 75/jump-if-!= break/disp8 -4743 $clean-up-blocks:reclaim-var-on-stack: -4744 (size-of %eax) # => eax -4745 01/add *Next-local-stack-offset 0/r32/eax -4746 } -4747 (pop %esi) -4748 e9/jump loop/disp32 -4749 } -4750 $clean-up-blocks:end: -4751 # . restore registers -4752 5e/pop-to-esi -4753 59/pop-to-ecx -4754 58/pop-to-eax -4755 # . epilogue -4756 89/<- %esp 5/r32/ebp -4757 5d/pop-to-ebp -4758 c3/return -4759 -4760 emit-subx-var-def: # out: (addr buffered-file), stmt: (handle statement) -4761 # . prologue -4762 55/push-ebp -4763 89/<- %ebp 4/r32/esp -4764 # . save registers -4765 50/push-eax -4766 51/push-ecx -4767 # eax = stmt -4768 8b/-> *(ebp+0xc) 0/r32/eax -4769 # var n/eax: int = size-of(stmt->var) -4770 (size-of *(eax+4)) # Vardef-var => eax -4771 # while n > 0 -4772 { -4773 3d/compare-eax-with 0/imm32 -4774 7e/jump-if-<= break/disp8 -4775 (emit-indent *(ebp+8) *Curr-block-depth) -4776 (write-buffered *(ebp+8) "68/push 0/imm32\n") -4777 # n -= 4 -4778 2d/subtract-from-eax 4/imm32 -4779 # -4780 eb/jump loop/disp8 -4781 } -4782 $emit-subx-var-def:end: -4783 # . restore registers -4784 59/pop-to-ecx -4785 58/pop-to-eax -4786 # . epilogue -4787 89/<- %esp 5/r32/ebp -4788 5d/pop-to-ebp -4789 c3/return -4790 -4791 emit-subx-statement: # out: (addr buffered-file), stmt: (handle statement), primitives: (handle primitive), functions: (handle function) -4792 # . prologue -4793 55/push-ebp -4794 89/<- %ebp 4/r32/esp -4795 # . save registers -4796 50/push-eax -4797 51/push-ecx -4798 # if stmt matches a primitive, emit it -4799 { -4800 $emit-subx-statement:check-for-primitive: -4801 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => curr/eax -4802 3d/compare-eax-and 0/imm32 -4803 74/jump-if-= break/disp8 -4804 $emit-subx-statement:primitive: -4805 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr -4806 e9/jump $emit-subx-statement:end/disp32 -4807 } -4808 # else if stmt matches a function, emit a call to it -4809 { -4810 $emit-subx-statement:check-for-call: -4811 (find-matching-function *(ebp+0x14) *(ebp+0xc)) # functions, stmt => curr/eax -4812 3d/compare-eax-and 0/imm32 -4813 74/jump-if-= break/disp8 -4814 $emit-subx-statement:call: -4815 (emit-subx-call *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr -4816 e9/jump $emit-subx-statement:end/disp32 -4817 } -4818 # else abort -4819 e9/jump $emit-subx-statement:abort/disp32 -4820 $emit-subx-statement:end: -4821 # . restore registers -4822 59/pop-to-ecx -4823 58/pop-to-eax -4824 # . epilogue -4825 89/<- %esp 5/r32/ebp -4826 5d/pop-to-ebp -4827 c3/return -4828 -4829 $emit-subx-statement:abort: -4830 # error("couldn't translate '" stmt "'\n") -4831 (write-buffered Stderr "couldn't translate an instruction with operation '") -4832 8b/-> *(ebp+0xc) 0/r32/eax -4833 (write-buffered Stderr *(eax+4)) # Stmt1-operation -4834 (write-buffered Stderr "'\n") -4835 (flush Stderr) -4836 # . syscall(exit, 1) -4837 bb/copy-to-ebx 1/imm32 -4838 b8/copy-to-eax 1/imm32/exit -4839 cd/syscall 0x80/imm8 -4840 # never gets here -4841 -4842 emit-subx-block: # out: (addr buffered-file), block: (handle block), vars: (addr stack (handle var)) -4843 # . prologue -4844 55/push-ebp -4845 89/<- %ebp 4/r32/esp -4846 # . save registers -4847 50/push-eax -4848 51/push-ecx -4849 56/push-esi -4850 # esi = block -4851 8b/-> *(ebp+0xc) 6/r32/esi -4852 # var stmts/eax: (handle list statement) = block->statements -4853 8b/-> *(esi+4) 0/r32/eax # Block-statements -4854 # -4855 { -4856 $emit-subx-block:check-empty: -4857 81 7/subop/compare %eax 0/imm32 -4858 0f 84/jump-if-= break/disp32 -4859 (emit-indent *(ebp+8) *Curr-block-depth) -4860 (write-buffered *(ebp+8) "{\n") -4861 # var v/ecx: (addr array byte) = block->var->name -4862 8b/-> *(esi+8) 1/r32/ecx # Block-var -4863 (write-buffered *(ebp+8) *ecx) # Var-name -4864 (write-buffered *(ebp+8) ":loop:\n") -4865 ff 0/subop/increment *Curr-block-depth -4866 (push *(ebp+0x10) %ecx) -4867 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10)) -4868 (pop *(ebp+0x10)) # => eax -4869 ff 1/subop/decrement *Curr-block-depth -4870 (emit-indent *(ebp+8) *Curr-block-depth) -4871 (write-buffered *(ebp+8) "}\n") -4872 (write-buffered *(ebp+8) *ecx) # Var-name -4873 (write-buffered *(ebp+8) ":break:\n") -4874 } -4875 $emit-subx-block:end: -4876 # . restore registers -4877 5e/pop-to-esi -4878 59/pop-to-ecx -4879 58/pop-to-eax -4880 # . epilogue -4881 89/<- %esp 5/r32/ebp -4882 5d/pop-to-ebp -4883 c3/return -4884 -4885 # Primitives supported -4886 # For each operation, put variants with hard-coded registers before flexible ones. -4887 == data -4888 Primitives: -4889 # - increment/decrement -4890 _Primitive-inc-eax: -4891 # var/eax <- increment => 40/increment-eax -4892 "increment"/imm32/name -4893 0/imm32/no-inouts -4894 Single-int-var-in-eax/imm32/outputs -4895 "40/increment-eax"/imm32/subx-name -4896 0/imm32/no-rm32 -4897 0/imm32/no-r32 -4898 0/imm32/no-imm32 -4899 0/imm32/no-disp32 -4900 0/imm32/output-is-write-only -4901 _Primitive-inc-ecx/imm32/next -4902 _Primitive-inc-ecx: -4903 # var/ecx <- increment => 41/increment-ecx -4904 "increment"/imm32/name -4905 0/imm32/no-inouts -4906 Single-int-var-in-ecx/imm32/outputs -4907 "41/increment-ecx"/imm32/subx-name -4908 0/imm32/no-rm32 -4909 0/imm32/no-r32 -4910 0/imm32/no-imm32 -4911 0/imm32/no-disp32 -4912 0/imm32/output-is-write-only -4913 _Primitive-inc-edx/imm32/next -4914 _Primitive-inc-edx: -4915 # var/edx <- increment => 42/increment-edx -4916 "increment"/imm32/name -4917 0/imm32/no-inouts -4918 Single-int-var-in-edx/imm32/outputs -4919 "42/increment-edx"/imm32/subx-name -4920 0/imm32/no-rm32 -4921 0/imm32/no-r32 -4922 0/imm32/no-imm32 -4923 0/imm32/no-disp32 -4924 0/imm32/output-is-write-only -4925 _Primitive-inc-ebx/imm32/next -4926 _Primitive-inc-ebx: -4927 # var/ebx <- increment => 43/increment-ebx -4928 "increment"/imm32/name -4929 0/imm32/no-inouts -4930 Single-int-var-in-ebx/imm32/outputs -4931 "43/increment-ebx"/imm32/subx-name -4932 0/imm32/no-rm32 -4933 0/imm32/no-r32 -4934 0/imm32/no-imm32 -4935 0/imm32/no-disp32 -4936 0/imm32/output-is-write-only -4937 _Primitive-inc-esi/imm32/next -4938 _Primitive-inc-esi: -4939 # var/esi <- increment => 46/increment-esi -4940 "increment"/imm32/name -4941 0/imm32/no-inouts -4942 Single-int-var-in-esi/imm32/outputs -4943 "46/increment-esi"/imm32/subx-name -4944 0/imm32/no-rm32 -4945 0/imm32/no-r32 -4946 0/imm32/no-imm32 -4947 0/imm32/no-disp32 -4948 0/imm32/output-is-write-only -4949 _Primitive-inc-edi/imm32/next -4950 _Primitive-inc-edi: -4951 # var/edi <- increment => 47/increment-edi -4952 "increment"/imm32/name -4953 0/imm32/no-inouts -4954 Single-int-var-in-edi/imm32/outputs -4955 "47/increment-edi"/imm32/subx-name -4956 0/imm32/no-rm32 -4957 0/imm32/no-r32 -4958 0/imm32/no-imm32 -4959 0/imm32/no-disp32 -4960 0/imm32/output-is-write-only -4961 _Primitive-dec-eax/imm32/next -4962 _Primitive-dec-eax: -4963 # var/eax <- decrement => 48/decrement-eax -4964 "decrement"/imm32/name -4965 0/imm32/no-inouts -4966 Single-int-var-in-eax/imm32/outputs -4967 "48/decrement-eax"/imm32/subx-name -4968 0/imm32/no-rm32 -4969 0/imm32/no-r32 -4970 0/imm32/no-imm32 -4971 0/imm32/no-disp32 -4972 0/imm32/output-is-write-only -4973 _Primitive-dec-ecx/imm32/next -4974 _Primitive-dec-ecx: -4975 # var/ecx <- decrement => 49/decrement-ecx -4976 "decrement"/imm32/name -4977 0/imm32/no-inouts -4978 Single-int-var-in-ecx/imm32/outputs -4979 "49/decrement-ecx"/imm32/subx-name -4980 0/imm32/no-rm32 -4981 0/imm32/no-r32 -4982 0/imm32/no-imm32 -4983 0/imm32/no-disp32 -4984 0/imm32/output-is-write-only -4985 _Primitive-dec-edx/imm32/next -4986 _Primitive-dec-edx: -4987 # var/edx <- decrement => 4a/decrement-edx -4988 "decrement"/imm32/name -4989 0/imm32/no-inouts -4990 Single-int-var-in-edx/imm32/outputs -4991 "4a/decrement-edx"/imm32/subx-name -4992 0/imm32/no-rm32 -4993 0/imm32/no-r32 -4994 0/imm32/no-imm32 -4995 0/imm32/no-disp32 -4996 0/imm32/output-is-write-only -4997 _Primitive-dec-ebx/imm32/next -4998 _Primitive-dec-ebx: -4999 # var/ebx <- decrement => 4b/decrement-ebx -5000 "decrement"/imm32/name -5001 0/imm32/no-inouts -5002 Single-int-var-in-ebx/imm32/outputs -5003 "4b/decrement-ebx"/imm32/subx-name -5004 0/imm32/no-rm32 -5005 0/imm32/no-r32 -5006 0/imm32/no-imm32 -5007 0/imm32/no-disp32 -5008 0/imm32/output-is-write-only -5009 _Primitive-dec-esi/imm32/next -5010 _Primitive-dec-esi: -5011 # var/esi <- decrement => 4e/decrement-esi -5012 "decrement"/imm32/name -5013 0/imm32/no-inouts -5014 Single-int-var-in-esi/imm32/outputs -5015 "4e/decrement-esi"/imm32/subx-name -5016 0/imm32/no-rm32 -5017 0/imm32/no-r32 -5018 0/imm32/no-imm32 -5019 0/imm32/no-disp32 -5020 0/imm32/output-is-write-only -5021 _Primitive-dec-edi/imm32/next -5022 _Primitive-dec-edi: -5023 # var/edi <- decrement => 4f/decrement-edi -5024 "decrement"/imm32/name -5025 0/imm32/no-inouts -5026 Single-int-var-in-edi/imm32/outputs -5027 "4f/decrement-edi"/imm32/subx-name -5028 0/imm32/no-rm32 -5029 0/imm32/no-r32 -5030 0/imm32/no-imm32 -5031 0/imm32/no-disp32 -5032 0/imm32/output-is-write-only -5033 _Primitive-inc-mem/imm32/next -5034 _Primitive-inc-mem: -5035 # increment var => ff 0/subop/increment *(ebp+__) -5036 "increment"/imm32/name -5037 Single-int-var-on-stack/imm32/inouts -5038 0/imm32/no-outputs -5039 "ff 0/subop/increment"/imm32/subx-name -5040 1/imm32/rm32-is-first-inout -5041 0/imm32/no-r32 -5042 0/imm32/no-imm32 -5043 0/imm32/no-disp32 -5044 0/imm32/output-is-write-only -5045 _Primitive-inc-reg/imm32/next -5046 _Primitive-inc-reg: -5047 # var/reg <- increment => ff 0/subop/increment %__ -5048 "increment"/imm32/name -5049 0/imm32/no-inouts -5050 Single-int-var-in-some-register/imm32/outputs -5051 "ff 0/subop/increment"/imm32/subx-name -5052 3/imm32/rm32-is-first-output -5053 0/imm32/no-r32 -5054 0/imm32/no-imm32 -5055 0/imm32/no-disp32 -5056 0/imm32/output-is-write-only -5057 _Primitive-dec-mem/imm32/next -5058 _Primitive-dec-mem: -5059 # decrement var => ff 1/subop/decrement *(ebp+__) -5060 "decrement"/imm32/name -5061 Single-int-var-on-stack/imm32/inouts -5062 0/imm32/no-outputs -5063 "ff 1/subop/decrement"/imm32/subx-name -5064 1/imm32/rm32-is-first-inout -5065 0/imm32/no-r32 -5066 0/imm32/no-imm32 -5067 0/imm32/no-disp32 -5068 0/imm32/output-is-write-only -5069 _Primitive-dec-reg/imm32/next -5070 _Primitive-dec-reg: -5071 # var/reg <- decrement => ff 1/subop/decrement %__ -5072 "decrement"/imm32/name -5073 0/imm32/no-inouts -5074 Single-int-var-in-some-register/imm32/outputs -5075 "ff 1/subop/decrement"/imm32/subx-name -5076 3/imm32/rm32-is-first-output -5077 0/imm32/no-r32 -5078 0/imm32/no-imm32 -5079 0/imm32/no-disp32 -5080 0/imm32/output-is-write-only -5081 _Primitive-add-to-eax/imm32/next -5082 # - add -5083 _Primitive-add-to-eax: -5084 # var/eax <- add lit => 05/add-to-eax lit/imm32 -5085 "add"/imm32/name -5086 Single-lit-var/imm32/inouts -5087 Single-int-var-in-eax/imm32/outputs -5088 "05/add-to-eax"/imm32/subx-name -5089 0/imm32/no-rm32 -5090 0/imm32/no-r32 -5091 1/imm32/imm32-is-first-inout -5092 0/imm32/no-disp32 -5093 0/imm32/output-is-write-only -5094 _Primitive-add-reg-to-reg/imm32/next -5095 _Primitive-add-reg-to-reg: -5096 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 -5097 "add"/imm32/name -5098 Single-int-var-in-some-register/imm32/inouts -5099 Single-int-var-in-some-register/imm32/outputs -5100 "01/add-to"/imm32/subx-name -5101 3/imm32/rm32-is-first-output -5102 1/imm32/r32-is-first-inout -5103 0/imm32/no-imm32 -5104 0/imm32/no-disp32 -5105 0/imm32/output-is-write-only -5106 _Primitive-add-reg-to-mem/imm32/next -5107 _Primitive-add-reg-to-mem: -5108 # add-to var1 var2/reg => 01/add-to var1 var2/r32 -5109 "add-to"/imm32/name -5110 Two-args-int-stack-int-reg/imm32/inouts -5111 0/imm32/outputs -5112 "01/add-to"/imm32/subx-name -5113 1/imm32/rm32-is-first-inout -5114 2/imm32/r32-is-second-inout -5115 0/imm32/no-imm32 -5116 0/imm32/no-disp32 -5117 0/imm32/output-is-write-only -5118 _Primitive-add-mem-to-reg/imm32/next -5119 _Primitive-add-mem-to-reg: -5120 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 -5121 "add"/imm32/name -5122 Single-int-var-on-stack/imm32/inouts -5123 Single-int-var-in-some-register/imm32/outputs -5124 "03/add"/imm32/subx-name -5125 1/imm32/rm32-is-first-inout -5126 3/imm32/r32-is-first-output -5127 0/imm32/no-imm32 -5128 0/imm32/no-disp32 -5129 0/imm32/output-is-write-only -5130 _Primitive-add-lit-to-reg/imm32/next -5131 _Primitive-add-lit-to-reg: -5132 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 -5133 "add"/imm32/name -5134 Single-lit-var/imm32/inouts -5135 Single-int-var-in-some-register/imm32/outputs -5136 "81 0/subop/add"/imm32/subx-name -5137 3/imm32/rm32-is-first-output -5138 0/imm32/no-r32 -5139 1/imm32/imm32-is-first-inout -5140 0/imm32/no-disp32 -5141 0/imm32/output-is-write-only -5142 _Primitive-add-lit-to-mem/imm32/next -5143 _Primitive-add-lit-to-mem: -5144 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 -5145 "add-to"/imm32/name -5146 Int-var-and-literal/imm32/inouts -5147 0/imm32/outputs -5148 "81 0/subop/add"/imm32/subx-name -5149 1/imm32/rm32-is-first-inout -5150 0/imm32/no-r32 -5151 2/imm32/imm32-is-second-inout -5152 0/imm32/no-disp32 -5153 0/imm32/output-is-write-only -5154 _Primitive-subtract-from-eax/imm32/next -5155 # - subtract -5156 _Primitive-subtract-from-eax: -5157 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 -5158 "subtract"/imm32/name -5159 Single-lit-var/imm32/inouts -5160 Single-int-var-in-eax/imm32/outputs -5161 "2d/subtract-from-eax"/imm32/subx-name -5162 0/imm32/no-rm32 -5163 0/imm32/no-r32 -5164 1/imm32/imm32-is-first-inout -5165 0/imm32/no-disp32 -5166 0/imm32/output-is-write-only -5167 _Primitive-subtract-reg-from-reg/imm32/next -5168 _Primitive-subtract-reg-from-reg: -5169 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 -5170 "subtract"/imm32/name -5171 Single-int-var-in-some-register/imm32/inouts -5172 Single-int-var-in-some-register/imm32/outputs -5173 "29/subtract-from"/imm32/subx-name -5174 3/imm32/rm32-is-first-output -5175 1/imm32/r32-is-first-inout -5176 0/imm32/no-imm32 -5177 0/imm32/no-disp32 -5178 0/imm32/output-is-write-only -5179 _Primitive-subtract-reg-from-mem/imm32/next -5180 _Primitive-subtract-reg-from-mem: -5181 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 -5182 "subtract-from"/imm32/name -5183 Two-args-int-stack-int-reg/imm32/inouts -5184 0/imm32/outputs -5185 "29/subtract-from"/imm32/subx-name -5186 1/imm32/rm32-is-first-inout -5187 2/imm32/r32-is-second-inout -5188 0/imm32/no-imm32 -5189 0/imm32/no-disp32 -5190 0/imm32/output-is-write-only -5191 _Primitive-subtract-mem-from-reg/imm32/next -5192 _Primitive-subtract-mem-from-reg: -5193 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 -5194 "subtract"/imm32/name -5195 Single-int-var-on-stack/imm32/inouts -5196 Single-int-var-in-some-register/imm32/outputs -5197 "2b/subtract"/imm32/subx-name -5198 1/imm32/rm32-is-first-inout -5199 3/imm32/r32-is-first-output -5200 0/imm32/no-imm32 -5201 0/imm32/no-disp32 -5202 0/imm32/output-is-write-only -5203 _Primitive-subtract-lit-from-reg/imm32/next -5204 _Primitive-subtract-lit-from-reg: -5205 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 -5206 "subtract"/imm32/name -5207 Single-lit-var/imm32/inouts -5208 Single-int-var-in-some-register/imm32/outputs -5209 "81 5/subop/subtract"/imm32/subx-name -5210 3/imm32/rm32-is-first-output -5211 0/imm32/no-r32 -5212 1/imm32/imm32-is-first-inout -5213 0/imm32/no-disp32 -5214 0/imm32/output-is-write-only -5215 _Primitive-subtract-lit-from-mem/imm32/next -5216 _Primitive-subtract-lit-from-mem: -5217 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 -5218 "subtract-from"/imm32/name -5219 Int-var-and-literal/imm32/inouts -5220 0/imm32/outputs -5221 "81 5/subop/subtract"/imm32/subx-name -5222 1/imm32/rm32-is-first-inout -5223 0/imm32/no-r32 -5224 2/imm32/imm32-is-first-inout -5225 0/imm32/no-disp32 -5226 0/imm32/output-is-write-only -5227 _Primitive-and-with-eax/imm32/next -5228 # - and -5229 _Primitive-and-with-eax: -5230 # var/eax <- and lit => 25/and-with-eax lit/imm32 -5231 "and"/imm32/name -5232 Single-lit-var/imm32/inouts -5233 Single-int-var-in-eax/imm32/outputs -5234 "25/and-with-eax"/imm32/subx-name -5235 0/imm32/no-rm32 -5236 0/imm32/no-r32 -5237 1/imm32/imm32-is-first-inout -5238 0/imm32/no-disp32 -5239 0/imm32/output-is-write-only -5240 _Primitive-and-reg-with-reg/imm32/next -5241 _Primitive-and-reg-with-reg: -5242 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 -5243 "and"/imm32/name -5244 Single-int-var-in-some-register/imm32/inouts -5245 Single-int-var-in-some-register/imm32/outputs -5246 "21/and-with"/imm32/subx-name -5247 3/imm32/rm32-is-first-output -5248 1/imm32/r32-is-first-inout -5249 0/imm32/no-imm32 -5250 0/imm32/no-disp32 -5251 0/imm32/output-is-write-only -5252 _Primitive-and-reg-with-mem/imm32/next -5253 _Primitive-and-reg-with-mem: -5254 # and-with var1 var2/reg => 21/and-with var1 var2/r32 -5255 "and-with"/imm32/name -5256 Two-args-int-stack-int-reg/imm32/inouts -5257 0/imm32/outputs -5258 "21/and-with"/imm32/subx-name -5259 1/imm32/rm32-is-first-inout -5260 2/imm32/r32-is-second-inout -5261 0/imm32/no-imm32 -5262 0/imm32/no-disp32 -5263 0/imm32/output-is-write-only -5264 _Primitive-and-mem-with-reg/imm32/next -5265 _Primitive-and-mem-with-reg: -5266 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 -5267 "and"/imm32/name -5268 Single-int-var-on-stack/imm32/inouts -5269 Single-int-var-in-some-register/imm32/outputs -5270 "23/and"/imm32/subx-name -5271 1/imm32/rm32-is-first-inout -5272 3/imm32/r32-is-first-output -5273 0/imm32/no-imm32 -5274 0/imm32/no-disp32 -5275 0/imm32/output-is-write-only -5276 _Primitive-and-lit-with-reg/imm32/next -5277 _Primitive-and-lit-with-reg: -5278 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 -5279 "and"/imm32/name -5280 Single-lit-var/imm32/inouts -5281 Single-int-var-in-some-register/imm32/outputs -5282 "81 4/subop/and"/imm32/subx-name -5283 3/imm32/rm32-is-first-output -5284 0/imm32/no-r32 -5285 1/imm32/imm32-is-first-inout -5286 0/imm32/no-disp32 -5287 0/imm32/output-is-write-only -5288 _Primitive-and-lit-with-mem/imm32/next -5289 _Primitive-and-lit-with-mem: -5290 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 -5291 "and-with"/imm32/name -5292 Int-var-and-literal/imm32/inouts -5293 0/imm32/outputs -5294 "81 4/subop/and"/imm32/subx-name -5295 1/imm32/rm32-is-first-inout -5296 0/imm32/no-r32 -5297 2/imm32/imm32-is-first-inout -5298 0/imm32/no-disp32 -5299 0/imm32/output-is-write-only -5300 _Primitive-or-with-eax/imm32/next -5301 # - or -5302 _Primitive-or-with-eax: -5303 # var/eax <- or lit => 0d/or-with-eax lit/imm32 -5304 "or"/imm32/name -5305 Single-lit-var/imm32/inouts -5306 Single-int-var-in-eax/imm32/outputs -5307 "0d/or-with-eax"/imm32/subx-name -5308 0/imm32/no-rm32 -5309 0/imm32/no-r32 -5310 1/imm32/imm32-is-first-inout -5311 0/imm32/no-disp32 -5312 0/imm32/output-is-write-only -5313 _Primitive-or-reg-with-reg/imm32/next -5314 _Primitive-or-reg-with-reg: -5315 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 -5316 "or"/imm32/name -5317 Single-int-var-in-some-register/imm32/inouts -5318 Single-int-var-in-some-register/imm32/outputs -5319 "09/or-with"/imm32/subx-name -5320 3/imm32/rm32-is-first-output -5321 1/imm32/r32-is-first-inout -5322 0/imm32/no-imm32 -5323 0/imm32/no-disp32 -5324 0/imm32/output-is-write-only -5325 _Primitive-or-reg-with-mem/imm32/next -5326 _Primitive-or-reg-with-mem: -5327 # or-with var1 var2/reg => 09/or-with var1 var2/r32 -5328 "or-with"/imm32/name -5329 Two-args-int-stack-int-reg/imm32/inouts -5330 0/imm32/outputs -5331 "09/or-with"/imm32/subx-name -5332 1/imm32/rm32-is-first-inout -5333 2/imm32/r32-is-second-inout -5334 0/imm32/no-imm32 -5335 0/imm32/no-disp32 -5336 0/imm32/output-is-write-only -5337 _Primitive-or-mem-with-reg/imm32/next -5338 _Primitive-or-mem-with-reg: -5339 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 -5340 "or"/imm32/name -5341 Single-int-var-on-stack/imm32/inouts -5342 Single-int-var-in-some-register/imm32/outputs -5343 "0b/or"/imm32/subx-name -5344 1/imm32/rm32-is-first-inout -5345 3/imm32/r32-is-first-output -5346 0/imm32/no-imm32 -5347 0/imm32/no-disp32 -5348 0/imm32/output-is-write-only -5349 _Primitive-or-lit-with-reg/imm32/next -5350 _Primitive-or-lit-with-reg: -5351 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 -5352 "or"/imm32/name -5353 Single-lit-var/imm32/inouts -5354 Single-int-var-in-some-register/imm32/outputs -5355 "81 1/subop/or"/imm32/subx-name -5356 3/imm32/rm32-is-first-output -5357 0/imm32/no-r32 -5358 1/imm32/imm32-is-first-inout -5359 0/imm32/no-disp32 -5360 0/imm32/output-is-write-only -5361 _Primitive-or-lit-with-mem/imm32/next -5362 _Primitive-or-lit-with-mem: -5363 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 -5364 "or-with"/imm32/name -5365 Int-var-and-literal/imm32/inouts -5366 0/imm32/outputs -5367 "81 1/subop/or"/imm32/subx-name -5368 1/imm32/rm32-is-first-inout -5369 0/imm32/no-r32 -5370 2/imm32/imm32-is-second-inout -5371 0/imm32/no-disp32 -5372 0/imm32/output-is-write-only -5373 _Primitive-xor-with-eax/imm32/next -5374 # - xor -5375 _Primitive-xor-with-eax: -5376 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 -5377 "xor"/imm32/name -5378 Single-lit-var/imm32/inouts -5379 Single-int-var-in-eax/imm32/outputs -5380 "35/xor-with-eax"/imm32/subx-name -5381 0/imm32/no-rm32 -5382 0/imm32/no-r32 -5383 1/imm32/imm32-is-first-inout -5384 0/imm32/no-disp32 -5385 0/imm32/output-is-write-only -5386 _Primitive-xor-reg-with-reg/imm32/next -5387 _Primitive-xor-reg-with-reg: -5388 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 -5389 "xor"/imm32/name -5390 Single-int-var-in-some-register/imm32/inouts -5391 Single-int-var-in-some-register/imm32/outputs -5392 "31/xor-with"/imm32/subx-name -5393 3/imm32/rm32-is-first-output -5394 1/imm32/r32-is-first-inout -5395 0/imm32/no-imm32 -5396 0/imm32/no-disp32 -5397 0/imm32/output-is-write-only -5398 _Primitive-xor-reg-with-mem/imm32/next -5399 _Primitive-xor-reg-with-mem: -5400 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 -5401 "xor-with"/imm32/name -5402 Two-args-int-stack-int-reg/imm32/inouts -5403 0/imm32/outputs -5404 "31/xor-with"/imm32/subx-name -5405 1/imm32/rm32-is-first-inout -5406 2/imm32/r32-is-second-inout -5407 0/imm32/no-imm32 -5408 0/imm32/no-disp32 -5409 0/imm32/output-is-write-only -5410 _Primitive-xor-mem-with-reg/imm32/next -5411 _Primitive-xor-mem-with-reg: -5412 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 -5413 "xor"/imm32/name -5414 Single-int-var-on-stack/imm32/inouts -5415 Single-int-var-in-some-register/imm32/outputs -5416 "33/xor"/imm32/subx-name -5417 1/imm32/rm32-is-first-inout -5418 3/imm32/r32-is-first-output -5419 0/imm32/no-imm32 -5420 0/imm32/no-disp32 -5421 0/imm32/output-is-write-only -5422 _Primitive-xor-lit-with-reg/imm32/next -5423 _Primitive-xor-lit-with-reg: -5424 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 -5425 "xor"/imm32/name -5426 Single-lit-var/imm32/inouts -5427 Single-int-var-in-some-register/imm32/outputs -5428 "81 6/subop/xor"/imm32/subx-name -5429 3/imm32/rm32-is-first-output -5430 0/imm32/no-r32 -5431 1/imm32/imm32-is-first-inout -5432 0/imm32/no-disp32 -5433 0/imm32/output-is-write-only -5434 _Primitive-xor-lit-with-mem/imm32/next -5435 _Primitive-xor-lit-with-mem: -5436 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 -5437 "xor-with"/imm32/name -5438 Int-var-and-literal/imm32/inouts -5439 0/imm32/outputs -5440 "81 6/subop/xor"/imm32/subx-name -5441 1/imm32/rm32-is-first-inout -5442 0/imm32/no-r32 -5443 2/imm32/imm32-is-first-inout -5444 0/imm32/no-disp32 -5445 0/imm32/output-is-write-only -5446 _Primitive-copy-to-eax/imm32/next -5447 # - copy -5448 _Primitive-copy-to-eax: -5449 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 -5450 "copy"/imm32/name -5451 Single-lit-var/imm32/inouts -5452 Single-int-var-in-eax/imm32/outputs -5453 "b8/copy-to-eax"/imm32/subx-name -5454 0/imm32/no-rm32 -5455 0/imm32/no-r32 -5456 1/imm32/imm32-is-first-inout -5457 0/imm32/no-disp32 -5458 1/imm32/output-is-write-only -5459 _Primitive-copy-to-ecx/imm32/next -5460 _Primitive-copy-to-ecx: -5461 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 -5462 "copy"/imm32/name -5463 Single-lit-var/imm32/inouts -5464 Single-int-var-in-ecx/imm32/outputs -5465 "b9/copy-to-ecx"/imm32/subx-name -5466 0/imm32/no-rm32 -5467 0/imm32/no-r32 -5468 1/imm32/imm32-is-first-inout -5469 0/imm32/no-disp32 -5470 1/imm32/output-is-write-only -5471 _Primitive-copy-to-edx/imm32/next -5472 _Primitive-copy-to-edx: -5473 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 -5474 "copy"/imm32/name -5475 Single-lit-var/imm32/inouts -5476 Single-int-var-in-edx/imm32/outputs -5477 "ba/copy-to-edx"/imm32/subx-name -5478 0/imm32/no-rm32 -5479 0/imm32/no-r32 -5480 1/imm32/imm32-is-first-inout -5481 0/imm32/no-disp32 -5482 1/imm32/output-is-write-only -5483 _Primitive-copy-to-ebx/imm32/next -5484 _Primitive-copy-to-ebx: -5485 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 -5486 "copy"/imm32/name -5487 Single-lit-var/imm32/inouts -5488 Single-int-var-in-ebx/imm32/outputs -5489 "bb/copy-to-ebx"/imm32/subx-name -5490 0/imm32/no-rm32 -5491 0/imm32/no-r32 -5492 1/imm32/imm32-is-first-inout -5493 0/imm32/no-disp32 -5494 1/imm32/output-is-write-only -5495 _Primitive-copy-to-esi/imm32/next -5496 _Primitive-copy-to-esi: -5497 # var/esi <- copy lit => be/copy-to-esi lit/imm32 -5498 "copy"/imm32/name -5499 Single-lit-var/imm32/inouts -5500 Single-int-var-in-esi/imm32/outputs -5501 "be/copy-to-esi"/imm32/subx-name -5502 0/imm32/no-rm32 -5503 0/imm32/no-r32 -5504 1/imm32/imm32-is-first-inout -5505 0/imm32/no-disp32 -5506 1/imm32/output-is-write-only -5507 _Primitive-copy-to-edi/imm32/next -5508 _Primitive-copy-to-edi: -5509 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 -5510 "copy"/imm32/name -5511 Single-lit-var/imm32/inouts -5512 Single-int-var-in-edi/imm32/outputs -5513 "bf/copy-to-edi"/imm32/subx-name -5514 0/imm32/no-rm32 -5515 0/imm32/no-r32 -5516 1/imm32/imm32-is-first-inout -5517 0/imm32/no-disp32 -5518 1/imm32/output-is-write-only -5519 _Primitive-copy-reg-to-reg/imm32/next -5520 _Primitive-copy-reg-to-reg: -5521 # var1/reg <- copy var2/reg => 89/copy-to var1/rm32 var2/r32 -5522 "copy"/imm32/name -5523 Single-int-var-in-some-register/imm32/inouts -5524 Single-int-var-in-some-register/imm32/outputs -5525 "89/copy-to"/imm32/subx-name -5526 3/imm32/rm32-is-first-output -5527 1/imm32/r32-is-first-inout -5528 0/imm32/no-imm32 -5529 0/imm32/no-disp32 -5530 1/imm32/output-is-write-only -5531 _Primitive-copy-reg-to-mem/imm32/next -5532 _Primitive-copy-reg-to-mem: -5533 # copy-to var1 var2/reg => 89/copy-to var1 var2/r32 -5534 "copy-to"/imm32/name -5535 Two-args-int-stack-int-reg/imm32/inouts -5536 0/imm32/outputs -5537 "89/copy-to"/imm32/subx-name -5538 1/imm32/rm32-is-first-inout -5539 2/imm32/r32-is-second-inout -5540 0/imm32/no-imm32 -5541 0/imm32/no-disp32 -5542 1/imm32/output-is-write-only -5543 _Primitive-copy-mem-to-reg/imm32/next -5544 _Primitive-copy-mem-to-reg: -5545 # var1/reg <- copy var2 => 8b/copy-from var2/rm32 var1/r32 -5546 "copy"/imm32/name -5547 Single-int-var-on-stack/imm32/inouts -5548 Single-int-var-in-some-register/imm32/outputs -5549 "8b/copy-from"/imm32/subx-name -5550 1/imm32/rm32-is-first-inout -5551 3/imm32/r32-is-first-output -5552 0/imm32/no-imm32 -5553 0/imm32/no-disp32 -5554 1/imm32/output-is-write-only -5555 _Primitive-copy-lit-to-reg/imm32/next -5556 _Primitive-copy-lit-to-reg: -5557 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 -5558 "copy"/imm32/name -5559 Single-lit-var/imm32/inouts -5560 Single-int-var-in-some-register/imm32/outputs -5561 "c7 0/subop/copy"/imm32/subx-name -5562 3/imm32/rm32-is-first-output -5563 0/imm32/no-r32 -5564 1/imm32/imm32-is-first-inout -5565 0/imm32/no-disp32 -5566 1/imm32/output-is-write-only -5567 _Primitive-copy-lit-to-mem/imm32/next -5568 _Primitive-copy-lit-to-mem: -5569 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 -5570 "copy-to"/imm32/name -5571 Int-var-and-literal/imm32/inouts -5572 0/imm32/outputs -5573 "c7 0/subop/copy"/imm32/subx-name -5574 1/imm32/rm32-is-first-inout -5575 0/imm32/no-r32 -5576 2/imm32/imm32-is-first-inout -5577 0/imm32/no-disp32 -5578 1/imm32/output-is-write-only -5579 _Primitive-compare-mem-with-reg/imm32/next -5580 # - compare -5581 _Primitive-compare-mem-with-reg: -5582 # compare var1 var2/reg => 39/compare-> var1/rm32 var2/r32 -5583 "compare"/imm32/name -5584 Two-args-int-stack-int-reg/imm32/inouts -5585 0/imm32/outputs -5586 "39/compare->"/imm32/subx-name -5587 1/imm32/rm32-is-first-inout -5588 2/imm32/r32-is-second-inout -5589 0/imm32/no-imm32 -5590 0/imm32/no-disp32 -5591 0/imm32/output-is-write-only -5592 _Primitive-compare-reg-with-mem/imm32/next -5593 _Primitive-compare-reg-with-mem: -5594 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 -5595 "compare"/imm32/name -5596 Two-args-int-reg-int-stack/imm32/inouts -5597 0/imm32/outputs -5598 "3b/compare<-"/imm32/subx-name -5599 2/imm32/rm32-is-second-inout -5600 1/imm32/r32-is-first-inout -5601 0/imm32/no-imm32 -5602 0/imm32/no-disp32 -5603 0/imm32/output-is-write-only -5604 _Primitive-compare-eax-with-literal/imm32/next -5605 _Primitive-compare-eax-with-literal: -5606 # compare var1/eax n => 3d/compare-eax-with n/imm32 -5607 "compare"/imm32/name -5608 Two-args-int-eax-int-literal/imm32/inouts -5609 0/imm32/outputs -5610 "3d/compare-eax-with"/imm32/subx-name -5611 0/imm32/no-rm32 -5612 0/imm32/no-r32 -5613 2/imm32/imm32-is-second-inout -5614 0/imm32/no-disp32 -5615 0/imm32/output-is-write-only -5616 _Primitive-compare-regmem-with-literal/imm32/next -5617 _Primitive-compare-regmem-with-literal: -5618 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 -5619 "compare"/imm32/name -5620 Int-var-and-literal/imm32/inouts -5621 0/imm32/outputs -5622 "81 7/subop/compare"/imm32/subx-name -5623 1/imm32/rm32-is-first-inout -5624 0/imm32/no-r32 -5625 2/imm32/imm32-is-second-inout -5626 0/imm32/no-disp32 -5627 0/imm32/output-is-write-only -5628 _Primitive-multiply-reg-by-mem/imm32/next -5629 # - multiply -5630 _Primitive-multiply-reg-by-mem: -5631 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 -5632 "multiply"/imm32/name -5633 Single-int-var-on-stack/imm32/inouts -5634 Single-int-var-in-some-register/imm32/outputs -5635 "0f af/multiply"/imm32/subx-name -5636 1/imm32/rm32-is-first-inout -5637 3/imm32/r32-is-first-output -5638 0/imm32/no-imm32 -5639 0/imm32/no-disp32 -5640 0/imm32/output-is-write-only -5641 _Primitive-break-if-addr</imm32/next -5642 # - branches -5643 _Primitive-break-if-addr<: -5644 "break-if-addr<"/imm32/name -5645 0/imm32/inouts -5646 0/imm32/outputs -5647 "0f 82/jump-if-addr< break/disp32"/imm32/subx-name -5648 0/imm32/no-rm32 -5649 0/imm32/no-r32 -5650 0/imm32/no-imm32 -5651 0/imm32/no-disp32 -5652 0/imm32/no-output -5653 _Primitive-break-if-addr>=/imm32/next -5654 _Primitive-break-if-addr>=: -5655 "break-if-addr>="/imm32/name -5656 0/imm32/inouts -5657 0/imm32/outputs -5658 "0f 83/jump-if-addr>= break/disp32"/imm32/subx-name -5659 0/imm32/no-rm32 -5660 0/imm32/no-r32 -5661 0/imm32/no-imm32 -5662 0/imm32/no-disp32 -5663 0/imm32/no-output -5664 _Primitive-break-if-=/imm32/next -5665 _Primitive-break-if-=: -5666 "break-if-="/imm32/name -5667 0/imm32/inouts -5668 0/imm32/outputs -5669 "0f 84/jump-if-= break/disp32"/imm32/subx-name -5670 0/imm32/no-rm32 -5671 0/imm32/no-r32 -5672 0/imm32/no-imm32 -5673 0/imm32/no-disp32 -5674 0/imm32/no-output -5675 _Primitive-break-if-!=/imm32/next -5676 _Primitive-break-if-!=: -5677 "break-if-!="/imm32/name -5678 0/imm32/inouts -5679 0/imm32/outputs -5680 "0f 85/jump-if-!= break/disp32"/imm32/subx-name -5681 0/imm32/no-rm32 -5682 0/imm32/no-r32 -5683 0/imm32/no-imm32 -5684 0/imm32/no-disp32 -5685 0/imm32/no-output -5686 _Primitive-break-if-addr<=/imm32/next -5687 _Primitive-break-if-addr<=: -5688 "break-if-addr<="/imm32/name -5689 0/imm32/inouts +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 +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 "0f 86/jump-if-addr<= break/disp32"/imm32/subx-name -5692 0/imm32/no-rm32 +5691 "81 1/subop/or"/imm32/subx-name +5692 1/imm32/rm32-is-first-inout 5693 0/imm32/no-r32 -5694 0/imm32/no-imm32 +5694 2/imm32/imm32-is-second-inout 5695 0/imm32/no-disp32 -5696 0/imm32/no-output -5697 _Primitive-break-if-addr>/imm32/next -5698 _Primitive-break-if-addr>: -5699 "break-if-addr>"/imm32/name -5700 0/imm32/inouts -5701 0/imm32/outputs -5702 "0f 87/jump-if-addr> break/disp32"/imm32/subx-name -5703 0/imm32/no-rm32 -5704 0/imm32/no-r32 -5705 0/imm32/no-imm32 -5706 0/imm32/no-disp32 -5707 0/imm32/no-output -5708 _Primitive-break-if-</imm32/next -5709 _Primitive-break-if-<: -5710 "break-if-<"/imm32/name -5711 0/imm32/inouts -5712 0/imm32/outputs -5713 "0f 8c/jump-if-< break/disp32"/imm32/subx-name -5714 0/imm32/no-rm32 -5715 0/imm32/no-r32 -5716 0/imm32/no-imm32 -5717 0/imm32/no-disp32 -5718 0/imm32/no-output -5719 _Primitive-break-if->=/imm32/next -5720 _Primitive-break-if->=: -5721 "break-if->="/imm32/name -5722 0/imm32/inouts -5723 0/imm32/outputs -5724 "0f 8d/jump-if->= break/disp32"/imm32/subx-name -5725 0/imm32/no-rm32 -5726 0/imm32/no-r32 -5727 0/imm32/no-imm32 -5728 0/imm32/no-disp32 -5729 0/imm32/no-output -5730 _Primitive-break-if-<=/imm32/next -5731 _Primitive-break-if-<=: -5732 "break-if-<="/imm32/name -5733 0/imm32/inouts -5734 0/imm32/outputs -5735 "0f 8e/jump-if-<= break/disp32"/imm32/subx-name -5736 0/imm32/no-rm32 -5737 0/imm32/no-r32 -5738 0/imm32/no-imm32 -5739 0/imm32/no-disp32 -5740 0/imm32/no-output -5741 _Primitive-break-if->/imm32/next -5742 _Primitive-break-if->: -5743 "break-if->"/imm32/name -5744 0/imm32/inouts -5745 0/imm32/outputs -5746 "0f 8f/jump-if-> break/disp32"/imm32/subx-name -5747 0/imm32/no-rm32 -5748 0/imm32/no-r32 -5749 0/imm32/no-imm32 -5750 0/imm32/no-disp32 -5751 0/imm32/no-output -5752 _Primitive-loop-if-addr</imm32/next -5753 _Primitive-loop-if-addr<: -5754 "loop-if-addr<"/imm32/name -5755 0/imm32/inouts -5756 0/imm32/outputs -5757 "0f 82/jump-if-addr< loop/disp32"/imm32/subx-name -5758 0/imm32/no-rm32 -5759 0/imm32/no-r32 -5760 0/imm32/no-imm32 -5761 0/imm32/no-disp32 -5762 0/imm32/no-output -5763 _Primitive-loop-if-addr>=/imm32/next -5764 _Primitive-loop-if-addr>=: -5765 "loop-if-addr>="/imm32/name -5766 0/imm32/inouts -5767 0/imm32/outputs -5768 "0f 83/jump-if-addr>= loop/disp32"/imm32/subx-name -5769 0/imm32/no-rm32 -5770 0/imm32/no-r32 -5771 0/imm32/no-imm32 -5772 0/imm32/no-disp32 -5773 0/imm32/no-output -5774 _Primitive-loop-if-=/imm32/next -5775 _Primitive-loop-if-=: -5776 "loop-if-="/imm32/name -5777 0/imm32/inouts -5778 0/imm32/outputs -5779 "0f 84/jump-if-= loop/disp32"/imm32/subx-name -5780 0/imm32/no-rm32 -5781 0/imm32/no-r32 -5782 0/imm32/no-imm32 -5783 0/imm32/no-disp32 -5784 0/imm32/no-output -5785 _Primitive-loop-if-!=/imm32/next -5786 _Primitive-loop-if-!=: -5787 "loop-if-!="/imm32/name -5788 0/imm32/inouts -5789 0/imm32/outputs -5790 "0f 85/jump-if-!= loop/disp32"/imm32/subx-name -5791 0/imm32/no-rm32 -5792 0/imm32/no-r32 -5793 0/imm32/no-imm32 -5794 0/imm32/no-disp32 -5795 0/imm32/no-output -5796 _Primitive-loop-if-addr<=/imm32/next -5797 _Primitive-loop-if-addr<=: -5798 "loop-if-addr<="/imm32/name -5799 0/imm32/inouts -5800 0/imm32/outputs -5801 "0f 86/jump-if-addr<= loop/disp32"/imm32/subx-name +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 0/imm32/no-imm32 +5804 1/imm32/imm32-is-first-inout 5805 0/imm32/no-disp32 -5806 0/imm32/no-output -5807 _Primitive-loop-if-addr>/imm32/next -5808 _Primitive-loop-if-addr>: -5809 "loop-if-addr>"/imm32/name -5810 0/imm32/inouts -5811 0/imm32/outputs -5812 "0f 87/jump-if-addr> loop/disp32"/imm32/subx-name -5813 0/imm32/no-rm32 -5814 0/imm32/no-r32 -5815 0/imm32/no-imm32 -5816 0/imm32/no-disp32 -5817 0/imm32/no-output -5818 _Primitive-loop-if-</imm32/next -5819 _Primitive-loop-if-<: -5820 "loop-if-<"/imm32/name -5821 0/imm32/inouts -5822 0/imm32/outputs -5823 "0f 8c/jump-if-< loop/disp32"/imm32/subx-name -5824 0/imm32/no-rm32 -5825 0/imm32/no-r32 -5826 0/imm32/no-imm32 -5827 0/imm32/no-disp32 -5828 0/imm32/no-output -5829 _Primitive-loop-if->=/imm32/next -5830 _Primitive-loop-if->=: -5831 "loop-if->="/imm32/name -5832 0/imm32/inouts -5833 0/imm32/outputs -5834 "0f 8d/jump-if->= loop/disp32"/imm32/subx-name -5835 0/imm32/no-rm32 -5836 0/imm32/no-r32 -5837 0/imm32/no-imm32 -5838 0/imm32/no-disp32 -5839 0/imm32/no-output -5840 _Primitive-loop-if-<=/imm32/next -5841 _Primitive-loop-if-<=: -5842 "loop-if-<="/imm32/name -5843 0/imm32/inouts -5844 0/imm32/outputs -5845 "0f 8e/jump-if-<= loop/disp32"/imm32/subx-name -5846 0/imm32/no-rm32 -5847 0/imm32/no-r32 -5848 0/imm32/no-imm32 -5849 0/imm32/no-disp32 -5850 0/imm32/no-output -5851 _Primitive-loop-if->/imm32/next -5852 _Primitive-loop-if->: -5853 "loop-if->"/imm32/name -5854 0/imm32/inouts -5855 0/imm32/outputs -5856 "0f 8f/jump-if-> loop/disp32"/imm32/subx-name -5857 0/imm32/no-rm32 -5858 0/imm32/no-r32 -5859 0/imm32/no-imm32 -5860 0/imm32/no-disp32 -5861 0/imm32/no-output -5862 _Primitive-loop/imm32/next # we probably don't need an unconditional break -5863 _Primitive-loop: -5864 "loop"/imm32/name -5865 0/imm32/inouts -5866 0/imm32/outputs -5867 "e9/jump loop/disp32"/imm32/subx-name -5868 0/imm32/no-rm32 -5869 0/imm32/no-r32 -5870 0/imm32/no-imm32 -5871 0/imm32/no-disp32 -5872 0/imm32/no-output -5873 _Primitive-break-if-addr<-named/imm32/next -5874 # - branches to named blocks -5875 _Primitive-break-if-addr<-named: -5876 "break-if-addr<"/imm32/name -5877 Single-lit-var/imm32/inouts -5878 0/imm32/outputs -5879 "0f 82/jump-if-addr<"/imm32/subx-name -5880 0/imm32/no-rm32 -5881 0/imm32/no-r32 -5882 0/imm32/no-imm32 -5883 1/imm32/disp32-is-first-inout -5884 0/imm32/no-output -5885 _Primitive-break-if-addr>=-named/imm32/next -5886 _Primitive-break-if-addr>=-named: -5887 "break-if-addr>="/imm32/name -5888 Single-lit-var/imm32/inouts -5889 0/imm32/outputs -5890 "0f 83/jump-if-addr>="/imm32/subx-name -5891 0/imm32/no-rm32 -5892 0/imm32/no-r32 -5893 0/imm32/no-imm32 -5894 1/imm32/disp32-is-first-inout -5895 0/imm32/no-output -5896 _Primitive-break-if-=-named/imm32/next -5897 _Primitive-break-if-=-named: -5898 "break-if-="/imm32/name -5899 Single-lit-var/imm32/inouts -5900 0/imm32/outputs -5901 "0f 84/jump-if-="/imm32/subx-name -5902 0/imm32/no-rm32 -5903 0/imm32/no-r32 -5904 0/imm32/no-imm32 -5905 1/imm32/disp32-is-first-inout -5906 0/imm32/no-output -5907 _Primitive-break-if-!=-named/imm32/next -5908 _Primitive-break-if-!=-named: -5909 "break-if-!="/imm32/name -5910 Single-lit-var/imm32/inouts -5911 0/imm32/outputs -5912 "0f 85/jump-if-!="/imm32/subx-name -5913 0/imm32/no-rm32 -5914 0/imm32/no-r32 -5915 0/imm32/no-imm32 -5916 1/imm32/disp32-is-first-inout -5917 0/imm32/no-output -5918 _Primitive-break-if-addr<=-named/imm32/next -5919 _Primitive-break-if-addr<=-named: -5920 "break-if-addr<="/imm32/name -5921 Single-lit-var/imm32/inouts -5922 0/imm32/outputs -5923 "0f 86/jump-if-addr<="/imm32/subx-name -5924 0/imm32/no-rm32 -5925 0/imm32/no-r32 -5926 0/imm32/no-imm32 -5927 1/imm32/disp32-is-first-inout -5928 0/imm32/no-output -5929 _Primitive-break-if-addr>-named/imm32/next -5930 _Primitive-break-if-addr>-named: -5931 "break-if-addr>"/imm32/name -5932 Single-lit-var/imm32/inouts +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 "0f 87/jump-if-addr>"/imm32/subx-name +5934 "3d/compare-eax-with"/imm32/subx-name 5935 0/imm32/no-rm32 5936 0/imm32/no-r32 -5937 0/imm32/no-imm32 -5938 1/imm32/disp32-is-first-inout -5939 0/imm32/no-output -5940 _Primitive-break-if-<-named/imm32/next -5941 _Primitive-break-if-<-named: -5942 "break-if-<"/imm32/name -5943 Single-lit-var/imm32/inouts -5944 0/imm32/outputs -5945 "0f 8c/jump-if-<"/imm32/subx-name -5946 0/imm32/no-rm32 -5947 0/imm32/no-r32 -5948 0/imm32/no-imm32 -5949 1/imm32/disp32-is-first-inout -5950 0/imm32/no-output -5951 _Primitive-break-if->=-named/imm32/next -5952 _Primitive-break-if->=-named: -5953 "break-if->="/imm32/name -5954 Single-lit-var/imm32/inouts -5955 0/imm32/outputs -5956 "0f 8d/jump-if->="/imm32/subx-name -5957 0/imm32/no-rm32 -5958 0/imm32/no-r32 -5959 0/imm32/no-imm32 -5960 1/imm32/disp32-is-first-inout -5961 0/imm32/no-output -5962 _Primitive-break-if-<=-named/imm32/next -5963 _Primitive-break-if-<=-named: -5964 "break-if-<="/imm32/name -5965 Single-lit-var/imm32/inouts -5966 0/imm32/outputs -5967 "0f 8e/jump-if-<="/imm32/subx-name -5968 0/imm32/no-rm32 -5969 0/imm32/no-r32 -5970 0/imm32/no-imm32 -5971 1/imm32/disp32-is-first-inout -5972 0/imm32/no-output -5973 _Primitive-break-if->-named/imm32/next -5974 _Primitive-break-if->-named: -5975 "break-if->"/imm32/name -5976 Single-lit-var/imm32/inouts -5977 0/imm32/outputs -5978 "0f 8f/jump-if->"/imm32/subx-name -5979 0/imm32/no-rm32 -5980 0/imm32/no-r32 -5981 0/imm32/no-imm32 -5982 1/imm32/disp32-is-first-inout -5983 0/imm32/no-output -5984 _Primitive-loop-if-addr<-named/imm32/next -5985 _Primitive-loop-if-addr<-named: -5986 "loop-if-addr<"/imm32/name -5987 Single-lit-var/imm32/inouts -5988 0/imm32/outputs -5989 "0f 82/jump-if-addr<"/imm32/subx-name -5990 0/imm32/no-rm32 -5991 0/imm32/no-r32 -5992 0/imm32/no-imm32 -5993 1/imm32/disp32-is-first-inout -5994 0/imm32/no-output -5995 _Primitive-loop-if-addr>=-named/imm32/next -5996 _Primitive-loop-if-addr>=-named: -5997 "loop-if-addr>="/imm32/name -5998 Single-lit-var/imm32/inouts -5999 0/imm32/outputs -6000 "0f 83/jump-if-addr>="/imm32/subx-name -6001 0/imm32/no-rm32 -6002 0/imm32/no-r32 -6003 0/imm32/no-imm32 -6004 1/imm32/disp32-is-first-inout -6005 0/imm32/no-output -6006 _Primitive-loop-if-=-named/imm32/next -6007 _Primitive-loop-if-=-named: -6008 "loop-if-="/imm32/name -6009 Single-lit-var/imm32/inouts -6010 0/imm32/outputs -6011 "0f 84/jump-if-="/imm32/subx-name -6012 0/imm32/no-rm32 -6013 0/imm32/no-r32 -6014 0/imm32/no-imm32 -6015 1/imm32/disp32-is-first-inout -6016 0/imm32/no-output -6017 _Primitive-loop-if-!=-named/imm32/next -6018 _Primitive-loop-if-!=-named: -6019 "loop-if-!="/imm32/name -6020 Single-lit-var/imm32/inouts -6021 0/imm32/outputs -6022 "0f 85/jump-if-!="/imm32/subx-name -6023 0/imm32/no-rm32 -6024 0/imm32/no-r32 -6025 0/imm32/no-imm32 -6026 1/imm32/disp32-is-first-inout -6027 0/imm32/no-output -6028 _Primitive-loop-if-addr<=-named/imm32/next -6029 _Primitive-loop-if-addr<=-named: -6030 "loop-if-addr<="/imm32/name -6031 Single-lit-var/imm32/inouts -6032 0/imm32/outputs -6033 "0f 86/jump-if-addr<="/imm32/subx-name -6034 0/imm32/no-rm32 -6035 0/imm32/no-r32 -6036 0/imm32/no-imm32 -6037 1/imm32/disp32-is-first-inout -6038 0/imm32/no-output -6039 _Primitive-loop-if-addr>-named/imm32/next -6040 _Primitive-loop-if-addr>-named: -6041 "loop-if-addr>"/imm32/name -6042 Single-lit-var/imm32/inouts -6043 0/imm32/outputs -6044 "0f 87/jump-if-addr>"/imm32/subx-name -6045 0/imm32/no-rm32 -6046 0/imm32/no-r32 -6047 0/imm32/no-imm32 -6048 1/imm32/disp32-is-first-inout -6049 0/imm32/no-output -6050 _Primitive-loop-if-<-named/imm32/next -6051 _Primitive-loop-if-<-named: -6052 "loop-if-<"/imm32/name -6053 Single-lit-var/imm32/inouts -6054 0/imm32/outputs -6055 "0f 8c/jump-if-<"/imm32/subx-name -6056 0/imm32/no-rm32 -6057 0/imm32/no-r32 -6058 0/imm32/no-imm32 -6059 1/imm32/disp32-is-first-inout -6060 0/imm32/no-output -6061 _Primitive-loop-if->=-named/imm32/next -6062 _Primitive-loop-if->=-named: -6063 "loop-if->="/imm32/name -6064 Single-lit-var/imm32/inouts -6065 0/imm32/outputs -6066 "0f 8d/jump-if->="/imm32/subx-name -6067 0/imm32/no-rm32 -6068 0/imm32/no-r32 -6069 0/imm32/no-imm32 -6070 1/imm32/disp32-is-first-inout -6071 0/imm32/no-output -6072 _Primitive-loop-if-<=-named/imm32/next -6073 _Primitive-loop-if-<=-named: -6074 "loop-if-<="/imm32/name -6075 Single-lit-var/imm32/inouts -6076 0/imm32/outputs -6077 "0f 8e/jump-if-<="/imm32/subx-name -6078 0/imm32/no-rm32 -6079 0/imm32/no-r32 -6080 0/imm32/no-imm32 -6081 1/imm32/disp32-is-first-inout -6082 0/imm32/no-output -6083 _Primitive-loop-if->-named/imm32/next -6084 _Primitive-loop-if->-named: -6085 "loop-if->"/imm32/name -6086 Single-lit-var/imm32/inouts -6087 0/imm32/outputs -6088 "0f 8f/jump-if->"/imm32/subx-name -6089 0/imm32/no-rm32 -6090 0/imm32/no-r32 -6091 0/imm32/no-imm32 -6092 1/imm32/disp32-is-first-inout -6093 0/imm32/no-output -6094 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break -6095 _Primitive-loop-named: -6096 "loop"/imm32/name -6097 Single-lit-var/imm32/inouts -6098 0/imm32/outputs -6099 "e9/jump"/imm32/subx-name -6100 0/imm32/no-rm32 -6101 0/imm32/no-r32 -6102 0/imm32/no-imm32 -6103 1/imm32/disp32-is-first-inout -6104 0/imm32/no-output -6105 0/imm32/next -6106 -6107 Single-int-var-on-stack: -6108 Int-var-on-stack/imm32 -6109 0/imm32/next -6110 -6111 Int-var-on-stack: -6112 "arg1"/imm32/name -6113 Type-int/imm32 -6114 1/imm32/some-block-depth -6115 1/imm32/some-stack-offset -6116 0/imm32/no-register -6117 -6118 Two-args-int-stack-int-reg: -6119 Int-var-on-stack/imm32 -6120 Single-int-var-in-some-register/imm32/next -6121 -6122 Two-args-int-reg-int-stack: -6123 Int-var-in-some-register/imm32 -6124 Single-int-var-on-stack/imm32/next -6125 -6126 Two-args-int-eax-int-literal: -6127 Int-var-in-eax/imm32 -6128 Single-lit-var/imm32/next -6129 -6130 Int-var-and-literal: -6131 Int-var-on-stack/imm32 -6132 Single-lit-var/imm32/next -6133 -6134 Single-int-var-in-some-register: -6135 Int-var-in-some-register/imm32 -6136 0/imm32/next -6137 -6138 Int-var-in-some-register: -6139 "arg1"/imm32/name -6140 Type-int/imm32 -6141 1/imm32/some-block-depth -6142 0/imm32/no-stack-offset -6143 "*"/imm32/register -6144 -6145 Single-int-var-in-eax: -6146 Int-var-in-eax/imm32 -6147 0/imm32/next -6148 -6149 Int-var-in-eax: -6150 "arg1"/imm32/name -6151 Type-int/imm32 -6152 1/imm32/some-block-depth -6153 0/imm32/no-stack-offset -6154 "eax"/imm32/register -6155 -6156 Single-int-var-in-ecx: -6157 Int-var-in-ecx/imm32 -6158 0/imm32/next -6159 -6160 Int-var-in-ecx: -6161 "arg1"/imm32/name -6162 Type-int/imm32 -6163 1/imm32/some-block-depth -6164 0/imm32/no-stack-offset -6165 "ecx"/imm32/register -6166 -6167 Single-int-var-in-edx: -6168 Int-var-in-edx/imm32 -6169 0/imm32/next -6170 -6171 Int-var-in-edx: -6172 "arg1"/imm32/name -6173 Type-int/imm32 -6174 1/imm32/some-block-depth -6175 0/imm32/no-stack-offset -6176 "edx"/imm32/register -6177 -6178 Single-int-var-in-ebx: -6179 Int-var-in-ebx/imm32 -6180 0/imm32/next -6181 -6182 Int-var-in-ebx: -6183 "arg1"/imm32/name -6184 Type-int/imm32 -6185 1/imm32/some-block-depth -6186 0/imm32/no-stack-offset -6187 "ebx"/imm32/register -6188 -6189 Single-int-var-in-esi: -6190 Int-var-in-esi/imm32 -6191 0/imm32/next -6192 -6193 Int-var-in-esi: -6194 "arg1"/imm32/name -6195 Type-int/imm32 -6196 1/imm32/some-block-depth -6197 0/imm32/no-stack-offset -6198 "esi"/imm32/register -6199 -6200 Single-int-var-in-edi: -6201 Int-var-in-edi/imm32 -6202 0/imm32/next -6203 -6204 Int-var-in-edi: -6205 "arg1"/imm32/name -6206 Type-int/imm32 -6207 1/imm32/some-block-depth -6208 0/imm32/no-stack-offset -6209 "edi"/imm32/register -6210 -6211 Single-lit-var: -6212 Lit-var/imm32 -6213 0/imm32/next -6214 -6215 Lit-var: -6216 "literal"/imm32/name -6217 Type-literal/imm32 -6218 1/imm32/some-block-depth -6219 0/imm32/no-stack-offset -6220 0/imm32/no-register -6221 -6222 Type-int: -6223 1/imm32/left/int -6224 0/imm32/right/null -6225 -6226 Type-literal: -6227 0/imm32/left/literal -6228 0/imm32/right/null -6229 -6230 == code -6231 emit-subx-primitive: # out: (addr buffered-file), stmt: (handle statement), primitive: (handle function) -6232 # . prologue -6233 55/push-ebp -6234 89/<- %ebp 4/r32/esp -6235 # . save registers -6236 50/push-eax -6237 51/push-ecx -6238 # ecx = primitive -6239 8b/-> *(ebp+0x10) 1/r32/ecx -6240 # emit primitive name -6241 (emit-indent *(ebp+8) *Curr-block-depth) -6242 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name -6243 # emit rm32 if necessary -6244 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt -6245 # emit r32 if necessary -6246 (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt -6247 # emit imm32 if necessary -6248 (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt -6249 # emit disp32 if necessary -6250 (emit-subx-disp32 *(ebp+8) *(ecx+0x1c) *(ebp+0xc)) # out, Primitive-subx-disp32, stmt -6251 (write-buffered *(ebp+8) Newline) -6252 $emit-subx-primitive:end: -6253 # . restore registers -6254 59/pop-to-ecx -6255 58/pop-to-eax -6256 # . epilogue -6257 89/<- %esp 5/r32/ebp -6258 5d/pop-to-ebp -6259 c3/return -6260 -6261 emit-subx-rm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6262 # . prologue -6263 55/push-ebp -6264 89/<- %ebp 4/r32/esp -6265 # . save registers -6266 50/push-eax -6267 # if (l == 0) return -6268 81 7/subop/compare *(ebp+0xc) 0/imm32 -6269 74/jump-if-= $emit-subx-rm32:end/disp8 -6270 # -6271 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -6272 (emit-subx-var-as-rm32 *(ebp+8) %eax) # out, var -6273 $emit-subx-rm32:end: -6274 # . restore registers -6275 58/pop-to-eax -6276 # . epilogue -6277 89/<- %esp 5/r32/ebp -6278 5d/pop-to-ebp -6279 c3/return -6280 -6281 get-stmt-operand-from-arg-location: # stmt: (handle statement), l: arg-location -> var/eax: (handle variable) -6282 # . prologue -6283 55/push-ebp -6284 89/<- %ebp 4/r32/esp -6285 # . save registers -6286 51/push-ecx -6287 # eax = l -6288 8b/-> *(ebp+0xc) 0/r32/eax -6289 # ecx = stmt -6290 8b/-> *(ebp+8) 1/r32/ecx -6291 # if (l == 1) return stmt->inouts->var -6292 { -6293 3d/compare-eax-and 1/imm32 -6294 75/jump-if-!= break/disp8 -6295 $get-stmt-operand-from-arg-location:1: -6296 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts -6297 8b/-> *eax 0/r32/eax # Operand-var -6298 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -6299 } -6300 # if (l == 2) return stmt->inouts->next->var -6301 { -6302 3d/compare-eax-and 2/imm32 -6303 75/jump-if-!= break/disp8 -6304 $get-stmt-operand-from-arg-location:2: -6305 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts -6306 8b/-> *(eax+4) 0/r32/eax # Operand-next -6307 8b/-> *eax 0/r32/eax # Operand-var -6308 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -6309 } -6310 # if (l == 3) return stmt->outputs -6311 { -6312 3d/compare-eax-and 3/imm32 -6313 75/jump-if-!= break/disp8 -6314 $get-stmt-operand-from-arg-location:3: -6315 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs -6316 8b/-> *eax 0/r32/eax # Operand-var -6317 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -6318 } -6319 # abort -6320 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 -6321 $get-stmt-operand-from-arg-location:end: -6322 # . restore registers -6323 59/pop-to-ecx -6324 # . epilogue -6325 89/<- %esp 5/r32/ebp -6326 5d/pop-to-ebp -6327 c3/return -6328 -6329 $get-stmt-operand-from-arg-location:abort: -6330 # error("invalid arg-location " eax) -6331 (write-buffered Stderr "invalid arg-location ") -6332 (print-int32-buffered Stderr %eax) -6333 (write-buffered Stderr Newline) -6334 (flush Stderr) -6335 # . syscall(exit, 1) -6336 bb/copy-to-ebx 1/imm32 -6337 b8/copy-to-eax 1/imm32/exit -6338 cd/syscall 0x80/imm8 -6339 # never gets here -6340 -6341 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6342 # . prologue -6343 55/push-ebp -6344 89/<- %ebp 4/r32/esp -6345 # . save registers -6346 50/push-eax -6347 51/push-ecx -6348 # if (location == 0) return -6349 81 7/subop/compare *(ebp+0xc) 0/imm32 -6350 0f 84/jump-if-= $emit-subx-r32:end/disp32 -6351 # -6352 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -6353 (maybe-get Registers *(eax+0x10) 8) # Var-register => eax: (addr register-index) -6354 (write-buffered *(ebp+8) Space) -6355 (print-int32-buffered *(ebp+8) *eax) -6356 (write-buffered *(ebp+8) "/r32") -6357 $emit-subx-r32:end: -6358 # . restore registers -6359 59/pop-to-ecx -6360 58/pop-to-eax -6361 # . epilogue -6362 89/<- %esp 5/r32/ebp -6363 5d/pop-to-ebp -6364 c3/return -6365 -6366 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6367 # . prologue -6368 55/push-ebp -6369 89/<- %ebp 4/r32/esp -6370 # . save registers -6371 50/push-eax -6372 51/push-ecx -6373 # if (location == 0) return -6374 81 7/subop/compare *(ebp+0xc) 0/imm32 -6375 74/jump-if-= $emit-subx-imm32:end/disp8 -6376 # -6377 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -6378 (write-buffered *(ebp+8) Space) -6379 (write-buffered *(ebp+8) *eax) # Var-name -6380 (write-buffered *(ebp+8) "/imm32") -6381 $emit-subx-imm32:end: -6382 # . restore registers -6383 59/pop-to-ecx -6384 58/pop-to-eax -6385 # . epilogue -6386 89/<- %esp 5/r32/ebp -6387 5d/pop-to-ebp -6388 c3/return -6389 -6390 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6391 # . prologue -6392 55/push-ebp -6393 89/<- %ebp 4/r32/esp -6394 # . save registers -6395 50/push-eax -6396 51/push-ecx -6397 # if (location == 0) return -6398 81 7/subop/compare *(ebp+0xc) 0/imm32 -6399 0f 84/jump-if-= $emit-subx-disp32:end/disp32 -6400 # -6401 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -6402 (write-buffered *(ebp+8) Space) -6403 (write-buffered *(ebp+8) *eax) # Var-name -6404 # hack: if instruction operation starts with "break", emit ":break" -6405 # var name/ecx: (addr array byte) = stmt->operation -6406 8b/-> *(ebp+0x10) 0/r32/eax -6407 8b/-> *(eax+4) 1/r32/ecx -6408 { -6409 (string-starts-with? %ecx "break") # => eax -6410 3d/compare-eax-and 0/imm32 -6411 74/jump-if-= break/disp8 -6412 (write-buffered *(ebp+8) ":break") -6413 } -6414 # hack: if instruction operation starts with "loop", emit ":loop" -6415 { -6416 (string-starts-with? %ecx "loop") # => eax -6417 3d/compare-eax-and 0/imm32 -6418 74/jump-if-= break/disp8 -6419 (write-buffered *(ebp+8) ":loop") -6420 } -6421 (write-buffered *(ebp+8) "/disp32") -6422 $emit-subx-disp32:end: -6423 # . restore registers -6424 59/pop-to-ecx -6425 58/pop-to-eax -6426 # . epilogue -6427 89/<- %esp 5/r32/ebp -6428 5d/pop-to-ebp -6429 c3/return +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 +5945 0/imm32/outputs +5946 "81 7/subop/compare"/imm32/subx-name +5947 1/imm32/rm32-is-first-inout +5948 0/imm32/no-r32 +5949 2/imm32/imm32-is-second-inout +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 emit-subx-call: # out: (addr buffered-file), stmt: (handle statement), callee: (handle function) -6432 # . prologue -6433 55/push-ebp -6434 89/<- %ebp 4/r32/esp -6435 # . save registers -6436 50/push-eax -6437 51/push-ecx -6438 # -6439 (emit-indent *(ebp+8) *Curr-block-depth) -6440 (write-buffered *(ebp+8) "(") -6441 # - emit function name -6442 8b/-> *(ebp+0x10) 1/r32/ecx -6443 (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name -6444 # - emit arguments -6445 # var curr/ecx: (handle list var) = stmt->inouts -6446 8b/-> *(ebp+0xc) 1/r32/ecx -6447 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts -6448 { -6449 # if (curr == null) break -6450 81 7/subop/compare %ecx 0/imm32 -6451 74/jump-if-= break/disp8 -6452 # -6453 (emit-subx-call-operand *(ebp+8) *ecx) -6454 # curr = curr->next -6455 8b/-> *(ecx+4) 1/r32/ecx -6456 eb/jump loop/disp8 -6457 } -6458 # -6459 (write-buffered *(ebp+8) ")\n") -6460 $emit-subx-call:end: -6461 # . restore registers -6462 59/pop-to-ecx -6463 58/pop-to-eax -6464 # . epilogue -6465 89/<- %esp 5/r32/ebp -6466 5d/pop-to-ebp -6467 c3/return +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 emit-subx-call-operand: # out: (addr buffered-file), operand: (handle variable) -6470 # shares code with emit-subx-var-as-rm32 -6471 # . prologue -6472 55/push-ebp -6473 89/<- %ebp 4/r32/esp -6474 # . save registers -6475 50/push-eax -6476 # eax = operand -6477 8b/-> *(ebp+0xc) 0/r32/eax -6478 # if (operand->register) emit "%__" -6479 { -6480 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -6481 74/jump-if-= break/disp8 -6482 $emit-subx-call-operand:register: -6483 (write-buffered *(ebp+8) " %") -6484 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register -6485 e9/jump $emit-subx-call-operand:end/disp32 -6486 } -6487 # else if (operand->stack-offset) emit "*(ebp+__)" -6488 { -6489 81 7/subop/compare *(eax+0xc) 0/imm32 # Var-stack-offset -6490 74/jump-if-= break/disp8 -6491 $emit-subx-call-operand:stack: -6492 (write-buffered *(ebp+8) Space) -6493 (write-buffered *(ebp+8) "*(ebp+") -6494 8b/-> *(ebp+0xc) 0/r32/eax -6495 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-stack-offset -6496 (write-buffered *(ebp+8) ")") -6497 e9/jump $emit-subx-call-operand:end/disp32 -6498 } -6499 # else if (operand->type == literal) emit "__" -6500 { -6501 50/push-eax -6502 8b/-> *(eax+4) 0/r32/eax # Var-type -6503 81 7/subop/compare *eax 0/imm32 # Tree-left -6504 58/pop-to-eax -6505 75/jump-if-!= break/disp8 -6506 $emit-subx-call-operand:literal: -6507 (write-buffered *(ebp+8) Space) -6508 (write-buffered *(ebp+8) *eax) -6509 } -6510 $emit-subx-call-operand:end: -6511 # . restore registers -6512 58/pop-to-eax -6513 # . epilogue -6514 89/<- %esp 5/r32/ebp -6515 5d/pop-to-ebp -6516 c3/return -6517 -6518 emit-subx-var-as-rm32: # out: (addr buffered-file), operand: (handle variable) -6519 # . prologue -6520 55/push-ebp -6521 89/<- %ebp 4/r32/esp -6522 # . save registers -6523 50/push-eax -6524 # eax = operand -6525 8b/-> *(ebp+0xc) 0/r32/eax -6526 # if (operand->register) emit "%__" -6527 { -6528 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -6529 74/jump-if-= break/disp8 -6530 $emit-subx-var-as-rm32:register: -6531 (write-buffered *(ebp+8) " %") -6532 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register -6533 } -6534 # else if (operand->stack-offset) emit "*(ebp+__)" -6535 { -6536 81 7/subop/compare *(eax+0xc) 0/imm32 # Var-stack-offset -6537 74/jump-if-= break/disp8 -6538 $emit-subx-var-as-rm32:stack: -6539 (write-buffered *(ebp+8) Space) -6540 (write-buffered *(ebp+8) "*(ebp+") -6541 8b/-> *(ebp+0xc) 0/r32/eax -6542 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-stack-offset -6543 (write-buffered *(ebp+8) ")") -6544 } -6545 $emit-subx-var-as-rm32:end: -6546 # . restore registers -6547 58/pop-to-eax -6548 # . epilogue -6549 89/<- %esp 5/r32/ebp -6550 5d/pop-to-ebp -6551 c3/return -6552 -6553 find-matching-function: # functions: (addr function), stmt: (handle statement) -> result/eax: (handle function) -6554 # . prologue -6555 55/push-ebp -6556 89/<- %ebp 4/r32/esp -6557 # . save registers -6558 51/push-ecx -6559 # var curr/ecx: (handle function) = functions -6560 8b/-> *(ebp+8) 1/r32/ecx -6561 { -6562 # if (curr == null) break -6563 81 7/subop/compare %ecx 0/imm32 -6564 74/jump-if-= break/disp8 -6565 # if match(stmt, curr) return curr -6566 { -6567 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax -6568 3d/compare-eax-and 0/imm32 -6569 74/jump-if-= break/disp8 -6570 89/<- %eax 1/r32/ecx -6571 eb/jump $find-matching-function:end/disp8 -6572 } -6573 # curr = curr->next -6574 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next -6575 eb/jump loop/disp8 -6576 } -6577 # return null -6578 b8/copy-to-eax 0/imm32 -6579 $find-matching-function:end: -6580 # . restore registers -6581 59/pop-to-ecx -6582 # . epilogue -6583 89/<- %esp 5/r32/ebp -6584 5d/pop-to-ebp -6585 c3/return -6586 -6587 find-matching-primitive: # primitives: (handle primitive), stmt: (handle statement) -> result/eax: (handle primitive) -6588 # . prologue -6589 55/push-ebp -6590 89/<- %ebp 4/r32/esp -6591 # . save registers -6592 51/push-ecx -6593 # var curr/ecx: (handle primitive) = primitives -6594 8b/-> *(ebp+8) 1/r32/ecx -6595 { -6596 $find-matching-primitive:loop: -6597 # if (curr == null) break -6598 81 7/subop/compare %ecx 0/imm32 -6599 0f 84/jump-if-= break/disp32 -6600 #? (write-buffered Stderr "prim: ") -6601 #? (write-buffered Stderr *ecx) # Primitive-name -6602 #? (write-buffered Stderr " => ") -6603 #? (write-buffered Stderr *(ecx+0xc)) # Primitive-subx-name -6604 #? (write-buffered Stderr Newline) -6605 #? (flush Stderr) -6606 # if match(curr, stmt) return curr -6607 { -6608 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax -6609 3d/compare-eax-and 0/imm32 -6610 74/jump-if-= break/disp8 -6611 89/<- %eax 1/r32/ecx -6612 eb/jump $find-matching-primitive:end/disp8 -6613 } -6614 $find-matching-primitive:next-primitive: -6615 # curr = curr->next -6616 8b/-> *(ecx+0x24) 1/r32/ecx # Primitive-next -6617 e9/jump loop/disp32 -6618 } -6619 # return null -6620 b8/copy-to-eax 0/imm32 -6621 $find-matching-primitive:end: -6622 # . restore registers -6623 59/pop-to-ecx -6624 # . epilogue -6625 89/<- %esp 5/r32/ebp -6626 5d/pop-to-ebp -6627 c3/return -6628 -6629 mu-stmt-matches-function?: # stmt: (handle statement), function: (handle function) => result/eax: boolean -6630 # . prologue -6631 55/push-ebp -6632 89/<- %ebp 4/r32/esp -6633 # . save registers -6634 51/push-ecx -6635 # return function->name == stmt->operation -6636 8b/-> *(ebp+8) 1/r32/ecx -6637 8b/-> *(ebp+0xc) 0/r32/eax -6638 (string-equal? *(ecx+4) *eax) # Stmt1-operation, Function-name => eax -6639 $mu-stmt-matches-function?:end: -6640 # . restore registers -6641 59/pop-to-ecx -6642 # . epilogue -6643 89/<- %esp 5/r32/ebp -6644 5d/pop-to-ebp -6645 c3/return -6646 -6647 mu-stmt-matches-primitive?: # stmt: (handle statement), primitive: (handle primitive) => result/eax: boolean -6648 # A mu stmt matches a primitive if the name matches, all the inout vars -6649 # match, and all the output vars match. -6650 # Vars match if types match and registers match. -6651 # In addition, a stmt output matches a primitive's output if types match -6652 # and the primitive has a wildcard register. -6653 # . prologue -6654 55/push-ebp -6655 89/<- %ebp 4/r32/esp -6656 # . save registers -6657 51/push-ecx -6658 52/push-edx -6659 53/push-ebx -6660 56/push-esi -6661 57/push-edi -6662 # ecx = stmt -6663 8b/-> *(ebp+8) 1/r32/ecx -6664 # edx = primitive -6665 8b/-> *(ebp+0xc) 2/r32/edx -6666 { -6667 $mu-stmt-matches-primitive?:check-name: -6668 # if (primitive->name != stmt->operation) return false -6669 (string-equal? *(ecx+4) *edx) # Stmt1-operation, Primitive-name => eax -6670 3d/compare-eax-and 0/imm32 -6671 75/jump-if-!= break/disp8 -6672 b8/copy-to-eax 0/imm32 -6673 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6674 } -6675 $mu-stmt-matches-primitive?:check-inouts: -6676 # for (curr/esi in stmt->inouts, curr2/edi in primitive->inouts) -6677 8b/-> *(ecx+8) 6/r32/esi # Stmt1-inouts -6678 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts -6679 { -6680 # if (curr == 0 && curr2 == 0) move on to check outputs -6681 { -6682 81 7/subop/compare %esi 0/imm32 -6683 75/jump-if-!= break/disp8 -6684 $mu-stmt-matches-primitive?:stmt-inout-is-null: -6685 { -6686 81 7/subop/compare %edi 0/imm32 -6687 75/jump-if-!= break/disp8 -6688 # -6689 e9/jump $mu-stmt-matches-primitive?:check-outputs/disp32 -6690 } -6691 # return false -6692 b8/copy-to-eax 0/imm32/false -6693 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6694 } -6695 # if (curr2 == 0) return false -6696 { -6697 81 7/subop/compare %edi 0/imm32 -6698 75/jump-if-!= break/disp8 -6699 $mu-stmt-matches-primitive?:prim-inout-is-null: -6700 b8/copy-to-eax 0/imm32/false -6701 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6702 } -6703 # if (curr != curr2) return false -6704 { -6705 (operand-matches-primitive? *esi *edi) # => eax -6706 3d/compare-eax-and 0/imm32 -6707 75/jump-if-!= break/disp8 -6708 b8/copy-to-eax 0/imm32/false -6709 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6710 } -6711 # curr=curr->next -6712 8b/-> *(esi+4) 6/r32/esi # Operand-next -6713 # curr2=curr2->next -6714 8b/-> *(edi+4) 7/r32/edi # Operand-next -6715 eb/jump loop/disp8 -6716 } -6717 $mu-stmt-matches-primitive?:check-outputs: -6718 # for (curr/esi in stmt->outputs, curr2/edi in primitive->outputs) -6719 8b/-> *(ecx+0xc) 6/r32/esi # Stmt1-outputs -6720 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs -6721 { -6722 # if (curr == 0) return (curr2 == 0) -6723 { -6724 $mu-stmt-matches-primitive?:check-output: -6725 81 7/subop/compare %esi 0/imm32 -6726 75/jump-if-!= break/disp8 -6727 { -6728 81 7/subop/compare %edi 0/imm32 -6729 75/jump-if-!= break/disp8 -6730 # return true -6731 b8/copy-to-eax 1/imm32 -6732 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6733 } -6734 # return false -6735 b8/copy-to-eax 0/imm32 -6736 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6737 } -6738 # if (curr2 == 0) return false -6739 { -6740 81 7/subop/compare %edi 0/imm32 -6741 75/jump-if-!= break/disp8 -6742 b8/copy-to-eax 0/imm32 -6743 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6744 } -6745 # if (curr != curr2) return false -6746 { -6747 (operand-matches-primitive? *esi *edi) # List-value List-value => eax -6748 3d/compare-eax-and 0/imm32 -6749 75/jump-if-!= break/disp8 -6750 b8/copy-to-eax 0/imm32 -6751 e9/jump $mu-stmt-matches-primitive?:end/disp32 -6752 } -6753 # curr=curr->next -6754 8b/-> *(esi+4) 6/r32/esi # Operand-next -6755 # curr2=curr2->next -6756 8b/-> *(edi+4) 7/r32/edi # Operand-next -6757 eb/jump loop/disp8 -6758 } -6759 $mu-stmt-matches-primitive?:return-true: -6760 b8/copy-to-eax 1/imm32 -6761 $mu-stmt-matches-primitive?:end: -6762 # . restore registers -6763 5f/pop-to-edi -6764 5e/pop-to-esi -6765 5b/pop-to-ebx -6766 5a/pop-to-edx -6767 59/pop-to-ecx -6768 # . epilogue -6769 89/<- %esp 5/r32/ebp -6770 5d/pop-to-ebp -6771 c3/return -6772 -6773 operand-matches-primitive?: # var: (handle var), prim-var: (handle var) => result/eax: boolean -6774 # . prologue -6775 55/push-ebp -6776 89/<- %ebp 4/r32/esp -6777 # . save registers -6778 56/push-esi -6779 57/push-edi -6780 # esi = var -6781 8b/-> *(ebp+8) 6/r32/esi -6782 # edi = prim-var -6783 8b/-> *(ebp+0xc) 7/r32/edi -6784 # if (var->type != prim-var->type) return false -6785 (type-equal? *(esi+4) *(edi+4)) # Var-type, Var-type => eax -6786 3d/compare-eax-and 0/imm32 -6787 b8/copy-to-eax 0/imm32/false -6788 74/jump-if-= $operand-matches-primitive?:end/disp8 -6789 # return false if var->register doesn't match prim-var->register -6790 { -6791 # if addresses are equal, don't return here -6792 8b/-> *(esi+0x10) 0/r32/eax -6793 39/compare *(edi+0x10) 0/r32/eax -6794 74/jump-if-= break/disp8 -6795 # if either address is 0, return false -6796 3d/compare-eax-and 0/imm32 -6797 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result -6798 81 7/subop/compare *(edi+0x10) 0/imm32 -6799 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result -6800 # if prim-var->register is "*", return true -6801 (string-equal? *(edi+0x10) "*") # Var-register -6802 3d/compare-eax-and 0/imm32 -6803 b8/copy-to-eax 1/imm32/true -6804 75/jump-if-!= $operand-matches-primitive?:end/disp8 -6805 # if string contents don't match, return false -6806 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register -6807 3d/compare-eax-and 0/imm32 -6808 b8/copy-to-eax 0/imm32/false -6809 74/jump-if-= $operand-matches-primitive?:end/disp8 +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 +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 +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: +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 +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") +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 # return true -6812 b8/copy-to-eax 1/imm32/true -6813 $operand-matches-primitive?:end: -6814 # . restore registers -6815 5f/pop-to-edi -6816 5e/pop-to-esi -6817 # . epilogue -6818 89/<- %esp 5/r32/ebp -6819 5d/pop-to-ebp -6820 c3/return -6821 -6822 type-equal?: # a: (handle tree type-id), b: (handle tree type-id) => result/eax: boolean -6823 # . prologue -6824 55/push-ebp -6825 89/<- %ebp 4/r32/esp -6826 # . save registers -6827 51/push-ecx -6828 52/push-edx -6829 # ecx = a -6830 8b/-> *(ebp+8) 1/r32/ecx -6831 # edx = b -6832 8b/-> *(ebp+0xc) 2/r32/edx -6833 # if (a == b) return true -6834 8b/-> %ecx 0/r32/eax # Var-type -6835 39/compare %edx 0/r32/eax # Var-type -6836 b8/copy-to-eax 1/imm32/true -6837 74/jump-if-= $type-equal?:end/disp8 -6838 # if (a < MAX_TYPE_ID) return false -6839 81 7/subop/compare %ecx 0x10000/imm32 -6840 b8/copy-to-eax 0/imm32/false -6841 72/jump-if-addr< $type-equal?:end/disp8 -6842 # if (b < MAX_TYPE_ID) return false -6843 81 7/subop/compare %edx 0x10000/imm32 -6844 b8/copy-to-eax 0/imm32/false -6845 72/jump-if-addr< $type-equal?:end/disp8 -6846 # if (!type-equal?(a->left, b->left)) return false -6847 (type-equal? *ecx *edx) # Tree-left, Tree-left => eax -6848 3d/compare-eax-and 0/imm32 -6849 74/jump-if-= $type-equal?:end/disp8 -6850 # return type-equal?(a->right, b->right) -6851 (type-equal? *(ecx+4) *(edx+4)) # Tree-right, Tree-right => eax -6852 $type-equal?:end: -6853 # . restore registers -6854 5a/pop-to-edx -6855 59/pop-to-ecx -6856 # . epilogue -6857 89/<- %esp 5/r32/ebp -6858 5d/pop-to-ebp -6859 c3/return -6860 -6861 test-emit-subx-statement-primitive: -6862 # Primitive operation on a variable on the stack. -6863 # increment foo -6864 # => -6865 # ff 0/subop/increment *(ebp-8) -6866 # -6867 # There's a variable on the var stack as follows: -6868 # name: 'foo' -6869 # type: int -6870 # stack-offset: -8 -6871 # -6872 # There's a primitive with this info: -6873 # name: 'increment' -6874 # inouts: int/mem -6875 # value: 'ff 0/subop/increment' -6876 # -6877 # There's nothing in functions. -6878 # -6879 # . prologue -6880 55/push-ebp -6881 89/<- %ebp 4/r32/esp -6882 # setup -6883 (clear-stream _test-output-stream) -6884 (clear-stream $_test-output-buffered-file->buffer) -6885 # var type/ecx: (handle tree type-id) = int -6886 68/push 0/imm32/right/null -6887 68/push 1/imm32/left/int -6888 89/<- %ecx 4/r32/esp -6889 # var var-foo/ecx: var -6890 68/push 0/imm32/no-register -6891 68/push -8/imm32/stack-offset -6892 68/push 1/imm32/block-depth -6893 51/push-ecx -6894 68/push "foo"/imm32 -6895 89/<- %ecx 4/r32/esp -6896 # var operand/ebx: (list var) -6897 68/push 0/imm32/next -6898 51/push-ecx/var-foo -6899 89/<- %ebx 4/r32/esp -6900 # var stmt/esi: statement -6901 68/push 0/imm32/next -6902 68/push 0/imm32/outputs -6903 53/push-ebx/operands -6904 68/push "increment"/imm32/operation -6905 68/push 1/imm32 -6906 89/<- %esi 4/r32/esp -6907 # var primitives/ebx: primitive -6908 68/push 0/imm32/next -6909 68/push 0/imm32/output-is-write-only -6910 68/push 0/imm32/no-disp32 -6911 68/push 0/imm32/no-imm32 -6912 68/push 0/imm32/no-r32 -6913 68/push 1/imm32/rm32-is-first-inout -6914 68/push "ff 0/subop/increment"/imm32/subx-name -6915 68/push 0/imm32/outputs -6916 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call -6917 68/push "increment"/imm32/name -6918 89/<- %ebx 4/r32/esp -6919 # convert -6920 c7 0/subop/copy *Curr-block-depth 0/imm32 -6921 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -6922 (flush _test-output-buffered-file) -6923 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -6929 # check output -6930 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-statement-primitive") -6931 # . epilogue -6932 89/<- %esp 5/r32/ebp -6933 5d/pop-to-ebp -6934 c3/return -6935 -6936 test-emit-subx-statement-primitive-register: -6937 # Primitive operation on a variable in a register. -6938 # foo <- increment -6939 # => -6940 # ff 0/subop/increment %eax # sub-optimal, but should suffice -6941 # -6942 # There's a variable on the var stack as follows: -6943 # name: 'foo' -6944 # type: int -6945 # register: 'eax' -6946 # -6947 # There's a primitive with this info: -6948 # name: 'increment' -6949 # out: int/reg -6950 # value: 'ff 0/subop/increment' -6951 # -6952 # There's nothing in functions. -6953 # +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 # setup -6958 (clear-stream _test-output-stream) -6959 (clear-stream $_test-output-buffered-file->buffer) -6960 # var type/ecx: (handle tree type-id) = int -6961 68/push 0/imm32/right/null -6962 68/push 1/imm32/left/int -6963 89/<- %ecx 4/r32/esp -6964 # var var-foo/ecx: var in eax -6965 68/push "eax"/imm32/register -6966 68/push 0/imm32/no-stack-offset -6967 68/push 1/imm32/block-depth -6968 51/push-ecx -6969 68/push "foo"/imm32 -6970 89/<- %ecx 4/r32/esp -6971 # var operand/ebx: (list var) -6972 68/push 0/imm32/next -6973 51/push-ecx/var-foo -6974 89/<- %ebx 4/r32/esp -6975 # var stmt/esi: statement -6976 68/push 0/imm32/next -6977 53/push-ebx/outputs -6978 68/push 0/imm32/inouts -6979 68/push "increment"/imm32/operation -6980 68/push 1/imm32 -6981 89/<- %esi 4/r32/esp -6982 # var formal-var/ebx: var in any register -6983 68/push Any-register/imm32 -6984 68/push 0/imm32/no-stack-offset -6985 68/push 1/imm32/block-depth -6986 ff 6/subop/push *(ecx+4) # Var-type -6987 68/push "dummy"/imm32 -6988 89/<- %ebx 4/r32/esp -6989 # var operand/ebx: (list var) -6990 68/push 0/imm32/next -6991 53/push-ebx/formal-var -6992 89/<- %ebx 4/r32/esp -6993 # var primitives/ebx: primitive -6994 68/push 0/imm32/next -6995 68/push 0/imm32/output-is-write-only -6996 68/push 0/imm32/no-disp32 -6997 68/push 0/imm32/no-imm32 -6998 68/push 0/imm32/no-r32 -6999 68/push 3/imm32/rm32-in-first-output -7000 68/push "ff 0/subop/increment"/imm32/subx-name -7001 53/push-ebx/outputs -7002 68/push 0/imm32/inouts -7003 68/push "increment"/imm32/name -7004 89/<- %ebx 4/r32/esp -7005 # convert -7006 c7 0/subop/copy *Curr-block-depth 0/imm32 -7007 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -7008 (flush _test-output-buffered-file) -7009 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7015 # check output -7016 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-primitive-register") -7017 # . epilogue -7018 89/<- %esp 5/r32/ebp -7019 5d/pop-to-ebp -7020 c3/return -7021 -7022 test-emit-subx-statement-select-primitive: -7023 # Select the right primitive between overloads. -7024 # foo <- increment -7025 # => -7026 # ff 0/subop/increment %eax # sub-optimal, but should suffice -7027 # -7028 # There's a variable on the var stack as follows: -7029 # name: 'foo' -7030 # type: int -7031 # register: 'eax' -7032 # -7033 # There's two primitives, as follows: -7034 # - name: 'increment' -7035 # out: int/reg -7036 # value: 'ff 0/subop/increment' -7037 # - name: 'increment' -7038 # inout: int/mem -7039 # value: 'ff 0/subop/increment' -7040 # -7041 # There's nothing in functions. -7042 # -7043 # . prologue -7044 55/push-ebp -7045 89/<- %ebp 4/r32/esp -7046 # setup -7047 (clear-stream _test-output-stream) -7048 (clear-stream $_test-output-buffered-file->buffer) -7049 # var type/ecx: (handle tree type-id) = int -7050 68/push 0/imm32/right/null -7051 68/push 1/imm32/left/int -7052 89/<- %ecx 4/r32/esp -7053 # var var-foo/ecx: var in eax -7054 68/push "eax"/imm32/register -7055 68/push 0/imm32/no-stack-offset -7056 68/push 1/imm32/block-depth -7057 51/push-ecx -7058 68/push "foo"/imm32 -7059 89/<- %ecx 4/r32/esp -7060 # var real-outputs/edi: (list var) -7061 68/push 0/imm32/next -7062 51/push-ecx/var-foo -7063 89/<- %edi 4/r32/esp -7064 # var stmt/esi: statement -7065 68/push 0/imm32/next -7066 57/push-edi/outputs -7067 68/push 0/imm32/inouts -7068 68/push "increment"/imm32/operation -7069 68/push 1/imm32 -7070 89/<- %esi 4/r32/esp -7071 # var formal-var/ebx: var in any register -7072 68/push Any-register/imm32 -7073 68/push 0/imm32/no-stack-offset -7074 68/push 1/imm32/block-depth -7075 ff 6/subop/push *(ecx+4) # Var-type -7076 68/push "dummy"/imm32 -7077 89/<- %ebx 4/r32/esp -7078 # var formal-outputs/ebx: (list var) = {formal-var, 0} -7079 68/push 0/imm32/next -7080 53/push-ebx/formal-var -7081 89/<- %ebx 4/r32/esp -7082 # var primitive1/ebx: primitive -7083 68/push 0/imm32/next -7084 68/push 0/imm32/output-is-write-only -7085 68/push 0/imm32/no-disp32 -7086 68/push 0/imm32/no-imm32 -7087 68/push 0/imm32/no-r32 -7088 68/push 3/imm32/rm32-in-first-output -7089 68/push "ff 0/subop/increment"/imm32/subx-name -7090 53/push-ebx/outputs/formal-outputs -7091 68/push 0/imm32/inouts -7092 68/push "increment"/imm32/name -7093 89/<- %ebx 4/r32/esp -7094 # var primitives/ebx: primitive -7095 53/push-ebx/next -7096 68/push 0/imm32/output-is-write-only -7097 68/push 0/imm32/no-disp32 -7098 68/push 0/imm32/no-imm32 -7099 68/push 0/imm32/no-r32 -7100 68/push 1/imm32/rm32-is-first-inout -7101 68/push "ff 0/subop/increment"/imm32/subx-name -7102 68/push 0/imm32/outputs -7103 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -7104 68/push "increment"/imm32/name -7105 89/<- %ebx 4/r32/esp -7106 # convert -7107 c7 0/subop/copy *Curr-block-depth 0/imm32 -7108 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -7109 (flush _test-output-buffered-file) -7110 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7116 # check output -7117 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive") -7118 # . epilogue -7119 89/<- %esp 5/r32/ebp -7120 5d/pop-to-ebp -7121 c3/return -7122 -7123 test-emit-subx-statement-select-primitive-2: -7124 # Select the right primitive between overloads. -7125 # foo <- increment -7126 # => -7127 # ff 0/subop/increment %eax # sub-optimal, but should suffice -7128 # -7129 # There's a variable on the var stack as follows: -7130 # name: 'foo' -7131 # type: int -7132 # register: 'eax' -7133 # -7134 # There's two primitives, as follows: -7135 # - name: 'increment' -7136 # out: int/reg -7137 # value: 'ff 0/subop/increment' -7138 # - name: 'increment' -7139 # inout: int/mem -7140 # value: 'ff 0/subop/increment' -7141 # -7142 # There's nothing in functions. -7143 # -7144 # . prologue -7145 55/push-ebp -7146 89/<- %ebp 4/r32/esp -7147 # setup -7148 (clear-stream _test-output-stream) -7149 (clear-stream $_test-output-buffered-file->buffer) -7150 # var type/ecx: (handle tree type-id) = int -7151 68/push 0/imm32/right/null -7152 68/push 1/imm32/left/int -7153 89/<- %ecx 4/r32/esp -7154 # var var-foo/ecx: var in eax -7155 68/push "eax"/imm32/register -7156 68/push 0/imm32/no-stack-offset -7157 68/push 1/imm32/block-depth -7158 51/push-ecx -7159 68/push "foo"/imm32 -7160 89/<- %ecx 4/r32/esp -7161 # var inouts/edi: (list var) -7162 68/push 0/imm32/next -7163 51/push-ecx/var-foo -7164 89/<- %edi 4/r32/esp -7165 # var stmt/esi: statement -7166 68/push 0/imm32/next -7167 68/push 0/imm32/outputs -7168 57/push-edi/inouts -7169 68/push "increment"/imm32/operation -7170 68/push 1/imm32 -7171 89/<- %esi 4/r32/esp -7172 # var formal-var/ebx: var in any register -7173 68/push Any-register/imm32 -7174 68/push 0/imm32/no-stack-offset -7175 68/push 1/imm32/block-depth -7176 ff 6/subop/push *(ecx+4) # Var-type -7177 68/push "dummy"/imm32 -7178 89/<- %ebx 4/r32/esp -7179 # var operand/ebx: (list var) -7180 68/push 0/imm32/next -7181 53/push-ebx/formal-var -7182 89/<- %ebx 4/r32/esp -7183 # var primitive1/ebx: primitive -7184 68/push 0/imm32/next -7185 68/push 0/imm32/output-is-write-only -7186 68/push 0/imm32/no-disp32 -7187 68/push 0/imm32/no-imm32 -7188 68/push 0/imm32/no-r32 -7189 68/push 3/imm32/rm32-in-first-output -7190 68/push "ff 0/subop/increment"/imm32/subx-name -7191 53/push-ebx/outputs/formal-outputs -7192 68/push 0/imm32/inouts -7193 68/push "increment"/imm32/name -7194 89/<- %ebx 4/r32/esp -7195 # var primitives/ebx: primitive -7196 53/push-ebx/next -7197 68/push 0/imm32/output-is-write-only -7198 68/push 0/imm32/no-disp32 -7199 68/push 0/imm32/no-imm32 -7200 68/push 0/imm32/no-r32 -7201 68/push 1/imm32/rm32-is-first-inout -7202 68/push "ff 0/subop/increment"/imm32/subx-name -7203 68/push 0/imm32/outputs -7204 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -7205 68/push "increment"/imm32/name -7206 89/<- %ebx 4/r32/esp -7207 # convert -7208 c7 0/subop/copy *Curr-block-depth 0/imm32 -7209 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -7210 (flush _test-output-buffered-file) -7211 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7217 # check output -7218 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2") -7219 # . epilogue -7220 89/<- %esp 5/r32/ebp -7221 5d/pop-to-ebp -7222 c3/return -7223 -7224 test-increment-register: -7225 # Select the right register between overloads. -7226 # foo <- increment -7227 # => -7228 # 50/increment-eax -7229 # -7230 # There's a variable on the var stack as follows: -7231 # name: 'foo' -7232 # type: int -7233 # register: 'eax' -7234 # -7235 # Primitives are the global definitions. -7236 # -7237 # There are no functions defined. -7238 # -7239 # . prologue -7240 55/push-ebp -7241 89/<- %ebp 4/r32/esp -7242 # setup -7243 (clear-stream _test-output-stream) -7244 (clear-stream $_test-output-buffered-file->buffer) -7245 # var type/ecx: (handle tree type-id) = int -7246 68/push 0/imm32/right/null -7247 68/push 1/imm32/left/int -7248 89/<- %ecx 4/r32/esp -7249 # var var-foo/ecx: var in eax -7250 68/push "eax"/imm32/register -7251 68/push 0/imm32/no-stack-offset -7252 68/push 1/imm32/block-depth -7253 51/push-ecx -7254 68/push "foo"/imm32 -7255 89/<- %ecx 4/r32/esp -7256 # var real-outputs/edi: (list var) -7257 68/push 0/imm32/next -7258 51/push-ecx/var-foo -7259 89/<- %edi 4/r32/esp -7260 # var stmt/esi: statement -7261 68/push 0/imm32/next -7262 57/push-edi/outputs -7263 68/push 0/imm32/inouts -7264 68/push "increment"/imm32/operation -7265 68/push 1/imm32/regular-statement -7266 89/<- %esi 4/r32/esp -7267 # convert -7268 c7 0/subop/copy *Curr-block-depth 0/imm32 -7269 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7270 (flush _test-output-buffered-file) -7271 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7277 # check output -7278 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") -7279 # . epilogue -7280 89/<- %esp 5/r32/ebp -7281 5d/pop-to-ebp -7282 c3/return -7283 -7284 test-increment-var: -7285 # Select the right primitive between overloads. -7286 # foo <- increment -7287 # => -7288 # ff 0/subop/increment %eax # sub-optimal, but should suffice -7289 # -7290 # There's a variable on the var stack as follows: -7291 # name: 'foo' -7292 # type: int -7293 # register: 'eax' -7294 # -7295 # Primitives are the global definitions. -7296 # -7297 # There are no functions defined. -7298 # -7299 # . prologue -7300 55/push-ebp -7301 89/<- %ebp 4/r32/esp -7302 # setup -7303 (clear-stream _test-output-stream) -7304 (clear-stream $_test-output-buffered-file->buffer) -7305 # var type/ecx: (handle tree type-id) = int -7306 68/push 0/imm32/right/null -7307 68/push 1/imm32/left/int -7308 89/<- %ecx 4/r32/esp -7309 # var var-foo/ecx: var in eax -7310 68/push "eax"/imm32/register -7311 68/push 0/imm32/no-stack-offset -7312 68/push 1/imm32/block-depth -7313 51/push-ecx -7314 68/push "foo"/imm32 -7315 89/<- %ecx 4/r32/esp -7316 # var inouts/edi: (list var) -7317 68/push 0/imm32/next -7318 51/push-ecx/var-foo -7319 89/<- %edi 4/r32/esp -7320 # var stmt/esi: statement -7321 68/push 0/imm32/next -7322 68/push 0/imm32/outputs -7323 57/push-edi/inouts -7324 68/push "increment"/imm32/operation -7325 68/push 1/imm32 -7326 89/<- %esi 4/r32/esp -7327 # convert -7328 c7 0/subop/copy *Curr-block-depth 0/imm32 -7329 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7330 (flush _test-output-buffered-file) -7331 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7337 # check output -7338 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-increment-var") -7339 # . epilogue -7340 89/<- %esp 5/r32/ebp -7341 5d/pop-to-ebp -7342 c3/return -7343 -7344 test-add-reg-to-reg: -7345 # var1/reg <- add var2/reg -7346 # => -7347 # 01/add %var1 var2 -7348 # -7349 # . prologue -7350 55/push-ebp -7351 89/<- %ebp 4/r32/esp -7352 # setup -7353 (clear-stream _test-output-stream) -7354 (clear-stream $_test-output-buffered-file->buffer) -7355 # var type/ecx: (handle tree type-id) = int -7356 68/push 0/imm32/right/null -7357 68/push 1/imm32/left/int -7358 89/<- %ecx 4/r32/esp -7359 # var var-var1/ecx: var in eax -7360 68/push "eax"/imm32/register -7361 68/push 0/imm32/no-stack-offset -7362 68/push 1/imm32/block-depth -7363 51/push-ecx -7364 68/push "var1"/imm32 -7365 89/<- %ecx 4/r32/esp -7366 # var var-var2/edx: var in ecx -7367 68/push "ecx"/imm32/register -7368 68/push 0/imm32/no-stack-offset -7369 68/push 1/imm32/block-depth -7370 ff 6/subop/push *(ecx+4) # Var-type -7371 68/push "var2"/imm32 -7372 89/<- %edx 4/r32/esp -7373 # var inouts/esi: (list var2) -7374 68/push 0/imm32/next -7375 52/push-edx/var-var2 -7376 89/<- %esi 4/r32/esp -7377 # var outputs/edi: (list var1) -7378 68/push 0/imm32/next -7379 51/push-ecx/var-var1 -7380 89/<- %edi 4/r32/esp -7381 # var stmt/esi: statement -7382 68/push 0/imm32/next -7383 57/push-edi/outputs -7384 56/push-esi/inouts -7385 68/push "add"/imm32/operation -7386 68/push 1/imm32 -7387 89/<- %esi 4/r32/esp -7388 # convert -7389 c7 0/subop/copy *Curr-block-depth 0/imm32 -7390 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7391 (flush _test-output-buffered-file) -7392 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7398 # check output -7399 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") -7400 # . epilogue -7401 89/<- %esp 5/r32/ebp -7402 5d/pop-to-ebp -7403 c3/return -7404 -7405 test-add-reg-to-mem: -7406 # add-to var1 var2/reg -7407 # => -7408 # 01/add *(ebp+__) var2 -7409 # -7410 # . prologue -7411 55/push-ebp -7412 89/<- %ebp 4/r32/esp -7413 # setup -7414 (clear-stream _test-output-stream) -7415 (clear-stream $_test-output-buffered-file->buffer) -7416 # var type/ecx: (handle tree type-id) = int -7417 68/push 0/imm32/right/null -7418 68/push 1/imm32/left/int -7419 89/<- %ecx 4/r32/esp -7420 # var var-var1/ecx: var -7421 68/push 0/imm32/no-register -7422 68/push 8/imm32/stack-offset -7423 68/push 1/imm32/block-depth -7424 51/push-ecx -7425 68/push "var1"/imm32 -7426 89/<- %ecx 4/r32/esp -7427 # var var-var2/edx: var in ecx -7428 68/push "ecx"/imm32/register -7429 68/push 0/imm32/no-stack-offset -7430 68/push 1/imm32/block-depth -7431 ff 6/subop/push *(ecx+4) # Var-type -7432 68/push "var2"/imm32 -7433 89/<- %edx 4/r32/esp -7434 # var inouts/esi: (list var2) -7435 68/push 0/imm32/next -7436 52/push-edx/var-var2 -7437 89/<- %esi 4/r32/esp -7438 # var inouts = (list var1 var2) -7439 56/push-esi/next -7440 51/push-ecx/var-var1 -7441 89/<- %esi 4/r32/esp -7442 # var stmt/esi: statement -7443 68/push 0/imm32/next -7444 68/push 0/imm32/outputs -7445 56/push-esi/inouts -7446 68/push "add-to"/imm32/operation -7447 68/push 1/imm32 -7448 89/<- %esi 4/r32/esp -7449 # convert -7450 c7 0/subop/copy *Curr-block-depth 0/imm32 -7451 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7452 (flush _test-output-buffered-file) -7453 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7459 # check output -7460 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") -7461 # . epilogue -7462 89/<- %esp 5/r32/ebp -7463 5d/pop-to-ebp -7464 c3/return -7465 -7466 test-add-mem-to-reg: -7467 # var1/reg <- add var2 -7468 # => -7469 # 03/add *(ebp+__) var1 -7470 # -7471 # . prologue -7472 55/push-ebp -7473 89/<- %ebp 4/r32/esp -7474 # setup -7475 (clear-stream _test-output-stream) -7476 (clear-stream $_test-output-buffered-file->buffer) -7477 # var type/ecx: (handle tree type-id) = int -7478 68/push 0/imm32/right/null -7479 68/push 1/imm32/left/int -7480 89/<- %ecx 4/r32/esp -7481 # var var-var1/ecx: var in eax -7482 68/push "eax"/imm32/register -7483 68/push 0/imm32/no-stack-offset -7484 68/push 1/imm32/block-depth -7485 51/push-ecx -7486 68/push "var1"/imm32 -7487 89/<- %ecx 4/r32/esp -7488 # var var-var2/edx: var -7489 68/push 0/imm32/no-register -7490 68/push 8/imm32/stack-offset -7491 68/push 1/imm32/block-depth -7492 ff 6/subop/push *(ecx+4) # Var-type -7493 68/push "var2"/imm32 -7494 89/<- %edx 4/r32/esp -7495 # var inouts/esi: (list var2) -7496 68/push 0/imm32/next -7497 52/push-edx/var-var2 -7498 89/<- %esi 4/r32/esp -7499 # var outputs/edi: (list var1) -7500 68/push 0/imm32/next -7501 51/push-ecx/var-var1 -7502 89/<- %edi 4/r32/esp -7503 # var stmt/esi: statement +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 +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 +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 57/push-edi/outputs -7506 56/push-esi/inouts -7507 68/push "add"/imm32/operation -7508 68/push 1/imm32 -7509 89/<- %esi 4/r32/esp -7510 # convert -7511 c7 0/subop/copy *Curr-block-depth 0/imm32 -7512 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7513 (flush _test-output-buffered-file) -7514 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7520 # check output -7521 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") -7522 # . epilogue -7523 89/<- %esp 5/r32/ebp -7524 5d/pop-to-ebp -7525 c3/return -7526 -7527 test-add-literal-to-eax: -7528 # var1/eax <- add 0x34 -7529 # => -7530 # 05/add-to-eax 0x34/imm32 -7531 # -7532 # . prologue -7533 55/push-ebp -7534 89/<- %ebp 4/r32/esp -7535 # setup -7536 (clear-stream _test-output-stream) -7537 (clear-stream $_test-output-buffered-file->buffer) -7538 # var type/ecx: (handle tree type-id) = int -7539 68/push 0/imm32/right/null -7540 68/push 1/imm32/left/int -7541 89/<- %ecx 4/r32/esp -7542 # var var-var1/ecx: var in eax -7543 68/push "eax"/imm32/register -7544 68/push 0/imm32/no-stack-offset -7545 68/push 1/imm32/block-depth -7546 51/push-ecx -7547 68/push "var1"/imm32 -7548 89/<- %ecx 4/r32/esp -7549 # var type/edx: (handle tree type-id) = literal -7550 68/push 0/imm32/right/null -7551 68/push 0/imm32/left/literal -7552 89/<- %edx 4/r32/esp -7553 # var var-var2/edx: var literal -7554 68/push 0/imm32/no-register -7555 68/push 0/imm32/no-stack-offset -7556 68/push 1/imm32/block-depth -7557 52/push-edx -7558 68/push "0x34"/imm32 -7559 89/<- %edx 4/r32/esp -7560 # var inouts/esi: (list var2) -7561 68/push 0/imm32/next -7562 52/push-edx/var-var2 -7563 89/<- %esi 4/r32/esp -7564 # var outputs/edi: (list var1) -7565 68/push 0/imm32/next -7566 51/push-ecx/var-var1 -7567 89/<- %edi 4/r32/esp -7568 # var stmt/esi: statement -7569 68/push 0/imm32/next -7570 57/push-edi/outputs -7571 56/push-esi/inouts -7572 68/push "add"/imm32/operation -7573 68/push 1/imm32 -7574 89/<- %esi 4/r32/esp -7575 # convert -7576 c7 0/subop/copy *Curr-block-depth 0/imm32 -7577 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7578 (flush _test-output-buffered-file) -7579 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7585 # check output -7586 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") -7587 # . epilogue -7588 89/<- %esp 5/r32/ebp -7589 5d/pop-to-ebp -7590 c3/return -7591 -7592 test-add-literal-to-reg: -7593 # var1/ecx <- add 0x34 -7594 # => -7595 # 81 0/subop/add %ecx 0x34/imm32 -7596 # -7597 # . prologue -7598 55/push-ebp -7599 89/<- %ebp 4/r32/esp -7600 # setup -7601 (clear-stream _test-output-stream) -7602 (clear-stream $_test-output-buffered-file->buffer) -7603 # var type/ecx: (handle tree type-id) = int -7604 68/push 0/imm32/right/null -7605 68/push 1/imm32/left/int -7606 89/<- %ecx 4/r32/esp -7607 # var var-var1/ecx: var in ecx -7608 68/push "ecx"/imm32/register -7609 68/push 0/imm32/no-stack-offset -7610 68/push 1/imm32/block-depth -7611 51/push-ecx -7612 68/push "var1"/imm32 -7613 89/<- %ecx 4/r32/esp -7614 # var type/edx: (handle tree type-id) = literal -7615 68/push 0/imm32/right/null -7616 68/push 0/imm32/left/literal -7617 89/<- %edx 4/r32/esp -7618 # var var-var2/edx: var literal -7619 68/push 0/imm32/no-register -7620 68/push 0/imm32/no-stack-offset -7621 68/push 1/imm32/block-depth -7622 52/push-edx -7623 68/push "0x34"/imm32 -7624 89/<- %edx 4/r32/esp -7625 # var inouts/esi: (list var2) -7626 68/push 0/imm32/next -7627 52/push-edx/var-var2 -7628 89/<- %esi 4/r32/esp -7629 # var outputs/edi: (list var1) -7630 68/push 0/imm32/next -7631 51/push-ecx/var-var1 -7632 89/<- %edi 4/r32/esp -7633 # var stmt/esi: statement -7634 68/push 0/imm32/next -7635 57/push-edi/outputs -7636 56/push-esi/inouts -7637 68/push "add"/imm32/operation -7638 68/push 1/imm32 -7639 89/<- %esi 4/r32/esp -7640 # convert -7641 c7 0/subop/copy *Curr-block-depth 0/imm32 -7642 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7643 (flush _test-output-buffered-file) -7644 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7650 # check output -7651 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") -7652 # . epilogue -7653 89/<- %esp 5/r32/ebp -7654 5d/pop-to-ebp -7655 c3/return -7656 -7657 test-add-literal-to-mem: -7658 # add-to var1, 0x34 -7659 # => -7660 # 81 0/subop/add %eax 0x34/imm32 -7661 # -7662 # . prologue -7663 55/push-ebp -7664 89/<- %ebp 4/r32/esp -7665 # setup -7666 (clear-stream _test-output-stream) -7667 (clear-stream $_test-output-buffered-file->buffer) -7668 # var type/ecx: (handle tree type-id) = int -7669 68/push 0/imm32/right/null -7670 68/push 1/imm32/left/int -7671 89/<- %ecx 4/r32/esp -7672 # var var-var1/ecx: var -7673 68/push 0/imm32/no-register -7674 68/push 8/imm32/stack-offset -7675 68/push 1/imm32/block-depth -7676 51/push-ecx -7677 68/push "var1"/imm32 -7678 89/<- %ecx 4/r32/esp -7679 # var type/edx: (handle tree type-id) = literal +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 0/imm32/left/literal -7682 89/<- %edx 4/r32/esp -7683 # var var-var2/edx: var literal -7684 68/push 0/imm32/no-register +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 52/push-edx -7688 68/push "0x34"/imm32 -7689 89/<- %edx 4/r32/esp -7690 # var inouts/esi: (list var2) -7691 68/push 0/imm32/next -7692 52/push-edx/var-var2 -7693 89/<- %esi 4/r32/esp -7694 # var inouts = (list var1 inouts) -7695 56/push-esi/next -7696 51/push-ecx/var-var1 -7697 89/<- %esi 4/r32/esp -7698 # var stmt/esi: statement -7699 68/push 0/imm32/next -7700 68/push 0/imm32/outputs -7701 56/push-esi/inouts -7702 68/push "add-to"/imm32/operation -7703 68/push 1/imm32 -7704 89/<- %esi 4/r32/esp -7705 # convert -7706 c7 0/subop/copy *Curr-block-depth 0/imm32 -7707 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7708 (flush _test-output-buffered-file) -7709 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7715 # check output -7716 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") -7717 # . epilogue -7718 89/<- %esp 5/r32/ebp -7719 5d/pop-to-ebp -7720 c3/return -7721 -7722 test-compare-mem-with-reg: -7723 # compare var1, var2/eax -7724 # => -7725 # 39/compare *(ebp+___) 0/r32/eax -7726 # -7727 # . prologue -7728 55/push-ebp -7729 89/<- %ebp 4/r32/esp -7730 # setup -7731 (clear-stream _test-output-stream) -7732 (clear-stream $_test-output-buffered-file->buffer) -7733 # var type/ecx: (handle tree type-id) = int -7734 68/push 0/imm32/right/null -7735 68/push 1/imm32/left/int -7736 89/<- %ecx 4/r32/esp -7737 # var var-var2/ecx: var in eax -7738 68/push "eax"/imm32/register -7739 68/push 0/imm32/no-stack-offset -7740 68/push 1/imm32/block-depth -7741 51/push-ecx -7742 68/push "var2"/imm32 +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/edx: var +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 ff 6/subop/push *(ecx+4) # Var-type +7748 51/push-ecx 7749 68/push "var1"/imm32 -7750 89/<- %edx 4/r32/esp -7751 # var inouts/esi: (list var1 var2) -7752 68/push 0/imm32/next -7753 51/push-ecx/var-var2 -7754 89/<- %esi 4/r32/esp -7755 56/push-esi -7756 52/push-edx/var-var1 -7757 89/<- %esi 4/r32/esp -7758 # var stmt/esi: statement +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 68/push 0/imm32/outputs -7761 56/push-esi/inouts -7762 68/push "compare"/imm32/operation -7763 68/push 1/imm32 -7764 89/<- %esi 4/r32/esp -7765 # convert -7766 c7 0/subop/copy *Curr-block-depth 0/imm32 -7767 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7768 (flush _test-output-buffered-file) -7769 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7775 # check output -7776 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") -7777 # . epilogue -7778 89/<- %esp 5/r32/ebp -7779 5d/pop-to-ebp -7780 c3/return -7781 -7782 test-compare-reg-with-mem: -7783 # compare var1/eax, var2 -7784 # => -7785 # 3b/compare *(ebp+___) 0/r32/eax -7786 # -7787 # . prologue -7788 55/push-ebp -7789 89/<- %ebp 4/r32/esp -7790 # setup -7791 (clear-stream _test-output-stream) -7792 (clear-stream $_test-output-buffered-file->buffer) -7793 # var type/ecx: (handle tree type-id) = int -7794 68/push 0/imm32/right/null -7795 68/push 1/imm32/left/int -7796 89/<- %ecx 4/r32/esp -7797 # var var-var1/ecx: var in eax -7798 68/push "eax"/imm32/register -7799 68/push 0/imm32/no-stack-offset -7800 68/push 1/imm32/block-depth -7801 51/push-ecx -7802 68/push "var1"/imm32 -7803 89/<- %ecx 4/r32/esp -7804 # var var-var2/edx: var -7805 68/push 0/imm32/no-register -7806 68/push 8/imm32/stack-offset -7807 68/push 1/imm32/block-depth -7808 ff 6/subop/push *(ecx+4) # Var-type -7809 68/push "var2"/imm32 -7810 89/<- %edx 4/r32/esp -7811 # var inouts/esi: (list var1 var2) -7812 68/push 0/imm32/next -7813 52/push-edx/var-var2 -7814 89/<- %esi 4/r32/esp -7815 56/push-esi -7816 51/push-ecx/var-var1 -7817 89/<- %esi 4/r32/esp -7818 # var stmt/esi: statement -7819 68/push 0/imm32/next -7820 68/push 0/imm32/outputs -7821 56/push-esi/inouts -7822 68/push "compare"/imm32/operation -7823 68/push 1/imm32 -7824 89/<- %esi 4/r32/esp -7825 # convert -7826 c7 0/subop/copy *Curr-block-depth 0/imm32 -7827 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7828 (flush _test-output-buffered-file) -7829 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7835 # check output -7836 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") -7837 # . epilogue -7838 89/<- %esp 5/r32/ebp -7839 5d/pop-to-ebp -7840 c3/return -7841 -7842 test-compare-mem-with-literal: -7843 # compare var1, 0x34 -7844 # => -7845 # 81 7/subop/compare *(ebp+___) 0x34/imm32 -7846 # -7847 # . prologue -7848 55/push-ebp -7849 89/<- %ebp 4/r32/esp -7850 # setup -7851 (clear-stream _test-output-stream) -7852 (clear-stream $_test-output-buffered-file->buffer) -7853 # var type/ecx: (handle tree type-id) = int -7854 68/push 0/imm32/right/null -7855 68/push 1/imm32/left/int -7856 89/<- %ecx 4/r32/esp -7857 # var var-var1/ecx: var -7858 68/push 0/imm32/no-register -7859 68/push 8/imm32/stack-offset -7860 68/push 1/imm32/block-depth -7861 51/push-ecx -7862 68/push "var1"/imm32 -7863 89/<- %ecx 4/r32/esp -7864 # var type/edx: (handle tree type-id) = literal -7865 68/push 0/imm32/right/null -7866 68/push 0/imm32/left/literal -7867 89/<- %edx 4/r32/esp -7868 # var var-var2/edx: var literal -7869 68/push 0/imm32/no-register -7870 68/push 0/imm32/no-stack-offset -7871 68/push 1/imm32/block-depth -7872 52/push-edx -7873 68/push "0x34"/imm32 -7874 89/<- %edx 4/r32/esp -7875 # var inouts/esi: (list var2) -7876 68/push 0/imm32/next -7877 52/push-edx/var-var2 -7878 89/<- %esi 4/r32/esp -7879 # var inouts = (list var1 inouts) -7880 56/push-esi/next -7881 51/push-ecx/var-var1 -7882 89/<- %esi 4/r32/esp -7883 # var stmt/esi: statement -7884 68/push 0/imm32/next -7885 68/push 0/imm32/outputs -7886 56/push-esi/inouts -7887 68/push "compare"/imm32/operation -7888 68/push 1/imm32 -7889 89/<- %esi 4/r32/esp -7890 # convert -7891 c7 0/subop/copy *Curr-block-depth 0/imm32 -7892 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7893 (flush _test-output-buffered-file) -7894 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7900 # check output -7901 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") -7902 # . epilogue -7903 89/<- %esp 5/r32/ebp -7904 5d/pop-to-ebp -7905 c3/return -7906 -7907 test-compare-eax-with-literal: -7908 # compare var1/eax 0x34 -7909 # => -7910 # 3d/compare-eax-with 0x34/imm32 -7911 # -7912 # . prologue -7913 55/push-ebp -7914 89/<- %ebp 4/r32/esp -7915 # setup -7916 (clear-stream _test-output-stream) -7917 (clear-stream $_test-output-buffered-file->buffer) -7918 # var type/ecx: (handle tree type-id) = int -7919 68/push 0/imm32/right/null -7920 68/push 1/imm32/left/int -7921 89/<- %ecx 4/r32/esp -7922 # var var-var1/ecx: var in eax -7923 68/push "eax"/imm32/register -7924 68/push 0/imm32/no-stack-offset -7925 68/push 1/imm32/block-depth -7926 51/push-ecx -7927 68/push "var1"/imm32 -7928 89/<- %ecx 4/r32/esp -7929 # var type/edx: (handle tree type-id) = literal -7930 68/push 0/imm32/right/null -7931 68/push 0/imm32/left/literal -7932 89/<- %edx 4/r32/esp -7933 # var var-var2/edx: var literal -7934 68/push 0/imm32/no-register -7935 68/push 0/imm32/no-stack-offset -7936 68/push 1/imm32/block-depth -7937 52/push-edx -7938 68/push "0x34"/imm32 -7939 89/<- %edx 4/r32/esp -7940 # var inouts/esi: (list var2) -7941 68/push 0/imm32/next -7942 52/push-edx/var-var2 -7943 89/<- %esi 4/r32/esp -7944 # var inouts = (list var1 inouts) -7945 56/push-esi/next -7946 51/push-ecx/var-var1 -7947 89/<- %esi 4/r32/esp -7948 # var stmt/esi: statement -7949 68/push 0/imm32/next -7950 68/push 0/imm32/outputs -7951 56/push-esi/inouts -7952 68/push "compare"/imm32/operation -7953 68/push 1/imm32/regular-stmt -7954 89/<- %esi 4/r32/esp -7955 # convert -7956 c7 0/subop/copy *Curr-block-depth 0/imm32 -7957 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7958 (flush _test-output-buffered-file) -7959 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -7965 # check output -7966 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") -7967 # . epilogue -7968 89/<- %esp 5/r32/ebp -7969 5d/pop-to-ebp -7970 c3/return -7971 -7972 test-compare-reg-with-literal: -7973 # compare var1/ecx 0x34 -7974 # => -7975 # 81 7/subop/compare %ecx 0x34/imm32 -7976 # -7977 # . prologue -7978 55/push-ebp -7979 89/<- %ebp 4/r32/esp -7980 # setup -7981 (clear-stream _test-output-stream) -7982 (clear-stream $_test-output-buffered-file->buffer) -7983 # var type/ecx: (handle tree type-id) = int -7984 68/push 0/imm32/right/null -7985 68/push 1/imm32/left/int -7986 89/<- %ecx 4/r32/esp -7987 # var var-var1/ecx: var in ecx -7988 68/push "ecx"/imm32/register -7989 68/push 0/imm32/no-stack-offset -7990 68/push 1/imm32/block-depth -7991 51/push-ecx -7992 68/push "var1"/imm32 -7993 89/<- %ecx 4/r32/esp -7994 # var type/edx: (handle tree type-id) = literal -7995 68/push 0/imm32/right/null -7996 68/push 0/imm32/left/literal -7997 89/<- %edx 4/r32/esp -7998 # var var-var2/edx: var literal -7999 68/push 0/imm32/no-register -8000 68/push 0/imm32/no-stack-offset -8001 68/push 1/imm32/block-depth -8002 52/push-edx -8003 68/push "0x34"/imm32 -8004 89/<- %edx 4/r32/esp -8005 # var inouts/esi: (list var2) -8006 68/push 0/imm32/next -8007 52/push-edx/var-var2 -8008 89/<- %esi 4/r32/esp -8009 # var inouts = (list var1 inouts) -8010 56/push-esi/next -8011 51/push-ecx/var-var1 -8012 89/<- %esi 4/r32/esp -8013 # var stmt/esi: statement -8014 68/push 0/imm32/next -8015 68/push 0/imm32/outputs -8016 56/push-esi/inouts -8017 68/push "compare"/imm32/operation -8018 68/push 1/imm32/regular-stmt -8019 89/<- %esi 4/r32/esp -8020 # convert -8021 c7 0/subop/copy *Curr-block-depth 0/imm32 -8022 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8023 (flush _test-output-buffered-file) -8024 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -8030 # check output -8031 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") -8032 # . epilogue -8033 89/<- %esp 5/r32/ebp -8034 5d/pop-to-ebp -8035 c3/return -8036 -8037 test-emit-subx-statement-function-call: -8038 # Call a function on a variable on the stack. -8039 # f foo -8040 # => -8041 # (f2 *(ebp-8)) -8042 # (Changing the function name supports overloading in general, but here it -8043 # just serves to help disambiguate things.) -8044 # -8045 # There's a variable on the var stack as follows: -8046 # name: 'foo' -8047 # type: int -8048 # stack-offset: -8 -8049 # -8050 # There's nothing in primitives. -8051 # -8052 # There's a function with this info: -8053 # name: 'f' -8054 # inout: int/mem -8055 # value: 'f2' -8056 # -8057 # . prologue -8058 55/push-ebp -8059 89/<- %ebp 4/r32/esp -8060 # setup -8061 (clear-stream _test-output-stream) -8062 (clear-stream $_test-output-buffered-file->buffer) -8063 # var type/ecx: (handle tree type-id) = int -8064 68/push 0/imm32/right/null -8065 68/push 1/imm32/left/int -8066 89/<- %ecx 4/r32/esp -8067 # var var-foo/ecx: var -8068 68/push 0/imm32/no-register -8069 68/push -8/imm32/stack-offset -8070 68/push 0/imm32/block-depth -8071 51/push-ecx -8072 68/push "foo"/imm32 -8073 89/<- %ecx 4/r32/esp -8074 # var operands/esi: (list var) -8075 68/push 0/imm32/next -8076 51/push-ecx/var-foo -8077 89/<- %esi 4/r32/esp -8078 # var stmt/esi: statement -8079 68/push 0/imm32/next -8080 68/push 0/imm32/outputs -8081 56/push-esi/inouts -8082 68/push "f"/imm32/operation -8083 68/push 1/imm32 -8084 89/<- %esi 4/r32/esp -8085 # var functions/ebx: function -8086 68/push 0/imm32/next -8087 68/push 0/imm32/body -8088 68/push 0/imm32/outputs -8089 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -8090 68/push "f2"/imm32/subx-name -8091 68/push "f"/imm32/name -8092 89/<- %ebx 4/r32/esp -8093 # convert -8094 c7 0/subop/copy *Curr-block-depth 0/imm32 -8095 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) -8096 (flush _test-output-buffered-file) -8097 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -8103 # check output -8104 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-statement-function-call") -8105 # . epilogue -8106 89/<- %esp 5/r32/ebp -8107 5d/pop-to-ebp -8108 c3/return -8109 -8110 test-emit-subx-statement-function-call-with-literal-arg: -8111 # Call a function on a literal. -8112 # f 34 -8113 # => -8114 # (f2 34) -8115 # -8116 # . prologue -8117 55/push-ebp -8118 89/<- %ebp 4/r32/esp -8119 # setup -8120 (clear-stream _test-output-stream) -8121 (clear-stream $_test-output-buffered-file->buffer) -8122 # var type/ecx: (handle tree type-id) = literal -8123 68/push 0/imm32/right/null -8124 68/push 0/imm32/left/literal -8125 89/<- %ecx 4/r32/esp -8126 # var var-foo/ecx: var literal -8127 68/push 0/imm32/no-register -8128 68/push 0/imm32/no-stack-offset -8129 68/push 0/imm32/block-depth -8130 51/push-ecx -8131 68/push "34"/imm32 -8132 89/<- %ecx 4/r32/esp -8133 # var operands/esi: (list var) -8134 68/push 0/imm32/next -8135 51/push-ecx/var-foo -8136 89/<- %esi 4/r32/esp -8137 # var stmt/esi: statement -8138 68/push 0/imm32/next -8139 68/push 0/imm32/outputs -8140 56/push-esi/inouts -8141 68/push "f"/imm32/operation -8142 68/push 1/imm32 -8143 89/<- %esi 4/r32/esp -8144 # var functions/ebx: function -8145 68/push 0/imm32/next -8146 68/push 0/imm32/body -8147 68/push 0/imm32/outputs -8148 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -8149 68/push "f2"/imm32/subx-name -8150 68/push "f"/imm32/name -8151 89/<- %ebx 4/r32/esp -8152 # convert -8153 c7 0/subop/copy *Curr-block-depth 0/imm32 -8154 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) -8155 (flush _test-output-buffered-file) -8156 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -8162 # check output -8163 (check-next-stream-line-equal _test-output-stream "(f2 34)" "F - test-emit-subx-statement-function-call-with-literal-arg") -8164 # . epilogue -8165 89/<- %esp 5/r32/ebp -8166 5d/pop-to-ebp -8167 c3/return -8168 -8169 emit-indent: # out: (addr buffered-file), n: int -8170 # . prologue -8171 55/push-ebp -8172 89/<- %ebp 4/r32/esp -8173 # . save registers -8174 50/push-eax -8175 # var i/eax: int = n -8176 8b/-> *(ebp+0xc) 0/r32/eax -8177 { -8178 # if (i <= 0) break -8179 3d/compare-eax-with 0/imm32 -8180 7e/jump-if-<= break/disp8 -8181 (write-buffered *(ebp+8) " ") -8182 48/decrement-eax -8183 eb/jump loop/disp8 -8184 } -8185 $emit-indent:end: -8186 # . restore registers -8187 58/pop-to-eax -8188 # . epilogue -8189 89/<- %esp 5/r32/ebp -8190 5d/pop-to-ebp -8191 c3/return -8192 -8193 emit-subx-prologue: # out: (addr buffered-file) -8194 # . prologue -8195 55/push-ebp -8196 89/<- %ebp 4/r32/esp -8197 # -8198 (write-buffered *(ebp+8) " # . prologue\n") -8199 (write-buffered *(ebp+8) " 55/push-ebp\n") -8200 (write-buffered *(ebp+8) " 89/<- %ebp 4/r32/esp\n") -8201 $emit-subx-prologue:end: -8202 # . epilogue -8203 89/<- %esp 5/r32/ebp -8204 5d/pop-to-ebp -8205 c3/return -8206 -8207 emit-subx-epilogue: # out: (addr buffered-file) -8208 # . prologue -8209 55/push-ebp -8210 89/<- %ebp 4/r32/esp -8211 # -8212 (write-buffered *(ebp+8) " # . epilogue\n") -8213 (write-buffered *(ebp+8) " 89/<- %esp 5/r32/ebp\n") -8214 (write-buffered *(ebp+8) " 5d/pop-to-ebp\n") -8215 (write-buffered *(ebp+8) " c3/return\n") -8216 $emit-subx-epilogue:end: -8217 # . epilogue -8218 89/<- %esp 5/r32/ebp -8219 5d/pop-to-ebp -8220 c3/return +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 +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 +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 +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 +8401 89/<- %esi 4/r32/esp +8402 # var stmt/esi: statement +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 diff --git a/html/apps/pack.subx.html b/html/apps/pack.subx.html index ac2e8513..6cba91b4 100644 --- a/html/apps/pack.subx.html +++ b/html/apps/pack.subx.html @@ -381,7 +381,7 @@ if ('onhashchange' in window) { 422 # write nothing to input 423 # subx-pack(_test-input-buffered-file, _test-output-buffered-file) 424 # . . push args - 425 68/push _test-output-buffered-file/imm32 + 425 68/push _test-output-buffered-file/imm32 426 68/push _test-input-buffered-file/imm32 427 # . . call 428 e8/call subx-pack/disp32 @@ -390,7 +390,7 @@ if ('onhashchange' in window) { 431 # check that the line just passed through 432 # . flush(_test-output-buffered-file) 433 # . . push args - 434 68/push _test-output-buffered-file/imm32 + 434 68/push _test-output-buffered-file/imm32 435 # . . call 436 e8/call flush/disp32 437 # . . discard args @@ -454,7 +454,7 @@ if ('onhashchange' in window) { 495 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 496 # subx-pack(_test-input-buffered-file, _test-output-buffered-file) 497 # . . push args - 498 68/push _test-output-buffered-file/imm32 + 498 68/push _test-output-buffered-file/imm32 499 68/push _test-input-buffered-file/imm32 500 # . . call 501 e8/call subx-pack/disp32 @@ -463,7 +463,7 @@ if ('onhashchange' in window) { 504 # check that the line just passed through 505 # . flush(_test-output-buffered-file) 506 # . . push args - 507 68/push _test-output-buffered-file/imm32 + 507 68/push _test-output-buffered-file/imm32 508 # . . call 509 e8/call flush/disp32 510 # . . discard args @@ -527,7 +527,7 @@ if ('onhashchange' in window) { 568 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 569 # subx-pack(_test-input-buffered-file, _test-output-buffered-file) 570 # . . push args - 571 68/push _test-output-buffered-file/imm32 + 571 68/push _test-output-buffered-file/imm32 572 68/push _test-input-buffered-file/imm32 573 # . . call 574 e8/call subx-pack/disp32 @@ -536,7 +536,7 @@ if ('onhashchange' in window) { 577 # check that the line just passed through 578 # . flush(_test-output-buffered-file) 579 # . . push args - 580 68/push _test-output-buffered-file/imm32 + 580 68/push _test-output-buffered-file/imm32 581 # . . call 582 e8/call flush/disp32 583 # . . discard args @@ -619,7 +619,7 @@ if ('onhashchange' in window) { 660 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 661 # subx-pack(_test-input-buffered-file, _test-output-buffered-file) 662 # . . push args - 663 68/push _test-output-buffered-file/imm32 + 663 68/push _test-output-buffered-file/imm32 664 68/push _test-input-buffered-file/imm32 665 # . . call 666 e8/call subx-pack/disp32 @@ -629,7 +629,7 @@ if ('onhashchange' in window) { 670 +-- 26 lines: #? # debug print --------------------------------------------------------------------------------------------------------------------------- 696 # . flush(_test-output-buffered-file) 697 # . . push args - 698 68/push _test-output-buffered-file/imm32 + 698 68/push _test-output-buffered-file/imm32 699 # . . call 700 e8/call flush/disp32 701 # . . discard args @@ -748,7 +748,7 @@ if ('onhashchange' in window) { 814 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 815 # subx-pack(_test-input-buffered-file, _test-output-buffered-file) 816 # . . push args - 817 68/push _test-output-buffered-file/imm32 + 817 68/push _test-output-buffered-file/imm32 818 68/push _test-input-buffered-file/imm32 819 # . . call 820 e8/call subx-pack/disp32 @@ -763,7 +763,7 @@ if ('onhashchange' in window) { 829 +-- 26 lines: #? # debug print --------------------------------------------------------------------------------------------------------------------------- 855 # . flush(_test-output-buffered-file) 856 # . . push args - 857 68/push _test-output-buffered-file/imm32 + 857 68/push _test-output-buffered-file/imm32 858 # . . call 859 e8/call flush/disp32 860 # . . discard args @@ -1008,7 +1008,7 @@ if ('onhashchange' in window) { 1163 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1164 # convert-data(_test-input-stream, _test-output-buffered-file) 1165 # . . push args -1166 68/push _test-output-buffered-file/imm32 +1166 68/push _test-output-buffered-file/imm32 1167 68/push _test-input-stream/imm32 1168 # . . call 1169 e8/call convert-data/disp32 @@ -1017,7 +1017,7 @@ if ('onhashchange' in window) { 1172 # check that the line just passed through 1173 # . flush(_test-output-buffered-file) 1174 # . . push args -1175 68/push _test-output-buffered-file/imm32 +1175 68/push _test-output-buffered-file/imm32 1176 # . . call 1177 e8/call flush/disp32 1178 # . . discard args @@ -1075,7 +1075,7 @@ if ('onhashchange' in window) { 1255 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1256 # convert-data(_test-input-stream, _test-output-buffered-file) 1257 # . . push args -1258 68/push _test-output-buffered-file/imm32 +1258 68/push _test-output-buffered-file/imm32 1259 68/push _test-input-stream/imm32 1260 # . . call 1261 e8/call convert-data/disp32 @@ -1084,7 +1084,7 @@ if ('onhashchange' in window) { 1264 # check that the line just passed through 1265 # . flush(_test-output-buffered-file) 1266 # . . push args -1267 68/push _test-output-buffered-file/imm32 +1267 68/push _test-output-buffered-file/imm32 1268 # . . call 1269 e8/call flush/disp32 1270 # . . discard args @@ -1142,7 +1142,7 @@ if ('onhashchange' in window) { 1322 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1323 # convert-data(_test-input-stream, _test-output-buffered-file) 1324 # . . push args -1325 68/push _test-output-buffered-file/imm32 +1325 68/push _test-output-buffered-file/imm32 1326 68/push _test-input-stream/imm32 1327 # . . call 1328 e8/call convert-data/disp32 @@ -1151,7 +1151,7 @@ if ('onhashchange' in window) { 1331 # check that the line just passed through 1332 # . flush(_test-output-buffered-file) 1333 # . . push args -1334 68/push _test-output-buffered-file/imm32 +1334 68/push _test-output-buffered-file/imm32 1335 # . . call 1336 e8/call flush/disp32 1337 # . . discard args @@ -1208,7 +1208,7 @@ if ('onhashchange' in window) { 1388 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1389 # convert-data(_test-input-stream, _test-output-buffered-file) 1390 # . . push args -1391 68/push _test-output-buffered-file/imm32 +1391 68/push _test-output-buffered-file/imm32 1392 68/push _test-input-stream/imm32 1393 # . . call 1394 e8/call convert-data/disp32 @@ -1217,7 +1217,7 @@ if ('onhashchange' in window) { 1397 # check that 4 bytes were written 1398 # . flush(_test-output-buffered-file) 1399 # . . push args -1400 68/push _test-output-buffered-file/imm32 +1400 68/push _test-output-buffered-file/imm32 1401 # . . call 1402 e8/call flush/disp32 1403 # . . discard args @@ -1275,7 +1275,7 @@ if ('onhashchange' in window) { 1455 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1456 # convert-data(_test-input-stream, _test-output-buffered-file) 1457 # . . push args -1458 68/push _test-output-buffered-file/imm32 +1458 68/push _test-output-buffered-file/imm32 1459 68/push _test-input-stream/imm32 1460 # . . call 1461 e8/call convert-data/disp32 @@ -1284,7 +1284,7 @@ if ('onhashchange' in window) { 1464 # check that a single byte was written (imm16 is not a valid operand type) 1465 # . flush(_test-output-buffered-file) 1466 # . . push args -1467 68/push _test-output-buffered-file/imm32 +1467 68/push _test-output-buffered-file/imm32 1468 # . . call 1469 e8/call flush/disp32 1470 # . . discard args @@ -1341,7 +1341,7 @@ if ('onhashchange' in window) { 1521 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1522 # convert-data(_test-input-stream, _test-output-buffered-file) 1523 # . . push args -1524 68/push _test-output-buffered-file/imm32 +1524 68/push _test-output-buffered-file/imm32 1525 68/push _test-input-stream/imm32 1526 # . . call 1527 e8/call convert-data/disp32 @@ -1350,7 +1350,7 @@ if ('onhashchange' in window) { 1530 # check output 1531 # . flush(_test-output-buffered-file) 1532 # . . push args -1533 68/push _test-output-buffered-file/imm32 +1533 68/push _test-output-buffered-file/imm32 1534 # . . call 1535 e8/call flush/disp32 1536 # . . discard args @@ -1407,7 +1407,7 @@ if ('onhashchange' in window) { 1587 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1588 # convert-data(_test-input-stream, _test-output-buffered-file) 1589 # . . push args -1590 68/push _test-output-buffered-file/imm32 +1590 68/push _test-output-buffered-file/imm32 1591 68/push _test-input-stream/imm32 1592 # . . call 1593 e8/call convert-data/disp32 @@ -1416,7 +1416,7 @@ if ('onhashchange' in window) { 1596 # check output 1597 # . flush(_test-output-buffered-file) 1598 # . . push args -1599 68/push _test-output-buffered-file/imm32 +1599 68/push _test-output-buffered-file/imm32 1600 # . . call 1601 e8/call flush/disp32 1602 # . . discard args @@ -1473,7 +1473,7 @@ if ('onhashchange' in window) { 1653 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1654 # convert-data(_test-input-stream, _test-output-buffered-file) 1655 # . . push args -1656 68/push _test-output-buffered-file/imm32 +1656 68/push _test-output-buffered-file/imm32 1657 68/push _test-input-stream/imm32 1658 # . . call 1659 e8/call convert-data/disp32 @@ -1482,7 +1482,7 @@ if ('onhashchange' in window) { 1662 # check output 1663 # . flush(_test-output-buffered-file) 1664 # . . push args -1665 68/push _test-output-buffered-file/imm32 +1665 68/push _test-output-buffered-file/imm32 1666 # . . call 1667 e8/call flush/disp32 1668 # . . discard args @@ -1540,7 +1540,7 @@ if ('onhashchange' in window) { 1745 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1746 # convert-data(_test-input-stream, _test-output-buffered-file) 1747 # . . push args -1748 68/push _test-output-buffered-file/imm32 +1748 68/push _test-output-buffered-file/imm32 1749 68/push _test-input-stream/imm32 1750 # . . call 1751 e8/call convert-data/disp32 @@ -1549,7 +1549,7 @@ if ('onhashchange' in window) { 1754 # check output 1755 # . flush(_test-output-buffered-file) 1756 # . . push args -1757 68/push _test-output-buffered-file/imm32 +1757 68/push _test-output-buffered-file/imm32 1758 # . . call 1759 e8/call flush/disp32 1760 # . . discard args @@ -2856,7 +2856,7 @@ if ('onhashchange' in window) { 3349 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3350 # convert-instruction(_test-input-stream, _test-output-buffered-file) 3351 # . . push args -3352 68/push _test-output-buffered-file/imm32 +3352 68/push _test-output-buffered-file/imm32 3353 68/push _test-input-stream/imm32 3354 # . . call 3355 e8/call convert-instruction/disp32 @@ -2865,7 +2865,7 @@ if ('onhashchange' in window) { 3358 # check that the line just passed through 3359 # . flush(_test-output-buffered-file) 3360 # . . push args -3361 68/push _test-output-buffered-file/imm32 +3361 68/push _test-output-buffered-file/imm32 3362 # . . call 3363 e8/call flush/disp32 3364 # . . discard args @@ -2922,7 +2922,7 @@ if ('onhashchange' in window) { 3415 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3416 # convert-instruction(_test-input-stream, _test-output-buffered-file) 3417 # . . push args -3418 68/push _test-output-buffered-file/imm32 +3418 68/push _test-output-buffered-file/imm32 3419 68/push _test-input-stream/imm32 3420 # . . call 3421 e8/call convert-instruction/disp32 @@ -2931,7 +2931,7 @@ if ('onhashchange' in window) { 3424 # check that the line just passed through 3425 # . flush(_test-output-buffered-file) 3426 # . . push args -3427 68/push _test-output-buffered-file/imm32 +3427 68/push _test-output-buffered-file/imm32 3428 # . . call 3429 e8/call flush/disp32 3430 # . . discard args @@ -2988,7 +2988,7 @@ if ('onhashchange' in window) { 3481 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3482 # convert-instruction(_test-input-stream, _test-output-buffered-file) 3483 # . . push args -3484 68/push _test-output-buffered-file/imm32 +3484 68/push _test-output-buffered-file/imm32 3485 68/push _test-input-stream/imm32 3486 # . . call 3487 e8/call convert-instruction/disp32 @@ -2997,7 +2997,7 @@ if ('onhashchange' in window) { 3490 # check output 3491 # . flush(_test-output-buffered-file) 3492 # . . push args -3493 68/push _test-output-buffered-file/imm32 +3493 68/push _test-output-buffered-file/imm32 3494 # . . call 3495 e8/call flush/disp32 3496 # . . discard args @@ -3055,7 +3055,7 @@ if ('onhashchange' in window) { 3573 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3574 # convert-instruction(_test-input-stream, _test-output-buffered-file) 3575 # . . push args -3576 68/push _test-output-buffered-file/imm32 +3576 68/push _test-output-buffered-file/imm32 3577 68/push _test-input-stream/imm32 3578 # . . call 3579 e8/call convert-instruction/disp32 @@ -3064,7 +3064,7 @@ if ('onhashchange' in window) { 3582 # check output 3583 # . flush(_test-output-buffered-file) 3584 # . . push args -3585 68/push _test-output-buffered-file/imm32 +3585 68/push _test-output-buffered-file/imm32 3586 # . . call 3587 e8/call flush/disp32 3588 # . . discard args @@ -3122,7 +3122,7 @@ if ('onhashchange' in window) { 3665 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3666 # convert-instruction(_test-input-stream, _test-output-buffered-file) 3667 # . . push args -3668 68/push _test-output-buffered-file/imm32 +3668 68/push _test-output-buffered-file/imm32 3669 68/push _test-input-stream/imm32 3670 # . . call 3671 e8/call convert-instruction/disp32 @@ -3131,7 +3131,7 @@ if ('onhashchange' in window) { 3674 # check output 3675 # . flush(_test-output-buffered-file) 3676 # . . push args -3677 68/push _test-output-buffered-file/imm32 +3677 68/push _test-output-buffered-file/imm32 3678 # . . call 3679 e8/call flush/disp32 3680 # . . discard args @@ -3189,7 +3189,7 @@ if ('onhashchange' in window) { 3757 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3758 # convert-instruction(_test-input-stream, _test-output-buffered-file) 3759 # . . push args -3760 68/push _test-output-buffered-file/imm32 +3760 68/push _test-output-buffered-file/imm32 3761 68/push _test-input-stream/imm32 3762 # . . call 3763 e8/call convert-instruction/disp32 @@ -3198,7 +3198,7 @@ if ('onhashchange' in window) { 3766 # check output 3767 # . flush(_test-output-buffered-file) 3768 # . . push args -3769 68/push _test-output-buffered-file/imm32 +3769 68/push _test-output-buffered-file/imm32 3770 # . . call 3771 e8/call flush/disp32 3772 # . . discard args @@ -3256,7 +3256,7 @@ if ('onhashchange' in window) { 3849 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3850 # convert-instruction(_test-input-stream, _test-output-buffered-file) 3851 # . . push args -3852 68/push _test-output-buffered-file/imm32 +3852 68/push _test-output-buffered-file/imm32 3853 68/push _test-input-stream/imm32 3854 # . . call 3855 e8/call convert-instruction/disp32 @@ -3265,7 +3265,7 @@ if ('onhashchange' in window) { 3858 # check output 3859 # . flush(_test-output-buffered-file) 3860 # . . push args -3861 68/push _test-output-buffered-file/imm32 +3861 68/push _test-output-buffered-file/imm32 3862 # . . call 3863 e8/call flush/disp32 3864 # . . discard args @@ -3323,7 +3323,7 @@ if ('onhashchange' in window) { 3941 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3942 # convert-instruction(_test-input-stream, _test-output-buffered-file) 3943 # . . push args -3944 68/push _test-output-buffered-file/imm32 +3944 68/push _test-output-buffered-file/imm32 3945 68/push _test-input-stream/imm32 3946 # . . call 3947 e8/call convert-instruction/disp32 @@ -3332,7 +3332,7 @@ if ('onhashchange' in window) { 3950 # check output 3951 # . flush(_test-output-buffered-file) 3952 # . . push args -3953 68/push _test-output-buffered-file/imm32 +3953 68/push _test-output-buffered-file/imm32 3954 # . . call 3955 e8/call flush/disp32 3956 # . . discard args @@ -3390,7 +3390,7 @@ if ('onhashchange' in window) { 4033 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4034 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4035 # . . push args -4036 68/push _test-output-buffered-file/imm32 +4036 68/push _test-output-buffered-file/imm32 4037 68/push _test-input-stream/imm32 4038 # . . call 4039 e8/call convert-instruction/disp32 @@ -3399,7 +3399,7 @@ if ('onhashchange' in window) { 4042 # check output 4043 # . flush(_test-output-buffered-file) 4044 # . . push args -4045 68/push _test-output-buffered-file/imm32 +4045 68/push _test-output-buffered-file/imm32 4046 # . . call 4047 e8/call flush/disp32 4048 # . . discard args @@ -3457,7 +3457,7 @@ if ('onhashchange' in window) { 4125 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4126 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4127 # . . push args -4128 68/push _test-output-buffered-file/imm32 +4128 68/push _test-output-buffered-file/imm32 4129 68/push _test-input-stream/imm32 4130 # . . call 4131 e8/call convert-instruction/disp32 @@ -3466,7 +3466,7 @@ if ('onhashchange' in window) { 4134 # check output 4135 # . flush(_test-output-buffered-file) 4136 # . . push args -4137 68/push _test-output-buffered-file/imm32 +4137 68/push _test-output-buffered-file/imm32 4138 # . . call 4139 e8/call flush/disp32 4140 # . . discard args @@ -3524,7 +3524,7 @@ if ('onhashchange' in window) { 4217 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4218 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4219 # . . push args -4220 68/push _test-output-buffered-file/imm32 +4220 68/push _test-output-buffered-file/imm32 4221 68/push _test-input-stream/imm32 4222 # . . call 4223 e8/call convert-instruction/disp32 @@ -3533,7 +3533,7 @@ if ('onhashchange' in window) { 4226 # check output 4227 # . flush(_test-output-buffered-file) 4228 # . . push args -4229 68/push _test-output-buffered-file/imm32 +4229 68/push _test-output-buffered-file/imm32 4230 # . . call 4231 e8/call flush/disp32 4232 # . . discard args @@ -3591,7 +3591,7 @@ if ('onhashchange' in window) { 4309 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4310 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4311 # . . push args -4312 68/push _test-output-buffered-file/imm32 +4312 68/push _test-output-buffered-file/imm32 4313 68/push _test-input-stream/imm32 4314 # . . call 4315 e8/call convert-instruction/disp32 @@ -3600,7 +3600,7 @@ if ('onhashchange' in window) { 4318 # check output 4319 # . flush(_test-output-buffered-file) 4320 # . . push args -4321 68/push _test-output-buffered-file/imm32 +4321 68/push _test-output-buffered-file/imm32 4322 # . . call 4323 e8/call flush/disp32 4324 # . . discard args @@ -3657,7 +3657,7 @@ if ('onhashchange' in window) { 4400 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4401 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4402 # . . push args -4403 68/push _test-output-buffered-file/imm32 +4403 68/push _test-output-buffered-file/imm32 4404 68/push _test-input-stream/imm32 4405 # . . call 4406 e8/call convert-instruction/disp32 @@ -3665,7 +3665,7 @@ if ('onhashchange' in window) { 4408 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4409 # . flush(_test-output-buffered-file) 4410 # . . push args -4411 68/push _test-output-buffered-file/imm32 +4411 68/push _test-output-buffered-file/imm32 4412 # . . call 4413 e8/call flush/disp32 4414 # . . discard args @@ -3724,7 +3724,7 @@ if ('onhashchange' in window) { 4492 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4493 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4494 # . . push args -4495 68/push _test-output-buffered-file/imm32 +4495 68/push _test-output-buffered-file/imm32 4496 68/push _test-input-stream/imm32 4497 # . . call 4498 e8/call convert-instruction/disp32 @@ -3733,7 +3733,7 @@ if ('onhashchange' in window) { 4501 # check output 4502 # . flush(_test-output-buffered-file) 4503 # . . push args -4504 68/push _test-output-buffered-file/imm32 +4504 68/push _test-output-buffered-file/imm32 4505 # . . call 4506 e8/call flush/disp32 4507 # . . discard args @@ -3791,7 +3791,7 @@ if ('onhashchange' in window) { 4584 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4585 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4586 # . . push args -4587 68/push _test-output-buffered-file/imm32 +4587 68/push _test-output-buffered-file/imm32 4588 68/push _test-input-stream/imm32 4589 # . . call 4590 e8/call convert-instruction/disp32 @@ -3800,7 +3800,7 @@ if ('onhashchange' in window) { 4593 # check output 4594 # . flush(_test-output-buffered-file) 4595 # . . push args -4596 68/push _test-output-buffered-file/imm32 +4596 68/push _test-output-buffered-file/imm32 4597 # . . call 4598 e8/call flush/disp32 4599 # . . discard args @@ -3858,7 +3858,7 @@ if ('onhashchange' in window) { 4676 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4677 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4678 # . . push args -4679 68/push _test-output-buffered-file/imm32 +4679 68/push _test-output-buffered-file/imm32 4680 68/push _test-input-stream/imm32 4681 # . . call 4682 e8/call convert-instruction/disp32 @@ -3867,7 +3867,7 @@ if ('onhashchange' in window) { 4685 # check output 4686 # . flush(_test-output-buffered-file) 4687 # . . push args -4688 68/push _test-output-buffered-file/imm32 +4688 68/push _test-output-buffered-file/imm32 4689 # . . call 4690 e8/call flush/disp32 4691 # . . discard args @@ -3925,7 +3925,7 @@ if ('onhashchange' in window) { 4768 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4769 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4770 # . . push args -4771 68/push _test-output-buffered-file/imm32 +4771 68/push _test-output-buffered-file/imm32 4772 68/push _test-input-stream/imm32 4773 # . . call 4774 e8/call convert-instruction/disp32 @@ -3934,7 +3934,7 @@ if ('onhashchange' in window) { 4777 # check output 4778 # . flush(_test-output-buffered-file) 4779 # . . push args -4780 68/push _test-output-buffered-file/imm32 +4780 68/push _test-output-buffered-file/imm32 4781 # . . call 4782 e8/call flush/disp32 4783 # . . discard args @@ -3992,7 +3992,7 @@ if ('onhashchange' in window) { 4860 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4861 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4862 # . . push args -4863 68/push _test-output-buffered-file/imm32 +4863 68/push _test-output-buffered-file/imm32 4864 68/push _test-input-stream/imm32 4865 # . . call 4866 e8/call convert-instruction/disp32 @@ -4001,7 +4001,7 @@ if ('onhashchange' in window) { 4869 # check output 4870 # . flush(_test-output-buffered-file) 4871 # . . push args -4872 68/push _test-output-buffered-file/imm32 +4872 68/push _test-output-buffered-file/imm32 4873 # . . call 4874 e8/call flush/disp32 4875 # . . discard args @@ -4059,7 +4059,7 @@ if ('onhashchange' in window) { 4952 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4953 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4954 # . . push args -4955 68/push _test-output-buffered-file/imm32 +4955 68/push _test-output-buffered-file/imm32 4956 68/push _test-input-stream/imm32 4957 # . . call 4958 e8/call convert-instruction/disp32 @@ -4068,7 +4068,7 @@ if ('onhashchange' in window) { 4961 # check output 4962 # . flush(_test-output-buffered-file) 4963 # . . push args -4964 68/push _test-output-buffered-file/imm32 +4964 68/push _test-output-buffered-file/imm32 4965 # . . call 4966 e8/call flush/disp32 4967 # . . discard args @@ -4126,7 +4126,7 @@ if ('onhashchange' in window) { 5044 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5045 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5046 # . . push args -5047 68/push _test-output-buffered-file/imm32 +5047 68/push _test-output-buffered-file/imm32 5048 68/push _test-input-stream/imm32 5049 # . . call 5050 e8/call convert-instruction/disp32 @@ -4135,7 +4135,7 @@ if ('onhashchange' in window) { 5053 # check output 5054 # . flush(_test-output-buffered-file) 5055 # . . push args -5056 68/push _test-output-buffered-file/imm32 +5056 68/push _test-output-buffered-file/imm32 5057 # . . call 5058 e8/call flush/disp32 5059 # . . discard args @@ -4193,7 +4193,7 @@ if ('onhashchange' in window) { 5136 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5137 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5138 # . . push args -5139 68/push _test-output-buffered-file/imm32 +5139 68/push _test-output-buffered-file/imm32 5140 68/push _test-input-stream/imm32 5141 # . . call 5142 e8/call convert-instruction/disp32 @@ -4202,7 +4202,7 @@ if ('onhashchange' in window) { 5145 # check output 5146 # . flush(_test-output-buffered-file) 5147 # . . push args -5148 68/push _test-output-buffered-file/imm32 +5148 68/push _test-output-buffered-file/imm32 5149 # . . call 5150 e8/call flush/disp32 5151 # . . discard args @@ -4260,7 +4260,7 @@ if ('onhashchange' in window) { 5228 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5229 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5230 # . . push args -5231 68/push _test-output-buffered-file/imm32 +5231 68/push _test-output-buffered-file/imm32 5232 68/push _test-input-stream/imm32 5233 # . . call 5234 e8/call convert-instruction/disp32 @@ -4269,7 +4269,7 @@ if ('onhashchange' in window) { 5237 # check output 5238 # . flush(_test-output-buffered-file) 5239 # . . push args -5240 68/push _test-output-buffered-file/imm32 +5240 68/push _test-output-buffered-file/imm32 5241 # . . call 5242 e8/call flush/disp32 5243 # . . discard args @@ -4327,7 +4327,7 @@ if ('onhashchange' in window) { 5320 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5321 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5322 # . . push args -5323 68/push _test-output-buffered-file/imm32 +5323 68/push _test-output-buffered-file/imm32 5324 68/push _test-input-stream/imm32 5325 # . . call 5326 e8/call convert-instruction/disp32 @@ -4336,7 +4336,7 @@ if ('onhashchange' in window) { 5329 # check output 5330 # . flush(_test-output-buffered-file) 5331 # . . push args -5332 68/push _test-output-buffered-file/imm32 +5332 68/push _test-output-buffered-file/imm32 5333 # . . call 5334 e8/call flush/disp32 5335 # . . discard args @@ -4394,7 +4394,7 @@ if ('onhashchange' in window) { 5412 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5413 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5414 # . . push args -5415 68/push _test-output-buffered-file/imm32 +5415 68/push _test-output-buffered-file/imm32 5416 68/push _test-input-stream/imm32 5417 # . . call 5418 e8/call convert-instruction/disp32 @@ -4403,7 +4403,7 @@ if ('onhashchange' in window) { 5421 # check output 5422 # . flush(_test-output-buffered-file) 5423 # . . push args -5424 68/push _test-output-buffered-file/imm32 +5424 68/push _test-output-buffered-file/imm32 5425 # . . call 5426 e8/call flush/disp32 5427 # . . discard args @@ -4461,7 +4461,7 @@ if ('onhashchange' in window) { 5504 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5505 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5506 # . . push args -5507 68/push _test-output-buffered-file/imm32 +5507 68/push _test-output-buffered-file/imm32 5508 68/push _test-input-stream/imm32 5509 # . . call 5510 e8/call convert-instruction/disp32 @@ -4470,7 +4470,7 @@ if ('onhashchange' in window) { 5513 # check output 5514 # . flush(_test-output-buffered-file) 5515 # . . push args -5516 68/push _test-output-buffered-file/imm32 +5516 68/push _test-output-buffered-file/imm32 5517 # . . call 5518 e8/call flush/disp32 5519 # . . discard args @@ -4528,7 +4528,7 @@ if ('onhashchange' in window) { 5596 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5597 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5598 # . . push args -5599 68/push _test-output-buffered-file/imm32 +5599 68/push _test-output-buffered-file/imm32 5600 68/push _test-input-stream/imm32 5601 # . . call 5602 e8/call convert-instruction/disp32 @@ -4537,7 +4537,7 @@ if ('onhashchange' in window) { 5605 # check output 5606 # . flush(_test-output-buffered-file) 5607 # . . push args -5608 68/push _test-output-buffered-file/imm32 +5608 68/push _test-output-buffered-file/imm32 5609 # . . call 5610 e8/call flush/disp32 5611 # . . discard args @@ -4596,7 +4596,7 @@ if ('onhashchange' in window) { 5689 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5690 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5691 # . . push args -5692 68/push _test-output-buffered-file/imm32 +5692 68/push _test-output-buffered-file/imm32 5693 68/push _test-input-stream/imm32 5694 # . . call 5695 e8/call convert-instruction/disp32 @@ -4605,7 +4605,7 @@ if ('onhashchange' in window) { 5698 # check output 5699 # . flush(_test-output-buffered-file) 5700 # . . push args -5701 68/push _test-output-buffered-file/imm32 +5701 68/push _test-output-buffered-file/imm32 5702 # . . call 5703 e8/call flush/disp32 5704 # . . discard args @@ -4664,7 +4664,7 @@ if ('onhashchange' in window) { 5782 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5783 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5784 # . . push args -5785 68/push _test-output-buffered-file/imm32 +5785 68/push _test-output-buffered-file/imm32 5786 68/push _test-input-stream/imm32 5787 # . . call 5788 e8/call convert-instruction/disp32 @@ -4673,7 +4673,7 @@ if ('onhashchange' in window) { 5791 # check output 5792 # . flush(_test-output-buffered-file) 5793 # . . push args -5794 68/push _test-output-buffered-file/imm32 +5794 68/push _test-output-buffered-file/imm32 5795 # . . call 5796 e8/call flush/disp32 5797 # . . discard args diff --git a/html/apps/sigils.subx.html b/html/apps/sigils.subx.html index 5d023370..865a9db3 100644 --- a/html/apps/sigils.subx.html +++ b/html/apps/sigils.subx.html @@ -497,7 +497,7 @@ if ('onhashchange' in window) { 474 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 475 # subx-sigils(_test-input-buffered-file, _test-output-buffered-file) 476 # . . push args - 477 68/push _test-output-buffered-file/imm32 + 477 68/push _test-output-buffered-file/imm32 478 68/push _test-input-buffered-file/imm32 479 # . . call 480 e8/call subx-sigils/disp32 @@ -506,7 +506,7 @@ if ('onhashchange' in window) { 483 # check that the line just passed through 484 # . flush(_test-output-buffered-file) 485 # . . push args - 486 68/push _test-output-buffered-file/imm32 + 486 68/push _test-output-buffered-file/imm32 487 # . . call 488 e8/call flush/disp32 489 # . . discard args @@ -570,7 +570,7 @@ if ('onhashchange' in window) { 572 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 573 # subx-sigils(_test-input-buffered-file, _test-output-buffered-file) 574 # . . push args - 575 68/push _test-output-buffered-file/imm32 + 575 68/push _test-output-buffered-file/imm32 576 68/push _test-input-buffered-file/imm32 577 # . . call 578 e8/call subx-sigils/disp32 @@ -579,7 +579,7 @@ if ('onhashchange' in window) { 581 # check that the line just passed through 582 # . flush(_test-output-buffered-file) 583 # . . push args - 584 68/push _test-output-buffered-file/imm32 + 584 68/push _test-output-buffered-file/imm32 585 # . . call 586 e8/call flush/disp32 587 # . . discard args @@ -643,7 +643,7 @@ if ('onhashchange' in window) { 670 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 671 # subx-sigils(_test-input-buffered-file, _test-output-buffered-file) 672 # . . push args - 673 68/push _test-output-buffered-file/imm32 + 673 68/push _test-output-buffered-file/imm32 674 68/push _test-input-buffered-file/imm32 675 # . . call 676 e8/call subx-sigils/disp32 @@ -652,7 +652,7 @@ if ('onhashchange' in window) { 679 # check that the line just passed through 680 # . flush(_test-output-buffered-file) 681 # . . push args - 682 68/push _test-output-buffered-file/imm32 + 682 68/push _test-output-buffered-file/imm32 683 # . . call 684 e8/call flush/disp32 685 # . . discard args @@ -715,7 +715,7 @@ if ('onhashchange' in window) { 742 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 743 # subx-sigils(_test-input-buffered-file, _test-output-buffered-file) 744 # . . push args - 745 68/push _test-output-buffered-file/imm32 + 745 68/push _test-output-buffered-file/imm32 746 68/push _test-input-buffered-file/imm32 747 # . . call 748 e8/call subx-sigils/disp32 @@ -724,7 +724,7 @@ if ('onhashchange' in window) { 751 # check that the line just passed through 752 # . flush(_test-output-buffered-file) 753 # . . push args - 754 68/push _test-output-buffered-file/imm32 + 754 68/push _test-output-buffered-file/imm32 755 # . . call 756 e8/call flush/disp32 757 # . . discard args @@ -788,7 +788,7 @@ if ('onhashchange' in window) { 840 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 841 # subx-sigils(_test-input-buffered-file, _test-output-buffered-file) 842 # . . push args - 843 68/push _test-output-buffered-file/imm32 + 843 68/push _test-output-buffered-file/imm32 844 68/push _test-input-buffered-file/imm32 845 # . . call 846 e8/call subx-sigils/disp32 @@ -797,7 +797,7 @@ if ('onhashchange' in window) { 849 # check that the line just passed through 850 # . flush(_test-output-buffered-file) 851 # . . push args - 852 68/push _test-output-buffered-file/imm32 + 852 68/push _test-output-buffered-file/imm32 853 # . . call 854 e8/call flush/disp32 855 # . . discard args @@ -860,7 +860,7 @@ if ('onhashchange' in window) { 912 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 913 # subx-sigils(_test-input-buffered-file, _test-output-buffered-file) 914 # . . push args - 915 68/push _test-output-buffered-file/imm32 + 915 68/push _test-output-buffered-file/imm32 916 68/push _test-input-buffered-file/imm32 917 # . . call 918 e8/call subx-sigils/disp32 @@ -869,7 +869,7 @@ if ('onhashchange' in window) { 921 # check that the line just passed through 922 # . flush(_test-output-buffered-file) 923 # . . push args - 924 68/push _test-output-buffered-file/imm32 + 924 68/push _test-output-buffered-file/imm32 925 # . . call 926 e8/call flush/disp32 927 # . . discard args @@ -933,7 +933,7 @@ if ('onhashchange' in window) { 1010 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1011 # subx-sigils(_test-input-buffered-file, _test-output-buffered-file) 1012 # . . push args -1013 68/push _test-output-buffered-file/imm32 +1013 68/push _test-output-buffered-file/imm32 1014 68/push _test-input-buffered-file/imm32 1015 # . . call 1016 e8/call subx-sigils/disp32 @@ -942,7 +942,7 @@ if ('onhashchange' in window) { 1019 # check that the line just passed through 1020 # . flush(_test-output-buffered-file) 1021 # . . push args -1022 68/push _test-output-buffered-file/imm32 +1022 68/push _test-output-buffered-file/imm32 1023 # . . call 1024 e8/call flush/disp32 1025 # . . discard args @@ -1007,7 +1007,7 @@ if ('onhashchange' in window) { 1109 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1110 # subx-sigils(_test-input-buffered-file, _test-output-buffered-file) 1111 # . . push args -1112 68/push _test-output-buffered-file/imm32 +1112 68/push _test-output-buffered-file/imm32 1113 68/push _test-input-buffered-file/imm32 1114 # . . call 1115 e8/call subx-sigils/disp32 @@ -1016,7 +1016,7 @@ if ('onhashchange' in window) { 1118 # check that the line just passed through 1119 # . flush(_test-output-buffered-file) 1120 # . . push args -1121 68/push _test-output-buffered-file/imm32 +1121 68/push _test-output-buffered-file/imm32 1122 # . . call 1123 e8/call flush/disp32 1124 # . . discard args @@ -1080,7 +1080,7 @@ if ('onhashchange' in window) { 1207 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1208 # subx-sigils(_test-input-buffered-file, _test-output-buffered-file) 1209 # . . push args -1210 68/push _test-output-buffered-file/imm32 +1210 68/push _test-output-buffered-file/imm32 1211 68/push _test-input-buffered-file/imm32 1212 # . . call 1213 e8/call subx-sigils/disp32 @@ -1089,7 +1089,7 @@ if ('onhashchange' in window) { 1216 # check that the line just passed through 1217 # . flush(_test-output-buffered-file) 1218 # . . push args -1219 68/push _test-output-buffered-file/imm32 +1219 68/push _test-output-buffered-file/imm32 1220 # . . call 1221 e8/call flush/disp32 1222 # . . discard args @@ -1153,7 +1153,7 @@ if ('onhashchange' in window) { 1305 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1306 # subx-sigils(_test-input-buffered-file, _test-output-buffered-file) 1307 # . . push args -1308 68/push _test-output-buffered-file/imm32 +1308 68/push _test-output-buffered-file/imm32 1309 68/push _test-input-buffered-file/imm32 1310 # . . call 1311 e8/call subx-sigils/disp32 @@ -1162,7 +1162,7 @@ if ('onhashchange' in window) { 1314 # check that the line just passed through 1315 # . flush(_test-output-buffered-file) 1316 # . . push args -1317 68/push _test-output-buffered-file/imm32 +1317 68/push _test-output-buffered-file/imm32 1318 # . . call 1319 e8/call flush/disp32 1320 # . . discard args @@ -1281,14 +1281,14 @@ if ('onhashchange' in window) { 1458 # emit-direct-mode(_test-output-buffered-file, str) 1459 # . . push args 1460 51/push-ecx -1461 68/push _test-output-buffered-file/imm32 +1461 68/push _test-output-buffered-file/imm32 1462 # . . call 1463 e8/call emit-direct-mode/disp32 1464 # . . discard args 1465 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1466 # . flush(_test-output-buffered-file) 1467 # . . push args -1468 68/push _test-output-buffered-file/imm32 +1468 68/push _test-output-buffered-file/imm32 1469 # . . call 1470 e8/call flush/disp32 1471 # . . discard args @@ -1339,14 +1339,14 @@ if ('onhashchange' in window) { 1541 # emit-direct-mode(_test-output-buffered-file, str/ecx) 1542 # . . push args 1543 51/push-ecx -1544 68/push _test-output-buffered-file/imm32 +1544 68/push _test-output-buffered-file/imm32 1545 # . . call 1546 e8/call emit-direct-mode/disp32 1547 # . . discard args 1548 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1549 # . flush(_test-output-buffered-file) 1550 # . . push args -1551 68/push _test-output-buffered-file/imm32 +1551 68/push _test-output-buffered-file/imm32 1552 # . . call 1553 e8/call flush/disp32 1554 # . . discard args @@ -3117,14 +3117,14 @@ if ('onhashchange' in window) { 3344 68/push 0/imm32/.scale 3345 68/push 4/imm32/.index/none 3346 68/push 0/imm32/.base -3347 68/push _test-output-buffered-file/imm32 +3347 68/push _test-output-buffered-file/imm32 3348 # . . call 3349 e8/call emit-indirect-mode/disp32 3350 # . . discard args 3351 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp 3352 # . flush(_test-output-buffered-file) 3353 # . . push args -3354 68/push _test-output-buffered-file/imm32 +3354 68/push _test-output-buffered-file/imm32 3355 # . . call 3356 e8/call flush/disp32 3357 # . . discard args @@ -3169,14 +3169,14 @@ if ('onhashchange' in window) { 3421 68/push 0/imm32/.scale 3422 68/push 4/imm32/.index/none 3423 68/push 7/imm32/.base -3424 68/push _test-output-buffered-file/imm32 +3424 68/push _test-output-buffered-file/imm32 3425 # . . call 3426 e8/call emit-indirect-mode/disp32 3427 # . . discard args 3428 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp 3429 # . flush(_test-output-buffered-file) 3430 # . . push args -3431 68/push _test-output-buffered-file/imm32 +3431 68/push _test-output-buffered-file/imm32 3432 # . . call 3433 e8/call flush/disp32 3434 # . . discard args @@ -3221,14 +3221,14 @@ if ('onhashchange' in window) { 3498 68/push 0/imm32/.scale 3499 68/push 4/imm32/.index/none 3500 68/push 6/imm32/.base -3501 68/push _test-output-buffered-file/imm32 +3501 68/push _test-output-buffered-file/imm32 3502 # . . call 3503 e8/call emit-indirect-mode/disp32 3504 # . . discard args 3505 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp 3506 # . flush(_test-output-buffered-file) 3507 # . . push args -3508 68/push _test-output-buffered-file/imm32 +3508 68/push _test-output-buffered-file/imm32 3509 # . . call 3510 e8/call flush/disp32 3511 # . . discard args @@ -3273,14 +3273,14 @@ if ('onhashchange' in window) { 3575 68/push 0/imm32/.scale 3576 68/push 4/imm32/.index/none 3577 68/push 6/imm32/.base -3578 68/push _test-output-buffered-file/imm32 +3578 68/push _test-output-buffered-file/imm32 3579 # . . call 3580 e8/call emit-indirect-mode/disp32 3581 # . . discard args 3582 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp 3583 # . flush(_test-output-buffered-file) 3584 # . . push args -3585 68/push _test-output-buffered-file/imm32 +3585 68/push _test-output-buffered-file/imm32 3586 # . . call 3587 e8/call flush/disp32 3588 # . . discard args @@ -3325,14 +3325,14 @@ if ('onhashchange' in window) { 3652 68/push 2/imm32/.scale 3653 68/push 1/imm32/.index 3654 68/push 6/imm32/.base -3655 68/push _test-output-buffered-file/imm32 +3655 68/push _test-output-buffered-file/imm32 3656 # . . call 3657 e8/call emit-indirect-mode/disp32 3658 # . . discard args 3659 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp 3660 # . flush(_test-output-buffered-file) 3661 # . . push args -3662 68/push _test-output-buffered-file/imm32 +3662 68/push _test-output-buffered-file/imm32 3663 # . . call 3664 e8/call flush/disp32 3665 # . . discard args @@ -3377,14 +3377,14 @@ if ('onhashchange' in window) { 3729 68/push 0/imm32/.scale 3730 68/push 0/imm32/.index 3731 68/push 5/imm32/.base/ebp -3732 68/push _test-output-buffered-file/imm32 +3732 68/push _test-output-buffered-file/imm32 3733 # . . call 3734 e8/call emit-indirect-mode/disp32 3735 # . . discard args 3736 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp 3737 # . flush(_test-output-buffered-file) 3738 # . . push args -3739 68/push _test-output-buffered-file/imm32 +3739 68/push _test-output-buffered-file/imm32 3740 # . . call 3741 e8/call flush/disp32 3742 # . . discard args @@ -3429,14 +3429,14 @@ if ('onhashchange' in window) { 3806 68/push 0/imm32/.scale 3807 68/push 0/imm32/.index 3808 68/push 4/imm32/.base/esp -3809 68/push _test-output-buffered-file/imm32 +3809 68/push _test-output-buffered-file/imm32 3810 # . . call 3811 e8/call emit-indirect-mode/disp32 3812 # . . discard args 3813 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp 3814 # . flush(_test-output-buffered-file) 3815 # . . push args -3816 68/push _test-output-buffered-file/imm32 +3816 68/push _test-output-buffered-file/imm32 3817 # . . call 3818 e8/call flush/disp32 3819 # . . discard args diff --git a/html/apps/subx-params.subx.html b/html/apps/subx-params.subx.html index 2cd4ecd4..adb28457 100644 --- a/html/apps/subx-params.subx.html +++ b/html/apps/subx-params.subx.html @@ -70,7 +70,7 @@ if ('onhashchange' in window) { 16 17 # capacity of trace-stream 18 Trace-size: -19 0x80000/imm32/512KB +19 0x100000/imm32/1MB diff --git a/html/apps/survey.subx.html b/html/apps/survey.subx.html index c1fe6d8d..dc442e1f 100644 --- a/html/apps/survey.subx.html +++ b/html/apps/survey.subx.html @@ -388,7 +388,7 @@ if ('onhashchange' in window) { 532 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 533 # subx-survey(_test-input-buffered-file, _test-output-buffered-file) 534 # . . push args - 535 68/push _test-output-buffered-file/imm32 + 535 68/push _test-output-buffered-file/imm32 536 68/push _test-input-buffered-file/imm32 537 # . . call 538 e8/call subx-survey/disp32 @@ -2029,7 +2029,7 @@ if ('onhashchange' in window) { 2681 # . . push args 2682 52/push-edx 2683 51/push-ecx -2684 68/push _test-output-buffered-file/imm32 +2684 68/push _test-output-buffered-file/imm32 2685 68/push _test-input-stream/imm32 2686 # . . call 2687 e8/call emit-segments/disp32 @@ -2038,7 +2038,7 @@ if ('onhashchange' in window) { 2690 # checks 2691 # . flush(_test-output-buffered-file) 2692 # . . push args -2693 68/push _test-output-buffered-file/imm32 +2693 68/push _test-output-buffered-file/imm32 2694 # . . call 2695 e8/call flush/disp32 2696 # . . discard args @@ -2208,7 +2208,7 @@ if ('onhashchange' in window) { 2892 # . . push args 2893 52/push-edx 2894 51/push-ecx -2895 68/push _test-output-buffered-file/imm32 +2895 68/push _test-output-buffered-file/imm32 2896 68/push _test-input-stream/imm32 2897 # . . call 2898 e8/call emit-segments/disp32 @@ -2217,7 +2217,7 @@ if ('onhashchange' in window) { 2901 # checks 2902 # . flush(_test-output-buffered-file) 2903 # . . push args -2904 68/push _test-output-buffered-file/imm32 +2904 68/push _test-output-buffered-file/imm32 2905 # . . call 2906 e8/call flush/disp32 2907 # . . discard args @@ -2378,7 +2378,7 @@ if ('onhashchange' in window) { 3094 # . . push args 3095 52/push-edx 3096 51/push-ecx -3097 68/push _test-output-buffered-file/imm32 +3097 68/push _test-output-buffered-file/imm32 3098 68/push _test-input-stream/imm32 3099 # . . call 3100 e8/call emit-segments/disp32 @@ -2387,7 +2387,7 @@ if ('onhashchange' in window) { 3103 # checks 3104 # . flush(_test-output-buffered-file) 3105 # . . push args -3106 68/push _test-output-buffered-file/imm32 +3106 68/push _test-output-buffered-file/imm32 3107 # . . call 3108 e8/call flush/disp32 3109 # . . discard args -- cgit 1.4.1-2-gfad0