From ace5351a9b03b44c4582a060ba1060b01d25adb9 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Fri, 24 Apr 2020 19:51:51 -0700 Subject: 6210 --- html/apps/mu.subx.html | 21810 ++++++++++++++++++++++++----------------------- 1 file changed, 10986 insertions(+), 10824 deletions(-) (limited to 'html/apps') diff --git a/html/apps/mu.subx.html b/html/apps/mu.subx.html index ae00ba3e..bdcf4a03 100644 --- a/html/apps/mu.subx.html +++ b/html/apps/mu.subx.html @@ -79,7 +79,7 @@ if ('onhashchange' in window) { 17 # (e.g. array indexing always checks bounds) 18 19 # == Language description - 20 # A program is a sequence of function definitions. + 20 # A program is a sequence of function and type definitions. 21 # 22 # Function example: 23 # fn foo n: int -> result/eax: int { @@ -321,7 +321,7 @@ if ('onhashchange' in window) { 259 260 Function-name: # (handle array byte) 261 0/imm32 - 262 Function-subx-name: # (handle array byte) + 262 _Function-unused: 263 4/imm32 264 Function-inouts: # (handle list var) 265 8/imm32 @@ -425,10869 +425,11031 @@ if ('onhashchange' in window) { 363 # However, there's no need for singletons, so we can assume (int) == int 364 # - if x->right == nil, x is an atom 365 # - x->left contains either a pointer to a pair, or an atomic type-id directly. - 366 # type ids will be less than 0x10000 (MAX_TYPE_ID). - 367 - 368 Tree-left: # either type-id or (addr tree type-id) - 369 0/imm32 - 370 Tree-right: # (addr tree type-id) + 366 + 367 Tree-is-atom: # boolean + 368 0/imm32 + 369 # if left-is-atom? + 370 Tree-value: # type-id 371 4/imm32 - 372 Tree-size: # (addr int) - 373 8/imm32 - 374 - 375 # Types - 376 - 377 Max-type-id: - 378 0x10000/imm32 - 379 - 380 Type-id: # (stream (address array byte)) - 381 0x1c/imm32/write - 382 0/imm32/read - 383 0x100/imm32/length - 384 # data - 385 "literal"/imm32 # 0 - 386 "int"/imm32 # 1 - 387 "addr"/imm32 # 2 - 388 "array"/imm32 # 3 - 389 "handle"/imm32 # 4 - 390 "boolean"/imm32 # 5 - 391 "constant"/imm32 # 6: like a literal, but replaced with its value in Var-offset - 392 "offset"/imm32 # 7: (offset T) is guaranteed to be a 32-bit multiple of size-of(T) - 393 0/imm32 - 394 # 0x20 - 395 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 - 396 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 - 397 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 + 372 # unless left-is-atom? + 373 Tree-left: # (addr tree type-id) + 374 4/imm32 + 375 Tree-right: # (addr tree type-id) + 376 8/imm32 + 377 # + 378 Tree-size: # (addr int) + 379 0xc/imm32 + 380 + 381 # Types + 382 + 383 Type-id: # (stream (address array byte)) + 384 0x1c/imm32/write + 385 0/imm32/read + 386 0x100/imm32/size + 387 # data + 388 "literal"/imm32 # 0 + 389 "int"/imm32 # 1 + 390 "addr"/imm32 # 2 + 391 "array"/imm32 # 3 + 392 "handle"/imm32 # 4 + 393 "boolean"/imm32 # 5 + 394 "constant"/imm32 # 6: like a literal, but replaced with its value in Var-offset + 395 "offset"/imm32 # 7: (offset T) is guaranteed to be a 32-bit multiple of size-of(T) + 396 0/imm32 + 397 # 0x20 398 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 399 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 400 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 401 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 - 402 - 403 # Program->types contains some typeinfo for each type definition. - 404 # Types contain vars with types, but can't specify registers. - 405 Typeinfo-id: # type-id - 406 0/imm32 - 407 Typeinfo-fields: # (handle table string (handle typeinfo-entry)) - 408 4/imm32 - 409 # Total size must be >= 0 - 410 # During parsing it may take on two additional values: - 411 # -2: not yet initialized - 412 # -1: in process of being computed - 413 # See populate-mu-type-sizes for details. - 414 Typeinfo-total-size-in-bytes: # int - 415 8/imm32 - 416 Typeinfo-next: # (handle typeinfo) - 417 0xc/imm32 - 418 Typeinfo-size: # (addr int) - 419 0x10/imm32 - 420 - 421 # Each entry in the typeinfo->fields table has a pointer to a string and a - 422 # pointer to a typeinfo-entry. - 423 Typeinfo-fields-row-size: # (addr int) - 424 8/imm32 - 425 - 426 # typeinfo-entry objects have information about a field in a single record type - 427 # - 428 # each field of a type is represented using two var's: - 429 # 1. the input var: expected type of the field; convenient for creating using parse-var-with-type - 430 # 2. the output var: a constant containing the byte offset; convenient for code-generation - 431 # computing the output happens after parsing; in the meantime we preserve the - 432 # order of fields in the 'index' field. - 433 Typeinfo-entry-input-var: # (handle var) - 434 0/imm32 - 435 Typeinfo-entry-index: # int - 436 4/imm32 - 437 Typeinfo-entry-output-var: # (handle var) - 438 8/imm32 - 439 Typeinfo-entry-size: # (addr int) - 440 0xc/imm32 - 441 - 442 == code - 443 - 444 Entry: - 445 # . prologue - 446 89/<- %ebp 4/r32/esp - 447 (new-segment *Heap-size Heap) - 448 # if (argv[1] == "test') run-tests() - 449 { - 450 # if (argc <= 1) break - 451 81 7/subop/compare *ebp 1/imm32 - 452 7e/jump-if-<= break/disp8 - 453 # if (argv[1] != "test") break - 454 (kernel-string-equal? *(ebp+8) "test") # => eax - 455 3d/compare-eax-and 0/imm32/false - 456 74/jump-if-= break/disp8 - 457 # - 458 (run-tests) - 459 # syscall(exit, *Num-test-failures) - 460 8b/-> *Num-test-failures 3/r32/ebx - 461 eb/jump $mu-main:end/disp8 - 462 } - 463 # otherwise convert Stdin - 464 (convert-mu Stdin Stdout) - 465 (flush Stdout) - 466 # syscall(exit, 0) - 467 bb/copy-to-ebx 0/imm32 - 468 $mu-main:end: - 469 b8/copy-to-eax 1/imm32/exit - 470 cd/syscall 0x80/imm8 - 471 - 472 convert-mu: # in: (addr buffered-file), out: (addr buffered-file) - 473 # . prologue - 474 55/push-ebp - 475 89/<- %ebp 4/r32/esp - 476 # initialize global data structures - 477 c7 0/subop/copy *Next-block-index 1/imm32 - 478 c7 0/subop/copy *Type-id 0x1c/imm32 # stream-write - 479 c7 0/subop/copy *_Program-functions 0/imm32 - 480 c7 0/subop/copy *_Program-types 0/imm32 - 481 # - 482 (parse-mu *(ebp+8)) - 483 (populate-mu-type-sizes) - 484 (check-mu-types) - 485 (emit-subx *(ebp+0xc)) - 486 $convert-mu:end: - 487 # . epilogue - 488 89/<- %esp 5/r32/ebp - 489 5d/pop-to-ebp - 490 c3/return - 491 - 492 test-convert-empty-input: - 493 # empty input => empty output - 494 # . prologue - 495 55/push-ebp - 496 89/<- %ebp 4/r32/esp - 497 # setup - 498 (clear-stream _test-input-stream) - 499 (clear-stream $_test-input-buffered-file->buffer) - 500 (clear-stream _test-output-stream) - 501 (clear-stream $_test-output-buffered-file->buffer) - 502 # - 503 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 504 (flush _test-output-buffered-file) - 505 (check-stream-equal _test-output-stream "" "F - test-convert-empty-input") - 506 # . epilogue - 507 89/<- %esp 5/r32/ebp - 508 5d/pop-to-ebp - 509 c3/return - 510 - 511 test-convert-function-skeleton: - 512 # . prologue - 513 55/push-ebp - 514 89/<- %ebp 4/r32/esp - 515 # setup - 516 (clear-stream _test-input-stream) - 517 (clear-stream $_test-input-buffered-file->buffer) - 518 (clear-stream _test-output-stream) - 519 (clear-stream $_test-output-buffered-file->buffer) - 520 # - 521 (write _test-input-stream "fn foo {\n") - 522 (write _test-input-stream "}\n") - 523 # convert - 524 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 525 (flush _test-output-buffered-file) - 526 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 532 # check output - 533 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-skeleton/0") - 534 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-skeleton/1") - 535 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-skeleton/2") - 536 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-skeleton/3") - 537 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-skeleton/4") - 538 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-skeleton/5") - 539 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-skeleton/6") - 540 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-skeleton/7") - 541 # . epilogue - 542 89/<- %esp 5/r32/ebp - 543 5d/pop-to-ebp - 544 c3/return - 545 - 546 test-convert-multiple-function-skeletons: - 547 # . prologue - 548 55/push-ebp - 549 89/<- %ebp 4/r32/esp - 550 # setup - 551 (clear-stream _test-input-stream) - 552 (clear-stream $_test-input-buffered-file->buffer) - 553 (clear-stream _test-output-stream) - 554 (clear-stream $_test-output-buffered-file->buffer) - 555 # - 556 (write _test-input-stream "fn foo {\n") - 557 (write _test-input-stream "}\n") - 558 (write _test-input-stream "fn bar {\n") - 559 (write _test-input-stream "}\n") - 560 # convert - 561 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 562 (flush _test-output-buffered-file) - 563 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 569 # check first function - 570 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-multiple-function-skeletons/0") - 571 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/1") - 572 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/2") - 573 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/3") - 574 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/4") - 575 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/5") - 576 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/6") - 577 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/7") - 578 # check second function - 579 (check-next-stream-line-equal _test-output-stream "bar:" "F - test-convert-multiple-function-skeletons/10") - 580 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/11") - 581 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/12") - 582 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/13") - 583 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/14") - 584 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/15") - 585 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/16") - 586 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/17") - 587 # . epilogue - 588 89/<- %esp 5/r32/ebp - 589 5d/pop-to-ebp - 590 c3/return - 591 - 592 test-convert-function-with-arg: - 593 # . prologue - 594 55/push-ebp - 595 89/<- %ebp 4/r32/esp - 596 # setup - 597 (clear-stream _test-input-stream) - 598 (clear-stream $_test-input-buffered-file->buffer) - 599 (clear-stream _test-output-stream) - 600 (clear-stream $_test-output-buffered-file->buffer) - 601 # - 602 (write _test-input-stream "fn foo n: int {\n") - 603 (write _test-input-stream "}\n") - 604 # convert - 605 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 606 (flush _test-output-buffered-file) - 607 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 613 # check output - 614 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg/0") - 615 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg/1") - 616 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg/2") - 617 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg/3") - 618 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg/4") - 619 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg/5") - 620 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg/6") - 621 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg/7") - 622 # . epilogue - 623 89/<- %esp 5/r32/ebp - 624 5d/pop-to-ebp - 625 c3/return - 626 - 627 test-convert-function-with-arg-and-body: - 628 # . prologue - 629 55/push-ebp - 630 89/<- %ebp 4/r32/esp - 631 # setup - 632 (clear-stream _test-input-stream) - 633 (clear-stream $_test-input-buffered-file->buffer) - 634 (clear-stream _test-output-stream) - 635 (clear-stream $_test-output-buffered-file->buffer) - 636 # - 637 (write _test-input-stream "fn foo n: int {\n") - 638 (write _test-input-stream " increment n\n") - 639 (write _test-input-stream "}\n") - 640 # convert - 641 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 642 (flush _test-output-buffered-file) - 643 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 649 # check output - 650 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg-and-body/0") - 651 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg-and-body/1") - 652 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg-and-body/2") - 653 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg-and-body/3") - 654 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-arg-and-body/4") - 655 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-arg-and-body/5") - 656 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-arg-and-body/6") - 657 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-arg-and-body/7") - 658 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-arg-and-body/8") - 659 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg-and-body/9") - 660 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg-and-body/10") - 661 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg-and-body/11") - 662 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg-and-body/12") - 663 # . epilogue - 664 89/<- %esp 5/r32/ebp - 665 5d/pop-to-ebp - 666 c3/return - 667 - 668 test-convert-function-distinguishes-args: - 669 # . prologue - 670 55/push-ebp - 671 89/<- %ebp 4/r32/esp - 672 # setup - 673 (clear-stream _test-input-stream) - 674 (clear-stream $_test-input-buffered-file->buffer) - 675 (clear-stream _test-output-stream) - 676 (clear-stream $_test-output-buffered-file->buffer) - 677 # - 678 (write _test-input-stream "fn foo a: int, b: int {\n") - 679 (write _test-input-stream " increment b\n") - 680 (write _test-input-stream "}\n") - 681 # convert - 682 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 683 (flush _test-output-buffered-file) - 684 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 690 # check output - 691 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-distinguishes-args/0") - 692 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-distinguishes-args/1") - 693 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-distinguishes-args/2") - 694 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-distinguishes-args/3") - 695 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-distinguishes-args/4") - 696 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-distinguishes-args/5") - 697 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x0000000c)" "F - test-convert-function-distinguishes-args/6") - 698 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-distinguishes-args/7") - 699 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-distinguishes-args/8") - 700 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-distinguishes-args/9") - 701 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-distinguishes-args/10") - 702 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-distinguishes-args/11") - 703 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-distinguishes-args/12") - 704 # . epilogue - 705 89/<- %esp 5/r32/ebp - 706 5d/pop-to-ebp - 707 c3/return - 708 - 709 test-convert-function-returns-result: - 710 # . prologue - 711 55/push-ebp - 712 89/<- %ebp 4/r32/esp - 713 # setup - 714 (clear-stream _test-input-stream) - 715 (clear-stream $_test-input-buffered-file->buffer) - 716 (clear-stream _test-output-stream) - 717 (clear-stream $_test-output-buffered-file->buffer) - 718 # - 719 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") - 720 (write _test-input-stream " result <- copy a\n") - 721 (write _test-input-stream " result <- increment\n") - 722 (write _test-input-stream "}\n") - 723 # convert - 724 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 725 (flush _test-output-buffered-file) - 726 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 732 # check output - 733 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-returns-result/0") - 734 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-returns-result/1") - 735 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-returns-result/2") - 736 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-returns-result/3") - 737 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-returns-result/4") - 738 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-returns-result/5") - 739 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-returns-result/6") - 740 (check-next-stream-line-equal _test-output-stream " 40/increment-eax" "F - test-convert-function-returns-result/7") - 741 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-returns-result/8") - 742 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-returns-result/9") - 743 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-returns-result/10") - 744 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-returns-result/11") - 745 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-returns-result/12") - 746 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-returns-result/13") - 747 # . epilogue - 748 89/<- %esp 5/r32/ebp - 749 5d/pop-to-ebp - 750 c3/return - 751 - 752 test-convert-function-with-literal-arg: - 753 # . prologue - 754 55/push-ebp - 755 89/<- %ebp 4/r32/esp - 756 # setup - 757 (clear-stream _test-input-stream) - 758 (clear-stream $_test-input-buffered-file->buffer) - 759 (clear-stream _test-output-stream) - 760 (clear-stream $_test-output-buffered-file->buffer) - 761 # - 762 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") - 763 (write _test-input-stream " result <- copy a\n") - 764 (write _test-input-stream " result <- add 1\n") - 765 (write _test-input-stream "}\n") - 766 # convert - 767 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 768 (flush _test-output-buffered-file) - 769 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 775 # check output - 776 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-literal-arg/0") - 777 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-literal-arg/1") - 778 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-literal-arg/2") - 779 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-literal-arg/3") - 780 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-literal-arg/4") - 781 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-literal-arg/5") - 782 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-with-literal-arg/6") - 783 (check-next-stream-line-equal _test-output-stream " 05/add-to-eax 1/imm32" "F - test-convert-function-with-literal-arg/7") - 784 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-literal-arg/8") - 785 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-literal-arg/9") - 786 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-literal-arg/10") - 787 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-literal-arg/11") - 788 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-literal-arg/12") - 789 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-literal-arg/13") - 790 # . epilogue - 791 89/<- %esp 5/r32/ebp - 792 5d/pop-to-ebp - 793 c3/return - 794 - 795 test-convert-function-with-literal-arg-2: - 796 # . prologue - 797 55/push-ebp - 798 89/<- %ebp 4/r32/esp - 799 # setup - 800 (clear-stream _test-input-stream) - 801 (clear-stream $_test-input-buffered-file->buffer) - 802 (clear-stream _test-output-stream) - 803 (clear-stream $_test-output-buffered-file->buffer) - 804 # - 805 (write _test-input-stream "fn foo a: int, b: int -> result/ebx: int {\n") - 806 (write _test-input-stream " result <- copy a\n") - 807 (write _test-input-stream " result <- add 1\n") - 808 (write _test-input-stream "}\n") - 809 # convert - 810 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 811 (flush _test-output-buffered-file) - 812 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 818 # check output - 819 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-literal-arg-2/0") - 820 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-literal-arg-2/1") - 821 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-literal-arg-2/2") - 822 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-literal-arg-2/3") - 823 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-literal-arg-2/4") - 824 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-literal-arg-2/5") - 825 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-with-literal-arg-2/6") - 826 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %ebx 1/imm32" "F - test-convert-function-with-literal-arg-2/7") - 827 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-literal-arg-2/8") - 828 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-literal-arg-2/9") - 829 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-literal-arg-2/10") - 830 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-literal-arg-2/11") - 831 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-literal-arg-2/12") - 832 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-literal-arg-2/13") - 833 # . epilogue - 834 89/<- %esp 5/r32/ebp - 835 5d/pop-to-ebp - 836 c3/return - 837 - 838 test-convert-function-call-with-literal-arg: - 839 # . prologue - 840 55/push-ebp - 841 89/<- %ebp 4/r32/esp - 842 # setup - 843 (clear-stream _test-input-stream) - 844 (clear-stream $_test-input-buffered-file->buffer) - 845 (clear-stream _test-output-stream) - 846 (clear-stream $_test-output-buffered-file->buffer) - 847 # - 848 (write _test-input-stream "fn main -> result/ebx: int {\n") - 849 (write _test-input-stream " result <- do-add 3 4\n") - 850 (write _test-input-stream "}\n") - 851 (write _test-input-stream "fn do-add a: int, b: int -> result/ebx: int {\n") - 852 (write _test-input-stream " result <- copy a\n") - 853 (write _test-input-stream " result <- add b\n") + 402 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 + 403 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 + 404 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 + 405 + 406 # == Type definitions + 407 # Program->types contains some typeinfo for each type definition. + 408 # Types contain vars with types, but can't specify registers. + 409 Typeinfo-id: # type-id + 410 0/imm32 + 411 Typeinfo-fields: # (handle table string (handle typeinfo-entry)) + 412 4/imm32 + 413 # Total size must be >= 0 + 414 # During parsing it may take on two additional values: + 415 # -2: not yet initialized + 416 # -1: in process of being computed + 417 # See populate-mu-type-sizes for details. + 418 Typeinfo-total-size-in-bytes: # int + 419 8/imm32 + 420 Typeinfo-next: # (handle typeinfo) + 421 0xc/imm32 + 422 Typeinfo-size: # (addr int) + 423 0x10/imm32 + 424 + 425 # Each entry in the typeinfo->fields table has a pointer to a string and a + 426 # pointer to a typeinfo-entry. + 427 Typeinfo-fields-row-size: # (addr int) + 428 8/imm32 + 429 + 430 # typeinfo-entry objects have information about a field in a single record type + 431 # + 432 # each field of a type is represented using two var's: + 433 # 1. the input var: expected type of the field; convenient for creating using parse-var-with-type + 434 # 2. the output var: a constant containing the byte offset; convenient for code-generation + 435 # computing the output happens after parsing; in the meantime we preserve the + 436 # order of fields in the 'index' field. + 437 Typeinfo-entry-input-var: # (handle var) + 438 0/imm32 + 439 Typeinfo-entry-index: # int + 440 4/imm32 + 441 Typeinfo-entry-output-var: # (handle var) + 442 8/imm32 + 443 Typeinfo-entry-size: # (addr int) + 444 0xc/imm32 + 445 + 446 == code + 447 + 448 Entry: + 449 # . prologue + 450 89/<- %ebp 4/r32/esp + 451 (new-segment *Heap-size Heap) + 452 # if (argv[1] == "test') run-tests() + 453 { + 454 # if (argc <= 1) break + 455 81 7/subop/compare *ebp 1/imm32 + 456 7e/jump-if-<= break/disp8 + 457 # if (argv[1] != "test") break + 458 (kernel-string-equal? *(ebp+8) "test") # => eax + 459 3d/compare-eax-and 0/imm32/false + 460 74/jump-if-= break/disp8 + 461 # + 462 (run-tests) + 463 # syscall(exit, *Num-test-failures) + 464 8b/-> *Num-test-failures 3/r32/ebx + 465 eb/jump $mu-main:end/disp8 + 466 } + 467 # otherwise convert Stdin + 468 (convert-mu Stdin Stdout) + 469 (flush Stdout) + 470 # syscall(exit, 0) + 471 bb/copy-to-ebx 0/imm32 + 472 $mu-main:end: + 473 b8/copy-to-eax 1/imm32/exit + 474 cd/syscall 0x80/imm8 + 475 + 476 convert-mu: # in: (addr buffered-file), out: (addr buffered-file) + 477 # . prologue + 478 55/push-ebp + 479 89/<- %ebp 4/r32/esp + 480 # initialize global data structures + 481 c7 0/subop/copy *Next-block-index 1/imm32 + 482 c7 0/subop/copy *Type-id 0x1c/imm32 # stream-write + 483 c7 0/subop/copy *_Program-functions 0/imm32 + 484 c7 0/subop/copy *_Program-types 0/imm32 + 485 # + 486 (parse-mu *(ebp+8)) + 487 (populate-mu-type-sizes) + 488 (check-mu-types) + 489 (emit-subx *(ebp+0xc)) + 490 $convert-mu:end: + 491 # . epilogue + 492 89/<- %esp 5/r32/ebp + 493 5d/pop-to-ebp + 494 c3/return + 495 + 496 test-convert-empty-input: + 497 # empty input => empty output + 498 # . prologue + 499 55/push-ebp + 500 89/<- %ebp 4/r32/esp + 501 # setup + 502 (clear-stream _test-input-stream) + 503 (clear-stream $_test-input-buffered-file->buffer) + 504 (clear-stream _test-output-stream) + 505 (clear-stream $_test-output-buffered-file->buffer) + 506 # + 507 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 508 (flush _test-output-buffered-file) + 509 (check-stream-equal _test-output-stream "" "F - test-convert-empty-input") + 510 # . epilogue + 511 89/<- %esp 5/r32/ebp + 512 5d/pop-to-ebp + 513 c3/return + 514 + 515 test-convert-function-skeleton: + 516 # . prologue + 517 55/push-ebp + 518 89/<- %ebp 4/r32/esp + 519 # setup + 520 (clear-stream _test-input-stream) + 521 (clear-stream $_test-input-buffered-file->buffer) + 522 (clear-stream _test-output-stream) + 523 (clear-stream $_test-output-buffered-file->buffer) + 524 # + 525 (write _test-input-stream "fn foo {\n") + 526 (write _test-input-stream "}\n") + 527 # convert + 528 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 529 (flush _test-output-buffered-file) + 530 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 536 # check output + 537 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-skeleton/0") + 538 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-skeleton/1") + 539 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-skeleton/2") + 540 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-skeleton/3") + 541 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-skeleton/4") + 542 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-skeleton/5") + 543 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-skeleton/6") + 544 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-skeleton/7") + 545 # . epilogue + 546 89/<- %esp 5/r32/ebp + 547 5d/pop-to-ebp + 548 c3/return + 549 + 550 test-convert-multiple-function-skeletons: + 551 # . prologue + 552 55/push-ebp + 553 89/<- %ebp 4/r32/esp + 554 # setup + 555 (clear-stream _test-input-stream) + 556 (clear-stream $_test-input-buffered-file->buffer) + 557 (clear-stream _test-output-stream) + 558 (clear-stream $_test-output-buffered-file->buffer) + 559 # + 560 (write _test-input-stream "fn foo {\n") + 561 (write _test-input-stream "}\n") + 562 (write _test-input-stream "fn bar {\n") + 563 (write _test-input-stream "}\n") + 564 # convert + 565 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 566 (flush _test-output-buffered-file) + 567 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 573 # check first function + 574 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-multiple-function-skeletons/0") + 575 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/1") + 576 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/2") + 577 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/3") + 578 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/4") + 579 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/5") + 580 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/6") + 581 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/7") + 582 # check second function + 583 (check-next-stream-line-equal _test-output-stream "bar:" "F - test-convert-multiple-function-skeletons/10") + 584 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/11") + 585 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/12") + 586 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/13") + 587 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/14") + 588 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/15") + 589 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/16") + 590 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/17") + 591 # . epilogue + 592 89/<- %esp 5/r32/ebp + 593 5d/pop-to-ebp + 594 c3/return + 595 + 596 test-convert-function-with-arg: + 597 # . prologue + 598 55/push-ebp + 599 89/<- %ebp 4/r32/esp + 600 # setup + 601 (clear-stream _test-input-stream) + 602 (clear-stream $_test-input-buffered-file->buffer) + 603 (clear-stream _test-output-stream) + 604 (clear-stream $_test-output-buffered-file->buffer) + 605 # + 606 (write _test-input-stream "fn foo n: int {\n") + 607 (write _test-input-stream "}\n") + 608 # convert + 609 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 610 (flush _test-output-buffered-file) + 611 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 617 # check output + 618 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg/0") + 619 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg/1") + 620 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg/2") + 621 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg/3") + 622 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg/4") + 623 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg/5") + 624 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg/6") + 625 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg/7") + 626 # . epilogue + 627 89/<- %esp 5/r32/ebp + 628 5d/pop-to-ebp + 629 c3/return + 630 + 631 test-convert-function-with-arg-and-body: + 632 # . prologue + 633 55/push-ebp + 634 89/<- %ebp 4/r32/esp + 635 # setup + 636 (clear-stream _test-input-stream) + 637 (clear-stream $_test-input-buffered-file->buffer) + 638 (clear-stream _test-output-stream) + 639 (clear-stream $_test-output-buffered-file->buffer) + 640 # + 641 (write _test-input-stream "fn foo n: int {\n") + 642 (write _test-input-stream " increment n\n") + 643 (write _test-input-stream "}\n") + 644 # convert + 645 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 646 (flush _test-output-buffered-file) + 647 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 653 # check output + 654 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg-and-body/0") + 655 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg-and-body/1") + 656 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg-and-body/2") + 657 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg-and-body/3") + 658 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-arg-and-body/4") + 659 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-arg-and-body/5") + 660 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-arg-and-body/6") + 661 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-arg-and-body/7") + 662 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-arg-and-body/8") + 663 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg-and-body/9") + 664 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg-and-body/10") + 665 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg-and-body/11") + 666 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg-and-body/12") + 667 # . epilogue + 668 89/<- %esp 5/r32/ebp + 669 5d/pop-to-ebp + 670 c3/return + 671 + 672 test-convert-function-distinguishes-args: + 673 # . prologue + 674 55/push-ebp + 675 89/<- %ebp 4/r32/esp + 676 # setup + 677 (clear-stream _test-input-stream) + 678 (clear-stream $_test-input-buffered-file->buffer) + 679 (clear-stream _test-output-stream) + 680 (clear-stream $_test-output-buffered-file->buffer) + 681 # + 682 (write _test-input-stream "fn foo a: int, b: int {\n") + 683 (write _test-input-stream " increment b\n") + 684 (write _test-input-stream "}\n") + 685 # convert + 686 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 687 (flush _test-output-buffered-file) + 688 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 694 # check output + 695 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-distinguishes-args/0") + 696 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-distinguishes-args/1") + 697 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-distinguishes-args/2") + 698 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-distinguishes-args/3") + 699 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-distinguishes-args/4") + 700 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-distinguishes-args/5") + 701 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x0000000c)" "F - test-convert-function-distinguishes-args/6") + 702 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-distinguishes-args/7") + 703 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-distinguishes-args/8") + 704 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-distinguishes-args/9") + 705 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-distinguishes-args/10") + 706 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-distinguishes-args/11") + 707 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-distinguishes-args/12") + 708 # . epilogue + 709 89/<- %esp 5/r32/ebp + 710 5d/pop-to-ebp + 711 c3/return + 712 + 713 test-convert-function-returns-result: + 714 # . prologue + 715 55/push-ebp + 716 89/<- %ebp 4/r32/esp + 717 # setup + 718 (clear-stream _test-input-stream) + 719 (clear-stream $_test-input-buffered-file->buffer) + 720 (clear-stream _test-output-stream) + 721 (clear-stream $_test-output-buffered-file->buffer) + 722 # + 723 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") + 724 (write _test-input-stream " result <- copy a\n") + 725 (write _test-input-stream " result <- increment\n") + 726 (write _test-input-stream "}\n") + 727 # convert + 728 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 729 (flush _test-output-buffered-file) + 730 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 736 # check output + 737 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-returns-result/0") + 738 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-returns-result/1") + 739 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-returns-result/2") + 740 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-returns-result/3") + 741 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-returns-result/4") + 742 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-returns-result/5") + 743 (check-next-stream-line-equal _test-output-stream " 8b/-> *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-returns-result/6") + 744 (check-next-stream-line-equal _test-output-stream " 40/increment-eax" "F - test-convert-function-returns-result/7") + 745 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-returns-result/8") + 746 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-returns-result/9") + 747 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-returns-result/10") + 748 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-returns-result/11") + 749 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-returns-result/12") + 750 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-returns-result/13") + 751 # . epilogue + 752 89/<- %esp 5/r32/ebp + 753 5d/pop-to-ebp + 754 c3/return + 755 + 756 test-convert-function-with-literal-arg: + 757 # . prologue + 758 55/push-ebp + 759 89/<- %ebp 4/r32/esp + 760 # setup + 761 (clear-stream _test-input-stream) + 762 (clear-stream $_test-input-buffered-file->buffer) + 763 (clear-stream _test-output-stream) + 764 (clear-stream $_test-output-buffered-file->buffer) + 765 # + 766 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") + 767 (write _test-input-stream " result <- copy a\n") + 768 (write _test-input-stream " result <- add 1\n") + 769 (write _test-input-stream "}\n") + 770 # convert + 771 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 772 (flush _test-output-buffered-file) + 773 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 779 # check output + 780 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-literal-arg/0") + 781 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-literal-arg/1") + 782 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-literal-arg/2") + 783 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-literal-arg/3") + 784 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-literal-arg/4") + 785 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-literal-arg/5") + 786 (check-next-stream-line-equal _test-output-stream " 8b/-> *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-with-literal-arg/6") + 787 (check-next-stream-line-equal _test-output-stream " 05/add-to-eax 1/imm32" "F - test-convert-function-with-literal-arg/7") + 788 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-literal-arg/8") + 789 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-literal-arg/9") + 790 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-literal-arg/10") + 791 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-literal-arg/11") + 792 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-literal-arg/12") + 793 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-literal-arg/13") + 794 # . epilogue + 795 89/<- %esp 5/r32/ebp + 796 5d/pop-to-ebp + 797 c3/return + 798 + 799 test-convert-function-with-literal-arg-2: + 800 # . prologue + 801 55/push-ebp + 802 89/<- %ebp 4/r32/esp + 803 # setup + 804 (clear-stream _test-input-stream) + 805 (clear-stream $_test-input-buffered-file->buffer) + 806 (clear-stream _test-output-stream) + 807 (clear-stream $_test-output-buffered-file->buffer) + 808 # + 809 (write _test-input-stream "fn foo a: int, b: int -> result/ebx: int {\n") + 810 (write _test-input-stream " result <- copy a\n") + 811 (write _test-input-stream " result <- add 1\n") + 812 (write _test-input-stream "}\n") + 813 # convert + 814 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 815 (flush _test-output-buffered-file) + 816 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 822 # check output + 823 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-literal-arg-2/0") + 824 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-literal-arg-2/1") + 825 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-literal-arg-2/2") + 826 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-literal-arg-2/3") + 827 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-literal-arg-2/4") + 828 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-literal-arg-2/5") + 829 (check-next-stream-line-equal _test-output-stream " 8b/-> *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-with-literal-arg-2/6") + 830 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %ebx 1/imm32" "F - test-convert-function-with-literal-arg-2/7") + 831 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-literal-arg-2/8") + 832 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-literal-arg-2/9") + 833 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-literal-arg-2/10") + 834 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-literal-arg-2/11") + 835 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-literal-arg-2/12") + 836 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-literal-arg-2/13") + 837 # . epilogue + 838 89/<- %esp 5/r32/ebp + 839 5d/pop-to-ebp + 840 c3/return + 841 + 842 test-convert-function-call-with-literal-arg: + 843 # . prologue + 844 55/push-ebp + 845 89/<- %ebp 4/r32/esp + 846 # setup + 847 (clear-stream _test-input-stream) + 848 (clear-stream $_test-input-buffered-file->buffer) + 849 (clear-stream _test-output-stream) + 850 (clear-stream $_test-output-buffered-file->buffer) + 851 # + 852 (write _test-input-stream "fn main -> result/ebx: int {\n") + 853 (write _test-input-stream " result <- do-add 3 4\n") 854 (write _test-input-stream "}\n") - 855 # convert - 856 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 857 (flush _test-output-buffered-file) - 858 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 864 # check output - 865 (check-next-stream-line-equal _test-output-stream "main:" "F - test-convert-function-call-with-literal-arg/0") - 866 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/1") - 867 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/2") - 868 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/3") - 869 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/4") - 870 (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:" "F - test-convert-function-call-with-literal-arg/5") - 871 (check-next-stream-line-equal _test-output-stream " (do-add 3 4)" "F - test-convert-function-call-with-literal-arg/6") - 872 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/7") - 873 (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/8") - 874 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/9") - 875 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/10") - 876 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/11") - 877 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/12") - 878 (check-next-stream-line-equal _test-output-stream "do-add:" "F - test-convert-function-call-with-literal-arg/13") - 879 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/14") - 880 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/15") - 881 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/16") - 882 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/17") - 883 (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:" "F - test-convert-function-call-with-literal-arg/18") - 884 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/19") - 885 (check-next-stream-line-equal _test-output-stream " 03/add *(ebp+0x0000000c) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/20") - 886 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/21") - 887 (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:" "F - test-convert-function-call-with-literal-arg/22") - 888 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/23") - 889 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/24") - 890 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/25") - 891 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/26") - 892 # . epilogue - 893 89/<- %esp 5/r32/ebp - 894 5d/pop-to-ebp - 895 c3/return - 896 - 897 test-convert-function-with-local-var-in-mem: - 898 # . prologue - 899 55/push-ebp - 900 89/<- %ebp 4/r32/esp - 901 # setup - 902 (clear-stream _test-input-stream) - 903 (clear-stream $_test-input-buffered-file->buffer) - 904 (clear-stream _test-output-stream) - 905 (clear-stream $_test-output-buffered-file->buffer) - 906 # - 907 (write _test-input-stream "fn foo {\n") - 908 (write _test-input-stream " var x: int\n") - 909 (write _test-input-stream " increment x\n") - 910 (write _test-input-stream "}\n") - 911 # convert - 912 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 913 (flush _test-output-buffered-file) - 914 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 920 # check output - 921 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-mem/0") - 922 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-mem/1") - 923 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-mem/2") - 924 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-mem/3") - 925 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-mem/4") - 926 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-mem/5") - 927 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-mem/6") - 928 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-mem/7") - 929 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-in-mem/8") - 930 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-mem/9") - 931 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-mem/10") - 932 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-mem/11") - 933 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-mem/12") - 934 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-mem/13") - 935 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-mem/14") - 936 # . epilogue - 937 89/<- %esp 5/r32/ebp - 938 5d/pop-to-ebp - 939 c3/return - 940 - 941 test-convert-function-with-local-var-with-compound-type-in-mem: - 942 # . prologue - 943 55/push-ebp - 944 89/<- %ebp 4/r32/esp - 945 # setup - 946 (clear-stream _test-input-stream) - 947 (clear-stream $_test-input-buffered-file->buffer) - 948 (clear-stream _test-output-stream) - 949 (clear-stream $_test-output-buffered-file->buffer) - 950 # - 951 (write _test-input-stream "fn foo {\n") - 952 (write _test-input-stream " var x: (addr int)\n") - 953 (write _test-input-stream " copy-to x, 0\n") - 954 (write _test-input-stream "}\n") - 955 # convert - 956 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 957 (flush _test-output-buffered-file) - 958 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 964 # check output - 965 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-with-compound-type-in-mem/0") - 966 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-with-compound-type-in-mem/1") - 967 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-with-compound-type-in-mem/2") - 968 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-with-compound-type-in-mem/3") - 969 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-with-compound-type-in-mem/4") - 970 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-with-compound-type-in-mem/5") - 971 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-with-compound-type-in-mem/6") - 972 (check-next-stream-line-equal _test-output-stream " c7 0/subop/copy *(ebp+0xfffffffc) 0/imm32" "F - test-convert-function-with-local-var-with-compound-type-in-mem/7") - 973 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-with-compound-type-in-mem/8") - 974 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-with-compound-type-in-mem/9") - 975 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-with-compound-type-in-mem/10") - 976 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-with-compound-type-in-mem/11") - 977 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-with-compound-type-in-mem/12") - 978 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-with-compound-type-in-mem/13") - 979 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-with-compound-type-in-mem/14") - 980 # . epilogue - 981 89/<- %esp 5/r32/ebp - 982 5d/pop-to-ebp - 983 c3/return - 984 - 985 test-convert-function-with-local-var-in-reg: - 986 # . prologue - 987 55/push-ebp - 988 89/<- %ebp 4/r32/esp - 989 # setup - 990 (clear-stream _test-input-stream) - 991 (clear-stream $_test-input-buffered-file->buffer) - 992 (clear-stream _test-output-stream) - 993 (clear-stream $_test-output-buffered-file->buffer) - 994 # - 995 (write _test-input-stream "fn foo {\n") - 996 (write _test-input-stream " var x/ecx: int <- copy 3\n") - 997 (write _test-input-stream " x <- increment\n") - 998 (write _test-input-stream "}\n") - 999 # convert - 1000 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1001 (flush _test-output-buffered-file) - 1002 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1008 # check output - 1009 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-reg/0") - 1010 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-reg/1") - 1011 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-reg/2") - 1012 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-reg/3") - 1013 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-reg/4") - 1014 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-reg/5") - 1015 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-local-var-in-reg/6") - 1016 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-function-with-local-var-in-reg/7") - 1017 (check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-convert-function-with-local-var-in-reg/8") - 1018 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9") - 1019 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-reg/10") - 1020 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-reg/11") - 1021 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-reg/12") - 1022 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-reg/13") - 1023 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-reg/14") - 1024 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-reg/15") - 1025 # . epilogue - 1026 89/<- %esp 5/r32/ebp - 1027 5d/pop-to-ebp - 1028 c3/return - 1029 - 1030 test-convert-function-with-second-local-var-in-same-reg: - 1031 # . prologue - 1032 55/push-ebp - 1033 89/<- %ebp 4/r32/esp - 1034 # setup - 1035 (clear-stream _test-input-stream) - 1036 (clear-stream $_test-input-buffered-file->buffer) - 1037 (clear-stream _test-output-stream) - 1038 (clear-stream $_test-output-buffered-file->buffer) - 1039 # - 1040 (write _test-input-stream "fn foo {\n") - 1041 (write _test-input-stream " var x/ecx: int <- copy 3\n") - 1042 (write _test-input-stream " var y/ecx: int <- copy 4\n") - 1043 (write _test-input-stream " y <- increment\n") - 1044 (write _test-input-stream "}\n") - 1045 # convert - 1046 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1047 (flush _test-output-buffered-file) - 1048 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1054 # check output - 1055 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-second-local-var-in-same-reg/0") - 1056 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-second-local-var-in-same-reg/1") - 1057 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-second-local-var-in-same-reg/2") - 1058 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-second-local-var-in-same-reg/3") - 1059 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-second-local-var-in-same-reg/4") - 1060 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-second-local-var-in-same-reg/5") - 1061 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-second-local-var-in-same-reg/6") - 1062 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-function-with-second-local-var-in-same-reg/7") - 1063 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-convert-function-with-second-local-var-in-same-reg/8") - 1064 (check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-convert-function-with-second-local-var-in-same-reg/9") - 1065 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-second-local-var-in-same-reg/10") - 1066 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-second-local-var-in-same-reg/11") - 1067 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-second-local-var-in-same-reg/12") - 1068 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-second-local-var-in-same-reg/13") - 1069 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-second-local-var-in-same-reg/14") - 1070 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-second-local-var-in-same-reg/15") - 1071 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-second-local-var-in-same-reg/16") - 1072 # . epilogue - 1073 89/<- %esp 5/r32/ebp - 1074 5d/pop-to-ebp - 1075 c3/return - 1076 - 1077 test-convert-function-with-local-var-dereferenced: - 1078 # . prologue - 1079 55/push-ebp - 1080 89/<- %ebp 4/r32/esp - 1081 # setup - 1082 (clear-stream _test-input-stream) - 1083 (clear-stream $_test-input-buffered-file->buffer) - 1084 (clear-stream _test-output-stream) - 1085 (clear-stream $_test-output-buffered-file->buffer) - 1086 # - 1087 (write _test-input-stream "fn foo {\n") - 1088 (write _test-input-stream " var x/ecx: (addr int) <- copy 0\n") - 1089 (write _test-input-stream " increment *x\n") - 1090 (write _test-input-stream "}\n") - 1091 # convert - 1092 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1093 (flush _test-output-buffered-file) - 1094 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1100 # check output - 1101 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-dereferenced/0") - 1102 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-dereferenced/1") - 1103 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-dereferenced/2") - 1104 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-dereferenced/3") - 1105 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-dereferenced/4") - 1106 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-dereferenced/5") - 1107 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-local-var-dereferenced/6") - 1108 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-function-with-local-var-dereferenced/7") - 1109 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *ecx" "F - test-convert-function-with-local-var-dereferenced/8") - 1110 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9") - 1111 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-dereferenced/10") - 1112 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-dereferenced/11") - 1113 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-dereferenced/12") - 1114 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-dereferenced/13") - 1115 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-dereferenced/14") - 1116 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-dereferenced/15") - 1117 # . epilogue - 1118 89/<- %esp 5/r32/ebp - 1119 5d/pop-to-ebp - 1120 c3/return - 1121 - 1122 test-convert-compare-register-with-literal: - 1123 # . prologue - 1124 55/push-ebp - 1125 89/<- %ebp 4/r32/esp - 1126 # setup - 1127 (clear-stream _test-input-stream) - 1128 (clear-stream $_test-input-buffered-file->buffer) - 1129 (clear-stream _test-output-stream) - 1130 (clear-stream $_test-output-buffered-file->buffer) - 1131 # - 1132 (write _test-input-stream "fn foo {\n") - 1133 (write _test-input-stream " var x/ecx: int <- copy 0\n") - 1134 (write _test-input-stream " compare x, 0\n") - 1135 (write _test-input-stream "}\n") - 1136 # convert - 1137 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1138 (flush _test-output-buffered-file) - 1139 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1145 # check output - 1146 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-compare-register-with-literal/0") - 1147 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-compare-register-with-literal/1") - 1148 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-compare-register-with-literal/2") - 1149 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-compare-register-with-literal/3") - 1150 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-compare-register-with-literal/4") - 1151 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-compare-register-with-literal/5") - 1152 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-compare-register-with-literal/6") - 1153 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-compare-register-with-literal/7") - 1154 (check-next-stream-line-equal _test-output-stream " 81 7/subop/compare %ecx 0/imm32" "F - test-convert-compare-register-with-literal/8") - 1155 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9") - 1156 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-compare-register-with-literal/10") - 1157 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-compare-register-with-literal/11") - 1158 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-compare-register-with-literal/12") - 1159 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-compare-register-with-literal/13") - 1160 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-compare-register-with-literal/14") - 1161 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-compare-register-with-literal/15") - 1162 # . epilogue - 1163 89/<- %esp 5/r32/ebp - 1164 5d/pop-to-ebp - 1165 c3/return - 1166 - 1167 test-convert-function-with-local-var-in-block: - 1168 # . prologue - 1169 55/push-ebp - 1170 89/<- %ebp 4/r32/esp - 1171 # setup - 1172 (clear-stream _test-input-stream) - 1173 (clear-stream $_test-input-buffered-file->buffer) - 1174 (clear-stream _test-output-stream) - 1175 (clear-stream $_test-output-buffered-file->buffer) - 1176 # - 1177 (write _test-input-stream "fn foo {\n") - 1178 (write _test-input-stream " {\n") - 1179 (write _test-input-stream " var x: int\n") - 1180 (write _test-input-stream " increment x\n") - 1181 (write _test-input-stream " }\n") - 1182 (write _test-input-stream "}\n") - 1183 # convert - 1184 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1185 (flush _test-output-buffered-file) - 1186 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1192 # check output - 1193 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-block/0") - 1194 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-block/1") - 1195 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-block/2") - 1196 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-block/3") - 1197 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/4") - 1198 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-block/5") - 1199 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/6") - 1200 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-local-var-in-block/7") - 1201 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-block/8") - 1202 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-block/9") - 1203 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-in-block/10") - 1204 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/11") - 1205 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-local-var-in-block/12") - 1206 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/13") - 1207 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-block/14") - 1208 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-block/15") - 1209 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-block/16") - 1210 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-block/17") - 1211 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-block/18") - 1212 # . epilogue - 1213 89/<- %esp 5/r32/ebp - 1214 5d/pop-to-ebp - 1215 c3/return - 1216 - 1217 test-convert-function-with-local-var-in-named-block: - 1218 # . prologue - 1219 55/push-ebp - 1220 89/<- %ebp 4/r32/esp - 1221 # setup - 1222 (clear-stream _test-input-stream) - 1223 (clear-stream $_test-input-buffered-file->buffer) - 1224 (clear-stream _test-output-stream) - 1225 (clear-stream $_test-output-buffered-file->buffer) - 1226 # - 1227 (write _test-input-stream "fn foo {\n") - 1228 (write _test-input-stream " $bar: {\n") - 1229 (write _test-input-stream " var x: int\n") - 1230 (write _test-input-stream " increment x\n") - 1231 (write _test-input-stream " }\n") - 1232 (write _test-input-stream "}\n") - 1233 # convert - 1234 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1235 (flush _test-output-buffered-file) - 1236 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1242 # check output - 1243 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-named-block/0") - 1244 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-named-block/1") - 1245 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-named-block/2") - 1246 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-named-block/3") - 1247 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/4") - 1248 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-named-block/5") - 1249 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/6") - 1250 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-local-var-in-named-block/7") - 1251 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-named-block/8") - 1252 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-named-block/9") - 1253 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-in-named-block/10") - 1254 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/11") - 1255 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-local-var-in-named-block/12") - 1256 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/13") - 1257 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-named-block/14") - 1258 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-named-block/15") - 1259 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-named-block/16") - 1260 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-named-block/17") - 1261 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-named-block/18") - 1262 # . epilogue - 1263 89/<- %esp 5/r32/ebp - 1264 5d/pop-to-ebp - 1265 c3/return - 1266 - 1267 test-always-shadow-outermost-reg-vars-in-function: - 1268 # . prologue - 1269 55/push-ebp - 1270 89/<- %ebp 4/r32/esp - 1271 # setup - 1272 (clear-stream _test-input-stream) - 1273 (clear-stream $_test-input-buffered-file->buffer) - 1274 (clear-stream _test-output-stream) - 1275 (clear-stream $_test-output-buffered-file->buffer) - 1276 # - 1277 (write _test-input-stream "fn foo {\n") - 1278 (write _test-input-stream " var x/ecx: int <- copy 3\n") - 1279 (write _test-input-stream "}\n") - 1280 # convert - 1281 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1282 (flush _test-output-buffered-file) - 1283 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1289 # check output - 1290 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-always-shadow-outermost-reg-vars-in-function/0") - 1291 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-always-shadow-outermost-reg-vars-in-function/1") - 1292 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-always-shadow-outermost-reg-vars-in-function/2") - 1293 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-always-shadow-outermost-reg-vars-in-function/3") - 1294 (check-next-stream-line-equal _test-output-stream " {" "F - test-always-shadow-outermost-reg-vars-in-function/4") - 1295 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-always-shadow-outermost-reg-vars-in-function/5") - 1296 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-compare-register-with-literal/6") - 1297 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-always-shadow-outermost-reg-vars-in-function/8") - 1298 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9") - 1299 (check-next-stream-line-equal _test-output-stream " }" "F - test-always-shadow-outermost-reg-vars-in-function/12") - 1300 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-always-shadow-outermost-reg-vars-in-function/13") - 1301 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-always-shadow-outermost-reg-vars-in-function/14") - 1302 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-always-shadow-outermost-reg-vars-in-function/15") - 1303 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-always-shadow-outermost-reg-vars-in-function/16") - 1304 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-always-shadow-outermost-reg-vars-in-function/17") - 1305 # . epilogue - 1306 89/<- %esp 5/r32/ebp - 1307 5d/pop-to-ebp - 1308 c3/return - 1309 - 1310 _pending-test-clobber-dead-local: - 1311 # . prologue - 1312 55/push-ebp - 1313 89/<- %ebp 4/r32/esp - 1314 # setup - 1315 (clear-stream _test-input-stream) - 1316 (clear-stream $_test-input-buffered-file->buffer) - 1317 (clear-stream _test-output-stream) - 1318 (clear-stream $_test-output-buffered-file->buffer) - 1319 # - 1320 (write _test-input-stream "fn foo {\n") - 1321 (write _test-input-stream " var x/ecx: int <- copy 3\n") - 1322 (write _test-input-stream " {\n") - 1323 (write _test-input-stream " var y/ecx: int <- copy 4\n") - 1324 (write _test-input-stream " }\n") - 1325 (write _test-input-stream "}\n") - 1326 # convert - 1327 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1328 (flush _test-output-buffered-file) - 1329 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1335 # check output - 1336 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-clobber-dead-local/0") - 1337 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-clobber-dead-local/1") - 1338 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-clobber-dead-local/2") - 1339 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-clobber-dead-local/3") - 1340 (check-next-stream-line-equal _test-output-stream " {" "F - test-clobber-dead-local/4") - 1341 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-clobber-dead-local/5") - 1342 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-clobber-dead-local/6") - 1343 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-clobber-dead-local/7") - 1344 (check-next-stream-line-equal _test-output-stream " {" "F - test-clobber-dead-local/8") - 1345 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-clobber-dead-local/9") - 1346 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-clobber-dead-local/10") # no push/pop here - 1347 (check-next-stream-line-equal _test-output-stream " }" "F - test-clobber-dead-local/11") - 1348 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-clobber-dead-local/12") - 1349 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-clobber-dead-local/13") - 1350 (check-next-stream-line-equal _test-output-stream " }" "F - test-clobber-dead-local/14") - 1351 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-clobber-dead-local/15") - 1352 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-clobber-dead-local/16") - 1353 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-clobber-dead-local/17") - 1354 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-clobber-dead-local/18") - 1355 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-clobber-dead-local/19") - 1356 # . epilogue - 1357 89/<- %esp 5/r32/ebp - 1358 5d/pop-to-ebp - 1359 c3/return - 1360 - 1361 test-shadow-live-local: - 1362 # . prologue - 1363 55/push-ebp - 1364 89/<- %ebp 4/r32/esp - 1365 # setup - 1366 (clear-stream _test-input-stream) - 1367 (clear-stream $_test-input-buffered-file->buffer) - 1368 (clear-stream _test-output-stream) - 1369 (clear-stream $_test-output-buffered-file->buffer) - 1370 # - 1371 (write _test-input-stream "fn foo {\n") - 1372 (write _test-input-stream " var x/ecx: int <- copy 3\n") - 1373 (write _test-input-stream " {\n") - 1374 (write _test-input-stream " var y/ecx: int <- copy 4\n") - 1375 (write _test-input-stream " }\n") - 1376 (write _test-input-stream " x <- increment\n") - 1377 (write _test-input-stream "}\n") - 1378 # convert - 1379 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1380 (flush _test-output-buffered-file) - 1381 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1387 # check output - 1388 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-shadow-live-local/0") - 1389 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-shadow-live-local/1") - 1390 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-shadow-live-local/2") - 1391 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-shadow-live-local/3") - 1392 (check-next-stream-line-equal _test-output-stream " {" "F - test-shadow-live-local/4") - 1393 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-shadow-live-local/5") - 1394 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-shadow-live-local/6") - 1395 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-shadow-live-local/7") - 1396 (check-next-stream-line-equal _test-output-stream " {" "F - test-shadow-live-local/8") - 1397 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-shadow-live-local/9") - 1398 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-shadow-live-local/10") - 1399 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-shadow-live-local/11") - 1400 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-shadow-live-local/12") - 1401 (check-next-stream-line-equal _test-output-stream " }" "F - test-shadow-live-local/13") - 1402 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-shadow-live-local/14") - 1403 (check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-shadow-live-local/15") - 1404 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-shadow-live-local/16") - 1405 (check-next-stream-line-equal _test-output-stream " }" "F - test-shadow-live-local/17") - 1406 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-shadow-live-local/18") - 1407 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-shadow-live-local/19") - 1408 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-shadow-live-local/20") - 1409 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-shadow-live-local/21") - 1410 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-shadow-live-local/21") - 1411 # . epilogue - 1412 89/<- %esp 5/r32/ebp - 1413 5d/pop-to-ebp - 1414 c3/return - 1415 - 1416 test-shadow-live-output: - 1417 # . prologue - 1418 55/push-ebp - 1419 89/<- %ebp 4/r32/esp - 1420 # setup - 1421 (clear-stream _test-input-stream) - 1422 (clear-stream $_test-input-buffered-file->buffer) - 1423 (clear-stream _test-output-stream) - 1424 (clear-stream $_test-output-buffered-file->buffer) - 1425 # - 1426 (write _test-input-stream "fn foo -> x/ecx: int {\n") - 1427 (write _test-input-stream " x <- copy 3\n") - 1428 (write _test-input-stream " {\n") - 1429 (write _test-input-stream " var y/ecx: int <- copy 4\n") - 1430 (write _test-input-stream " }\n") - 1431 (write _test-input-stream " x <- increment\n") - 1432 (write _test-input-stream "}\n") - 1433 # convert - 1434 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1435 (flush _test-output-buffered-file) - 1436 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1442 # check output - 1443 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-shadow-live-output/0") - 1444 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-shadow-live-output/1") - 1445 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-shadow-live-output/2") - 1446 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-shadow-live-output/3") - 1447 (check-next-stream-line-equal _test-output-stream " {" "F - test-shadow-live-output/4") - 1448 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-shadow-live-output/5") - 1449 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-shadow-live-output/7") # no push because it's an output reg - 1450 (check-next-stream-line-equal _test-output-stream " {" "F - test-shadow-live-output/8") - 1451 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-shadow-live-output/9") - 1452 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-shadow-live-output/10") - 1453 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-shadow-live-output/11") - 1454 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-shadow-live-output/12") - 1455 (check-next-stream-line-equal _test-output-stream " }" "F - test-shadow-live-output/13") - 1456 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-shadow-live-output/14") - 1457 (check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-shadow-live-output/15") - 1458 (check-next-stream-line-equal _test-output-stream " }" "F - test-shadow-live-output/17") - 1459 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-shadow-live-output/18") - 1460 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-shadow-live-output/19") - 1461 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-shadow-live-output/20") - 1462 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-shadow-live-output/21") - 1463 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-shadow-live-output/21") - 1464 # . epilogue - 1465 89/<- %esp 5/r32/ebp - 1466 5d/pop-to-ebp - 1467 c3/return - 1468 - 1469 _pending-test-local-clobbered-by-output: - 1470 # also doesn't spill - 1471 # . prologue - 1472 55/push-ebp - 1473 89/<- %ebp 4/r32/esp - 1474 # setup - 1475 (clear-stream _test-input-stream) - 1476 (clear-stream $_test-input-buffered-file->buffer) - 1477 (clear-stream _test-output-stream) - 1478 (clear-stream $_test-output-buffered-file->buffer) - 1479 # - 1480 (write _test-input-stream "fn foo -> x/ecx: int {\n") - 1481 (write _test-input-stream " var y/ecx: int <- copy 4\n") - 1482 (write _test-input-stream " x <- copy y\n") - 1483 (write _test-input-stream "}\n") - 1484 # convert - 1485 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1486 (flush _test-output-buffered-file) - 1487 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1493 # check output - 1494 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-local-clobbered-by-output/0") - 1495 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-local-clobbered-by-output/1") - 1496 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-local-clobbered-by-output/2") - 1497 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-local-clobbered-by-output/3") - 1498 (check-next-stream-line-equal _test-output-stream " {" "F - test-local-clobbered-by-output/4") - 1499 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-local-clobbered-by-output/5") - 1500 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-local-clobbered-by-output/6") - 1501 (check-next-stream-line-equal _test-output-stream " 89/copy-to %ecx 0x00000001/r32" "F - test-local-clobbered-by-output/7") - 1502 (check-next-stream-line-equal _test-output-stream " }" "F - test-local-clobbered-by-output/8") - 1503 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-local-clobbered-by-output/9") - 1504 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-local-clobbered-by-output/10") - 1505 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-local-clobbered-by-output/11") - 1506 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-local-clobbered-by-output/12") - 1507 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-local-clobbered-by-output/13") - 1508 # . epilogue - 1509 89/<- %esp 5/r32/ebp - 1510 5d/pop-to-ebp - 1511 c3/return - 1512 - 1513 test-convert-function-with-branches-in-block: - 1514 # . prologue - 1515 55/push-ebp - 1516 89/<- %ebp 4/r32/esp - 1517 # setup - 1518 (clear-stream _test-input-stream) - 1519 (clear-stream $_test-input-buffered-file->buffer) - 1520 (clear-stream _test-output-stream) - 1521 (clear-stream $_test-output-buffered-file->buffer) - 1522 # - 1523 (write _test-input-stream "fn foo x: int {\n") - 1524 (write _test-input-stream " {\n") - 1525 (write _test-input-stream " break-if->=\n") - 1526 (write _test-input-stream " loop-if-addr<\n") - 1527 (write _test-input-stream " increment x\n") - 1528 (write _test-input-stream " loop\n") - 1529 (write _test-input-stream " }\n") - 1530 (write _test-input-stream "}\n") - 1531 # convert - 1532 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1533 (flush _test-output-buffered-file) - 1534 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1540 # check output - 1541 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-block/0") - 1542 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-block/1") - 1543 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-block/2") - 1544 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-block/3") - 1545 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/4") - 1546 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-in-block/5") - 1547 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/6") - 1548 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-in-block/7") - 1549 (check-next-stream-line-equal _test-output-stream " 0f 8d/jump-if->= break/disp32" "F - test-convert-function-with-branches-in-block/8") - 1550 (check-next-stream-line-equal _test-output-stream " 0f 82/jump-if-addr< loop/disp32" "F - test-convert-function-with-branches-in-block/9") - 1551 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-block/10") - 1552 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-block/11") - 1553 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/12") - 1554 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-in-block/13") - 1555 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/14") - 1556 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-in-block/15") - 1557 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-block/16") - 1558 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-block/17") - 1559 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-block/18") - 1560 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-block/19") - 1561 # . epilogue - 1562 89/<- %esp 5/r32/ebp - 1563 5d/pop-to-ebp - 1564 c3/return - 1565 - 1566 test-convert-function-with-branches-in-named-block: - 1567 # . prologue - 1568 55/push-ebp - 1569 89/<- %ebp 4/r32/esp - 1570 # setup - 1571 (clear-stream _test-input-stream) - 1572 (clear-stream $_test-input-buffered-file->buffer) - 1573 (clear-stream _test-output-stream) - 1574 (clear-stream $_test-output-buffered-file->buffer) - 1575 # - 1576 (write _test-input-stream "fn foo x: int {\n") - 1577 (write _test-input-stream " $bar: {\n") - 1578 (write _test-input-stream " break-if->= $bar\n") - 1579 (write _test-input-stream " loop-if-addr< $bar\n") - 1580 (write _test-input-stream " increment x\n") - 1581 (write _test-input-stream " loop\n") - 1582 (write _test-input-stream " }\n") - 1583 (write _test-input-stream "}\n") - 1584 # convert - 1585 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1586 (flush _test-output-buffered-file) - 1587 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1593 # check output - 1594 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-named-block/0") - 1595 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-named-block/1") - 1596 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-named-block/2") - 1597 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-named-block/3") - 1598 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/4") - 1599 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-in-named-block/5") - 1600 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/6") - 1601 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-branches-in-named-block/7") - 1602 (check-next-stream-line-equal _test-output-stream " 0f 8d/jump-if->= $bar:break/disp32" "F - test-convert-function-with-branches-in-named-block/8") - 1603 (check-next-stream-line-equal _test-output-stream " 0f 82/jump-if-addr< $bar:loop/disp32" "F - test-convert-function-with-branches-in-named-block/9") - 1604 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-named-block/10") - 1605 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-named-block/11") - 1606 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/12") - 1607 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-branches-in-named-block/13") - 1608 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/14") - 1609 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-in-named-block/15") - 1610 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-named-block/16") - 1611 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-named-block/17") - 1612 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-named-block/18") - 1613 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-named-block/19") - 1614 # . epilogue - 1615 89/<- %esp 5/r32/ebp - 1616 5d/pop-to-ebp - 1617 c3/return - 1618 - 1619 test-convert-function-with-var-in-nested-block: - 1620 # . prologue - 1621 55/push-ebp - 1622 89/<- %ebp 4/r32/esp - 1623 # setup - 1624 (clear-stream _test-input-stream) - 1625 (clear-stream $_test-input-buffered-file->buffer) - 1626 (clear-stream _test-output-stream) - 1627 (clear-stream $_test-output-buffered-file->buffer) - 1628 # - 1629 (write _test-input-stream "fn foo x: int {\n") - 1630 (write _test-input-stream " {\n") - 1631 (write _test-input-stream " {\n") - 1632 (write _test-input-stream " var x: int\n") - 1633 (write _test-input-stream " increment x\n") - 1634 (write _test-input-stream " }\n") - 1635 (write _test-input-stream " }\n") - 1636 (write _test-input-stream "}\n") - 1637 # convert - 1638 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1639 (flush _test-output-buffered-file) - 1640 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1646 # check output - 1647 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-var-in-nested-block/0") - 1648 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-var-in-nested-block/1") - 1649 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-var-in-nested-block/2") - 1650 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-var-in-nested-block/3") - 1651 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/4") - 1652 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-var-in-nested-block/5") - 1653 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/6") - 1654 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-var-in-nested-block/7") - 1655 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/8") - 1656 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-var-in-nested-block/9") - 1657 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10") - 1658 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-var-in-nested-block/11") - 1659 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-var-in-nested-block/12") - 1660 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/13") - 1661 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-var-in-nested-block/14") - 1662 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/15") - 1663 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-var-in-nested-block/16") - 1664 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/17") - 1665 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-var-in-nested-block/18") - 1666 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-var-in-nested-block/19") - 1667 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-var-in-nested-block/20") - 1668 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-var-in-nested-block/21") - 1669 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-var-in-nested-block/22") - 1670 # . epilogue - 1671 89/<- %esp 5/r32/ebp - 1672 5d/pop-to-ebp - 1673 c3/return - 1674 - 1675 test-convert-function-with-multiple-vars-in-nested-blocks: - 1676 # . prologue - 1677 55/push-ebp - 1678 89/<- %ebp 4/r32/esp - 1679 # setup - 1680 (clear-stream _test-input-stream) - 1681 (clear-stream $_test-input-buffered-file->buffer) - 1682 (clear-stream _test-output-stream) - 1683 (clear-stream $_test-output-buffered-file->buffer) - 1684 # - 1685 (write _test-input-stream "fn foo x: int {\n") - 1686 (write _test-input-stream " {\n") - 1687 (write _test-input-stream " var x/eax: int <- copy 0\n") - 1688 (write _test-input-stream " {\n") - 1689 (write _test-input-stream " var y: int\n") - 1690 (write _test-input-stream " x <- add y\n") - 1691 (write _test-input-stream " }\n") - 1692 (write _test-input-stream " }\n") - 1693 (write _test-input-stream "}\n") - 1694 # convert - 1695 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1696 (flush _test-output-buffered-file) - 1697 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1703 # check output - 1704 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/0") - 1705 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-multiple-vars-in-nested-blocks/1") - 1706 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/2") - 1707 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/3") - 1708 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/4") - 1709 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/5") - 1710 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/6") - 1711 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/7") - 1712 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-with-multiple-vars-in-nested-blocks/8") - 1713 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/9") - 1714 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/10") - 1715 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/11") - 1716 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12") - 1717 (check-next-stream-line-equal _test-output-stream " 03/add *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/13") - 1718 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/14") - 1719 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/15") - 1720 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/16") - 1721 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-with-multiple-vars-in-nested-blocks/17") - 1722 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/18") - 1723 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/19") - 1724 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/20") - 1725 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/21") - 1726 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-multiple-vars-in-nested-blocks/22") - 1727 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/23") - 1728 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/24") - 1729 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-multiple-vars-in-nested-blocks/25") - 1730 # . epilogue - 1731 89/<- %esp 5/r32/ebp - 1732 5d/pop-to-ebp - 1733 c3/return - 1734 - 1735 test-convert-function-with-branches-and-local-vars: - 1736 # A conditional 'break' after a 'var' in a block is converted into a - 1737 # nested block that performs all necessary cleanup before jumping. This - 1738 # results in some ugly code duplication. - 1739 # . prologue - 1740 55/push-ebp - 1741 89/<- %ebp 4/r32/esp - 1742 # setup - 1743 (clear-stream _test-input-stream) - 1744 (clear-stream $_test-input-buffered-file->buffer) - 1745 (clear-stream _test-output-stream) - 1746 (clear-stream $_test-output-buffered-file->buffer) - 1747 # - 1748 (write _test-input-stream "fn foo {\n") - 1749 (write _test-input-stream " {\n") - 1750 (write _test-input-stream " var x: int\n") - 1751 (write _test-input-stream " break-if->=\n") - 1752 (write _test-input-stream " increment x\n") - 1753 (write _test-input-stream " }\n") - 1754 (write _test-input-stream "}\n") - 1755 # convert - 1756 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1757 (flush _test-output-buffered-file) - 1758 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1764 # check output - 1765 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-local-vars/0") - 1766 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-local-vars/1") - 1767 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-local-vars/2") - 1768 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-and-local-vars/3") - 1769 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/4") - 1770 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-and-local-vars/5") - 1771 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/6") - 1772 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-and-local-vars/7") - 1773 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-local-vars/8") - 1774 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/9") - 1775 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-branches-and-local-vars/10") - 1776 (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") - 1777 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:break/disp32" "F - test-convert-function-with-branches-and-local-vars/12") - 1778 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/13") - 1779 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-branches-and-local-vars/14") - 1780 (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") - 1781 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/16") - 1782 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-and-local-vars/17") - 1783 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/18") - 1784 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-and-local-vars/19") - 1785 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-local-vars/20") - 1786 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-and-local-vars/21") - 1787 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-local-vars/22") - 1788 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-local-vars/23") - 1789 # . epilogue - 1790 89/<- %esp 5/r32/ebp - 1791 5d/pop-to-ebp - 1792 c3/return - 1793 - 1794 test-convert-function-with-conditional-loops-and-local-vars: - 1795 # A conditional 'loop' after a 'var' in a block is converted into a nested - 1796 # block that performs all necessary cleanup before jumping. This results - 1797 # in some ugly code duplication. - 1798 # . prologue - 1799 55/push-ebp - 1800 89/<- %ebp 4/r32/esp - 1801 # setup - 1802 (clear-stream _test-input-stream) - 1803 (clear-stream $_test-input-buffered-file->buffer) - 1804 (clear-stream _test-output-stream) - 1805 (clear-stream $_test-output-buffered-file->buffer) - 1806 # - 1807 (write _test-input-stream "fn foo {\n") - 1808 (write _test-input-stream " {\n") - 1809 (write _test-input-stream " var x: int\n") - 1810 (write _test-input-stream " loop-if->=\n") - 1811 (write _test-input-stream " increment x\n") - 1812 (write _test-input-stream " }\n") - 1813 (write _test-input-stream "}\n") - 1814 # convert - 1815 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1816 (flush _test-output-buffered-file) - 1817 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1823 # check output - 1824 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-conditional-loops-and-local-vars/0") - 1825 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-conditional-loops-and-local-vars/1") - 1826 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/2") - 1827 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-conditional-loops-and-local-vars/3") - 1828 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/4") - 1829 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-conditional-loops-and-local-vars/5") - 1830 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/6") - 1831 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-conditional-loops-and-local-vars/7") - 1832 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-conditional-loops-and-local-vars/8") - 1833 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/9") - 1834 (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") - 1835 (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") - 1836 (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") - 1837 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/13") - 1838 (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") - 1839 (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") - 1840 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/16") - 1841 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-conditional-loops-and-local-vars/17") - 1842 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/18") - 1843 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-conditional-loops-and-local-vars/19") - 1844 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-conditional-loops-and-local-vars/20") - 1845 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/21") - 1846 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/22") - 1847 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-conditional-loops-and-local-vars/23") - 1848 # . epilogue - 1849 89/<- %esp 5/r32/ebp - 1850 5d/pop-to-ebp - 1851 c3/return - 1852 - 1853 test-convert-function-with-unconditional-loops-and-local-vars: - 1854 # An unconditional 'loop' after a 'var' in a block is emitted _after_ the - 1855 # regular block cleanup. Any instructions after 'loop' are dead and - 1856 # therefore skipped. - 1857 # . prologue - 1858 55/push-ebp - 1859 89/<- %ebp 4/r32/esp - 1860 # setup - 1861 (clear-stream _test-input-stream) - 1862 (clear-stream $_test-input-buffered-file->buffer) - 1863 (clear-stream _test-output-stream) - 1864 (clear-stream $_test-output-buffered-file->buffer) - 1865 # - 1866 (write _test-input-stream "fn foo {\n") - 1867 (write _test-input-stream " {\n") - 1868 (write _test-input-stream " var x: int\n") - 1869 (write _test-input-stream " loop\n") - 1870 (write _test-input-stream " increment x\n") - 1871 (write _test-input-stream " }\n") - 1872 (write _test-input-stream "}\n") - 1873 # convert - 1874 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1875 (flush _test-output-buffered-file) - 1876 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1882 # check output - 1883 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-unconditional-loops-and-local-vars/0") - 1884 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-unconditional-loops-and-local-vars/1") - 1885 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/2") - 1886 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-unconditional-loops-and-local-vars/3") - 1887 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-loops-and-local-vars/4") - 1888 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-unconditional-loops-and-local-vars/5") - 1889 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-loops-and-local-vars/6") - 1890 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-unconditional-loops-and-local-vars/7") - 1891 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-loops-and-local-vars/8") - 1892 (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") - 1893 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-unconditional-loops-and-local-vars/10") - 1894 # not emitted: ff 0/subop/increment *(ebp+0xfffffffc) - 1895 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-loops-and-local-vars/11") - 1896 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-unconditional-loops-and-local-vars/12") - 1897 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-loops-and-local-vars/13") - 1898 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-unconditional-loops-and-local-vars/14") - 1899 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-unconditional-loops-and-local-vars/15") - 1900 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/16") - 1901 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/17") - 1902 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-unconditional-loops-and-local-vars/18") - 1903 # . epilogue - 1904 89/<- %esp 5/r32/ebp - 1905 5d/pop-to-ebp - 1906 c3/return - 1907 - 1908 test-convert-function-with-branches-and-loops-and-local-vars: - 1909 # . prologue - 1910 55/push-ebp - 1911 89/<- %ebp 4/r32/esp - 1912 # setup - 1913 (clear-stream _test-input-stream) - 1914 (clear-stream $_test-input-buffered-file->buffer) - 1915 (clear-stream _test-output-stream) - 1916 (clear-stream $_test-output-buffered-file->buffer) - 1917 # - 1918 (write _test-input-stream "fn foo {\n") - 1919 (write _test-input-stream " {\n") - 1920 (write _test-input-stream " var x: int\n") - 1921 (write _test-input-stream " break-if->=\n") - 1922 (write _test-input-stream " increment x\n") - 1923 (write _test-input-stream " loop\n") - 1924 (write _test-input-stream " }\n") - 1925 (write _test-input-stream "}\n") - 1926 # convert - 1927 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1928 (flush _test-output-buffered-file) - 1929 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1935 # check output - 1936 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-loops-and-local-vars/0") - 1937 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-loops-and-local-vars/1") - 1938 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/2") - 1939 (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") - 1940 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/4") - 1941 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-and-loops-and-local-vars/5") - 1942 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/6") - 1943 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-and-loops-and-local-vars/7") - 1944 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-loops-and-local-vars/8") - 1945 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/9") - 1946 (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") - 1947 (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") - 1948 (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") - 1949 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/13") - 1950 (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") - 1951 (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") - 1952 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-and-loops-and-local-vars/16") - 1953 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/17") - 1954 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-and-loops-and-local-vars/18") - 1955 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/19") - 1956 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-and-loops-and-local-vars/20") - 1957 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-loops-and-local-vars/21") - 1958 (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") - 1959 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/23") - 1960 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-loops-and-local-vars/24") - 1961 # . epilogue - 1962 89/<- %esp 5/r32/ebp - 1963 5d/pop-to-ebp - 1964 c3/return - 1965 - 1966 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars: - 1967 # . prologue - 1968 55/push-ebp - 1969 89/<- %ebp 4/r32/esp - 1970 # setup - 1971 (clear-stream _test-input-stream) - 1972 (clear-stream $_test-input-buffered-file->buffer) - 1973 (clear-stream _test-output-stream) - 1974 (clear-stream $_test-output-buffered-file->buffer) - 1975 # - 1976 (write _test-input-stream "fn foo {\n") - 1977 (write _test-input-stream " a: {\n") - 1978 (write _test-input-stream " var x: int\n") - 1979 (write _test-input-stream " {\n") - 1980 (write _test-input-stream " var y: int\n") - 1981 (write _test-input-stream " break-if->= a\n") - 1982 (write _test-input-stream " increment x\n") - 1983 (write _test-input-stream " loop\n") - 1984 (write _test-input-stream " }\n") - 1985 (write _test-input-stream " }\n") - 1986 (write _test-input-stream "}\n") - 1987 # convert - 1988 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 1989 (flush _test-output-buffered-file) - 1990 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 1996 # check output - 1997 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0") - 1998 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1") - 1999 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2") - 2000 (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") - 2001 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4") - 2002 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5") - 2003 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6") - 2004 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7") - 2005 (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") - 2006 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9") - 2007 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10") - 2008 (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") - 2009 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12") - 2010 (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") - 2011 (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") - 2012 (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") - 2013 (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") - 2014 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17") - 2015 (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") - 2016 (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") - 2017 (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") - 2018 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21") - 2019 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22") - 2020 (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") - 2021 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24") - 2022 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25") - 2023 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26") - 2024 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27") - 2025 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28") - 2026 (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") - 2027 (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") - 2028 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31") - 2029 # . epilogue - 2030 89/<- %esp 5/r32/ebp - 2031 5d/pop-to-ebp - 2032 c3/return - 2033 - 2034 test-convert-function-with-nonlocal-unconditional-break-and-local-vars: - 2035 # . prologue - 2036 55/push-ebp - 2037 89/<- %ebp 4/r32/esp - 2038 # setup - 2039 (clear-stream _test-input-stream) - 2040 (clear-stream $_test-input-buffered-file->buffer) - 2041 (clear-stream _test-output-stream) - 2042 (clear-stream $_test-output-buffered-file->buffer) - 2043 # - 2044 (write _test-input-stream "fn foo {\n") - 2045 (write _test-input-stream " a: {\n") - 2046 (write _test-input-stream " var x: int\n") - 2047 (write _test-input-stream " {\n") - 2048 (write _test-input-stream " var y: int\n") - 2049 (write _test-input-stream " break a\n") - 2050 (write _test-input-stream " increment x\n") - 2051 (write _test-input-stream " }\n") - 2052 (write _test-input-stream " }\n") - 2053 (write _test-input-stream "}\n") - 2054 # convert - 2055 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2056 (flush _test-output-buffered-file) - 2057 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2063 # check output - 2064 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0") - 2065 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1") - 2066 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2") - 2067 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/3") - 2068 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4") - 2069 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5") - 2070 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6") - 2071 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7") - 2072 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8") - 2073 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9") - 2074 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10") - 2075 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11") - 2076 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/12") - 2077 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/13") - 2078 (check-next-stream-line-equal _test-output-stream " e9/jump a:break/disp32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/14") - 2079 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15") - 2080 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16") - 2081 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/17") - 2082 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18") - 2083 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19") - 2084 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20") - 2085 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21") - 2086 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22") - 2087 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/23") - 2088 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24") - 2089 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25") - 2090 # . epilogue - 2091 89/<- %esp 5/r32/ebp - 2092 5d/pop-to-ebp - 2093 c3/return - 2094 - 2095 test-convert-function-with-unconditional-break-and-local-vars: - 2096 # . prologue - 2097 55/push-ebp - 2098 89/<- %ebp 4/r32/esp - 2099 # setup - 2100 (clear-stream _test-input-stream) - 2101 (clear-stream $_test-input-buffered-file->buffer) - 2102 (clear-stream _test-output-stream) - 2103 (clear-stream $_test-output-buffered-file->buffer) - 2104 # - 2105 (write _test-input-stream "fn foo {\n") - 2106 (write _test-input-stream " {\n") - 2107 (write _test-input-stream " var x: int\n") - 2108 (write _test-input-stream " {\n") - 2109 (write _test-input-stream " var y: int\n") - 2110 (write _test-input-stream " break\n") - 2111 (write _test-input-stream " increment x\n") - 2112 (write _test-input-stream " }\n") - 2113 (write _test-input-stream " }\n") - 2114 (write _test-input-stream "}\n") - 2115 # convert - 2116 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2117 (flush _test-output-buffered-file) - 2118 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2124 # check output - 2125 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-unconditional-break-and-local-vars/0") - 2126 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-unconditional-break-and-local-vars/1") - 2127 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/2") - 2128 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-unconditional-break-and-local-vars/3") - 2129 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/4") - 2130 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/5") - 2131 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/6") - 2132 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/7") - 2133 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/8") - 2134 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/9") - 2135 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/10") - 2136 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11") - 2137 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/12") - 2138 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/13") - 2139 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/14") - 2140 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/15") - 2141 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/16") - 2142 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/17") - 2143 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/18") - 2144 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/19") - 2145 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-unconditional-break-and-local-vars/20") - 2146 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/21") - 2147 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/22") - 2148 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-unconditional-break-and-local-vars/23") - 2149 # . epilogue - 2150 89/<- %esp 5/r32/ebp - 2151 5d/pop-to-ebp - 2152 c3/return - 2153 - 2154 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars: - 2155 # . prologue - 2156 55/push-ebp - 2157 89/<- %ebp 4/r32/esp - 2158 # setup - 2159 (clear-stream _test-input-stream) - 2160 (clear-stream $_test-input-buffered-file->buffer) - 2161 (clear-stream _test-output-stream) - 2162 (clear-stream $_test-output-buffered-file->buffer) - 2163 # - 2164 (write _test-input-stream "fn foo {\n") - 2165 (write _test-input-stream " a: {\n") - 2166 (write _test-input-stream " var x: int\n") - 2167 (write _test-input-stream " {\n") - 2168 (write _test-input-stream " var y: int\n") - 2169 (write _test-input-stream " loop a\n") - 2170 (write _test-input-stream " increment x\n") - 2171 (write _test-input-stream " }\n") - 2172 (write _test-input-stream " }\n") - 2173 (write _test-input-stream "}\n") - 2174 # convert - 2175 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2176 (flush _test-output-buffered-file) - 2177 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2183 # check output - 2184 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0") - 2185 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1") - 2186 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2") - 2187 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/3") - 2188 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4") - 2189 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5") - 2190 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6") - 2191 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7") - 2192 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8") - 2193 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9") - 2194 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10") - 2195 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11") - 2196 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/12") - 2197 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/13") - 2198 (check-next-stream-line-equal _test-output-stream " e9/jump a:loop/disp32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/14") - 2199 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15") - 2200 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16") - 2201 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/17") - 2202 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18") - 2203 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19") - 2204 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20") - 2205 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21") - 2206 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22") - 2207 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/23") - 2208 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24") - 2209 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25") - 2210 # . epilogue - 2211 89/<- %esp 5/r32/ebp - 2212 5d/pop-to-ebp - 2213 c3/return - 2214 - 2215 test-convert-function-with-local-array-var-in-mem: - 2216 # . prologue - 2217 55/push-ebp - 2218 89/<- %ebp 4/r32/esp - 2219 # setup - 2220 (clear-stream _test-input-stream) - 2221 (clear-stream $_test-input-buffered-file->buffer) - 2222 (clear-stream _test-output-stream) - 2223 (clear-stream $_test-output-buffered-file->buffer) - 2224 # - 2225 (write _test-input-stream "fn foo {\n") - 2226 (write _test-input-stream " var x: (array int 3)\n") - 2227 (write _test-input-stream "}\n") - 2228 # convert - 2229 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2230 (flush _test-output-buffered-file) - 2231 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2237 # check output - 2238 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-array-var-in-mem/0") - 2239 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-array-var-in-mem/1") - 2240 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-array-var-in-mem/2") - 2241 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-array-var-in-mem/3") - 2242 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-array-var-in-mem/4") - 2243 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-array-var-in-mem/5") - 2244 # define x - 2245 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x0000000c)" "F - test-convert-function-with-local-array-var-in-mem/7") - 2246 (check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-function-with-local-array-var-in-mem/8") - 2247 # reclaim x - 2248 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-function-with-local-array-var-in-mem/9") - 2249 # - 2250 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-array-var-in-mem/10") - 2251 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-array-var-in-mem/11") - 2252 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-array-var-in-mem/12") - 2253 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-array-var-in-mem/13") - 2254 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-array-var-in-mem/14") - 2255 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-array-var-in-mem/15") - 2256 # . epilogue - 2257 89/<- %esp 5/r32/ebp - 2258 5d/pop-to-ebp - 2259 c3/return - 2260 - 2261 test-convert-address: - 2262 # . prologue - 2263 55/push-ebp - 2264 89/<- %ebp 4/r32/esp - 2265 # setup - 2266 (clear-stream _test-input-stream) - 2267 (clear-stream $_test-input-buffered-file->buffer) - 2268 (clear-stream _test-output-stream) - 2269 (clear-stream $_test-output-buffered-file->buffer) - 2270 # - 2271 (write _test-input-stream "fn foo {\n") - 2272 (write _test-input-stream " var a: int\n") - 2273 (write _test-input-stream " var b/eax: (addr int) <- address a\n") - 2274 (write _test-input-stream "}\n") - 2275 # convert - 2276 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2277 (flush _test-output-buffered-file) - 2278 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2284 # check output - 2285 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-address/0") - 2286 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-address/1") - 2287 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-address/2") - 2288 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-address/3") - 2289 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-address/4") - 2290 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-address/5") - 2291 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-address/6") - 2292 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-address/7") - 2293 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32" "F - test-convert-address/8") - 2294 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-address/9") - 2295 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-address/10") - 2296 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-address/11") - 2297 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-address/12") - 2298 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-address/13") - 2299 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-address/14") - 2300 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-address/15") - 2301 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-address/16") - 2302 # . epilogue - 2303 89/<- %esp 5/r32/ebp - 2304 5d/pop-to-ebp - 2305 c3/return - 2306 - 2307 test-convert-length-of-array: - 2308 # . prologue - 2309 55/push-ebp - 2310 89/<- %ebp 4/r32/esp - 2311 # setup - 2312 (clear-stream _test-input-stream) - 2313 (clear-stream $_test-input-buffered-file->buffer) - 2314 (clear-stream _test-output-stream) - 2315 (clear-stream $_test-output-buffered-file->buffer) - 2316 # - 2317 (write _test-input-stream "fn foo a: (addr array int) {\n") - 2318 (write _test-input-stream " var b/eax: (addr array int) <- copy a\n") - 2319 (write _test-input-stream " var c/eax: int <- length b\n") - 2320 (write _test-input-stream "}\n") - 2321 # convert - 2322 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2323 (flush _test-output-buffered-file) - 2324 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2330 # check output - 2331 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array/0") - 2332 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array/1") - 2333 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array/2") - 2334 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array/3") - 2335 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array/4") - 2336 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array/5") - 2337 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/6") - 2338 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-length-of-array/7") - 2339 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *eax 0x00000000/r32" "F - test-convert-length-of-array/9") - 2340 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/11") - 2341 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array/12") - 2342 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array/13") - 2343 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array/14") - 2344 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array/15") - 2345 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array/16") - 2346 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array/17") - 2347 # . epilogue - 2348 89/<- %esp 5/r32/ebp - 2349 5d/pop-to-ebp - 2350 c3/return - 2351 - 2352 test-convert-length-of-array-on-stack: - 2353 # . prologue - 2354 55/push-ebp - 2355 89/<- %ebp 4/r32/esp - 2356 # setup - 2357 (clear-stream _test-input-stream) - 2358 (clear-stream $_test-input-buffered-file->buffer) - 2359 (clear-stream _test-output-stream) - 2360 (clear-stream $_test-output-buffered-file->buffer) - 2361 # - 2362 (write _test-input-stream "fn foo {\n") - 2363 (write _test-input-stream " var a: (array int 3)\n") - 2364 (write _test-input-stream " var b/eax: int <- length a\n") - 2365 (write _test-input-stream "}\n") - 2366 # convert - 2367 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2368 (flush _test-output-buffered-file) - 2369 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2375 # check output - 2376 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array-on-stack/0") - 2377 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array-on-stack/1") - 2378 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array-on-stack/2") - 2379 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array-on-stack/3") - 2380 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array-on-stack/4") - 2381 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array-on-stack/5") - 2382 # define x - 2383 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x0000000c)" "F - test-convert-length-of-array-on-stack/6") - 2384 (check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-length-of-array-on-stack/7") - 2385 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array-on-stack/8") - 2386 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0xfffffff0) 0x00000000/r32" "F - test-convert-length-of-array-on-stack/9") - 2387 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array-on-stack/10") - 2388 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-length-of-array-on-stack/11") - 2389 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array-on-stack/12") - 2390 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array-on-stack/13") - 2391 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array-on-stack/14") - 2392 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array-on-stack/15") - 2393 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array-on-stack/16") - 2394 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array-on-stack/17") - 2395 # . epilogue - 2396 89/<- %esp 5/r32/ebp - 2397 5d/pop-to-ebp - 2398 c3/return - 2399 - 2400 test-convert-index-into-array: - 2401 # . prologue - 2402 55/push-ebp - 2403 89/<- %ebp 4/r32/esp - 2404 # setup - 2405 (clear-stream _test-input-stream) - 2406 (clear-stream $_test-input-buffered-file->buffer) - 2407 (clear-stream _test-output-stream) - 2408 (clear-stream $_test-output-buffered-file->buffer) - 2409 # - 2410 (write _test-input-stream "fn foo {\n") - 2411 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") - 2412 (write _test-input-stream " var idx/ecx: int <- copy 3\n") - 2413 (write _test-input-stream " var x/eax: (addr int) <- index arr, idx\n") - 2414 (write _test-input-stream "}\n") - 2415 # convert - 2416 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2417 (flush _test-output-buffered-file) - 2418 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2424 # check output - 2425 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array/0") - 2426 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array/1") - 2427 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array/2") - 2428 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array/3") - 2429 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array/4") - 2430 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array/5") - 2431 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array/6") - 2432 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array/7") - 2433 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array/8") - 2434 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-index-into-array/9") - 2435 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32" "F - test-convert-index-into-array/11") - 2436 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array/13") - 2437 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array/14") - 2438 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array/15") - 2439 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array/16") - 2440 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array/17") - 2441 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array/18") - 2442 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array/19") - 2443 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array/20") - 2444 # . epilogue - 2445 89/<- %esp 5/r32/ebp - 2446 5d/pop-to-ebp - 2447 c3/return - 2448 - 2449 test-convert-index-into-array-with-literal: - 2450 # . prologue - 2451 55/push-ebp - 2452 89/<- %ebp 4/r32/esp - 2453 # setup - 2454 (clear-stream _test-input-stream) - 2455 (clear-stream $_test-input-buffered-file->buffer) - 2456 (clear-stream _test-output-stream) - 2457 (clear-stream $_test-output-buffered-file->buffer) - 2458 # - 2459 (write _test-input-stream "fn foo {\n") - 2460 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") - 2461 (write _test-input-stream " var x/eax: (addr int) <- index arr, 2\n") - 2462 (write _test-input-stream "}\n") - 2463 # convert - 2464 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2465 (flush _test-output-buffered-file) - 2466 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2472 # check output - 2473 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-with-literal/0") - 2474 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-with-literal/1") - 2475 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-with-literal/2") - 2476 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-with-literal/3") - 2477 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-with-literal/4") - 2478 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-with-literal/5") - 2479 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-with-literal/6") - 2480 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-with-literal/7") - 2481 # 2 * 4 bytes/elem + 4 bytes for length = offset 12 - 2482 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x0000000c) 0x00000000/r32" "F - test-convert-index-into-array-with-literal/8") - 2483 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-with-literal/9") - 2484 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-with-literal/10") - 2485 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-with-literal/11") - 2486 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-with-literal/12") - 2487 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-with-literal/13") - 2488 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-with-literal/14") - 2489 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-with-literal/15") - 2490 # . epilogue - 2491 89/<- %esp 5/r32/ebp - 2492 5d/pop-to-ebp - 2493 c3/return - 2494 - 2495 test-convert-index-into-array-on-stack: - 2496 # . prologue - 2497 55/push-ebp - 2498 89/<- %ebp 4/r32/esp - 2499 # setup - 2500 (clear-stream _test-input-stream) - 2501 (clear-stream $_test-input-buffered-file->buffer) - 2502 (clear-stream _test-output-stream) - 2503 (clear-stream $_test-output-buffered-file->buffer) - 2504 # - 2505 (write _test-input-stream "fn foo {\n") - 2506 (write _test-input-stream " var arr: (array int 3)\n") - 2507 (write _test-input-stream " var idx/eax: int <- copy 2\n") - 2508 (write _test-input-stream " var x/eax: (addr int) <- index arr, idx\n") - 2509 (write _test-input-stream "}\n") - 2510 # convert - 2511 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2512 (flush _test-output-buffered-file) - 2513 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2519 # check output - 2520 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-on-stack/0") - 2521 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-on-stack/1") - 2522 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-on-stack/2") - 2523 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-on-stack/3") - 2524 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-on-stack/4") - 2525 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-on-stack/5") - 2526 # var arr - 2527 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x0000000c)" "F - test-convert-index-into-array-on-stack/6") - 2528 (check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-index-into-array-on-stack/7") - 2529 # var idx - 2530 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-on-stack/8") - 2531 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 2/imm32" "F - test-convert-index-into-array-on-stack/9") - 2532 # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc - 2533 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + eax<<0x00000002 + 0xfffffff4) 0x00000000/r32" "F - test-convert-index-into-array-on-stack/10") - 2534 # reclaim idx - 2535 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-on-stack/11") - 2536 # reclaim arr - 2537 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-index-into-array-on-stack/12") - 2538 # - 2539 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-on-stack/13") - 2540 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-on-stack/14") - 2541 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-on-stack/15") - 2542 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-on-stack/16") - 2543 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-on-stack/17") - 2544 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-on-stack/18") - 2545 # . epilogue - 2546 89/<- %esp 5/r32/ebp - 2547 5d/pop-to-ebp - 2548 c3/return - 2549 - 2550 test-convert-index-into-array-on-stack-with-literal: - 2551 # . prologue - 2552 55/push-ebp - 2553 89/<- %ebp 4/r32/esp - 2554 # setup - 2555 (clear-stream _test-input-stream) - 2556 (clear-stream $_test-input-buffered-file->buffer) - 2557 (clear-stream _test-output-stream) - 2558 (clear-stream $_test-output-buffered-file->buffer) - 2559 # - 2560 (write _test-input-stream "fn foo {\n") - 2561 (write _test-input-stream " var arr: (array int 3)\n") - 2562 (write _test-input-stream " var x/eax: (addr int) <- index arr, 2\n") - 2563 (write _test-input-stream "}\n") - 2564 # convert - 2565 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2566 (flush _test-output-buffered-file) - 2567 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2573 # check output - 2574 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-on-stack-with-literal/0") - 2575 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-on-stack-with-literal/1") - 2576 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-on-stack-with-literal/2") - 2577 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-on-stack-with-literal/3") - 2578 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-on-stack-with-literal/4") - 2579 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-on-stack-with-literal/5") - 2580 # var arr - 2581 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x0000000c)" "F - test-convert-index-into-array-on-stack-with-literal/6") - 2582 (check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-index-into-array-on-stack-with-literal/7") - 2583 # var x - 2584 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-on-stack-with-literal/8") - 2585 # x is at (ebp-0x10) + 4 + 2*4 = ebp-4 - 2586 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + 0xfffffffc) 0x00000000/r32" "F - test-convert-index-into-array-on-stack-with-literal/9") - 2587 # reclaim x - 2588 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-on-stack-with-literal/10") - 2589 # reclaim arr - 2590 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-index-into-array-on-stack-with-literal/11") - 2591 # - 2592 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-on-stack-with-literal/12") - 2593 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-on-stack-with-literal/13") - 2594 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-on-stack-with-literal/14") - 2595 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-on-stack-with-literal/15") - 2596 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-on-stack-with-literal/16") - 2597 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-on-stack-with-literal/17") - 2598 # . epilogue - 2599 89/<- %esp 5/r32/ebp - 2600 5d/pop-to-ebp - 2601 c3/return - 2602 - 2603 test-convert-index-into-array-using-offset: - 2604 # . prologue - 2605 55/push-ebp - 2606 89/<- %ebp 4/r32/esp - 2607 # setup - 2608 (clear-stream _test-input-stream) - 2609 (clear-stream $_test-input-buffered-file->buffer) - 2610 (clear-stream _test-output-stream) - 2611 (clear-stream $_test-output-buffered-file->buffer) - 2612 # - 2613 (write _test-input-stream "fn foo {\n") - 2614 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") - 2615 (write _test-input-stream " var idx/ecx: int <- copy 3\n") - 2616 (write _test-input-stream " var off/ecx: (offset int) <- compute-offset arr, idx\n") - 2617 (write _test-input-stream " var x/eax: (addr int) <- index arr, off\n") - 2618 (write _test-input-stream "}\n") - 2619 # convert - 2620 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2621 (flush _test-output-buffered-file) - 2622 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2628 # check output - 2629 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-using-offset/0") - 2630 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-using-offset/1") - 2631 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-using-offset/2") - 2632 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-using-offset/3") - 2633 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-using-offset/4") - 2634 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-using-offset/5") - 2635 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-using-offset/6") - 2636 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-using-offset/7") - 2637 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-using-offset/8") - 2638 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-index-into-array-using-offset/9") - 2639 (check-next-stream-line-equal _test-output-stream " 69/multiply 0x00000004/imm32 %ecx 0x00000001/r32" "F - test-convert-index-into-array-using-offset/10") - 2640 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-using-offset/11") - 2641 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-using-offset/12") - 2642 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-using-offset/13") - 2643 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-using-offset/14") - 2644 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-using-offset/15") - 2645 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-using-offset/16") - 2646 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-using-offset/17") - 2647 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-using-offset/18") - 2648 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-using-offset/19") - 2649 # . epilogue - 2650 89/<- %esp 5/r32/ebp - 2651 5d/pop-to-ebp - 2652 c3/return - 2653 - 2654 test-convert-index-into-array-using-offset-on-stack: - 2655 # . prologue - 2656 55/push-ebp - 2657 89/<- %ebp 4/r32/esp - 2658 # setup - 2659 (clear-stream _test-input-stream) - 2660 (clear-stream $_test-input-buffered-file->buffer) - 2661 (clear-stream _test-output-stream) - 2662 (clear-stream $_test-output-buffered-file->buffer) - 2663 # - 2664 (write _test-input-stream "fn foo {\n") - 2665 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") - 2666 (write _test-input-stream " var idx: int\n") - 2667 (write _test-input-stream " var off/ecx: (offset int) <- compute-offset arr, idx\n") - 2668 (write _test-input-stream " var x/eax: (addr int) <- index arr, off\n") - 2669 (write _test-input-stream "}\n") - 2670 # convert - 2671 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2672 (flush _test-output-buffered-file) - 2673 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2679 # check output - 2680 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-using-offset-on-stack/0") - 2681 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-using-offset-on-stack/1") - 2682 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-using-offset-on-stack/2") - 2683 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-using-offset-on-stack/3") - 2684 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-using-offset-on-stack/4") - 2685 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-using-offset-on-stack/5") - 2686 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-using-offset-on-stack/6") - 2687 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-using-offset-on-stack/7") - 2688 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-index-into-array-using-offset-on-stack/8") - 2689 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-using-offset-on-stack/9") - 2690 (check-next-stream-line-equal _test-output-stream " 69/multiply 0x00000004/imm32 *(ebp+0xfffffff8) 0x00000001/r32" "F - test-convert-index-into-array-using-offset-on-stack/10") - 2691 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-using-offset-on-stack/11") - 2692 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-using-offset-on-stack/12") - 2693 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-index-into-array-using-offset-on-stack/13") - 2694 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-using-offset-on-stack/14") - 2695 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-using-offset-on-stack/15") - 2696 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-using-offset-on-stack/16") - 2697 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-using-offset-on-stack/17") - 2698 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-using-offset-on-stack/18") - 2699 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-using-offset-on-stack/19") - 2700 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-using-offset-on-stack/20") - 2701 # . epilogue - 2702 89/<- %esp 5/r32/ebp - 2703 5d/pop-to-ebp - 2704 c3/return - 2705 - 2706 test-convert-function-and-type-definition: - 2707 # . prologue - 2708 55/push-ebp - 2709 89/<- %ebp 4/r32/esp - 2710 # setup - 2711 (clear-stream _test-input-stream) - 2712 (clear-stream $_test-input-buffered-file->buffer) - 2713 (clear-stream _test-output-stream) - 2714 (clear-stream $_test-output-buffered-file->buffer) - 2715 # - 2716 (write _test-input-stream "fn foo a: (addr t) {\n") - 2717 (write _test-input-stream " var _a/eax: (addr t) <- copy a\n") - 2718 (write _test-input-stream " var b/ecx: (addr int) <- get _a, x\n") - 2719 (write _test-input-stream " var c/ecx: (addr int) <- get _a, y\n") - 2720 (write _test-input-stream "}\n") - 2721 (write _test-input-stream "type t {\n") - 2722 (write _test-input-stream " x: int\n") - 2723 (write _test-input-stream " y: int\n") + 855 (write _test-input-stream "fn do-add a: int, b: int -> result/ebx: int {\n") + 856 (write _test-input-stream " result <- copy a\n") + 857 (write _test-input-stream " result <- add b\n") + 858 (write _test-input-stream "}\n") + 859 # convert + 860 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 861 (flush _test-output-buffered-file) + 862 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 868 # check output + 869 (check-next-stream-line-equal _test-output-stream "main:" "F - test-convert-function-call-with-literal-arg/0") + 870 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/1") + 871 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/2") + 872 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/3") + 873 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/4") + 874 (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:" "F - test-convert-function-call-with-literal-arg/5") + 875 (check-next-stream-line-equal _test-output-stream " (do-add 3 4)" "F - test-convert-function-call-with-literal-arg/6") + 876 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/7") + 877 (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/8") + 878 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/9") + 879 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/10") + 880 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/11") + 881 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/12") + 882 (check-next-stream-line-equal _test-output-stream "do-add:" "F - test-convert-function-call-with-literal-arg/13") + 883 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/14") + 884 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/15") + 885 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/16") + 886 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/17") + 887 (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:" "F - test-convert-function-call-with-literal-arg/18") + 888 (check-next-stream-line-equal _test-output-stream " 8b/-> *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/19") + 889 (check-next-stream-line-equal _test-output-stream " 03/add *(ebp+0x0000000c) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/20") + 890 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/21") + 891 (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:" "F - test-convert-function-call-with-literal-arg/22") + 892 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/23") + 893 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/24") + 894 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/25") + 895 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/26") + 896 # . epilogue + 897 89/<- %esp 5/r32/ebp + 898 5d/pop-to-ebp + 899 c3/return + 900 + 901 test-convert-function-with-local-var-in-mem: + 902 # . prologue + 903 55/push-ebp + 904 89/<- %ebp 4/r32/esp + 905 # setup + 906 (clear-stream _test-input-stream) + 907 (clear-stream $_test-input-buffered-file->buffer) + 908 (clear-stream _test-output-stream) + 909 (clear-stream $_test-output-buffered-file->buffer) + 910 # + 911 (write _test-input-stream "fn foo {\n") + 912 (write _test-input-stream " var x: int\n") + 913 (write _test-input-stream " increment x\n") + 914 (write _test-input-stream "}\n") + 915 # convert + 916 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 917 (flush _test-output-buffered-file) + 918 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 924 # check output + 925 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-mem/0") + 926 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-mem/1") + 927 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-mem/2") + 928 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-mem/3") + 929 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-mem/4") + 930 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-mem/5") + 931 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-mem/6") + 932 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-mem/7") + 933 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-in-mem/8") + 934 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-mem/9") + 935 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-mem/10") + 936 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-mem/11") + 937 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-mem/12") + 938 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-mem/13") + 939 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-mem/14") + 940 # . epilogue + 941 89/<- %esp 5/r32/ebp + 942 5d/pop-to-ebp + 943 c3/return + 944 + 945 test-convert-function-with-local-var-with-compound-type-in-mem: + 946 # . prologue + 947 55/push-ebp + 948 89/<- %ebp 4/r32/esp + 949 # setup + 950 (clear-stream _test-input-stream) + 951 (clear-stream $_test-input-buffered-file->buffer) + 952 (clear-stream _test-output-stream) + 953 (clear-stream $_test-output-buffered-file->buffer) + 954 # + 955 (write _test-input-stream "fn foo {\n") + 956 (write _test-input-stream " var x: (addr int)\n") + 957 (write _test-input-stream " copy-to x, 0\n") + 958 (write _test-input-stream "}\n") + 959 # convert + 960 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 961 (flush _test-output-buffered-file) + 962 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 968 # check output + 969 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-with-compound-type-in-mem/0") + 970 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-with-compound-type-in-mem/1") + 971 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-with-compound-type-in-mem/2") + 972 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-with-compound-type-in-mem/3") + 973 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-with-compound-type-in-mem/4") + 974 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-with-compound-type-in-mem/5") + 975 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-with-compound-type-in-mem/6") + 976 (check-next-stream-line-equal _test-output-stream " c7 0/subop/copy *(ebp+0xfffffffc) 0/imm32" "F - test-convert-function-with-local-var-with-compound-type-in-mem/7") + 977 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-with-compound-type-in-mem/8") + 978 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-with-compound-type-in-mem/9") + 979 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-with-compound-type-in-mem/10") + 980 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-with-compound-type-in-mem/11") + 981 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-with-compound-type-in-mem/12") + 982 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-with-compound-type-in-mem/13") + 983 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-with-compound-type-in-mem/14") + 984 # . epilogue + 985 89/<- %esp 5/r32/ebp + 986 5d/pop-to-ebp + 987 c3/return + 988 + 989 test-convert-function-with-local-var-in-reg: + 990 # . prologue + 991 55/push-ebp + 992 89/<- %ebp 4/r32/esp + 993 # setup + 994 (clear-stream _test-input-stream) + 995 (clear-stream $_test-input-buffered-file->buffer) + 996 (clear-stream _test-output-stream) + 997 (clear-stream $_test-output-buffered-file->buffer) + 998 # + 999 (write _test-input-stream "fn foo {\n") + 1000 (write _test-input-stream " var x/ecx: int <- copy 3\n") + 1001 (write _test-input-stream " x <- increment\n") + 1002 (write _test-input-stream "}\n") + 1003 # convert + 1004 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1005 (flush _test-output-buffered-file) + 1006 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1012 # check output + 1013 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-reg/0") + 1014 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-reg/1") + 1015 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-reg/2") + 1016 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-reg/3") + 1017 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-reg/4") + 1018 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-reg/5") + 1019 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-local-var-in-reg/6") + 1020 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-function-with-local-var-in-reg/7") + 1021 (check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-convert-function-with-local-var-in-reg/8") + 1022 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9") + 1023 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-reg/10") + 1024 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-reg/11") + 1025 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-reg/12") + 1026 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-reg/13") + 1027 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-reg/14") + 1028 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-reg/15") + 1029 # . epilogue + 1030 89/<- %esp 5/r32/ebp + 1031 5d/pop-to-ebp + 1032 c3/return + 1033 + 1034 test-convert-function-with-second-local-var-in-same-reg: + 1035 # . prologue + 1036 55/push-ebp + 1037 89/<- %ebp 4/r32/esp + 1038 # setup + 1039 (clear-stream _test-input-stream) + 1040 (clear-stream $_test-input-buffered-file->buffer) + 1041 (clear-stream _test-output-stream) + 1042 (clear-stream $_test-output-buffered-file->buffer) + 1043 # + 1044 (write _test-input-stream "fn foo {\n") + 1045 (write _test-input-stream " var x/ecx: int <- copy 3\n") + 1046 (write _test-input-stream " var y/ecx: int <- copy 4\n") + 1047 (write _test-input-stream " y <- increment\n") + 1048 (write _test-input-stream "}\n") + 1049 # convert + 1050 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1051 (flush _test-output-buffered-file) + 1052 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1058 # check output + 1059 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-second-local-var-in-same-reg/0") + 1060 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-second-local-var-in-same-reg/1") + 1061 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-second-local-var-in-same-reg/2") + 1062 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-second-local-var-in-same-reg/3") + 1063 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-second-local-var-in-same-reg/4") + 1064 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-second-local-var-in-same-reg/5") + 1065 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-second-local-var-in-same-reg/6") + 1066 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-function-with-second-local-var-in-same-reg/7") + 1067 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-convert-function-with-second-local-var-in-same-reg/8") + 1068 (check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-convert-function-with-second-local-var-in-same-reg/9") + 1069 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-second-local-var-in-same-reg/10") + 1070 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-second-local-var-in-same-reg/11") + 1071 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-second-local-var-in-same-reg/12") + 1072 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-second-local-var-in-same-reg/13") + 1073 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-second-local-var-in-same-reg/14") + 1074 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-second-local-var-in-same-reg/15") + 1075 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-second-local-var-in-same-reg/16") + 1076 # . epilogue + 1077 89/<- %esp 5/r32/ebp + 1078 5d/pop-to-ebp + 1079 c3/return + 1080 + 1081 test-convert-function-with-local-var-dereferenced: + 1082 # . prologue + 1083 55/push-ebp + 1084 89/<- %ebp 4/r32/esp + 1085 # setup + 1086 (clear-stream _test-input-stream) + 1087 (clear-stream $_test-input-buffered-file->buffer) + 1088 (clear-stream _test-output-stream) + 1089 (clear-stream $_test-output-buffered-file->buffer) + 1090 # + 1091 (write _test-input-stream "fn foo {\n") + 1092 (write _test-input-stream " var x/ecx: (addr int) <- copy 0\n") + 1093 (write _test-input-stream " increment *x\n") + 1094 (write _test-input-stream "}\n") + 1095 # convert + 1096 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1097 (flush _test-output-buffered-file) + 1098 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1104 # check output + 1105 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-dereferenced/0") + 1106 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-dereferenced/1") + 1107 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-dereferenced/2") + 1108 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-dereferenced/3") + 1109 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-dereferenced/4") + 1110 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-dereferenced/5") + 1111 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-local-var-dereferenced/6") + 1112 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-function-with-local-var-dereferenced/7") + 1113 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *ecx" "F - test-convert-function-with-local-var-dereferenced/8") + 1114 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9") + 1115 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-dereferenced/10") + 1116 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-dereferenced/11") + 1117 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-dereferenced/12") + 1118 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-dereferenced/13") + 1119 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-dereferenced/14") + 1120 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-dereferenced/15") + 1121 # . epilogue + 1122 89/<- %esp 5/r32/ebp + 1123 5d/pop-to-ebp + 1124 c3/return + 1125 + 1126 test-convert-compare-register-with-literal: + 1127 # . prologue + 1128 55/push-ebp + 1129 89/<- %ebp 4/r32/esp + 1130 # setup + 1131 (clear-stream _test-input-stream) + 1132 (clear-stream $_test-input-buffered-file->buffer) + 1133 (clear-stream _test-output-stream) + 1134 (clear-stream $_test-output-buffered-file->buffer) + 1135 # + 1136 (write _test-input-stream "fn foo {\n") + 1137 (write _test-input-stream " var x/ecx: int <- copy 0\n") + 1138 (write _test-input-stream " compare x, 0\n") + 1139 (write _test-input-stream "}\n") + 1140 # convert + 1141 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1142 (flush _test-output-buffered-file) + 1143 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1149 # check output + 1150 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-compare-register-with-literal/0") + 1151 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-compare-register-with-literal/1") + 1152 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-compare-register-with-literal/2") + 1153 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-compare-register-with-literal/3") + 1154 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-compare-register-with-literal/4") + 1155 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-compare-register-with-literal/5") + 1156 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-compare-register-with-literal/6") + 1157 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-compare-register-with-literal/7") + 1158 (check-next-stream-line-equal _test-output-stream " 81 7/subop/compare %ecx 0/imm32" "F - test-convert-compare-register-with-literal/8") + 1159 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9") + 1160 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-compare-register-with-literal/10") + 1161 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-compare-register-with-literal/11") + 1162 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-compare-register-with-literal/12") + 1163 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-compare-register-with-literal/13") + 1164 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-compare-register-with-literal/14") + 1165 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-compare-register-with-literal/15") + 1166 # . epilogue + 1167 89/<- %esp 5/r32/ebp + 1168 5d/pop-to-ebp + 1169 c3/return + 1170 + 1171 test-convert-function-with-local-var-in-block: + 1172 # . prologue + 1173 55/push-ebp + 1174 89/<- %ebp 4/r32/esp + 1175 # setup + 1176 (clear-stream _test-input-stream) + 1177 (clear-stream $_test-input-buffered-file->buffer) + 1178 (clear-stream _test-output-stream) + 1179 (clear-stream $_test-output-buffered-file->buffer) + 1180 # + 1181 (write _test-input-stream "fn foo {\n") + 1182 (write _test-input-stream " {\n") + 1183 (write _test-input-stream " var x: int\n") + 1184 (write _test-input-stream " increment x\n") + 1185 (write _test-input-stream " }\n") + 1186 (write _test-input-stream "}\n") + 1187 # convert + 1188 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1189 (flush _test-output-buffered-file) + 1190 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1196 # check output + 1197 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-block/0") + 1198 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-block/1") + 1199 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-block/2") + 1200 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-block/3") + 1201 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/4") + 1202 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-block/5") + 1203 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/6") + 1204 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-local-var-in-block/7") + 1205 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-block/8") + 1206 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-block/9") + 1207 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-in-block/10") + 1208 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/11") + 1209 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-local-var-in-block/12") + 1210 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/13") + 1211 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-block/14") + 1212 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-block/15") + 1213 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-block/16") + 1214 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-block/17") + 1215 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-block/18") + 1216 # . epilogue + 1217 89/<- %esp 5/r32/ebp + 1218 5d/pop-to-ebp + 1219 c3/return + 1220 + 1221 test-convert-function-with-local-var-in-named-block: + 1222 # . prologue + 1223 55/push-ebp + 1224 89/<- %ebp 4/r32/esp + 1225 # setup + 1226 (clear-stream _test-input-stream) + 1227 (clear-stream $_test-input-buffered-file->buffer) + 1228 (clear-stream _test-output-stream) + 1229 (clear-stream $_test-output-buffered-file->buffer) + 1230 # + 1231 (write _test-input-stream "fn foo {\n") + 1232 (write _test-input-stream " $bar: {\n") + 1233 (write _test-input-stream " var x: int\n") + 1234 (write _test-input-stream " increment x\n") + 1235 (write _test-input-stream " }\n") + 1236 (write _test-input-stream "}\n") + 1237 # convert + 1238 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1239 (flush _test-output-buffered-file) + 1240 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1246 # check output + 1247 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-named-block/0") + 1248 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-named-block/1") + 1249 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-named-block/2") + 1250 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-named-block/3") + 1251 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/4") + 1252 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-named-block/5") + 1253 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/6") + 1254 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-local-var-in-named-block/7") + 1255 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-named-block/8") + 1256 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-named-block/9") + 1257 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-in-named-block/10") + 1258 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/11") + 1259 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-local-var-in-named-block/12") + 1260 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/13") + 1261 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-named-block/14") + 1262 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-named-block/15") + 1263 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-named-block/16") + 1264 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-named-block/17") + 1265 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-named-block/18") + 1266 # . epilogue + 1267 89/<- %esp 5/r32/ebp + 1268 5d/pop-to-ebp + 1269 c3/return + 1270 + 1271 test-always-shadow-outermost-reg-vars-in-function: + 1272 # . prologue + 1273 55/push-ebp + 1274 89/<- %ebp 4/r32/esp + 1275 # setup + 1276 (clear-stream _test-input-stream) + 1277 (clear-stream $_test-input-buffered-file->buffer) + 1278 (clear-stream _test-output-stream) + 1279 (clear-stream $_test-output-buffered-file->buffer) + 1280 # + 1281 (write _test-input-stream "fn foo {\n") + 1282 (write _test-input-stream " var x/ecx: int <- copy 3\n") + 1283 (write _test-input-stream "}\n") + 1284 # convert + 1285 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1286 (flush _test-output-buffered-file) + 1287 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1293 # check output + 1294 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-always-shadow-outermost-reg-vars-in-function/0") + 1295 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-always-shadow-outermost-reg-vars-in-function/1") + 1296 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-always-shadow-outermost-reg-vars-in-function/2") + 1297 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-always-shadow-outermost-reg-vars-in-function/3") + 1298 (check-next-stream-line-equal _test-output-stream " {" "F - test-always-shadow-outermost-reg-vars-in-function/4") + 1299 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-always-shadow-outermost-reg-vars-in-function/5") + 1300 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-compare-register-with-literal/6") + 1301 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-always-shadow-outermost-reg-vars-in-function/8") + 1302 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9") + 1303 (check-next-stream-line-equal _test-output-stream " }" "F - test-always-shadow-outermost-reg-vars-in-function/12") + 1304 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-always-shadow-outermost-reg-vars-in-function/13") + 1305 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-always-shadow-outermost-reg-vars-in-function/14") + 1306 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-always-shadow-outermost-reg-vars-in-function/15") + 1307 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-always-shadow-outermost-reg-vars-in-function/16") + 1308 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-always-shadow-outermost-reg-vars-in-function/17") + 1309 # . epilogue + 1310 89/<- %esp 5/r32/ebp + 1311 5d/pop-to-ebp + 1312 c3/return + 1313 + 1314 _pending-test-clobber-dead-local: + 1315 # . prologue + 1316 55/push-ebp + 1317 89/<- %ebp 4/r32/esp + 1318 # setup + 1319 (clear-stream _test-input-stream) + 1320 (clear-stream $_test-input-buffered-file->buffer) + 1321 (clear-stream _test-output-stream) + 1322 (clear-stream $_test-output-buffered-file->buffer) + 1323 # + 1324 (write _test-input-stream "fn foo {\n") + 1325 (write _test-input-stream " var x/ecx: int <- copy 3\n") + 1326 (write _test-input-stream " {\n") + 1327 (write _test-input-stream " var y/ecx: int <- copy 4\n") + 1328 (write _test-input-stream " }\n") + 1329 (write _test-input-stream "}\n") + 1330 # convert + 1331 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1332 (flush _test-output-buffered-file) + 1333 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1339 # check output + 1340 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-clobber-dead-local/0") + 1341 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-clobber-dead-local/1") + 1342 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-clobber-dead-local/2") + 1343 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-clobber-dead-local/3") + 1344 (check-next-stream-line-equal _test-output-stream " {" "F - test-clobber-dead-local/4") + 1345 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-clobber-dead-local/5") + 1346 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-clobber-dead-local/6") + 1347 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-clobber-dead-local/7") + 1348 (check-next-stream-line-equal _test-output-stream " {" "F - test-clobber-dead-local/8") + 1349 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-clobber-dead-local/9") + 1350 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-clobber-dead-local/10") # no push/pop here + 1351 (check-next-stream-line-equal _test-output-stream " }" "F - test-clobber-dead-local/11") + 1352 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-clobber-dead-local/12") + 1353 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-clobber-dead-local/13") + 1354 (check-next-stream-line-equal _test-output-stream " }" "F - test-clobber-dead-local/14") + 1355 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-clobber-dead-local/15") + 1356 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-clobber-dead-local/16") + 1357 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-clobber-dead-local/17") + 1358 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-clobber-dead-local/18") + 1359 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-clobber-dead-local/19") + 1360 # . epilogue + 1361 89/<- %esp 5/r32/ebp + 1362 5d/pop-to-ebp + 1363 c3/return + 1364 + 1365 test-shadow-live-local: + 1366 # . prologue + 1367 55/push-ebp + 1368 89/<- %ebp 4/r32/esp + 1369 # setup + 1370 (clear-stream _test-input-stream) + 1371 (clear-stream $_test-input-buffered-file->buffer) + 1372 (clear-stream _test-output-stream) + 1373 (clear-stream $_test-output-buffered-file->buffer) + 1374 # + 1375 (write _test-input-stream "fn foo {\n") + 1376 (write _test-input-stream " var x/ecx: int <- copy 3\n") + 1377 (write _test-input-stream " {\n") + 1378 (write _test-input-stream " var y/ecx: int <- copy 4\n") + 1379 (write _test-input-stream " }\n") + 1380 (write _test-input-stream " x <- increment\n") + 1381 (write _test-input-stream "}\n") + 1382 # convert + 1383 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1384 (flush _test-output-buffered-file) + 1385 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1391 # check output + 1392 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-shadow-live-local/0") + 1393 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-shadow-live-local/1") + 1394 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-shadow-live-local/2") + 1395 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-shadow-live-local/3") + 1396 (check-next-stream-line-equal _test-output-stream " {" "F - test-shadow-live-local/4") + 1397 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-shadow-live-local/5") + 1398 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-shadow-live-local/6") + 1399 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-shadow-live-local/7") + 1400 (check-next-stream-line-equal _test-output-stream " {" "F - test-shadow-live-local/8") + 1401 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-shadow-live-local/9") + 1402 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-shadow-live-local/10") + 1403 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-shadow-live-local/11") + 1404 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-shadow-live-local/12") + 1405 (check-next-stream-line-equal _test-output-stream " }" "F - test-shadow-live-local/13") + 1406 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-shadow-live-local/14") + 1407 (check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-shadow-live-local/15") + 1408 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-shadow-live-local/16") + 1409 (check-next-stream-line-equal _test-output-stream " }" "F - test-shadow-live-local/17") + 1410 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-shadow-live-local/18") + 1411 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-shadow-live-local/19") + 1412 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-shadow-live-local/20") + 1413 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-shadow-live-local/21") + 1414 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-shadow-live-local/21") + 1415 # . epilogue + 1416 89/<- %esp 5/r32/ebp + 1417 5d/pop-to-ebp + 1418 c3/return + 1419 + 1420 test-shadow-live-output: + 1421 # . prologue + 1422 55/push-ebp + 1423 89/<- %ebp 4/r32/esp + 1424 # setup + 1425 (clear-stream _test-input-stream) + 1426 (clear-stream $_test-input-buffered-file->buffer) + 1427 (clear-stream _test-output-stream) + 1428 (clear-stream $_test-output-buffered-file->buffer) + 1429 # + 1430 (write _test-input-stream "fn foo -> x/ecx: int {\n") + 1431 (write _test-input-stream " x <- copy 3\n") + 1432 (write _test-input-stream " {\n") + 1433 (write _test-input-stream " var y/ecx: int <- copy 4\n") + 1434 (write _test-input-stream " }\n") + 1435 (write _test-input-stream " x <- increment\n") + 1436 (write _test-input-stream "}\n") + 1437 # convert + 1438 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1439 (flush _test-output-buffered-file) + 1440 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1446 # check output + 1447 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-shadow-live-output/0") + 1448 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-shadow-live-output/1") + 1449 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-shadow-live-output/2") + 1450 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-shadow-live-output/3") + 1451 (check-next-stream-line-equal _test-output-stream " {" "F - test-shadow-live-output/4") + 1452 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-shadow-live-output/5") + 1453 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-shadow-live-output/7") # no push because it's an output reg + 1454 (check-next-stream-line-equal _test-output-stream " {" "F - test-shadow-live-output/8") + 1455 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-shadow-live-output/9") + 1456 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-shadow-live-output/10") + 1457 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-shadow-live-output/11") + 1458 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-shadow-live-output/12") + 1459 (check-next-stream-line-equal _test-output-stream " }" "F - test-shadow-live-output/13") + 1460 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-shadow-live-output/14") + 1461 (check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-shadow-live-output/15") + 1462 (check-next-stream-line-equal _test-output-stream " }" "F - test-shadow-live-output/17") + 1463 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-shadow-live-output/18") + 1464 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-shadow-live-output/19") + 1465 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-shadow-live-output/20") + 1466 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-shadow-live-output/21") + 1467 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-shadow-live-output/21") + 1468 # . epilogue + 1469 89/<- %esp 5/r32/ebp + 1470 5d/pop-to-ebp + 1471 c3/return + 1472 + 1473 _pending-test-local-clobbered-by-output: + 1474 # also doesn't spill + 1475 # . prologue + 1476 55/push-ebp + 1477 89/<- %ebp 4/r32/esp + 1478 # setup + 1479 (clear-stream _test-input-stream) + 1480 (clear-stream $_test-input-buffered-file->buffer) + 1481 (clear-stream _test-output-stream) + 1482 (clear-stream $_test-output-buffered-file->buffer) + 1483 # + 1484 (write _test-input-stream "fn foo -> x/ecx: int {\n") + 1485 (write _test-input-stream " var y/ecx: int <- copy 4\n") + 1486 (write _test-input-stream " x <- copy y\n") + 1487 (write _test-input-stream "}\n") + 1488 # convert + 1489 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1490 (flush _test-output-buffered-file) + 1491 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1497 # check output + 1498 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-local-clobbered-by-output/0") + 1499 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-local-clobbered-by-output/1") + 1500 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-local-clobbered-by-output/2") + 1501 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-local-clobbered-by-output/3") + 1502 (check-next-stream-line-equal _test-output-stream " {" "F - test-local-clobbered-by-output/4") + 1503 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-local-clobbered-by-output/5") + 1504 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-local-clobbered-by-output/6") + 1505 (check-next-stream-line-equal _test-output-stream " 89/<- %ecx 0x00000001/r32" "F - test-local-clobbered-by-output/7") + 1506 (check-next-stream-line-equal _test-output-stream " }" "F - test-local-clobbered-by-output/8") + 1507 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-local-clobbered-by-output/9") + 1508 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-local-clobbered-by-output/10") + 1509 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-local-clobbered-by-output/11") + 1510 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-local-clobbered-by-output/12") + 1511 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-local-clobbered-by-output/13") + 1512 # . epilogue + 1513 89/<- %esp 5/r32/ebp + 1514 5d/pop-to-ebp + 1515 c3/return + 1516 + 1517 test-convert-function-with-branches-in-block: + 1518 # . prologue + 1519 55/push-ebp + 1520 89/<- %ebp 4/r32/esp + 1521 # setup + 1522 (clear-stream _test-input-stream) + 1523 (clear-stream $_test-input-buffered-file->buffer) + 1524 (clear-stream _test-output-stream) + 1525 (clear-stream $_test-output-buffered-file->buffer) + 1526 # + 1527 (write _test-input-stream "fn foo x: int {\n") + 1528 (write _test-input-stream " {\n") + 1529 (write _test-input-stream " break-if->=\n") + 1530 (write _test-input-stream " loop-if-addr<\n") + 1531 (write _test-input-stream " increment x\n") + 1532 (write _test-input-stream " loop\n") + 1533 (write _test-input-stream " }\n") + 1534 (write _test-input-stream "}\n") + 1535 # convert + 1536 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1537 (flush _test-output-buffered-file) + 1538 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1544 # check output + 1545 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-block/0") + 1546 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-block/1") + 1547 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-block/2") + 1548 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-block/3") + 1549 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/4") + 1550 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-in-block/5") + 1551 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/6") + 1552 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-in-block/7") + 1553 (check-next-stream-line-equal _test-output-stream " 0f 8d/jump-if->= break/disp32" "F - test-convert-function-with-branches-in-block/8") + 1554 (check-next-stream-line-equal _test-output-stream " 0f 82/jump-if-addr< loop/disp32" "F - test-convert-function-with-branches-in-block/9") + 1555 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-block/10") + 1556 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-block/11") + 1557 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/12") + 1558 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-in-block/13") + 1559 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/14") + 1560 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-in-block/15") + 1561 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-block/16") + 1562 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-block/17") + 1563 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-block/18") + 1564 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-block/19") + 1565 # . epilogue + 1566 89/<- %esp 5/r32/ebp + 1567 5d/pop-to-ebp + 1568 c3/return + 1569 + 1570 test-convert-function-with-branches-in-named-block: + 1571 # . prologue + 1572 55/push-ebp + 1573 89/<- %ebp 4/r32/esp + 1574 # setup + 1575 (clear-stream _test-input-stream) + 1576 (clear-stream $_test-input-buffered-file->buffer) + 1577 (clear-stream _test-output-stream) + 1578 (clear-stream $_test-output-buffered-file->buffer) + 1579 # + 1580 (write _test-input-stream "fn foo x: int {\n") + 1581 (write _test-input-stream " $bar: {\n") + 1582 (write _test-input-stream " break-if->= $bar\n") + 1583 (write _test-input-stream " loop-if-addr< $bar\n") + 1584 (write _test-input-stream " increment x\n") + 1585 (write _test-input-stream " loop\n") + 1586 (write _test-input-stream " }\n") + 1587 (write _test-input-stream "}\n") + 1588 # convert + 1589 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1590 (flush _test-output-buffered-file) + 1591 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1597 # check output + 1598 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-named-block/0") + 1599 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-named-block/1") + 1600 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-named-block/2") + 1601 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-named-block/3") + 1602 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/4") + 1603 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-in-named-block/5") + 1604 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/6") + 1605 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-branches-in-named-block/7") + 1606 (check-next-stream-line-equal _test-output-stream " 0f 8d/jump-if->= $bar:break/disp32" "F - test-convert-function-with-branches-in-named-block/8") + 1607 (check-next-stream-line-equal _test-output-stream " 0f 82/jump-if-addr< $bar:loop/disp32" "F - test-convert-function-with-branches-in-named-block/9") + 1608 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-named-block/10") + 1609 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-named-block/11") + 1610 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/12") + 1611 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-branches-in-named-block/13") + 1612 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/14") + 1613 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-in-named-block/15") + 1614 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-named-block/16") + 1615 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-named-block/17") + 1616 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-named-block/18") + 1617 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-named-block/19") + 1618 # . epilogue + 1619 89/<- %esp 5/r32/ebp + 1620 5d/pop-to-ebp + 1621 c3/return + 1622 + 1623 test-convert-function-with-var-in-nested-block: + 1624 # . prologue + 1625 55/push-ebp + 1626 89/<- %ebp 4/r32/esp + 1627 # setup + 1628 (clear-stream _test-input-stream) + 1629 (clear-stream $_test-input-buffered-file->buffer) + 1630 (clear-stream _test-output-stream) + 1631 (clear-stream $_test-output-buffered-file->buffer) + 1632 # + 1633 (write _test-input-stream "fn foo x: int {\n") + 1634 (write _test-input-stream " {\n") + 1635 (write _test-input-stream " {\n") + 1636 (write _test-input-stream " var x: int\n") + 1637 (write _test-input-stream " increment x\n") + 1638 (write _test-input-stream " }\n") + 1639 (write _test-input-stream " }\n") + 1640 (write _test-input-stream "}\n") + 1641 # convert + 1642 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1643 (flush _test-output-buffered-file) + 1644 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1650 # check output + 1651 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-var-in-nested-block/0") + 1652 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-var-in-nested-block/1") + 1653 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-var-in-nested-block/2") + 1654 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-var-in-nested-block/3") + 1655 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/4") + 1656 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-var-in-nested-block/5") + 1657 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/6") + 1658 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-var-in-nested-block/7") + 1659 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/8") + 1660 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-var-in-nested-block/9") + 1661 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10") + 1662 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-var-in-nested-block/11") + 1663 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-var-in-nested-block/12") + 1664 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/13") + 1665 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-var-in-nested-block/14") + 1666 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/15") + 1667 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-var-in-nested-block/16") + 1668 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/17") + 1669 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-var-in-nested-block/18") + 1670 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-var-in-nested-block/19") + 1671 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-var-in-nested-block/20") + 1672 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-var-in-nested-block/21") + 1673 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-var-in-nested-block/22") + 1674 # . epilogue + 1675 89/<- %esp 5/r32/ebp + 1676 5d/pop-to-ebp + 1677 c3/return + 1678 + 1679 test-convert-function-with-multiple-vars-in-nested-blocks: + 1680 # . prologue + 1681 55/push-ebp + 1682 89/<- %ebp 4/r32/esp + 1683 # setup + 1684 (clear-stream _test-input-stream) + 1685 (clear-stream $_test-input-buffered-file->buffer) + 1686 (clear-stream _test-output-stream) + 1687 (clear-stream $_test-output-buffered-file->buffer) + 1688 # + 1689 (write _test-input-stream "fn foo x: int {\n") + 1690 (write _test-input-stream " {\n") + 1691 (write _test-input-stream " var x/eax: int <- copy 0\n") + 1692 (write _test-input-stream " {\n") + 1693 (write _test-input-stream " var y: int\n") + 1694 (write _test-input-stream " x <- add y\n") + 1695 (write _test-input-stream " }\n") + 1696 (write _test-input-stream " }\n") + 1697 (write _test-input-stream "}\n") + 1698 # convert + 1699 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1700 (flush _test-output-buffered-file) + 1701 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1707 # check output + 1708 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/0") + 1709 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-multiple-vars-in-nested-blocks/1") + 1710 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/2") + 1711 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/3") + 1712 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/4") + 1713 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/5") + 1714 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/6") + 1715 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/7") + 1716 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-with-multiple-vars-in-nested-blocks/8") + 1717 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/9") + 1718 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/10") + 1719 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/11") + 1720 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12") + 1721 (check-next-stream-line-equal _test-output-stream " 03/add *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/13") + 1722 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/14") + 1723 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/15") + 1724 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/16") + 1725 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-with-multiple-vars-in-nested-blocks/17") + 1726 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/18") + 1727 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/19") + 1728 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/20") + 1729 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/21") + 1730 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-multiple-vars-in-nested-blocks/22") + 1731 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/23") + 1732 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/24") + 1733 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-multiple-vars-in-nested-blocks/25") + 1734 # . epilogue + 1735 89/<- %esp 5/r32/ebp + 1736 5d/pop-to-ebp + 1737 c3/return + 1738 + 1739 test-convert-function-with-branches-and-local-vars: + 1740 # A conditional 'break' after a 'var' in a block is converted into a + 1741 # nested block that performs all necessary cleanup before jumping. This + 1742 # results in some ugly code duplication. + 1743 # . prologue + 1744 55/push-ebp + 1745 89/<- %ebp 4/r32/esp + 1746 # setup + 1747 (clear-stream _test-input-stream) + 1748 (clear-stream $_test-input-buffered-file->buffer) + 1749 (clear-stream _test-output-stream) + 1750 (clear-stream $_test-output-buffered-file->buffer) + 1751 # + 1752 (write _test-input-stream "fn foo {\n") + 1753 (write _test-input-stream " {\n") + 1754 (write _test-input-stream " var x: int\n") + 1755 (write _test-input-stream " break-if->=\n") + 1756 (write _test-input-stream " increment x\n") + 1757 (write _test-input-stream " }\n") + 1758 (write _test-input-stream "}\n") + 1759 # convert + 1760 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1761 (flush _test-output-buffered-file) + 1762 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1768 # check output + 1769 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-local-vars/0") + 1770 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-local-vars/1") + 1771 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-local-vars/2") + 1772 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-and-local-vars/3") + 1773 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/4") + 1774 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-and-local-vars/5") + 1775 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/6") + 1776 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-and-local-vars/7") + 1777 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-local-vars/8") + 1778 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/9") + 1779 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-branches-and-local-vars/10") + 1780 (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") + 1781 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:break/disp32" "F - test-convert-function-with-branches-and-local-vars/12") + 1782 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/13") + 1783 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-branches-and-local-vars/14") + 1784 (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") + 1785 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/16") + 1786 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-and-local-vars/17") + 1787 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/18") + 1788 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-and-local-vars/19") + 1789 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-local-vars/20") + 1790 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-and-local-vars/21") + 1791 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-local-vars/22") + 1792 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-local-vars/23") + 1793 # . epilogue + 1794 89/<- %esp 5/r32/ebp + 1795 5d/pop-to-ebp + 1796 c3/return + 1797 + 1798 test-convert-function-with-conditional-loops-and-local-vars: + 1799 # A conditional 'loop' after a 'var' in a block is converted into a nested + 1800 # block that performs all necessary cleanup before jumping. This results + 1801 # in some ugly code duplication. + 1802 # . prologue + 1803 55/push-ebp + 1804 89/<- %ebp 4/r32/esp + 1805 # setup + 1806 (clear-stream _test-input-stream) + 1807 (clear-stream $_test-input-buffered-file->buffer) + 1808 (clear-stream _test-output-stream) + 1809 (clear-stream $_test-output-buffered-file->buffer) + 1810 # + 1811 (write _test-input-stream "fn foo {\n") + 1812 (write _test-input-stream " {\n") + 1813 (write _test-input-stream " var x: int\n") + 1814 (write _test-input-stream " loop-if->=\n") + 1815 (write _test-input-stream " increment x\n") + 1816 (write _test-input-stream " }\n") + 1817 (write _test-input-stream "}\n") + 1818 # convert + 1819 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1820 (flush _test-output-buffered-file) + 1821 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1827 # check output + 1828 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-conditional-loops-and-local-vars/0") + 1829 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-conditional-loops-and-local-vars/1") + 1830 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/2") + 1831 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-conditional-loops-and-local-vars/3") + 1832 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/4") + 1833 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-conditional-loops-and-local-vars/5") + 1834 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/6") + 1835 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-conditional-loops-and-local-vars/7") + 1836 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-conditional-loops-and-local-vars/8") + 1837 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/9") + 1838 (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") + 1839 (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") + 1840 (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") + 1841 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/13") + 1842 (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") + 1843 (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") + 1844 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/16") + 1845 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-conditional-loops-and-local-vars/17") + 1846 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/18") + 1847 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-conditional-loops-and-local-vars/19") + 1848 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-conditional-loops-and-local-vars/20") + 1849 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/21") + 1850 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/22") + 1851 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-conditional-loops-and-local-vars/23") + 1852 # . epilogue + 1853 89/<- %esp 5/r32/ebp + 1854 5d/pop-to-ebp + 1855 c3/return + 1856 + 1857 test-convert-function-with-unconditional-loops-and-local-vars: + 1858 # An unconditional 'loop' after a 'var' in a block is emitted _after_ the + 1859 # regular block cleanup. Any instructions after 'loop' are dead and + 1860 # therefore skipped. + 1861 # . prologue + 1862 55/push-ebp + 1863 89/<- %ebp 4/r32/esp + 1864 # setup + 1865 (clear-stream _test-input-stream) + 1866 (clear-stream $_test-input-buffered-file->buffer) + 1867 (clear-stream _test-output-stream) + 1868 (clear-stream $_test-output-buffered-file->buffer) + 1869 # + 1870 (write _test-input-stream "fn foo {\n") + 1871 (write _test-input-stream " {\n") + 1872 (write _test-input-stream " var x: int\n") + 1873 (write _test-input-stream " loop\n") + 1874 (write _test-input-stream " increment x\n") + 1875 (write _test-input-stream " }\n") + 1876 (write _test-input-stream "}\n") + 1877 # convert + 1878 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1879 (flush _test-output-buffered-file) + 1880 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1886 # check output + 1887 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-unconditional-loops-and-local-vars/0") + 1888 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-unconditional-loops-and-local-vars/1") + 1889 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/2") + 1890 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-unconditional-loops-and-local-vars/3") + 1891 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-loops-and-local-vars/4") + 1892 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-unconditional-loops-and-local-vars/5") + 1893 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-loops-and-local-vars/6") + 1894 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-unconditional-loops-and-local-vars/7") + 1895 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-loops-and-local-vars/8") + 1896 (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") + 1897 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-unconditional-loops-and-local-vars/10") + 1898 # not emitted: ff 0/subop/increment *(ebp+0xfffffffc) + 1899 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-loops-and-local-vars/11") + 1900 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-unconditional-loops-and-local-vars/12") + 1901 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-loops-and-local-vars/13") + 1902 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-unconditional-loops-and-local-vars/14") + 1903 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-unconditional-loops-and-local-vars/15") + 1904 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/16") + 1905 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/17") + 1906 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-unconditional-loops-and-local-vars/18") + 1907 # . epilogue + 1908 89/<- %esp 5/r32/ebp + 1909 5d/pop-to-ebp + 1910 c3/return + 1911 + 1912 test-convert-function-with-branches-and-loops-and-local-vars: + 1913 # . prologue + 1914 55/push-ebp + 1915 89/<- %ebp 4/r32/esp + 1916 # setup + 1917 (clear-stream _test-input-stream) + 1918 (clear-stream $_test-input-buffered-file->buffer) + 1919 (clear-stream _test-output-stream) + 1920 (clear-stream $_test-output-buffered-file->buffer) + 1921 # + 1922 (write _test-input-stream "fn foo {\n") + 1923 (write _test-input-stream " {\n") + 1924 (write _test-input-stream " var x: int\n") + 1925 (write _test-input-stream " break-if->=\n") + 1926 (write _test-input-stream " increment x\n") + 1927 (write _test-input-stream " loop\n") + 1928 (write _test-input-stream " }\n") + 1929 (write _test-input-stream "}\n") + 1930 # convert + 1931 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1932 (flush _test-output-buffered-file) + 1933 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1939 # check output + 1940 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-loops-and-local-vars/0") + 1941 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-loops-and-local-vars/1") + 1942 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/2") + 1943 (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") + 1944 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/4") + 1945 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-and-loops-and-local-vars/5") + 1946 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/6") + 1947 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-and-loops-and-local-vars/7") + 1948 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-loops-and-local-vars/8") + 1949 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/9") + 1950 (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") + 1951 (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") + 1952 (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") + 1953 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/13") + 1954 (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") + 1955 (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") + 1956 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-and-loops-and-local-vars/16") + 1957 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/17") + 1958 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-and-loops-and-local-vars/18") + 1959 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/19") + 1960 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-and-loops-and-local-vars/20") + 1961 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-loops-and-local-vars/21") + 1962 (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") + 1963 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/23") + 1964 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-loops-and-local-vars/24") + 1965 # . epilogue + 1966 89/<- %esp 5/r32/ebp + 1967 5d/pop-to-ebp + 1968 c3/return + 1969 + 1970 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars: + 1971 # . prologue + 1972 55/push-ebp + 1973 89/<- %ebp 4/r32/esp + 1974 # setup + 1975 (clear-stream _test-input-stream) + 1976 (clear-stream $_test-input-buffered-file->buffer) + 1977 (clear-stream _test-output-stream) + 1978 (clear-stream $_test-output-buffered-file->buffer) + 1979 # + 1980 (write _test-input-stream "fn foo {\n") + 1981 (write _test-input-stream " a: {\n") + 1982 (write _test-input-stream " var x: int\n") + 1983 (write _test-input-stream " {\n") + 1984 (write _test-input-stream " var y: int\n") + 1985 (write _test-input-stream " break-if->= a\n") + 1986 (write _test-input-stream " increment x\n") + 1987 (write _test-input-stream " loop\n") + 1988 (write _test-input-stream " }\n") + 1989 (write _test-input-stream " }\n") + 1990 (write _test-input-stream "}\n") + 1991 # convert + 1992 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 1993 (flush _test-output-buffered-file) + 1994 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 2000 # check output + 2001 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0") + 2002 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1") + 2003 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2") + 2004 (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") + 2005 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4") + 2006 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5") + 2007 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6") + 2008 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7") + 2009 (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") + 2010 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9") + 2011 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10") + 2012 (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") + 2013 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12") + 2014 (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") + 2015 (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") + 2016 (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") + 2017 (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") + 2018 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17") + 2019 (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") + 2020 (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") + 2021 (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") + 2022 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21") + 2023 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22") + 2024 (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") + 2025 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24") + 2026 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25") + 2027 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26") + 2028 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27") + 2029 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28") + 2030 (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") + 2031 (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") + 2032 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31") + 2033 # . epilogue + 2034 89/<- %esp 5/r32/ebp + 2035 5d/pop-to-ebp + 2036 c3/return + 2037 + 2038 test-convert-function-with-nonlocal-unconditional-break-and-local-vars: + 2039 # . prologue + 2040 55/push-ebp + 2041 89/<- %ebp 4/r32/esp + 2042 # setup + 2043 (clear-stream _test-input-stream) + 2044 (clear-stream $_test-input-buffered-file->buffer) + 2045 (clear-stream _test-output-stream) + 2046 (clear-stream $_test-output-buffered-file->buffer) + 2047 # + 2048 (write _test-input-stream "fn foo {\n") + 2049 (write _test-input-stream " a: {\n") + 2050 (write _test-input-stream " var x: int\n") + 2051 (write _test-input-stream " {\n") + 2052 (write _test-input-stream " var y: int\n") + 2053 (write _test-input-stream " break a\n") + 2054 (write _test-input-stream " increment x\n") + 2055 (write _test-input-stream " }\n") + 2056 (write _test-input-stream " }\n") + 2057 (write _test-input-stream "}\n") + 2058 # convert + 2059 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2060 (flush _test-output-buffered-file) + 2061 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 2067 # check output + 2068 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0") + 2069 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1") + 2070 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2") + 2071 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/3") + 2072 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4") + 2073 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5") + 2074 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6") + 2075 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7") + 2076 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8") + 2077 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9") + 2078 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10") + 2079 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11") + 2080 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/12") + 2081 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/13") + 2082 (check-next-stream-line-equal _test-output-stream " e9/jump a:break/disp32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/14") + 2083 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15") + 2084 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16") + 2085 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/17") + 2086 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18") + 2087 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19") + 2088 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20") + 2089 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21") + 2090 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22") + 2091 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/23") + 2092 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24") + 2093 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25") + 2094 # . epilogue + 2095 89/<- %esp 5/r32/ebp + 2096 5d/pop-to-ebp + 2097 c3/return + 2098 + 2099 test-convert-function-with-unconditional-break-and-local-vars: + 2100 # . prologue + 2101 55/push-ebp + 2102 89/<- %ebp 4/r32/esp + 2103 # setup + 2104 (clear-stream _test-input-stream) + 2105 (clear-stream $_test-input-buffered-file->buffer) + 2106 (clear-stream _test-output-stream) + 2107 (clear-stream $_test-output-buffered-file->buffer) + 2108 # + 2109 (write _test-input-stream "fn foo {\n") + 2110 (write _test-input-stream " {\n") + 2111 (write _test-input-stream " var x: int\n") + 2112 (write _test-input-stream " {\n") + 2113 (write _test-input-stream " var y: int\n") + 2114 (write _test-input-stream " break\n") + 2115 (write _test-input-stream " increment x\n") + 2116 (write _test-input-stream " }\n") + 2117 (write _test-input-stream " }\n") + 2118 (write _test-input-stream "}\n") + 2119 # convert + 2120 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2121 (flush _test-output-buffered-file) + 2122 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 2128 # check output + 2129 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-unconditional-break-and-local-vars/0") + 2130 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-unconditional-break-and-local-vars/1") + 2131 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/2") + 2132 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-unconditional-break-and-local-vars/3") + 2133 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/4") + 2134 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/5") + 2135 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/6") + 2136 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/7") + 2137 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/8") + 2138 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/9") + 2139 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/10") + 2140 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11") + 2141 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/12") + 2142 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/13") + 2143 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/14") + 2144 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/15") + 2145 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/16") + 2146 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/17") + 2147 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/18") + 2148 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/19") + 2149 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-unconditional-break-and-local-vars/20") + 2150 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/21") + 2151 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/22") + 2152 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-unconditional-break-and-local-vars/23") + 2153 # . epilogue + 2154 89/<- %esp 5/r32/ebp + 2155 5d/pop-to-ebp + 2156 c3/return + 2157 + 2158 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars: + 2159 # . prologue + 2160 55/push-ebp + 2161 89/<- %ebp 4/r32/esp + 2162 # setup + 2163 (clear-stream _test-input-stream) + 2164 (clear-stream $_test-input-buffered-file->buffer) + 2165 (clear-stream _test-output-stream) + 2166 (clear-stream $_test-output-buffered-file->buffer) + 2167 # + 2168 (write _test-input-stream "fn foo {\n") + 2169 (write _test-input-stream " a: {\n") + 2170 (write _test-input-stream " var x: int\n") + 2171 (write _test-input-stream " {\n") + 2172 (write _test-input-stream " var y: int\n") + 2173 (write _test-input-stream " loop a\n") + 2174 (write _test-input-stream " increment x\n") + 2175 (write _test-input-stream " }\n") + 2176 (write _test-input-stream " }\n") + 2177 (write _test-input-stream "}\n") + 2178 # convert + 2179 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2180 (flush _test-output-buffered-file) + 2181 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 2187 # check output + 2188 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0") + 2189 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1") + 2190 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2") + 2191 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/3") + 2192 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4") + 2193 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5") + 2194 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6") + 2195 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7") + 2196 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8") + 2197 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9") + 2198 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10") + 2199 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11") + 2200 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/12") + 2201 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/13") + 2202 (check-next-stream-line-equal _test-output-stream " e9/jump a:loop/disp32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/14") + 2203 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15") + 2204 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16") + 2205 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/17") + 2206 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18") + 2207 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19") + 2208 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20") + 2209 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21") + 2210 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22") + 2211 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/23") + 2212 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24") + 2213 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25") + 2214 # . epilogue + 2215 89/<- %esp 5/r32/ebp + 2216 5d/pop-to-ebp + 2217 c3/return + 2218 + 2219 test-convert-function-with-local-array-var-in-mem: + 2220 # . prologue + 2221 55/push-ebp + 2222 89/<- %ebp 4/r32/esp + 2223 # setup + 2224 (clear-stream _test-input-stream) + 2225 (clear-stream $_test-input-buffered-file->buffer) + 2226 (clear-stream _test-output-stream) + 2227 (clear-stream $_test-output-buffered-file->buffer) + 2228 # + 2229 (write _test-input-stream "fn foo {\n") + 2230 (write _test-input-stream " var x: (array int 3)\n") + 2231 (write _test-input-stream "}\n") + 2232 # convert + 2233 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2234 (flush _test-output-buffered-file) + 2235 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 2241 # check output + 2242 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-array-var-in-mem/0") + 2243 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-array-var-in-mem/1") + 2244 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-array-var-in-mem/2") + 2245 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-array-var-in-mem/3") + 2246 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-array-var-in-mem/4") + 2247 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-array-var-in-mem/5") + 2248 # define x + 2249 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x0000000c)" "F - test-convert-function-with-local-array-var-in-mem/7") + 2250 (check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-function-with-local-array-var-in-mem/8") + 2251 # reclaim x + 2252 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-function-with-local-array-var-in-mem/9") + 2253 # + 2254 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-array-var-in-mem/10") + 2255 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-array-var-in-mem/11") + 2256 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-array-var-in-mem/12") + 2257 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-array-var-in-mem/13") + 2258 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-array-var-in-mem/14") + 2259 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-array-var-in-mem/15") + 2260 # . epilogue + 2261 89/<- %esp 5/r32/ebp + 2262 5d/pop-to-ebp + 2263 c3/return + 2264 + 2265 test-convert-address: + 2266 # . prologue + 2267 55/push-ebp + 2268 89/<- %ebp 4/r32/esp + 2269 # setup + 2270 (clear-stream _test-input-stream) + 2271 (clear-stream $_test-input-buffered-file->buffer) + 2272 (clear-stream _test-output-stream) + 2273 (clear-stream $_test-output-buffered-file->buffer) + 2274 # + 2275 (write _test-input-stream "fn foo {\n") + 2276 (write _test-input-stream " var a: int\n") + 2277 (write _test-input-stream " var b/eax: (addr int) <- address a\n") + 2278 (write _test-input-stream "}\n") + 2279 # convert + 2280 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2281 (flush _test-output-buffered-file) + 2282 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 2288 # check output + 2289 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-address/0") + 2290 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-address/1") + 2291 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-address/2") + 2292 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-address/3") + 2293 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-address/4") + 2294 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-address/5") + 2295 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-address/6") + 2296 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-address/7") + 2297 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32" "F - test-convert-address/8") + 2298 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-address/9") + 2299 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-address/10") + 2300 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-address/11") + 2301 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-address/12") + 2302 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-address/13") + 2303 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-address/14") + 2304 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-address/15") + 2305 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-address/16") + 2306 # . epilogue + 2307 89/<- %esp 5/r32/ebp + 2308 5d/pop-to-ebp + 2309 c3/return + 2310 + 2311 test-convert-length-of-array: + 2312 # . prologue + 2313 55/push-ebp + 2314 89/<- %ebp 4/r32/esp + 2315 # setup + 2316 (clear-stream _test-input-stream) + 2317 (clear-stream $_test-input-buffered-file->buffer) + 2318 (clear-stream _test-output-stream) + 2319 (clear-stream $_test-output-buffered-file->buffer) + 2320 # + 2321 (write _test-input-stream "fn foo a: (addr array int) {\n") + 2322 (write _test-input-stream " var b/eax: (addr array int) <- copy a\n") + 2323 (write _test-input-stream " var c/eax: int <- length b\n") + 2324 (write _test-input-stream "}\n") + 2325 # convert + 2326 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2327 (flush _test-output-buffered-file) + 2328 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 2334 # check output + 2335 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array/0") + 2336 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array/1") + 2337 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array/2") + 2338 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array/3") + 2339 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array/4") + 2340 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array/5") + 2341 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/6") + 2342 (check-next-stream-line-equal _test-output-stream " 8b/-> *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-length-of-array/7") + 2343 (check-next-stream-line-equal _test-output-stream " 8b/-> *eax 0x00000000/r32" "F - test-convert-length-of-array/9") + 2344 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/11") + 2345 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array/12") + 2346 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array/13") + 2347 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array/14") + 2348 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array/15") + 2349 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array/16") + 2350 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array/17") + 2351 # . epilogue + 2352 89/<- %esp 5/r32/ebp + 2353 5d/pop-to-ebp + 2354 c3/return + 2355 + 2356 test-convert-length-of-array-on-stack: + 2357 # . prologue + 2358 55/push-ebp + 2359 89/<- %ebp 4/r32/esp + 2360 # setup + 2361 (clear-stream _test-input-stream) + 2362 (clear-stream $_test-input-buffered-file->buffer) + 2363 (clear-stream _test-output-stream) + 2364 (clear-stream $_test-output-buffered-file->buffer) + 2365 # + 2366 (write _test-input-stream "fn foo {\n") + 2367 (write _test-input-stream " var a: (array int 3)\n") + 2368 (write _test-input-stream " var b/eax: int <- length a\n") + 2369 (write _test-input-stream "}\n") + 2370 # convert + 2371 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2372 (flush _test-output-buffered-file) + 2373 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 2379 # check output + 2380 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array-on-stack/0") + 2381 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array-on-stack/1") + 2382 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array-on-stack/2") + 2383 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array-on-stack/3") + 2384 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array-on-stack/4") + 2385 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array-on-stack/5") + 2386 # define x + 2387 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x0000000c)" "F - test-convert-length-of-array-on-stack/6") + 2388 (check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-length-of-array-on-stack/7") + 2389 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array-on-stack/8") + 2390 (check-next-stream-line-equal _test-output-stream " 8b/-> *(ebp+0xfffffff0) 0x00000000/r32" "F - test-convert-length-of-array-on-stack/9") + 2391 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array-on-stack/10") + 2392 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-length-of-array-on-stack/11") + 2393 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array-on-stack/12") + 2394 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array-on-stack/13") + 2395 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array-on-stack/14") + 2396 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array-on-stack/15") + 2397 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array-on-stack/16") + 2398 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array-on-stack/17") + 2399 # . epilogue + 2400 89/<- %esp 5/r32/ebp + 2401 5d/pop-to-ebp + 2402 c3/return + 2403 + 2404 test-convert-index-into-array: + 2405 # . prologue + 2406 55/push-ebp + 2407 89/<- %ebp 4/r32/esp + 2408 # setup + 2409 (clear-stream _test-input-stream) + 2410 (clear-stream $_test-input-buffered-file->buffer) + 2411 (clear-stream _test-output-stream) + 2412 (clear-stream $_test-output-buffered-file->buffer) + 2413 # + 2414 (write _test-input-stream "fn foo {\n") + 2415 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") + 2416 (write _test-input-stream " var idx/ecx: int <- copy 3\n") + 2417 (write _test-input-stream " var x/eax: (addr int) <- index arr, idx\n") + 2418 (write _test-input-stream "}\n") + 2419 # convert + 2420 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2421 (flush _test-output-buffered-file) + 2422 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 2428 # check output + 2429 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array/0") + 2430 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array/1") + 2431 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array/2") + 2432 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array/3") + 2433 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array/4") + 2434 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array/5") + 2435 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array/6") + 2436 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array/7") + 2437 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array/8") + 2438 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-index-into-array/9") + 2439 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32" "F - test-convert-index-into-array/11") + 2440 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array/13") + 2441 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array/14") + 2442 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array/15") + 2443 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array/16") + 2444 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array/17") + 2445 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array/18") + 2446 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array/19") + 2447 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array/20") + 2448 # . epilogue + 2449 89/<- %esp 5/r32/ebp + 2450 5d/pop-to-ebp + 2451 c3/return + 2452 + 2453 test-convert-index-into-array-with-literal: + 2454 # . prologue + 2455 55/push-ebp + 2456 89/<- %ebp 4/r32/esp + 2457 # setup + 2458 (clear-stream _test-input-stream) + 2459 (clear-stream $_test-input-buffered-file->buffer) + 2460 (clear-stream _test-output-stream) + 2461 (clear-stream $_test-output-buffered-file->buffer) + 2462 # + 2463 (write _test-input-stream "fn foo {\n") + 2464 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") + 2465 (write _test-input-stream " var x/eax: (addr int) <- index arr, 2\n") + 2466 (write _test-input-stream "}\n") + 2467 # convert + 2468 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2469 (flush _test-output-buffered-file) + 2470 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 2476 # check output + 2477 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-with-literal/0") + 2478 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-with-literal/1") + 2479 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-with-literal/2") + 2480 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-with-literal/3") + 2481 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-with-literal/4") + 2482 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-with-literal/5") + 2483 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-with-literal/6") + 2484 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-with-literal/7") + 2485 # 2 * 4 bytes/elem + 4 bytes for size = offset 12 + 2486 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x0000000c) 0x00000000/r32" "F - test-convert-index-into-array-with-literal/8") + 2487 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-with-literal/9") + 2488 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-with-literal/10") + 2489 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-with-literal/11") + 2490 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-with-literal/12") + 2491 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-with-literal/13") + 2492 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-with-literal/14") + 2493 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-with-literal/15") + 2494 # . epilogue + 2495 89/<- %esp 5/r32/ebp + 2496 5d/pop-to-ebp + 2497 c3/return + 2498 + 2499 test-convert-index-into-array-on-stack: + 2500 # . prologue + 2501 55/push-ebp + 2502 89/<- %ebp 4/r32/esp + 2503 # setup + 2504 (clear-stream _test-input-stream) + 2505 (clear-stream $_test-input-buffered-file->buffer) + 2506 (clear-stream _test-output-stream) + 2507 (clear-stream $_test-output-buffered-file->buffer) + 2508 # + 2509 (write _test-input-stream "fn foo {\n") + 2510 (write _test-input-stream " var arr: (array int 3)\n") + 2511 (write _test-input-stream " var idx/eax: int <- copy 2\n") + 2512 (write _test-input-stream " var x/eax: (addr int) <- index arr, idx\n") + 2513 (write _test-input-stream "}\n") + 2514 # convert + 2515 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2516 (flush _test-output-buffered-file) + 2517 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 2523 # check output + 2524 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-on-stack/0") + 2525 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-on-stack/1") + 2526 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-on-stack/2") + 2527 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-on-stack/3") + 2528 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-on-stack/4") + 2529 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-on-stack/5") + 2530 # var arr + 2531 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x0000000c)" "F - test-convert-index-into-array-on-stack/6") + 2532 (check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-index-into-array-on-stack/7") + 2533 # var idx + 2534 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-on-stack/8") + 2535 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 2/imm32" "F - test-convert-index-into-array-on-stack/9") + 2536 # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc + 2537 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + eax<<0x00000002 + 0xfffffff4) 0x00000000/r32" "F - test-convert-index-into-array-on-stack/10") + 2538 # reclaim idx + 2539 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-on-stack/11") + 2540 # reclaim arr + 2541 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-index-into-array-on-stack/12") + 2542 # + 2543 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-on-stack/13") + 2544 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-on-stack/14") + 2545 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-on-stack/15") + 2546 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-on-stack/16") + 2547 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-on-stack/17") + 2548 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-on-stack/18") + 2549 # . epilogue + 2550 89/<- %esp 5/r32/ebp + 2551 5d/pop-to-ebp + 2552 c3/return + 2553 + 2554 test-convert-index-into-array-on-stack-with-literal: + 2555 # . prologue + 2556 55/push-ebp + 2557 89/<- %ebp 4/r32/esp + 2558 # setup + 2559 (clear-stream _test-input-stream) + 2560 (clear-stream $_test-input-buffered-file->buffer) + 2561 (clear-stream _test-output-stream) + 2562 (clear-stream $_test-output-buffered-file->buffer) + 2563 # + 2564 (write _test-input-stream "fn foo {\n") + 2565 (write _test-input-stream " var arr: (array int 3)\n") + 2566 (write _test-input-stream " var x/eax: (addr int) <- index arr, 2\n") + 2567 (write _test-input-stream "}\n") + 2568 # convert + 2569 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2570 (flush _test-output-buffered-file) + 2571 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 2577 # check output + 2578 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-on-stack-with-literal/0") + 2579 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-on-stack-with-literal/1") + 2580 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-on-stack-with-literal/2") + 2581 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-on-stack-with-literal/3") + 2582 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-on-stack-with-literal/4") + 2583 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-on-stack-with-literal/5") + 2584 # var arr + 2585 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x0000000c)" "F - test-convert-index-into-array-on-stack-with-literal/6") + 2586 (check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-index-into-array-on-stack-with-literal/7") + 2587 # var x + 2588 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-on-stack-with-literal/8") + 2589 # x is at (ebp-0x10) + 4 + 2*4 = ebp-4 + 2590 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + 0xfffffffc) 0x00000000/r32" "F - test-convert-index-into-array-on-stack-with-literal/9") + 2591 # reclaim x + 2592 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-on-stack-with-literal/10") + 2593 # reclaim arr + 2594 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-index-into-array-on-stack-with-literal/11") + 2595 # + 2596 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-on-stack-with-literal/12") + 2597 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-on-stack-with-literal/13") + 2598 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-on-stack-with-literal/14") + 2599 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-on-stack-with-literal/15") + 2600 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-on-stack-with-literal/16") + 2601 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-on-stack-with-literal/17") + 2602 # . epilogue + 2603 89/<- %esp 5/r32/ebp + 2604 5d/pop-to-ebp + 2605 c3/return + 2606 + 2607 test-convert-index-into-array-using-offset: + 2608 # . prologue + 2609 55/push-ebp + 2610 89/<- %ebp 4/r32/esp + 2611 # setup + 2612 (clear-stream _test-input-stream) + 2613 (clear-stream $_test-input-buffered-file->buffer) + 2614 (clear-stream _test-output-stream) + 2615 (clear-stream $_test-output-buffered-file->buffer) + 2616 # + 2617 (write _test-input-stream "fn foo {\n") + 2618 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") + 2619 (write _test-input-stream " var idx/ecx: int <- copy 3\n") + 2620 (write _test-input-stream " var off/ecx: (offset int) <- compute-offset arr, idx\n") + 2621 (write _test-input-stream " var x/eax: (addr int) <- index arr, off\n") + 2622 (write _test-input-stream "}\n") + 2623 # convert + 2624 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2625 (flush _test-output-buffered-file) + 2626 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 2632 # check output + 2633 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-using-offset/0") + 2634 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-using-offset/1") + 2635 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-using-offset/2") + 2636 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-using-offset/3") + 2637 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-using-offset/4") + 2638 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-using-offset/5") + 2639 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-using-offset/6") + 2640 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-using-offset/7") + 2641 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-using-offset/8") + 2642 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-index-into-array-using-offset/9") + 2643 (check-next-stream-line-equal _test-output-stream " 69/multiply %ecx 0x00000004/imm32 0x00000001/r32" "F - test-convert-index-into-array-using-offset/10") + 2644 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-using-offset/11") + 2645 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-using-offset/12") + 2646 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-using-offset/13") + 2647 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-using-offset/14") + 2648 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-using-offset/15") + 2649 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-using-offset/16") + 2650 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-using-offset/17") + 2651 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-using-offset/18") + 2652 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-using-offset/19") + 2653 # . epilogue + 2654 89/<- %esp 5/r32/ebp + 2655 5d/pop-to-ebp + 2656 c3/return + 2657 + 2658 test-convert-index-into-array-using-offset-on-stack: + 2659 # . prologue + 2660 55/push-ebp + 2661 89/<- %ebp 4/r32/esp + 2662 # setup + 2663 (clear-stream _test-input-stream) + 2664 (clear-stream $_test-input-buffered-file->buffer) + 2665 (clear-stream _test-output-stream) + 2666 (clear-stream $_test-output-buffered-file->buffer) + 2667 # + 2668 (write _test-input-stream "fn foo {\n") + 2669 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") + 2670 (write _test-input-stream " var idx: int\n") + 2671 (write _test-input-stream " var off/ecx: (offset int) <- compute-offset arr, idx\n") + 2672 (write _test-input-stream " var x/eax: (addr int) <- index arr, off\n") + 2673 (write _test-input-stream "}\n") + 2674 # convert + 2675 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2676 (flush _test-output-buffered-file) + 2677 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 2683 # check output + 2684 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-using-offset-on-stack/0") + 2685 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-using-offset-on-stack/1") + 2686 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-using-offset-on-stack/2") + 2687 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-using-offset-on-stack/3") + 2688 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-using-offset-on-stack/4") + 2689 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-using-offset-on-stack/5") + 2690 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-using-offset-on-stack/6") + 2691 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-using-offset-on-stack/7") + 2692 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-index-into-array-using-offset-on-stack/8") + 2693 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-using-offset-on-stack/9") + 2694 (check-next-stream-line-equal _test-output-stream " 69/multiply *(ebp+0xfffffff8) 0x00000004/imm32 0x00000001/r32" "F - test-convert-index-into-array-using-offset-on-stack/10") + 2695 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-using-offset-on-stack/11") + 2696 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-using-offset-on-stack/12") + 2697 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-index-into-array-using-offset-on-stack/13") + 2698 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-using-offset-on-stack/14") + 2699 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-using-offset-on-stack/15") + 2700 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-using-offset-on-stack/16") + 2701 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-using-offset-on-stack/17") + 2702 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-using-offset-on-stack/18") + 2703 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-using-offset-on-stack/19") + 2704 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-using-offset-on-stack/20") + 2705 # . epilogue + 2706 89/<- %esp 5/r32/ebp + 2707 5d/pop-to-ebp + 2708 c3/return + 2709 + 2710 test-convert-function-and-type-definition: + 2711 # . prologue + 2712 55/push-ebp + 2713 89/<- %ebp 4/r32/esp + 2714 # setup + 2715 (clear-stream _test-input-stream) + 2716 (clear-stream $_test-input-buffered-file->buffer) + 2717 (clear-stream _test-output-stream) + 2718 (clear-stream $_test-output-buffered-file->buffer) + 2719 # + 2720 (write _test-input-stream "fn foo a: (addr t) {\n") + 2721 (write _test-input-stream " var _a/eax: (addr t) <- copy a\n") + 2722 (write _test-input-stream " var b/ecx: (addr int) <- get _a, x\n") + 2723 (write _test-input-stream " var c/ecx: (addr int) <- get _a, y\n") 2724 (write _test-input-stream "}\n") - 2725 # convert - 2726 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2727 (flush _test-output-buffered-file) - 2728 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2734 # check output - 2735 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-and-type-definition/0") - 2736 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-and-type-definition/1") - 2737 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-and-type-definition/2") - 2738 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-and-type-definition/3") - 2739 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-and-type-definition/4") - 2740 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-and-type-definition/5") - 2741 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-and-type-definition/6") - 2742 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-and-type-definition/7") - 2743 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-and-type-definition/8") - 2744 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000000) 0x00000001/r32" "F - test-convert-function-and-type-definition/9") - 2745 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000004) 0x00000001/r32" "F - test-convert-function-and-type-definition/11") - 2746 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/13") - 2747 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/14") - 2748 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-and-type-definition/15") - 2749 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-and-type-definition/16") - 2750 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-and-type-definition/17") - 2751 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-and-type-definition/18") - 2752 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-and-type-definition/19") - 2753 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-and-type-definition/20") - 2754 # . epilogue - 2755 89/<- %esp 5/r32/ebp - 2756 5d/pop-to-ebp - 2757 c3/return - 2758 - 2759 test-convert-function-with-local-var-with-user-defined-type: - 2760 # . prologue - 2761 55/push-ebp - 2762 89/<- %ebp 4/r32/esp - 2763 # setup - 2764 (clear-stream _test-input-stream) - 2765 (clear-stream $_test-input-buffered-file->buffer) - 2766 (clear-stream _test-output-stream) - 2767 (clear-stream $_test-output-buffered-file->buffer) - 2768 # - 2769 (write _test-input-stream "fn foo {\n") - 2770 (write _test-input-stream " var a: t\n") - 2771 (write _test-input-stream "}\n") - 2772 (write _test-input-stream "type t {\n") - 2773 (write _test-input-stream " x: int\n") - 2774 (write _test-input-stream " y: int\n") + 2725 (write _test-input-stream "type t {\n") + 2726 (write _test-input-stream " x: int\n") + 2727 (write _test-input-stream " y: int\n") + 2728 (write _test-input-stream "}\n") + 2729 # convert + 2730 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2731 (flush _test-output-buffered-file) + 2732 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 2738 # check output + 2739 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-and-type-definition/0") + 2740 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-and-type-definition/1") + 2741 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-and-type-definition/2") + 2742 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-and-type-definition/3") + 2743 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-and-type-definition/4") + 2744 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-and-type-definition/5") + 2745 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-and-type-definition/6") + 2746 (check-next-stream-line-equal _test-output-stream " 8b/-> *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-and-type-definition/7") + 2747 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-and-type-definition/8") + 2748 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000000) 0x00000001/r32" "F - test-convert-function-and-type-definition/9") + 2749 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000004) 0x00000001/r32" "F - test-convert-function-and-type-definition/11") + 2750 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/13") + 2751 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/14") + 2752 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-and-type-definition/15") + 2753 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-and-type-definition/16") + 2754 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-and-type-definition/17") + 2755 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-and-type-definition/18") + 2756 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-and-type-definition/19") + 2757 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-and-type-definition/20") + 2758 # . epilogue + 2759 89/<- %esp 5/r32/ebp + 2760 5d/pop-to-ebp + 2761 c3/return + 2762 + 2763 test-convert-function-with-local-var-with-user-defined-type: + 2764 # . prologue + 2765 55/push-ebp + 2766 89/<- %ebp 4/r32/esp + 2767 # setup + 2768 (clear-stream _test-input-stream) + 2769 (clear-stream $_test-input-buffered-file->buffer) + 2770 (clear-stream _test-output-stream) + 2771 (clear-stream $_test-output-buffered-file->buffer) + 2772 # + 2773 (write _test-input-stream "fn foo {\n") + 2774 (write _test-input-stream " var a: t\n") 2775 (write _test-input-stream "}\n") - 2776 # convert - 2777 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2778 (flush _test-output-buffered-file) - 2779 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2785 # check output - 2786 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-with-user-defined-type/0") - 2787 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-with-user-defined-type/1") - 2788 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-with-user-defined-type/2") - 2789 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-with-user-defined-type/3") - 2790 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-with-user-defined-type/4") - 2791 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-with-user-defined-type/5") - 2792 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-with-user-defined-type/6") - 2793 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-with-user-defined-type/7") - 2794 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000008/imm32" "F - test-convert-function-with-local-var-with-user-defined-type/8") - 2795 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-with-user-defined-type/9") - 2796 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-with-user-defined-type/10") - 2797 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-with-user-defined-type/11") - 2798 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-with-user-defined-type/12") - 2799 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-with-user-defined-type/13") - 2800 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-with-user-defined-type/14") - 2801 # . epilogue - 2802 89/<- %esp 5/r32/ebp - 2803 5d/pop-to-ebp - 2804 c3/return - 2805 - 2806 test-convert-get-of-type-on-stack: - 2807 # . prologue - 2808 55/push-ebp - 2809 89/<- %ebp 4/r32/esp - 2810 # setup - 2811 (clear-stream _test-input-stream) - 2812 (clear-stream $_test-input-buffered-file->buffer) - 2813 (clear-stream _test-output-stream) - 2814 (clear-stream $_test-output-buffered-file->buffer) - 2815 # - 2816 (write _test-input-stream "fn foo {\n") - 2817 (write _test-input-stream " var a: t\n") - 2818 (write _test-input-stream " var c/ecx: (addr int) <- get a, y\n") - 2819 (write _test-input-stream "}\n") - 2820 (write _test-input-stream "type t {\n") - 2821 (write _test-input-stream " x: int\n") - 2822 (write _test-input-stream " y: int\n") + 2776 (write _test-input-stream "type t {\n") + 2777 (write _test-input-stream " x: int\n") + 2778 (write _test-input-stream " y: int\n") + 2779 (write _test-input-stream "}\n") + 2780 # convert + 2781 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2782 (flush _test-output-buffered-file) + 2783 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 2789 # check output + 2790 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-with-user-defined-type/0") + 2791 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-with-user-defined-type/1") + 2792 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-with-user-defined-type/2") + 2793 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-with-user-defined-type/3") + 2794 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-with-user-defined-type/4") + 2795 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-with-user-defined-type/5") + 2796 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-with-user-defined-type/6") + 2797 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-with-user-defined-type/7") + 2798 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000008/imm32" "F - test-convert-function-with-local-var-with-user-defined-type/8") + 2799 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-with-user-defined-type/9") + 2800 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-with-user-defined-type/10") + 2801 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-with-user-defined-type/11") + 2802 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-with-user-defined-type/12") + 2803 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-with-user-defined-type/13") + 2804 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-with-user-defined-type/14") + 2805 # . epilogue + 2806 89/<- %esp 5/r32/ebp + 2807 5d/pop-to-ebp + 2808 c3/return + 2809 + 2810 test-convert-function-call-with-arg-of-user-defined-type: + 2811 # . prologue + 2812 55/push-ebp + 2813 89/<- %ebp 4/r32/esp + 2814 # setup + 2815 (clear-stream _test-input-stream) + 2816 (clear-stream $_test-input-buffered-file->buffer) + 2817 (clear-stream _test-output-stream) + 2818 (clear-stream $_test-output-buffered-file->buffer) + 2819 # + 2820 (write _test-input-stream "fn f {\n") + 2821 (write _test-input-stream " var a: t\n") + 2822 (write _test-input-stream " foo a\n") 2823 (write _test-input-stream "}\n") - 2824 # convert - 2825 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2826 (flush _test-output-buffered-file) - 2827 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2833 # check output - 2834 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-get-of-type-on-stack/0") - 2835 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-get-of-type-on-stack/1") - 2836 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-get-of-type-on-stack/2") - 2837 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-get-of-type-on-stack/3") - 2838 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-get-of-type-on-stack/4") - 2839 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-get-of-type-on-stack/5") - 2840 # var a - 2841 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-get-of-type-on-stack/6") - 2842 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-get-of-type-on-stack/7") - 2843 # var c - 2844 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-get-of-type-on-stack/8") - 2845 # get - 2846 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32" "F - test-convert-get-of-type-on-stack/9") - 2847 # reclaim c - 2848 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-get-of-type-on-stack/10") - 2849 # reclaim a - 2850 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000008/imm32" "F - test-convert-get-of-type-on-stack/11") - 2851 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-get-of-type-on-stack/12") - 2852 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-get-of-type-on-stack/13") - 2853 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-get-of-type-on-stack/14") - 2854 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-get-of-type-on-stack/15") - 2855 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-get-of-type-on-stack/16") - 2856 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-get-of-type-on-stack/17") - 2857 # . epilogue - 2858 89/<- %esp 5/r32/ebp - 2859 5d/pop-to-ebp - 2860 c3/return - 2861 - 2862 test-convert-array-of-user-defined-types: - 2863 # . prologue - 2864 55/push-ebp - 2865 89/<- %ebp 4/r32/esp - 2866 # setup - 2867 (clear-stream _test-input-stream) - 2868 (clear-stream $_test-input-buffered-file->buffer) - 2869 (clear-stream _test-output-stream) - 2870 (clear-stream $_test-output-buffered-file->buffer) - 2871 # - 2872 (write _test-input-stream "type t {\n") # each t is 8 bytes, which is a power of 2 - 2873 (write _test-input-stream " x: int\n") - 2874 (write _test-input-stream " y: int\n") - 2875 (write _test-input-stream "}\n") - 2876 (write _test-input-stream "fn foo {\n") - 2877 (write _test-input-stream " var arr/eax: (addr array t) <- copy 0\n") - 2878 (write _test-input-stream " var idx/ecx: int <- copy 3\n") - 2879 (write _test-input-stream " var x/eax: (addr int) <- index arr, idx\n") - 2880 (write _test-input-stream "}\n") - 2881 # convert - 2882 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2883 (flush _test-output-buffered-file) - 2884 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2890 # check output - 2891 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-array-of-user-defined-types/0") - 2892 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-array-of-user-defined-types/1") - 2893 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-array-of-user-defined-types/2") - 2894 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-array-of-user-defined-types/3") - 2895 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-array-of-user-defined-types/4") - 2896 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-array-of-user-defined-types/5") - 2897 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-array-of-user-defined-types/6") - 2898 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-array-of-user-defined-types/7") - 2899 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-array-of-user-defined-types/8") - 2900 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-array-of-user-defined-types/9") - 2901 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx<<0x00000003 + 4) 0x00000000/r32" "F - test-convert-array-of-user-defined-types/11") - 2902 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-array-of-user-defined-types/13") - 2903 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-array-of-user-defined-types/14") - 2904 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-array-of-user-defined-types/15") - 2905 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-array-of-user-defined-types/16") - 2906 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-array-of-user-defined-types/17") - 2907 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-array-of-user-defined-types/18") - 2908 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-array-of-user-defined-types/19") - 2909 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-array-of-user-defined-types/20") - 2910 # . epilogue - 2911 89/<- %esp 5/r32/ebp - 2912 5d/pop-to-ebp - 2913 c3/return - 2914 - 2915 ####################################################### - 2916 # Parsing - 2917 ####################################################### - 2918 - 2919 parse-mu: # in: (addr buffered-file) - 2920 # pseudocode - 2921 # var curr-function: (addr (handle function)) = Program->functions - 2922 # var curr-type: (addr (handle typeinfo)) = Program->types - 2923 # var line: (stream byte 512) - 2924 # var word-slice: slice - 2925 # while true # line loop - 2926 # clear-stream(line) - 2927 # read-line-buffered(in, line) - 2928 # if (line->write == 0) break # end of file - 2929 # word-slice = next-mu-token(line) - 2930 # if slice-empty?(word-slice) # end of line - 2931 # continue - 2932 # else if slice-starts-with?(word-slice, "#") # comment - 2933 # continue # end of line - 2934 # else if slice-equal?(word-slice, "fn") - 2935 # var new-function: (handle function) = allocate(function) - 2936 # var vars: (stack (addr var) 256) - 2937 # populate-mu-function-header(in, new-function, vars) - 2938 # populate-mu-function-body(in, new-function, vars) - 2939 # assert(vars->top == 0) - 2940 # *curr-function = new-function - 2941 # curr-function = &new-function->next - 2942 # else if slice-equal?(word-slice, "type") - 2943 # word-slice = next-mu-token(line) - 2944 # type-id = pos-or-insert-slice(Type-id, word-slice) - 2945 # var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id) - 2946 # assert(next-word(line) == "{") - 2947 # populate-mu-type(in, new-type) - 2948 # else - 2949 # abort() - 2950 # - 2951 # . prologue - 2952 55/push-ebp - 2953 89/<- %ebp 4/r32/esp - 2954 # . save registers - 2955 50/push-eax - 2956 51/push-ecx - 2957 52/push-edx - 2958 53/push-ebx - 2959 56/push-esi - 2960 57/push-edi - 2961 # var line/ecx: (stream byte 512) - 2962 81 5/subop/subtract %esp 0x200/imm32 - 2963 68/push 0x200/imm32/length - 2964 68/push 0/imm32/read - 2965 68/push 0/imm32/write - 2966 89/<- %ecx 4/r32/esp - 2967 # var word-slice/edx: slice - 2968 68/push 0/imm32/end - 2969 68/push 0/imm32/start - 2970 89/<- %edx 4/r32/esp - 2971 # var curr-function/edi: (addr (handle function)) - 2972 bf/copy-to-edi _Program-functions/imm32 - 2973 # var curr-type/esi: (addr (handle typeinfo)) - 2974 be/copy-to-esi _Program-types/imm32 - 2975 # var vars/ebx: (stack (addr var) 256) - 2976 81 5/subop/subtract %esp 0x400/imm32 - 2977 68/push 0x400/imm32/length - 2978 68/push 0/imm32/top - 2979 89/<- %ebx 4/r32/esp - 2980 { - 2981 $parse-mu:line-loop: - 2982 (clear-stream %ecx) - 2983 (read-line-buffered *(ebp+8) %ecx) - 2984 # if (line->write == 0) break - 2985 81 7/subop/compare *ecx 0/imm32 - 2986 0f 84/jump-if-= break/disp32 - 2987 +-- 6 lines: #? # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------ - 2993 (next-mu-token %ecx %edx) - 2994 # if slice-empty?(word-slice) continue - 2995 (slice-empty? %edx) - 2996 3d/compare-eax-and 0/imm32/false - 2997 0f 85/jump-if-!= loop/disp32 - 2998 # if (*word-slice->start == "#") continue - 2999 # . eax = *word-slice->start - 3000 8b/-> *edx 0/r32/eax - 3001 8a/copy-byte *eax 0/r32/AL - 3002 81 4/subop/and %eax 0xff/imm32 - 3003 # . if (eax == '#') continue - 3004 3d/compare-eax-and 0x23/imm32/hash - 3005 0f 84/jump-if-= loop/disp32 - 3006 # if (slice-equal?(word-slice, "fn")) parse a function - 3007 { - 3008 $parse-mu:fn: - 3009 (slice-equal? %edx "fn") - 3010 3d/compare-eax-and 0/imm32/false - 3011 0f 84/jump-if-= break/disp32 - 3012 # var new-function/eax: (handle function) = populate-mu-function(line, in, vars) - 3013 (allocate Heap *Function-size) # => eax - 3014 (zero-out %eax *Function-size) - 3015 (clear-stack %ebx) - 3016 (populate-mu-function-header %ecx %eax %ebx) - 3017 (populate-mu-function-body *(ebp+8) %eax %ebx) - 3018 # *curr-function = new-function - 3019 89/<- *edi 0/r32/eax - 3020 # curr-function = &new-function->next - 3021 8d/address-> *(eax+0x14) 7/r32/edi # Function-next - 3022 e9/jump $parse-mu:line-loop/disp32 - 3023 } - 3024 # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition - 3025 { - 3026 $parse-mu:type: - 3027 (slice-equal? %edx "type") - 3028 3d/compare-eax-and 0/imm32 - 3029 0f 84/jump-if-= break/disp32 - 3030 (next-mu-token %ecx %edx) - 3031 # var type-id/eax: int - 3032 (pos-or-insert-slice Type-id %edx) # => eax - 3033 # var new-type/eax: (handle typeinfo) - 3034 (find-or-create-typeinfo %eax) # => eax - 3035 # TODO: ensure that 'line' has nothing else but '{' - 3036 (populate-mu-type *(ebp+8) %eax) # => eax - 3037 e9/jump $parse-mu:line-loop/disp32 - 3038 } - 3039 # otherwise abort - 3040 e9/jump $parse-mu:error1/disp32 - 3041 } # end line loop - 3042 $parse-mu:end: - 3043 # . reclaim locals - 3044 81 0/subop/add %esp 0x630/imm32 - 3045 # . restore registers - 3046 5f/pop-to-edi - 3047 5e/pop-to-esi - 3048 5b/pop-to-ebx - 3049 5a/pop-to-edx - 3050 59/pop-to-ecx - 3051 58/pop-to-eax - 3052 # . epilogue - 3053 89/<- %esp 5/r32/ebp - 3054 5d/pop-to-ebp - 3055 c3/return - 3056 - 3057 $parse-mu:error1: - 3058 # error("unexpected top-level command: " word-slice "\n") - 3059 (write-buffered Stderr "unexpected top-level command: ") - 3060 (write-slice-buffered Stderr %edx) - 3061 (write-buffered Stderr "\n") - 3062 (flush Stderr) - 3063 # . syscall(exit, 1) - 3064 bb/copy-to-ebx 1/imm32 - 3065 b8/copy-to-eax 1/imm32/exit - 3066 cd/syscall 0x80/imm8 - 3067 # never gets here + 2824 (write _test-input-stream "fn foo x: t {\n") + 2825 (write _test-input-stream "}\n") + 2826 (write _test-input-stream "type t {\n") + 2827 (write _test-input-stream " x: int\n") + 2828 (write _test-input-stream " y: int\n") + 2829 (write _test-input-stream "}\n") + 2830 # convert + 2831 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2832 (flush _test-output-buffered-file) + 2833 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 2839 # check output + 2840 (check-next-stream-line-equal _test-output-stream "f:" "F - test-convert-function-call-with-arg-of-user-defined-type/0") + 2841 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-arg-of-user-defined-type/1") + 2842 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/2") + 2843 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-arg-of-user-defined-type/3") + 2844 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-arg-of-user-defined-type/4") + 2845 (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:" "F - test-convert-function-call-with-arg-of-user-defined-type/5") + 2846 # var a: t + 2847 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type/6") + 2848 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type/7") + 2849 # foo a + 2850 (check-next-stream-line-equal _test-output-stream " (foo *(ebp+0xfffffff8) *(ebp+0xfffffffc))" "F - test-convert-function-call-with-arg-of-user-defined-type/8") + 2851 # + 2852 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000008/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type/9") + 2853 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-arg-of-user-defined-type/10") + 2854 (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:" "F - test-convert-function-call-with-arg-of-user-defined-type/11") + 2855 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-arg-of-user-defined-type/12") + 2856 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/13") + 2857 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/14") + 2858 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-arg-of-user-defined-type/15") + 2859 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-call-with-arg-of-user-defined-type/16") + 2860 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-arg-of-user-defined-type/17") + 2861 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/18") + 2862 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-arg-of-user-defined-type/19") + 2863 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-arg-of-user-defined-type/20") + 2864 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/21") + 2865 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/22") + 2866 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-arg-of-user-defined-type/23") + 2867 # . epilogue + 2868 89/<- %esp 5/r32/ebp + 2869 5d/pop-to-ebp + 2870 c3/return + 2871 + 2872 test-convert-function-call-with-arg-of-user-defined-type-register-indirect: + 2873 # . prologue + 2874 55/push-ebp + 2875 89/<- %ebp 4/r32/esp + 2876 # setup + 2877 (clear-stream _test-input-stream) + 2878 (clear-stream $_test-input-buffered-file->buffer) + 2879 (clear-stream _test-output-stream) + 2880 (clear-stream $_test-output-buffered-file->buffer) + 2881 # + 2882 (write _test-input-stream "fn f {\n") + 2883 (write _test-input-stream " var a/eax: (addr t) <- copy 0\n") + 2884 (write _test-input-stream " foo *a\n") + 2885 (write _test-input-stream "}\n") + 2886 (write _test-input-stream "fn foo x: t {\n") + 2887 (write _test-input-stream "}\n") + 2888 (write _test-input-stream "type t {\n") + 2889 (write _test-input-stream " x: int\n") + 2890 (write _test-input-stream " y: int\n") + 2891 (write _test-input-stream "}\n") + 2892 # convert + 2893 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2894 (flush _test-output-buffered-file) + 2895 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 2901 # check output + 2902 (check-next-stream-line-equal _test-output-stream "f:" "F - test-convert-function-call-with-arg-of-user-defined-type/0") + 2903 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-arg-of-user-defined-type/1") + 2904 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/2") + 2905 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-arg-of-user-defined-type/3") + 2906 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-arg-of-user-defined-type/4") + 2907 (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:" "F - test-convert-function-call-with-arg-of-user-defined-type/5") + 2908 # var a + 2909 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-call-with-arg-of-user-defined-type/6") + 2910 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type/7") + 2911 # foo a + 2912 (check-next-stream-line-equal _test-output-stream " (foo *(eax+0x00000000) *(eax+0x00000004))" "F - test-convert-function-call-with-arg-of-user-defined-type/8") + 2913 # + 2914 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-call-with-arg-of-user-defined-type/9") + 2915 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-arg-of-user-defined-type/10") + 2916 (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:" "F - test-convert-function-call-with-arg-of-user-defined-type/11") + 2917 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-arg-of-user-defined-type/12") + 2918 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/13") + 2919 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/14") + 2920 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-arg-of-user-defined-type/15") + 2921 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-call-with-arg-of-user-defined-type/16") + 2922 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-arg-of-user-defined-type/17") + 2923 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/18") + 2924 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-arg-of-user-defined-type/19") + 2925 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-arg-of-user-defined-type/20") + 2926 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/21") + 2927 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/22") + 2928 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-arg-of-user-defined-type/23") + 2929 # . epilogue + 2930 89/<- %esp 5/r32/ebp + 2931 5d/pop-to-ebp + 2932 c3/return + 2933 + 2934 # we don't have special support for call-by-reference; just explicitly create + 2935 # a new variable with the address of the arg + 2936 test-convert-function-call-with-arg-of-user-defined-type-by-reference: + 2937 # . prologue + 2938 55/push-ebp + 2939 89/<- %ebp 4/r32/esp + 2940 # setup + 2941 (clear-stream _test-input-stream) + 2942 (clear-stream $_test-input-buffered-file->buffer) + 2943 (clear-stream _test-output-stream) + 2944 (clear-stream $_test-output-buffered-file->buffer) + 2945 # + 2946 (write _test-input-stream "fn f {\n") + 2947 (write _test-input-stream " var a: t\n") + 2948 (write _test-input-stream " var b/eax: (addr t) <- address a\n") + 2949 (write _test-input-stream " foo b\n") + 2950 (write _test-input-stream "}\n") + 2951 (write _test-input-stream "fn foo x: (addr t) {\n") + 2952 (write _test-input-stream " var x/ecx: (addr int) <- copy x\n") + 2953 (write _test-input-stream " increment *x\n") + 2954 (write _test-input-stream "}\n") + 2955 (write _test-input-stream "type t {\n") + 2956 (write _test-input-stream " x: int\n") + 2957 (write _test-input-stream " y: int\n") + 2958 (write _test-input-stream "}\n") + 2959 # convert + 2960 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2961 (flush _test-output-buffered-file) + 2962 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 2968 # check output + 2969 (check-next-stream-line-equal _test-output-stream "f:" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0") + 2970 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1") + 2971 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/2") + 2972 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/3") + 2973 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4") + 2974 (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/5") + 2975 # var a: t + 2976 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/6") + 2977 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/7") + 2978 # var b/eax: (addr t) + 2979 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/8") + 2980 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/9") + 2981 # foo a + 2982 (check-next-stream-line-equal _test-output-stream " (foo %eax)" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10") + 2983 # + 2984 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/11") + 2985 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000008/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/12") + 2986 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13") + 2987 (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/14") + 2988 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15") + 2989 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/16") + 2990 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/17") + 2991 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18") + 2992 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19") + 2993 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20") + 2994 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/21") + 2995 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/22") + 2996 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23") + 2997 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/24") + 2998 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/25") + 2999 (check-next-stream-line-equal _test-output-stream " 89/<- %ecx 0x00000001/r32" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/26") + 3000 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *ecx" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/27") + 3001 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/28") + 3002 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/29") + 3003 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30") + 3004 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/31") + 3005 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/32") + 3006 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/33") + 3007 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/34") + 3008 # . epilogue + 3009 89/<- %esp 5/r32/ebp + 3010 5d/pop-to-ebp + 3011 c3/return + 3012 + 3013 test-convert-get-of-type-on-stack: + 3014 # . prologue + 3015 55/push-ebp + 3016 89/<- %ebp 4/r32/esp + 3017 # setup + 3018 (clear-stream _test-input-stream) + 3019 (clear-stream $_test-input-buffered-file->buffer) + 3020 (clear-stream _test-output-stream) + 3021 (clear-stream $_test-output-buffered-file->buffer) + 3022 # + 3023 (write _test-input-stream "fn foo {\n") + 3024 (write _test-input-stream " var a: t\n") + 3025 (write _test-input-stream " var c/ecx: (addr int) <- get a, y\n") + 3026 (write _test-input-stream "}\n") + 3027 (write _test-input-stream "type t {\n") + 3028 (write _test-input-stream " x: int\n") + 3029 (write _test-input-stream " y: int\n") + 3030 (write _test-input-stream "}\n") + 3031 # convert + 3032 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 3033 (flush _test-output-buffered-file) + 3034 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 3040 # check output + 3041 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-get-of-type-on-stack/0") + 3042 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-get-of-type-on-stack/1") + 3043 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-get-of-type-on-stack/2") + 3044 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-get-of-type-on-stack/3") + 3045 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-get-of-type-on-stack/4") + 3046 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-get-of-type-on-stack/5") + 3047 # var a + 3048 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-get-of-type-on-stack/6") + 3049 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-get-of-type-on-stack/7") + 3050 # var c + 3051 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-get-of-type-on-stack/8") + 3052 # get + 3053 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32" "F - test-convert-get-of-type-on-stack/9") + 3054 # reclaim c + 3055 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-get-of-type-on-stack/10") + 3056 # reclaim a + 3057 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000008/imm32" "F - test-convert-get-of-type-on-stack/11") + 3058 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-get-of-type-on-stack/12") + 3059 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-get-of-type-on-stack/13") + 3060 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-get-of-type-on-stack/14") + 3061 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-get-of-type-on-stack/15") + 3062 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-get-of-type-on-stack/16") + 3063 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-get-of-type-on-stack/17") + 3064 # . epilogue + 3065 89/<- %esp 5/r32/ebp + 3066 5d/pop-to-ebp + 3067 c3/return 3068 - 3069 $parse-mu:error2: - 3070 # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n") - 3071 (print-int32-buffered Stderr *ebx) - 3072 (write-buffered Stderr " vars not reclaimed after fn '") - 3073 (write-slice-buffered Stderr *eax) # Function-name - 3074 (write-buffered Stderr "'\n") - 3075 (flush Stderr) - 3076 # . syscall(exit, 1) - 3077 bb/copy-to-ebx 1/imm32 - 3078 b8/copy-to-eax 1/imm32/exit - 3079 cd/syscall 0x80/imm8 - 3080 # never gets here - 3081 - 3082 # scenarios considered: - 3083 # ✗ fn foo # no block - 3084 # ✓ fn foo { - 3085 # ✗ fn foo { { - 3086 # ✗ fn foo { } - 3087 # ✗ fn foo { } { - 3088 # ✗ fn foo x { - 3089 # ✗ fn foo x: { - 3090 # ✓ fn foo x: int { - 3091 # ✓ fn foo x: int { - 3092 # ✓ fn foo x: int -> y/eax: int { - 3093 populate-mu-function-header: # first-line: (addr stream byte), out: (handle function), vars: (addr stack (handle var)) - 3094 # pseudocode: - 3095 # var name: slice - 3096 # next-mu-token(first-line, name) - 3097 # assert(name not in '{' '}' '->') - 3098 # out->name = slice-to-string(name) - 3099 # ## inouts - 3100 # while true - 3101 # ## name - 3102 # name = next-mu-token(first-line) - 3103 # if (name == '{') goto done - 3104 # if (name == '->') break - 3105 # assert(name != '}') - 3106 # var v: (handle var) = parse-var-with-type(name, first-line) - 3107 # assert(v->register == null) - 3108 # # v->block-depth is implicitly 0 - 3109 # out->inouts = append(out->inouts, v) - 3110 # push(vars, v) - 3111 # ## outputs - 3112 # while true - 3113 # ## name - 3114 # name = next-mu-token(first-line) - 3115 # assert(name not in '{' '}' '->') - 3116 # var v: (handle var) = parse-var-with-type(name, first-line) - 3117 # assert(v->register != null) - 3118 # out->outputs = append(out->outputs, v) - 3119 # done: - 3120 # - 3121 # . prologue - 3122 55/push-ebp - 3123 89/<- %ebp 4/r32/esp - 3124 # . save registers - 3125 50/push-eax - 3126 51/push-ecx - 3127 52/push-edx - 3128 53/push-ebx - 3129 57/push-edi - 3130 # edi = out - 3131 8b/-> *(ebp+0xc) 7/r32/edi - 3132 # var word-slice/ecx: slice - 3133 68/push 0/imm32/end - 3134 68/push 0/imm32/start - 3135 89/<- %ecx 4/r32/esp - 3136 # read function name - 3137 (next-mu-token *(ebp+8) %ecx) - 3138 # error checking - 3139 # TODO: error if name starts with 'break' or 'loop' - 3140 # if (word-slice == '{') abort - 3141 (slice-equal? %ecx "{") # => eax - 3142 3d/compare-eax-and 0/imm32/false - 3143 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 - 3144 # if (word-slice == '->') abort - 3145 (slice-equal? %ecx "->") # => eax - 3146 3d/compare-eax-and 0/imm32/false - 3147 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 - 3148 # if (word-slice == '}') abort - 3149 (slice-equal? %ecx "}") # => eax - 3150 3d/compare-eax-and 0/imm32/false - 3151 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 - 3152 # save function name - 3153 (slice-to-string Heap %ecx) # => eax - 3154 89/<- *edi 0/r32/eax # Function-name - 3155 # initialize default subx-name as well - 3156 89/<- *(edi+4) 0/r32/eax # Function-subx-name - 3157 # save function inouts - 3158 { - 3159 $populate-mu-function-header:check-for-inout: - 3160 (next-mu-token *(ebp+8) %ecx) - 3161 # if (word-slice == '{') goto done - 3162 (slice-equal? %ecx "{") # => eax - 3163 3d/compare-eax-and 0/imm32/false - 3164 0f 85/jump-if-!= $populate-mu-function-header:done/disp32 - 3165 # if (word-slice == '->') break - 3166 (slice-equal? %ecx "->") # => eax - 3167 3d/compare-eax-and 0/imm32/false - 3168 0f 85/jump-if-!= break/disp32 - 3169 # if (word-slice == '}') abort - 3170 (slice-equal? %ecx "}") # => eax - 3171 3d/compare-eax-and 0/imm32/false - 3172 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 - 3173 # var v/ebx: (handle var) = parse-var-with-type(word-slice, first-line) - 3174 (parse-var-with-type %ecx *(ebp+8)) # => eax - 3175 89/<- %ebx 0/r32/eax - 3176 # assert(v->register == null) - 3177 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register - 3178 0f 85/jump-if-!= $populate-mu-function-header:error2/disp32 - 3179 # v->block-depth is implicitly 0 - 3180 # - 3181 # out->inouts = append(out->inouts, v) - 3182 (append-list Heap %ebx *(edi+8)) # Function-inouts => eax - 3183 89/<- *(edi+8) 0/r32/eax # Function-inouts - 3184 # push(vars, v) - 3185 (push *(ebp+0x10) %ebx) - 3186 # - 3187 e9/jump loop/disp32 - 3188 } - 3189 # save function outputs - 3190 { - 3191 $populate-mu-function-header:check-for-out: - 3192 (next-mu-token *(ebp+8) %ecx) - 3193 # if (word-slice == '{') break - 3194 (slice-equal? %ecx "{") # => eax - 3195 3d/compare-eax-and 0/imm32/false - 3196 0f 85/jump-if-!= break/disp32 - 3197 # if (word-slice == '->') abort - 3198 (slice-equal? %ecx "->") # => eax - 3199 3d/compare-eax-and 0/imm32/false - 3200 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 - 3201 # if (word-slice == '}') abort - 3202 (slice-equal? %ecx "}") # => eax + 3069 test-convert-array-of-user-defined-types: + 3070 # . prologue + 3071 55/push-ebp + 3072 89/<- %ebp 4/r32/esp + 3073 # setup + 3074 (clear-stream _test-input-stream) + 3075 (clear-stream $_test-input-buffered-file->buffer) + 3076 (clear-stream _test-output-stream) + 3077 (clear-stream $_test-output-buffered-file->buffer) + 3078 # + 3079 (write _test-input-stream "type t {\n") # each t is 8 bytes, which is a power of 2 + 3080 (write _test-input-stream " x: int\n") + 3081 (write _test-input-stream " y: int\n") + 3082 (write _test-input-stream "}\n") + 3083 (write _test-input-stream "fn foo {\n") + 3084 (write _test-input-stream " var arr/eax: (addr array t) <- copy 0\n") + 3085 (write _test-input-stream " var idx/ecx: int <- copy 3\n") + 3086 (write _test-input-stream " var x/eax: (addr int) <- index arr, idx\n") + 3087 (write _test-input-stream "}\n") + 3088 # convert + 3089 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 3090 (flush _test-output-buffered-file) + 3091 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 3097 # check output + 3098 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-array-of-user-defined-types/0") + 3099 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-array-of-user-defined-types/1") + 3100 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-array-of-user-defined-types/2") + 3101 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-array-of-user-defined-types/3") + 3102 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-array-of-user-defined-types/4") + 3103 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-array-of-user-defined-types/5") + 3104 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-array-of-user-defined-types/6") + 3105 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-array-of-user-defined-types/7") + 3106 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-array-of-user-defined-types/8") + 3107 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-array-of-user-defined-types/9") + 3108 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx<<0x00000003 + 4) 0x00000000/r32" "F - test-convert-array-of-user-defined-types/11") + 3109 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-array-of-user-defined-types/13") + 3110 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-array-of-user-defined-types/14") + 3111 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-array-of-user-defined-types/15") + 3112 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-array-of-user-defined-types/16") + 3113 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-array-of-user-defined-types/17") + 3114 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-array-of-user-defined-types/18") + 3115 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-array-of-user-defined-types/19") + 3116 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-array-of-user-defined-types/20") + 3117 # . epilogue + 3118 89/<- %esp 5/r32/ebp + 3119 5d/pop-to-ebp + 3120 c3/return + 3121 + 3122 ####################################################### + 3123 # Parsing + 3124 ####################################################### + 3125 + 3126 parse-mu: # in: (addr buffered-file) + 3127 # pseudocode + 3128 # var curr-function: (addr (handle function)) = Program->functions + 3129 # var curr-type: (addr (handle typeinfo)) = Program->types + 3130 # var line: (stream byte 512) + 3131 # var word-slice: slice + 3132 # while true # line loop + 3133 # clear-stream(line) + 3134 # read-line-buffered(in, line) + 3135 # if (line->write == 0) break # end of file + 3136 # word-slice = next-mu-token(line) + 3137 # if slice-empty?(word-slice) # end of line + 3138 # continue + 3139 # else if slice-starts-with?(word-slice, "#") # comment + 3140 # continue # end of line + 3141 # else if slice-equal?(word-slice, "fn") + 3142 # var new-function: (handle function) = allocate(function) + 3143 # var vars: (stack (addr var) 256) + 3144 # populate-mu-function-header(in, new-function, vars) + 3145 # populate-mu-function-body(in, new-function, vars) + 3146 # assert(vars->top == 0) + 3147 # *curr-function = new-function + 3148 # curr-function = &new-function->next + 3149 # else if slice-equal?(word-slice, "type") + 3150 # word-slice = next-mu-token(line) + 3151 # type-id = pos-or-insert-slice(Type-id, word-slice) + 3152 # var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id) + 3153 # assert(next-word(line) == "{") + 3154 # populate-mu-type(in, new-type) + 3155 # else + 3156 # abort() + 3157 # + 3158 # . prologue + 3159 55/push-ebp + 3160 89/<- %ebp 4/r32/esp + 3161 # . save registers + 3162 50/push-eax + 3163 51/push-ecx + 3164 52/push-edx + 3165 53/push-ebx + 3166 56/push-esi + 3167 57/push-edi + 3168 # var line/ecx: (stream byte 512) + 3169 81 5/subop/subtract %esp 0x200/imm32 + 3170 68/push 0x200/imm32/size + 3171 68/push 0/imm32/read + 3172 68/push 0/imm32/write + 3173 89/<- %ecx 4/r32/esp + 3174 # var word-slice/edx: slice + 3175 68/push 0/imm32/end + 3176 68/push 0/imm32/start + 3177 89/<- %edx 4/r32/esp + 3178 # var curr-function/edi: (addr (handle function)) + 3179 bf/copy-to-edi _Program-functions/imm32 + 3180 # var curr-type/esi: (addr (handle typeinfo)) + 3181 be/copy-to-esi _Program-types/imm32 + 3182 # var vars/ebx: (stack (addr var) 256) + 3183 81 5/subop/subtract %esp 0x400/imm32 + 3184 68/push 0x400/imm32/size + 3185 68/push 0/imm32/top + 3186 89/<- %ebx 4/r32/esp + 3187 { + 3188 $parse-mu:line-loop: + 3189 (clear-stream %ecx) + 3190 (read-line-buffered *(ebp+8) %ecx) + 3191 # if (line->write == 0) break + 3192 81 7/subop/compare *ecx 0/imm32 + 3193 0f 84/jump-if-= break/disp32 + 3194 +-- 6 lines: #? # dump line --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 3200 (next-mu-token %ecx %edx) + 3201 # if slice-empty?(word-slice) continue + 3202 (slice-empty? %edx) 3203 3d/compare-eax-and 0/imm32/false - 3204 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 - 3205 # - 3206 (parse-var-with-type %ecx *(ebp+8)) # => eax - 3207 89/<- %ebx 0/r32/eax - 3208 # assert(var->register != null) - 3209 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register - 3210 0f 84/jump-if-= $populate-mu-function-header:error3/disp32 - 3211 (append-list Heap %ebx *(edi+0xc)) # Function-outputs => eax - 3212 89/<- *(edi+0xc) 0/r32/eax # Function-outputs - 3213 e9/jump loop/disp32 - 3214 } - 3215 $populate-mu-function-header:done: - 3216 (check-no-tokens-left *(ebp+8)) - 3217 $populate-mu-function-header:end: - 3218 # . reclaim locals - 3219 81 0/subop/add %esp 8/imm32 - 3220 # . restore registers - 3221 5f/pop-to-edi - 3222 5b/pop-to-ebx - 3223 5a/pop-to-edx - 3224 59/pop-to-ecx - 3225 58/pop-to-eax - 3226 # . epilogue - 3227 89/<- %esp 5/r32/ebp - 3228 5d/pop-to-ebp - 3229 c3/return - 3230 - 3231 $populate-mu-function-header:error1: - 3232 # error("function header not in form 'fn <name> {'") - 3233 (write-buffered Stderr "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '") - 3234 (flush Stderr) - 3235 (rewind-stream *(ebp+8)) - 3236 (write-stream 2 *(ebp+8)) - 3237 (write-buffered Stderr "'\n") - 3238 (flush Stderr) - 3239 # . syscall(exit, 1) - 3240 bb/copy-to-ebx 1/imm32 - 3241 b8/copy-to-eax 1/imm32/exit - 3242 cd/syscall 0x80/imm8 - 3243 # never gets here - 3244 - 3245 $populate-mu-function-header:error2: - 3246 # error("function input '" var "' cannot be in a register") - 3247 (write-buffered Stderr "function input '") - 3248 (write-buffered Stderr *ebx) # Var-name - 3249 (write-buffered Stderr "' cannot be in a register") - 3250 (flush Stderr) - 3251 # . syscall(exit, 1) - 3252 bb/copy-to-ebx 1/imm32 - 3253 b8/copy-to-eax 1/imm32/exit - 3254 cd/syscall 0x80/imm8 - 3255 # never gets here - 3256 - 3257 $populate-mu-function-header:error3: - 3258 # error("function input '" var "' must be in a register") - 3259 (write-buffered Stderr "function input '") - 3260 (write-buffered Stderr *eax) # Var-name - 3261 (write-buffered Stderr " must be in a register'") - 3262 (flush Stderr) - 3263 (rewind-stream *(ebp+8)) - 3264 (write-stream 2 *(ebp+8)) - 3265 (write-buffered Stderr "'\n") - 3266 (flush Stderr) - 3267 # . syscall(exit, 1) - 3268 bb/copy-to-ebx 1/imm32 - 3269 b8/copy-to-eax 1/imm32/exit - 3270 cd/syscall 0x80/imm8 - 3271 # never gets here - 3272 - 3273 test-function-header-with-arg: - 3274 # . prologue - 3275 55/push-ebp - 3276 89/<- %ebp 4/r32/esp - 3277 # setup - 3278 (clear-stream _test-input-stream) - 3279 (write _test-input-stream "foo n: int {\n") - 3280 # var result/ecx: function - 3281 2b/subtract-> *Function-size 4/r32/esp - 3282 89/<- %ecx 4/r32/esp - 3283 (zero-out %ecx *Function-size) - 3284 # var vars/ebx: (stack (addr var) 16) - 3285 81 5/subop/subtract %esp 0x10/imm32 - 3286 68/push 0x10/imm32/length - 3287 68/push 0/imm32/top - 3288 89/<- %ebx 4/r32/esp - 3289 # convert - 3290 (populate-mu-function-header _test-input-stream %ecx %ebx) - 3291 # check result - 3292 (check-strings-equal *ecx "foo" "F - test-function-header-with-arg/name") # Function-name - 3293 # edx: (handle list var) = result->inouts - 3294 8b/-> *(ecx+8) 2/r32/edx # Function-inouts - 3295 # ebx: (handle var) = result->inouts->value - 3296 8b/-> *edx 3/r32/ebx # List-value - 3297 (check-strings-equal *ebx "n" "F - test-function-header-with-arg/inout:0") # Var-name - 3298 8b/-> *(ebx+4) 3/r32/ebx # Var-type - 3299 (check-ints-equal *ebx 1 "F - test-function-header-with-arg/inout:0/type:0") # Tree-left - 3300 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-arg/inout:0/type:1") # Tree-right - 3301 # . epilogue - 3302 89/<- %esp 5/r32/ebp - 3303 5d/pop-to-ebp - 3304 c3/return - 3305 - 3306 test-function-header-with-multiple-args: - 3307 # . prologue - 3308 55/push-ebp - 3309 89/<- %ebp 4/r32/esp - 3310 # setup - 3311 (clear-stream _test-input-stream) - 3312 (write _test-input-stream "foo a: int, b: int c: int {\n") - 3313 # result/ecx: (handle function) - 3314 2b/subtract-> *Function-size 4/r32/esp - 3315 89/<- %ecx 4/r32/esp - 3316 (zero-out %ecx *Function-size) - 3317 # var vars/ebx: (stack (addr var) 16) - 3318 81 5/subop/subtract %esp 0x10/imm32 - 3319 68/push 0x10/imm32/length - 3320 68/push 0/imm32/top - 3321 89/<- %ebx 4/r32/esp - 3322 # convert - 3323 (populate-mu-function-header _test-input-stream %ecx %ebx) - 3324 # check result - 3325 (check-strings-equal *ecx "foo") # Function-name - 3326 # edx: (handle list var) = result->inouts - 3327 8b/-> *(ecx+8) 2/r32/edx # Function-inouts - 3328 $test-function-header-with-multiple-args:inout0: - 3329 # ebx: (handle var) = result->inouts->value - 3330 8b/-> *edx 3/r32/ebx # List-value - 3331 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name - 3332 8b/-> *(ebx+4) 3/r32/ebx # Var-type - 3333 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:0/type:0") # Tree-left - 3334 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:0/type:1") # Tree-right - 3335 # edx = result->inouts->next - 3336 8b/-> *(edx+4) 2/r32/edx # List-next - 3337 $test-function-header-with-multiple-args:inout1: - 3338 # ebx = result->inouts->next->value - 3339 8b/-> *edx 3/r32/ebx # List-value - 3340 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args/inout:1") # Var-name - 3341 8b/-> *(ebx+4) 3/r32/ebx # Var-type - 3342 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:1/type:0") # Tree-left - 3343 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:1/type:1") # Tree-right - 3344 # edx = result->inouts->next->next - 3345 8b/-> *(edx+4) 2/r32/edx # List-next - 3346 $test-function-header-with-multiple-args:inout2: - 3347 # ebx = result->inouts->next->next->value - 3348 8b/-> *edx 3/r32/ebx # List-value - 3349 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args/inout:2") # Var-name - 3350 8b/-> *(ebx+4) 3/r32/ebx # Var-type - 3351 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:2/type:0") # Tree-left - 3352 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:2/type:1") # Tree-right - 3353 # . epilogue - 3354 89/<- %esp 5/r32/ebp - 3355 5d/pop-to-ebp - 3356 c3/return - 3357 - 3358 test-function-with-multiple-args-and-outputs: - 3359 # . prologue - 3360 55/push-ebp - 3361 89/<- %ebp 4/r32/esp - 3362 # setup - 3363 (clear-stream _test-input-stream) - 3364 (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx: int {\n") - 3365 # result/ecx: (handle function) - 3366 2b/subtract-> *Function-size 4/r32/esp - 3367 89/<- %ecx 4/r32/esp - 3368 (zero-out %ecx *Function-size) - 3369 # var vars/ebx: (stack (addr var) 16) - 3370 81 5/subop/subtract %esp 0x10/imm32 - 3371 68/push 0x10/imm32/length - 3372 68/push 0/imm32/top - 3373 89/<- %ebx 4/r32/esp - 3374 # convert - 3375 (populate-mu-function-header _test-input-stream %ecx %ebx) - 3376 # check result - 3377 (check-strings-equal *ecx "foo") # Function-name - 3378 # edx: (handle list var) = result->inouts - 3379 8b/-> *(ecx+8) 2/r32/edx # Function-inouts - 3380 # ebx: (handle var) = result->inouts->value - 3381 8b/-> *edx 3/r32/ebx # List-value - 3382 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0") # Var-name - 3383 8b/-> *(ebx+4) 3/r32/ebx # Var-type - 3384 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0") # Tree-left - 3385 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1") # Tree-right - 3386 # edx = result->inouts->next - 3387 8b/-> *(edx+4) 2/r32/edx # List-next - 3388 # ebx = result->inouts->next->value - 3389 8b/-> *edx 3/r32/ebx # List-value - 3390 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1") # Var-name - 3391 8b/-> *(ebx+4) 3/r32/ebx # Var-type - 3392 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0") # Tree-left - 3393 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1") # Tree-right - 3394 # edx = result->inouts->next->next - 3395 8b/-> *(edx+4) 2/r32/edx # List-next - 3396 # ebx = result->inouts->next->next->value - 3397 8b/-> *edx 3/r32/ebx # List-value - 3398 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2") # Var-name - 3399 8b/-> *(ebx+4) 3/r32/ebx # Var-type - 3400 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0") # Tree-left - 3401 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1") # Tree-right - 3402 # edx: (handle list var) = result->outputs - 3403 8b/-> *(ecx+0xc) 2/r32/edx # Function-outputs - 3404 # ebx: (handle var) = result->outputs->value - 3405 8b/-> *edx 3/r32/ebx # List-value - 3406 (check-strings-equal *ebx "x" "F - test-function-header-with-multiple-args-and-outputs/output:0") # Var-name - 3407 (check-strings-equal *(ebx+0x10) "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register - 3408 8b/-> *(ebx+4) 3/r32/ebx # Var-type - 3409 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-left - 3410 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-right - 3411 # edx = result->outputs->next - 3412 8b/-> *(edx+4) 2/r32/edx # List-next - 3413 # ebx = result->outputs->next->value - 3414 8b/-> *edx 3/r32/ebx # List-value - 3415 (check-strings-equal *ebx "y" "F - test-function-header-with-multiple-args-and-outputs/output:1") # Var-name - 3416 (check-strings-equal *(ebx+0x10) "edx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register - 3417 8b/-> *(ebx+4) 3/r32/ebx # Var-type - 3418 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-left - 3419 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-right - 3420 # . epilogue - 3421 89/<- %esp 5/r32/ebp - 3422 5d/pop-to-ebp - 3423 c3/return - 3424 - 3425 # format for variables with types - 3426 # x: int - 3427 # x: int, - 3428 # x/eax: int - 3429 # x/eax: int, - 3430 # ignores at most one trailing comma - 3431 # WARNING: modifies name - 3432 parse-var-with-type: # name: (addr slice), first-line: (addr stream byte) -> result/eax: (handle var) - 3433 # pseudocode: - 3434 # var s: slice - 3435 # if (!slice-ends-with(name, ":")) - 3436 # abort - 3437 # --name->end to skip ':' - 3438 # next-token-from-slice(name->start, name->end, '/', s) - 3439 # result = new-var-from-slice(s) - 3440 # ## register - 3441 # next-token-from-slice(s->end, name->end, '/', s) - 3442 # if (!slice-empty?(s)) - 3443 # v->register = slice-to-string(s) - 3444 # ## type - 3445 # var type: (handle tree type-id) = parse-type(first-line) - 3446 # v->type = type - 3447 # return v - 3448 # - 3449 # . prologue - 3450 55/push-ebp - 3451 89/<- %ebp 4/r32/esp - 3452 # . save registers - 3453 51/push-ecx - 3454 52/push-edx - 3455 53/push-ebx - 3456 56/push-esi - 3457 57/push-edi - 3458 # esi = name - 3459 8b/-> *(ebp+8) 6/r32/esi - 3460 # if (!slice-ends-with?(name, ":")) abort - 3461 8b/-> *(esi+4) 1/r32/ecx # Slice-end - 3462 49/decrement-ecx - 3463 8a/copy-byte *ecx 1/r32/CL - 3464 81 4/subop/and %ecx 0xff/imm32 - 3465 81 7/subop/compare %ecx 0x3a/imm32/colon - 3466 0f 85/jump-if-!= $parse-var-with-type:abort/disp32 - 3467 # --name->end to skip ':' - 3468 ff 1/subop/decrement *(esi+4) - 3469 # var s/ecx: slice - 3470 68/push 0/imm32/end - 3471 68/push 0/imm32/start - 3472 89/<- %ecx 4/r32/esp - 3473 $parse-var-with-type:parse-name: - 3474 (next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/' - 3475 $parse-var-with-type:create-var: - 3476 # edi = new-var-from-slice(s) - 3477 (new-var-from-slice Heap %ecx) # => eax - 3478 89/<- %edi 0/r32/eax - 3479 # save v->register - 3480 $parse-var-with-type:save-register: - 3481 # s = next-token(...) - 3482 (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx) # s->end, name->end, '/' - 3483 # if (!slice-empty?(s)) v->register = slice-to-string(s) - 3484 { - 3485 $parse-var-with-type:write-register: - 3486 (slice-empty? %ecx) # => eax - 3487 3d/compare-eax-and 0/imm32/false - 3488 75/jump-if-!= break/disp8 - 3489 (slice-to-string Heap %ecx) - 3490 89/<- *(edi+0x10) 0/r32/eax # Var-register - 3491 } - 3492 $parse-var-with-type:save-type: - 3493 (parse-type Heap *(ebp+0xc)) # => eax - 3494 #? (write-buffered Stderr "saving to var ") - 3495 #? (print-int32-buffered Stderr %edi) - 3496 #? (write-buffered Stderr Newline) - 3497 #? (flush Stderr) - 3498 89/<- *(edi+4) 0/r32/eax # Var-type - 3499 $parse-var-with-type:end: - 3500 # return result - 3501 89/<- %eax 7/r32/edi - 3502 # . reclaim locals - 3503 81 0/subop/add %esp 8/imm32 - 3504 # . restore registers - 3505 5f/pop-to-edi - 3506 5e/pop-to-esi - 3507 5b/pop-to-ebx - 3508 5a/pop-to-edx - 3509 59/pop-to-ecx - 3510 # . epilogue - 3511 89/<- %esp 5/r32/ebp - 3512 5d/pop-to-ebp - 3513 c3/return - 3514 - 3515 $parse-var-with-type:abort: - 3516 # error("var should have form 'name: type' in '" line "'\n") - 3517 (write-buffered Stderr "var should have form 'name: type' in '") - 3518 (flush Stderr) - 3519 (rewind-stream *(ebp+0xc)) - 3520 (write-stream 2 *(ebp+0xc)) - 3521 (write-buffered Stderr "'\n") - 3522 (flush Stderr) - 3523 # . syscall(exit, 1) - 3524 bb/copy-to-ebx 1/imm32 - 3525 b8/copy-to-eax 1/imm32/exit - 3526 cd/syscall 0x80/imm8 - 3527 # never gets here - 3528 - 3529 parse-type: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) - 3530 # pseudocode: - 3531 # var s: slice = next-mu-token(in) - 3532 # assert s != "" - 3533 # assert s != "->" - 3534 # assert s != "{" - 3535 # assert s != "}" - 3536 # if s == ")" - 3537 # return 0 - 3538 # result = allocate(Tree) - 3539 # zero-out(result, *Tree-size) - 3540 # if s != "(" - 3541 # result->left = pos-or-insert-slice(Type-id, s) - 3542 # return - 3543 # result->left = parse-type(ad, in) - 3544 # result->right = parse-type-tree(ad, in) - 3545 # - 3546 # . prologue - 3547 55/push-ebp - 3548 89/<- %ebp 4/r32/esp - 3549 # . save registers - 3550 51/push-ecx - 3551 52/push-edx - 3552 # var s/ecx: slice - 3553 68/push 0/imm32 - 3554 68/push 0/imm32 - 3555 89/<- %ecx 4/r32/esp - 3556 # s = next-mu-token(in) - 3557 (next-mu-token *(ebp+0xc) %ecx) - 3558 #? (write-buffered Stderr "tok: ") - 3559 #? (write-slice-buffered Stderr %ecx) - 3560 #? (write-buffered Stderr "$\n") - 3561 #? (flush Stderr) - 3562 # assert s != "" - 3563 (slice-equal? %ecx "") - 3564 3d/compare-eax-and 0/imm32/false - 3565 0f 85/jump-if-!= $parse-type:abort/disp32 - 3566 # assert s != "{" - 3567 (slice-equal? %ecx "{") - 3568 3d/compare-eax-and 0/imm32/false - 3569 0f 85/jump-if-!= $parse-type:abort/disp32 - 3570 # assert s != "}" - 3571 (slice-equal? %ecx "}") - 3572 3d/compare-eax-and 0/imm32/false - 3573 0f 85/jump-if-!= $parse-type:abort/disp32 - 3574 # assert s != "->" - 3575 (slice-equal? %ecx "->") - 3576 3d/compare-eax-and 0/imm32/false - 3577 0f 85/jump-if-!= $parse-type:abort/disp32 - 3578 # if (s == ")") return 0 - 3579 (slice-equal? %ecx ")") - 3580 3d/compare-eax-and 0/imm32/false - 3581 b8/copy-to-eax 0/imm32 - 3582 0f 85/jump-if-!= $parse-type:end/disp32 - 3583 # var result/edx: (handle tree type-id) - 3584 (allocate *(ebp+8) *Tree-size) # => eax - 3585 (zero-out %eax *Tree-size) - 3586 89/<- %edx 0/r32/eax - 3587 { - 3588 # if (s != "(") break - 3589 (slice-equal? %ecx "(") - 3590 3d/compare-eax-and 0/imm32/false - 3591 75/jump-if-!= break/disp8 - 3592 # EGREGIOUS HACK for static array sizes: if s is a number, parse it - 3593 { - 3594 (is-hex-int? %ecx) # => eax - 3595 3d/compare-eax-and 0/imm32/false - 3596 74/jump-if-= break/disp8 - 3597 (parse-hex-int-from-slice %ecx) # => eax - 3598 89/<- *edx 0/r32/eax # Tree-left - 3599 e9/jump $parse-type:return-edx/disp32 - 3600 } - 3601 # result->left = pos-or-insert-slice(Type-id, s) - 3602 (pos-or-insert-slice Type-id %ecx) # => eax - 3603 #? (write-buffered Stderr "=> {") - 3604 #? (print-int32-buffered Stderr %eax) - 3605 #? (write-buffered Stderr ", 0}\n") - 3606 #? (flush Stderr) - 3607 89/<- *edx 0/r32/eax # Tree-left - 3608 e9/jump $parse-type:return-edx/disp32 - 3609 } - 3610 # otherwise s == "(" - 3611 # result->left = parse-type(ad, in) - 3612 (parse-type *(ebp+8) *(ebp+0xc)) - 3613 #? (write-buffered Stderr "=> {") - 3614 #? (print-int32-buffered Stderr %eax) - 3615 89/<- *edx 0/r32/eax # Tree-left - 3616 # result->right = parse-type-tree(ad, in) - 3617 (parse-type-tree *(ebp+8) *(ebp+0xc)) - 3618 #? (write-buffered Stderr Space) - 3619 #? (print-int32-buffered Stderr %eax) - 3620 #? (write-buffered Stderr "}\n") - 3621 #? (flush Stderr) - 3622 89/<- *(edx+4) 0/r32/eax # Tree-right - 3623 $parse-type:return-edx: - 3624 89/<- %eax 2/r32/edx - 3625 $parse-type:end: - 3626 # . reclaim locals - 3627 81 0/subop/add %esp 8/imm32 - 3628 # . restore registers - 3629 5a/pop-to-edx - 3630 59/pop-to-ecx - 3631 # . epilogue - 3632 89/<- %esp 5/r32/ebp - 3633 5d/pop-to-ebp - 3634 c3/return - 3635 - 3636 $parse-type:abort: - 3637 # error("unexpected token when parsing type: '" s "'\n") - 3638 (write-buffered Stderr "unexpected token when parsing type: '") - 3639 (write-slice-buffered Stderr %ecx) - 3640 (write-buffered Stderr "'\n") - 3641 (flush Stderr) - 3642 # . syscall(exit, 1) - 3643 bb/copy-to-ebx 1/imm32 - 3644 b8/copy-to-eax 1/imm32/exit - 3645 cd/syscall 0x80/imm8 - 3646 # never gets here - 3647 - 3648 parse-type-tree: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) - 3649 # pseudocode: - 3650 # var tmp: (handle tree type-id) = parse-type(ad, in) - 3651 # if tmp == 0 - 3652 # return 0 - 3653 # result = allocate(Tree) - 3654 # zero-out(result, *Tree-size) - 3655 # result->left = tmp - 3656 # result->right = parse-type-tree(ad, in) - 3657 # - 3658 # . prologue - 3659 55/push-ebp - 3660 89/<- %ebp 4/r32/esp - 3661 # . save registers - 3662 51/push-ecx - 3663 52/push-edx - 3664 # var tmp/eax: (handle tree type-id) = parse-type(ad, in) - 3665 (parse-type *(ebp+8) *(ebp+0xc)) - 3666 # if (tmp == 0) return tmp - 3667 3d/compare-eax-and 0/imm32 - 3668 74/jump-if-= $parse-type-tree:end/disp8 - 3669 # var tmp2/ecx = tmp - 3670 89/<- %ecx 0/r32/eax - 3671 # var result/edx: (handle tree type-id) - 3672 (allocate *(ebp+8) *Tree-size) # => eax - 3673 (zero-out %eax *Tree-size) - 3674 89/<- %edx 0/r32/eax - 3675 # result->left = tmp2 - 3676 89/<- *edx 1/r32/ecx # Tree-left - 3677 # result->right = parse-type-tree(ad, in) - 3678 (parse-type-tree *(ebp+8) *(ebp+0xc)) - 3679 89/<- *(edx+4) 0/r32/eax # Tree-right - 3680 $parse-type-tree:return-edx: - 3681 89/<- %eax 2/r32/edx - 3682 $parse-type-tree:end: - 3683 # . restore registers - 3684 5a/pop-to-edx - 3685 59/pop-to-ecx - 3686 # . epilogue - 3687 89/<- %esp 5/r32/ebp - 3688 5d/pop-to-ebp - 3689 c3/return - 3690 - 3691 next-mu-token: # in: (addr stream byte), out: (addr slice) - 3692 # pseudocode: - 3693 # start: - 3694 # skip-chars-matching-whitespace(in) - 3695 # if in->read >= in->write # end of in - 3696 # out = {0, 0} - 3697 # return - 3698 # out->start = &in->data[in->read] - 3699 # var curr-byte/eax: byte = in->data[in->read] - 3700 # if curr->byte == ',' # comment token - 3701 # ++in->read - 3702 # goto start - 3703 # if curr-byte == '#' # comment - 3704 # goto done # treat as eof - 3705 # if curr-byte == '"' # string literal - 3706 # skip-string(in) - 3707 # goto done # no metadata - 3708 # if curr-byte == '(' - 3709 # ++in->read - 3710 # goto done - 3711 # if curr-byte == ')' - 3712 # ++in->read - 3713 # goto done - 3714 # # read a word - 3715 # while true - 3716 # if in->read >= in->write - 3717 # break - 3718 # curr-byte = in->data[in->read] - 3719 # if curr-byte == ' ' - 3720 # break - 3721 # if curr-byte == '\r' - 3722 # break - 3723 # if curr-byte == '\n' - 3724 # break - 3725 # if curr-byte == '(' - 3726 # break - 3727 # if curr-byte == ')' - 3728 # break - 3729 # if curr-byte == ',' - 3730 # break - 3731 # ++in->read - 3732 # done: - 3733 # out->end = &in->data[in->read] - 3734 # - 3735 # . prologue - 3736 55/push-ebp - 3737 89/<- %ebp 4/r32/esp - 3738 # . save registers - 3739 50/push-eax - 3740 51/push-ecx - 3741 56/push-esi - 3742 57/push-edi - 3743 # esi = in - 3744 8b/-> *(ebp+8) 6/r32/esi - 3745 # edi = out - 3746 8b/-> *(ebp+0xc) 7/r32/edi - 3747 $next-mu-token:start: - 3748 (skip-chars-matching-whitespace %esi) - 3749 $next-mu-token:check0: - 3750 # if (in->read >= in->write) return out = {0, 0} - 3751 # . ecx = in->read - 3752 8b/-> *(esi+4) 1/r32/ecx - 3753 # . if (ecx >= in->write) return out = {0, 0} - 3754 3b/compare 1/r32/ecx *esi - 3755 c7 0/subop/copy *edi 0/imm32 - 3756 c7 0/subop/copy *(edi+4) 0/imm32 - 3757 0f 8d/jump-if->= $next-mu-token:end/disp32 - 3758 # out->start = &in->data[in->read] - 3759 8d/copy-address *(esi+ecx+0xc) 0/r32/eax - 3760 89/<- *edi 0/r32/eax - 3761 # var curr-byte/eax: byte = in->data[in->read] - 3762 31/xor %eax 0/r32/eax - 3763 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL - 3764 { - 3765 $next-mu-token:check-for-comma: - 3766 # if (curr-byte != ',') break - 3767 3d/compare-eax-and 0x2c/imm32/comma - 3768 75/jump-if-!= break/disp8 - 3769 # ++in->read - 3770 ff 0/subop/increment *(esi+4) - 3771 # restart - 3772 e9/jump $next-mu-token:start/disp32 - 3773 } - 3774 { - 3775 $next-mu-token:check-for-comment: - 3776 # if (curr-byte != '#') break - 3777 3d/compare-eax-and 0x23/imm32/pound - 3778 75/jump-if-!= break/disp8 - 3779 # return eof - 3780 e9/jump $next-mu-token:done/disp32 - 3781 } - 3782 { - 3783 $next-mu-token:check-for-string-literal: - 3784 # if (curr-byte != '"') break - 3785 3d/compare-eax-and 0x22/imm32/dquote - 3786 75/jump-if-!= break/disp8 - 3787 (skip-string %esi) - 3788 # return - 3789 e9/jump $next-mu-token:done/disp32 - 3790 } - 3791 { - 3792 $next-mu-token:check-for-open-paren: - 3793 # if (curr-byte != '(') break - 3794 3d/compare-eax-and 0x28/imm32/open-paren - 3795 75/jump-if-!= break/disp8 - 3796 # ++in->read - 3797 ff 0/subop/increment *(esi+4) - 3798 # return - 3799 e9/jump $next-mu-token:done/disp32 - 3800 } + 3204 0f 85/jump-if-!= loop/disp32 + 3205 # if (*word-slice->start == "#") continue + 3206 # . eax = *word-slice->start + 3207 8b/-> *edx 0/r32/eax + 3208 8a/copy-byte *eax 0/r32/AL + 3209 81 4/subop/and %eax 0xff/imm32 + 3210 # . if (eax == '#') continue + 3211 3d/compare-eax-and 0x23/imm32/hash + 3212 0f 84/jump-if-= loop/disp32 + 3213 # if (slice-equal?(word-slice, "fn")) parse a function + 3214 { + 3215 $parse-mu:fn: + 3216 (slice-equal? %edx "fn") + 3217 3d/compare-eax-and 0/imm32/false + 3218 0f 84/jump-if-= break/disp32 + 3219 # var new-function/eax: (handle function) = populate-mu-function(line, in, vars) + 3220 (allocate Heap *Function-size) # => eax + 3221 (clear-stack %ebx) + 3222 (populate-mu-function-header %ecx %eax %ebx) + 3223 (populate-mu-function-body *(ebp+8) %eax %ebx) + 3224 # *curr-function = new-function + 3225 89/<- *edi 0/r32/eax + 3226 # curr-function = &new-function->next + 3227 8d/address-> *(eax+0x14) 7/r32/edi # Function-next + 3228 e9/jump $parse-mu:line-loop/disp32 + 3229 } + 3230 # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition + 3231 { + 3232 $parse-mu:type: + 3233 (slice-equal? %edx "type") + 3234 3d/compare-eax-and 0/imm32 + 3235 0f 84/jump-if-= break/disp32 + 3236 (next-mu-token %ecx %edx) + 3237 # var type-id/eax: int + 3238 (pos-or-insert-slice Type-id %edx) # => eax + 3239 # var new-type/eax: (handle typeinfo) + 3240 (find-or-create-typeinfo %eax) # => eax + 3241 # TODO: ensure that 'line' has nothing else but '{' + 3242 (populate-mu-type *(ebp+8) %eax) # => eax + 3243 e9/jump $parse-mu:line-loop/disp32 + 3244 } + 3245 # otherwise abort + 3246 e9/jump $parse-mu:error1/disp32 + 3247 } # end line loop + 3248 $parse-mu:end: + 3249 # . reclaim locals + 3250 81 0/subop/add %esp 0x630/imm32 + 3251 # . restore registers + 3252 5f/pop-to-edi + 3253 5e/pop-to-esi + 3254 5b/pop-to-ebx + 3255 5a/pop-to-edx + 3256 59/pop-to-ecx + 3257 58/pop-to-eax + 3258 # . epilogue + 3259 89/<- %esp 5/r32/ebp + 3260 5d/pop-to-ebp + 3261 c3/return + 3262 + 3263 $parse-mu:error1: + 3264 # error("unexpected top-level command: " word-slice "\n") + 3265 (write-buffered Stderr "unexpected top-level command: ") + 3266 (write-slice-buffered Stderr %edx) + 3267 (write-buffered Stderr "\n") + 3268 (flush Stderr) + 3269 # . syscall(exit, 1) + 3270 bb/copy-to-ebx 1/imm32 + 3271 b8/copy-to-eax 1/imm32/exit + 3272 cd/syscall 0x80/imm8 + 3273 # never gets here + 3274 + 3275 $parse-mu:error2: + 3276 # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n") + 3277 (print-int32-buffered Stderr *ebx) + 3278 (write-buffered Stderr " vars not reclaimed after fn '") + 3279 (write-slice-buffered Stderr *eax) # Function-name + 3280 (write-buffered Stderr "'\n") + 3281 (flush Stderr) + 3282 # . syscall(exit, 1) + 3283 bb/copy-to-ebx 1/imm32 + 3284 b8/copy-to-eax 1/imm32/exit + 3285 cd/syscall 0x80/imm8 + 3286 # never gets here + 3287 + 3288 # scenarios considered: + 3289 # ✗ fn foo # no block + 3290 # ✓ fn foo { + 3291 # ✗ fn foo { { + 3292 # ✗ fn foo { } + 3293 # ✗ fn foo { } { + 3294 # ✗ fn foo x { + 3295 # ✗ fn foo x: { + 3296 # ✓ fn foo x: int { + 3297 # ✓ fn foo x: int { + 3298 # ✓ fn foo x: int -> y/eax: int { + 3299 populate-mu-function-header: # first-line: (addr stream byte), out: (handle function), vars: (addr stack (handle var)) + 3300 # pseudocode: + 3301 # var name: slice + 3302 # next-mu-token(first-line, name) + 3303 # assert(name not in '{' '}' '->') + 3304 # out->name = slice-to-string(name) + 3305 # ## inouts + 3306 # while true + 3307 # ## name + 3308 # name = next-mu-token(first-line) + 3309 # if (name == '{') goto done + 3310 # if (name == '->') break + 3311 # assert(name != '}') + 3312 # var v: (handle var) = parse-var-with-type(name, first-line) + 3313 # assert(v->register == null) + 3314 # # v->block-depth is implicitly 0 + 3315 # out->inouts = append(out->inouts, v) + 3316 # push(vars, v) + 3317 # ## outputs + 3318 # while true + 3319 # ## name + 3320 # name = next-mu-token(first-line) + 3321 # assert(name not in '{' '}' '->') + 3322 # var v: (handle var) = parse-var-with-type(name, first-line) + 3323 # assert(v->register != null) + 3324 # out->outputs = append(out->outputs, v) + 3325 # done: + 3326 # + 3327 # . prologue + 3328 55/push-ebp + 3329 89/<- %ebp 4/r32/esp + 3330 # . save registers + 3331 50/push-eax + 3332 51/push-ecx + 3333 52/push-edx + 3334 53/push-ebx + 3335 57/push-edi + 3336 # edi = out + 3337 8b/-> *(ebp+0xc) 7/r32/edi + 3338 # var word-slice/ecx: slice + 3339 68/push 0/imm32/end + 3340 68/push 0/imm32/start + 3341 89/<- %ecx 4/r32/esp + 3342 # read function name + 3343 (next-mu-token *(ebp+8) %ecx) + 3344 # error checking + 3345 # TODO: error if name starts with 'break' or 'loop' + 3346 # if (word-slice == '{') abort + 3347 (slice-equal? %ecx "{") # => eax + 3348 3d/compare-eax-and 0/imm32/false + 3349 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 + 3350 # if (word-slice == '->') abort + 3351 (slice-equal? %ecx "->") # => eax + 3352 3d/compare-eax-and 0/imm32/false + 3353 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 + 3354 # if (word-slice == '}') abort + 3355 (slice-equal? %ecx "}") # => eax + 3356 3d/compare-eax-and 0/imm32/false + 3357 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 + 3358 # save function name + 3359 (slice-to-string Heap %ecx) # => eax + 3360 89/<- *edi 0/r32/eax # Function-name + 3361 # save function inouts + 3362 { + 3363 $populate-mu-function-header:check-for-inout: + 3364 (next-mu-token *(ebp+8) %ecx) + 3365 # if (word-slice == '{') goto done + 3366 (slice-equal? %ecx "{") # => eax + 3367 3d/compare-eax-and 0/imm32/false + 3368 0f 85/jump-if-!= $populate-mu-function-header:done/disp32 + 3369 # if (word-slice == '->') break + 3370 (slice-equal? %ecx "->") # => eax + 3371 3d/compare-eax-and 0/imm32/false + 3372 0f 85/jump-if-!= break/disp32 + 3373 # if (word-slice == '}') abort + 3374 (slice-equal? %ecx "}") # => eax + 3375 3d/compare-eax-and 0/imm32/false + 3376 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 + 3377 # var v/ebx: (handle var) = parse-var-with-type(word-slice, first-line) + 3378 (parse-var-with-type %ecx *(ebp+8)) # => eax + 3379 89/<- %ebx 0/r32/eax + 3380 # assert(v->register == null) + 3381 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register + 3382 0f 85/jump-if-!= $populate-mu-function-header:error2/disp32 + 3383 # v->block-depth is implicitly 0 + 3384 # + 3385 # out->inouts = append(out->inouts, v) + 3386 (append-list Heap %ebx *(edi+8)) # Function-inouts => eax + 3387 89/<- *(edi+8) 0/r32/eax # Function-inouts + 3388 # push(vars, v) + 3389 (push *(ebp+0x10) %ebx) + 3390 # + 3391 e9/jump loop/disp32 + 3392 } + 3393 # save function outputs + 3394 { + 3395 $populate-mu-function-header:check-for-out: + 3396 (next-mu-token *(ebp+8) %ecx) + 3397 # if (word-slice == '{') break + 3398 (slice-equal? %ecx "{") # => eax + 3399 3d/compare-eax-and 0/imm32/false + 3400 0f 85/jump-if-!= break/disp32 + 3401 # if (word-slice == '->') abort + 3402 (slice-equal? %ecx "->") # => eax + 3403 3d/compare-eax-and 0/imm32/false + 3404 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 + 3405 # if (word-slice == '}') abort + 3406 (slice-equal? %ecx "}") # => eax + 3407 3d/compare-eax-and 0/imm32/false + 3408 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 + 3409 # + 3410 (parse-var-with-type %ecx *(ebp+8)) # => eax + 3411 89/<- %ebx 0/r32/eax + 3412 # assert(var->register != null) + 3413 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register + 3414 0f 84/jump-if-= $populate-mu-function-header:error3/disp32 + 3415 (append-list Heap %ebx *(edi+0xc)) # Function-outputs => eax + 3416 89/<- *(edi+0xc) 0/r32/eax # Function-outputs + 3417 e9/jump loop/disp32 + 3418 } + 3419 $populate-mu-function-header:done: + 3420 (check-no-tokens-left *(ebp+8)) + 3421 $populate-mu-function-header:end: + 3422 # . reclaim locals + 3423 81 0/subop/add %esp 8/imm32 + 3424 # . restore registers + 3425 5f/pop-to-edi + 3426 5b/pop-to-ebx + 3427 5a/pop-to-edx + 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 $populate-mu-function-header:error1: + 3436 # error("function header not in form 'fn <name> {'") + 3437 (write-buffered Stderr "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '") + 3438 (flush Stderr) + 3439 (rewind-stream *(ebp+8)) + 3440 (write-stream 2 *(ebp+8)) + 3441 (write-buffered Stderr "'\n") + 3442 (flush Stderr) + 3443 # . syscall(exit, 1) + 3444 bb/copy-to-ebx 1/imm32 + 3445 b8/copy-to-eax 1/imm32/exit + 3446 cd/syscall 0x80/imm8 + 3447 # never gets here + 3448 + 3449 $populate-mu-function-header:error2: + 3450 # error("function input '" var "' cannot be in a register") + 3451 (write-buffered Stderr "function input '") + 3452 (write-buffered Stderr *ebx) # Var-name + 3453 (write-buffered Stderr "' cannot be in a register") + 3454 (flush Stderr) + 3455 # . syscall(exit, 1) + 3456 bb/copy-to-ebx 1/imm32 + 3457 b8/copy-to-eax 1/imm32/exit + 3458 cd/syscall 0x80/imm8 + 3459 # never gets here + 3460 + 3461 $populate-mu-function-header:error3: + 3462 # error("function input '" var "' must be in a register") + 3463 (write-buffered Stderr "function input '") + 3464 (write-buffered Stderr *eax) # Var-name + 3465 (write-buffered Stderr " must be in a register'") + 3466 (flush Stderr) + 3467 (rewind-stream *(ebp+8)) + 3468 (write-stream 2 *(ebp+8)) + 3469 (write-buffered Stderr "'\n") + 3470 (flush Stderr) + 3471 # . syscall(exit, 1) + 3472 bb/copy-to-ebx 1/imm32 + 3473 b8/copy-to-eax 1/imm32/exit + 3474 cd/syscall 0x80/imm8 + 3475 # never gets here + 3476 + 3477 test-function-header-with-arg: + 3478 # . prologue + 3479 55/push-ebp + 3480 89/<- %ebp 4/r32/esp + 3481 # setup + 3482 (clear-stream _test-input-stream) + 3483 (write _test-input-stream "foo n: int {\n") + 3484 # var result/ecx: function + 3485 2b/subtract *Function-size 4/r32/esp + 3486 89/<- %ecx 4/r32/esp + 3487 (zero-out %ecx *Function-size) + 3488 # var vars/ebx: (stack (addr var) 16) + 3489 81 5/subop/subtract %esp 0x10/imm32 + 3490 68/push 0x10/imm32/size + 3491 68/push 0/imm32/top + 3492 89/<- %ebx 4/r32/esp + 3493 # convert + 3494 (populate-mu-function-header _test-input-stream %ecx %ebx) + 3495 # check result + 3496 (check-strings-equal *ecx "foo" "F - test-function-header-with-arg/name") # Function-name + 3497 # edx: (handle list var) = result->inouts + 3498 8b/-> *(ecx+8) 2/r32/edx # Function-inouts + 3499 # ebx: (handle var) = result->inouts->value + 3500 8b/-> *edx 3/r32/ebx # List-value + 3501 (check-strings-equal *ebx "n" "F - test-function-header-with-arg/inout:0") # Var-name + 3502 8b/-> *(ebx+4) 3/r32/ebx # Var-type + 3503 (check-ints-equal *ebx 1 "F - test-function-header-with-arg/inout:0/type:0") # Tree-is-atom + 3504 (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-arg/inout:0/type:1") # Tree-value + 3505 (check-ints-equal *(ebx+8) 0 "F - test-function-header-with-arg/inout:0/type:2") # Tree-right + 3506 # . epilogue + 3507 89/<- %esp 5/r32/ebp + 3508 5d/pop-to-ebp + 3509 c3/return + 3510 + 3511 test-function-header-with-multiple-args: + 3512 # . prologue + 3513 55/push-ebp + 3514 89/<- %ebp 4/r32/esp + 3515 # setup + 3516 (clear-stream _test-input-stream) + 3517 (write _test-input-stream "foo a: int, b: int c: int {\n") + 3518 # result/ecx: (handle function) + 3519 2b/subtract *Function-size 4/r32/esp + 3520 89/<- %ecx 4/r32/esp + 3521 (zero-out %ecx *Function-size) + 3522 # var vars/ebx: (stack (addr var) 16) + 3523 81 5/subop/subtract %esp 0x10/imm32 + 3524 68/push 0x10/imm32/size + 3525 68/push 0/imm32/top + 3526 89/<- %ebx 4/r32/esp + 3527 # convert + 3528 (populate-mu-function-header _test-input-stream %ecx %ebx) + 3529 # check result + 3530 (check-strings-equal *ecx "foo") # Function-name + 3531 # edx: (handle list var) = result->inouts + 3532 8b/-> *(ecx+8) 2/r32/edx # Function-inouts + 3533 $test-function-header-with-multiple-args:inout0: + 3534 # ebx: (handle var) = result->inouts->value + 3535 8b/-> *edx 3/r32/ebx # List-value + 3536 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name + 3537 8b/-> *(ebx+4) 3/r32/ebx # Var-type + 3538 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:0/type:0") # Tree-is-atom + 3539 (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1") # Tree-value + 3540 (check-ints-equal *(ebx+8) 0 "F - test-function-header-with-multiple-args/inout:0/type:2") # Tree-right + 3541 # edx = result->inouts->next + 3542 8b/-> *(edx+4) 2/r32/edx # List-next + 3543 $test-function-header-with-multiple-args:inout1: + 3544 # ebx = result->inouts->next->value + 3545 8b/-> *edx 3/r32/ebx # List-value + 3546 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args/inout:1") # Var-name + 3547 8b/-> *(ebx+4) 3/r32/ebx # Var-type + 3548 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:1/type:0") # Tree-is-atom + 3549 (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1") # Tree-value + 3550 (check-ints-equal *(ebx+8) 0 "F - test-function-header-with-multiple-args/inout:1/type:2") # Tree-right + 3551 # edx = result->inouts->next->next + 3552 8b/-> *(edx+4) 2/r32/edx # List-next + 3553 $test-function-header-with-multiple-args:inout2: + 3554 # ebx = result->inouts->next->next->value + 3555 8b/-> *edx 3/r32/ebx # List-value + 3556 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args/inout:2") # Var-name + 3557 8b/-> *(ebx+4) 3/r32/ebx # Var-type + 3558 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:2/type:0") # Tree-is-atom + 3559 (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1") # Tree-value + 3560 (check-ints-equal *(ebx+8) 0 "F - test-function-header-with-multiple-args/inout:2/type:2") # Tree-right + 3561 # . epilogue + 3562 89/<- %esp 5/r32/ebp + 3563 5d/pop-to-ebp + 3564 c3/return + 3565 + 3566 test-function-with-multiple-args-and-outputs: + 3567 # . prologue + 3568 55/push-ebp + 3569 89/<- %ebp 4/r32/esp + 3570 # setup + 3571 (clear-stream _test-input-stream) + 3572 (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx: int {\n") + 3573 # result/ecx: (handle function) + 3574 2b/subtract *Function-size 4/r32/esp + 3575 89/<- %ecx 4/r32/esp + 3576 (zero-out %ecx *Function-size) + 3577 # var vars/ebx: (stack (addr var) 16) + 3578 81 5/subop/subtract %esp 0x10/imm32 + 3579 68/push 0x10/imm32/size + 3580 68/push 0/imm32/top + 3581 89/<- %ebx 4/r32/esp + 3582 # convert + 3583 (populate-mu-function-header _test-input-stream %ecx %ebx) + 3584 # check result + 3585 (check-strings-equal *ecx "foo") # Function-name + 3586 # edx: (handle list var) = result->inouts + 3587 8b/-> *(ecx+8) 2/r32/edx # Function-inouts + 3588 # ebx: (handle var) = result->inouts->value + 3589 8b/-> *edx 3/r32/ebx # List-value + 3590 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0") # Var-name + 3591 8b/-> *(ebx+4) 3/r32/ebx # Var-type + 3592 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0") # Tree-is-atom + 3593 (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1") # Tree-value + 3594 (check-ints-equal *(ebx+8) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2") # Tree-right + 3595 # edx = result->inouts->next + 3596 8b/-> *(edx+4) 2/r32/edx # List-next + 3597 # ebx = result->inouts->next->value + 3598 8b/-> *edx 3/r32/ebx # List-value + 3599 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1") # Var-name + 3600 8b/-> *(ebx+4) 3/r32/ebx # Var-type + 3601 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0") # Tree-is-atom + 3602 (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1") # Tree-value + 3603 (check-ints-equal *(ebx+8) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2") # Tree-right + 3604 # edx = result->inouts->next->next + 3605 8b/-> *(edx+4) 2/r32/edx # List-next + 3606 # ebx = result->inouts->next->next->value + 3607 8b/-> *edx 3/r32/ebx # List-value + 3608 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2") # Var-name + 3609 8b/-> *(ebx+4) 3/r32/ebx # Var-type + 3610 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0") # Tree-is-atom + 3611 (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1") # Tree-value + 3612 (check-ints-equal *(ebx+8) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2") # Tree-right + 3613 # edx: (handle list var) = result->outputs + 3614 8b/-> *(ecx+0xc) 2/r32/edx # Function-outputs + 3615 # ebx: (handle var) = result->outputs->value + 3616 8b/-> *edx 3/r32/ebx # List-value + 3617 (check-strings-equal *ebx "x" "F - test-function-header-with-multiple-args-and-outputs/output:0") # Var-name + 3618 (check-strings-equal *(ebx+0x10) "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register + 3619 8b/-> *(ebx+4) 3/r32/ebx # Var-type + 3620 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0") # Tree-is-atom + 3621 (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-value + 3622 (check-ints-equal *(ebx+8) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2") # Tree-right + 3623 # edx = result->outputs->next + 3624 8b/-> *(edx+4) 2/r32/edx # List-next + 3625 # ebx = result->outputs->next->value + 3626 8b/-> *edx 3/r32/ebx # List-value + 3627 (check-strings-equal *ebx "y" "F - test-function-header-with-multiple-args-and-outputs/output:1") # Var-name + 3628 (check-strings-equal *(ebx+0x10) "edx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register + 3629 8b/-> *(ebx+4) 3/r32/ebx # Var-type + 3630 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0") # Tree-is-atom + 3631 (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-value + 3632 (check-ints-equal *(ebx+8) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2") # Tree-right + 3633 # . epilogue + 3634 89/<- %esp 5/r32/ebp + 3635 5d/pop-to-ebp + 3636 c3/return + 3637 + 3638 # format for variables with types + 3639 # x: int + 3640 # x: int, + 3641 # x/eax: int + 3642 # x/eax: int, + 3643 # ignores at most one trailing comma + 3644 # WARNING: modifies name + 3645 parse-var-with-type: # name: (addr slice), first-line: (addr stream byte) -> result/eax: (handle var) + 3646 # pseudocode: + 3647 # var s: slice + 3648 # if (!slice-ends-with(name, ":")) + 3649 # abort + 3650 # --name->end to skip ':' + 3651 # next-token-from-slice(name->start, name->end, '/', s) + 3652 # result = new-var-from-slice(s) + 3653 # ## register + 3654 # next-token-from-slice(s->end, name->end, '/', s) + 3655 # if (!slice-empty?(s)) + 3656 # v->register = slice-to-string(s) + 3657 # ## type + 3658 # var type: (handle tree type-id) = parse-type(first-line) + 3659 # v->type = type + 3660 # return v + 3661 # + 3662 # . prologue + 3663 55/push-ebp + 3664 89/<- %ebp 4/r32/esp + 3665 # . save registers + 3666 51/push-ecx + 3667 52/push-edx + 3668 53/push-ebx + 3669 56/push-esi + 3670 57/push-edi + 3671 # esi = name + 3672 8b/-> *(ebp+8) 6/r32/esi + 3673 # if (!slice-ends-with?(name, ":")) abort + 3674 8b/-> *(esi+4) 1/r32/ecx # Slice-end + 3675 49/decrement-ecx + 3676 8a/copy-byte *ecx 1/r32/CL + 3677 81 4/subop/and %ecx 0xff/imm32 + 3678 81 7/subop/compare %ecx 0x3a/imm32/colon + 3679 0f 85/jump-if-!= $parse-var-with-type:abort/disp32 + 3680 # --name->end to skip ':' + 3681 ff 1/subop/decrement *(esi+4) + 3682 # var s/ecx: slice + 3683 68/push 0/imm32/end + 3684 68/push 0/imm32/start + 3685 89/<- %ecx 4/r32/esp + 3686 $parse-var-with-type:parse-name: + 3687 (next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/' + 3688 $parse-var-with-type:create-var: + 3689 # edi = new-var-from-slice(s) + 3690 (new-var-from-slice Heap %ecx) # => eax + 3691 89/<- %edi 0/r32/eax + 3692 # save v->register + 3693 $parse-var-with-type:save-register: + 3694 # s = next-token(...) + 3695 (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx) # s->end, name->end, '/' + 3696 # if (!slice-empty?(s)) v->register = slice-to-string(s) + 3697 { + 3698 $parse-var-with-type:write-register: + 3699 (slice-empty? %ecx) # => eax + 3700 3d/compare-eax-and 0/imm32/false + 3701 75/jump-if-!= break/disp8 + 3702 (slice-to-string Heap %ecx) + 3703 89/<- *(edi+0x10) 0/r32/eax # Var-register + 3704 } + 3705 $parse-var-with-type:save-type: + 3706 (parse-type Heap *(ebp+0xc)) # => eax + 3707 #? (write-buffered Stderr "saving to var ") + 3708 #? (print-int32-buffered Stderr %edi) + 3709 #? (write-buffered Stderr Newline) + 3710 #? (flush Stderr) + 3711 89/<- *(edi+4) 0/r32/eax # Var-type + 3712 $parse-var-with-type:end: + 3713 # return result + 3714 89/<- %eax 7/r32/edi + 3715 # . reclaim locals + 3716 81 0/subop/add %esp 8/imm32 + 3717 # . restore registers + 3718 5f/pop-to-edi + 3719 5e/pop-to-esi + 3720 5b/pop-to-ebx + 3721 5a/pop-to-edx + 3722 59/pop-to-ecx + 3723 # . epilogue + 3724 89/<- %esp 5/r32/ebp + 3725 5d/pop-to-ebp + 3726 c3/return + 3727 + 3728 $parse-var-with-type:abort: + 3729 # error("var should have form 'name: type' in '" line "'\n") + 3730 (write-buffered Stderr "var should have form 'name: type' in '") + 3731 (flush Stderr) + 3732 (rewind-stream *(ebp+0xc)) + 3733 (write-stream 2 *(ebp+0xc)) + 3734 (write-buffered Stderr "'\n") + 3735 (flush Stderr) + 3736 # . syscall(exit, 1) + 3737 bb/copy-to-ebx 1/imm32 + 3738 b8/copy-to-eax 1/imm32/exit + 3739 cd/syscall 0x80/imm8 + 3740 # never gets here + 3741 + 3742 parse-type: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) + 3743 # pseudocode: + 3744 # var s: slice = next-mu-token(in) + 3745 # assert s != "" + 3746 # assert s != "->" + 3747 # assert s != "{" + 3748 # assert s != "}" + 3749 # if s == ")" + 3750 # return 0 + 3751 # result = allocate(Tree) + 3752 # zero-out(result, *Tree-size) + 3753 # if s != "(" + 3754 # result->left-is-atom? = true + 3755 # result->value = pos-or-insert-slice(Type-id, s) + 3756 # return + 3757 # result->left = parse-type(ad, in) + 3758 # result->right = parse-type-tree(ad, in) + 3759 # + 3760 # . prologue + 3761 55/push-ebp + 3762 89/<- %ebp 4/r32/esp + 3763 # . save registers + 3764 51/push-ecx + 3765 52/push-edx + 3766 # var s/ecx: slice + 3767 68/push 0/imm32 + 3768 68/push 0/imm32 + 3769 89/<- %ecx 4/r32/esp + 3770 # s = next-mu-token(in) + 3771 (next-mu-token *(ebp+0xc) %ecx) + 3772 #? (write-buffered Stderr "tok: ") + 3773 #? (write-slice-buffered Stderr %ecx) + 3774 #? (write-buffered Stderr "$\n") + 3775 #? (flush Stderr) + 3776 # assert s != "" + 3777 (slice-equal? %ecx "") + 3778 3d/compare-eax-and 0/imm32/false + 3779 0f 85/jump-if-!= $parse-type:abort/disp32 + 3780 # assert s != "{" + 3781 (slice-equal? %ecx "{") + 3782 3d/compare-eax-and 0/imm32/false + 3783 0f 85/jump-if-!= $parse-type:abort/disp32 + 3784 # assert s != "}" + 3785 (slice-equal? %ecx "}") + 3786 3d/compare-eax-and 0/imm32/false + 3787 0f 85/jump-if-!= $parse-type:abort/disp32 + 3788 # assert s != "->" + 3789 (slice-equal? %ecx "->") + 3790 3d/compare-eax-and 0/imm32/false + 3791 0f 85/jump-if-!= $parse-type:abort/disp32 + 3792 # if (s == ")") return 0 + 3793 (slice-equal? %ecx ")") + 3794 3d/compare-eax-and 0/imm32/false + 3795 b8/copy-to-eax 0/imm32 + 3796 0f 85/jump-if-!= $parse-type:end/disp32 + 3797 # var result/edx: (handle tree type-id) + 3798 (allocate *(ebp+8) *Tree-size) # => eax + 3799 $aa-alloc: + 3800 89/<- %edx 0/r32/eax 3801 { - 3802 $next-mu-token:check-for-close-paren: - 3803 # if (curr-byte != ')') break - 3804 3d/compare-eax-and 0x29/imm32/close-paren + 3802 # if (s != "(") break + 3803 (slice-equal? %ecx "(") + 3804 3d/compare-eax-and 0/imm32/false 3805 75/jump-if-!= break/disp8 - 3806 # ++in->read - 3807 ff 0/subop/increment *(esi+4) - 3808 # return - 3809 e9/jump $next-mu-token:done/disp32 - 3810 } - 3811 { - 3812 $next-mu-token:regular-word-without-metadata: - 3813 # if (in->read >= in->write) break - 3814 # . ecx = in->read - 3815 8b/-> *(esi+4) 1/r32/ecx - 3816 # . if (ecx >= in->write) break - 3817 3b/compare *esi 1/r32/ecx - 3818 7d/jump-if->= break/disp8 - 3819 # var c/eax: byte = in->data[in->read] - 3820 31/xor %eax 0/r32/eax - 3821 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL - 3822 # if (c == ' ') break - 3823 3d/compare-eax-and 0x20/imm32/space - 3824 74/jump-if-= break/disp8 - 3825 # if (c == '\r') break - 3826 3d/compare-eax-and 0xd/imm32/carriage-return - 3827 74/jump-if-= break/disp8 - 3828 # if (c == '\n') break - 3829 3d/compare-eax-and 0xa/imm32/newline - 3830 74/jump-if-= break/disp8 - 3831 # if (c == '(') break - 3832 3d/compare-eax-and 0x28/imm32/open-paren - 3833 0f 84/jump-if-= break/disp32 - 3834 # if (c == ')') break - 3835 3d/compare-eax-and 0x29/imm32/close-paren - 3836 0f 84/jump-if-= break/disp32 - 3837 # if (c == ',') break - 3838 3d/compare-eax-and 0x2c/imm32/comma - 3839 0f 84/jump-if-= break/disp32 - 3840 # ++in->read - 3841 ff 0/subop/increment *(esi+4) - 3842 # - 3843 e9/jump loop/disp32 - 3844 } - 3845 $next-mu-token:done: - 3846 # out->end = &in->data[in->read] - 3847 8b/-> *(esi+4) 1/r32/ecx - 3848 8d/copy-address *(esi+ecx+0xc) 0/r32/eax - 3849 89/<- *(edi+4) 0/r32/eax - 3850 $next-mu-token:end: - 3851 # . restore registers - 3852 5f/pop-to-edi - 3853 5e/pop-to-esi - 3854 59/pop-to-ecx - 3855 58/pop-to-eax - 3856 # . epilogue - 3857 89/<- %esp 5/r32/ebp - 3858 5d/pop-to-ebp - 3859 c3/return - 3860 - 3861 pos-or-insert-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int - 3862 # . prologue - 3863 55/push-ebp - 3864 89/<- %ebp 4/r32/esp - 3865 # if (pos-slice(arr, s) != -1) return it - 3866 (pos-slice *(ebp+8) *(ebp+0xc)) # => eax - 3867 3d/compare-eax-and -1/imm32 - 3868 75/jump-if-!= $pos-or-insert-slice:end/disp8 - 3869 $pos-or-insert-slice:insert: - 3870 (slice-to-string Heap *(ebp+0xc)) # => eax - 3871 (write-int *(ebp+8) %eax) - 3872 (pos-slice *(ebp+8) *(ebp+0xc)) # => eax - 3873 $pos-or-insert-slice:end: - 3874 # . epilogue - 3875 89/<- %esp 5/r32/ebp - 3876 5d/pop-to-ebp - 3877 c3/return - 3878 - 3879 # return the index in an array of strings matching 's', -1 if not found - 3880 # index is denominated in elements, not bytes - 3881 pos-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int - 3882 # . prologue - 3883 55/push-ebp - 3884 89/<- %ebp 4/r32/esp - 3885 # . save registers - 3886 51/push-ecx - 3887 52/push-edx - 3888 53/push-ebx - 3889 56/push-esi - 3890 #? (write-buffered Stderr "pos-slice: ") - 3891 #? (write-slice-buffered Stderr *(ebp+0xc)) - 3892 #? (write-buffered Stderr "\n") - 3893 #? (flush Stderr) - 3894 # esi = arr - 3895 8b/-> *(ebp+8) 6/r32/esi - 3896 # var index/ecx: int = 0 - 3897 b9/copy-to-ecx 0/imm32 - 3898 # var curr/edx: (addr (addr array byte)) = arr->data - 3899 8d/copy-address *(esi+0xc) 2/r32/edx - 3900 # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write] - 3901 8b/-> *esi 3/r32/ebx - 3902 8d/copy-address *(esi+ebx+0xc) 3/r32/ebx - 3903 { - 3904 #? (write-buffered Stderr " ") - 3905 #? (print-int32-buffered Stderr %ecx) - 3906 #? (write-buffered Stderr "\n") - 3907 #? (flush Stderr) - 3908 # if (curr >= max) return -1 - 3909 39/compare %edx 3/r32/ebx - 3910 b8/copy-to-eax -1/imm32 - 3911 73/jump-if-addr>= $pos-slice:end/disp8 - 3912 # if (slice-equal?(s, *curr)) break - 3913 (slice-equal? *(ebp+0xc) *edx) # => eax - 3914 3d/compare-eax-and 0/imm32/false - 3915 75/jump-if-!= break/disp8 - 3916 # ++index - 3917 41/increment-ecx - 3918 # curr += 4 - 3919 81 0/subop/add %edx 4/imm32 - 3920 # - 3921 eb/jump loop/disp8 - 3922 } - 3923 # return index - 3924 89/<- %eax 1/r32/ecx - 3925 $pos-slice:end: - 3926 #? (write-buffered Stderr "=> ") - 3927 #? (print-int32-buffered Stderr %eax) - 3928 #? (write-buffered Stderr "\n") - 3929 # . restore registers - 3930 5e/pop-to-esi - 3931 5b/pop-to-ebx - 3932 5a/pop-to-edx - 3933 59/pop-to-ecx - 3934 # . epilogue - 3935 89/<- %esp 5/r32/ebp - 3936 5d/pop-to-ebp - 3937 c3/return - 3938 - 3939 test-parse-var-with-type: - 3940 # . prologue - 3941 55/push-ebp - 3942 89/<- %ebp 4/r32/esp - 3943 # (eax..ecx) = "x:" - 3944 b8/copy-to-eax "x:"/imm32 - 3945 8b/-> *eax 1/r32/ecx - 3946 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 3947 05/add-to-eax 4/imm32 - 3948 # var slice/ecx: slice = {eax, ecx} - 3949 51/push-ecx - 3950 50/push-eax - 3951 89/<- %ecx 4/r32/esp - 3952 # _test-input-stream contains "int" - 3953 (clear-stream _test-input-stream) - 3954 (write _test-input-stream "int") - 3955 # - 3956 (parse-var-with-type %ecx _test-input-stream) - 3957 8b/-> *eax 2/r32/edx # Var-name - 3958 (check-strings-equal %edx "x" "F - test-var-with-type/name") - 3959 8b/-> *(eax+4) 2/r32/edx # Var-type - 3960 (check-ints-equal *edx 1 "F - test-var-with-type/type") - 3961 (check-ints-equal *(edx+4) 0 "F - test-var-with-type/type") - 3962 # . epilogue - 3963 89/<- %esp 5/r32/ebp - 3964 5d/pop-to-ebp - 3965 c3/return - 3966 - 3967 test-parse-var-with-type-and-register: - 3968 # . prologue - 3969 55/push-ebp - 3970 89/<- %ebp 4/r32/esp - 3971 # (eax..ecx) = "x/eax:" - 3972 b8/copy-to-eax "x/eax:"/imm32 - 3973 8b/-> *eax 1/r32/ecx - 3974 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 3975 05/add-to-eax 4/imm32 - 3976 # var slice/ecx: slice = {eax, ecx} - 3977 51/push-ecx - 3978 50/push-eax - 3979 89/<- %ecx 4/r32/esp - 3980 # _test-input-stream contains "int" - 3981 (clear-stream _test-input-stream) - 3982 (write _test-input-stream "int") - 3983 # - 3984 (parse-var-with-type %ecx _test-input-stream) - 3985 8b/-> *eax 2/r32/edx # Var-name - 3986 (check-strings-equal %edx "x" "F - test-var-with-type-and-register/name") - 3987 8b/-> *(eax+0x10) 2/r32/edx # Var-register - 3988 (check-strings-equal %edx "eax" "F - test-var-with-type-and-register/register") - 3989 8b/-> *(eax+4) 2/r32/edx # Var-type - 3990 (check-ints-equal *edx 1 "F - test-var-with-type-and-register/type") - 3991 (check-ints-equal *(edx+4) 0 "F - test-var-with-type-and-register/type") - 3992 # . epilogue - 3993 89/<- %esp 5/r32/ebp - 3994 5d/pop-to-ebp - 3995 c3/return - 3996 - 3997 test-parse-var-with-trailing-characters: - 3998 # . prologue - 3999 55/push-ebp - 4000 89/<- %ebp 4/r32/esp - 4001 # (eax..ecx) = "x:" - 4002 b8/copy-to-eax "x:"/imm32 - 4003 8b/-> *eax 1/r32/ecx - 4004 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4005 05/add-to-eax 4/imm32 - 4006 # var slice/ecx: slice = {eax, ecx} - 4007 51/push-ecx - 4008 50/push-eax - 4009 89/<- %ecx 4/r32/esp - 4010 # _test-input-stream contains "int," - 4011 (clear-stream _test-input-stream) - 4012 (write _test-input-stream "int,") - 4013 # - 4014 (parse-var-with-type %ecx _test-input-stream) - 4015 8b/-> *eax 2/r32/edx # Var-name - 4016 (check-strings-equal %edx "x" "F - test-var-with-trailing-characters/name") - 4017 8b/-> *(eax+0x10) 2/r32/edx # Var-register - 4018 (check-ints-equal %edx 0 "F - test-var-with-trailing-characters/register") - 4019 8b/-> *(eax+4) 2/r32/edx # Var-type - 4020 (check-ints-equal *edx 1 "F - test-var-with-trailing-characters/type") - 4021 (check-ints-equal *(edx+4) 0 "F - test-var-with-trailing-characters/type") - 4022 # . epilogue - 4023 89/<- %esp 5/r32/ebp - 4024 5d/pop-to-ebp - 4025 c3/return - 4026 - 4027 test-parse-var-with-register-and-trailing-characters: - 4028 # . prologue - 4029 55/push-ebp - 4030 89/<- %ebp 4/r32/esp - 4031 # (eax..ecx) = "x/eax:" - 4032 b8/copy-to-eax "x/eax:"/imm32 - 4033 8b/-> *eax 1/r32/ecx - 4034 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4035 05/add-to-eax 4/imm32 - 4036 # var slice/ecx: slice = {eax, ecx} - 4037 51/push-ecx - 4038 50/push-eax - 4039 89/<- %ecx 4/r32/esp - 4040 # _test-input-stream contains "int," - 4041 (clear-stream _test-input-stream) - 4042 (write _test-input-stream "int,") - 4043 # - 4044 (parse-var-with-type %ecx _test-input-stream) - 4045 8b/-> *eax 2/r32/edx # Var-name - 4046 (check-strings-equal %edx "x" "F - test-var-with-register-and-trailing-characters/name") - 4047 8b/-> *(eax+0x10) 2/r32/edx # Var-register - 4048 (check-strings-equal %edx "eax" "F - test-var-with-register-and-trailing-characters/register") - 4049 8b/-> *(eax+4) 2/r32/edx # Var-type - 4050 (check-ints-equal *edx 1 "F - test-var-with-register-and-trailing-characters/type") - 4051 (check-ints-equal *(edx+4) 0 "F - test-var-with-register-and-trailing-characters/type") - 4052 # . epilogue - 4053 89/<- %esp 5/r32/ebp - 4054 5d/pop-to-ebp - 4055 c3/return - 4056 - 4057 test-parse-var-with-compound-type: - 4058 # . prologue - 4059 55/push-ebp - 4060 89/<- %ebp 4/r32/esp - 4061 # (eax..ecx) = "x:" - 4062 b8/copy-to-eax "x:"/imm32 - 4063 8b/-> *eax 1/r32/ecx - 4064 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4065 05/add-to-eax 4/imm32 - 4066 # var slice/ecx: slice = {eax, ecx} - 4067 51/push-ecx - 4068 50/push-eax - 4069 89/<- %ecx 4/r32/esp - 4070 # _test-input-stream contains "(addr int)" - 4071 (clear-stream _test-input-stream) - 4072 (write _test-input-stream "(addr int)") - 4073 # - 4074 (parse-var-with-type %ecx _test-input-stream) - 4075 8b/-> *eax 2/r32/edx # Var-name - 4076 (check-strings-equal %edx "x" "F - test-var-with-compound-type/name") - 4077 8b/-> *(eax+0x10) 2/r32/edx # Var-register - 4078 (check-ints-equal %edx 0 "F - test-var-with-compound-type/register") - 4079 # var type/edx: (handle tree type-id) = var->type - 4080 8b/-> *(eax+4) 2/r32/edx # Var-type - 4081 # type->left == atom(addr) - 4082 8b/-> *edx 0/r32/eax # Atom-value - 4083 (check-ints-equal *eax 2 "F - test-var-with-compound-type/type:0") # Tree-left - 4084 # type->right->left == atom(int) - 4085 8b/-> *(edx+4) 2/r32/edx # Tree-right - 4086 8b/-> *edx 0/r32/eax # Tree-left - 4087 (check-ints-equal *eax 1 "F - test-var-with-compound-type/type:1") # Atom-value - 4088 # type->right->right == null - 4089 (check-ints-equal *(edx+4) 0 "F - test-var-with-compound-type/type:2") # Tree-right - 4090 # . epilogue - 4091 89/<- %esp 5/r32/ebp - 4092 5d/pop-to-ebp - 4093 c3/return - 4094 - 4095 # identifier starts with a letter or '$' or '_' - 4096 # no constraints at the moment on later letters - 4097 # all we really want to do so far is exclude '{', '}' and '->' - 4098 is-identifier?: # in: (addr slice) -> result/eax: boolean - 4099 # . prologue - 4100 55/push-ebp - 4101 89/<- %ebp 4/r32/esp - 4102 # if (slice-empty?(in)) return false - 4103 (slice-empty? *(ebp+8)) # => eax - 4104 3d/compare-eax-and 0/imm32/false - 4105 75/jump-if-!= $is-identifier?:false/disp8 - 4106 # var c/eax: byte = *in->start - 4107 8b/-> *(ebp+8) 0/r32/eax - 4108 8b/-> *eax 0/r32/eax - 4109 8a/copy-byte *eax 0/r32/AL - 4110 81 4/subop/and %eax 0xff/imm32 - 4111 # if (c == '$') return true - 4112 3d/compare-eax-and 0x24/imm32/$ - 4113 74/jump-if-= $is-identifier?:true/disp8 - 4114 # if (c == '_') return true - 4115 3d/compare-eax-and 0x5f/imm32/_ - 4116 74/jump-if-= $is-identifier?:true/disp8 - 4117 # drop case - 4118 25/and-eax-with 0x5f/imm32 - 4119 # if (c < 'A') return false - 4120 3d/compare-eax-and 0x41/imm32/A - 4121 7c/jump-if-< $is-identifier?:false/disp8 - 4122 # if (c > 'Z') return false - 4123 3d/compare-eax-and 0x5a/imm32/Z - 4124 7f/jump-if-> $is-identifier?:false/disp8 - 4125 # otherwise return true - 4126 $is-identifier?:true: - 4127 b8/copy-to-eax 1/imm32/true - 4128 eb/jump $is-identifier?:end/disp8 - 4129 $is-identifier?:false: - 4130 b8/copy-to-eax 0/imm32/false - 4131 $is-identifier?:end: - 4132 # . epilogue - 4133 89/<- %esp 5/r32/ebp - 4134 5d/pop-to-ebp - 4135 c3/return - 4136 - 4137 test-is-identifier-dollar: - 4138 # . prologue - 4139 55/push-ebp - 4140 89/<- %ebp 4/r32/esp - 4141 # (eax..ecx) = "$a" - 4142 b8/copy-to-eax "$a"/imm32 - 4143 8b/-> *eax 1/r32/ecx - 4144 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4145 05/add-to-eax 4/imm32 - 4146 # var slice/ecx: slice = {eax, ecx} - 4147 51/push-ecx - 4148 50/push-eax - 4149 89/<- %ecx 4/r32/esp - 4150 # - 4151 (is-identifier? %ecx) - 4152 (check-ints-equal %eax 1 "F - test-is-identifier-dollar") - 4153 # . epilogue - 4154 89/<- %esp 5/r32/ebp - 4155 5d/pop-to-ebp - 4156 c3/return - 4157 - 4158 test-is-identifier-underscore: - 4159 # . prologue - 4160 55/push-ebp - 4161 89/<- %ebp 4/r32/esp - 4162 # (eax..ecx) = "_a" - 4163 b8/copy-to-eax "_a"/imm32 - 4164 8b/-> *eax 1/r32/ecx - 4165 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4166 05/add-to-eax 4/imm32 - 4167 # var slice/ecx: slice = {eax, ecx} - 4168 51/push-ecx - 4169 50/push-eax - 4170 89/<- %ecx 4/r32/esp - 4171 # - 4172 (is-identifier? %ecx) - 4173 (check-ints-equal %eax 1 "F - test-is-identifier-underscore") - 4174 # . epilogue - 4175 89/<- %esp 5/r32/ebp - 4176 5d/pop-to-ebp - 4177 c3/return - 4178 - 4179 test-is-identifier-a: - 4180 # . prologue - 4181 55/push-ebp - 4182 89/<- %ebp 4/r32/esp - 4183 # (eax..ecx) = "a$" - 4184 b8/copy-to-eax "a$"/imm32 - 4185 8b/-> *eax 1/r32/ecx - 4186 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4187 05/add-to-eax 4/imm32 - 4188 # var slice/ecx: slice = {eax, ecx} - 4189 51/push-ecx - 4190 50/push-eax - 4191 89/<- %ecx 4/r32/esp - 4192 # - 4193 (is-identifier? %ecx) - 4194 (check-ints-equal %eax 1 "F - test-is-identifier-a") - 4195 # . epilogue - 4196 89/<- %esp 5/r32/ebp - 4197 5d/pop-to-ebp - 4198 c3/return - 4199 - 4200 test-is-identifier-z: - 4201 # . prologue - 4202 55/push-ebp - 4203 89/<- %ebp 4/r32/esp - 4204 # (eax..ecx) = "z$" - 4205 b8/copy-to-eax "z$"/imm32 - 4206 8b/-> *eax 1/r32/ecx - 4207 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4208 05/add-to-eax 4/imm32 - 4209 # var slice/ecx: slice = {eax, ecx} - 4210 51/push-ecx - 4211 50/push-eax - 4212 89/<- %ecx 4/r32/esp - 4213 # - 4214 (is-identifier? %ecx) - 4215 (check-ints-equal %eax 1 "F - test-is-identifier-z") - 4216 # . epilogue - 4217 89/<- %esp 5/r32/ebp - 4218 5d/pop-to-ebp - 4219 c3/return - 4220 - 4221 test-is-identifier-A: - 4222 # . prologue - 4223 55/push-ebp - 4224 89/<- %ebp 4/r32/esp - 4225 # (eax..ecx) = "A$" - 4226 b8/copy-to-eax "A$"/imm32 - 4227 8b/-> *eax 1/r32/ecx - 4228 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4229 05/add-to-eax 4/imm32 - 4230 # var slice/ecx: slice = {eax, ecx} - 4231 51/push-ecx - 4232 50/push-eax - 4233 89/<- %ecx 4/r32/esp - 4234 # - 4235 (is-identifier? %ecx) - 4236 (check-ints-equal %eax 1 "F - test-is-identifier-A") - 4237 # . epilogue - 4238 89/<- %esp 5/r32/ebp - 4239 5d/pop-to-ebp - 4240 c3/return - 4241 - 4242 test-is-identifier-Z: - 4243 # . prologue - 4244 55/push-ebp - 4245 89/<- %ebp 4/r32/esp - 4246 # (eax..ecx) = "Z$" - 4247 b8/copy-to-eax "Z$"/imm32 - 4248 8b/-> *eax 1/r32/ecx - 4249 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4250 05/add-to-eax 4/imm32 - 4251 # var slice/ecx: slice = {eax, ecx} - 4252 51/push-ecx - 4253 50/push-eax - 4254 89/<- %ecx 4/r32/esp - 4255 # - 4256 (is-identifier? %ecx) - 4257 (check-ints-equal %eax 1 "F - test-is-identifier-Z") - 4258 # . epilogue - 4259 89/<- %esp 5/r32/ebp - 4260 5d/pop-to-ebp - 4261 c3/return - 4262 - 4263 test-is-identifier-@: - 4264 # character before 'A' is invalid - 4265 # . prologue - 4266 55/push-ebp - 4267 89/<- %ebp 4/r32/esp - 4268 # (eax..ecx) = "@a" - 4269 b8/copy-to-eax "@a"/imm32 - 4270 8b/-> *eax 1/r32/ecx - 4271 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4272 05/add-to-eax 4/imm32 - 4273 # var slice/ecx: slice = {eax, ecx} - 4274 51/push-ecx - 4275 50/push-eax - 4276 89/<- %ecx 4/r32/esp - 4277 # - 4278 (is-identifier? %ecx) - 4279 (check-ints-equal %eax 0 "F - test-is-identifier-@") - 4280 # . epilogue - 4281 89/<- %esp 5/r32/ebp - 4282 5d/pop-to-ebp - 4283 c3/return - 4284 - 4285 test-is-identifier-square-bracket: - 4286 # character after 'Z' is invalid - 4287 # . prologue - 4288 55/push-ebp - 4289 89/<- %ebp 4/r32/esp - 4290 # (eax..ecx) = "[a" - 4291 b8/copy-to-eax "[a"/imm32 - 4292 8b/-> *eax 1/r32/ecx - 4293 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4294 05/add-to-eax 4/imm32 - 4295 # var slice/ecx: slice = {eax, ecx} - 4296 51/push-ecx - 4297 50/push-eax - 4298 89/<- %ecx 4/r32/esp - 4299 # - 4300 (is-identifier? %ecx) - 4301 (check-ints-equal %eax 0 "F - test-is-identifier-@") - 4302 # . epilogue - 4303 89/<- %esp 5/r32/ebp - 4304 5d/pop-to-ebp - 4305 c3/return - 4306 - 4307 test-is-identifier-backtick: - 4308 # character before 'a' is invalid - 4309 # . prologue - 4310 55/push-ebp - 4311 89/<- %ebp 4/r32/esp - 4312 # (eax..ecx) = "`a" - 4313 b8/copy-to-eax "`a"/imm32 - 4314 8b/-> *eax 1/r32/ecx - 4315 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4316 05/add-to-eax 4/imm32 - 4317 # var slice/ecx: slice = {eax, ecx} - 4318 51/push-ecx - 4319 50/push-eax - 4320 89/<- %ecx 4/r32/esp - 4321 # - 4322 (is-identifier? %ecx) - 4323 (check-ints-equal %eax 0 "F - test-is-identifier-backtick") - 4324 # . epilogue - 4325 89/<- %esp 5/r32/ebp - 4326 5d/pop-to-ebp - 4327 c3/return - 4328 - 4329 test-is-identifier-curly-brace-open: - 4330 # character after 'z' is invalid; also used for blocks - 4331 # . prologue - 4332 55/push-ebp - 4333 89/<- %ebp 4/r32/esp - 4334 # (eax..ecx) = "{a" - 4335 b8/copy-to-eax "{a"/imm32 - 4336 8b/-> *eax 1/r32/ecx - 4337 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4338 05/add-to-eax 4/imm32 - 4339 # var slice/ecx: slice = {eax, ecx} - 4340 51/push-ecx - 4341 50/push-eax - 4342 89/<- %ecx 4/r32/esp - 4343 # - 4344 (is-identifier? %ecx) - 4345 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open") - 4346 # . epilogue - 4347 89/<- %esp 5/r32/ebp - 4348 5d/pop-to-ebp - 4349 c3/return - 4350 - 4351 test-is-identifier-curly-brace-close: - 4352 # . prologue - 4353 55/push-ebp - 4354 89/<- %ebp 4/r32/esp - 4355 # (eax..ecx) = "}a" - 4356 b8/copy-to-eax "}a"/imm32 - 4357 8b/-> *eax 1/r32/ecx - 4358 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4359 05/add-to-eax 4/imm32 - 4360 # var slice/ecx: slice = {eax, ecx} - 4361 51/push-ecx - 4362 50/push-eax - 4363 89/<- %ecx 4/r32/esp - 4364 # - 4365 (is-identifier? %ecx) - 4366 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close") - 4367 # . epilogue - 4368 89/<- %esp 5/r32/ebp - 4369 5d/pop-to-ebp - 4370 c3/return - 4371 - 4372 test-is-identifier-hyphen: - 4373 # disallow leading '-' since '->' has special meaning - 4374 # . prologue - 4375 55/push-ebp - 4376 89/<- %ebp 4/r32/esp - 4377 # (eax..ecx) = "-a" - 4378 b8/copy-to-eax "-a"/imm32 - 4379 8b/-> *eax 1/r32/ecx - 4380 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4381 05/add-to-eax 4/imm32 - 4382 # var slice/ecx: slice = {eax, ecx} - 4383 51/push-ecx - 4384 50/push-eax - 4385 89/<- %ecx 4/r32/esp - 4386 # - 4387 (is-identifier? %ecx) - 4388 (check-ints-equal %eax 0 "F - test-is-identifier-hyphen") - 4389 # . epilogue - 4390 89/<- %esp 5/r32/ebp - 4391 5d/pop-to-ebp - 4392 c3/return - 4393 - 4394 populate-mu-function-body: # in: (addr buffered-file), out: (handle function), vars: (addr stack (handle var)) - 4395 # . prologue - 4396 55/push-ebp - 4397 89/<- %ebp 4/r32/esp - 4398 # . save registers - 4399 50/push-eax - 4400 56/push-esi - 4401 57/push-edi - 4402 # esi = in - 4403 8b/-> *(ebp+8) 6/r32/esi - 4404 # edi = out - 4405 8b/-> *(ebp+0xc) 7/r32/edi - 4406 # var eax: (handle block) = parse-mu-block(in, vars, fn) - 4407 (parse-mu-block %esi *(ebp+0x10) %edi) # => eax - 4408 # out->body = eax - 4409 89/<- *(edi+0x10) 0/r32/eax # Function-body - 4410 $populate-mu-function-body:end: - 4411 # . restore registers - 4412 5f/pop-to-edi - 4413 5e/pop-to-esi - 4414 58/pop-to-eax - 4415 # . epilogue - 4416 89/<- %esp 5/r32/ebp - 4417 5d/pop-to-ebp - 4418 c3/return - 4419 - 4420 # parses a block, assuming that the leading '{' has already been read by the caller - 4421 parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle block) - 4422 # pseudocode: - 4423 # var line: (stream byte 512) - 4424 # var word-slice: slice - 4425 # result/eax = allocate(Heap, Stmt-size) - 4426 # result->tag = 0/block - 4427 # result->name = some unique name - 4428 # while true # line loop - 4429 # clear-stream(line) - 4430 # read-line-buffered(in, line) - 4431 # if (line->write == 0) break # end of file - 4432 # word-slice = next-mu-token(line) - 4433 # if slice-empty?(word-slice) # end of line - 4434 # continue - 4435 # else if slice-starts-with?(word-slice, "#") - 4436 # continue - 4437 # else if slice-equal?(word-slice, "{") - 4438 # assert(no-tokens-in(line)) - 4439 # block = parse-mu-block(in, vars, fn) - 4440 # append-to-block(result, block) - 4441 # else if slice-equal?(word-slice, "}") - 4442 # break - 4443 # else if slice-ends-with?(word-slice, ":") - 4444 # # TODO: error-check the rest of 'line' - 4445 # --word-slice->end to skip ':' - 4446 # named-block = parse-mu-named-block(word-slice, in, vars, fn) - 4447 # append-to-block(result, named-block) - 4448 # else if slice-equal?(word-slice, "var") - 4449 # var-def = parse-mu-var-def(line, vars) - 4450 # append-to-block(result, var-def) - 4451 # else - 4452 # stmt = parse-mu-stmt(line, vars, fn) - 4453 # append-to-block(result, stmt) - 4454 # return result - 4455 # - 4456 # . prologue - 4457 55/push-ebp - 4458 89/<- %ebp 4/r32/esp - 4459 # . save registers - 4460 51/push-ecx - 4461 52/push-edx - 4462 53/push-ebx - 4463 57/push-edi - 4464 # var line/ecx: (stream byte 512) - 4465 81 5/subop/subtract %esp 0x200/imm32 - 4466 68/push 0x200/imm32/length - 4467 68/push 0/imm32/read - 4468 68/push 0/imm32/write - 4469 89/<- %ecx 4/r32/esp - 4470 # var word-slice/edx: slice - 4471 68/push 0/imm32/end - 4472 68/push 0/imm32/start - 4473 89/<- %edx 4/r32/esp - 4474 # edi = result - 4475 (allocate Heap *Stmt-size) # => eax - 4476 (zero-out %eax *Stmt-size) - 4477 89/<- %edi 0/r32/eax - 4478 # set result->tag - 4479 c7 0/subop/copy *edi 0/imm32/block # Stmt-tag - 4480 # set result->var - 4481 (new-block-name *(ebp+0x10)) # => eax - 4482 89/<- *(edi+8) 0/r32/eax # Block-var - 4483 # push result->var to vars - 4484 (push *(ebp+0xc) %eax) - 4485 { - 4486 $parse-mu-block:line-loop: - 4487 # line = read-line-buffered(in) - 4488 (clear-stream %ecx) - 4489 (read-line-buffered *(ebp+8) %ecx) - 4490 #? (write-buffered Stderr "line: ") - 4491 #? (write-stream-data Stderr %ecx) - 4492 #? (write-buffered Stderr Newline) - 4493 #? (flush Stderr) - 4494 # if (line->write == 0) break - 4495 81 7/subop/compare *ecx 0/imm32 - 4496 0f 84/jump-if-= break/disp32 - 4497 # word-slice = next-mu-token(line) - 4498 (next-mu-token %ecx %edx) - 4499 #? (write-buffered Stderr "word: ") - 4500 #? (write-slice-buffered Stderr %edx) - 4501 #? (write-buffered Stderr Newline) - 4502 #? (flush Stderr) - 4503 # if slice-empty?(word-slice) continue - 4504 (slice-empty? %edx) - 4505 3d/compare-eax-and 0/imm32/false - 4506 0f 85/jump-if-!= loop/disp32 - 4507 # if (slice-starts-with?(word-slice, '#') continue - 4508 # . eax = *word-slice->start - 4509 8b/-> *edx 0/r32/eax - 4510 8a/copy-byte *eax 0/r32/AL - 4511 81 4/subop/and %eax 0xff/imm32 - 4512 # . if (eax == '#') continue - 4513 3d/compare-eax-and 0x23/imm32/hash - 4514 0f 84/jump-if-= loop/disp32 - 4515 # if slice-equal?(word-slice, "{") - 4516 { - 4517 $parse-mu-block:check-for-block: - 4518 (slice-equal? %edx "{") - 4519 3d/compare-eax-and 0/imm32/false - 4520 74/jump-if-= break/disp8 - 4521 (check-no-tokens-left %ecx) - 4522 # parse new block and append - 4523 (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax - 4524 (append-to-block Heap %edi %eax) - 4525 e9/jump $parse-mu-block:line-loop/disp32 - 4526 } - 4527 # if slice-equal?(word-slice, "}") break - 4528 $parse-mu-block:check-for-end: - 4529 (slice-equal? %edx "}") - 4530 3d/compare-eax-and 0/imm32/false - 4531 0f 85/jump-if-!= break/disp32 - 4532 # if slice-ends-with?(word-slice, ":") parse named block and append - 4533 { - 4534 $parse-mu-block:check-for-named-block: - 4535 # . eax = *(word-slice->end-1) - 4536 8b/-> *(edx+4) 0/r32/eax - 4537 48/decrement-eax - 4538 8a/copy-byte *eax 0/r32/AL - 4539 81 4/subop/and %eax 0xff/imm32 - 4540 # . if (eax != ':') break - 4541 3d/compare-eax-and 0x3a/imm32/colon - 4542 0f 85/jump-if-!= break/disp32 - 4543 # TODO: error-check the rest of 'line' - 4544 # - 4545 # skip ':' - 4546 ff 1/subop/decrement *(edx+4) # Slice-end - 4547 # - 4548 (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax - 4549 (append-to-block Heap %edi %eax) - 4550 e9/jump $parse-mu-block:line-loop/disp32 - 4551 } - 4552 # if slice-equal?(word-slice, "var") - 4553 { - 4554 $parse-mu-block:check-for-var: - 4555 (slice-equal? %edx "var") - 4556 3d/compare-eax-and 0/imm32/false - 4557 74/jump-if-= break/disp8 - 4558 # - 4559 (parse-mu-var-def %ecx *(ebp+0xc)) # => eax - 4560 (append-to-block Heap %edi %eax) - 4561 e9/jump $parse-mu-block:line-loop/disp32 - 4562 } - 4563 $parse-mu-block:regular-stmt: - 4564 # otherwise - 4565 (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10)) # => eax - 4566 (append-to-block Heap %edi %eax) - 4567 e9/jump loop/disp32 - 4568 } # end line loop + 3806 # EGREGIOUS HACK for static array sizes: if s is a number, parse it + 3807 { + 3808 $parse-type:int: + 3809 (is-hex-int? %ecx) # => eax + 3810 3d/compare-eax-and 0/imm32/false + 3811 74/jump-if-= break/disp8 + 3812 (parse-hex-int-from-slice %ecx) # => eax + 3813 89/<- *(edx+4) 0/r32/eax # Tree-left + 3814 e9/jump $parse-type:return-edx/disp32 + 3815 } + 3816 $parse-type:atom: + 3817 # result->left-is-atom? = true + 3818 c7 0/subop/copy *edx 1/imm32/true # Tree-is-atom + 3819 # result->value = pos-or-insert-slice(Type-id, s) + 3820 (pos-or-insert-slice Type-id %ecx) # => eax + 3821 #? (write-buffered Stderr "=> {") + 3822 #? (print-int32-buffered Stderr %eax) + 3823 #? (write-buffered Stderr ", 0}\n") + 3824 #? (flush Stderr) + 3825 89/<- *(edx+4) 0/r32/eax # Tree-value + 3826 e9/jump $parse-type:return-edx/disp32 + 3827 } + 3828 $parse-type:non-atom: + 3829 # otherwise s == "(" + 3830 # result->left = parse-type(ad, in) + 3831 (parse-type *(ebp+8) *(ebp+0xc)) + 3832 #? (write-buffered Stderr "=> {") + 3833 #? (print-int32-buffered Stderr %eax) + 3834 89/<- *(edx+4) 0/r32/eax # Tree-left + 3835 # result->right = parse-type-tree(ad, in) + 3836 (parse-type-tree *(ebp+8) *(ebp+0xc)) + 3837 #? (write-buffered Stderr Space) + 3838 #? (print-int32-buffered Stderr %eax) + 3839 #? (write-buffered Stderr "}\n") + 3840 #? (flush Stderr) + 3841 89/<- *(edx+8) 0/r32/eax # Tree-right + 3842 $parse-type:return-edx: + 3843 89/<- %eax 2/r32/edx + 3844 $parse-type:end: + 3845 # . reclaim locals + 3846 81 0/subop/add %esp 8/imm32 + 3847 # . restore registers + 3848 5a/pop-to-edx + 3849 59/pop-to-ecx + 3850 # . epilogue + 3851 89/<- %esp 5/r32/ebp + 3852 5d/pop-to-ebp + 3853 c3/return + 3854 + 3855 $parse-type:abort: + 3856 # error("unexpected token when parsing type: '" s "'\n") + 3857 (write-buffered Stderr "unexpected token when parsing type: '") + 3858 (write-slice-buffered Stderr %ecx) + 3859 (write-buffered Stderr "'\n") + 3860 (flush Stderr) + 3861 # . syscall(exit, 1) + 3862 bb/copy-to-ebx 1/imm32 + 3863 b8/copy-to-eax 1/imm32/exit + 3864 cd/syscall 0x80/imm8 + 3865 # never gets here + 3866 + 3867 parse-type-tree: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) + 3868 # pseudocode: + 3869 # var tmp: (handle tree type-id) = parse-type(ad, in) + 3870 # if tmp == 0 + 3871 # return 0 + 3872 # result = allocate(Tree) + 3873 # zero-out(result, *Tree-size) + 3874 # result->left = tmp + 3875 # result->right = parse-type-tree(ad, in) + 3876 # + 3877 # . prologue + 3878 55/push-ebp + 3879 89/<- %ebp 4/r32/esp + 3880 # . save registers + 3881 51/push-ecx + 3882 52/push-edx + 3883 # var tmp/eax: (handle tree type-id) = parse-type(ad, in) + 3884 (parse-type *(ebp+8) *(ebp+0xc)) + 3885 # if (tmp == 0) return tmp + 3886 3d/compare-eax-and 0/imm32 + 3887 74/jump-if-= $parse-type-tree:end/disp8 + 3888 # var tmp2/ecx = tmp + 3889 89/<- %ecx 0/r32/eax + 3890 # var result/edx: (handle tree type-id) + 3891 (allocate *(ebp+8) *Tree-size) # => eax + 3892 89/<- %edx 0/r32/eax + 3893 # result->left = tmp2 + 3894 89/<- *(edx+4) 1/r32/ecx # Tree-left + 3895 # result->right = parse-type-tree(ad, in) + 3896 (parse-type-tree *(ebp+8) *(ebp+0xc)) + 3897 89/<- *(edx+8) 0/r32/eax # Tree-right + 3898 $parse-type-tree:return-edx: + 3899 89/<- %eax 2/r32/edx + 3900 $parse-type-tree:end: + 3901 # . restore registers + 3902 5a/pop-to-edx + 3903 59/pop-to-ecx + 3904 # . epilogue + 3905 89/<- %esp 5/r32/ebp + 3906 5d/pop-to-ebp + 3907 c3/return + 3908 + 3909 next-mu-token: # in: (addr stream byte), out: (addr slice) + 3910 # pseudocode: + 3911 # start: + 3912 # skip-chars-matching-whitespace(in) + 3913 # if in->read >= in->write # end of in + 3914 # out = {0, 0} + 3915 # return + 3916 # out->start = &in->data[in->read] + 3917 # var curr-byte/eax: byte = in->data[in->read] + 3918 # if curr->byte == ',' # comment token + 3919 # ++in->read + 3920 # goto start + 3921 # if curr-byte == '#' # comment + 3922 # goto done # treat as eof + 3923 # if curr-byte == '"' # string literal + 3924 # skip-string(in) + 3925 # goto done # no metadata + 3926 # if curr-byte == '(' + 3927 # ++in->read + 3928 # goto done + 3929 # if curr-byte == ')' + 3930 # ++in->read + 3931 # goto done + 3932 # # read a word + 3933 # while true + 3934 # if in->read >= in->write + 3935 # break + 3936 # curr-byte = in->data[in->read] + 3937 # if curr-byte == ' ' + 3938 # break + 3939 # if curr-byte == '\r' + 3940 # break + 3941 # if curr-byte == '\n' + 3942 # break + 3943 # if curr-byte == '(' + 3944 # break + 3945 # if curr-byte == ')' + 3946 # break + 3947 # if curr-byte == ',' + 3948 # break + 3949 # ++in->read + 3950 # done: + 3951 # out->end = &in->data[in->read] + 3952 # + 3953 # . prologue + 3954 55/push-ebp + 3955 89/<- %ebp 4/r32/esp + 3956 # . save registers + 3957 50/push-eax + 3958 51/push-ecx + 3959 56/push-esi + 3960 57/push-edi + 3961 # esi = in + 3962 8b/-> *(ebp+8) 6/r32/esi + 3963 # edi = out + 3964 8b/-> *(ebp+0xc) 7/r32/edi + 3965 $next-mu-token:start: + 3966 (skip-chars-matching-whitespace %esi) + 3967 $next-mu-token:check0: + 3968 # if (in->read >= in->write) return out = {0, 0} + 3969 # . ecx = in->read + 3970 8b/-> *(esi+4) 1/r32/ecx + 3971 # . if (ecx >= in->write) return out = {0, 0} + 3972 3b/compare<- *esi 1/r32/ecx + 3973 c7 0/subop/copy *edi 0/imm32 + 3974 c7 0/subop/copy *(edi+4) 0/imm32 + 3975 0f 8d/jump-if->= $next-mu-token:end/disp32 + 3976 # out->start = &in->data[in->read] + 3977 8d/copy-address *(esi+ecx+0xc) 0/r32/eax + 3978 89/<- *edi 0/r32/eax + 3979 # var curr-byte/eax: byte = in->data[in->read] + 3980 31/xor-with %eax 0/r32/eax + 3981 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL + 3982 { + 3983 $next-mu-token:check-for-comma: + 3984 # if (curr-byte != ',') break + 3985 3d/compare-eax-and 0x2c/imm32/comma + 3986 75/jump-if-!= break/disp8 + 3987 # ++in->read + 3988 ff 0/subop/increment *(esi+4) + 3989 # restart + 3990 e9/jump $next-mu-token:start/disp32 + 3991 } + 3992 { + 3993 $next-mu-token:check-for-comment: + 3994 # if (curr-byte != '#') break + 3995 3d/compare-eax-and 0x23/imm32/pound + 3996 75/jump-if-!= break/disp8 + 3997 # return eof + 3998 e9/jump $next-mu-token:done/disp32 + 3999 } + 4000 { + 4001 $next-mu-token:check-for-string-literal: + 4002 # if (curr-byte != '"') break + 4003 3d/compare-eax-and 0x22/imm32/dquote + 4004 75/jump-if-!= break/disp8 + 4005 (skip-string %esi) + 4006 # return + 4007 e9/jump $next-mu-token:done/disp32 + 4008 } + 4009 { + 4010 $next-mu-token:check-for-open-paren: + 4011 # if (curr-byte != '(') break + 4012 3d/compare-eax-and 0x28/imm32/open-paren + 4013 75/jump-if-!= break/disp8 + 4014 # ++in->read + 4015 ff 0/subop/increment *(esi+4) + 4016 # return + 4017 e9/jump $next-mu-token:done/disp32 + 4018 } + 4019 { + 4020 $next-mu-token:check-for-close-paren: + 4021 # if (curr-byte != ')') break + 4022 3d/compare-eax-and 0x29/imm32/close-paren + 4023 75/jump-if-!= break/disp8 + 4024 # ++in->read + 4025 ff 0/subop/increment *(esi+4) + 4026 # return + 4027 e9/jump $next-mu-token:done/disp32 + 4028 } + 4029 { + 4030 $next-mu-token:regular-word-without-metadata: + 4031 # if (in->read >= in->write) break + 4032 # . ecx = in->read + 4033 8b/-> *(esi+4) 1/r32/ecx + 4034 # . if (ecx >= in->write) break + 4035 3b/compare<- *esi 1/r32/ecx + 4036 7d/jump-if->= break/disp8 + 4037 # var c/eax: byte = in->data[in->read] + 4038 31/xor-with %eax 0/r32/eax + 4039 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL + 4040 # if (c == ' ') break + 4041 3d/compare-eax-and 0x20/imm32/space + 4042 74/jump-if-= break/disp8 + 4043 # if (c == '\r') break + 4044 3d/compare-eax-and 0xd/imm32/carriage-return + 4045 74/jump-if-= break/disp8 + 4046 # if (c == '\n') break + 4047 3d/compare-eax-and 0xa/imm32/newline + 4048 74/jump-if-= break/disp8 + 4049 # if (c == '(') break + 4050 3d/compare-eax-and 0x28/imm32/open-paren + 4051 0f 84/jump-if-= break/disp32 + 4052 # if (c == ')') break + 4053 3d/compare-eax-and 0x29/imm32/close-paren + 4054 0f 84/jump-if-= break/disp32 + 4055 # if (c == ',') break + 4056 3d/compare-eax-and 0x2c/imm32/comma + 4057 0f 84/jump-if-= break/disp32 + 4058 # ++in->read + 4059 ff 0/subop/increment *(esi+4) + 4060 # + 4061 e9/jump loop/disp32 + 4062 } + 4063 $next-mu-token:done: + 4064 # out->end = &in->data[in->read] + 4065 8b/-> *(esi+4) 1/r32/ecx + 4066 8d/copy-address *(esi+ecx+0xc) 0/r32/eax + 4067 89/<- *(edi+4) 0/r32/eax + 4068 $next-mu-token:end: + 4069 # . restore registers + 4070 5f/pop-to-edi + 4071 5e/pop-to-esi + 4072 59/pop-to-ecx + 4073 58/pop-to-eax + 4074 # . epilogue + 4075 89/<- %esp 5/r32/ebp + 4076 5d/pop-to-ebp + 4077 c3/return + 4078 + 4079 pos-or-insert-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int + 4080 # . prologue + 4081 55/push-ebp + 4082 89/<- %ebp 4/r32/esp + 4083 # if (pos-slice(arr, s) != -1) return it + 4084 (pos-slice *(ebp+8) *(ebp+0xc)) # => eax + 4085 3d/compare-eax-and -1/imm32 + 4086 75/jump-if-!= $pos-or-insert-slice:end/disp8 + 4087 $pos-or-insert-slice:insert: + 4088 (slice-to-string Heap *(ebp+0xc)) # => eax + 4089 (write-int *(ebp+8) %eax) + 4090 (pos-slice *(ebp+8) *(ebp+0xc)) # => eax + 4091 $pos-or-insert-slice:end: + 4092 # . epilogue + 4093 89/<- %esp 5/r32/ebp + 4094 5d/pop-to-ebp + 4095 c3/return + 4096 + 4097 # return the index in an array of strings matching 's', -1 if not found + 4098 # index is denominated in elements, not bytes + 4099 pos-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int + 4100 # . prologue + 4101 55/push-ebp + 4102 89/<- %ebp 4/r32/esp + 4103 # . save registers + 4104 51/push-ecx + 4105 52/push-edx + 4106 53/push-ebx + 4107 56/push-esi + 4108 #? (write-buffered Stderr "pos-slice: ") + 4109 #? (write-slice-buffered Stderr *(ebp+0xc)) + 4110 #? (write-buffered Stderr "\n") + 4111 #? (flush Stderr) + 4112 # esi = arr + 4113 8b/-> *(ebp+8) 6/r32/esi + 4114 # var index/ecx: int = 0 + 4115 b9/copy-to-ecx 0/imm32 + 4116 # var curr/edx: (addr (addr array byte)) = arr->data + 4117 8d/copy-address *(esi+0xc) 2/r32/edx + 4118 # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write] + 4119 8b/-> *esi 3/r32/ebx + 4120 8d/copy-address *(esi+ebx+0xc) 3/r32/ebx + 4121 { + 4122 #? (write-buffered Stderr " ") + 4123 #? (print-int32-buffered Stderr %ecx) + 4124 #? (write-buffered Stderr "\n") + 4125 #? (flush Stderr) + 4126 # if (curr >= max) return -1 + 4127 39/compare %edx 3/r32/ebx + 4128 b8/copy-to-eax -1/imm32 + 4129 73/jump-if-addr>= $pos-slice:end/disp8 + 4130 # if (slice-equal?(s, *curr)) break + 4131 (slice-equal? *(ebp+0xc) *edx) # => eax + 4132 3d/compare-eax-and 0/imm32/false + 4133 75/jump-if-!= break/disp8 + 4134 # ++index + 4135 41/increment-ecx + 4136 # curr += 4 + 4137 81 0/subop/add %edx 4/imm32 + 4138 # + 4139 eb/jump loop/disp8 + 4140 } + 4141 # return index + 4142 89/<- %eax 1/r32/ecx + 4143 $pos-slice:end: + 4144 #? (write-buffered Stderr "=> ") + 4145 #? (print-int32-buffered Stderr %eax) + 4146 #? (write-buffered Stderr "\n") + 4147 # . restore registers + 4148 5e/pop-to-esi + 4149 5b/pop-to-ebx + 4150 5a/pop-to-edx + 4151 59/pop-to-ecx + 4152 # . epilogue + 4153 89/<- %esp 5/r32/ebp + 4154 5d/pop-to-ebp + 4155 c3/return + 4156 + 4157 test-parse-var-with-type: + 4158 # . prologue + 4159 55/push-ebp + 4160 89/<- %ebp 4/r32/esp + 4161 # (eax..ecx) = "x:" + 4162 b8/copy-to-eax "x:"/imm32 + 4163 8b/-> *eax 1/r32/ecx + 4164 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4165 05/add-to-eax 4/imm32 + 4166 # var slice/ecx: slice = {eax, ecx} + 4167 51/push-ecx + 4168 50/push-eax + 4169 89/<- %ecx 4/r32/esp + 4170 # _test-input-stream contains "int" + 4171 (clear-stream _test-input-stream) + 4172 (write _test-input-stream "int") + 4173 # + 4174 (parse-var-with-type %ecx _test-input-stream) + 4175 8b/-> *eax 2/r32/edx # Var-name + 4176 (check-strings-equal %edx "x" "F - test-parse-var-with-type/name") + 4177 8b/-> *(eax+4) 2/r32/edx # Var-type + 4178 (check-ints-equal *edx 1 "F - test-parse-var-with-type/type:0") # Tree-is-atom + 4179 (check-ints-equal *(edx+4) 1 "F - test-parse-var-with-type/type:1") # Tree-value + 4180 (check-ints-equal *(edx+8) 0 "F - test-parse-var-with-type/type:2") # Tree-right + 4181 # . epilogue + 4182 89/<- %esp 5/r32/ebp + 4183 5d/pop-to-ebp + 4184 c3/return + 4185 + 4186 test-parse-var-with-type-and-register: + 4187 # . prologue + 4188 55/push-ebp + 4189 89/<- %ebp 4/r32/esp + 4190 # (eax..ecx) = "x/eax:" + 4191 b8/copy-to-eax "x/eax:"/imm32 + 4192 8b/-> *eax 1/r32/ecx + 4193 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4194 05/add-to-eax 4/imm32 + 4195 # var slice/ecx: slice = {eax, ecx} + 4196 51/push-ecx + 4197 50/push-eax + 4198 89/<- %ecx 4/r32/esp + 4199 # _test-input-stream contains "int" + 4200 (clear-stream _test-input-stream) + 4201 (write _test-input-stream "int") + 4202 # + 4203 (parse-var-with-type %ecx _test-input-stream) + 4204 8b/-> *eax 2/r32/edx # Var-name + 4205 (check-strings-equal %edx "x" "F - test-parse-var-with-type-and-register/name") + 4206 8b/-> *(eax+0x10) 2/r32/edx # Var-register + 4207 (check-strings-equal %edx "eax" "F - test-parse-var-with-type-and-register/register") + 4208 8b/-> *(eax+4) 2/r32/edx # Var-type + 4209 (check-ints-equal *edx 1 "F - test-parse-var-with-type-and-register/type:0") # Tree-is-atom + 4210 (check-ints-equal *(edx+4) 1 "F - test-parse-var-with-type-and-register/type:1") # Tree-left + 4211 (check-ints-equal *(edx+8) 0 "F - test-parse-var-with-type-and-register/type:2") # Tree-right + 4212 # . epilogue + 4213 89/<- %esp 5/r32/ebp + 4214 5d/pop-to-ebp + 4215 c3/return + 4216 + 4217 test-parse-var-with-trailing-characters: + 4218 # . prologue + 4219 55/push-ebp + 4220 89/<- %ebp 4/r32/esp + 4221 # (eax..ecx) = "x:" + 4222 b8/copy-to-eax "x:"/imm32 + 4223 8b/-> *eax 1/r32/ecx + 4224 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4225 05/add-to-eax 4/imm32 + 4226 # var slice/ecx: slice = {eax, ecx} + 4227 51/push-ecx + 4228 50/push-eax + 4229 89/<- %ecx 4/r32/esp + 4230 # _test-input-stream contains "int," + 4231 (clear-stream _test-input-stream) + 4232 (write _test-input-stream "int,") + 4233 # + 4234 (parse-var-with-type %ecx _test-input-stream) + 4235 8b/-> *eax 2/r32/edx # Var-name + 4236 (check-strings-equal %edx "x" "F - test-parse-var-with-trailing-characters/name") + 4237 8b/-> *(eax+0x10) 2/r32/edx # Var-register + 4238 (check-ints-equal %edx 0 "F - test-parse-var-with-trailing-characters/register") + 4239 8b/-> *(eax+4) 2/r32/edx # Var-type + 4240 (check-ints-equal *edx 1 "F - test-parse-var-with-trailing-characters/type:0") # Tree-is-atom + 4241 (check-ints-equal *(edx+4) 1 "F - test-parse-var-with-trailing-characters/type:1") # Tree-left + 4242 (check-ints-equal *(edx+8) 0 "F - test-parse-var-with-trailing-characters/type:1") # Tree-right + 4243 # . epilogue + 4244 89/<- %esp 5/r32/ebp + 4245 5d/pop-to-ebp + 4246 c3/return + 4247 + 4248 test-parse-var-with-register-and-trailing-characters: + 4249 # . prologue + 4250 55/push-ebp + 4251 89/<- %ebp 4/r32/esp + 4252 # (eax..ecx) = "x/eax:" + 4253 b8/copy-to-eax "x/eax:"/imm32 + 4254 8b/-> *eax 1/r32/ecx + 4255 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4256 05/add-to-eax 4/imm32 + 4257 # var slice/ecx: slice = {eax, ecx} + 4258 51/push-ecx + 4259 50/push-eax + 4260 89/<- %ecx 4/r32/esp + 4261 # _test-input-stream contains "int," + 4262 (clear-stream _test-input-stream) + 4263 (write _test-input-stream "int,") + 4264 # + 4265 (parse-var-with-type %ecx _test-input-stream) + 4266 8b/-> *eax 2/r32/edx # Var-name + 4267 (check-strings-equal %edx "x" "F - test-parse-var-with-register-and-trailing-characters/name") + 4268 8b/-> *(eax+0x10) 2/r32/edx # Var-register + 4269 (check-strings-equal %edx "eax" "F - test-parse-var-with-register-and-trailing-characters/register") + 4270 8b/-> *(eax+4) 2/r32/edx # Var-type + 4271 (check-ints-equal *edx 1 "F - test-parse-var-with-register-and-trailing-characters/type:0") # Tree-is-atom + 4272 (check-ints-equal *(edx+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1") # Tree-left + 4273 (check-ints-equal *(edx+8) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2") # Tree-right + 4274 # . epilogue + 4275 89/<- %esp 5/r32/ebp + 4276 5d/pop-to-ebp + 4277 c3/return + 4278 + 4279 test-parse-var-with-compound-type: + 4280 # . prologue + 4281 55/push-ebp + 4282 89/<- %ebp 4/r32/esp + 4283 # (eax..ecx) = "x:" + 4284 b8/copy-to-eax "x:"/imm32 + 4285 8b/-> *eax 1/r32/ecx + 4286 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4287 05/add-to-eax 4/imm32 + 4288 # var slice/ecx: slice = {eax, ecx} + 4289 51/push-ecx + 4290 50/push-eax + 4291 89/<- %ecx 4/r32/esp + 4292 # _test-input-stream contains "(addr int)" + 4293 (clear-stream _test-input-stream) + 4294 (write _test-input-stream "(addr int)") + 4295 # + 4296 (parse-var-with-type %ecx _test-input-stream) + 4297 8b/-> *eax 2/r32/edx # Var-name + 4298 (check-strings-equal %edx "x" "F - test-parse-var-with-compound-type/name") + 4299 8b/-> *(eax+0x10) 2/r32/edx # Var-register + 4300 (check-ints-equal %edx 0 "F - test-parse-var-with-compound-type/register") + 4301 # var type/edx: (handle tree type-id) = var->type + 4302 8b/-> *(eax+4) 2/r32/edx # Var-type + 4303 # type is a non-atom + 4304 (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0") # Tree-is-atom + 4305 # type->left == atom(addr) + 4306 8b/-> *(edx+4) 0/r32/eax # Tree-left + 4307 (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1") # Tree-is-atom + 4308 (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2") # Tree-value + 4309 # type->right->left == atom(int) + 4310 8b/-> *(edx+8) 2/r32/edx # Tree-right + 4311 8b/-> *(edx+4) 0/r32/eax # Tree-left + 4312 (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3") # Tree-is-atom + 4313 (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4") # Tree-value + 4314 # type->right->right == null + 4315 (check-ints-equal *(edx+8) 0 "F - test-parse-var-with-compound-type/type:5") # Tree-right + 4316 # . epilogue + 4317 89/<- %esp 5/r32/ebp + 4318 5d/pop-to-ebp + 4319 c3/return + 4320 + 4321 # identifier starts with a letter or '$' or '_' + 4322 # no constraints at the moment on later letters + 4323 # all we really want to do so far is exclude '{', '}' and '->' + 4324 is-identifier?: # in: (addr slice) -> result/eax: boolean + 4325 # . prologue + 4326 55/push-ebp + 4327 89/<- %ebp 4/r32/esp + 4328 # if (slice-empty?(in)) return false + 4329 (slice-empty? *(ebp+8)) # => eax + 4330 3d/compare-eax-and 0/imm32/false + 4331 75/jump-if-!= $is-identifier?:false/disp8 + 4332 # var c/eax: byte = *in->start + 4333 8b/-> *(ebp+8) 0/r32/eax + 4334 8b/-> *eax 0/r32/eax + 4335 8a/copy-byte *eax 0/r32/AL + 4336 81 4/subop/and %eax 0xff/imm32 + 4337 # if (c == '$') return true + 4338 3d/compare-eax-and 0x24/imm32/$ + 4339 74/jump-if-= $is-identifier?:true/disp8 + 4340 # if (c == '_') return true + 4341 3d/compare-eax-and 0x5f/imm32/_ + 4342 74/jump-if-= $is-identifier?:true/disp8 + 4343 # drop case + 4344 25/and-eax-with 0x5f/imm32 + 4345 # if (c < 'A') return false + 4346 3d/compare-eax-and 0x41/imm32/A + 4347 7c/jump-if-< $is-identifier?:false/disp8 + 4348 # if (c > 'Z') return false + 4349 3d/compare-eax-and 0x5a/imm32/Z + 4350 7f/jump-if-> $is-identifier?:false/disp8 + 4351 # otherwise return true + 4352 $is-identifier?:true: + 4353 b8/copy-to-eax 1/imm32/true + 4354 eb/jump $is-identifier?:end/disp8 + 4355 $is-identifier?:false: + 4356 b8/copy-to-eax 0/imm32/false + 4357 $is-identifier?:end: + 4358 # . epilogue + 4359 89/<- %esp 5/r32/ebp + 4360 5d/pop-to-ebp + 4361 c3/return + 4362 + 4363 test-is-identifier-dollar: + 4364 # . prologue + 4365 55/push-ebp + 4366 89/<- %ebp 4/r32/esp + 4367 # (eax..ecx) = "$a" + 4368 b8/copy-to-eax "$a"/imm32 + 4369 8b/-> *eax 1/r32/ecx + 4370 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4371 05/add-to-eax 4/imm32 + 4372 # var slice/ecx: slice = {eax, ecx} + 4373 51/push-ecx + 4374 50/push-eax + 4375 89/<- %ecx 4/r32/esp + 4376 # + 4377 (is-identifier? %ecx) + 4378 (check-ints-equal %eax 1 "F - test-is-identifier-dollar") + 4379 # . epilogue + 4380 89/<- %esp 5/r32/ebp + 4381 5d/pop-to-ebp + 4382 c3/return + 4383 + 4384 test-is-identifier-underscore: + 4385 # . prologue + 4386 55/push-ebp + 4387 89/<- %ebp 4/r32/esp + 4388 # (eax..ecx) = "_a" + 4389 b8/copy-to-eax "_a"/imm32 + 4390 8b/-> *eax 1/r32/ecx + 4391 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4392 05/add-to-eax 4/imm32 + 4393 # var slice/ecx: slice = {eax, ecx} + 4394 51/push-ecx + 4395 50/push-eax + 4396 89/<- %ecx 4/r32/esp + 4397 # + 4398 (is-identifier? %ecx) + 4399 (check-ints-equal %eax 1 "F - test-is-identifier-underscore") + 4400 # . epilogue + 4401 89/<- %esp 5/r32/ebp + 4402 5d/pop-to-ebp + 4403 c3/return + 4404 + 4405 test-is-identifier-a: + 4406 # . prologue + 4407 55/push-ebp + 4408 89/<- %ebp 4/r32/esp + 4409 # (eax..ecx) = "a$" + 4410 b8/copy-to-eax "a$"/imm32 + 4411 8b/-> *eax 1/r32/ecx + 4412 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4413 05/add-to-eax 4/imm32 + 4414 # var slice/ecx: slice = {eax, ecx} + 4415 51/push-ecx + 4416 50/push-eax + 4417 89/<- %ecx 4/r32/esp + 4418 # + 4419 (is-identifier? %ecx) + 4420 (check-ints-equal %eax 1 "F - test-is-identifier-a") + 4421 # . epilogue + 4422 89/<- %esp 5/r32/ebp + 4423 5d/pop-to-ebp + 4424 c3/return + 4425 + 4426 test-is-identifier-z: + 4427 # . prologue + 4428 55/push-ebp + 4429 89/<- %ebp 4/r32/esp + 4430 # (eax..ecx) = "z$" + 4431 b8/copy-to-eax "z$"/imm32 + 4432 8b/-> *eax 1/r32/ecx + 4433 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4434 05/add-to-eax 4/imm32 + 4435 # var slice/ecx: slice = {eax, ecx} + 4436 51/push-ecx + 4437 50/push-eax + 4438 89/<- %ecx 4/r32/esp + 4439 # + 4440 (is-identifier? %ecx) + 4441 (check-ints-equal %eax 1 "F - test-is-identifier-z") + 4442 # . epilogue + 4443 89/<- %esp 5/r32/ebp + 4444 5d/pop-to-ebp + 4445 c3/return + 4446 + 4447 test-is-identifier-A: + 4448 # . prologue + 4449 55/push-ebp + 4450 89/<- %ebp 4/r32/esp + 4451 # (eax..ecx) = "A$" + 4452 b8/copy-to-eax "A$"/imm32 + 4453 8b/-> *eax 1/r32/ecx + 4454 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4455 05/add-to-eax 4/imm32 + 4456 # var slice/ecx: slice = {eax, ecx} + 4457 51/push-ecx + 4458 50/push-eax + 4459 89/<- %ecx 4/r32/esp + 4460 # + 4461 (is-identifier? %ecx) + 4462 (check-ints-equal %eax 1 "F - test-is-identifier-A") + 4463 # . epilogue + 4464 89/<- %esp 5/r32/ebp + 4465 5d/pop-to-ebp + 4466 c3/return + 4467 + 4468 test-is-identifier-Z: + 4469 # . prologue + 4470 55/push-ebp + 4471 89/<- %ebp 4/r32/esp + 4472 # (eax..ecx) = "Z$" + 4473 b8/copy-to-eax "Z$"/imm32 + 4474 8b/-> *eax 1/r32/ecx + 4475 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4476 05/add-to-eax 4/imm32 + 4477 # var slice/ecx: slice = {eax, ecx} + 4478 51/push-ecx + 4479 50/push-eax + 4480 89/<- %ecx 4/r32/esp + 4481 # + 4482 (is-identifier? %ecx) + 4483 (check-ints-equal %eax 1 "F - test-is-identifier-Z") + 4484 # . epilogue + 4485 89/<- %esp 5/r32/ebp + 4486 5d/pop-to-ebp + 4487 c3/return + 4488 + 4489 test-is-identifier-@: + 4490 # character before 'A' is invalid + 4491 # . prologue + 4492 55/push-ebp + 4493 89/<- %ebp 4/r32/esp + 4494 # (eax..ecx) = "@a" + 4495 b8/copy-to-eax "@a"/imm32 + 4496 8b/-> *eax 1/r32/ecx + 4497 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4498 05/add-to-eax 4/imm32 + 4499 # var slice/ecx: slice = {eax, ecx} + 4500 51/push-ecx + 4501 50/push-eax + 4502 89/<- %ecx 4/r32/esp + 4503 # + 4504 (is-identifier? %ecx) + 4505 (check-ints-equal %eax 0 "F - test-is-identifier-@") + 4506 # . epilogue + 4507 89/<- %esp 5/r32/ebp + 4508 5d/pop-to-ebp + 4509 c3/return + 4510 + 4511 test-is-identifier-square-bracket: + 4512 # character after 'Z' is invalid + 4513 # . prologue + 4514 55/push-ebp + 4515 89/<- %ebp 4/r32/esp + 4516 # (eax..ecx) = "[a" + 4517 b8/copy-to-eax "[a"/imm32 + 4518 8b/-> *eax 1/r32/ecx + 4519 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4520 05/add-to-eax 4/imm32 + 4521 # var slice/ecx: slice = {eax, ecx} + 4522 51/push-ecx + 4523 50/push-eax + 4524 89/<- %ecx 4/r32/esp + 4525 # + 4526 (is-identifier? %ecx) + 4527 (check-ints-equal %eax 0 "F - test-is-identifier-@") + 4528 # . epilogue + 4529 89/<- %esp 5/r32/ebp + 4530 5d/pop-to-ebp + 4531 c3/return + 4532 + 4533 test-is-identifier-backtick: + 4534 # character before 'a' is invalid + 4535 # . prologue + 4536 55/push-ebp + 4537 89/<- %ebp 4/r32/esp + 4538 # (eax..ecx) = "`a" + 4539 b8/copy-to-eax "`a"/imm32 + 4540 8b/-> *eax 1/r32/ecx + 4541 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4542 05/add-to-eax 4/imm32 + 4543 # var slice/ecx: slice = {eax, ecx} + 4544 51/push-ecx + 4545 50/push-eax + 4546 89/<- %ecx 4/r32/esp + 4547 # + 4548 (is-identifier? %ecx) + 4549 (check-ints-equal %eax 0 "F - test-is-identifier-backtick") + 4550 # . epilogue + 4551 89/<- %esp 5/r32/ebp + 4552 5d/pop-to-ebp + 4553 c3/return + 4554 + 4555 test-is-identifier-curly-brace-open: + 4556 # character after 'z' is invalid; also used for blocks + 4557 # . prologue + 4558 55/push-ebp + 4559 89/<- %ebp 4/r32/esp + 4560 # (eax..ecx) = "{a" + 4561 b8/copy-to-eax "{a"/imm32 + 4562 8b/-> *eax 1/r32/ecx + 4563 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4564 05/add-to-eax 4/imm32 + 4565 # var slice/ecx: slice = {eax, ecx} + 4566 51/push-ecx + 4567 50/push-eax + 4568 89/<- %ecx 4/r32/esp 4569 # - 4570 (pop *(ebp+0xc)) # => eax - 4571 # return result - 4572 89/<- %eax 7/r32/edi - 4573 $parse-mu-block:end: - 4574 # . reclaim locals - 4575 81 0/subop/add %esp 0x214/imm32 - 4576 # . restore registers - 4577 5f/pop-to-edi - 4578 5b/pop-to-ebx - 4579 5a/pop-to-edx - 4580 59/pop-to-ecx - 4581 # . epilogue - 4582 89/<- %esp 5/r32/ebp - 4583 5d/pop-to-ebp - 4584 c3/return - 4585 - 4586 $parse-mu-block:abort: - 4587 # error("'{' or '}' should be on its own line, but got '") - 4588 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") - 4589 (rewind-stream %ecx) - 4590 (write-stream 2 %ecx) - 4591 (write-buffered Stderr "'\n") - 4592 (flush Stderr) - 4593 # . syscall(exit, 1) - 4594 bb/copy-to-ebx 1/imm32 - 4595 b8/copy-to-eax 1/imm32/exit - 4596 cd/syscall 0x80/imm8 - 4597 # never gets here - 4598 - 4599 new-block-name: # fn: (handle function) -> result/eax: (handle var) + 4570 (is-identifier? %ecx) + 4571 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open") + 4572 # . epilogue + 4573 89/<- %esp 5/r32/ebp + 4574 5d/pop-to-ebp + 4575 c3/return + 4576 + 4577 test-is-identifier-curly-brace-close: + 4578 # . prologue + 4579 55/push-ebp + 4580 89/<- %ebp 4/r32/esp + 4581 # (eax..ecx) = "}a" + 4582 b8/copy-to-eax "}a"/imm32 + 4583 8b/-> *eax 1/r32/ecx + 4584 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4585 05/add-to-eax 4/imm32 + 4586 # var slice/ecx: slice = {eax, ecx} + 4587 51/push-ecx + 4588 50/push-eax + 4589 89/<- %ecx 4/r32/esp + 4590 # + 4591 (is-identifier? %ecx) + 4592 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close") + 4593 # . epilogue + 4594 89/<- %esp 5/r32/ebp + 4595 5d/pop-to-ebp + 4596 c3/return + 4597 + 4598 test-is-identifier-hyphen: + 4599 # disallow leading '-' since '->' has special meaning 4600 # . prologue 4601 55/push-ebp 4602 89/<- %ebp 4/r32/esp - 4603 # . save registers - 4604 51/push-ecx - 4605 52/push-edx - 4606 # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:' - 4607 8b/-> *(ebp+8) 0/r32/eax - 4608 8b/-> *eax 0/r32/eax # Function-name - 4609 8b/-> *eax 0/r32/eax # String-length - 4610 05/add-to-eax 0xd/imm32 # 10 + 2 for '$:' - 4611 89/<- %ecx 0/r32/eax - 4612 # var name/edx: (stream byte n) - 4613 29/subtract %esp 1/r32/ecx - 4614 ff 6/subop/push %ecx - 4615 68/push 0/imm32/read - 4616 68/push 0/imm32/write - 4617 89/<- %edx 4/r32/esp - 4618 (clear-stream %edx) - 4619 # eax = fn->name - 4620 8b/-> *(ebp+8) 0/r32/eax - 4621 8b/-> *eax 0/r32/eax # Function-name - 4622 # construct result using Next-block-index (and increment it) - 4623 (write %edx "$") - 4624 (write %edx %eax) - 4625 (write %edx ":") - 4626 (print-int32 %edx *Next-block-index) - 4627 ff 0/subop/increment *Next-block-index - 4628 # var s/eax: slice = {name->data, name->data + name->write} (clobbering edx) - 4629 # . eax = name->write - 4630 8b/-> *edx 0/r32/eax - 4631 # . edx = name->data - 4632 8d/copy-address *(edx+0xc) 2/r32/edx - 4633 # . eax = name->write + name->data - 4634 01/add %eax 2/r32/edx - 4635 # . push {edx, eax} - 4636 ff 6/subop/push %eax - 4637 ff 6/subop/push %edx - 4638 89/<- %eax 4/r32/esp - 4639 # result->var = new literal(s) - 4640 (new-literal Heap %eax) # => eax - 4641 $new-block-name:end: - 4642 # . reclaim locals - 4643 81 0/subop/add %ecx 0xc/imm32 # name.{read/write/len} - 4644 81 0/subop/add %ecx 8/imm32 # slice - 4645 01/add %esp 1/r32/ecx - 4646 # . restore registers - 4647 5a/pop-to-edx - 4648 59/pop-to-ecx - 4649 # . epilogue - 4650 89/<- %esp 5/r32/ebp - 4651 5d/pop-to-ebp - 4652 c3/return - 4653 - 4654 == data - 4655 - 4656 # Global state added to each var record when parsing a function - 4657 Next-block-index: # (addr int) - 4658 1/imm32 - 4659 - 4660 == code - 4661 - 4662 check-no-tokens-left: # line: (addr stream byte) - 4663 # . prologue - 4664 55/push-ebp - 4665 89/<- %ebp 4/r32/esp - 4666 # . save registers - 4667 50/push-eax - 4668 51/push-ecx - 4669 # var s/ecx: slice - 4670 68/push 0/imm32/end - 4671 68/push 0/imm32/start - 4672 89/<- %ecx 4/r32/esp - 4673 # - 4674 (next-mu-token *(ebp+8) %ecx) - 4675 # if slice-empty?(s) return - 4676 (slice-empty? %ecx) - 4677 3d/compare-eax-and 0/imm32/false - 4678 75/jump-if-!= $check-no-tokens-left:end/disp8 - 4679 # if (slice-starts-with?(s, '#') return - 4680 # . eax = *s->start - 4681 8b/-> *edx 0/r32/eax - 4682 8a/copy-byte *eax 0/r32/AL - 4683 81 4/subop/and %eax 0xff/imm32 - 4684 # . if (eax == '#') continue - 4685 3d/compare-eax-and 0x23/imm32/hash - 4686 74/jump-if-= $check-no-tokens-left:end/disp8 - 4687 # abort - 4688 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") - 4689 (rewind-stream %ecx) - 4690 (write-stream 2 %ecx) - 4691 (write-buffered Stderr "'\n") - 4692 (flush Stderr) - 4693 # . syscall(exit, 1) - 4694 bb/copy-to-ebx 1/imm32 - 4695 b8/copy-to-eax 1/imm32/exit - 4696 cd/syscall 0x80/imm8 - 4697 # never gets here - 4698 $check-no-tokens-left:end: - 4699 # . reclaim locals - 4700 81 0/subop/add %esp 8/imm32 - 4701 # . restore registers - 4702 59/pop-to-ecx - 4703 58/pop-to-eax - 4704 # . epilogue - 4705 89/<- %esp 5/r32/ebp - 4706 5d/pop-to-ebp - 4707 c3/return - 4708 - 4709 parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) - 4710 # pseudocode: - 4711 # var v: (handle var) = new-literal(name) - 4712 # push(vars, v) - 4713 # result = parse-mu-block(in, vars, fn) - 4714 # pop(vars) - 4715 # result->name = s - 4716 # return result - 4717 # - 4718 # . prologue - 4719 55/push-ebp - 4720 89/<- %ebp 4/r32/esp - 4721 # . save registers - 4722 51/push-ecx - 4723 # var v/ecx: (handle var) - 4724 (new-literal Heap *(ebp+8)) # => eax - 4725 89/<- %ecx 0/r32/eax - 4726 # push(vars, v) - 4727 (push *(ebp+0x10) %ecx) - 4728 # eax = result - 4729 (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) # => eax - 4730 # pop the var - 4731 50/push-eax - 4732 (pop *(ebp+0x10)) # => eax - 4733 58/pop-to-eax - 4734 # result->tag = named-block - 4735 c7 0/subop/copy *eax 0/imm32/block # Stmt-tag - 4736 # result->var = v - 4737 89/<- *(eax+8) 1/r32/ecx # Block-var - 4738 $parse-mu-named-block:end: - 4739 # . restore registers - 4740 59/pop-to-ecx - 4741 # . epilogue - 4742 89/<- %esp 5/r32/ebp - 4743 5d/pop-to-ebp - 4744 c3/return - 4745 - 4746 parse-mu-var-def: # line: (addr stream byte), vars: (addr stack (handle var)) -> result/eax: (handle stmt) - 4747 # . prologue - 4748 55/push-ebp - 4749 89/<- %ebp 4/r32/esp - 4750 # . save registers - 4751 51/push-ecx - 4752 52/push-edx - 4753 # var word-slice/ecx: slice - 4754 68/push 0/imm32/end - 4755 68/push 0/imm32/start - 4756 89/<- %ecx 4/r32/esp - 4757 # var v/edx: (handle var) = parse-var-with-type(line) - 4758 (next-mu-token *(ebp+8) %ecx) - 4759 (parse-var-with-type %ecx *(ebp+8)) # => eax - 4760 89/<- %edx 0/r32/eax - 4761 # - 4762 (push *(ebp+0xc) %edx) - 4763 # either v has no register and there's no more to this line - 4764 8b/-> *(edx+0x10) 0/r32/eax # Var-register - 4765 3d/compare-eax-and 0/imm32 - 4766 { - 4767 75/jump-if-!= break/disp8 - 4768 # TODO: ensure that there's nothing else on this line - 4769 (new-var-def Heap %edx) # => eax - 4770 eb/jump $parse-mu-var-def:end/disp8 - 4771 } - 4772 # or v has a register and there's more to this line - 4773 { - 4774 74/jump-if-= break/disp8 - 4775 # ensure that the next word is '<-' - 4776 (next-mu-token *(ebp+8) %ecx) - 4777 (slice-equal? %ecx "<-") # => eax - 4778 3d/compare-eax-and 0/imm32/false - 4779 74/jump-if-= $parse-mu-var-def:abort/disp8 - 4780 # - 4781 (new-reg-var-def Heap %edx) # => eax - 4782 (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc)) - 4783 } - 4784 $parse-mu-var-def:end: - 4785 # . reclaim locals - 4786 81 0/subop/add %esp 8/imm32 - 4787 # . restore registers - 4788 5a/pop-to-edx - 4789 59/pop-to-ecx - 4790 # . epilogue - 4791 89/<- %esp 5/r32/ebp - 4792 5d/pop-to-ebp - 4793 c3/return - 4794 - 4795 $parse-mu-var-def:abort: - 4796 (rewind-stream *(ebp+8)) - 4797 # error("register variable requires a valid instruction to initialize but got '" line "'\n") - 4798 (write-buffered Stderr "register variable requires a valid instruction to initialize but got '") - 4799 (flush Stderr) - 4800 (write-stream 2 *(ebp+8)) - 4801 (write-buffered Stderr "'\n") - 4802 (flush Stderr) - 4803 # . syscall(exit, 1) - 4804 bb/copy-to-ebx 1/imm32 - 4805 b8/copy-to-eax 1/imm32/exit - 4806 cd/syscall 0x80/imm8 - 4807 # never gets here - 4808 - 4809 test-parse-mu-var-def: - 4810 # 'var n: int' - 4811 # . prologue - 4812 55/push-ebp - 4813 89/<- %ebp 4/r32/esp - 4814 # setup - 4815 (clear-stream _test-input-stream) - 4816 (write _test-input-stream "n: int\n") # caller has consumed the 'var' - 4817 # var vars/ecx: (stack (addr var) 4) - 4818 81 5/subop/subtract %esp 0x10/imm32 - 4819 68/push 0x10/imm32/length - 4820 68/push 0/imm32/top - 4821 89/<- %ecx 4/r32/esp - 4822 (clear-stack %ecx) - 4823 # convert - 4824 (parse-mu-var-def _test-input-stream %ecx) # => eax - 4825 # check result - 4826 (check-ints-equal *eax 2 "F - test-parse-mu-var-def/tag") # Stmt-tag is var-def - 4827 8b/-> *(eax+4) 0/r32/eax # Vardef-var - 4828 (check-strings-equal *eax "n" "F - test-parse-mu-var-def/var-name") # Var-name - 4829 (check-ints-equal *(eax+0x10) 0 "F - test-parse-mu-var-def/var-register") # Var-register - 4830 # ensure type is int - 4831 8b/-> *(eax+4) 0/r32/eax # Var-type - 4832 (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0") # Tree-left - 4833 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-var-def/var-type:0") # Tree-right - 4834 # . epilogue - 4835 89/<- %esp 5/r32/ebp - 4836 5d/pop-to-ebp - 4837 c3/return - 4838 - 4839 test-parse-mu-reg-var-def: - 4840 # 'var n/eax: int <- copy 0' - 4841 # . prologue - 4842 55/push-ebp - 4843 89/<- %ebp 4/r32/esp - 4844 # setup - 4845 (clear-stream _test-input-stream) - 4846 (write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var' - 4847 # var vars/ecx: (stack (addr var) 4) - 4848 81 5/subop/subtract %esp 0x10/imm32 - 4849 68/push 0x10/imm32/length - 4850 68/push 0/imm32/top - 4851 89/<- %ecx 4/r32/esp - 4852 (clear-stack %ecx) - 4853 # convert - 4854 (parse-mu-var-def _test-input-stream %ecx) # => eax - 4855 # check result - 4856 (check-ints-equal *eax 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is reg-var-def - 4857 8b/-> *(eax+0xc) 0/r32/eax # Regvardef-outputs - 4858 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/single-output") # List-next - 4859 8b/-> *eax 0/r32/eax # Stmt-var-value - 4860 (check-strings-equal *eax "n" "F - test-parse-mu-reg-var-def/output-name") # Var-name - 4861 (check-strings-equal *(eax+0x10) "eax" "F - test-parse-mu-reg-var-def/output-register") # Var-register - 4862 # ensure type is int - 4863 8b/-> *(eax+4) 0/r32/eax # Var-type - 4864 (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-left - 4865 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-right - 4866 # . epilogue - 4867 89/<- %esp 5/r32/ebp - 4868 5d/pop-to-ebp - 4869 c3/return - 4870 - 4871 parse-mu-stmt: # line: (addr stream byte), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) - 4872 # pseudocode: - 4873 # var name: slice - 4874 # result = allocate(Heap, Stmt-size) - 4875 # if stmt-has-outputs?(line) - 4876 # while true - 4877 # name = next-mu-token(line) - 4878 # if (name == '<-') break - 4879 # assert(is-identifier?(name)) - 4880 # var v: (handle var) = lookup-or-define-var(name, vars, fn) # regular stmts may define vars in fn outputs - 4881 # result->outputs = append(result->outputs, v) - 4882 # add-operation-and-inputs-to-stmt(result, line, vars) - 4883 # - 4884 # . prologue - 4885 55/push-ebp - 4886 89/<- %ebp 4/r32/esp - 4887 # . save registers - 4888 51/push-ecx - 4889 52/push-edx - 4890 57/push-edi - 4891 # var name/ecx: slice - 4892 68/push 0/imm32/end - 4893 68/push 0/imm32/start - 4894 89/<- %ecx 4/r32/esp - 4895 # var is-deref?/edx: boolean = false - 4896 ba/copy-to-edx 0/imm32/false - 4897 # result/edi: (handle stmt) - 4898 (allocate Heap *Stmt-size) # => eax - 4899 (zero-out %eax *Stmt-size) - 4900 89/<- %edi 0/r32/eax - 4901 # result->tag = 1/stmt - 4902 c7 0/subop/copy *edi 1/imm32/stmt1 # Stmt-tag - 4903 { - 4904 (stmt-has-outputs? *(ebp+8)) - 4905 3d/compare-eax-and 0/imm32/false - 4906 0f 84/jump-if-= break/disp32 - 4907 { - 4908 $parse-mu-stmt:read-outputs: - 4909 # name = next-mu-token(line) - 4910 (next-mu-token *(ebp+8) %ecx) - 4911 # if slice-empty?(word-slice) break - 4912 (slice-empty? %ecx) # => eax - 4913 3d/compare-eax-and 0/imm32/false - 4914 0f 85/jump-if-!= break/disp32 - 4915 # if (name == "<-") break - 4916 (slice-equal? %ecx "<-") # => eax - 4917 3d/compare-eax-and 0/imm32/false - 4918 0f 85/jump-if-!= break/disp32 - 4919 # is-deref? = false - 4920 ba/copy-to-edx 0/imm32/false - 4921 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? - 4922 8b/-> *ecx 0/r32/eax # Slice-start - 4923 8a/copy-byte *eax 0/r32/AL - 4924 81 4/subop/and %eax 0xff/imm32 - 4925 3d/compare-eax-and 0x2a/imm32/asterisk - 4926 { - 4927 75/jump-if-!= break/disp8 - 4928 ff 0/subop/increment *ecx - 4929 ba/copy-to-edx 1/imm32/true - 4930 } - 4931 # assert(is-identifier?(name)) - 4932 (is-identifier? %ecx) # => eax - 4933 3d/compare-eax-and 0/imm32/false - 4934 0f 84/jump-if-= $parse-mu-stmt:abort/disp32 - 4935 # result->outputs = new stmt-var(lookup(name, vars, fn), result->outputs, is-deref?) - 4936 (lookup-or-define-var %ecx *(ebp+0xc) *(ebp+0x10)) # => eax - 4937 (append-stmt-var Heap %eax *(edi+0xc) %edx) # Stmt1-outputs => eax - 4938 89/<- *(edi+0xc) 0/r32/eax # Stmt1-outputs - 4939 e9/jump loop/disp32 - 4940 } - 4941 } - 4942 (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc)) - 4943 $parse-mu-stmt:end: - 4944 # return result - 4945 89/<- %eax 7/r32/edi - 4946 # . reclaim locals - 4947 81 0/subop/add %esp 8/imm32 - 4948 # . restore registers - 4949 5f/pop-to-edi - 4950 5a/pop-to-edx - 4951 59/pop-to-ecx - 4952 # . epilogue - 4953 89/<- %esp 5/r32/ebp - 4954 5d/pop-to-ebp - 4955 c3/return - 4956 - 4957 $parse-mu-stmt:abort: - 4958 # error("invalid identifier '" name "'\n") - 4959 (write-buffered Stderr "invalid identifier '") - 4960 (write-slice-buffered Stderr %ecx) - 4961 (write-buffered Stderr "'\n") - 4962 (flush Stderr) - 4963 # . syscall(exit, 1) - 4964 bb/copy-to-ebx 1/imm32 - 4965 b8/copy-to-eax 1/imm32/exit - 4966 cd/syscall 0x80/imm8 - 4967 # never gets here - 4968 - 4969 add-operation-and-inputs-to-stmt: # stmt: (handle stmt), line: (addr stream byte), vars: (addr stack (handle var)) - 4970 # pseudocode: - 4971 # stmt->name = slice-to-string(next-mu-token(line)) - 4972 # while true - 4973 # name = next-mu-token(line) - 4974 # v = lookup-var-or-literal(name) - 4975 # stmt->inouts = append(stmt->inouts, v) - 4976 # - 4977 # . prologue - 4978 55/push-ebp - 4979 89/<- %ebp 4/r32/esp - 4980 # . save registers - 4981 50/push-eax - 4982 51/push-ecx - 4983 52/push-edx - 4984 53/push-ebx - 4985 57/push-edi - 4986 # edi = stmt - 4987 8b/-> *(ebp+8) 7/r32/edi - 4988 # var name/ecx: slice - 4989 68/push 0/imm32/end - 4990 68/push 0/imm32/start - 4991 89/<- %ecx 4/r32/esp - 4992 # var is-deref?/edx: boolean = false - 4993 ba/copy-to-edx 0/imm32/false - 4994 $add-operation-and-inputs-to-stmt:read-operation: - 4995 (next-mu-token *(ebp+0xc) %ecx) - 4996 (slice-to-string Heap %ecx) # => eax - 4997 89/<- *(edi+4) 0/r32/eax # Stmt1-operation or Regvardef-operation - 4998 # var is-get?/ebx: boolean = (name == "get") - 4999 (slice-equal? %ecx "get") # => eax - 5000 89/<- %ebx 0/r32/eax - 5001 { - 5002 $add-operation-and-inputs-to-stmt:read-inouts: - 5003 # name = next-mu-token(line) - 5004 (next-mu-token *(ebp+0xc) %ecx) - 5005 # if slice-empty?(word-slice) break - 5006 (slice-empty? %ecx) # => eax - 5007 3d/compare-eax-and 0/imm32/false - 5008 0f 85/jump-if-!= break/disp32 - 5009 # if (name == "<-") abort - 5010 (slice-equal? %ecx "<-") - 5011 3d/compare-eax-and 0/imm32/false - 5012 0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32 - 5013 # if (is-get? && second operand) lookup or create offset - 5014 { - 5015 81 7/subop/compare %ebx 0/imm32/false - 5016 74/jump-if-= break/disp8 - 5017 81 7/subop/compare *(edi+8) 0/imm32 # Stmt1-inouts or Regvardef-inouts - 5018 74/jump-if-= break/disp8 - 5019 (lookup-or-create-constant *(edi+8) %ecx) # Stmt1-inouts => eax - 5020 #? (write-buffered Stderr "creating new output var ") - 5021 #? (print-int32-buffered Stderr %eax) - 5022 #? (write-buffered Stderr " for field called ") - 5023 #? (write-slice-buffered Stderr %ecx) - 5024 #? (write-buffered Stderr Newline) - 5025 #? (flush Stderr) - 5026 e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32 - 5027 } - 5028 # is-deref? = false - 5029 ba/copy-to-edx 0/imm32/false - 5030 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? - 5031 8b/-> *ecx 0/r32/eax # Slice-start - 5032 8a/copy-byte *eax 0/r32/AL - 5033 81 4/subop/and %eax 0xff/imm32 - 5034 3d/compare-eax-and 0x2a/imm32/asterisk - 5035 { - 5036 75/jump-if-!= break/disp8 - 5037 $add-operation-and-inputs-to-stmt:inout-is-deref: - 5038 ff 0/subop/increment *ecx - 5039 ba/copy-to-edx 1/imm32/true - 5040 } - 5041 (lookup-var-or-literal %ecx *(ebp+0x10)) # => eax - 5042 $add-operation-and-inputs-to-stmt:save-var: - 5043 (append-stmt-var Heap %eax *(edi+8) %edx) # Stmt1-inouts or Regvardef-inouts => eax - 5044 89/<- *(edi+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts - 5045 e9/jump loop/disp32 - 5046 } - 5047 $add-operation-and-inputs-to-stmt:end: - 5048 # . reclaim locals - 5049 81 0/subop/add %esp 8/imm32 - 5050 # . restore registers - 5051 5f/pop-to-edi - 5052 5b/pop-to-ebx - 5053 5a/pop-to-edx - 5054 59/pop-to-ecx - 5055 58/pop-to-eax - 5056 # . epilogue - 5057 89/<- %esp 5/r32/ebp - 5058 5d/pop-to-ebp - 5059 c3/return - 5060 - 5061 $add-operation-and-inputs-to-stmt:abort: - 5062 # error("invalid statement '" line "'\n") - 5063 (rewind-stream *(ebp+8)) - 5064 (write-buffered Stderr "invalid identifier '") - 5065 (flush Stderr) - 5066 (write-stream 2 *(ebp+8)) - 5067 (write-buffered Stderr "'\n") - 5068 (flush Stderr) - 5069 # . syscall(exit, 1) - 5070 bb/copy-to-ebx 1/imm32 - 5071 b8/copy-to-eax 1/imm32/exit - 5072 cd/syscall 0x80/imm8 - 5073 # never gets here - 5074 - 5075 stmt-has-outputs?: # line: (addr stream byte) -> result/eax: boolean - 5076 # . prologue - 5077 55/push-ebp - 5078 89/<- %ebp 4/r32/esp - 5079 # . save registers - 5080 51/push-ecx - 5081 # var word-slice/ecx: slice - 5082 68/push 0/imm32/end - 5083 68/push 0/imm32/start - 5084 89/<- %ecx 4/r32/esp - 5085 # result = false - 5086 b8/copy-to-eax 0/imm32/false - 5087 (rewind-stream *(ebp+8)) - 5088 { - 5089 (next-mu-token *(ebp+8) %ecx) - 5090 # if slice-empty?(word-slice) break - 5091 (slice-empty? %ecx) - 5092 3d/compare-eax-and 0/imm32/false - 5093 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) - 5094 0f 85/jump-if-!= break/disp32 - 5095 # if slice-starts-with?(word-slice, '#') break - 5096 # . eax = *word-slice->start - 5097 8b/-> *ecx 0/r32/eax - 5098 8a/copy-byte *eax 0/r32/AL - 5099 81 4/subop/and %eax 0xff/imm32 - 5100 # . if (eax == '#') break - 5101 3d/compare-eax-and 0x23/imm32/hash - 5102 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) - 5103 0f 84/jump-if-= break/disp32 - 5104 # if slice-equal?(word-slice, '<-') return true - 5105 (slice-equal? %ecx "<-") - 5106 3d/compare-eax-and 0/imm32/false - 5107 74/jump-if-= loop/disp8 - 5108 b8/copy-to-eax 1/imm32/true - 5109 } - 5110 $stmt-has-outputs:end: - 5111 (rewind-stream *(ebp+8)) - 5112 # . reclaim locals - 5113 81 0/subop/add %esp 8/imm32 - 5114 # . restore registers - 5115 59/pop-to-ecx - 5116 # . epilogue - 5117 89/<- %esp 5/r32/ebp - 5118 5d/pop-to-ebp - 5119 c3/return - 5120 - 5121 # if 'name' starts with a digit, create a new literal var for it - 5122 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found - 5123 lookup-var-or-literal: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) - 5124 # . prologue - 5125 55/push-ebp - 5126 89/<- %ebp 4/r32/esp - 5127 # . save registers - 5128 51/push-ecx - 5129 56/push-esi - 5130 # esi = name - 5131 8b/-> *(ebp+8) 6/r32/esi - 5132 # if slice-empty?(name) abort - 5133 (slice-empty? %esi) # => eax - 5134 3d/compare-eax-and 0/imm32/false - 5135 0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32 - 5136 # var c/ecx: byte = *name->start - 5137 8b/-> *esi 1/r32/ecx - 5138 8a/copy-byte *ecx 1/r32/CL - 5139 81 4/subop/and %ecx 0xff/imm32 - 5140 # if is-decimal-digit?(c) return new var(name) - 5141 { - 5142 (is-decimal-digit? %ecx) # => eax - 5143 3d/compare-eax-and 0/imm32/false - 5144 74/jump-if-= break/disp8 - 5145 (new-literal-integer Heap %esi) # => eax - 5146 eb/jump $lookup-var-or-literal:end/disp8 - 5147 } - 5148 # else if (c == '"') return new var(name) - 5149 { - 5150 81 7/subop/compare %ecx 0x22/imm32/dquote - 5151 75/jump-if-!= break/disp8 - 5152 (new-literal Heap %esi) # => eax - 5153 eb/jump $lookup-var-or-literal:end/disp8 - 5154 } - 5155 # otherwise return lookup-var(name, vars) - 5156 { - 5157 (lookup-var %esi *(ebp+0xc)) # => eax - 5158 } - 5159 $lookup-var-or-literal:end: - 5160 # . restore registers - 5161 5e/pop-to-esi - 5162 59/pop-to-ecx - 5163 # . epilogue - 5164 89/<- %esp 5/r32/ebp - 5165 5d/pop-to-ebp - 5166 c3/return - 5167 - 5168 $lookup-var-or-literal:abort: - 5169 (write-buffered Stderr "empty variable!") - 5170 (flush Stderr) - 5171 # . syscall(exit, 1) - 5172 bb/copy-to-ebx 1/imm32 - 5173 b8/copy-to-eax 1/imm32/exit - 5174 cd/syscall 0x80/imm8 - 5175 # never gets here - 5176 - 5177 # return first 'name' from the top (back) of 'vars' and abort if not found - 5178 lookup-var: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) - 5179 # . prologue - 5180 55/push-ebp - 5181 89/<- %ebp 4/r32/esp - 5182 # var target/eax: (handle array byte) = slice-to-string(name) - 5183 (slice-to-string Heap *(ebp+8)) # => eax - 5184 # - 5185 (lookup-var-helper %eax *(ebp+0xc)) # => eax - 5186 # if (result == 0) abort - 5187 3d/compare-eax-and 0/imm32 - 5188 74/jump-if-= $lookup-var:abort/disp8 - 5189 $lookup-var:end: - 5190 # . epilogue - 5191 89/<- %esp 5/r32/ebp - 5192 5d/pop-to-ebp - 5193 c3/return + 4603 # (eax..ecx) = "-a" + 4604 b8/copy-to-eax "-a"/imm32 + 4605 8b/-> *eax 1/r32/ecx + 4606 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4607 05/add-to-eax 4/imm32 + 4608 # var slice/ecx: slice = {eax, ecx} + 4609 51/push-ecx + 4610 50/push-eax + 4611 89/<- %ecx 4/r32/esp + 4612 # + 4613 (is-identifier? %ecx) + 4614 (check-ints-equal %eax 0 "F - test-is-identifier-hyphen") + 4615 # . epilogue + 4616 89/<- %esp 5/r32/ebp + 4617 5d/pop-to-ebp + 4618 c3/return + 4619 + 4620 populate-mu-function-body: # in: (addr buffered-file), out: (handle function), vars: (addr stack (handle var)) + 4621 # . prologue + 4622 55/push-ebp + 4623 89/<- %ebp 4/r32/esp + 4624 # . save registers + 4625 50/push-eax + 4626 56/push-esi + 4627 57/push-edi + 4628 # esi = in + 4629 8b/-> *(ebp+8) 6/r32/esi + 4630 # edi = out + 4631 8b/-> *(ebp+0xc) 7/r32/edi + 4632 # var eax: (handle block) = parse-mu-block(in, vars, fn) + 4633 (parse-mu-block %esi *(ebp+0x10) %edi) # => eax + 4634 # out->body = eax + 4635 89/<- *(edi+0x10) 0/r32/eax # Function-body + 4636 $populate-mu-function-body:end: + 4637 # . restore registers + 4638 5f/pop-to-edi + 4639 5e/pop-to-esi + 4640 58/pop-to-eax + 4641 # . epilogue + 4642 89/<- %esp 5/r32/ebp + 4643 5d/pop-to-ebp + 4644 c3/return + 4645 + 4646 # parses a block, assuming that the leading '{' has already been read by the caller + 4647 parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle block) + 4648 # pseudocode: + 4649 # var line: (stream byte 512) + 4650 # var word-slice: slice + 4651 # result/eax = allocate(Heap, Stmt-size) + 4652 # result->tag = 0/block + 4653 # result->name = some unique name + 4654 # while true # line loop + 4655 # clear-stream(line) + 4656 # read-line-buffered(in, line) + 4657 # if (line->write == 0) break # end of file + 4658 # word-slice = next-mu-token(line) + 4659 # if slice-empty?(word-slice) # end of line + 4660 # continue + 4661 # else if slice-starts-with?(word-slice, "#") + 4662 # continue + 4663 # else if slice-equal?(word-slice, "{") + 4664 # assert(no-tokens-in(line)) + 4665 # block = parse-mu-block(in, vars, fn) + 4666 # append-to-block(result, block) + 4667 # else if slice-equal?(word-slice, "}") + 4668 # break + 4669 # else if slice-ends-with?(word-slice, ":") + 4670 # # TODO: error-check the rest of 'line' + 4671 # --word-slice->end to skip ':' + 4672 # named-block = parse-mu-named-block(word-slice, in, vars, fn) + 4673 # append-to-block(result, named-block) + 4674 # else if slice-equal?(word-slice, "var") + 4675 # var-def = parse-mu-var-def(line, vars) + 4676 # append-to-block(result, var-def) + 4677 # else + 4678 # stmt = parse-mu-stmt(line, vars, fn) + 4679 # append-to-block(result, stmt) + 4680 # return result + 4681 # + 4682 # . prologue + 4683 55/push-ebp + 4684 89/<- %ebp 4/r32/esp + 4685 # . save registers + 4686 51/push-ecx + 4687 52/push-edx + 4688 53/push-ebx + 4689 57/push-edi + 4690 # var line/ecx: (stream byte 512) + 4691 81 5/subop/subtract %esp 0x200/imm32 + 4692 68/push 0x200/imm32/size + 4693 68/push 0/imm32/read + 4694 68/push 0/imm32/write + 4695 89/<- %ecx 4/r32/esp + 4696 # var word-slice/edx: slice + 4697 68/push 0/imm32/end + 4698 68/push 0/imm32/start + 4699 89/<- %edx 4/r32/esp + 4700 # edi = result + 4701 (allocate Heap *Stmt-size) # => eax + 4702 89/<- %edi 0/r32/eax + 4703 # set result->tag + 4704 c7 0/subop/copy *edi 0/imm32/block # Stmt-tag + 4705 # set result->var + 4706 (new-block-name *(ebp+0x10)) # => eax + 4707 89/<- *(edi+8) 0/r32/eax # Block-var + 4708 # push result->var to vars + 4709 (push *(ebp+0xc) %eax) + 4710 { + 4711 $parse-mu-block:line-loop: + 4712 # line = read-line-buffered(in) + 4713 (clear-stream %ecx) + 4714 (read-line-buffered *(ebp+8) %ecx) + 4715 #? (write-buffered Stderr "line: ") + 4716 #? (write-stream-data Stderr %ecx) + 4717 #? (write-buffered Stderr Newline) + 4718 #? (flush Stderr) + 4719 # if (line->write == 0) break + 4720 81 7/subop/compare *ecx 0/imm32 + 4721 0f 84/jump-if-= break/disp32 + 4722 # word-slice = next-mu-token(line) + 4723 (next-mu-token %ecx %edx) + 4724 #? (write-buffered Stderr "word: ") + 4725 #? (write-slice-buffered Stderr %edx) + 4726 #? (write-buffered Stderr Newline) + 4727 #? (flush Stderr) + 4728 # if slice-empty?(word-slice) continue + 4729 (slice-empty? %edx) + 4730 3d/compare-eax-and 0/imm32/false + 4731 0f 85/jump-if-!= loop/disp32 + 4732 # if (slice-starts-with?(word-slice, '#') continue + 4733 # . eax = *word-slice->start + 4734 8b/-> *edx 0/r32/eax + 4735 8a/copy-byte *eax 0/r32/AL + 4736 81 4/subop/and %eax 0xff/imm32 + 4737 # . if (eax == '#') continue + 4738 3d/compare-eax-and 0x23/imm32/hash + 4739 0f 84/jump-if-= loop/disp32 + 4740 # if slice-equal?(word-slice, "{") + 4741 { + 4742 $parse-mu-block:check-for-block: + 4743 (slice-equal? %edx "{") + 4744 3d/compare-eax-and 0/imm32/false + 4745 74/jump-if-= break/disp8 + 4746 (check-no-tokens-left %ecx) + 4747 # parse new block and append + 4748 (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax + 4749 (append-to-block Heap %edi %eax) + 4750 e9/jump $parse-mu-block:line-loop/disp32 + 4751 } + 4752 # if slice-equal?(word-slice, "}") break + 4753 $parse-mu-block:check-for-end: + 4754 (slice-equal? %edx "}") + 4755 3d/compare-eax-and 0/imm32/false + 4756 0f 85/jump-if-!= break/disp32 + 4757 # if slice-ends-with?(word-slice, ":") parse named block and append + 4758 { + 4759 $parse-mu-block:check-for-named-block: + 4760 # . eax = *(word-slice->end-1) + 4761 8b/-> *(edx+4) 0/r32/eax + 4762 48/decrement-eax + 4763 8a/copy-byte *eax 0/r32/AL + 4764 81 4/subop/and %eax 0xff/imm32 + 4765 # . if (eax != ':') break + 4766 3d/compare-eax-and 0x3a/imm32/colon + 4767 0f 85/jump-if-!= break/disp32 + 4768 # TODO: error-check the rest of 'line' + 4769 # + 4770 # skip ':' + 4771 ff 1/subop/decrement *(edx+4) # Slice-end + 4772 # + 4773 (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax + 4774 (append-to-block Heap %edi %eax) + 4775 e9/jump $parse-mu-block:line-loop/disp32 + 4776 } + 4777 # if slice-equal?(word-slice, "var") + 4778 { + 4779 $parse-mu-block:check-for-var: + 4780 (slice-equal? %edx "var") + 4781 3d/compare-eax-and 0/imm32/false + 4782 74/jump-if-= break/disp8 + 4783 # + 4784 (parse-mu-var-def %ecx *(ebp+0xc)) # => eax + 4785 (append-to-block Heap %edi %eax) + 4786 e9/jump $parse-mu-block:line-loop/disp32 + 4787 } + 4788 $parse-mu-block:regular-stmt: + 4789 # otherwise + 4790 (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10)) # => eax + 4791 (append-to-block Heap %edi %eax) + 4792 e9/jump loop/disp32 + 4793 } # end line loop + 4794 # + 4795 (pop *(ebp+0xc)) # => eax + 4796 # return result + 4797 89/<- %eax 7/r32/edi + 4798 $parse-mu-block:end: + 4799 # . reclaim locals + 4800 81 0/subop/add %esp 0x214/imm32 + 4801 # . restore registers + 4802 5f/pop-to-edi + 4803 5b/pop-to-ebx + 4804 5a/pop-to-edx + 4805 59/pop-to-ecx + 4806 # . epilogue + 4807 89/<- %esp 5/r32/ebp + 4808 5d/pop-to-ebp + 4809 c3/return + 4810 + 4811 $parse-mu-block:abort: + 4812 # error("'{' or '}' should be on its own line, but got '") + 4813 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") + 4814 (rewind-stream %ecx) + 4815 (write-stream 2 %ecx) + 4816 (write-buffered Stderr "'\n") + 4817 (flush Stderr) + 4818 # . syscall(exit, 1) + 4819 bb/copy-to-ebx 1/imm32 + 4820 b8/copy-to-eax 1/imm32/exit + 4821 cd/syscall 0x80/imm8 + 4822 # never gets here + 4823 + 4824 new-block-name: # fn: (handle function) -> result/eax: (handle var) + 4825 # . prologue + 4826 55/push-ebp + 4827 89/<- %ebp 4/r32/esp + 4828 # . save registers + 4829 51/push-ecx + 4830 52/push-edx + 4831 # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:' + 4832 8b/-> *(ebp+8) 0/r32/eax + 4833 8b/-> *eax 0/r32/eax # Function-name + 4834 8b/-> *eax 0/r32/eax # String-size + 4835 05/add-to-eax 0xd/imm32 # 10 + 2 for '$:' + 4836 89/<- %ecx 0/r32/eax + 4837 # var name/edx: (stream byte n) + 4838 29/subtract-from %esp 1/r32/ecx + 4839 ff 6/subop/push %ecx + 4840 68/push 0/imm32/read + 4841 68/push 0/imm32/write + 4842 89/<- %edx 4/r32/esp + 4843 (clear-stream %edx) + 4844 # eax = fn->name + 4845 8b/-> *(ebp+8) 0/r32/eax + 4846 8b/-> *eax 0/r32/eax # Function-name + 4847 # construct result using Next-block-index (and increment it) + 4848 (write %edx "$") + 4849 (write %edx %eax) + 4850 (write %edx ":") + 4851 (print-int32 %edx *Next-block-index) + 4852 ff 0/subop/increment *Next-block-index + 4853 # var s/eax: slice = {name->data, name->data + name->write} (clobbering edx) + 4854 # . eax = name->write + 4855 8b/-> *edx 0/r32/eax + 4856 # . edx = name->data + 4857 8d/copy-address *(edx+0xc) 2/r32/edx + 4858 # . eax = name->write + name->data + 4859 01/add-to %eax 2/r32/edx + 4860 # . push {edx, eax} + 4861 ff 6/subop/push %eax + 4862 ff 6/subop/push %edx + 4863 89/<- %eax 4/r32/esp + 4864 # result->var = new literal(s) + 4865 (new-literal Heap %eax) # => eax + 4866 $new-block-name:end: + 4867 # . reclaim locals + 4868 81 0/subop/add %ecx 0xc/imm32 # name.{read/write/len} + 4869 81 0/subop/add %ecx 8/imm32 # slice + 4870 01/add-to %esp 1/r32/ecx + 4871 # . restore registers + 4872 5a/pop-to-edx + 4873 59/pop-to-ecx + 4874 # . epilogue + 4875 89/<- %esp 5/r32/ebp + 4876 5d/pop-to-ebp + 4877 c3/return + 4878 + 4879 == data + 4880 + 4881 # Global state added to each var record when parsing a function + 4882 Next-block-index: # (addr int) + 4883 1/imm32 + 4884 + 4885 == code + 4886 + 4887 check-no-tokens-left: # line: (addr stream byte) + 4888 # . prologue + 4889 55/push-ebp + 4890 89/<- %ebp 4/r32/esp + 4891 # . save registers + 4892 50/push-eax + 4893 51/push-ecx + 4894 # var s/ecx: slice + 4895 68/push 0/imm32/end + 4896 68/push 0/imm32/start + 4897 89/<- %ecx 4/r32/esp + 4898 # + 4899 (next-mu-token *(ebp+8) %ecx) + 4900 # if slice-empty?(s) return + 4901 (slice-empty? %ecx) + 4902 3d/compare-eax-and 0/imm32/false + 4903 75/jump-if-!= $check-no-tokens-left:end/disp8 + 4904 # if (slice-starts-with?(s, '#') return + 4905 # . eax = *s->start + 4906 8b/-> *edx 0/r32/eax + 4907 8a/copy-byte *eax 0/r32/AL + 4908 81 4/subop/and %eax 0xff/imm32 + 4909 # . if (eax == '#') continue + 4910 3d/compare-eax-and 0x23/imm32/hash + 4911 74/jump-if-= $check-no-tokens-left:end/disp8 + 4912 # abort + 4913 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") + 4914 (rewind-stream %ecx) + 4915 (write-stream 2 %ecx) + 4916 (write-buffered Stderr "'\n") + 4917 (flush Stderr) + 4918 # . syscall(exit, 1) + 4919 bb/copy-to-ebx 1/imm32 + 4920 b8/copy-to-eax 1/imm32/exit + 4921 cd/syscall 0x80/imm8 + 4922 # never gets here + 4923 $check-no-tokens-left:end: + 4924 # . reclaim locals + 4925 81 0/subop/add %esp 8/imm32 + 4926 # . restore registers + 4927 59/pop-to-ecx + 4928 58/pop-to-eax + 4929 # . epilogue + 4930 89/<- %esp 5/r32/ebp + 4931 5d/pop-to-ebp + 4932 c3/return + 4933 + 4934 parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) + 4935 # pseudocode: + 4936 # var v: (handle var) = new-literal(name) + 4937 # push(vars, v) + 4938 # result = parse-mu-block(in, vars, fn) + 4939 # pop(vars) + 4940 # result->name = s + 4941 # return result + 4942 # + 4943 # . prologue + 4944 55/push-ebp + 4945 89/<- %ebp 4/r32/esp + 4946 # . save registers + 4947 51/push-ecx + 4948 # var v/ecx: (handle var) + 4949 (new-literal Heap *(ebp+8)) # => eax + 4950 89/<- %ecx 0/r32/eax + 4951 # push(vars, v) + 4952 (push *(ebp+0x10) %ecx) + 4953 # eax = result + 4954 (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) # => eax + 4955 # pop the var + 4956 50/push-eax + 4957 (pop *(ebp+0x10)) # => eax + 4958 58/pop-to-eax + 4959 # result->tag = named-block + 4960 c7 0/subop/copy *eax 0/imm32/block # Stmt-tag + 4961 # result->var = v + 4962 89/<- *(eax+8) 1/r32/ecx # Block-var + 4963 $parse-mu-named-block:end: + 4964 # . restore registers + 4965 59/pop-to-ecx + 4966 # . epilogue + 4967 89/<- %esp 5/r32/ebp + 4968 5d/pop-to-ebp + 4969 c3/return + 4970 + 4971 parse-mu-var-def: # line: (addr stream byte), vars: (addr stack (handle var)) -> result/eax: (handle stmt) + 4972 # . prologue + 4973 55/push-ebp + 4974 89/<- %ebp 4/r32/esp + 4975 # . save registers + 4976 51/push-ecx + 4977 52/push-edx + 4978 # var word-slice/ecx: slice + 4979 68/push 0/imm32/end + 4980 68/push 0/imm32/start + 4981 89/<- %ecx 4/r32/esp + 4982 # var v/edx: (handle var) = parse-var-with-type(line) + 4983 (next-mu-token *(ebp+8) %ecx) + 4984 (parse-var-with-type %ecx *(ebp+8)) # => eax + 4985 89/<- %edx 0/r32/eax + 4986 # + 4987 (push *(ebp+0xc) %edx) + 4988 # either v has no register and there's no more to this line + 4989 8b/-> *(edx+0x10) 0/r32/eax # Var-register + 4990 3d/compare-eax-and 0/imm32 + 4991 { + 4992 75/jump-if-!= break/disp8 + 4993 # TODO: ensure that there's nothing else on this line + 4994 (new-var-def Heap %edx) # => eax + 4995 eb/jump $parse-mu-var-def:end/disp8 + 4996 } + 4997 # or v has a register and there's more to this line + 4998 { + 4999 74/jump-if-= break/disp8 + 5000 # ensure that the next word is '<-' + 5001 (next-mu-token *(ebp+8) %ecx) + 5002 (slice-equal? %ecx "<-") # => eax + 5003 3d/compare-eax-and 0/imm32/false + 5004 74/jump-if-= $parse-mu-var-def:abort/disp8 + 5005 # + 5006 (new-reg-var-def Heap %edx) # => eax + 5007 (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc)) + 5008 } + 5009 $parse-mu-var-def:end: + 5010 # . reclaim locals + 5011 81 0/subop/add %esp 8/imm32 + 5012 # . restore registers + 5013 5a/pop-to-edx + 5014 59/pop-to-ecx + 5015 # . epilogue + 5016 89/<- %esp 5/r32/ebp + 5017 5d/pop-to-ebp + 5018 c3/return + 5019 + 5020 $parse-mu-var-def:abort: + 5021 (rewind-stream *(ebp+8)) + 5022 # error("register variable requires a valid instruction to initialize but got '" line "'\n") + 5023 (write-buffered Stderr "register variable requires a valid instruction to initialize but got '") + 5024 (flush Stderr) + 5025 (write-stream 2 *(ebp+8)) + 5026 (write-buffered Stderr "'\n") + 5027 (flush Stderr) + 5028 # . syscall(exit, 1) + 5029 bb/copy-to-ebx 1/imm32 + 5030 b8/copy-to-eax 1/imm32/exit + 5031 cd/syscall 0x80/imm8 + 5032 # never gets here + 5033 + 5034 test-parse-mu-var-def: + 5035 # 'var n: int' + 5036 # . prologue + 5037 55/push-ebp + 5038 89/<- %ebp 4/r32/esp + 5039 # setup + 5040 (clear-stream _test-input-stream) + 5041 (write _test-input-stream "n: int\n") # caller has consumed the 'var' + 5042 # var vars/ecx: (stack (addr var) 4) + 5043 81 5/subop/subtract %esp 0x10/imm32 + 5044 68/push 0x10/imm32/size + 5045 68/push 0/imm32/top + 5046 89/<- %ecx 4/r32/esp + 5047 (clear-stack %ecx) + 5048 # convert + 5049 (parse-mu-var-def _test-input-stream %ecx) # => eax + 5050 # check result + 5051 (check-ints-equal *eax 2 "F - test-parse-mu-var-def/tag") # Stmt-tag is var-def + 5052 8b/-> *(eax+4) 0/r32/eax # Vardef-var + 5053 (check-strings-equal *eax "n" "F - test-parse-mu-var-def/var-name") # Var-name + 5054 (check-ints-equal *(eax+0x10) 0 "F - test-parse-mu-var-def/var-register") # Var-register + 5055 # ensure type is int + 5056 8b/-> *(eax+4) 0/r32/eax # Var-type + 5057 (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0") # Tree-is-atom + 5058 (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1") # Tree-value + 5059 (check-ints-equal *(eax+8) 0 "F - test-parse-mu-var-def/var-type:2") # Tree-right + 5060 # . epilogue + 5061 89/<- %esp 5/r32/ebp + 5062 5d/pop-to-ebp + 5063 c3/return + 5064 + 5065 test-parse-mu-reg-var-def: + 5066 # 'var n/eax: int <- copy 0' + 5067 # . prologue + 5068 55/push-ebp + 5069 89/<- %ebp 4/r32/esp + 5070 # setup + 5071 (clear-stream _test-input-stream) + 5072 (write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var' + 5073 # var vars/ecx: (stack (addr var) 4) + 5074 81 5/subop/subtract %esp 0x10/imm32 + 5075 68/push 0x10/imm32/size + 5076 68/push 0/imm32/top + 5077 89/<- %ecx 4/r32/esp + 5078 (clear-stack %ecx) + 5079 # convert + 5080 (parse-mu-var-def _test-input-stream %ecx) # => eax + 5081 # check result + 5082 (check-ints-equal *eax 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is reg-var-def + 5083 8b/-> *(eax+0xc) 0/r32/eax # Regvardef-outputs + 5084 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/single-output") # List-next + 5085 8b/-> *eax 0/r32/eax # Stmt-var-value + 5086 (check-strings-equal *eax "n" "F - test-parse-mu-reg-var-def/output-name") # Var-name + 5087 (check-strings-equal *(eax+0x10) "eax" "F - test-parse-mu-reg-var-def/output-register") # Var-register + 5088 # ensure type is int + 5089 8b/-> *(eax+4) 0/r32/eax # Var-type + 5090 (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/var-type:0") # Tree-is-atom + 5091 (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-value + 5092 (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-right + 5093 # . epilogue + 5094 89/<- %esp 5/r32/ebp + 5095 5d/pop-to-ebp + 5096 c3/return + 5097 + 5098 parse-mu-stmt: # line: (addr stream byte), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) + 5099 # pseudocode: + 5100 # var name: slice + 5101 # result = allocate(Heap, Stmt-size) + 5102 # if stmt-has-outputs?(line) + 5103 # while true + 5104 # name = next-mu-token(line) + 5105 # if (name == '<-') break + 5106 # assert(is-identifier?(name)) + 5107 # var v: (handle var) = lookup-or-define-var(name, vars, fn) # regular stmts may define vars in fn outputs + 5108 # result->outputs = append(result->outputs, v) + 5109 # add-operation-and-inputs-to-stmt(result, line, vars) + 5110 # + 5111 # . prologue + 5112 55/push-ebp + 5113 89/<- %ebp 4/r32/esp + 5114 # . save registers + 5115 51/push-ecx + 5116 52/push-edx + 5117 57/push-edi + 5118 # var name/ecx: slice + 5119 68/push 0/imm32/end + 5120 68/push 0/imm32/start + 5121 89/<- %ecx 4/r32/esp + 5122 # var is-deref?/edx: boolean = false + 5123 ba/copy-to-edx 0/imm32/false + 5124 # result/edi: (handle stmt) + 5125 (allocate Heap *Stmt-size) # => eax + 5126 89/<- %edi 0/r32/eax + 5127 # result->tag = 1/stmt + 5128 c7 0/subop/copy *edi 1/imm32/stmt1 # Stmt-tag + 5129 { + 5130 (stmt-has-outputs? *(ebp+8)) + 5131 3d/compare-eax-and 0/imm32/false + 5132 0f 84/jump-if-= break/disp32 + 5133 { + 5134 $parse-mu-stmt:read-outputs: + 5135 # name = next-mu-token(line) + 5136 (next-mu-token *(ebp+8) %ecx) + 5137 # if slice-empty?(word-slice) break + 5138 (slice-empty? %ecx) # => eax + 5139 3d/compare-eax-and 0/imm32/false + 5140 0f 85/jump-if-!= break/disp32 + 5141 # if (name == "<-") break + 5142 (slice-equal? %ecx "<-") # => eax + 5143 3d/compare-eax-and 0/imm32/false + 5144 0f 85/jump-if-!= break/disp32 + 5145 # is-deref? = false + 5146 ba/copy-to-edx 0/imm32/false + 5147 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? + 5148 8b/-> *ecx 0/r32/eax # Slice-start + 5149 8a/copy-byte *eax 0/r32/AL + 5150 81 4/subop/and %eax 0xff/imm32 + 5151 3d/compare-eax-and 0x2a/imm32/asterisk + 5152 { + 5153 75/jump-if-!= break/disp8 + 5154 ff 0/subop/increment *ecx + 5155 ba/copy-to-edx 1/imm32/true + 5156 } + 5157 # assert(is-identifier?(name)) + 5158 (is-identifier? %ecx) # => eax + 5159 3d/compare-eax-and 0/imm32/false + 5160 0f 84/jump-if-= $parse-mu-stmt:abort/disp32 + 5161 # result->outputs = new stmt-var(lookup(name, vars, fn), result->outputs, is-deref?) + 5162 (lookup-or-define-var %ecx *(ebp+0xc) *(ebp+0x10)) # => eax + 5163 (append-stmt-var Heap %eax *(edi+0xc) %edx) # Stmt1-outputs => eax + 5164 89/<- *(edi+0xc) 0/r32/eax # Stmt1-outputs + 5165 e9/jump loop/disp32 + 5166 } + 5167 } + 5168 (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc)) + 5169 $parse-mu-stmt:end: + 5170 # return result + 5171 89/<- %eax 7/r32/edi + 5172 # . reclaim locals + 5173 81 0/subop/add %esp 8/imm32 + 5174 # . restore registers + 5175 5f/pop-to-edi + 5176 5a/pop-to-edx + 5177 59/pop-to-ecx + 5178 # . epilogue + 5179 89/<- %esp 5/r32/ebp + 5180 5d/pop-to-ebp + 5181 c3/return + 5182 + 5183 $parse-mu-stmt:abort: + 5184 # error("invalid identifier '" name "'\n") + 5185 (write-buffered Stderr "invalid identifier '") + 5186 (write-slice-buffered Stderr %ecx) + 5187 (write-buffered Stderr "'\n") + 5188 (flush Stderr) + 5189 # . syscall(exit, 1) + 5190 bb/copy-to-ebx 1/imm32 + 5191 b8/copy-to-eax 1/imm32/exit + 5192 cd/syscall 0x80/imm8 + 5193 # never gets here 5194 - 5195 $lookup-var:abort: - 5196 (write-buffered Stderr "unknown variable '") - 5197 (write-slice-buffered Stderr *(ebp+8)) - 5198 (write-buffered Stderr "'\n") - 5199 (flush Stderr) - 5200 # . syscall(exit, 1) - 5201 bb/copy-to-ebx 1/imm32 - 5202 b8/copy-to-eax 1/imm32/exit - 5203 cd/syscall 0x80/imm8 - 5204 # never gets here - 5205 - 5206 # return first 'name' from the top (back) of 'vars', and 0/null if not found - 5207 lookup-var-helper: # name: (addr array byte), vars: (addr stack (handle var)) -> result/eax: (handle var) - 5208 # pseudocode: - 5209 # var curr: (addr handle var) = &vars->data[vars->top - 4] - 5210 # var min = vars->data - 5211 # while curr >= min - 5212 # var v: (handle var) = *curr - 5213 # if v->name == name - 5214 # return v - 5215 # return 0 - 5216 # - 5217 # . prologue - 5218 55/push-ebp - 5219 89/<- %ebp 4/r32/esp - 5220 # . save registers - 5221 52/push-edx - 5222 53/push-ebx - 5223 56/push-esi - 5224 # esi = vars - 5225 8b/-> *(ebp+0xc) 6/r32/esi - 5226 # ebx = vars->top - 5227 8b/-> *esi 3/r32/ebx - 5228 # if (vars->top > vars->length) abort - 5229 3b/compare 0/r32/eax *(esi+4) - 5230 0f 8f/jump-if-> $lookup-var-helper:error1/disp32 - 5231 # var min/edx: (addr handle var) = vars->data - 5232 8d/copy-address *(esi+8) 2/r32/edx - 5233 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 4] - 5234 81 5/subop/subtract %ebx 4/imm32 - 5235 8d/copy-address *(esi+ebx+8) 3/r32/ebx - 5236 { - 5237 # if (curr < min) return 0 - 5238 39/compare %ebx 2/r32/edx - 5239 b8/copy-to-eax 0/imm32 - 5240 0f 82/jump-if-addr< break/disp32 - 5241 # var v/eax: (handle var) = *curr - 5242 8b/-> *ebx 0/r32/eax - 5243 # if (v->name == name) return v - 5244 (string-equal? *eax *(ebp+8)) # Var-name - 5245 3d/compare-eax-and 0/imm32/false - 5246 8b/-> *ebx 0/r32/eax - 5247 75/jump-if-!= break/disp8 - 5248 # curr -= 4 - 5249 81 5/subop/subtract %ebx 4/imm32 - 5250 e9/jump loop/disp32 - 5251 } - 5252 $lookup-var-helper:end: - 5253 # . restore registers - 5254 5e/pop-to-esi - 5255 5b/pop-to-ebx - 5256 5a/pop-to-edx - 5257 # . epilogue - 5258 89/<- %esp 5/r32/ebp - 5259 5d/pop-to-ebp - 5260 c3/return - 5261 - 5262 $lookup-var-helper:error1: - 5263 (write-buffered Stderr "malformed stack when looking up '") - 5264 (write-slice-buffered Stderr *(ebp+8)) - 5265 (write-buffered Stderr "'\n") - 5266 (flush Stderr) - 5267 # . syscall(exit, 1) - 5268 bb/copy-to-ebx 1/imm32 - 5269 b8/copy-to-eax 1/imm32/exit - 5270 cd/syscall 0x80/imm8 - 5271 # never gets here - 5272 - 5273 # return first 'name' from the top (back) of 'vars' and create a new var for a fn output if not found - 5274 lookup-or-define-var: # name: (addr slice), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle var) - 5275 # . prologue - 5276 55/push-ebp - 5277 89/<- %ebp 4/r32/esp - 5278 # . save registers - 5279 51/push-ecx - 5280 # var target/ecx: (handle array byte) = slice-to-string(name) - 5281 (slice-to-string Heap *(ebp+8)) # => eax - 5282 89/<- %ecx 0/r32/eax - 5283 # - 5284 (lookup-var-helper %ecx *(ebp+0xc)) # => eax - 5285 { - 5286 # if (result != 0) return - 5287 3d/compare-eax-and 0/imm32 - 5288 75/jump-if-!= break/disp8 - 5289 # if name is one of fn's outputs, return it - 5290 { - 5291 (find-in-function-outputs *(ebp+0x10) %ecx) # => eax - 5292 3d/compare-eax-and 0/imm32 - 5293 # otherwise abort - 5294 0f 84/jump-if-!= $lookup-var:abort/disp32 - 5295 } - 5296 } - 5297 $lookup-or-define-var:end: - 5298 # . restore registers - 5299 59/pop-to-ecx - 5300 # . epilogue - 5301 89/<- %esp 5/r32/ebp - 5302 5d/pop-to-ebp - 5303 c3/return - 5304 - 5305 find-in-function-outputs: # fn: (handle function), name: (handle array byte) -> result/eax: (handle var) - 5306 # . prologue - 5307 55/push-ebp - 5308 89/<- %ebp 4/r32/esp - 5309 # . save registers - 5310 51/push-ecx - 5311 # var curr/ecx: (handle list var) = fn->outputs - 5312 8b/-> *(ebp+8) 1/r32/ecx - 5313 8b/-> *(ecx+0xc) 1/r32/ecx - 5314 # while curr != null - 5315 { - 5316 81 7/subop/compare %ecx 0/imm32 - 5317 74/jump-if-= break/disp8 - 5318 # var v: (handle var) = *curr - 5319 8b/-> *ecx 0/r32/eax # List-value - 5320 # if (curr->name == name) return curr - 5321 50/push-eax - 5322 (string-equal? *eax *(ebp+0xc)) - 5323 3d/compare-eax-and 0/imm32/false - 5324 58/pop-to-eax - 5325 75/jump-if-!= $find-in-function-outputs:end/disp8 - 5326 # curr = curr->next - 5327 8b/-> *(ecx+4) 1/r32/ecx # List-next - 5328 eb/jump loop/disp8 - 5329 } - 5330 b8/copy-to-eax 0/imm32 - 5331 $find-in-function-outputs:end: - 5332 # . restore registers - 5333 59/pop-to-ecx - 5334 # . epilogue - 5335 89/<- %esp 5/r32/ebp - 5336 5d/pop-to-ebp - 5337 c3/return - 5338 - 5339 test-parse-mu-stmt: - 5340 # . prologue - 5341 55/push-ebp - 5342 89/<- %ebp 4/r32/esp - 5343 # setup - 5344 (clear-stream _test-input-stream) - 5345 (write _test-input-stream "increment n\n") - 5346 # var vars/ecx: (stack (addr var) 4) - 5347 81 5/subop/subtract %esp 0x10/imm32 - 5348 68/push 0x10/imm32/length - 5349 68/push 0/imm32/top - 5350 89/<- %ecx 4/r32/esp - 5351 (clear-stack %ecx) - 5352 # var v/edx: var - 5353 81 5/subop/subtract %esp 0x14/imm32 # Var-size - 5354 89/<- %edx 4/r32/esp - 5355 (zero-out %edx 0x14) # Var-size - 5356 # v->name = "n" - 5357 c7 0/subop/copy *edx "n"/imm32 # Var-name - 5358 # - 5359 (push %ecx %edx) - 5360 # convert - 5361 (parse-mu-stmt _test-input-stream %ecx) # => eax - 5362 # check result - 5363 (check-ints-equal *eax 1 "F - test-parse-mu-stmt/tag") # Stmt-tag is Stmt1 - 5364 (check-strings-equal *(eax+4) "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation - 5365 # edx: (handle list var) = result->inouts - 5366 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts - 5367 # ebx: (handle var) = result->inouts->value - 5368 8b/-> *edx 3/r32/ebx # Stmt-var-value - 5369 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt/inout:0") # Var-name - 5370 # . epilogue - 5371 89/<- %esp 5/r32/ebp - 5372 5d/pop-to-ebp - 5373 c3/return - 5374 - 5375 test-parse-mu-stmt-with-comma: - 5376 # . prologue - 5377 55/push-ebp - 5378 89/<- %ebp 4/r32/esp - 5379 # setup - 5380 (clear-stream _test-input-stream) - 5381 (write _test-input-stream "copy-to n, 3\n") - 5382 # var vars/ecx: (stack (addr var) 4) - 5383 81 5/subop/subtract %esp 0x10/imm32 - 5384 68/push 0x10/imm32/length - 5385 68/push 0/imm32/top - 5386 89/<- %ecx 4/r32/esp - 5387 (clear-stack %ecx) - 5388 # var v/edx: var - 5389 81 5/subop/subtract %esp 0x14/imm32 # Var-size - 5390 89/<- %edx 4/r32/esp - 5391 (zero-out %edx 0x14) # Var-size - 5392 # v->name = "n" - 5393 c7 0/subop/copy *edx "n"/imm32 # Var-name - 5394 # - 5395 (push %ecx %edx) - 5396 # convert - 5397 (parse-mu-stmt _test-input-stream %ecx) # => eax - 5398 # check result - 5399 (check-ints-equal *eax 1 "F - test-parse-mu-stmt-with-comma/tag") # Stmt-tag is Stmt1 - 5400 (check-strings-equal *(eax+4) "copy-to" "F - test-parse-mu-stmt-with-comma/name") # Stmt1-operation - 5401 # edx: (handle list var) = result->inouts - 5402 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts - 5403 # ebx: (handle var) = result->inouts->value - 5404 8b/-> *edx 3/r32/ebx # Stmt-var-value - 5405 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt-with-comma/inout:0") # Var-name - 5406 # . epilogue - 5407 89/<- %esp 5/r32/ebp - 5408 5d/pop-to-ebp - 5409 c3/return - 5410 - 5411 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) - 5412 # . prologue - 5413 55/push-ebp - 5414 89/<- %ebp 4/r32/esp - 5415 # . save registers - 5416 51/push-ecx - 5417 # - 5418 (allocate *(ebp+8) *Function-size) # => eax - 5419 8b/-> *(ebp+0xc) 1/r32/ecx - 5420 89/<- *eax 1/r32/ecx # Function-name - 5421 8b/-> *(ebp+0x10) 1/r32/ecx - 5422 89/<- *(eax+4) 1/r32/ecx # Function-subx-name - 5423 8b/-> *(ebp+0x14) 1/r32/ecx - 5424 89/<- *(eax+8) 1/r32/ecx # Function-inouts - 5425 8b/-> *(ebp+0x18) 1/r32/ecx - 5426 89/<- *(eax+0xc) 1/r32/ecx # Function-outputs - 5427 8b/-> *(ebp+0x1c) 1/r32/ecx - 5428 89/<- *(eax+0x10) 1/r32/ecx # Function-body - 5429 8b/-> *(ebp+0x20) 1/r32/ecx - 5430 89/<- *(eax+0x14) 1/r32/ecx # Function-next - 5431 $new-function:end: - 5432 # . restore registers - 5433 59/pop-to-ecx - 5434 # . epilogue - 5435 89/<- %esp 5/r32/ebp - 5436 5d/pop-to-ebp - 5437 c3/return - 5438 - 5439 new-var: # ad: (addr allocation-descriptor), name: (addr array byte) -> result/eax: (handle var) - 5440 # . prologue - 5441 55/push-ebp - 5442 89/<- %ebp 4/r32/esp - 5443 # . save registers - 5444 51/push-ecx - 5445 # - 5446 (allocate *(ebp+8) *Var-size) # => eax - 5447 (zero-out %eax *Var-size) - 5448 8b/-> *(ebp+0xc) 1/r32/ecx - 5449 89/<- *eax 1/r32/ecx # Var-name - 5450 $new-var:end: - 5451 # . restore registers - 5452 59/pop-to-ecx - 5453 # . epilogue - 5454 89/<- %esp 5/r32/ebp - 5455 5d/pop-to-ebp - 5456 c3/return - 5457 - 5458 new-literal-integer: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) - 5459 # . prologue - 5460 55/push-ebp - 5461 89/<- %ebp 4/r32/esp - 5462 # . save registers - 5463 51/push-ecx - 5464 # if (!is-hex-int?(name)) abort - 5465 (is-hex-int? *(ebp+0xc)) # => eax - 5466 3d/compare-eax-and 0/imm32/false - 5467 0f 84/jump-if-= $new-literal-integer:abort/disp32 - 5468 # var type/ecx: (handle tree type-id) = new type() - 5469 (allocate *(ebp+8) *Tree-size) # => eax - 5470 (zero-out %eax *Tree-size) # default type is 'literal' - 5471 89/<- %ecx 0/r32/eax - 5472 # result = new var(s) - 5473 (new-var-from-slice *(ebp+8) *(ebp+0xc)) # => eax - 5474 89/<- *(eax+4) 1/r32/ecx - 5475 $new-literal-integer:end: - 5476 # . restore registers - 5477 59/pop-to-ecx - 5478 # . epilogue - 5479 89/<- %esp 5/r32/ebp - 5480 5d/pop-to-ebp - 5481 c3/return - 5482 - 5483 $new-literal-integer:abort: - 5484 (write-buffered Stderr "variable cannot begin with a digit '") - 5485 (write-slice-buffered Stderr *(ebp+0xc)) - 5486 (write-buffered Stderr "'\n") - 5487 (flush Stderr) - 5488 # . syscall(exit, 1) - 5489 bb/copy-to-ebx 1/imm32 - 5490 b8/copy-to-eax 1/imm32/exit - 5491 cd/syscall 0x80/imm8 - 5492 # never gets here - 5493 - 5494 new-literal: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) - 5495 # . prologue - 5496 55/push-ebp - 5497 89/<- %ebp 4/r32/esp - 5498 # . save registers - 5499 51/push-ecx - 5500 52/push-edx - 5501 # var s/ecx: (addr array byte) - 5502 (slice-to-string Heap *(ebp+0xc)) # => eax - 5503 89/<- %ecx 0/r32/eax - 5504 # type = new type() - 5505 (allocate *(ebp+8) *Tree-size) # => eax - 5506 (zero-out %eax *Tree-size) # default type is 'literal' - 5507 89/<- %edx 0/r32/eax - 5508 # eax = result - 5509 (new-var *(ebp+8) %ecx) # => eax - 5510 # result->type = type - 5511 89/<- *(eax+4) 2/r32/edx # Var-type - 5512 $new-literal:end: - 5513 # . restore registers - 5514 5a/pop-to-edx - 5515 59/pop-to-ecx - 5516 # . epilogue - 5517 89/<- %esp 5/r32/ebp - 5518 5d/pop-to-ebp - 5519 c3/return - 5520 - 5521 new-var-from-slice: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) - 5522 # . prologue - 5523 55/push-ebp - 5524 89/<- %ebp 4/r32/esp - 5525 # . save registers - 5526 51/push-ecx - 5527 # result = new-var(slice-to-string(name)) - 5528 (slice-to-string Heap *(ebp+0xc)) # => eax - 5529 (new-var *(ebp+8) %eax) - 5530 $new-var-from-slice:end: - 5531 # . restore registers - 5532 59/pop-to-ecx - 5533 # . epilogue - 5534 89/<- %esp 5/r32/ebp - 5535 5d/pop-to-ebp - 5536 c3/return - 5537 - 5538 new-block: # ad: (addr allocation-descriptor), data: (handle list stmt) -> result/eax: (handle stmt) - 5539 # . prologue - 5540 55/push-ebp - 5541 89/<- %ebp 4/r32/esp - 5542 # . save registers - 5543 51/push-ecx - 5544 # - 5545 (allocate *(ebp+8) *Stmt-size) # => eax - 5546 (zero-out %eax *Stmt-size) - 5547 c7 0/subop/copy *eax 0/imm32/tag/block # Stmt-tag - 5548 8b/-> *(ebp+0xc) 1/r32/ecx - 5549 89/<- *(eax+4) 1/r32/ecx # Block-stmts - 5550 $new-block:end: - 5551 # . restore registers - 5552 59/pop-to-ecx - 5553 # . epilogue - 5554 89/<- %esp 5/r32/ebp - 5555 5d/pop-to-ebp - 5556 c3/return - 5557 - 5558 new-var-def: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle stmt) - 5559 # . prologue - 5560 55/push-ebp - 5561 89/<- %ebp 4/r32/esp - 5562 # . save registers - 5563 51/push-ecx - 5564 # - 5565 (allocate *(ebp+8) *Stmt-size) # => eax - 5566 (zero-out %eax *Stmt-size) - 5567 c7 0/subop/copy *eax 2/imm32/tag/var-on-stack # Stmt-tag - 5568 # result->var = var - 5569 8b/-> *(ebp+0xc) 1/r32/ecx - 5570 89/<- *(eax+4) 1/r32/ecx # Vardef-var - 5571 $new-var-def:end: - 5572 # . restore registers - 5573 59/pop-to-ecx - 5574 # . epilogue - 5575 89/<- %esp 5/r32/ebp - 5576 5d/pop-to-ebp - 5577 c3/return - 5578 - 5579 new-reg-var-def: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle stmt) - 5580 # . prologue - 5581 55/push-ebp - 5582 89/<- %ebp 4/r32/esp - 5583 # . save registers - 5584 51/push-ecx - 5585 57/push-edi - 5586 # ecx = var - 5587 8b/-> *(ebp+0xc) 1/r32/ecx - 5588 # edi = result - 5589 (allocate *(ebp+8) *Stmt-size) # => eax - 5590 89/<- %edi 0/r32/eax - 5591 (zero-out %edi *Stmt-size) - 5592 # set tag - 5593 c7 0/subop/copy *edi 3/imm32/tag/var-in-register # Stmt-tag - 5594 # set output - 5595 (append-stmt-var Heap %ecx *(edi+0xc) 0) # Regvardef-outputs => eax - 5596 89/<- *(edi+0xc) 0/r32/eax # Regvardef-outputs - 5597 $new-reg-var-def:end: - 5598 89/<- %eax 7/r32/edi - 5599 # . restore registers - 5600 5f/pop-to-edi - 5601 59/pop-to-ecx - 5602 # . epilogue - 5603 89/<- %esp 5/r32/ebp - 5604 5d/pop-to-ebp - 5605 c3/return - 5606 - 5607 append-list: # ad: (addr allocation-descriptor), value: _type, list: (handle list _type) -> result/eax: (handle list _type) - 5608 # . prologue - 5609 55/push-ebp - 5610 89/<- %ebp 4/r32/esp - 5611 # . save registers - 5612 51/push-ecx - 5613 # - 5614 (allocate *(ebp+8) *List-size) # => eax - 5615 (zero-out %eax *List-size) - 5616 8b/-> *(ebp+0xc) 1/r32/ecx - 5617 89/<- *eax 1/r32/ecx # List-value - 5618 # if (list == null) return result - 5619 81 7/subop/compare *(ebp+0x10) 0/imm32 - 5620 74/jump-if-= $append-list:end/disp8 - 5621 # otherwise append - 5622 # var curr/ecx = list - 5623 8b/-> *(ebp+0x10) 1/r32/ecx - 5624 # while (curr->next != null) curr = curr->next - 5625 { - 5626 81 7/subop/compare *(ecx+4) 0/imm32 # List-next - 5627 74/jump-if-= break/disp8 - 5628 # curr = curr->next - 5629 8b/-> *(ecx+4) 1/r32/ecx - 5630 eb/jump loop/disp8 - 5631 } - 5632 # curr->next = result - 5633 89/<- *(ecx+4) 0/r32/eax - 5634 # return list - 5635 8b/-> *(ebp+0x10) 0/r32/eax - 5636 $append-list:end: - 5637 # . restore registers - 5638 59/pop-to-ecx - 5639 # . epilogue - 5640 89/<- %esp 5/r32/ebp - 5641 5d/pop-to-ebp - 5642 c3/return - 5643 - 5644 append-stmt-var: # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean -> result/eax: (handle stmt-var) - 5645 # . prologue - 5646 55/push-ebp - 5647 89/<- %ebp 4/r32/esp - 5648 # . save registers - 5649 51/push-ecx - 5650 # - 5651 (allocate *(ebp+8) *Stmt-var-size) # => eax - 5652 (zero-out %eax *Stmt-var-size) - 5653 8b/-> *(ebp+0xc) 1/r32/ecx - 5654 89/<- *eax 1/r32/ecx # Stmt-var-value - 5655 8b/-> *(ebp+0x14) 1/r32/ecx - 5656 89/<- *(eax+8) 1/r32/ecx # Stmt-var-is-deref - 5657 # if (list == null) return result - 5658 81 7/subop/compare *(ebp+0x10) 0/imm32 - 5659 74/jump-if-= $append-stmt-var:end/disp8 - 5660 # otherwise append - 5661 # var curr/ecx: (handle stmt-var) = vars - 5662 8b/-> *(ebp+0x10) 1/r32/ecx - 5663 # while (curr->next != null) curr = curr->next - 5664 { - 5665 81 7/subop/compare *(ecx+4) 0/imm32 # List-next - 5666 74/jump-if-= break/disp8 - 5667 # curr = curr->next - 5668 8b/-> *(ecx+4) 1/r32/ecx - 5669 eb/jump loop/disp8 - 5670 } - 5671 # curr->next = result - 5672 89/<- *(ecx+4) 0/r32/eax - 5673 # return vars - 5674 8b/-> *(ebp+0x10) 0/r32/eax - 5675 $append-stmt-var:end: - 5676 # . restore registers - 5677 59/pop-to-ecx - 5678 # . epilogue - 5679 89/<- %esp 5/r32/ebp - 5680 5d/pop-to-ebp - 5681 c3/return - 5682 - 5683 append-to-block: # ad: (addr allocation-descriptor), block: (handle block), x: (handle stmt) - 5684 # . prologue - 5685 55/push-ebp - 5686 89/<- %ebp 4/r32/esp - 5687 # . save registers - 5688 56/push-esi - 5689 # esi = block - 5690 8b/-> *(ebp+0xc) 6/r32/esi - 5691 (append-list *(ebp+8) *(ebp+0x10) *(esi+4)) # ad, x, Block-stmts - 5692 89/<- *(esi+4) 0/r32/eax # Block-stmts - 5693 $append-to-block:end: - 5694 # . restore registers - 5695 5e/pop-to-esi - 5696 # . epilogue - 5697 89/<- %esp 5/r32/ebp - 5698 5d/pop-to-ebp - 5699 c3/return - 5700 - 5701 ## Parsing types - 5702 # We need to create metadata on user-defined types, and we need to use this - 5703 # metadata as we parse instructions. - 5704 # However, we also want to allow types to be used before their definitions. - 5705 # This means we can't ever assume any type data structures exist. - 5706 - 5707 lookup-or-create-constant: # container: (handle stmt-var), field-name: (addr slice) -> result/eax: (handle var) - 5708 # . prologue - 5709 55/push-ebp - 5710 89/<- %ebp 4/r32/esp - 5711 # . save registers - 5712 56/push-esi - 5713 # var container-type/esi: type-id - 5714 (container-type *(ebp+8)) # => eax - 5715 #? (write-buffered Stderr "lookup-or-create-constant: container type-id: ") - 5716 #? (print-int32-buffered Stderr %eax) - 5717 #? (write-buffered Stderr Newline) - 5718 #? (flush Stderr) - 5719 89/<- %esi 0/r32/eax - 5720 # var typeinfo/eax: (addr typeinfo) - 5721 (find-or-create-typeinfo %esi) # => eax - 5722 #? (write-buffered Stderr "lookup-or-create-constant: typeinfo: ") - 5723 #? (print-int32-buffered Stderr %eax) - 5724 #? (write-buffered Stderr Newline) - 5725 #? (flush Stderr) - 5726 # result = find-or-create-typeinfo-output-var(typeinfo, field-name) - 5727 (find-or-create-typeinfo-output-var %eax *(ebp+0xc)) # => eax - 5728 $lookup-or-create-constant:end: - 5729 # . restore registers - 5730 5e/pop-to-esi - 5731 # . epilogue - 5732 89/<- %esp 5/r32/ebp - 5733 5d/pop-to-ebp - 5734 c3/return - 5735 - 5736 # if addr var: - 5737 # container->var->type->right->left->value - 5738 # otherwise - 5739 # container->var->type->value - 5740 container-type: # container: (handle stmt-var) -> result/eax: type-id - 5741 # . prologue - 5742 55/push-ebp - 5743 89/<- %ebp 4/r32/esp - 5744 # - 5745 8b/-> *(ebp+8) 0/r32/eax - 5746 8b/-> *eax 0/r32/eax # Stmt-var-value - 5747 8b/-> *(eax+4) 0/r32/eax # Var-type - 5748 { - 5749 81 7/subop/compare *(eax+4) 0/imm32 - 5750 74/jump-if-= break/disp8 - 5751 8b/-> *(eax+4) 0/r32/eax # Tree-right - 5752 8b/-> *eax 0/r32/eax # Tree-left - 5753 } - 5754 8b/-> *eax 0/r32/eax # Atom-value - 5755 $container-type:end: - 5756 # . epilogue - 5757 89/<- %esp 5/r32/ebp - 5758 5d/pop-to-ebp - 5759 c3/return - 5760 - 5761 find-or-create-typeinfo: # t: type-id -> result/eax: (handle typeinfo) - 5762 # . prologue - 5763 55/push-ebp - 5764 89/<- %ebp 4/r32/esp - 5765 # . save registers - 5766 51/push-ecx - 5767 # eax = find-typeinfo(t) - 5768 (find-typeinfo *(ebp+8)) # => eax - 5769 { - 5770 # if (curr != 0) break - 5771 3d/compare-eax-and 0/imm32 - 5772 75/jump-if-!= break/disp8 - 5773 $find-or-create-typeinfo:create: - 5774 (allocate Heap *Typeinfo-size) # => eax - 5775 (zero-out %eax *Typeinfo-size) - 5776 # result->id = t - 5777 8b/-> *(ebp+8) 1/r32/ecx - 5778 89/<- *eax 1/r32/ecx # Typeinfo-id - 5779 # result->fields = new table - 5780 # . ecx = new table - 5781 50/push-eax - 5782 (new-stream Heap 0x40 *Typeinfo-fields-row-size) # => eax - 5783 89/<- %ecx 0/r32/eax - 5784 58/pop-to-eax - 5785 # . result->fields = ecx - 5786 89/<- *(eax+4) 1/r32/ecx # Typeinfo-fields - 5787 # result->next = Program->types - 5788 8b/-> *_Program-types 1/r32/ecx - 5789 89/<- *(eax+0xc) 1/r32/ecx # Typeinfo-next - 5790 # Program->types = result - 5791 89/<- *_Program-types 0/r32/eax - 5792 } - 5793 $find-or-create-typeinfo:end: - 5794 # . restore registers - 5795 59/pop-to-ecx - 5796 # . epilogue - 5797 89/<- %esp 5/r32/ebp - 5798 5d/pop-to-ebp - 5799 c3/return - 5800 - 5801 find-typeinfo: # t: type-id -> result/eax: (handle typeinfo) - 5802 # . prologue - 5803 55/push-ebp - 5804 89/<- %ebp 4/r32/esp - 5805 # . save registers - 5806 51/push-ecx - 5807 # ecx = t - 5808 8b/-> *(ebp+8) 1/r32/ecx - 5809 # var curr/eax: (handle typeinfo) = Program->types - 5810 8b/-> *_Program-types 0/r32/eax - 5811 { - 5812 # if (curr == 0) break - 5813 3d/compare-eax-and 0/imm32 - 5814 74/jump-if-= break/disp8 - 5815 # if (curr->id == t) return curr - 5816 39/compare *eax 1/r32/ecx # Typeinfo-id - 5817 0f 84/jump-if-= $find-or-create-typeinfo:end/disp32 - 5818 # curr = curr->next - 5819 8b/-> *(eax+0xc) 0/r32/eax # Typeinfo-next - 5820 # - 5821 eb/jump loop/disp8 - 5822 } - 5823 $find-typeinfo:end: - 5824 # . restore registers - 5825 59/pop-to-ecx - 5826 # . epilogue - 5827 89/<- %esp 5/r32/ebp - 5828 5d/pop-to-ebp - 5829 c3/return - 5830 - 5831 find-or-create-typeinfo-output-var: # T: (handle typeinfo), f: (addr slice) -> result/eax: (handle var) - 5832 # . prologue - 5833 55/push-ebp - 5834 89/<- %ebp 4/r32/esp - 5835 # . save registers - 5836 51/push-ecx - 5837 56/push-esi - 5838 # esi = find-or-create-typeinfo-fields(T, f) - 5839 (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc)) # => eax - 5840 89/<- %esi 0/r32/eax - 5841 # if output var doesn't exist, create it - 5842 { - 5843 81 7/subop/compare *(esi+8) 0/imm32 # Typeinfo-entry-output-var - 5844 75/jump-if-!= break/disp8 - 5845 # var type/eax: (handle tree type-id) = new var("dummy name", constant type, -1 offset) - 5846 (allocate Heap *Tree-size) # => eax - 5847 c7 0/subop/copy *eax 6/imm32/constant # Atom-value - 5848 c7 0/subop/copy *(eax+4) 0/imm32 # Tree-right - 5849 89/<- %ecx 0/r32/eax - 5850 # eax = result - 5851 (new-var Heap "field") # => eax - 5852 # result->type = type - 5853 89/<- *(eax+4) 1/r32/ecx # Var-type - 5854 # result->offset isn't filled out yet - 5855 c7 0/subop/copy *(eax+0xc) -1/imm32/uninitialized # Var-offset - 5856 # save result as output var - 5857 89/<- *(esi+8) 0/r32/eax # Typeinfo-entry-output-var - 5858 } - 5859 # return the output var - 5860 8b/-> *(esi+8) 0/r32/eax # Typeinfo-entry-output-var - 5861 $find-or-create-typeinfo-output-var:end: - 5862 # . restore registers - 5863 5e/pop-to-esi - 5864 59/pop-to-ecx - 5865 # . epilogue - 5866 89/<- %esp 5/r32/ebp - 5867 5d/pop-to-ebp - 5868 c3/return - 5869 - 5870 find-or-create-typeinfo-fields: # T: (handle typeinfo), f: (addr slice) -> result/eax: (handle typeinfo-entry) - 5871 # . prologue - 5872 55/push-ebp - 5873 89/<- %ebp 4/r32/esp - 5874 # . save registers - 5875 56/push-esi - 5876 # esi = T->fields - 5877 8b/-> *(ebp+8) 6/r32/esi - 5878 8b/-> *(esi+4) 6/r32/esi # Typeinfo-fields - 5879 # esi = get-or-insert(T->fields, f) - 5880 (leaky-get-or-insert-slice %esi *(ebp+0xc) *Typeinfo-fields-row-size) # => eax - 5881 89/<- %esi 0/r32/eax - 5882 # if typeinfo-entry doesn't exist, allocate it - 5883 { - 5884 81 7/subop/compare *esi 0/imm32 # output var - 5885 75/jump-if-!= break/disp8 - 5886 (allocate Heap *Typeinfo-entry-size) # => eax - 5887 (zero-out %eax *Typeinfo-entry-size) - 5888 89/<- *esi 0/r32/eax - 5889 } - 5890 # eax = T->fields[f]->entry - 5891 8b/-> *esi 0/r32/eax - 5892 $find-or-create-typeinfo-fields:end: - 5893 # . restore registers - 5894 5e/pop-to-esi - 5895 # . epilogue - 5896 89/<- %esp 5/r32/ebp - 5897 5d/pop-to-ebp - 5898 c3/return - 5899 - 5900 populate-mu-type: # in: (addr stream byte), t: (handle typeinfo) - 5901 # pseudocode: - 5902 # var line: (stream byte 512) - 5903 # curr-index = 0 - 5904 # while true - 5905 # clear-stream(line) - 5906 # read-line-buffered(in, line) - 5907 # if line->write == 0 - 5908 # abort - 5909 # word-slice = next-mu-token(line) - 5910 # if slice-empty?(word-slice) # end of line - 5911 # continue - 5912 # if slice-equal?(word-slice, "}") - 5913 # break - 5914 # var v: (handle var) = parse-var-with-type(word-slice, line) - 5915 # var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name) - 5916 # TODO: ensure that r->first is null - 5917 # r->index = curr-index - 5918 # curr-index++ - 5919 # r->input-var = v - 5920 # if r->output-var == 0 - 5921 # r->output-var = new literal - 5922 # TODO: ensure nothing else in line - 5923 # t->total-size-in-bytes = -2 (not yet initialized) - 5924 # - 5925 # . prologue - 5926 55/push-ebp - 5927 89/<- %ebp 4/r32/esp - 5928 # var curr-index: int at *(ebp-4) - 5929 68/push 0/imm32 - 5930 # . save registers - 5931 50/push-eax - 5932 51/push-ecx - 5933 52/push-edx - 5934 53/push-ebx - 5935 56/push-esi - 5936 57/push-edi - 5937 # edi = t - 5938 8b/-> *(ebp+0xc) 7/r32/edi - 5939 # var line/ecx: (stream byte 512) - 5940 81 5/subop/subtract %esp 0x200/imm32 - 5941 68/push 0x200/imm32/length - 5942 68/push 0/imm32/read - 5943 68/push 0/imm32/write - 5944 89/<- %ecx 4/r32/esp - 5945 # var word-slice/edx: slice - 5946 68/push 0/imm32/end - 5947 68/push 0/imm32/start - 5948 89/<- %edx 4/r32/esp - 5949 { - 5950 $populate-mu-type:line-loop: - 5951 (clear-stream %ecx) - 5952 (read-line-buffered *(ebp+8) %ecx) - 5953 # if (line->write == 0) abort - 5954 81 7/subop/compare *ecx 0/imm32 - 5955 0f 84/jump-if-= $populate-mu-type:abort/disp32 - 5956 +-- 6 lines: #? # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------ - 5962 (next-mu-token %ecx %edx) - 5963 # if slice-empty?(word-slice) continue - 5964 (slice-empty? %edx) # => eax + 5195 add-operation-and-inputs-to-stmt: # stmt: (handle stmt), line: (addr stream byte), vars: (addr stack (handle var)) + 5196 # pseudocode: + 5197 # stmt->name = slice-to-string(next-mu-token(line)) + 5198 # while true + 5199 # name = next-mu-token(line) + 5200 # v = lookup-var-or-literal(name) + 5201 # stmt->inouts = append(stmt->inouts, v) + 5202 # + 5203 # . prologue + 5204 55/push-ebp + 5205 89/<- %ebp 4/r32/esp + 5206 # . save registers + 5207 50/push-eax + 5208 51/push-ecx + 5209 52/push-edx + 5210 53/push-ebx + 5211 57/push-edi + 5212 # edi = stmt + 5213 8b/-> *(ebp+8) 7/r32/edi + 5214 # var name/ecx: slice + 5215 68/push 0/imm32/end + 5216 68/push 0/imm32/start + 5217 89/<- %ecx 4/r32/esp + 5218 # var is-deref?/edx: boolean = false + 5219 ba/copy-to-edx 0/imm32/false + 5220 $add-operation-and-inputs-to-stmt:read-operation: + 5221 (next-mu-token *(ebp+0xc) %ecx) + 5222 (slice-to-string Heap %ecx) # => eax + 5223 89/<- *(edi+4) 0/r32/eax # Stmt1-operation or Regvardef-operation + 5224 # var is-get?/ebx: boolean = (name == "get") + 5225 (slice-equal? %ecx "get") # => eax + 5226 89/<- %ebx 0/r32/eax + 5227 { + 5228 $add-operation-and-inputs-to-stmt:read-inouts: + 5229 # name = next-mu-token(line) + 5230 (next-mu-token *(ebp+0xc) %ecx) + 5231 # if slice-empty?(word-slice) break + 5232 (slice-empty? %ecx) # => eax + 5233 3d/compare-eax-and 0/imm32/false + 5234 0f 85/jump-if-!= break/disp32 + 5235 # if (name == "<-") abort + 5236 (slice-equal? %ecx "<-") + 5237 3d/compare-eax-and 0/imm32/false + 5238 0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32 + 5239 # if (is-get? && second operand) lookup or create offset + 5240 { + 5241 81 7/subop/compare %ebx 0/imm32/false + 5242 74/jump-if-= break/disp8 + 5243 81 7/subop/compare *(edi+8) 0/imm32 # Stmt1-inouts or Regvardef-inouts + 5244 74/jump-if-= break/disp8 + 5245 (lookup-or-create-constant *(edi+8) %ecx) # Stmt1-inouts => eax + 5246 #? (write-buffered Stderr "creating new output var ") + 5247 #? (print-int32-buffered Stderr %eax) + 5248 #? (write-buffered Stderr " for field called ") + 5249 #? (write-slice-buffered Stderr %ecx) + 5250 #? (write-buffered Stderr Newline) + 5251 #? (flush Stderr) + 5252 e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32 + 5253 } + 5254 # is-deref? = false + 5255 ba/copy-to-edx 0/imm32/false + 5256 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? + 5257 8b/-> *ecx 0/r32/eax # Slice-start + 5258 8a/copy-byte *eax 0/r32/AL + 5259 81 4/subop/and %eax 0xff/imm32 + 5260 3d/compare-eax-and 0x2a/imm32/asterisk + 5261 { + 5262 75/jump-if-!= break/disp8 + 5263 $add-operation-and-inputs-to-stmt:inout-is-deref: + 5264 ff 0/subop/increment *ecx + 5265 ba/copy-to-edx 1/imm32/true + 5266 } + 5267 (lookup-var-or-literal %ecx *(ebp+0x10)) # => eax + 5268 $add-operation-and-inputs-to-stmt:save-var: + 5269 (append-stmt-var Heap %eax *(edi+8) %edx) # Stmt1-inouts or Regvardef-inouts => eax + 5270 89/<- *(edi+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts + 5271 e9/jump loop/disp32 + 5272 } + 5273 $add-operation-and-inputs-to-stmt:end: + 5274 # . reclaim locals + 5275 81 0/subop/add %esp 8/imm32 + 5276 # . restore registers + 5277 5f/pop-to-edi + 5278 5b/pop-to-ebx + 5279 5a/pop-to-edx + 5280 59/pop-to-ecx + 5281 58/pop-to-eax + 5282 # . epilogue + 5283 89/<- %esp 5/r32/ebp + 5284 5d/pop-to-ebp + 5285 c3/return + 5286 + 5287 $add-operation-and-inputs-to-stmt:abort: + 5288 # error("invalid statement '" line "'\n") + 5289 (rewind-stream *(ebp+8)) + 5290 (write-buffered Stderr "invalid identifier '") + 5291 (flush Stderr) + 5292 (write-stream 2 *(ebp+8)) + 5293 (write-buffered Stderr "'\n") + 5294 (flush Stderr) + 5295 # . syscall(exit, 1) + 5296 bb/copy-to-ebx 1/imm32 + 5297 b8/copy-to-eax 1/imm32/exit + 5298 cd/syscall 0x80/imm8 + 5299 # never gets here + 5300 + 5301 stmt-has-outputs?: # line: (addr stream byte) -> result/eax: boolean + 5302 # . prologue + 5303 55/push-ebp + 5304 89/<- %ebp 4/r32/esp + 5305 # . save registers + 5306 51/push-ecx + 5307 # var word-slice/ecx: slice + 5308 68/push 0/imm32/end + 5309 68/push 0/imm32/start + 5310 89/<- %ecx 4/r32/esp + 5311 # result = false + 5312 b8/copy-to-eax 0/imm32/false + 5313 (rewind-stream *(ebp+8)) + 5314 { + 5315 (next-mu-token *(ebp+8) %ecx) + 5316 # if slice-empty?(word-slice) break + 5317 (slice-empty? %ecx) + 5318 3d/compare-eax-and 0/imm32/false + 5319 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) + 5320 0f 85/jump-if-!= break/disp32 + 5321 # if slice-starts-with?(word-slice, '#') break + 5322 # . eax = *word-slice->start + 5323 8b/-> *ecx 0/r32/eax + 5324 8a/copy-byte *eax 0/r32/AL + 5325 81 4/subop/and %eax 0xff/imm32 + 5326 # . if (eax == '#') break + 5327 3d/compare-eax-and 0x23/imm32/hash + 5328 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) + 5329 0f 84/jump-if-= break/disp32 + 5330 # if slice-equal?(word-slice, '<-') return true + 5331 (slice-equal? %ecx "<-") + 5332 3d/compare-eax-and 0/imm32/false + 5333 74/jump-if-= loop/disp8 + 5334 b8/copy-to-eax 1/imm32/true + 5335 } + 5336 $stmt-has-outputs:end: + 5337 (rewind-stream *(ebp+8)) + 5338 # . reclaim locals + 5339 81 0/subop/add %esp 8/imm32 + 5340 # . restore registers + 5341 59/pop-to-ecx + 5342 # . epilogue + 5343 89/<- %esp 5/r32/ebp + 5344 5d/pop-to-ebp + 5345 c3/return + 5346 + 5347 # if 'name' starts with a digit, create a new literal var for it + 5348 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found + 5349 lookup-var-or-literal: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) + 5350 # . prologue + 5351 55/push-ebp + 5352 89/<- %ebp 4/r32/esp + 5353 # . save registers + 5354 51/push-ecx + 5355 56/push-esi + 5356 # esi = name + 5357 8b/-> *(ebp+8) 6/r32/esi + 5358 # if slice-empty?(name) abort + 5359 (slice-empty? %esi) # => eax + 5360 3d/compare-eax-and 0/imm32/false + 5361 0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32 + 5362 # var c/ecx: byte = *name->start + 5363 8b/-> *esi 1/r32/ecx + 5364 8a/copy-byte *ecx 1/r32/CL + 5365 81 4/subop/and %ecx 0xff/imm32 + 5366 # if is-decimal-digit?(c) return new var(name) + 5367 { + 5368 (is-decimal-digit? %ecx) # => eax + 5369 3d/compare-eax-and 0/imm32/false + 5370 74/jump-if-= break/disp8 + 5371 (new-literal-integer Heap %esi) # => eax + 5372 eb/jump $lookup-var-or-literal:end/disp8 + 5373 } + 5374 # else if (c == '"') return new var(name) + 5375 { + 5376 81 7/subop/compare %ecx 0x22/imm32/dquote + 5377 75/jump-if-!= break/disp8 + 5378 (new-literal Heap %esi) # => eax + 5379 eb/jump $lookup-var-or-literal:end/disp8 + 5380 } + 5381 # otherwise return lookup-var(name, vars) + 5382 { + 5383 (lookup-var %esi *(ebp+0xc)) # => eax + 5384 } + 5385 $lookup-var-or-literal:end: + 5386 # . restore registers + 5387 5e/pop-to-esi + 5388 59/pop-to-ecx + 5389 # . epilogue + 5390 89/<- %esp 5/r32/ebp + 5391 5d/pop-to-ebp + 5392 c3/return + 5393 + 5394 $lookup-var-or-literal:abort: + 5395 (write-buffered Stderr "empty variable!") + 5396 (flush Stderr) + 5397 # . syscall(exit, 1) + 5398 bb/copy-to-ebx 1/imm32 + 5399 b8/copy-to-eax 1/imm32/exit + 5400 cd/syscall 0x80/imm8 + 5401 # never gets here + 5402 + 5403 # return first 'name' from the top (back) of 'vars' and abort if not found + 5404 lookup-var: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) + 5405 # . prologue + 5406 55/push-ebp + 5407 89/<- %ebp 4/r32/esp + 5408 # var target/eax: (handle array byte) = slice-to-string(name) + 5409 (slice-to-string Heap *(ebp+8)) # => eax + 5410 # + 5411 (lookup-var-helper %eax *(ebp+0xc)) # => eax + 5412 # if (result == 0) abort + 5413 3d/compare-eax-and 0/imm32 + 5414 74/jump-if-= $lookup-var:abort/disp8 + 5415 $lookup-var:end: + 5416 # . epilogue + 5417 89/<- %esp 5/r32/ebp + 5418 5d/pop-to-ebp + 5419 c3/return + 5420 + 5421 $lookup-var:abort: + 5422 (write-buffered Stderr "unknown variable '") + 5423 (write-slice-buffered Stderr *(ebp+8)) + 5424 (write-buffered Stderr "'\n") + 5425 (flush Stderr) + 5426 # . syscall(exit, 1) + 5427 bb/copy-to-ebx 1/imm32 + 5428 b8/copy-to-eax 1/imm32/exit + 5429 cd/syscall 0x80/imm8 + 5430 # never gets here + 5431 + 5432 # return first 'name' from the top (back) of 'vars', and 0/null if not found + 5433 lookup-var-helper: # name: (addr array byte), vars: (addr stack (handle var)) -> result/eax: (handle var) + 5434 # pseudocode: + 5435 # var curr: (addr handle var) = &vars->data[vars->top - 4] + 5436 # var min = vars->data + 5437 # while curr >= min + 5438 # var v: (handle var) = *curr + 5439 # if v->name == name + 5440 # return v + 5441 # return 0 + 5442 # + 5443 # . prologue + 5444 55/push-ebp + 5445 89/<- %ebp 4/r32/esp + 5446 # . save registers + 5447 52/push-edx + 5448 53/push-ebx + 5449 56/push-esi + 5450 # esi = vars + 5451 8b/-> *(ebp+0xc) 6/r32/esi + 5452 # ebx = vars->top + 5453 8b/-> *esi 3/r32/ebx + 5454 # if (vars->top > vars->size) abort + 5455 3b/compare<- *(esi+4) 0/r32/eax + 5456 0f 8f/jump-if-> $lookup-var-helper:error1/disp32 + 5457 # var min/edx: (addr handle var) = vars->data + 5458 8d/copy-address *(esi+8) 2/r32/edx + 5459 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 4] + 5460 81 5/subop/subtract %ebx 4/imm32 + 5461 8d/copy-address *(esi+ebx+8) 3/r32/ebx + 5462 { + 5463 # if (curr < min) return 0 + 5464 39/compare %ebx 2/r32/edx + 5465 b8/copy-to-eax 0/imm32 + 5466 0f 82/jump-if-addr< break/disp32 + 5467 # var v/eax: (handle var) = *curr + 5468 8b/-> *ebx 0/r32/eax + 5469 # if (v->name == name) return v + 5470 (string-equal? *eax *(ebp+8)) # Var-name + 5471 3d/compare-eax-and 0/imm32/false + 5472 8b/-> *ebx 0/r32/eax + 5473 75/jump-if-!= break/disp8 + 5474 # curr -= 4 + 5475 81 5/subop/subtract %ebx 4/imm32 + 5476 e9/jump loop/disp32 + 5477 } + 5478 $lookup-var-helper:end: + 5479 # . restore registers + 5480 5e/pop-to-esi + 5481 5b/pop-to-ebx + 5482 5a/pop-to-edx + 5483 # . epilogue + 5484 89/<- %esp 5/r32/ebp + 5485 5d/pop-to-ebp + 5486 c3/return + 5487 + 5488 $lookup-var-helper:error1: + 5489 (write-buffered Stderr "malformed stack when looking up '") + 5490 (write-slice-buffered Stderr *(ebp+8)) + 5491 (write-buffered Stderr "'\n") + 5492 (flush Stderr) + 5493 # . syscall(exit, 1) + 5494 bb/copy-to-ebx 1/imm32 + 5495 b8/copy-to-eax 1/imm32/exit + 5496 cd/syscall 0x80/imm8 + 5497 # never gets here + 5498 + 5499 # return first 'name' from the top (back) of 'vars' and create a new var for a fn output if not found + 5500 lookup-or-define-var: # name: (addr slice), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle var) + 5501 # . prologue + 5502 55/push-ebp + 5503 89/<- %ebp 4/r32/esp + 5504 # . save registers + 5505 51/push-ecx + 5506 # var target/ecx: (handle array byte) = slice-to-string(name) + 5507 (slice-to-string Heap *(ebp+8)) # => eax + 5508 89/<- %ecx 0/r32/eax + 5509 # + 5510 (lookup-var-helper %ecx *(ebp+0xc)) # => eax + 5511 { + 5512 # if (result != 0) return + 5513 3d/compare-eax-and 0/imm32 + 5514 75/jump-if-!= break/disp8 + 5515 # if name is one of fn's outputs, return it + 5516 { + 5517 (find-in-function-outputs *(ebp+0x10) %ecx) # => eax + 5518 3d/compare-eax-and 0/imm32 + 5519 # otherwise abort + 5520 0f 84/jump-if-!= $lookup-var:abort/disp32 + 5521 } + 5522 } + 5523 $lookup-or-define-var:end: + 5524 # . restore registers + 5525 59/pop-to-ecx + 5526 # . epilogue + 5527 89/<- %esp 5/r32/ebp + 5528 5d/pop-to-ebp + 5529 c3/return + 5530 + 5531 find-in-function-outputs: # fn: (handle function), name: (handle array byte) -> result/eax: (handle var) + 5532 # . prologue + 5533 55/push-ebp + 5534 89/<- %ebp 4/r32/esp + 5535 # . save registers + 5536 51/push-ecx + 5537 # var curr/ecx: (handle list var) = fn->outputs + 5538 8b/-> *(ebp+8) 1/r32/ecx + 5539 8b/-> *(ecx+0xc) 1/r32/ecx + 5540 # while curr != null + 5541 { + 5542 81 7/subop/compare %ecx 0/imm32 + 5543 74/jump-if-= break/disp8 + 5544 # var v: (handle var) = *curr + 5545 8b/-> *ecx 0/r32/eax # List-value + 5546 # if (curr->name == name) return curr + 5547 50/push-eax + 5548 (string-equal? *eax *(ebp+0xc)) + 5549 3d/compare-eax-and 0/imm32/false + 5550 58/pop-to-eax + 5551 75/jump-if-!= $find-in-function-outputs:end/disp8 + 5552 # curr = curr->next + 5553 8b/-> *(ecx+4) 1/r32/ecx # List-next + 5554 eb/jump loop/disp8 + 5555 } + 5556 b8/copy-to-eax 0/imm32 + 5557 $find-in-function-outputs:end: + 5558 # . restore registers + 5559 59/pop-to-ecx + 5560 # . epilogue + 5561 89/<- %esp 5/r32/ebp + 5562 5d/pop-to-ebp + 5563 c3/return + 5564 + 5565 test-parse-mu-stmt: + 5566 # . prologue + 5567 55/push-ebp + 5568 89/<- %ebp 4/r32/esp + 5569 # setup + 5570 (clear-stream _test-input-stream) + 5571 (write _test-input-stream "increment n\n") + 5572 # var vars/ecx: (stack (addr var) 4) + 5573 81 5/subop/subtract %esp 0x10/imm32 + 5574 68/push 0x10/imm32/size + 5575 68/push 0/imm32/top + 5576 89/<- %ecx 4/r32/esp + 5577 (clear-stack %ecx) + 5578 # var v/edx: var + 5579 81 5/subop/subtract %esp 0x14/imm32 # Var-size + 5580 89/<- %edx 4/r32/esp + 5581 (zero-out %edx 0x14) # Var-size + 5582 # v->name = "n" + 5583 c7 0/subop/copy *edx "n"/imm32 # Var-name + 5584 # + 5585 (push %ecx %edx) + 5586 # convert + 5587 (parse-mu-stmt _test-input-stream %ecx) # => eax + 5588 # check result + 5589 (check-ints-equal *eax 1 "F - test-parse-mu-stmt/tag") # Stmt-tag is Stmt1 + 5590 (check-strings-equal *(eax+4) "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation + 5591 # edx: (handle list var) = result->inouts + 5592 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts + 5593 # ebx: (handle var) = result->inouts->value + 5594 8b/-> *edx 3/r32/ebx # Stmt-var-value + 5595 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt/inout:0") # Var-name + 5596 # . epilogue + 5597 89/<- %esp 5/r32/ebp + 5598 5d/pop-to-ebp + 5599 c3/return + 5600 + 5601 test-parse-mu-stmt-with-comma: + 5602 # . prologue + 5603 55/push-ebp + 5604 89/<- %ebp 4/r32/esp + 5605 # setup + 5606 (clear-stream _test-input-stream) + 5607 (write _test-input-stream "copy-to n, 3\n") + 5608 # var vars/ecx: (stack (addr var) 4) + 5609 81 5/subop/subtract %esp 0x10/imm32 + 5610 68/push 0x10/imm32/size + 5611 68/push 0/imm32/top + 5612 89/<- %ecx 4/r32/esp + 5613 (clear-stack %ecx) + 5614 # var v/edx: var + 5615 81 5/subop/subtract %esp 0x14/imm32 # Var-size + 5616 89/<- %edx 4/r32/esp + 5617 (zero-out %edx 0x14) # Var-size + 5618 # v->name = "n" + 5619 c7 0/subop/copy *edx "n"/imm32 # Var-name + 5620 # + 5621 (push %ecx %edx) + 5622 # convert + 5623 (parse-mu-stmt _test-input-stream %ecx) # => eax + 5624 # check result + 5625 (check-ints-equal *eax 1 "F - test-parse-mu-stmt-with-comma/tag") # Stmt-tag is Stmt1 + 5626 (check-strings-equal *(eax+4) "copy-to" "F - test-parse-mu-stmt-with-comma/name") # Stmt1-operation + 5627 # edx: (handle list var) = result->inouts + 5628 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts + 5629 # ebx: (handle var) = result->inouts->value + 5630 8b/-> *edx 3/r32/ebx # Stmt-var-value + 5631 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt-with-comma/inout:0") # Var-name + 5632 # . epilogue + 5633 89/<- %esp 5/r32/ebp + 5634 5d/pop-to-ebp + 5635 c3/return + 5636 + 5637 new-var: # ad: (addr allocation-descriptor), name: (addr array byte) -> result/eax: (handle var) + 5638 # . prologue + 5639 55/push-ebp + 5640 89/<- %ebp 4/r32/esp + 5641 # . save registers + 5642 51/push-ecx + 5643 # + 5644 (allocate *(ebp+8) *Var-size) # => eax + 5645 8b/-> *(ebp+0xc) 1/r32/ecx + 5646 89/<- *eax 1/r32/ecx # Var-name + 5647 $new-var:end: + 5648 # . restore registers + 5649 59/pop-to-ecx + 5650 # . epilogue + 5651 89/<- %esp 5/r32/ebp + 5652 5d/pop-to-ebp + 5653 c3/return + 5654 + 5655 new-literal-integer: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) + 5656 # . prologue + 5657 55/push-ebp + 5658 89/<- %ebp 4/r32/esp + 5659 # . save registers + 5660 51/push-ecx + 5661 # if (!is-hex-int?(name)) abort + 5662 (is-hex-int? *(ebp+0xc)) # => eax + 5663 3d/compare-eax-and 0/imm32/false + 5664 0f 84/jump-if-= $new-literal-integer:abort/disp32 + 5665 # var type/ecx: (handle tree type-id) = new type() + 5666 (allocate *(ebp+8) *Tree-size) # => eax + 5667 # nothing else to do; default type is 'literal' + 5668 c7 0/subop/copy *eax 1/imm32/true # Tree-is-atom + 5669 89/<- %ecx 0/r32/eax + 5670 # result = new var(s) + 5671 (new-var-from-slice *(ebp+8) *(ebp+0xc)) # => eax + 5672 89/<- *(eax+4) 1/r32/ecx + 5673 $new-literal-integer:end: + 5674 # . restore registers + 5675 59/pop-to-ecx + 5676 # . epilogue + 5677 89/<- %esp 5/r32/ebp + 5678 5d/pop-to-ebp + 5679 c3/return + 5680 + 5681 $new-literal-integer:abort: + 5682 (write-buffered Stderr "variable cannot begin with a digit '") + 5683 (write-slice-buffered Stderr *(ebp+0xc)) + 5684 (write-buffered Stderr "'\n") + 5685 (flush Stderr) + 5686 # . syscall(exit, 1) + 5687 bb/copy-to-ebx 1/imm32 + 5688 b8/copy-to-eax 1/imm32/exit + 5689 cd/syscall 0x80/imm8 + 5690 # never gets here + 5691 + 5692 new-literal: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) + 5693 # . prologue + 5694 55/push-ebp + 5695 89/<- %ebp 4/r32/esp + 5696 # . save registers + 5697 51/push-ecx + 5698 52/push-edx + 5699 # var s/ecx: (addr array byte) + 5700 (slice-to-string Heap *(ebp+0xc)) # => eax + 5701 89/<- %ecx 0/r32/eax + 5702 # type = new type() + 5703 (allocate *(ebp+8) *Tree-size) # => eax + 5704 # nothing else to do; default type is 'literal' + 5705 c7 0/subop/copy *eax 1/imm32/true # Tree-is-atom + 5706 89/<- %edx 0/r32/eax + 5707 # eax = result + 5708 (new-var *(ebp+8) %ecx) # => eax + 5709 # result->type = type + 5710 89/<- *(eax+4) 2/r32/edx # Var-type + 5711 $new-literal:end: + 5712 # . restore registers + 5713 5a/pop-to-edx + 5714 59/pop-to-ecx + 5715 # . epilogue + 5716 89/<- %esp 5/r32/ebp + 5717 5d/pop-to-ebp + 5718 c3/return + 5719 + 5720 new-var-from-slice: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) + 5721 # . prologue + 5722 55/push-ebp + 5723 89/<- %ebp 4/r32/esp + 5724 # . save registers + 5725 51/push-ecx + 5726 # result = new-var(slice-to-string(name)) + 5727 (slice-to-string Heap *(ebp+0xc)) # => eax + 5728 (new-var *(ebp+8) %eax) + 5729 $new-var-from-slice:end: + 5730 # . restore registers + 5731 59/pop-to-ecx + 5732 # . epilogue + 5733 89/<- %esp 5/r32/ebp + 5734 5d/pop-to-ebp + 5735 c3/return + 5736 + 5737 new-block: # ad: (addr allocation-descriptor), data: (handle list stmt) -> result/eax: (handle stmt) + 5738 # . prologue + 5739 55/push-ebp + 5740 89/<- %ebp 4/r32/esp + 5741 # . save registers + 5742 51/push-ecx + 5743 # + 5744 (allocate *(ebp+8) *Stmt-size) # => eax + 5745 c7 0/subop/copy *eax 0/imm32/tag/block # Stmt-tag + 5746 8b/-> *(ebp+0xc) 1/r32/ecx + 5747 89/<- *(eax+4) 1/r32/ecx # Block-stmts + 5748 $new-block:end: + 5749 # . restore registers + 5750 59/pop-to-ecx + 5751 # . epilogue + 5752 89/<- %esp 5/r32/ebp + 5753 5d/pop-to-ebp + 5754 c3/return + 5755 + 5756 new-var-def: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle stmt) + 5757 # . prologue + 5758 55/push-ebp + 5759 89/<- %ebp 4/r32/esp + 5760 # . save registers + 5761 51/push-ecx + 5762 # + 5763 (allocate *(ebp+8) *Stmt-size) # => eax + 5764 c7 0/subop/copy *eax 2/imm32/tag/var-on-stack # Stmt-tag + 5765 # result->var = var + 5766 8b/-> *(ebp+0xc) 1/r32/ecx + 5767 89/<- *(eax+4) 1/r32/ecx # Vardef-var + 5768 $new-var-def:end: + 5769 # . restore registers + 5770 59/pop-to-ecx + 5771 # . epilogue + 5772 89/<- %esp 5/r32/ebp + 5773 5d/pop-to-ebp + 5774 c3/return + 5775 + 5776 new-reg-var-def: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle stmt) + 5777 # . prologue + 5778 55/push-ebp + 5779 89/<- %ebp 4/r32/esp + 5780 # . save registers + 5781 51/push-ecx + 5782 57/push-edi + 5783 # ecx = var + 5784 8b/-> *(ebp+0xc) 1/r32/ecx + 5785 # edi = result + 5786 (allocate *(ebp+8) *Stmt-size) # => eax + 5787 89/<- %edi 0/r32/eax + 5788 # set tag + 5789 c7 0/subop/copy *edi 3/imm32/tag/var-in-register # Stmt-tag + 5790 # set output + 5791 (append-stmt-var Heap %ecx *(edi+0xc) 0) # Regvardef-outputs => eax + 5792 89/<- *(edi+0xc) 0/r32/eax # Regvardef-outputs + 5793 $new-reg-var-def:end: + 5794 89/<- %eax 7/r32/edi + 5795 # . restore registers + 5796 5f/pop-to-edi + 5797 59/pop-to-ecx + 5798 # . epilogue + 5799 89/<- %esp 5/r32/ebp + 5800 5d/pop-to-ebp + 5801 c3/return + 5802 + 5803 append-list: # ad: (addr allocation-descriptor), value: _type, list: (handle list _type) -> result/eax: (handle list _type) + 5804 # . prologue + 5805 55/push-ebp + 5806 89/<- %ebp 4/r32/esp + 5807 # . save registers + 5808 51/push-ecx + 5809 # + 5810 (allocate *(ebp+8) *List-size) # => eax + 5811 8b/-> *(ebp+0xc) 1/r32/ecx + 5812 89/<- *eax 1/r32/ecx # List-value + 5813 # if (list == null) return result + 5814 81 7/subop/compare *(ebp+0x10) 0/imm32 + 5815 74/jump-if-= $append-list:end/disp8 + 5816 # otherwise append + 5817 # var curr/ecx = list + 5818 8b/-> *(ebp+0x10) 1/r32/ecx + 5819 # while (curr->next != null) curr = curr->next + 5820 { + 5821 81 7/subop/compare *(ecx+4) 0/imm32 # List-next + 5822 74/jump-if-= break/disp8 + 5823 # curr = curr->next + 5824 8b/-> *(ecx+4) 1/r32/ecx + 5825 eb/jump loop/disp8 + 5826 } + 5827 # curr->next = result + 5828 89/<- *(ecx+4) 0/r32/eax + 5829 # return list + 5830 8b/-> *(ebp+0x10) 0/r32/eax + 5831 $append-list:end: + 5832 # . restore registers + 5833 59/pop-to-ecx + 5834 # . epilogue + 5835 89/<- %esp 5/r32/ebp + 5836 5d/pop-to-ebp + 5837 c3/return + 5838 + 5839 append-stmt-var: # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean -> result/eax: (handle stmt-var) + 5840 # . prologue + 5841 55/push-ebp + 5842 89/<- %ebp 4/r32/esp + 5843 # . save registers + 5844 51/push-ecx + 5845 # + 5846 (allocate *(ebp+8) *Stmt-var-size) # => eax + 5847 8b/-> *(ebp+0xc) 1/r32/ecx + 5848 89/<- *eax 1/r32/ecx # Stmt-var-value + 5849 8b/-> *(ebp+0x14) 1/r32/ecx + 5850 89/<- *(eax+8) 1/r32/ecx # Stmt-var-is-deref + 5851 # if (list == null) return result + 5852 81 7/subop/compare *(ebp+0x10) 0/imm32 + 5853 74/jump-if-= $append-stmt-var:end/disp8 + 5854 # otherwise append + 5855 # var curr/ecx: (handle stmt-var) = vars + 5856 8b/-> *(ebp+0x10) 1/r32/ecx + 5857 # while (curr->next != null) curr = curr->next + 5858 { + 5859 81 7/subop/compare *(ecx+4) 0/imm32 # List-next + 5860 74/jump-if-= break/disp8 + 5861 # curr = curr->next + 5862 8b/-> *(ecx+4) 1/r32/ecx + 5863 eb/jump loop/disp8 + 5864 } + 5865 # curr->next = result + 5866 89/<- *(ecx+4) 0/r32/eax + 5867 # return vars + 5868 8b/-> *(ebp+0x10) 0/r32/eax + 5869 $append-stmt-var:end: + 5870 # . restore registers + 5871 59/pop-to-ecx + 5872 # . epilogue + 5873 89/<- %esp 5/r32/ebp + 5874 5d/pop-to-ebp + 5875 c3/return + 5876 + 5877 append-to-block: # ad: (addr allocation-descriptor), block: (handle block), x: (handle stmt) + 5878 # . prologue + 5879 55/push-ebp + 5880 89/<- %ebp 4/r32/esp + 5881 # . save registers + 5882 56/push-esi + 5883 # esi = block + 5884 8b/-> *(ebp+0xc) 6/r32/esi + 5885 (append-list *(ebp+8) *(ebp+0x10) *(esi+4)) # ad, x, Block-stmts + 5886 89/<- *(esi+4) 0/r32/eax # Block-stmts + 5887 $append-to-block:end: + 5888 # . restore registers + 5889 5e/pop-to-esi + 5890 # . epilogue + 5891 89/<- %esp 5/r32/ebp + 5892 5d/pop-to-ebp + 5893 c3/return + 5894 + 5895 ## Parsing types + 5896 # We need to create metadata on user-defined types, and we need to use this + 5897 # metadata as we parse instructions. + 5898 # However, we also want to allow types to be used before their definitions. + 5899 # This means we can't ever assume any type data structures exist. + 5900 + 5901 lookup-or-create-constant: # container: (handle stmt-var), field-name: (addr slice) -> result/eax: (handle var) + 5902 # . prologue + 5903 55/push-ebp + 5904 89/<- %ebp 4/r32/esp + 5905 # . save registers + 5906 56/push-esi + 5907 # var container-type/esi: type-id + 5908 (container-type *(ebp+8)) # => eax + 5909 #? (write-buffered Stderr "lookup-or-create-constant: container type-id: ") + 5910 #? (print-int32-buffered Stderr %eax) + 5911 #? (write-buffered Stderr Newline) + 5912 #? (flush Stderr) + 5913 89/<- %esi 0/r32/eax + 5914 # var typeinfo/eax: (addr typeinfo) + 5915 (find-or-create-typeinfo %esi) # => eax + 5916 #? (write-buffered Stderr "lookup-or-create-constant: typeinfo: ") + 5917 #? (print-int32-buffered Stderr %eax) + 5918 #? (write-buffered Stderr Newline) + 5919 #? (flush Stderr) + 5920 # result = find-or-create-typeinfo-output-var(typeinfo, field-name) + 5921 (find-or-create-typeinfo-output-var %eax *(ebp+0xc)) # => eax + 5922 $lookup-or-create-constant:end: + 5923 # . restore registers + 5924 5e/pop-to-esi + 5925 # . epilogue + 5926 89/<- %esp 5/r32/ebp + 5927 5d/pop-to-ebp + 5928 c3/return + 5929 + 5930 # if addr var: + 5931 # container->var->type->right->left->value + 5932 # otherwise + 5933 # container->var->type->value + 5934 container-type: # container: (handle stmt-var) -> result/eax: type-id + 5935 # . prologue + 5936 55/push-ebp + 5937 89/<- %ebp 4/r32/esp + 5938 # + 5939 8b/-> *(ebp+8) 0/r32/eax + 5940 8b/-> *eax 0/r32/eax # Stmt-var-value + 5941 8b/-> *(eax+4) 0/r32/eax # Var-type + 5942 { + 5943 81 7/subop/compare *(eax+8) 0/imm32 # Tree-right + 5944 74/jump-if-= break/disp8 + 5945 8b/-> *(eax+8) 0/r32/eax # Tree-right + 5946 8b/-> *(eax+4) 0/r32/eax # Tree-left + 5947 } + 5948 8b/-> *(eax+4) 0/r32/eax # Tree-value + 5949 $container-type:end: + 5950 # . epilogue + 5951 89/<- %esp 5/r32/ebp + 5952 5d/pop-to-ebp + 5953 c3/return + 5954 + 5955 find-or-create-typeinfo: # t: type-id -> result/eax: (handle typeinfo) + 5956 # . prologue + 5957 55/push-ebp + 5958 89/<- %ebp 4/r32/esp + 5959 # . save registers + 5960 51/push-ecx + 5961 # eax = find-typeinfo(t) + 5962 (find-typeinfo *(ebp+8)) # => eax + 5963 { + 5964 # if (curr != 0) break 5965 3d/compare-eax-and 0/imm32 - 5966 0f 85/jump-if-!= loop/disp32 - 5967 # if slice-equal?(word-slice, "}") break - 5968 (slice-equal? %edx "}") - 5969 3d/compare-eax-and 0/imm32 - 5970 0f 85/jump-if-!= break/disp32 - 5971 $populate-mu-type:parse-element: - 5972 # var v/esi: (handle var) = parse-var-with-type(word-slice, first-line) - 5973 (parse-var-with-type %edx %ecx) # => eax - 5974 89/<- %esi 0/r32/eax - 5975 $populate-mu-type:create-typeinfo-fields: - 5976 # var r/ebx: (handle typeinfo-entry) - 5977 (find-or-create-typeinfo-fields %edi %edx) # => eax - 5978 89/<- %ebx 0/r32/eax - 5979 #? (write-buffered Stderr "var ") - 5980 #? (write-buffered Stderr *esi) # Var-name - 5981 #? (write-buffered Stderr " is at index ") - 5982 #? (print-int32-buffered Stderr *(ebp-4)) - 5983 #? (write-buffered Stderr Newline) - 5984 #? (flush Stderr) - 5985 # r->index = curr-index - 5986 8b/-> *(ebp-4) 0/r32/eax - 5987 89/<- *(ebx+4) 0/r32/eax # Typeinfo-entry-index - 5988 # ++curr-index - 5989 ff 0/subop/increment *(ebp-4) - 5990 $populate-mu-type:set-input-type: - 5991 # r->input-var = v - 5992 89/<- *ebx 6/r32/esi # Typeinfo-entry-input-var - 5993 { - 5994 $populate-mu-type:create-output-type: - 5995 # if (r->output-var == 0) create a new var with some placeholder data - 5996 81 7/subop/compare *(ebx+8) 0/imm32 # Typeinfo-entry-output-var - 5997 75/jump-if-!= break/disp8 - 5998 (new-literal Heap %edx) # => eax - 5999 89/<- *(ebx+8) 0/r32/eax # Typeinfo-entry-output-var - 6000 } - 6001 e9/jump loop/disp32 - 6002 } - 6003 $populate-mu-type:invalidate-total-size-in-bytes: - 6004 # Offsets and total size may not be accurate here since we may not yet - 6005 # have encountered the element types. - 6006 # We'll recompute them separately after parsing the entire program. - 6007 c7 0/subop/copy *(edi+8) -2/imm32/uninitialized # Typeinfo-total-size-in-bytes - 6008 $populate-mu-type:end: - 6009 # . reclaim locals - 6010 81 0/subop/add %esp 0x214/imm32 - 6011 # . restore registers - 6012 5f/pop-to-edi - 6013 5e/pop-to-esi - 6014 5b/pop-to-ebx - 6015 5a/pop-to-edx - 6016 59/pop-to-ecx - 6017 58/pop-to-eax - 6018 # reclaim curr-index - 6019 81 0/subop/add %esp 4/imm32 - 6020 # . epilogue - 6021 89/<- %esp 5/r32/ebp - 6022 5d/pop-to-ebp - 6023 c3/return - 6024 - 6025 $populate-mu-type:abort: - 6026 # error("unexpected top-level command: " word-slice "\n") - 6027 (write-buffered Stderr "incomplete type definition '") - 6028 (type-name *edi) # Typeinfo-id => eax - 6029 (write-buffered Stderr %eax) - 6030 (write-buffered Stderr "\n") - 6031 (flush Stderr) - 6032 # . syscall(exit, 1) - 6033 bb/copy-to-ebx 1/imm32 - 6034 b8/copy-to-eax 1/imm32/exit - 6035 cd/syscall 0x80/imm8 - 6036 # never gets here - 6037 - 6038 type-name: # index: int -> result/eax: (addr array byte) - 6039 # . prologue - 6040 55/push-ebp - 6041 89/<- %ebp 4/r32/esp - 6042 # - 6043 (index Type-id *(ebp+8)) - 6044 $type-name:end: - 6045 # . epilogue - 6046 89/<- %esp 5/r32/ebp - 6047 5d/pop-to-ebp - 6048 c3/return - 6049 - 6050 index: # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte) - 6051 # . prologue - 6052 55/push-ebp - 6053 89/<- %ebp 4/r32/esp - 6054 # . save registers - 6055 56/push-esi - 6056 # TODO: bounds-check index - 6057 # esi = arr - 6058 8b/-> *(ebp+8) 6/r32/esi - 6059 # eax = index - 6060 8b/-> *(ebp+0xc) 0/r32/eax - 6061 # eax = *(arr + 12 + index) - 6062 8b/-> *(esi+eax+0xc) 0/r32/eax - 6063 $index:end: - 6064 # . restore registers - 6065 5e/pop-to-esi - 6066 # . epilogue - 6067 89/<- %esp 5/r32/ebp - 6068 5d/pop-to-ebp - 6069 c3/return - 6070 - 6071 ####################################################### - 6072 # Compute type sizes - 6073 ####################################################### - 6074 - 6075 # Compute the sizes of all user-defined types. - 6076 # We'll need the sizes of their elements, which may be other user-defined - 6077 # types, which we will compute as needed. - 6078 - 6079 # Initially, all user-defined types have their sizes set to -2 (invalid) - 6080 populate-mu-type-sizes: - 6081 # . prologue - 6082 55/push-ebp - 6083 89/<- %ebp 4/r32/esp - 6084 # . save registers - 6085 51/push-ecx - 6086 $populate-mu-type-sizes:total-sizes: - 6087 # var curr/ecx: (handle typeinfo) = *Program->types - 6088 8b/-> *_Program-types 1/r32/ecx - 6089 { - 6090 # if (curr == null) break - 6091 81 7/subop/compare %ecx 0/imm32 - 6092 74/jump-if-= break/disp8 - 6093 (populate-mu-type-sizes-in-type %ecx) - 6094 # curr = curr->next - 6095 8b/-> *(ecx+0xc) 1/r32/ecx # Typeinfo-next - 6096 eb/jump loop/disp8 - 6097 } - 6098 $populate-mu-type-sizes:offsets: - 6099 # var curr/ecx: (handle typeinfo) = *Program->types - 6100 8b/-> *_Program-types 1/r32/ecx - 6101 { - 6102 # if (curr == null) break - 6103 81 7/subop/compare %ecx 0/imm32 - 6104 74/jump-if-= break/disp8 - 6105 (populate-mu-type-offsets %ecx) - 6106 # curr = curr->next - 6107 8b/-> *(ecx+0xc) 1/r32/ecx # Typeinfo-next - 6108 eb/jump loop/disp8 - 6109 } - 6110 $populate-mu-type-sizes:end: - 6111 # . restore registers - 6112 59/pop-to-ecx - 6113 # . epilogue - 6114 89/<- %esp 5/r32/ebp - 6115 5d/pop-to-ebp - 6116 c3/return - 6117 - 6118 # compute sizes of all fields, recursing as necessary - 6119 # sum up all their sizes to arrive at total size - 6120 # fields may be out of order, but that doesn't affect the answer - 6121 populate-mu-type-sizes-in-type: # T: (handle typeinfo) - 6122 # . prologue - 6123 55/push-ebp - 6124 89/<- %ebp 4/r32/esp - 6125 # . save registers - 6126 50/push-eax - 6127 51/push-ecx - 6128 52/push-edx - 6129 56/push-esi - 6130 57/push-edi - 6131 # esi = T - 6132 8b/-> *(ebp+8) 6/r32/esi - 6133 # if T is already computed, return - 6134 81 7/subop/compare *(esi+8) 0/imm32 # Typeinfo-total-size-in-bytes - 6135 7d/jump-if->= $populate-mu-type-sizes-in-type:end/disp8 - 6136 # if T is being computed, abort - 6137 81 7/subop/compare *(esi+8) -1/imm32/being-computed # Typeinfo-total-size-in-bytes - 6138 74/jump-if-= $populate-mu-type-sizes-in-type:abort/disp8 - 6139 # tag T (-2 to -1) to avoid infinite recursion - 6140 c7 0/subop/copy *(esi+8) -1/imm32/being-computed # Typeinfo-total-size-in-bytes - 6141 # var total-size/edi: int = 0 - 6142 bf/copy-to-edi 0/imm32 - 6143 # - for every field, if it's a user-defined type, compute its size - 6144 # var table/ecx: (handle table string_key (handle typeinfo-entry)) = T->fields - 6145 8b/-> *(esi+4) 1/r32/ecx # Typeinfo-fields - 6146 # var table-size/edx: int = table->write - 6147 8b/-> *ecx 2/r32/edx # stream-write - 6148 # var curr/ecx: (addr table_row) = table->data - 6149 8d/copy-address *(ecx+0xc) 1/r32/ecx - 6150 # var max/edx: (addr table_row) = table->data + table->write - 6151 8d/copy-address *(ecx+edx) 2/r32/edx - 6152 { - 6153 $populate-mu-type-sizes-in-type:loop: - 6154 # if (curr >= max) break - 6155 39/compare %ecx 2/r32/edx - 6156 73/jump-if-addr>= break/disp8 - 6157 # var t/eax: (handle typeinfo-entry) = curr->value - 6158 8b/-> *(ecx+4) 0/r32/eax - 6159 # compute size of t - 6160 (compute-size-of-var *eax) # Typeinfo-entry-input-var => eax - 6161 # result += eax - 6162 01/add-to %edi 0/r32/eax - 6163 # curr += row-size - 6164 81 0/subop/add %ecx 8/imm32 - 6165 # - 6166 eb/jump loop/disp8 - 6167 } - 6168 # - save result - 6169 89/<- *(esi+8) 7/r32/edi # Typeinfo-total-size-in-bytes - 6170 $populate-mu-type-sizes-in-type:end: - 6171 # . restore registers - 6172 5f/pop-to-edi - 6173 5e/pop-to-esi - 6174 5a/pop-to-edx - 6175 59/pop-to-ecx - 6176 58/pop-to-eax - 6177 # . epilogue - 6178 89/<- %esp 5/r32/ebp - 6179 5d/pop-to-ebp - 6180 c3/return - 6181 - 6182 $populate-mu-type-sizes-in-type:abort: - 6183 (write-buffered Stderr "cycle in type definitions\n") - 6184 (flush Stderr) - 6185 # . syscall(exit, 1) - 6186 bb/copy-to-ebx 1/imm32 - 6187 b8/copy-to-eax 1/imm32/exit - 6188 cd/syscall 0x80/imm8 - 6189 # never gets here - 6190 - 6191 # Analogous to size-of, except we need to compute what size-of can just read - 6192 # off the right data structures. - 6193 compute-size-of-var: # in: (handle var) -> result/eax: int - 6194 # . prologue - 6195 55/push-ebp - 6196 89/<- %ebp 4/r32/esp - 6197 # . push registers - 6198 51/push-ecx - 6199 # var t/ecx: (handle tree type-id) = v->type - 6200 8b/-> *(ebp+8) 1/r32/ecx - 6201 8b/-> *(ecx+4) 1/r32/ecx # Var-type - 6202 # if (t->left >= *Max-type-id) t = t->left - 6203 { - 6204 8b/-> *Max-type-id 0/r32/eax - 6205 39/compare *ecx 0/r32/eax # Tree-left - 6206 72/jump-if-addr< break/disp8 - 6207 8b/-> *ecx 1/r32/ecx # Tree-left - 6208 } - 6209 (compute-size-of-type-id *ecx) # Atom-left => eax - 6210 $compute-size-of-var:end: - 6211 # . restore registers - 6212 59/pop-to-ecx - 6213 # . epilogue - 6214 89/<- %esp 5/r32/ebp - 6215 5d/pop-to-ebp - 6216 c3/return - 6217 - 6218 compute-size-of-type-id: # t: type-id -> result/eax: int - 6219 # . prologue - 6220 55/push-ebp - 6221 89/<- %ebp 4/r32/esp - 6222 # - 6223 8b/-> *(ebp+8) 0/r32/eax - 6224 # if v is a literal, return 0 - 6225 3d/compare-eax-and 0/imm32 - 6226 74/jump-if-= $compute-size-of-type-id:end/disp8 # eax changes type from type-id to int - 6227 # if v has a user-defined type, compute its size - 6228 # TODO: support non-atom type - 6229 (find-typeinfo %eax) # => eax - 6230 { - 6231 3d/compare-eax-and 0/imm32 - 6232 74/jump-if-= break/disp8 - 6233 $compute-size-of-type-id:user-defined: - 6234 (populate-mu-type-sizes %eax) - 6235 8b/-> *(eax+8) 0/r32/eax # Typeinfo-total-size-in-bytes - 6236 eb/jump $compute-size-of-type-id:end/disp8 - 6237 } - 6238 # otherwise return the word size - 6239 b8/copy-to-eax 4/imm32 - 6240 $compute-size-of-type-id:end: - 6241 # . epilogue - 6242 89/<- %esp 5/r32/ebp - 6243 5d/pop-to-ebp - 6244 c3/return - 6245 - 6246 # at this point we have total sizes for all user-defined types - 6247 # compute offsets for each element - 6248 # complication: fields may be out of order - 6249 populate-mu-type-offsets: # in: (handle typeinfo) - 6250 # . prologue - 6251 55/push-ebp - 6252 89/<- %ebp 4/r32/esp - 6253 # . save registers - 6254 50/push-eax - 6255 51/push-ecx - 6256 52/push-edx - 6257 53/push-ebx - 6258 56/push-esi - 6259 57/push-edi - 6260 # var curr-offset/edi: int = 0 - 6261 bf/copy-to-edi 0/imm32 - 6262 # var table/ecx: (handle table string_key (handle typeinfo-entry)) = T->fields - 6263 8b/-> *(ebp+8) 1/r32/ecx - 6264 8b/-> *(ecx+4) 1/r32/ecx # Typeinfo-fields - 6265 # var num-elems/edx: int = table->write / 8 - 6266 8b/-> *ecx 2/r32/edx # stream-write - 6267 c1 5/subop/shift-right-logical %edx 3/imm8 - 6268 # var i/ebx: int = 0 - 6269 bb/copy-to-ebx 0/imm32 - 6270 { - 6271 $populate-mu-type-offsets:loop: - 6272 39/compare %ebx 2/r32/edx - 6273 7d/jump-if->= break/disp8 - 6274 # var v/esi: (handle typeinfo-entry) - 6275 (locate-typeinfo-entry-with-index %ecx %ebx) # => eax - 6276 89/<- %esi 0/r32/eax - 6277 # v->output-var->offset = curr-offset - 6278 8b/-> *(esi+8) 0/r32/eax # Typeinfo-entry-output-var - 6279 89/<- *(eax+0xc) 7/r32/edi # Var-offset - 6280 # curr-offset += size-of(v->input-var) - 6281 8b/-> *esi 0/r32/eax # Typeinfo-entry-input-var - 6282 (size-of %eax) # => eax - 6283 01/add-to %edi 0/r32/eax - 6284 # ++i - 6285 43/increment-ebx - 6286 eb/jump loop/disp8 - 6287 } - 6288 $populate-mu-type-offsets:end: - 6289 # . restore registers - 6290 5f/pop-to-edi - 6291 5e/pop-to-esi - 6292 5b/pop-to-ebx - 6293 5a/pop-to-edx - 6294 59/pop-to-ecx - 6295 58/pop-to-eax - 6296 # . epilogue - 6297 89/<- %esp 5/r32/ebp - 6298 5d/pop-to-ebp - 6299 c3/return - 6300 - 6301 locate-typeinfo-entry-with-index: # table: (handle table string_key (handle typeinfo-entry)), idx: int -> result/eax: (handle typeinfo-entry) - 6302 # . prologue - 6303 55/push-ebp - 6304 89/<- %ebp 4/r32/esp - 6305 # . save registers - 6306 51/push-ecx - 6307 52/push-edx - 6308 53/push-ebx - 6309 56/push-esi - 6310 57/push-edi - 6311 # esi = table - 6312 8b/-> *(ebp+8) 6/r32/esi - 6313 # var curr/ecx: (addr string_key) = table->data - 6314 8d/copy-address *(esi+0xc) 1/r32/ecx - 6315 # var max/edx: (addr byte) = &table->data[table->write] - 6316 8b/-> *esi 2/r32/edx - 6317 8d/copy-address *(ecx+edx) 2/r32/edx - 6318 { - 6319 $locate-typeinfo-entry-with-index:loop: - 6320 39/compare %ecx 2/r32/edx - 6321 73/jump-if-addr>= $locate-typeinfo-entry-with-index:abort/disp8 - 6322 # var v/ebx: (handle typeinfo-entry) - 6323 8b/-> *(ecx+4) 3/r32/ebx - 6324 # if (v->index == idx) return v - 6325 8b/-> *(ebx+4) 0/r32/eax # Typeinfo-entry-index - 6326 39/compare *(ebp+0xc) 0/r32/eax - 6327 89/<- %eax 3/r32/ebx - 6328 74/jump-if-= break/disp8 - 6329 # curr += 8 - 6330 81 0/subop/add %ecx 8/imm32 - 6331 eb/jump loop/disp8 - 6332 } - 6333 $locate-typeinfo-entry-with-index:end: - 6334 # . restore registers - 6335 5f/pop-to-edi - 6336 5e/pop-to-esi - 6337 5b/pop-to-ebx - 6338 5a/pop-to-edx - 6339 59/pop-to-ecx - 6340 # . epilogue - 6341 89/<- %esp 5/r32/ebp - 6342 5d/pop-to-ebp - 6343 c3/return - 6344 - 6345 $locate-typeinfo-entry-with-index:abort: - 6346 (write-buffered Stderr "overflowing typeinfo-entry->index ") - 6347 (print-int32-buffered Stderr %ecx) - 6348 (write-buffered Stderr "\n") - 6349 (flush Stderr) - 6350 # . syscall(exit, 1) - 6351 bb/copy-to-ebx 1/imm32 - 6352 b8/copy-to-eax 1/imm32/exit - 6353 cd/syscall 0x80/imm8 - 6354 # never gets here - 6355 - 6356 ####################################################### - 6357 # Type-checking - 6358 ####################################################### - 6359 - 6360 check-mu-types: - 6361 # . prologue - 6362 55/push-ebp - 6363 89/<- %ebp 4/r32/esp - 6364 # - 6365 $check-mu-types:end: - 6366 # . epilogue - 6367 89/<- %esp 5/r32/ebp - 6368 5d/pop-to-ebp - 6369 c3/return - 6370 - 6371 size-of: # v: (handle var) -> result/eax: int - 6372 # . prologue - 6373 55/push-ebp - 6374 89/<- %ebp 4/r32/esp - 6375 # . save registers - 6376 51/push-ecx - 6377 # var t/ecx: (handle tree type-id) = v->type - 6378 8b/-> *(ebp+8) 1/r32/ecx - 6379 8b/-> *(ecx+4) 1/r32/ecx # Var-type - 6380 # if is-mu-array?(t) return size-of-array(t) - 6381 { - 6382 (is-mu-array? %ecx) # => eax - 6383 3d/compare-eax-and 0/imm32/false - 6384 74/jump-if-= break/disp8 - 6385 (size-of-array %ecx) # => eax - 6386 eb/jump $size-of:end/disp8 - 6387 } - 6388 # if (t->left >= *Max-type-id) t = t->left - 6389 { - 6390 8b/-> *Max-type-id 0/r32/eax - 6391 39/compare *ecx 0/r32/eax # Tree-left - 6392 72/jump-if-addr< break/disp8 - 6393 8b/-> *ecx 1/r32/ecx # Tree-left - 6394 } - 6395 (size-of-type-id *ecx) # Atom-left => eax - 6396 $size-of:end: - 6397 # . restore registers - 6398 59/pop-to-ecx - 6399 # . epilogue - 6400 89/<- %esp 5/r32/ebp - 6401 5d/pop-to-ebp - 6402 c3/return - 6403 - 6404 is-mu-array?: # t: (handle tree type-id) -> result/eax: boolean - 6405 # . prologue - 6406 55/push-ebp - 6407 89/<- %ebp 4/r32/esp - 6408 # . save registers - 6409 51/push-ecx - 6410 # ecx = t->left - 6411 8b/-> *(ebp+8) 1/r32/ecx - 6412 8b/-> *ecx 1/r32/ecx # Tree-left - 6413 # if t is an atomic type, return false - 6414 3b/compare 1/r32/ecx *Max-type-id - 6415 b8/copy-to-eax 0/imm32/false - 6416 72/jump-if-addr< $is-mu-array?:end/disp8 - 6417 # return ecx->value == array - 6418 81 7/subop/compare *ecx 3/imm32/array-type-id # Atom-value - 6419 0f 94/set-if-= %al - 6420 81 4/subop/and %eax 0xff/imm32 - 6421 $is-mu-array?:end: - 6422 # . restore registers - 6423 59/pop-to-ecx - 6424 # . epilogue - 6425 89/<- %esp 5/r32/ebp - 6426 5d/pop-to-ebp - 6427 c3/return - 6428 - 6429 size-of-array: # a: (handle tree type-id) -> result/eax: int - 6430 # . prologue - 6431 55/push-ebp - 6432 89/<- %ebp 4/r32/esp - 6433 # . save registers - 6434 51/push-ecx - 6435 52/push-edx - 6436 # - 6437 8b/-> *(ebp+8) 1/r32/ecx - 6438 # TODO: assert that a->left is 'array' - 6439 8b/-> *(ecx+4) 1/r32/ecx # Tree-right - 6440 # var elem-type/edx: type-id = a->right->value - 6441 8b/-> *ecx 2/r32/edx # Atom-value - 6442 8b/-> *edx 2/r32/edx # Atom-value - 6443 # var array-size/ecx: int = a->right->right->left->value - 6444 8b/-> *(ecx+4) 1/r32/ecx # Tree-right - 6445 8b/-> *ecx 1/r32/ecx # Tree-left - 6446 8b/-> *ecx 1/r32/ecx # Atom-value - 6447 # return array-size * size-of(elem-type) - 6448 (size-of-type-id %edx) # => eax - 6449 f7 4/subop/multiply-into-eax %ecx - 6450 05/add-to-eax 4/imm32 # for array length - 6451 $size-of-array:end: - 6452 # . restore registers - 6453 5a/pop-to-edx - 6454 59/pop-to-ecx - 6455 # . epilogue - 6456 89/<- %esp 5/r32/ebp - 6457 5d/pop-to-ebp - 6458 c3/return - 6459 - 6460 size-of-type-id: # t: type-id -> result/eax: int - 6461 # . prologue - 6462 55/push-ebp - 6463 89/<- %ebp 4/r32/esp - 6464 # - 6465 8b/-> *(ebp+8) 0/r32/eax - 6466 # if v is a literal, return 0 - 6467 3d/compare-eax-and 0/imm32 - 6468 74/jump-if-= $size-of-type-id:end/disp8 # eax changes type from type-id to int - 6469 # if v has a user-defined type, return its size - 6470 # TODO: support non-atom type - 6471 (find-typeinfo %eax) # => eax - 6472 { - 6473 3d/compare-eax-and 0/imm32 - 6474 74/jump-if-= break/disp8 - 6475 $size-of-type-id:user-defined: - 6476 8b/-> *(eax+8) 0/r32/eax # Typeinfo-total-size-in-bytes - 6477 eb/jump $size-of-type-id:end/disp8 + 5966 75/jump-if-!= break/disp8 + 5967 $find-or-create-typeinfo:create: + 5968 (allocate Heap *Typeinfo-size) # => eax + 5969 # result->id = t + 5970 8b/-> *(ebp+8) 1/r32/ecx + 5971 89/<- *eax 1/r32/ecx # Typeinfo-id + 5972 # result->fields = new table + 5973 # . ecx = new table + 5974 50/push-eax + 5975 (new-stream Heap 0x40 *Typeinfo-fields-row-size) # => eax + 5976 89/<- %ecx 0/r32/eax + 5977 58/pop-to-eax + 5978 # . result->fields = ecx + 5979 89/<- *(eax+4) 1/r32/ecx # Typeinfo-fields + 5980 # result->next = Program->types + 5981 8b/-> *_Program-types 1/r32/ecx + 5982 89/<- *(eax+0xc) 1/r32/ecx # Typeinfo-next + 5983 # Program->types = result + 5984 89/<- *_Program-types 0/r32/eax + 5985 } + 5986 $find-or-create-typeinfo:end: + 5987 # . restore registers + 5988 59/pop-to-ecx + 5989 # . epilogue + 5990 89/<- %esp 5/r32/ebp + 5991 5d/pop-to-ebp + 5992 c3/return + 5993 + 5994 find-typeinfo: # t: type-id -> result/eax: (handle typeinfo) + 5995 # . prologue + 5996 55/push-ebp + 5997 89/<- %ebp 4/r32/esp + 5998 # . save registers + 5999 51/push-ecx + 6000 # ecx = t + 6001 8b/-> *(ebp+8) 1/r32/ecx + 6002 # var curr/eax: (handle typeinfo) = Program->types + 6003 8b/-> *_Program-types 0/r32/eax + 6004 { + 6005 # if (curr == 0) break + 6006 3d/compare-eax-and 0/imm32 + 6007 74/jump-if-= break/disp8 + 6008 # if (curr->id == t) return curr + 6009 39/compare *eax 1/r32/ecx # Typeinfo-id + 6010 0f 84/jump-if-= $find-or-create-typeinfo:end/disp32 + 6011 # curr = curr->next + 6012 8b/-> *(eax+0xc) 0/r32/eax # Typeinfo-next + 6013 # + 6014 eb/jump loop/disp8 + 6015 } + 6016 $find-typeinfo:end: + 6017 # . restore registers + 6018 59/pop-to-ecx + 6019 # . epilogue + 6020 89/<- %esp 5/r32/ebp + 6021 5d/pop-to-ebp + 6022 c3/return + 6023 + 6024 find-or-create-typeinfo-output-var: # T: (handle typeinfo), f: (addr slice) -> result/eax: (handle var) + 6025 # . prologue + 6026 55/push-ebp + 6027 89/<- %ebp 4/r32/esp + 6028 # . save registers + 6029 51/push-ecx + 6030 56/push-esi + 6031 # esi = find-or-create-typeinfo-fields(T, f) + 6032 (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc)) # => eax + 6033 89/<- %esi 0/r32/eax + 6034 # if output var doesn't exist, create it + 6035 { + 6036 81 7/subop/compare *(esi+8) 0/imm32 # Typeinfo-entry-output-var + 6037 75/jump-if-!= break/disp8 + 6038 # var type/eax: (handle tree type-id) = new var("dummy name", constant type, -1 offset) + 6039 (allocate Heap *Tree-size) # => eax + 6040 c7 0/subop/copy *(eax+4) 6/imm32/constant # Tree-value + 6041 c7 0/subop/copy *(eax+8) 0/imm32 # Tree-right + 6042 89/<- %ecx 0/r32/eax + 6043 # eax = result + 6044 (new-var Heap "field") # => eax + 6045 # result->type = type + 6046 89/<- *(eax+4) 1/r32/ecx # Var-type + 6047 # result->offset isn't filled out yet + 6048 c7 0/subop/copy *(eax+0xc) -1/imm32/uninitialized # Var-offset + 6049 # save result as output var + 6050 89/<- *(esi+8) 0/r32/eax # Typeinfo-entry-output-var + 6051 } + 6052 # return the output var + 6053 8b/-> *(esi+8) 0/r32/eax # Typeinfo-entry-output-var + 6054 $find-or-create-typeinfo-output-var:end: + 6055 # . restore registers + 6056 5e/pop-to-esi + 6057 59/pop-to-ecx + 6058 # . epilogue + 6059 89/<- %esp 5/r32/ebp + 6060 5d/pop-to-ebp + 6061 c3/return + 6062 + 6063 find-or-create-typeinfo-fields: # T: (handle typeinfo), f: (addr slice) -> result/eax: (handle typeinfo-entry) + 6064 # . prologue + 6065 55/push-ebp + 6066 89/<- %ebp 4/r32/esp + 6067 # . save registers + 6068 56/push-esi + 6069 # esi = T->fields + 6070 8b/-> *(ebp+8) 6/r32/esi + 6071 8b/-> *(esi+4) 6/r32/esi # Typeinfo-fields + 6072 # esi = get-or-insert(T->fields, f) + 6073 (get-or-insert-slice %esi *(ebp+0xc) *Typeinfo-fields-row-size Heap) # => eax + 6074 89/<- %esi 0/r32/eax + 6075 # if typeinfo-entry doesn't exist, allocate it + 6076 { + 6077 81 7/subop/compare *esi 0/imm32 # output var + 6078 75/jump-if-!= break/disp8 + 6079 (allocate Heap *Typeinfo-entry-size) # => eax + 6080 89/<- *esi 0/r32/eax + 6081 } + 6082 # eax = T->fields[f]->entry + 6083 8b/-> *esi 0/r32/eax + 6084 $find-or-create-typeinfo-fields:end: + 6085 # . restore registers + 6086 5e/pop-to-esi + 6087 # . epilogue + 6088 89/<- %esp 5/r32/ebp + 6089 5d/pop-to-ebp + 6090 c3/return + 6091 + 6092 populate-mu-type: # in: (addr stream byte), t: (handle typeinfo) + 6093 # pseudocode: + 6094 # var line: (stream byte 512) + 6095 # curr-index = 0 + 6096 # while true + 6097 # clear-stream(line) + 6098 # read-line-buffered(in, line) + 6099 # if line->write == 0 + 6100 # abort + 6101 # word-slice = next-mu-token(line) + 6102 # if slice-empty?(word-slice) # end of line + 6103 # continue + 6104 # if slice-equal?(word-slice, "}") + 6105 # break + 6106 # var v: (handle var) = parse-var-with-type(word-slice, line) + 6107 # var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name) + 6108 # TODO: ensure that r->first is null + 6109 # r->index = curr-index + 6110 # curr-index++ + 6111 # r->input-var = v + 6112 # if r->output-var == 0 + 6113 # r->output-var = new literal + 6114 # TODO: ensure nothing else in line + 6115 # t->total-size-in-bytes = -2 (not yet initialized) + 6116 # + 6117 # . prologue + 6118 55/push-ebp + 6119 89/<- %ebp 4/r32/esp + 6120 # var curr-index: int at *(ebp-4) + 6121 68/push 0/imm32 + 6122 # . save registers + 6123 50/push-eax + 6124 51/push-ecx + 6125 52/push-edx + 6126 53/push-ebx + 6127 56/push-esi + 6128 57/push-edi + 6129 # edi = t + 6130 8b/-> *(ebp+0xc) 7/r32/edi + 6131 # var line/ecx: (stream byte 512) + 6132 81 5/subop/subtract %esp 0x200/imm32 + 6133 68/push 0x200/imm32/size + 6134 68/push 0/imm32/read + 6135 68/push 0/imm32/write + 6136 89/<- %ecx 4/r32/esp + 6137 # var word-slice/edx: slice + 6138 68/push 0/imm32/end + 6139 68/push 0/imm32/start + 6140 89/<- %edx 4/r32/esp + 6141 { + 6142 $populate-mu-type:line-loop: + 6143 (clear-stream %ecx) + 6144 (read-line-buffered *(ebp+8) %ecx) + 6145 # if (line->write == 0) abort + 6146 81 7/subop/compare *ecx 0/imm32 + 6147 0f 84/jump-if-= $populate-mu-type:abort/disp32 + 6148 +-- 6 lines: #? # dump line --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 6154 (next-mu-token %ecx %edx) + 6155 # if slice-empty?(word-slice) continue + 6156 (slice-empty? %edx) # => eax + 6157 3d/compare-eax-and 0/imm32 + 6158 0f 85/jump-if-!= loop/disp32 + 6159 # if slice-equal?(word-slice, "}") break + 6160 (slice-equal? %edx "}") + 6161 3d/compare-eax-and 0/imm32 + 6162 0f 85/jump-if-!= break/disp32 + 6163 $populate-mu-type:parse-element: + 6164 # var v/esi: (handle var) = parse-var-with-type(word-slice, first-line) + 6165 (parse-var-with-type %edx %ecx) # => eax + 6166 89/<- %esi 0/r32/eax + 6167 $populate-mu-type:create-typeinfo-fields: + 6168 # var r/ebx: (handle typeinfo-entry) + 6169 (find-or-create-typeinfo-fields %edi %edx) # => eax + 6170 89/<- %ebx 0/r32/eax + 6171 #? (write-buffered Stderr "var ") + 6172 #? (write-buffered Stderr *esi) # Var-name + 6173 #? (write-buffered Stderr " is at index ") + 6174 #? (print-int32-buffered Stderr *(ebp-4)) + 6175 #? (write-buffered Stderr Newline) + 6176 #? (flush Stderr) + 6177 # r->index = curr-index + 6178 8b/-> *(ebp-4) 0/r32/eax + 6179 89/<- *(ebx+4) 0/r32/eax # Typeinfo-entry-index + 6180 # ++curr-index + 6181 ff 0/subop/increment *(ebp-4) + 6182 $populate-mu-type:set-input-type: + 6183 # r->input-var = v + 6184 89/<- *ebx 6/r32/esi # Typeinfo-entry-input-var + 6185 { + 6186 $populate-mu-type:create-output-type: + 6187 # if (r->output-var == 0) create a new var with some placeholder data + 6188 81 7/subop/compare *(ebx+8) 0/imm32 # Typeinfo-entry-output-var + 6189 75/jump-if-!= break/disp8 + 6190 (new-literal Heap %edx) # => eax + 6191 89/<- *(ebx+8) 0/r32/eax # Typeinfo-entry-output-var + 6192 } + 6193 e9/jump loop/disp32 + 6194 } + 6195 $populate-mu-type:invalidate-total-size-in-bytes: + 6196 # Offsets and total size may not be accurate here since we may not yet + 6197 # have encountered the element types. + 6198 # We'll recompute them separately after parsing the entire program. + 6199 c7 0/subop/copy *(edi+8) -2/imm32/uninitialized # Typeinfo-total-size-in-bytes + 6200 $populate-mu-type:end: + 6201 # . reclaim locals + 6202 81 0/subop/add %esp 0x214/imm32 + 6203 # . restore registers + 6204 5f/pop-to-edi + 6205 5e/pop-to-esi + 6206 5b/pop-to-ebx + 6207 5a/pop-to-edx + 6208 59/pop-to-ecx + 6209 58/pop-to-eax + 6210 # reclaim curr-index + 6211 81 0/subop/add %esp 4/imm32 + 6212 # . epilogue + 6213 89/<- %esp 5/r32/ebp + 6214 5d/pop-to-ebp + 6215 c3/return + 6216 + 6217 $populate-mu-type:abort: + 6218 # error("unexpected top-level command: " word-slice "\n") + 6219 (write-buffered Stderr "incomplete type definition '") + 6220 (type-name *edi) # Typeinfo-id => eax + 6221 (write-buffered Stderr %eax) + 6222 (write-buffered Stderr "\n") + 6223 (flush Stderr) + 6224 # . syscall(exit, 1) + 6225 bb/copy-to-ebx 1/imm32 + 6226 b8/copy-to-eax 1/imm32/exit + 6227 cd/syscall 0x80/imm8 + 6228 # never gets here + 6229 + 6230 type-name: # index: int -> result/eax: (addr array byte) + 6231 # . prologue + 6232 55/push-ebp + 6233 89/<- %ebp 4/r32/esp + 6234 # + 6235 (index Type-id *(ebp+8)) + 6236 $type-name:end: + 6237 # . epilogue + 6238 89/<- %esp 5/r32/ebp + 6239 5d/pop-to-ebp + 6240 c3/return + 6241 + 6242 index: # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte) + 6243 # . prologue + 6244 55/push-ebp + 6245 89/<- %ebp 4/r32/esp + 6246 # . save registers + 6247 56/push-esi + 6248 # TODO: bounds-check index + 6249 # esi = arr + 6250 8b/-> *(ebp+8) 6/r32/esi + 6251 # eax = index + 6252 8b/-> *(ebp+0xc) 0/r32/eax + 6253 # eax = *(arr + 12 + index) + 6254 8b/-> *(esi+eax+0xc) 0/r32/eax + 6255 $index:end: + 6256 # . restore registers + 6257 5e/pop-to-esi + 6258 # . epilogue + 6259 89/<- %esp 5/r32/ebp + 6260 5d/pop-to-ebp + 6261 c3/return + 6262 + 6263 ####################################################### + 6264 # Compute type sizes + 6265 ####################################################### + 6266 + 6267 # Compute the sizes of all user-defined types. + 6268 # We'll need the sizes of their elements, which may be other user-defined + 6269 # types, which we will compute as needed. + 6270 + 6271 # Initially, all user-defined types have their sizes set to -2 (invalid) + 6272 populate-mu-type-sizes: + 6273 # . prologue + 6274 55/push-ebp + 6275 89/<- %ebp 4/r32/esp + 6276 # . save registers + 6277 51/push-ecx + 6278 $populate-mu-type-sizes:total-sizes: + 6279 # var curr/ecx: (handle typeinfo) = *Program->types + 6280 8b/-> *_Program-types 1/r32/ecx + 6281 { + 6282 # if (curr == null) break + 6283 81 7/subop/compare %ecx 0/imm32 + 6284 74/jump-if-= break/disp8 + 6285 (populate-mu-type-sizes-in-type %ecx) + 6286 # curr = curr->next + 6287 8b/-> *(ecx+0xc) 1/r32/ecx # Typeinfo-next + 6288 eb/jump loop/disp8 + 6289 } + 6290 $populate-mu-type-sizes:offsets: + 6291 # var curr/ecx: (handle typeinfo) = *Program->types + 6292 8b/-> *_Program-types 1/r32/ecx + 6293 { + 6294 # if (curr == null) break + 6295 81 7/subop/compare %ecx 0/imm32 + 6296 74/jump-if-= break/disp8 + 6297 (populate-mu-type-offsets %ecx) + 6298 # curr = curr->next + 6299 8b/-> *(ecx+0xc) 1/r32/ecx # Typeinfo-next + 6300 eb/jump loop/disp8 + 6301 } + 6302 $populate-mu-type-sizes:end: + 6303 # . restore registers + 6304 59/pop-to-ecx + 6305 # . epilogue + 6306 89/<- %esp 5/r32/ebp + 6307 5d/pop-to-ebp + 6308 c3/return + 6309 + 6310 # compute sizes of all fields, recursing as necessary + 6311 # sum up all their sizes to arrive at total size + 6312 # fields may be out of order, but that doesn't affect the answer + 6313 populate-mu-type-sizes-in-type: # T: (handle typeinfo) + 6314 # . prologue + 6315 55/push-ebp + 6316 89/<- %ebp 4/r32/esp + 6317 # . save registers + 6318 50/push-eax + 6319 51/push-ecx + 6320 52/push-edx + 6321 56/push-esi + 6322 57/push-edi + 6323 # esi = T + 6324 8b/-> *(ebp+8) 6/r32/esi + 6325 # if T is already computed, return + 6326 81 7/subop/compare *(esi+8) 0/imm32 # Typeinfo-total-size-in-bytes + 6327 7d/jump-if->= $populate-mu-type-sizes-in-type:end/disp8 + 6328 # if T is being computed, abort + 6329 81 7/subop/compare *(esi+8) -1/imm32/being-computed # Typeinfo-total-size-in-bytes + 6330 74/jump-if-= $populate-mu-type-sizes-in-type:abort/disp8 + 6331 # tag T (-2 to -1) to avoid infinite recursion + 6332 c7 0/subop/copy *(esi+8) -1/imm32/being-computed # Typeinfo-total-size-in-bytes + 6333 # var total-size/edi: int = 0 + 6334 bf/copy-to-edi 0/imm32 + 6335 # - for every field, if it's a user-defined type, compute its size + 6336 # var table/ecx: (handle table string_key (handle typeinfo-entry)) = T->fields + 6337 8b/-> *(esi+4) 1/r32/ecx # Typeinfo-fields + 6338 # var table-size/edx: int = table->write + 6339 8b/-> *ecx 2/r32/edx # stream-write + 6340 # var curr/ecx: (addr table_row) = table->data + 6341 8d/copy-address *(ecx+0xc) 1/r32/ecx + 6342 # var max/edx: (addr table_row) = table->data + table->write + 6343 8d/copy-address *(ecx+edx) 2/r32/edx + 6344 { + 6345 $populate-mu-type-sizes-in-type:loop: + 6346 # if (curr >= max) break + 6347 39/compare %ecx 2/r32/edx + 6348 73/jump-if-addr>= break/disp8 + 6349 # var t/eax: (handle typeinfo-entry) = curr->value + 6350 8b/-> *(ecx+4) 0/r32/eax + 6351 # compute size of t + 6352 (compute-size-of-var *eax) # Typeinfo-entry-input-var => eax + 6353 # result += eax + 6354 01/add-to %edi 0/r32/eax + 6355 # curr += row-size + 6356 81 0/subop/add %ecx 8/imm32 + 6357 # + 6358 eb/jump loop/disp8 + 6359 } + 6360 # - save result + 6361 89/<- *(esi+8) 7/r32/edi # Typeinfo-total-size-in-bytes + 6362 $populate-mu-type-sizes-in-type:end: + 6363 # . restore registers + 6364 5f/pop-to-edi + 6365 5e/pop-to-esi + 6366 5a/pop-to-edx + 6367 59/pop-to-ecx + 6368 58/pop-to-eax + 6369 # . epilogue + 6370 89/<- %esp 5/r32/ebp + 6371 5d/pop-to-ebp + 6372 c3/return + 6373 + 6374 $populate-mu-type-sizes-in-type:abort: + 6375 (write-buffered Stderr "cycle in type definitions\n") + 6376 (flush Stderr) + 6377 # . syscall(exit, 1) + 6378 bb/copy-to-ebx 1/imm32 + 6379 b8/copy-to-eax 1/imm32/exit + 6380 cd/syscall 0x80/imm8 + 6381 # never gets here + 6382 + 6383 # Analogous to size-of, except we need to compute what size-of can just read + 6384 # off the right data structures. + 6385 compute-size-of-var: # in: (handle var) -> result/eax: int + 6386 # . prologue + 6387 55/push-ebp + 6388 89/<- %ebp 4/r32/esp + 6389 # . push registers + 6390 51/push-ecx + 6391 # var t/ecx: (handle tree type-id) = v->type + 6392 8b/-> *(ebp+8) 1/r32/ecx + 6393 8b/-> *(ecx+4) 1/r32/ecx # Var-type + 6394 # if (t->left-is-atom == false) t = t->left + 6395 { + 6396 81 7/subop/compare *ecx 0/imm32/false # Tree-is-atom + 6397 75/jump-if-!= break/disp8 + 6398 8b/-> *(ecx+4) 1/r32/ecx # Tree-left + 6399 } + 6400 (compute-size-of-type-id *(ecx+4)) # Tree-left => eax + 6401 $compute-size-of-var:end: + 6402 # . restore registers + 6403 59/pop-to-ecx + 6404 # . epilogue + 6405 89/<- %esp 5/r32/ebp + 6406 5d/pop-to-ebp + 6407 c3/return + 6408 + 6409 compute-size-of-type-id: # t: type-id -> result/eax: int + 6410 # . prologue + 6411 55/push-ebp + 6412 89/<- %ebp 4/r32/esp + 6413 # + 6414 8b/-> *(ebp+8) 0/r32/eax + 6415 # if v is a literal, return 0 + 6416 3d/compare-eax-and 0/imm32 + 6417 74/jump-if-= $compute-size-of-type-id:end/disp8 # eax changes type from type-id to int + 6418 # if v has a user-defined type, compute its size + 6419 # TODO: support non-atom type + 6420 (find-typeinfo %eax) # => eax + 6421 { + 6422 3d/compare-eax-and 0/imm32 + 6423 74/jump-if-= break/disp8 + 6424 $compute-size-of-type-id:user-defined: + 6425 (populate-mu-type-sizes %eax) + 6426 8b/-> *(eax+8) 0/r32/eax # Typeinfo-total-size-in-bytes + 6427 eb/jump $compute-size-of-type-id:end/disp8 + 6428 } + 6429 # otherwise return the word size + 6430 b8/copy-to-eax 4/imm32 + 6431 $compute-size-of-type-id:end: + 6432 # . epilogue + 6433 89/<- %esp 5/r32/ebp + 6434 5d/pop-to-ebp + 6435 c3/return + 6436 + 6437 # at this point we have total sizes for all user-defined types + 6438 # compute offsets for each element + 6439 # complication: fields may be out of order + 6440 populate-mu-type-offsets: # in: (handle typeinfo) + 6441 # . prologue + 6442 55/push-ebp + 6443 89/<- %ebp 4/r32/esp + 6444 # . save registers + 6445 50/push-eax + 6446 51/push-ecx + 6447 52/push-edx + 6448 53/push-ebx + 6449 56/push-esi + 6450 57/push-edi + 6451 # var curr-offset/edi: int = 0 + 6452 bf/copy-to-edi 0/imm32 + 6453 # var table/ecx: (handle table string_key (handle typeinfo-entry)) = T->fields + 6454 8b/-> *(ebp+8) 1/r32/ecx + 6455 8b/-> *(ecx+4) 1/r32/ecx # Typeinfo-fields + 6456 # var num-elems/edx: int = table->write / 8 + 6457 8b/-> *ecx 2/r32/edx # stream-write + 6458 c1 5/subop/shift-right-logical %edx 3/imm8 + 6459 # var i/ebx: int = 0 + 6460 bb/copy-to-ebx 0/imm32 + 6461 { + 6462 $populate-mu-type-offsets:loop: + 6463 39/compare %ebx 2/r32/edx + 6464 7d/jump-if->= break/disp8 + 6465 # var v/esi: (handle typeinfo-entry) + 6466 (locate-typeinfo-entry-with-index %ecx %ebx) # => eax + 6467 89/<- %esi 0/r32/eax + 6468 # v->output-var->offset = curr-offset + 6469 8b/-> *(esi+8) 0/r32/eax # Typeinfo-entry-output-var + 6470 89/<- *(eax+0xc) 7/r32/edi # Var-offset + 6471 # curr-offset += size-of(v->input-var) + 6472 8b/-> *esi 0/r32/eax # Typeinfo-entry-input-var + 6473 (size-of %eax) # => eax + 6474 01/add-to %edi 0/r32/eax + 6475 # ++i + 6476 43/increment-ebx + 6477 eb/jump loop/disp8 6478 } - 6479 # otherwise return the word size - 6480 b8/copy-to-eax 4/imm32 - 6481 $size-of-type-id:end: - 6482 # . epilogue - 6483 89/<- %esp 5/r32/ebp - 6484 5d/pop-to-ebp - 6485 c3/return - 6486 - 6487 type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean - 6488 # . prologue - 6489 55/push-ebp - 6490 89/<- %ebp 4/r32/esp - 6491 # . save registers - 6492 51/push-ecx - 6493 52/push-edx - 6494 # ecx = a - 6495 8b/-> *(ebp+8) 1/r32/ecx - 6496 # edx = b - 6497 8b/-> *(ebp+0xc) 2/r32/edx - 6498 # if (a == b) return true - 6499 8b/-> %ecx 0/r32/eax # Var-type - 6500 39/compare %edx 0/r32/eax # Var-type - 6501 b8/copy-to-eax 1/imm32/true - 6502 74/jump-if-= $type-equal?:end/disp8 - 6503 # if (a < MAX_TYPE_ID) return false - 6504 81 7/subop/compare %ecx 0x10000/imm32 - 6505 b8/copy-to-eax 0/imm32/false - 6506 72/jump-if-addr< $type-equal?:end/disp8 - 6507 # if (b < MAX_TYPE_ID) return false - 6508 81 7/subop/compare %edx 0x10000/imm32 - 6509 b8/copy-to-eax 0/imm32/false - 6510 72/jump-if-addr< $type-equal?:end/disp8 - 6511 # if (!type-equal?(a->left, b->left)) return false - 6512 (type-equal? *ecx *edx) # Tree-left, Tree-left => eax - 6513 3d/compare-eax-and 0/imm32/false - 6514 74/jump-if-= $type-equal?:end/disp8 - 6515 # return type-equal?(a->right, b->right) - 6516 (type-equal? *(ecx+4) *(edx+4)) # Tree-right, Tree-right => eax - 6517 $type-equal?:end: - 6518 # . restore registers - 6519 5a/pop-to-edx - 6520 59/pop-to-ecx - 6521 # . epilogue - 6522 89/<- %esp 5/r32/ebp - 6523 5d/pop-to-ebp - 6524 c3/return - 6525 - 6526 ####################################################### - 6527 # Code-generation - 6528 ####################################################### - 6529 - 6530 == data - 6531 - 6532 Curr-block-depth: # (addr int) - 6533 0/imm32 - 6534 Curr-local-stack-offset: # (addr int) - 6535 0/imm32 - 6536 - 6537 == code - 6538 - 6539 emit-subx: # out: (addr buffered-file) - 6540 # . prologue - 6541 55/push-ebp - 6542 89/<- %ebp 4/r32/esp - 6543 # . save registers - 6544 50/push-eax - 6545 51/push-ecx - 6546 57/push-edi - 6547 # edi = out - 6548 8b/-> *(ebp+8) 7/r32/edi - 6549 # var curr/ecx: (handle function) = *Program->functions - 6550 8b/-> *_Program-functions 1/r32/ecx - 6551 { - 6552 # if (curr == null) break - 6553 81 7/subop/compare %ecx 0/imm32 - 6554 0f 84/jump-if-= break/disp32 - 6555 (emit-subx-function %edi %ecx) - 6556 # curr = curr->next - 6557 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next - 6558 e9/jump loop/disp32 - 6559 } - 6560 $emit-subx:end: - 6561 # . restore registers - 6562 5f/pop-to-edi - 6563 59/pop-to-ecx - 6564 58/pop-to-eax - 6565 # . epilogue - 6566 89/<- %esp 5/r32/ebp - 6567 5d/pop-to-ebp - 6568 c3/return - 6569 - 6570 emit-subx-function: # out: (addr buffered-file), f: (handle function) - 6571 # . prologue - 6572 55/push-ebp - 6573 89/<- %ebp 4/r32/esp - 6574 # some preprocessing - 6575 (populate-mu-type-offsets-in-inouts *(ebp+0xc)) - 6576 # . save registers - 6577 50/push-eax - 6578 51/push-ecx - 6579 52/push-edx - 6580 57/push-edi - 6581 # edi = out - 6582 8b/-> *(ebp+8) 7/r32/edi - 6583 # ecx = f - 6584 8b/-> *(ebp+0xc) 1/r32/ecx - 6585 # var vars/edx: (stack (addr var) 256) - 6586 81 5/subop/subtract %esp 0x400/imm32 - 6587 68/push 0x400/imm32/length - 6588 68/push 0/imm32/top - 6589 89/<- %edx 4/r32/esp - 6590 # - 6591 (write-buffered %edi *ecx) - 6592 (write-buffered %edi ":\n") - 6593 # initialize some global state - 6594 c7 0/subop/copy *Curr-block-depth 1/imm32 - 6595 c7 0/subop/copy *Curr-local-stack-offset 0/imm32 - 6596 # - 6597 (emit-subx-prologue %edi) - 6598 (emit-subx-block %edi *(ecx+0x10) %edx) # Function-body - 6599 (emit-subx-epilogue %edi) - 6600 # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have - 6601 # been cleaned up - 6602 $emit-subx-function:end: - 6603 # . reclaim locals - 6604 81 0/subop/add %esp 408/imm32 - 6605 # . restore registers - 6606 5f/pop-to-edi - 6607 5a/pop-to-edx - 6608 59/pop-to-ecx - 6609 58/pop-to-eax - 6610 # . epilogue - 6611 89/<- %esp 5/r32/ebp - 6612 5d/pop-to-ebp - 6613 c3/return - 6614 - 6615 populate-mu-type-offsets-in-inouts: # f: (handle function) - 6616 # . prologue - 6617 55/push-ebp - 6618 89/<- %ebp 4/r32/esp - 6619 # . save registers - 6620 50/push-eax - 6621 51/push-ecx - 6622 52/push-edx - 6623 53/push-ebx - 6624 57/push-edi - 6625 # var next-offset/edx: int = 8 - 6626 ba/copy-to-edx 8/imm32 - 6627 # var curr/ecx: (handle list var) = f->inouts - 6628 8b/-> *(ebp+8) 1/r32/ecx - 6629 8b/-> *(ecx+8) 1/r32/ecx # Function-inouts - 6630 { - 6631 $populate-mu-type-offsets-in-inouts:loop: - 6632 81 7/subop/compare %ecx 0/imm32 - 6633 74/jump-if-= break/disp8 - 6634 # var v/ebx: (handle var) = curr->value - 6635 8b/-> *ecx 3/r32/ebx # List-value - 6636 # v->offset = next-offset - 6637 89/<- *(ebx+0xc) 2/r32/edx # Var-offset - 6638 # next-offset += size-of(v) - 6639 (size-of %ebx) # => eax - 6640 01/add %edx 0/r32/eax - 6641 # curr = curr->next - 6642 8b/-> *(ecx+4) 1/r32/ecx # List-next - 6643 eb/jump loop/disp8 - 6644 } - 6645 $populate-mu-type-offsets-in-inouts:end: - 6646 # . restore registers - 6647 5f/pop-to-edi - 6648 5b/pop-to-ebx - 6649 5a/pop-to-edx + 6479 $populate-mu-type-offsets:end: + 6480 # . restore registers + 6481 5f/pop-to-edi + 6482 5e/pop-to-esi + 6483 5b/pop-to-ebx + 6484 5a/pop-to-edx + 6485 59/pop-to-ecx + 6486 58/pop-to-eax + 6487 # . epilogue + 6488 89/<- %esp 5/r32/ebp + 6489 5d/pop-to-ebp + 6490 c3/return + 6491 + 6492 locate-typeinfo-entry-with-index: # table: (handle table string_key (handle typeinfo-entry)), idx: int -> result/eax: (handle typeinfo-entry) + 6493 # . prologue + 6494 55/push-ebp + 6495 89/<- %ebp 4/r32/esp + 6496 # . save registers + 6497 51/push-ecx + 6498 52/push-edx + 6499 53/push-ebx + 6500 56/push-esi + 6501 57/push-edi + 6502 # esi = table + 6503 8b/-> *(ebp+8) 6/r32/esi + 6504 # var curr/ecx: (addr string_key) = table->data + 6505 8d/copy-address *(esi+0xc) 1/r32/ecx + 6506 # var max/edx: (addr byte) = &table->data[table->write] + 6507 8b/-> *esi 2/r32/edx + 6508 8d/copy-address *(ecx+edx) 2/r32/edx + 6509 { + 6510 $locate-typeinfo-entry-with-index:loop: + 6511 39/compare %ecx 2/r32/edx + 6512 73/jump-if-addr>= $locate-typeinfo-entry-with-index:abort/disp8 + 6513 # var v/ebx: (handle typeinfo-entry) + 6514 8b/-> *(ecx+4) 3/r32/ebx + 6515 # if (v->index == idx) return v + 6516 8b/-> *(ebx+4) 0/r32/eax # Typeinfo-entry-index + 6517 39/compare *(ebp+0xc) 0/r32/eax + 6518 89/<- %eax 3/r32/ebx + 6519 74/jump-if-= break/disp8 + 6520 # curr += 8 + 6521 81 0/subop/add %ecx 8/imm32 + 6522 eb/jump loop/disp8 + 6523 } + 6524 $locate-typeinfo-entry-with-index:end: + 6525 # . restore registers + 6526 5f/pop-to-edi + 6527 5e/pop-to-esi + 6528 5b/pop-to-ebx + 6529 5a/pop-to-edx + 6530 59/pop-to-ecx + 6531 # . epilogue + 6532 89/<- %esp 5/r32/ebp + 6533 5d/pop-to-ebp + 6534 c3/return + 6535 + 6536 $locate-typeinfo-entry-with-index:abort: + 6537 (write-buffered Stderr "overflowing typeinfo-entry->index ") + 6538 (print-int32-buffered Stderr %ecx) + 6539 (write-buffered Stderr "\n") + 6540 (flush Stderr) + 6541 # . syscall(exit, 1) + 6542 bb/copy-to-ebx 1/imm32 + 6543 b8/copy-to-eax 1/imm32/exit + 6544 cd/syscall 0x80/imm8 + 6545 # never gets here + 6546 + 6547 ####################################################### + 6548 # Type-checking + 6549 ####################################################### + 6550 + 6551 check-mu-types: + 6552 # . prologue + 6553 55/push-ebp + 6554 89/<- %ebp 4/r32/esp + 6555 # + 6556 $check-mu-types:end: + 6557 # . epilogue + 6558 89/<- %esp 5/r32/ebp + 6559 5d/pop-to-ebp + 6560 c3/return + 6561 + 6562 size-of: # v: (handle var) -> result/eax: int + 6563 # . prologue + 6564 55/push-ebp + 6565 89/<- %ebp 4/r32/esp + 6566 # . save registers + 6567 51/push-ecx + 6568 # var t/ecx: (handle tree type-id) = v->type + 6569 8b/-> *(ebp+8) 1/r32/ecx + 6570 8b/-> *(ecx+4) 1/r32/ecx # Var-type + 6571 # if is-mu-array?(t) return size-of-array(t) + 6572 { + 6573 (is-mu-array? %ecx) # => eax + 6574 3d/compare-eax-and 0/imm32/false + 6575 74/jump-if-= break/disp8 + 6576 (size-of-array %ecx) # => eax + 6577 eb/jump $size-of:end/disp8 + 6578 } + 6579 # if (t->left-is-atom == false) t = t->left + 6580 { + 6581 81 7/subop/compare *ecx 0/imm32/false # Tree-is-atom + 6582 75/jump-if-!= break/disp8 + 6583 8b/-> *(ecx+4) 1/r32/ecx # Tree-left + 6584 } + 6585 (size-of-type-id *(ecx+4)) # Tree-left => eax + 6586 $size-of:end: + 6587 # . restore registers + 6588 59/pop-to-ecx + 6589 # . epilogue + 6590 89/<- %esp 5/r32/ebp + 6591 5d/pop-to-ebp + 6592 c3/return + 6593 + 6594 size-of-deref: # v: (handle var) -> result/eax: int + 6595 # . prologue + 6596 55/push-ebp + 6597 89/<- %ebp 4/r32/esp + 6598 # . save registers + 6599 51/push-ecx + 6600 # var t/ecx: (handle tree type-id) = v->type + 6601 8b/-> *(ebp+8) 1/r32/ecx + 6602 8b/-> *(ecx+4) 1/r32/ecx # Var-type + 6603 # TODO: assert(t is an addr) + 6604 8b/-> *(ecx+8) 1/r32/ecx # Tree-right + 6605 # if is-mu-array?(t) return size-of-array(t) + 6606 { + 6607 (is-mu-array? %ecx) # => eax + 6608 3d/compare-eax-and 0/imm32/false + 6609 74/jump-if-= break/disp8 + 6610 (size-of-array %ecx) # => eax + 6611 eb/jump $size-of:end/disp8 + 6612 } + 6613 # if (t->left-is-atom == false) t = t->left + 6614 { + 6615 81 7/subop/compare *ecx 0/imm32/false # Tree-is-atom + 6616 75/jump-if-!= break/disp8 + 6617 8b/-> *(ecx+4) 1/r32/ecx # Tree-left + 6618 } + 6619 (size-of-type-id *(ecx+4)) # Tree-left => eax + 6620 $size-of-deref:end: + 6621 # . restore registers + 6622 59/pop-to-ecx + 6623 # . epilogue + 6624 89/<- %esp 5/r32/ebp + 6625 5d/pop-to-ebp + 6626 c3/return + 6627 + 6628 is-mu-array?: # t: (handle tree type-id) -> result/eax: boolean + 6629 # . prologue + 6630 55/push-ebp + 6631 89/<- %ebp 4/r32/esp + 6632 # . save registers + 6633 51/push-ecx + 6634 # ecx = t + 6635 8b/-> *(ebp+8) 1/r32/ecx + 6636 # result = false + 6637 b8/copy-to-eax 0/imm32/false + 6638 # if t->left-is-atom, return false + 6639 81 7/subop/compare *ecx 0/imm32/false # Tree-is-atom + 6640 75/jump-if-!= $is-mu-array?:end/disp8 + 6641 # if !t->left->left-is-atom, return false + 6642 8b/-> *(ecx+4) 1/r32/ecx # Tree-left + 6643 81 7/subop/compare *ecx 0/imm32/false # Tree-is-atom + 6644 74/jump-if-= $is-mu-array?:end/disp8 + 6645 # return t->left->value == array + 6646 81 7/subop/compare *(ecx+4) 3/imm32/array-type-id # Tree-value + 6647 0f 94/set-if-= %al + 6648 $is-mu-array?:end: + 6649 # . restore registers 6650 59/pop-to-ecx - 6651 58/pop-to-eax - 6652 # . epilogue - 6653 89/<- %esp 5/r32/ebp - 6654 5d/pop-to-ebp - 6655 c3/return - 6656 - 6657 emit-subx-stmt-list: # out: (addr buffered-file), stmts: (handle list stmt), vars: (addr stack (handle var)) - 6658 # . prologue - 6659 55/push-ebp - 6660 89/<- %ebp 4/r32/esp - 6661 # . save registers - 6662 50/push-eax - 6663 51/push-ecx - 6664 52/push-edx - 6665 53/push-ebx - 6666 56/push-esi - 6667 # esi = stmts - 6668 8b/-> *(ebp+0xc) 6/r32/esi - 6669 # var var-seen?/edx: boolean <- copy false - 6670 ba/copy-to-edx 0/imm32/false - 6671 # - 6672 { - 6673 $emit-subx-stmt-list:loop: - 6674 81 7/subop/compare %esi 0/imm32 - 6675 0f 84/jump-if-= break/disp32 - 6676 # var curr-stmt/ecx = stmts->value - 6677 8b/-> *esi 1/r32/ecx # List-value - 6678 { - 6679 $emit-subx-stmt-list:check-for-block: - 6680 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag - 6681 75/jump-if-!= break/disp8 - 6682 $emit-subx-stmt-list:block: - 6683 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10)) - 6684 } - 6685 { - 6686 $emit-subx-stmt-list:check-for-stmt: - 6687 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag - 6688 0f 85/jump-if-!= break/disp32 - 6689 $emit-subx-stmt-list:stmt1: - 6690 { - 6691 (is-mu-branch? %ecx) # => eax - 6692 3d/compare-eax-and 0/imm32/false - 6693 0f 84/jump-if-= break/disp32 - 6694 $emit-subx-stmt-list:branch-stmt: - 6695 # if !var-seen? break - 6696 81 7/subop/compare %edx 0/imm32/false - 6697 0f 84/jump-if-= break/disp32 - 6698 $emit-subx-stmt-list:branch-stmt-and-var-seen: - 6699 +-- 26 lines: # unconditional loops ----------------------------------------------------------------------------------------------------------------------------------------------------- - 6725 +-- 15 lines: # unconditional breaks ---------------------------------------------------------------------------------------------------------------------------------------------------- - 6740 +-- 37 lines: # simple conditional branches without a target ---------------------------------------------------------------------------------------------------------------------------- - 6777 +-- 19 lines: # conditional branches with an explicit target ---------------------------------------------------------------------------------------------------------------------------- - 6796 } - 6797 $emit-subx-stmt-list:1-to-1: - 6798 (emit-subx-stmt *(ebp+8) %ecx Primitives *_Program-functions) - 6799 } - 6800 { - 6801 $emit-subx-stmt-list:check-for-var-def: - 6802 81 7/subop/compare *ecx 2/imm32/var-def # Stmt-tag - 6803 75/jump-if-!= break/disp8 - 6804 $emit-subx-stmt-list:var-def: - 6805 (emit-subx-var-def *(ebp+8) %ecx) - 6806 (push *(ebp+0x10) *(ecx+4)) # Vardef-var - 6807 # var-seen? = true - 6808 ba/copy-to-edx 1/imm32/true - 6809 } - 6810 { - 6811 $emit-subx-stmt-list:check-for-reg-var-def: - 6812 81 7/subop/compare *ecx 3/imm32/reg-var-def # Stmt-tag - 6813 0f 85/jump-if-!= break/disp32 - 6814 $emit-subx-stmt-list:reg-var-def: - 6815 # TODO: ensure that there's exactly one output - 6816 (compute-reg-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10)) - 6817 # register variable definition - 6818 (push *(ebp+0x10) %eax) - 6819 # emit the instruction as usual - 6820 (emit-subx-stmt *(ebp+8) %ecx Primitives *_Program-functions) - 6821 # var-seen? = true - 6822 ba/copy-to-edx 1/imm32/true - 6823 } - 6824 $emit-subx-stmt-list:continue: - 6825 # TODO: raise an error on unrecognized Stmt-tag - 6826 8b/-> *(esi+4) 6/r32/esi # List-next - 6827 e9/jump loop/disp32 - 6828 } - 6829 $emit-subx-stmt-list:emit-cleanup: - 6830 (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth) - 6831 $emit-subx-stmt-list:cleanup: - 6832 (clean-up-blocks *(ebp+0x10) *Curr-block-depth) - 6833 $emit-subx-stmt-list:end: - 6834 # . restore registers - 6835 5e/pop-to-esi - 6836 5b/pop-to-ebx - 6837 5a/pop-to-edx - 6838 59/pop-to-ecx - 6839 58/pop-to-eax - 6840 # . epilogue - 6841 89/<- %esp 5/r32/ebp - 6842 5d/pop-to-ebp - 6843 c3/return - 6844 - 6845 compute-reg-and-maybe-emit-spill: # out: (addr buffered-file), stmt: (handle reg-var-def), vars: (addr stack (handle var)) -> result/eax: (handle var) - 6846 # . prologue - 6847 55/push-ebp - 6848 89/<- %ebp 4/r32/esp - 6849 # . save registers - 6850 51/push-ecx - 6851 # ecx = stmt - 6852 8b/-> *(ebp+0xc) 1/r32/ecx - 6853 # var output/ecx: (handle var) = curr-stmt->outputs->value - 6854 8b/-> *(ecx+0xc) 1/r32/ecx # Regvardef-inouts - 6855 8b/-> *ecx 1/r32/ecx # List-value - 6856 # v->block-depth = *Curr-block-depth - 6857 8b/-> *Curr-block-depth 0/r32/eax - 6858 89/<- *(ecx+8) 0/r32/eax # Var-block-depth - 6859 # var reg/eax: (handle array byte) = output->register - 6860 8b/-> *(ecx+0x10) 0/r32/eax # Var-register - 6861 # ensure that output is in a register - 6862 3d/compare-eax-and 0/imm32 - 6863 0f 84/jump-if-= $compute-reg-and-maybe-emit-spill:abort/disp32 - 6864 # if already-spilled-this-block?(reg, vars) return - 6865 (already-spilled-this-block? %ecx *(ebp+0x10)) # => eax - 6866 3d/compare-eax-and 0/imm32/false - 6867 75/jump-if-!= $compute-reg-and-maybe-emit-spill:end/disp8 - 6868 # TODO: assert(size-of(output) == 4) - 6869 # *Curr-local-stack-offset -= 4 - 6870 81 5/subop/subtract *Curr-local-stack-offset 4/imm32 - 6871 # emit spill - 6872 (emit-indent *(ebp+8) *Curr-block-depth) - 6873 (write-buffered *(ebp+8) "ff 6/subop/push %") - 6874 (write-buffered *(ebp+8) *(ecx+0x10)) # Var-register - 6875 (write-buffered *(ebp+8) Newline) - 6876 $compute-reg-and-maybe-emit-spill:end: - 6877 # return output - 6878 89/<- %eax 1/r32/ecx - 6879 # . restore registers - 6880 59/pop-to-ecx - 6881 # . epilogue - 6882 89/<- %esp 5/r32/ebp - 6883 5d/pop-to-ebp - 6884 c3/return - 6885 - 6886 $compute-reg-and-maybe-emit-spill:abort: - 6887 # error("var '" var->name "' initialized from an instruction must live in a register\n") - 6888 (write-buffered Stderr "var '") - 6889 (write-buffered Stderr *eax) # Var-name - 6890 (write-buffered Stderr "' initialized from an instruction must live in a register\n") - 6891 (flush Stderr) - 6892 # . syscall(exit, 1) - 6893 bb/copy-to-ebx 1/imm32 - 6894 b8/copy-to-eax 1/imm32/exit - 6895 cd/syscall 0x80/imm8 - 6896 # never gets here - 6897 - 6898 emit-subx-cleanup-and-unconditional-nonlocal-branch: # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack (handle var)) - 6899 # . prologue - 6900 55/push-ebp - 6901 89/<- %ebp 4/r32/esp - 6902 # . save registers - 6903 50/push-eax - 6904 51/push-ecx - 6905 52/push-edx - 6906 # ecx = stmt - 6907 8b/-> *(ebp+0xc) 1/r32/ecx - 6908 # var target/edx: (addr array byte) = curr-stmt->inouts->value->name - 6909 8b/-> *(ecx+8) 2/r32/edx # Stmt1-inouts - 6910 8b/-> *edx 2/r32/edx # Stmt-var-value - 6911 8b/-> *edx 2/r32/edx # Var-name - 6912 # clean up until target block - 6913 (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %edx) - 6914 # emit jump to target block - 6915 (emit-indent *(ebp+8) *Curr-block-depth) - 6916 (write-buffered *(ebp+8) "e9/jump ") - 6917 (write-buffered *(ebp+8) %edx) - 6918 (string-starts-with? *(ecx+4) "break") - 6919 3d/compare-eax-and 0/imm32/false - 6920 { - 6921 74/jump-if-= break/disp8 - 6922 (write-buffered *(ebp+8) ":break/disp32\n") - 6923 } - 6924 3d/compare-eax-and 0/imm32/false # just in case the function call modified flags - 6925 { - 6926 75/jump-if-!= break/disp8 - 6927 (write-buffered *(ebp+8) ":loop/disp32\n") - 6928 } - 6929 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end: - 6930 # . restore registers - 6931 5a/pop-to-edx - 6932 59/pop-to-ecx - 6933 58/pop-to-eax - 6934 # . epilogue - 6935 89/<- %esp 5/r32/ebp - 6936 5d/pop-to-ebp - 6937 c3/return - 6938 - 6939 is-mu-branch?: # stmt: (addr stmt1) -> result/eax: boolean - 6940 # . prologue - 6941 55/push-ebp - 6942 89/<- %ebp 4/r32/esp - 6943 # . save registers - 6944 51/push-ecx - 6945 # ecx = stmt - 6946 8b/-> *(ebp+8) 1/r32/ecx - 6947 # if (stmt->operation starts with "loop") return true - 6948 (string-starts-with? *(ecx+4) "loop") # Stmt1-operation => eax - 6949 3d/compare-eax-and 0/imm32/false - 6950 75/jump-if-not-equal $is-mu-branch?:end/disp8 - 6951 # otherwise return (stmt->operation starts with "break") - 6952 (string-starts-with? *(ecx+4) "break") # Stmt1-operation => eax - 6953 $is-mu-branch?:end: - 6954 # . restore registers - 6955 59/pop-to-ecx - 6956 # . epilogue - 6957 89/<- %esp 5/r32/ebp - 6958 5d/pop-to-ebp - 6959 c3/return - 6960 - 6961 emit-reverse-break: # out: (addr buffered-file), stmt: (addr stmt1) - 6962 # . prologue - 6963 55/push-ebp - 6964 89/<- %ebp 4/r32/esp - 6965 # . save registers - 6966 50/push-eax - 6967 # eax = stmt - 6968 8b/-> *(ebp+0xc) 0/r32/eax - 6969 # - 6970 (get Reverse-branch *(eax+4) 8 "reverse-branch: ") # Stmt1-operation => eax: (addr addr array byte) - 6971 (emit-indent *(ebp+8) *Curr-block-depth) - 6972 (write-buffered *(ebp+8) *eax) - 6973 (write-buffered *(ebp+8) " break/disp32\n") - 6974 $emit-reverse-break:end: - 6975 # . restore registers - 6976 58/pop-to-eax - 6977 # . epilogue - 6978 89/<- %esp 5/r32/ebp - 6979 5d/pop-to-ebp - 6980 c3/return - 6981 - 6982 == data - 6983 - 6984 Reverse-branch: # (table string string) - 6985 # a table is a stream - 6986 0xa0/imm32/write - 6987 0/imm32/read - 6988 0xa0/imm32/length - 6989 # data - 6990 "break-if-="/imm32 "0f 85/jump-if-!="/imm32 - 6991 "loop-if-="/imm32 "0f 85/jump-if-!="/imm32 - 6992 "break-if-!="/imm32 "0f 84/jump-if-="/imm32 - 6993 "loop-if-!="/imm32 "0f 84/jump-if-="/imm32 - 6994 "break-if-<"/imm32 "0f 8d/jump-if->="/imm32 - 6995 "loop-if-<"/imm32 "0f 8d/jump-if->="/imm32 - 6996 "break-if->"/imm32 "0f 8e/jump-if-<="/imm32 - 6997 "loop-if->"/imm32 "0f 8e/jump-if-<="/imm32 - 6998 "break-if-<="/imm32 "0f 87/jump-if->"/imm32 - 6999 "loop-if-<="/imm32 "0f 87/jump-if->"/imm32 - 7000 "break-if->="/imm32 "0f 8c/jump-if-<"/imm32 - 7001 "loop-if->="/imm32 "0f 8c/jump-if-<"/imm32 - 7002 "break-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 - 7003 "loop-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 - 7004 "break-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 - 7005 "loop-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 - 7006 "break-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 - 7007 "loop-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 - 7008 "break-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 - 7009 "loop-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 - 7010 - 7011 == code - 7012 - 7013 emit-unconditional-jump-to-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), depth: int, label-suffix: (addr array byte) - 7014 # . prologue - 7015 55/push-ebp - 7016 89/<- %ebp 4/r32/esp - 7017 # . save registers - 7018 50/push-eax - 7019 51/push-ecx - 7020 52/push-edx - 7021 53/push-ebx - 7022 # ecx = vars - 7023 8b/-> *(ebp+0xc) 1/r32/ecx - 7024 # var eax: int = vars->top - 7025 8b/-> *ecx 0/r32/eax - 7026 # var min/ecx: (address (handle var)) = vars->data - 7027 81 0/subop/add %ecx 8/imm32 - 7028 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] - 7029 81 5/subop/subtract %eax 4/imm32 - 7030 8d/copy-address *(ecx+eax) 0/r32/eax - 7031 # edx = depth - 7032 8b/-> *(ebp+0x10) 2/r32/edx - 7033 { - 7034 $emit-unconditional-jump-to-depth:loop: - 7035 # if (curr < min) break - 7036 39/compare %eax 1/r32/ecx - 7037 0f 82/jump-if-addr< break/disp32 - 7038 # var v/ebx: (handle var) = *curr - 7039 8b/-> *eax 3/r32/ebx - 7040 # if (v->block-depth < until-block-depth) break - 7041 39/compare *(ebx+8) 2/r32/edx # Var-block-depth - 7042 0f 8c/jump-if-< break/disp32 - 7043 { - 7044 $emit-unconditional-jump-to-depth:check: - 7045 # if v->block-depth != until-block-depth, continue - 7046 39/compare *(ebx+8) 2/r32/edx # Var-block-depth - 7047 0f 85/jump-if-!= break/disp32 - 7048 $emit-unconditional-jump-to-depth:depth-found: - 7049 # if v is not a literal, continue - 7050 # . var eax: int = size-of(v) - 7051 50/push-eax - 7052 (size-of %ebx) # => eax - 7053 # . if (eax != 0) continue - 7054 3d/compare-eax-and 0/imm32 - 7055 58/pop-to-eax - 7056 # - 7057 0f 85/jump-if-!= break/disp32 - 7058 $emit-unconditional-jump-to-depth:label-found: - 7059 # emit unconditional jump, then return - 7060 (emit-indent *(ebp+8) *Curr-block-depth) - 7061 (write-buffered *(ebp+8) "e9/jump ") - 7062 (write-buffered *(ebp+8) *ebx) # Var-name - 7063 (write-buffered *(ebp+8) ":") - 7064 (write-buffered *(ebp+8) *(ebp+0x14)) - 7065 (write-buffered *(ebp+8) "/disp32\n") - 7066 eb/jump $emit-unconditional-jump-to-depth:end/disp8 - 7067 } - 7068 # curr -= 4 - 7069 2d/subtract-from-eax 4/imm32 - 7070 e9/jump loop/disp32 - 7071 } - 7072 # TODO: error if no label at 'depth' was found - 7073 $emit-unconditional-jump-to-depth:end: - 7074 # . restore registers - 7075 5b/pop-to-ebx - 7076 5a/pop-to-edx - 7077 59/pop-to-ecx - 7078 58/pop-to-eax - 7079 # . epilogue - 7080 89/<- %esp 5/r32/ebp - 7081 5d/pop-to-ebp - 7082 c3/return - 7083 - 7084 # emit clean-up code for 'vars' until some block depth - 7085 # doesn't actually modify 'vars' so we need traverse manually inside the stack - 7086 emit-cleanup-code-until-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-depth: int - 7087 # . prologue - 7088 55/push-ebp - 7089 89/<- %ebp 4/r32/esp - 7090 # . save registers - 7091 50/push-eax - 7092 51/push-ecx - 7093 52/push-edx - 7094 53/push-ebx - 7095 # ecx = vars - 7096 8b/-> *(ebp+0xc) 1/r32/ecx - 7097 # var eax: int = vars->top - 7098 8b/-> *ecx 0/r32/eax - 7099 # var min/ecx: (address (handle var)) = vars->data - 7100 81 0/subop/add %ecx 8/imm32 - 7101 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] - 7102 81 5/subop/subtract %eax 4/imm32 - 7103 8d/copy-address *(ecx+eax) 0/r32/eax - 7104 # edx = until-block-depth - 7105 8b/-> *(ebp+0x10) 2/r32/edx - 7106 { - 7107 $emit-cleanup-code-until-depth:loop: - 7108 # if (curr < min) break - 7109 39/compare %eax 1/r32/ecx - 7110 0f 82/jump-if-addr< break/disp32 - 7111 # var v/ebx: (handle var) = *curr - 7112 8b/-> *eax 3/r32/ebx - 7113 # if (v->block-depth < until-block-depth) break - 7114 39/compare *(ebx+8) 2/r32/edx # Var-block-depth - 7115 0f 8c/jump-if-< break/disp32 - 7116 # if v is in a register - 7117 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register - 7118 { - 7119 0f 84/jump-if-= break/disp32 - 7120 50/push-eax - 7121 { - 7122 $emit-cleanup-code-until-depth:check-for-previous-spill: - 7123 (same-register-spilled-before? %ebx *(ebp+0xc) %eax) # => eax - 7124 3d/compare-eax-and 0/imm32/false - 7125 0f 85/jump-if-!= break/disp32 - 7126 $emit-cleanup-code-until-depth:reclaim-var-in-register: - 7127 (emit-indent *(ebp+8) *Curr-block-depth) - 7128 (write-buffered *(ebp+8) "8f 0/subop/pop %") - 7129 (write-buffered *(ebp+8) *(ebx+0x10)) - 7130 (write-buffered *(ebp+8) Newline) - 7131 } - 7132 58/pop-to-eax - 7133 eb/jump $emit-cleanup-code-until-depth:continue/disp8 - 7134 } - 7135 # otherwise v is on the stack - 7136 { - 7137 75/jump-if-!= break/disp8 - 7138 $emit-cleanup-code-until-depth:reclaim-var-on-stack: - 7139 50/push-eax - 7140 (size-of %ebx) # => eax - 7141 # don't emit code for labels - 7142 3d/compare-eax-and 0/imm32 - 7143 74/jump-if-= break/disp8 - 7144 # - 7145 (emit-indent *(ebp+8) *Curr-block-depth) - 7146 (write-buffered *(ebp+8) "81 0/subop/add %esp ") - 7147 (print-int32-buffered *(ebp+8) %eax) - 7148 (write-buffered *(ebp+8) "/imm32\n") - 7149 58/pop-to-eax - 7150 } - 7151 $emit-cleanup-code-until-depth:continue: - 7152 # curr -= 4 - 7153 2d/subtract-from-eax 4/imm32 - 7154 e9/jump loop/disp32 + 6651 # . epilogue + 6652 89/<- %esp 5/r32/ebp + 6653 5d/pop-to-ebp + 6654 c3/return + 6655 + 6656 size-of-array: # a: (handle tree type-id) -> result/eax: int + 6657 # . prologue + 6658 55/push-ebp + 6659 89/<- %ebp 4/r32/esp + 6660 # . save registers + 6661 51/push-ecx + 6662 52/push-edx + 6663 # + 6664 8b/-> *(ebp+8) 1/r32/ecx + 6665 # TODO: assert that a->left is 'array' + 6666 8b/-> *(ecx+8) 1/r32/ecx # Tree-right + 6667 # var elem-type/edx: type-id = a->right->value + 6668 8b/-> *(ecx+4) 2/r32/edx # Tree-value + 6669 8b/-> *(edx+4) 2/r32/edx # Tree-value + 6670 # var array-size/ecx: int = a->right->right->left->value + 6671 8b/-> *(ecx+8) 1/r32/ecx # Tree-right + 6672 8b/-> *(ecx+4) 1/r32/ecx # Tree-left + 6673 8b/-> *(ecx+4) 1/r32/ecx # Tree-value + 6674 # return array-size * size-of(elem-type) + 6675 (size-of-type-id %edx) # => eax + 6676 f7 4/subop/multiply-into-eax %ecx + 6677 05/add-to-eax 4/imm32 # for array size + 6678 $size-of-array:end: + 6679 # . restore registers + 6680 5a/pop-to-edx + 6681 59/pop-to-ecx + 6682 # . epilogue + 6683 89/<- %esp 5/r32/ebp + 6684 5d/pop-to-ebp + 6685 c3/return + 6686 + 6687 size-of-type-id: # t: type-id -> result/eax: int + 6688 # . prologue + 6689 55/push-ebp + 6690 89/<- %ebp 4/r32/esp + 6691 # + 6692 8b/-> *(ebp+8) 0/r32/eax + 6693 # if v is a literal, return 0 + 6694 3d/compare-eax-and 0/imm32 + 6695 74/jump-if-= $size-of-type-id:end/disp8 # eax changes type from type-id to int + 6696 # if v has a user-defined type, return its size + 6697 # TODO: support non-atom type + 6698 (find-typeinfo %eax) # => eax + 6699 { + 6700 3d/compare-eax-and 0/imm32 + 6701 74/jump-if-= break/disp8 + 6702 $size-of-type-id:user-defined: + 6703 8b/-> *(eax+8) 0/r32/eax # Typeinfo-total-size-in-bytes + 6704 eb/jump $size-of-type-id:end/disp8 + 6705 } + 6706 # otherwise return the word size + 6707 b8/copy-to-eax 4/imm32 + 6708 $size-of-type-id:end: + 6709 # . epilogue + 6710 89/<- %esp 5/r32/ebp + 6711 5d/pop-to-ebp + 6712 c3/return + 6713 + 6714 type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean + 6715 # . prologue + 6716 55/push-ebp + 6717 89/<- %ebp 4/r32/esp + 6718 # . save registers + 6719 51/push-ecx + 6720 52/push-edx + 6721 # ecx = a + 6722 8b/-> *(ebp+8) 1/r32/ecx + 6723 # edx = b + 6724 8b/-> *(ebp+0xc) 2/r32/edx + 6725 # if (a == b) return true + 6726 8b/-> %ecx 0/r32/eax # Var-type + 6727 39/compare %edx 0/r32/eax # Var-type + 6728 b8/copy-to-eax 1/imm32/true + 6729 74/jump-if-= $type-equal?:end/disp8 + 6730 # if (a < MAX_TYPE_ID) return false + 6731 81 7/subop/compare %ecx 0x10000/imm32 + 6732 b8/copy-to-eax 0/imm32/false + 6733 72/jump-if-addr< $type-equal?:end/disp8 + 6734 # if (b < MAX_TYPE_ID) return false + 6735 81 7/subop/compare %edx 0x10000/imm32 + 6736 b8/copy-to-eax 0/imm32/false + 6737 72/jump-if-addr< $type-equal?:end/disp8 + 6738 # if (!type-equal?(a->left, b->left)) return false + 6739 (type-equal? *(ecx+4) *(edx+4)) # Tree-left, Tree-left => eax + 6740 3d/compare-eax-and 0/imm32/false + 6741 74/jump-if-= $type-equal?:end/disp8 + 6742 # return type-equal?(a->right, b->right) + 6743 (type-equal? *(ecx+8) *(edx+8)) # Tree-right, Tree-right => eax + 6744 $type-equal?:end: + 6745 # . restore registers + 6746 5a/pop-to-edx + 6747 59/pop-to-ecx + 6748 # . epilogue + 6749 89/<- %esp 5/r32/ebp + 6750 5d/pop-to-ebp + 6751 c3/return + 6752 + 6753 ####################################################### + 6754 # Code-generation + 6755 ####################################################### + 6756 + 6757 == data + 6758 + 6759 Curr-block-depth: # (addr int) + 6760 0/imm32 + 6761 Curr-local-stack-offset: # (addr int) + 6762 0/imm32 + 6763 + 6764 == code + 6765 + 6766 emit-subx: # out: (addr buffered-file) + 6767 # . prologue + 6768 55/push-ebp + 6769 89/<- %ebp 4/r32/esp + 6770 # . save registers + 6771 50/push-eax + 6772 51/push-ecx + 6773 57/push-edi + 6774 # edi = out + 6775 8b/-> *(ebp+8) 7/r32/edi + 6776 # var curr/ecx: (handle function) = *Program->functions + 6777 8b/-> *_Program-functions 1/r32/ecx + 6778 { + 6779 # if (curr == null) break + 6780 81 7/subop/compare %ecx 0/imm32 + 6781 0f 84/jump-if-= break/disp32 + 6782 (emit-subx-function %edi %ecx) + 6783 # curr = curr->next + 6784 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next + 6785 e9/jump loop/disp32 + 6786 } + 6787 $emit-subx:end: + 6788 # . restore registers + 6789 5f/pop-to-edi + 6790 59/pop-to-ecx + 6791 58/pop-to-eax + 6792 # . epilogue + 6793 89/<- %esp 5/r32/ebp + 6794 5d/pop-to-ebp + 6795 c3/return + 6796 + 6797 emit-subx-function: # out: (addr buffered-file), f: (handle function) + 6798 # . prologue + 6799 55/push-ebp + 6800 89/<- %ebp 4/r32/esp + 6801 # some preprocessing + 6802 (populate-mu-type-offsets-in-inouts *(ebp+0xc)) + 6803 # . save registers + 6804 50/push-eax + 6805 51/push-ecx + 6806 52/push-edx + 6807 57/push-edi + 6808 # edi = out + 6809 8b/-> *(ebp+8) 7/r32/edi + 6810 # ecx = f + 6811 8b/-> *(ebp+0xc) 1/r32/ecx + 6812 # var vars/edx: (stack (addr var) 256) + 6813 81 5/subop/subtract %esp 0x400/imm32 + 6814 68/push 0x400/imm32/size + 6815 68/push 0/imm32/top + 6816 89/<- %edx 4/r32/esp + 6817 # + 6818 (write-buffered %edi *ecx) + 6819 (write-buffered %edi ":\n") + 6820 # initialize some global state + 6821 c7 0/subop/copy *Curr-block-depth 1/imm32 + 6822 c7 0/subop/copy *Curr-local-stack-offset 0/imm32 + 6823 # + 6824 (emit-subx-prologue %edi) + 6825 (emit-subx-block %edi *(ecx+0x10) %edx) # Function-body + 6826 (emit-subx-epilogue %edi) + 6827 # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have + 6828 # been cleaned up + 6829 $emit-subx-function:end: + 6830 # . reclaim locals + 6831 81 0/subop/add %esp 408/imm32 + 6832 # . restore registers + 6833 5f/pop-to-edi + 6834 5a/pop-to-edx + 6835 59/pop-to-ecx + 6836 58/pop-to-eax + 6837 # . epilogue + 6838 89/<- %esp 5/r32/ebp + 6839 5d/pop-to-ebp + 6840 c3/return + 6841 + 6842 populate-mu-type-offsets-in-inouts: # f: (handle function) + 6843 # . prologue + 6844 55/push-ebp + 6845 89/<- %ebp 4/r32/esp + 6846 # . save registers + 6847 50/push-eax + 6848 51/push-ecx + 6849 52/push-edx + 6850 53/push-ebx + 6851 57/push-edi + 6852 # var next-offset/edx: int = 8 + 6853 ba/copy-to-edx 8/imm32 + 6854 # var curr/ecx: (handle list var) = f->inouts + 6855 8b/-> *(ebp+8) 1/r32/ecx + 6856 8b/-> *(ecx+8) 1/r32/ecx # Function-inouts + 6857 { + 6858 $populate-mu-type-offsets-in-inouts:loop: + 6859 81 7/subop/compare %ecx 0/imm32 + 6860 74/jump-if-= break/disp8 + 6861 # var v/ebx: (handle var) = curr->value + 6862 8b/-> *ecx 3/r32/ebx # List-value + 6863 # v->offset = next-offset + 6864 89/<- *(ebx+0xc) 2/r32/edx # Var-offset + 6865 # next-offset += size-of(v) + 6866 (size-of %ebx) # => eax + 6867 01/add-to %edx 0/r32/eax + 6868 # curr = curr->next + 6869 8b/-> *(ecx+4) 1/r32/ecx # List-next + 6870 eb/jump loop/disp8 + 6871 } + 6872 $populate-mu-type-offsets-in-inouts:end: + 6873 # . restore registers + 6874 5f/pop-to-edi + 6875 5b/pop-to-ebx + 6876 5a/pop-to-edx + 6877 59/pop-to-ecx + 6878 58/pop-to-eax + 6879 # . epilogue + 6880 89/<- %esp 5/r32/ebp + 6881 5d/pop-to-ebp + 6882 c3/return + 6883 + 6884 emit-subx-stmt-list: # out: (addr buffered-file), stmts: (handle list stmt), vars: (addr stack (handle var)) + 6885 # . prologue + 6886 55/push-ebp + 6887 89/<- %ebp 4/r32/esp + 6888 # . save registers + 6889 50/push-eax + 6890 51/push-ecx + 6891 52/push-edx + 6892 53/push-ebx + 6893 56/push-esi + 6894 # esi = stmts + 6895 8b/-> *(ebp+0xc) 6/r32/esi + 6896 # var var-seen?/edx: boolean <- copy false + 6897 ba/copy-to-edx 0/imm32/false + 6898 # + 6899 { + 6900 $emit-subx-stmt-list:loop: + 6901 81 7/subop/compare %esi 0/imm32 + 6902 0f 84/jump-if-= break/disp32 + 6903 # var curr-stmt/ecx = stmts->value + 6904 8b/-> *esi 1/r32/ecx # List-value + 6905 { + 6906 $emit-subx-stmt-list:check-for-block: + 6907 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag + 6908 75/jump-if-!= break/disp8 + 6909 $emit-subx-stmt-list:block: + 6910 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10)) + 6911 } + 6912 { + 6913 $emit-subx-stmt-list:check-for-stmt: + 6914 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag + 6915 0f 85/jump-if-!= break/disp32 + 6916 $emit-subx-stmt-list:stmt1: + 6917 { + 6918 (is-mu-branch? %ecx) # => eax + 6919 3d/compare-eax-and 0/imm32/false + 6920 0f 84/jump-if-= break/disp32 + 6921 $emit-subx-stmt-list:branch-stmt: + 6922 # if !var-seen? break + 6923 81 7/subop/compare %edx 0/imm32/false + 6924 0f 84/jump-if-= break/disp32 + 6925 $emit-subx-stmt-list:branch-stmt-and-var-seen: + 6926 +-- 26 lines: # unconditional loops -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 6952 +-- 15 lines: # unconditional breaks ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 6967 +-- 37 lines: # simple conditional branches without a target ------------------------------------------------------------------------------------------------------------------------------------------------------- + 7004 +-- 19 lines: # conditional branches with an explicit target ------------------------------------------------------------------------------------------------------------------------------------------------------- + 7023 } + 7024 $emit-subx-stmt-list:1-to-1: + 7025 (emit-subx-stmt *(ebp+8) %ecx Primitives) + 7026 } + 7027 { + 7028 $emit-subx-stmt-list:check-for-var-def: + 7029 81 7/subop/compare *ecx 2/imm32/var-def # Stmt-tag + 7030 75/jump-if-!= break/disp8 + 7031 $emit-subx-stmt-list:var-def: + 7032 (emit-subx-var-def *(ebp+8) %ecx) + 7033 (push *(ebp+0x10) *(ecx+4)) # Vardef-var + 7034 # var-seen? = true + 7035 ba/copy-to-edx 1/imm32/true + 7036 } + 7037 { + 7038 $emit-subx-stmt-list:check-for-reg-var-def: + 7039 81 7/subop/compare *ecx 3/imm32/reg-var-def # Stmt-tag + 7040 0f 85/jump-if-!= break/disp32 + 7041 $emit-subx-stmt-list:reg-var-def: + 7042 # TODO: ensure that there's exactly one output + 7043 (compute-reg-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10)) + 7044 # register variable definition + 7045 (push *(ebp+0x10) %eax) + 7046 # emit the instruction as usual + 7047 (emit-subx-stmt *(ebp+8) %ecx Primitives) + 7048 # var-seen? = true + 7049 ba/copy-to-edx 1/imm32/true + 7050 } + 7051 $emit-subx-stmt-list:continue: + 7052 # TODO: raise an error on unrecognized Stmt-tag + 7053 8b/-> *(esi+4) 6/r32/esi # List-next + 7054 e9/jump loop/disp32 + 7055 } + 7056 $emit-subx-stmt-list:emit-cleanup: + 7057 (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth) + 7058 $emit-subx-stmt-list:cleanup: + 7059 (clean-up-blocks *(ebp+0x10) *Curr-block-depth) + 7060 $emit-subx-stmt-list:end: + 7061 # . restore registers + 7062 5e/pop-to-esi + 7063 5b/pop-to-ebx + 7064 5a/pop-to-edx + 7065 59/pop-to-ecx + 7066 58/pop-to-eax + 7067 # . epilogue + 7068 89/<- %esp 5/r32/ebp + 7069 5d/pop-to-ebp + 7070 c3/return + 7071 + 7072 compute-reg-and-maybe-emit-spill: # out: (addr buffered-file), stmt: (handle reg-var-def), vars: (addr stack (handle var)) -> result/eax: (handle var) + 7073 # . prologue + 7074 55/push-ebp + 7075 89/<- %ebp 4/r32/esp + 7076 # . save registers + 7077 51/push-ecx + 7078 # ecx = stmt + 7079 8b/-> *(ebp+0xc) 1/r32/ecx + 7080 # var output/ecx: (handle var) = curr-stmt->outputs->value + 7081 8b/-> *(ecx+0xc) 1/r32/ecx # Regvardef-inouts + 7082 8b/-> *ecx 1/r32/ecx # List-value + 7083 # v->block-depth = *Curr-block-depth + 7084 8b/-> *Curr-block-depth 0/r32/eax + 7085 89/<- *(ecx+8) 0/r32/eax # Var-block-depth + 7086 # var reg/eax: (handle array byte) = output->register + 7087 8b/-> *(ecx+0x10) 0/r32/eax # Var-register + 7088 # ensure that output is in a register + 7089 3d/compare-eax-and 0/imm32 + 7090 0f 84/jump-if-= $compute-reg-and-maybe-emit-spill:abort/disp32 + 7091 # if already-spilled-this-block?(reg, vars) return + 7092 (already-spilled-this-block? %ecx *(ebp+0x10)) # => eax + 7093 3d/compare-eax-and 0/imm32/false + 7094 75/jump-if-!= $compute-reg-and-maybe-emit-spill:end/disp8 + 7095 # TODO: assert(size-of(output) == 4) + 7096 # *Curr-local-stack-offset -= 4 + 7097 81 5/subop/subtract *Curr-local-stack-offset 4/imm32 + 7098 # emit spill + 7099 (emit-indent *(ebp+8) *Curr-block-depth) + 7100 (write-buffered *(ebp+8) "ff 6/subop/push %") + 7101 (write-buffered *(ebp+8) *(ecx+0x10)) # Var-register + 7102 (write-buffered *(ebp+8) Newline) + 7103 $compute-reg-and-maybe-emit-spill:end: + 7104 # return output + 7105 89/<- %eax 1/r32/ecx + 7106 # . restore registers + 7107 59/pop-to-ecx + 7108 # . epilogue + 7109 89/<- %esp 5/r32/ebp + 7110 5d/pop-to-ebp + 7111 c3/return + 7112 + 7113 $compute-reg-and-maybe-emit-spill:abort: + 7114 # error("var '" var->name "' initialized from an instruction must live in a register\n") + 7115 (write-buffered Stderr "var '") + 7116 (write-buffered Stderr *eax) # Var-name + 7117 (write-buffered Stderr "' initialized from an instruction must live in a register\n") + 7118 (flush Stderr) + 7119 # . syscall(exit, 1) + 7120 bb/copy-to-ebx 1/imm32 + 7121 b8/copy-to-eax 1/imm32/exit + 7122 cd/syscall 0x80/imm8 + 7123 # never gets here + 7124 + 7125 emit-subx-cleanup-and-unconditional-nonlocal-branch: # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack (handle var)) + 7126 # . prologue + 7127 55/push-ebp + 7128 89/<- %ebp 4/r32/esp + 7129 # . save registers + 7130 50/push-eax + 7131 51/push-ecx + 7132 52/push-edx + 7133 # ecx = stmt + 7134 8b/-> *(ebp+0xc) 1/r32/ecx + 7135 # var target/edx: (addr array byte) = curr-stmt->inouts->value->name + 7136 8b/-> *(ecx+8) 2/r32/edx # Stmt1-inouts + 7137 8b/-> *edx 2/r32/edx # Stmt-var-value + 7138 8b/-> *edx 2/r32/edx # Var-name + 7139 # clean up until target block + 7140 (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %edx) + 7141 # emit jump to target block + 7142 (emit-indent *(ebp+8) *Curr-block-depth) + 7143 (write-buffered *(ebp+8) "e9/jump ") + 7144 (write-buffered *(ebp+8) %edx) + 7145 (string-starts-with? *(ecx+4) "break") + 7146 3d/compare-eax-and 0/imm32/false + 7147 { + 7148 74/jump-if-= break/disp8 + 7149 (write-buffered *(ebp+8) ":break/disp32\n") + 7150 } + 7151 3d/compare-eax-and 0/imm32/false # just in case the function call modified flags + 7152 { + 7153 75/jump-if-!= break/disp8 + 7154 (write-buffered *(ebp+8) ":loop/disp32\n") 7155 } - 7156 $emit-cleanup-code-until-depth:end: + 7156 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end: 7157 # . restore registers - 7158 5b/pop-to-ebx - 7159 5a/pop-to-edx - 7160 59/pop-to-ecx - 7161 58/pop-to-eax - 7162 # . epilogue - 7163 89/<- %esp 5/r32/ebp - 7164 5d/pop-to-ebp - 7165 c3/return - 7166 - 7167 # emit clean-up code for 'vars' until a given label is encountered - 7168 # doesn't actually modify 'vars' so we need traverse manually inside the stack - 7169 emit-cleanup-code-until-target: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-label: (addr array byte) - 7170 # . prologue - 7171 55/push-ebp - 7172 89/<- %ebp 4/r32/esp - 7173 # . save registers - 7174 50/push-eax - 7175 51/push-ecx - 7176 52/push-edx - 7177 53/push-ebx - 7178 # ecx = vars - 7179 8b/-> *(ebp+0xc) 1/r32/ecx - 7180 # var eax: int = vars->top - 7181 8b/-> *ecx 0/r32/eax - 7182 # var min/ecx: (address (handle var)) = vars->data - 7183 81 0/subop/add %ecx 8/imm32 - 7184 # var curr/edx: (address (handle var)) = &vars->data[vars->top - 4] - 7185 81 5/subop/subtract %eax 4/imm32 - 7186 8d/copy-address *(ecx+eax) 2/r32/edx - 7187 { - 7188 $emit-cleanup-code-until-target:loop: - 7189 # if (curr < min) break - 7190 39/compare %edx 1/r32/ecx - 7191 0f 82/jump-if-addr< break/disp32 - 7192 # var v/ebx: (handle var) = *curr - 7193 8b/-> *edx 3/r32/ebx - 7194 # if (v->name == until-block-label) break - 7195 (string-equal? *ebx *(ebp+0x10)) # => eax - 7196 3d/compare-eax-and 0/imm32/false - 7197 0f 85/jump-if-!= break/disp32 - 7198 # if v is in a register - 7199 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register - 7200 { - 7201 74/jump-if-= break/disp8 - 7202 50/push-eax - 7203 { - 7204 $emit-cleanup-code-until-target:check-for-previous-spill: - 7205 (same-register-spilled-before? %ebx *(ebp+0xc) %edx) # => eax - 7206 3d/compare-eax-and 0/imm32/false - 7207 75/jump-if-!= break/disp8 - 7208 $emit-cleanup-code-until-target:reclaim-var-in-register: - 7209 (emit-indent *(ebp+8) *Curr-block-depth) - 7210 (write-buffered *(ebp+8) "8f 0/subop/pop %") - 7211 (write-buffered *(ebp+8) *(ebx+0x10)) - 7212 (write-buffered *(ebp+8) Newline) - 7213 } - 7214 58/pop-to-eax - 7215 eb/jump $emit-cleanup-code-until-target:continue/disp8 - 7216 } - 7217 # otherwise v is on the stack - 7218 { - 7219 75/jump-if-!= break/disp8 - 7220 $emit-cleanup-code-until-target:reclaim-var-on-stack: - 7221 (size-of %ebx) # => eax - 7222 # don't emit code for labels - 7223 3d/compare-eax-and 0/imm32 - 7224 74/jump-if-= break/disp8 - 7225 # - 7226 (emit-indent *(ebp+8) *Curr-block-depth) - 7227 (write-buffered *(ebp+8) "81 0/subop/add %esp ") - 7228 (print-int32-buffered *(ebp+8) %eax) - 7229 (write-buffered *(ebp+8) "/imm32\n") - 7230 } - 7231 $emit-cleanup-code-until-target:continue: - 7232 # curr -= 4 - 7233 81 5/subop/subtract %edx 4/imm32 - 7234 e9/jump loop/disp32 - 7235 } - 7236 $emit-cleanup-code-until-target:end: - 7237 # . restore registers - 7238 5b/pop-to-ebx - 7239 5a/pop-to-edx - 7240 59/pop-to-ecx - 7241 58/pop-to-eax - 7242 # . epilogue - 7243 89/<- %esp 5/r32/ebp - 7244 5d/pop-to-ebp - 7245 c3/return - 7246 - 7247 # is there already a var with the same block-depth and register as 'v' on the 'vars' stack? - 7248 # v is guaranteed not to be within vars - 7249 already-spilled-this-block?: # v: (handle var), vars: (addr stack (handle var)) -> result/eax: boolean - 7250 # . prologue - 7251 55/push-ebp - 7252 89/<- %ebp 4/r32/esp - 7253 # . save registers - 7254 51/push-ecx - 7255 52/push-edx - 7256 53/push-ebx - 7257 56/push-esi - 7258 57/push-edi - 7259 # ecx = vars - 7260 8b/-> *(ebp+0xc) 1/r32/ecx - 7261 # var eax: int = vars->top - 7262 8b/-> *ecx 0/r32/eax - 7263 # var min/ecx: (address (handle var)) = vars->data - 7264 81 0/subop/add %ecx 8/imm32 - 7265 # var curr/edx: (address (handle var)) = &vars->data[vars->top - 4] - 7266 81 5/subop/subtract %eax 4/imm32 - 7267 8d/copy-address *(ecx+eax) 2/r32/edx - 7268 # var depth/ebx: int = v->block-depth - 7269 8b/-> *(ebp+8) 3/r32/ebx - 7270 8b/-> *(ebx+8) 3/r32/ebx # Var-block-depth - 7271 # var needle/esi: (handle array byte) = v->register - 7272 8b/-> *(ebp+8) 6/r32/esi - 7273 8b/-> *(esi+0x10) 6/r32/esi # Var-register - 7274 { - 7275 $already-spilled-this-block?:loop: - 7276 # if (curr < min) break - 7277 39/compare %edx 1/r32/ecx - 7278 0f 82/jump-if-addr< break/disp32 - 7279 # var cand/edi: (handle var) = *curr - 7280 8b/-> *edx 7/r32/edi - 7281 # if (cand->block-depth < depth) break - 7282 39/compare *(edi+8) 3/r32/ebx # Var-block-depth - 7283 0f 8c/jump-if-< break/disp32 - 7284 # var cand-reg/edi: (handle array byte) = cand->reg - 7285 8b/-> *(edi+0x10) 7/r32/edi - 7286 # if (cand-reg == null) continue - 7287 { - 7288 $already-spilled-this-block?:check-reg: - 7289 81 7/subop/compare %edi 0/imm32 - 7290 74/jump-if-= break/disp8 - 7291 # if (cand-reg == needle) return true - 7292 (string-equal? %esi %edi) # => eax - 7293 3d/compare-eax-and 0/imm32/false - 7294 74/jump-if-= break/disp8 - 7295 b8/copy-to-eax 1/imm32/true - 7296 eb/jump $already-spilled-this-block?:end/disp8 - 7297 } - 7298 $already-spilled-this-block?:continue: - 7299 # curr -= 4 - 7300 81 5/subop/subtract %edx 4/imm32 - 7301 e9/jump loop/disp32 - 7302 } - 7303 # return false - 7304 b8/copy-to-eax 0/imm32/false - 7305 $already-spilled-this-block?:end: - 7306 # . restore registers - 7307 5f/pop-to-edi - 7308 5e/pop-to-esi - 7309 5b/pop-to-ebx - 7310 5a/pop-to-edx - 7311 59/pop-to-ecx - 7312 # . epilogue - 7313 89/<- %esp 5/r32/ebp - 7314 5d/pop-to-ebp - 7315 c3/return - 7316 - 7317 # is there a var before 'v' with the same block-depth and register on the 'vars' stack? - 7318 # v is guaranteed to be within vars - 7319 # 'start' is provided as an optimization, a pointer within vars - 7320 # *start == v - 7321 same-register-spilled-before?: # v: (handle var), vars: (addr stack (handle var)), start: (addr (handle var)) -> result/eax: boolean - 7322 # . prologue - 7323 55/push-ebp - 7324 89/<- %ebp 4/r32/esp - 7325 # . save registers - 7326 51/push-ecx - 7327 52/push-edx - 7328 53/push-ebx - 7329 56/push-esi - 7330 57/push-edi - 7331 # ecx = v - 7332 8b/-> *(ebp+8) 1/r32/ecx - 7333 # var reg/edx: (handle array byte) = v->register - 7334 8b/-> *(ecx+0x10) 2/r32/edx # Var-register - 7335 # var depth/ebx: int = v->block-depth - 7336 8b/-> *(ecx+8) 3/r32/ebx # Var-block-depth - 7337 # var min/ecx: (address (handle var)) = vars->data - 7338 8b/-> *(ebp+0xc) 1/r32/ecx - 7339 81 0/subop/add %ecx 8/imm32 - 7340 # TODO: check that start >= min and start < &vars->data[top] - 7341 # TODO: check that *start == v - 7342 # var curr/esi: (address (handle var)) = start - 7343 8b/-> *(ebp+0x10) 6/r32/esi - 7344 # curr -= 4 - 7345 81 5/subop/subtract %esi 4/imm32 - 7346 { - 7347 $same-register-spilled-before?:loop: - 7348 # if (curr < min) break - 7349 39/compare %esi 1/r32/ecx - 7350 0f 82/jump-if-addr< break/disp32 - 7351 # var x/eax: (handle var) = *curr - 7352 8b/-> *esi 0/r32/eax - 7353 # if (x->block-depth < depth) break - 7354 39/compare *(eax+8) 3/r32/ebx # Var-block-depth - 7355 0f 8c/jump-if-< break/disp32 - 7356 # if (x->register == 0) continue - 7357 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register - 7358 74/jump-if-= $same-register-spilled-before?:continue/disp8 - 7359 # if (x->register == reg) return true - 7360 (string-equal? *(eax+0x10) %edx) # Var-register => eax - 7361 3d/compare-eax-and 0/imm32/false - 7362 75/jump-if-!= $same-register-spilled-before?:end/disp8 - 7363 $same-register-spilled-before?:continue: - 7364 # curr -= 4 - 7365 81 5/subop/subtract %esi 4/imm32 - 7366 e9/jump loop/disp32 - 7367 } - 7368 $same-register-spilled-before?:false: - 7369 b8/copy-to-eax 0/imm32/false - 7370 $same-register-spilled-before?:end: - 7371 # . restore registers - 7372 5f/pop-to-edi - 7373 5e/pop-to-esi - 7374 5b/pop-to-ebx - 7375 5a/pop-to-edx - 7376 59/pop-to-ecx - 7377 # . epilogue - 7378 89/<- %esp 5/r32/ebp - 7379 5d/pop-to-ebp - 7380 c3/return - 7381 - 7382 # clean up global state for 'vars' until some block depth - 7383 clean-up-blocks: # vars: (addr stack (handle var)), until-block-depth: int - 7384 # . prologue - 7385 55/push-ebp - 7386 89/<- %ebp 4/r32/esp - 7387 # . save registers - 7388 50/push-eax - 7389 51/push-ecx - 7390 56/push-esi - 7391 # esi = vars - 7392 8b/-> *(ebp+8) 6/r32/esi - 7393 # ecx = until-block-depth - 7394 8b/-> *(ebp+0xc) 1/r32/ecx - 7395 { - 7396 $clean-up-blocks:reclaim-loop: - 7397 # if (vars->top <= 0) break - 7398 81 7/subop/compare *esi 0/imm32 # Stack-top - 7399 7e/jump-if-<= break/disp8 - 7400 # var v/eax: (handle var) = top(vars) - 7401 (top %esi) # => eax - 7402 # if (v->block-depth < until-block-depth) break - 7403 39/compare *(eax+8) 1/r32/ecx # Var-block-depth - 7404 7c/jump-if-< break/disp8 - 7405 # if v is on the stack, update Curr-local-stack-offset - 7406 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register - 7407 { - 7408 75/jump-if-!= break/disp8 - 7409 $clean-up-blocks:reclaim-var-on-stack: - 7410 (size-of %eax) # => eax - 7411 01/add *Curr-local-stack-offset 0/r32/eax - 7412 } - 7413 (pop %esi) - 7414 e9/jump loop/disp32 - 7415 } - 7416 $clean-up-blocks:end: - 7417 # . restore registers - 7418 5e/pop-to-esi - 7419 59/pop-to-ecx - 7420 58/pop-to-eax - 7421 # . epilogue - 7422 89/<- %esp 5/r32/ebp - 7423 5d/pop-to-ebp - 7424 c3/return - 7425 - 7426 emit-subx-var-def: # out: (addr buffered-file), stmt: (handle stmt) - 7427 # . prologue - 7428 55/push-ebp - 7429 89/<- %ebp 4/r32/esp - 7430 # . save registers - 7431 50/push-eax - 7432 51/push-ecx - 7433 52/push-edx - 7434 # eax = stmt - 7435 8b/-> *(ebp+0xc) 0/r32/eax - 7436 # var v/ecx: (handle var) - 7437 8b/-> *(eax+4) 1/r32/ecx # Vardef-var - 7438 # v->block-depth = *Curr-block-depth - 7439 8b/-> *Curr-block-depth 0/r32/eax - 7440 89/<- *(ecx+8) 0/r32/eax # Var-block-depth - 7441 # var n/edx: int = size-of(stmt->var) - 7442 (size-of %ecx) # => eax - 7443 89/<- %edx 0/r32/eax - 7444 # *Curr-local-stack-offset -= n - 7445 29/subtract-from *Curr-local-stack-offset 2/r32/edx - 7446 # v->offset = *Curr-local-stack-offset - 7447 8b/-> *Curr-local-stack-offset 0/r32/eax - 7448 89/<- *(ecx+0xc) 0/r32/eax # Var-offset - 7449 # if v is an array, do something special - 7450 { - 7451 (is-mu-array? *(ecx+4)) # Var-type => eax - 7452 3d/compare-eax-and 0/imm32/false - 7453 0f 84/jump-if-= break/disp32 - 7454 # var array-size-without-length/edx: int = n-4 - 7455 81 5/subop/subtract %edx 4/imm32 - 7456 (emit-indent *(ebp+8) *Curr-block-depth) - 7457 (write-buffered *(ebp+8) "(push-n-zero-bytes ") - 7458 (print-int32-buffered *(ebp+8) %edx) - 7459 (write-buffered *(ebp+8) ")\n") - 7460 (emit-indent *(ebp+8) *Curr-block-depth) - 7461 (write-buffered *(ebp+8) "68/push ") - 7462 (print-int32-buffered *(ebp+8) %edx) - 7463 (write-buffered *(ebp+8) "/imm32\n") - 7464 eb/jump $emit-subx-var-def:end/disp8 - 7465 } - 7466 # while n > 0 - 7467 { - 7468 81 7/subop/compare %edx 0/imm32 - 7469 7e/jump-if-<= break/disp8 - 7470 (emit-indent *(ebp+8) *Curr-block-depth) - 7471 (write-buffered *(ebp+8) "68/push 0/imm32\n") - 7472 # n -= 4 - 7473 81 5/subop/subtract %edx 4/imm32 - 7474 # - 7475 eb/jump loop/disp8 - 7476 } - 7477 $emit-subx-var-def:end: - 7478 # . restore registers - 7479 5a/pop-to-edx - 7480 59/pop-to-ecx - 7481 58/pop-to-eax - 7482 # . epilogue - 7483 89/<- %esp 5/r32/ebp - 7484 5d/pop-to-ebp - 7485 c3/return - 7486 - 7487 emit-subx-stmt: # out: (addr buffered-file), stmt: (handle stmt), primitives: (handle primitive), functions: (handle function) - 7488 # . prologue - 7489 55/push-ebp - 7490 89/<- %ebp 4/r32/esp - 7491 # . save registers - 7492 50/push-eax - 7493 51/push-ecx - 7494 # - some special-case primitives that don't actually use the 'primitives' data structure - 7495 # ecx = stmt - 7496 8b/-> *(ebp+0xc) 1/r32/ecx - 7497 # array length - 7498 { - 7499 # if (!string-equal?(stmt->operation, "length")) break - 7500 (string-equal? *(ecx+4) "length") # Stmt1-operation => eax - 7501 3d/compare-eax-and 0/imm32 - 7502 0f 84/jump-if-= break/disp32 - 7503 (translate-mu-length-stmt *(ebp+8) *(ebp+0xc)) - 7504 e9/jump $emit-subx-stmt:end/disp32 - 7505 } - 7506 # index into array - 7507 { - 7508 # if (!string-equal?(var->operation, "index")) break - 7509 (string-equal? *(ecx+4) "index") # Stmt1-operation => eax - 7510 3d/compare-eax-and 0/imm32 - 7511 0f 84/jump-if-= break/disp32 - 7512 (translate-mu-index-stmt *(ebp+8) *(ebp+0xc)) - 7513 e9/jump $emit-subx-stmt:end/disp32 - 7514 } - 7515 # compute-offset for index into array - 7516 { - 7517 # if (!string-equal?(var->operation, "compute-offset")) break - 7518 (string-equal? *(ecx+4) "compute-offset") # Stmt1-operation => eax - 7519 3d/compare-eax-and 0/imm32 - 7520 0f 84/jump-if-= break/disp32 - 7521 (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc)) - 7522 e9/jump $emit-subx-stmt:end/disp32 - 7523 } - 7524 # get field from record - 7525 { - 7526 # if (!string-equal?(var->operation, "get")) break - 7527 (string-equal? *(ecx+4) "get") # Stmt1-operation => eax - 7528 3d/compare-eax-and 0/imm32 - 7529 0f 84/jump-if-= break/disp32 - 7530 (translate-mu-get-stmt *(ebp+8) *(ebp+0xc)) - 7531 e9/jump $emit-subx-stmt:end/disp32 - 7532 } - 7533 # - if stmt matches a primitive, emit it - 7534 { - 7535 $emit-subx-stmt:check-for-primitive: - 7536 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => curr/eax - 7537 3d/compare-eax-and 0/imm32 - 7538 74/jump-if-= break/disp8 - 7539 $emit-subx-stmt:primitive: - 7540 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr - 7541 e9/jump $emit-subx-stmt:end/disp32 - 7542 } - 7543 # - if stmt matches a function, emit a call to it - 7544 { - 7545 $emit-subx-stmt:check-for-call: - 7546 (find-matching-function *(ebp+0x14) *(ebp+0xc)) # functions, stmt => curr/eax - 7547 3d/compare-eax-and 0/imm32 - 7548 74/jump-if-= break/disp8 - 7549 $emit-subx-stmt:call: - 7550 (emit-subx-call *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr - 7551 e9/jump $emit-subx-stmt:end/disp32 - 7552 } - 7553 # otherwise, assume it's a SubX function (TODO: how to type-check?!) - 7554 (emit-hailmary-call *(ebp+8) *(ebp+0xc)) - 7555 $emit-subx-stmt:end: - 7556 # . restore registers - 7557 59/pop-to-ecx - 7558 58/pop-to-eax - 7559 # . epilogue - 7560 89/<- %esp 5/r32/ebp - 7561 5d/pop-to-ebp - 7562 c3/return - 7563 - 7564 translate-mu-length-stmt: # out: (address buffered-file), stmt: (handle stmt) - 7565 # . prologue - 7566 55/push-ebp - 7567 89/<- %ebp 4/r32/esp - 7568 # . save registers - 7569 50/push-eax - 7570 51/push-ecx - 7571 # ecx = stmt - 7572 8b/-> *(ebp+0xc) 1/r32/ecx - 7573 # - 7574 (emit-indent *(ebp+8) *Curr-block-depth) - 7575 (write-buffered *(ebp+8) "8b/copy-from *") - 7576 # var base/eax: (handle var) = inouts[0] - 7577 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts - 7578 8b/-> *eax 0/r32/eax # Stmt-var-value - 7579 # if base is an (address array ...) in a register - 7580 { - 7581 81 7/subop/compare *(eax+0x10)) 0/imm32 # Var-register - 7582 74/jump-if-= break/disp8 - 7583 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register - 7584 eb/jump $translate-mu-length-stmt:emit-output/disp8 - 7585 } - 7586 # otherwise if base is an (array ...) on the stack - 7587 { - 7588 81 7/subop/compare *(eax+0xc)) 0/imm32 # Var-offset - 7589 74/jump-if-= break/disp8 - 7590 (write-buffered *(ebp+8) "(ebp+") - 7591 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-offset - 7592 (write-buffered *(ebp+8) ")") - 7593 } - 7594 $translate-mu-length-stmt:emit-output: - 7595 (write-buffered *(ebp+8) " ") - 7596 # outputs[0] "/r32" - 7597 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs - 7598 8b/-> *eax 0/r32/eax # Stmt-var-value - 7599 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax - 7600 (print-int32-buffered *(ebp+8) *eax) - 7601 (write-buffered *(ebp+8) "/r32\n") - 7602 $translate-mu-length-stmt:end: - 7603 # . restore registers - 7604 59/pop-to-ecx - 7605 58/pop-to-eax - 7606 # . epilogue - 7607 89/<- %esp 5/r32/ebp - 7608 5d/pop-to-ebp - 7609 c3/return - 7610 - 7611 translate-mu-index-stmt: # out: (address buffered-file), stmt: (handle stmt) - 7612 # . prologue - 7613 55/push-ebp - 7614 89/<- %ebp 4/r32/esp - 7615 # . save registers + 7158 5a/pop-to-edx + 7159 59/pop-to-ecx + 7160 58/pop-to-eax + 7161 # . epilogue + 7162 89/<- %esp 5/r32/ebp + 7163 5d/pop-to-ebp + 7164 c3/return + 7165 + 7166 is-mu-branch?: # stmt: (addr stmt1) -> result/eax: boolean + 7167 # . prologue + 7168 55/push-ebp + 7169 89/<- %ebp 4/r32/esp + 7170 # . save registers + 7171 51/push-ecx + 7172 # ecx = stmt + 7173 8b/-> *(ebp+8) 1/r32/ecx + 7174 # if (stmt->operation starts with "loop") return true + 7175 (string-starts-with? *(ecx+4) "loop") # Stmt1-operation => eax + 7176 3d/compare-eax-and 0/imm32/false + 7177 75/jump-if-not-equal $is-mu-branch?:end/disp8 + 7178 # otherwise return (stmt->operation starts with "break") + 7179 (string-starts-with? *(ecx+4) "break") # Stmt1-operation => eax + 7180 $is-mu-branch?:end: + 7181 # . restore registers + 7182 59/pop-to-ecx + 7183 # . epilogue + 7184 89/<- %esp 5/r32/ebp + 7185 5d/pop-to-ebp + 7186 c3/return + 7187 + 7188 emit-reverse-break: # out: (addr buffered-file), stmt: (addr stmt1) + 7189 # . prologue + 7190 55/push-ebp + 7191 89/<- %ebp 4/r32/esp + 7192 # . save registers + 7193 50/push-eax + 7194 # eax = stmt + 7195 8b/-> *(ebp+0xc) 0/r32/eax + 7196 # + 7197 (get Reverse-branch *(eax+4) 8 "reverse-branch: ") # Stmt1-operation => eax: (addr addr array byte) + 7198 (emit-indent *(ebp+8) *Curr-block-depth) + 7199 (write-buffered *(ebp+8) *eax) + 7200 (write-buffered *(ebp+8) " break/disp32\n") + 7201 $emit-reverse-break:end: + 7202 # . restore registers + 7203 58/pop-to-eax + 7204 # . epilogue + 7205 89/<- %esp 5/r32/ebp + 7206 5d/pop-to-ebp + 7207 c3/return + 7208 + 7209 == data + 7210 + 7211 Reverse-branch: # (table string string) + 7212 # a table is a stream + 7213 0xa0/imm32/write + 7214 0/imm32/read + 7215 0xa0/imm32/size + 7216 # data + 7217 "break-if-="/imm32 "0f 85/jump-if-!="/imm32 + 7218 "loop-if-="/imm32 "0f 85/jump-if-!="/imm32 + 7219 "break-if-!="/imm32 "0f 84/jump-if-="/imm32 + 7220 "loop-if-!="/imm32 "0f 84/jump-if-="/imm32 + 7221 "break-if-<"/imm32 "0f 8d/jump-if->="/imm32 + 7222 "loop-if-<"/imm32 "0f 8d/jump-if->="/imm32 + 7223 "break-if->"/imm32 "0f 8e/jump-if-<="/imm32 + 7224 "loop-if->"/imm32 "0f 8e/jump-if-<="/imm32 + 7225 "break-if-<="/imm32 "0f 87/jump-if->"/imm32 + 7226 "loop-if-<="/imm32 "0f 87/jump-if->"/imm32 + 7227 "break-if->="/imm32 "0f 8c/jump-if-<"/imm32 + 7228 "loop-if->="/imm32 "0f 8c/jump-if-<"/imm32 + 7229 "break-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 + 7230 "loop-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 + 7231 "break-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 + 7232 "loop-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 + 7233 "break-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 + 7234 "loop-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 + 7235 "break-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 + 7236 "loop-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 + 7237 + 7238 == code + 7239 + 7240 emit-unconditional-jump-to-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), depth: int, label-suffix: (addr array byte) + 7241 # . prologue + 7242 55/push-ebp + 7243 89/<- %ebp 4/r32/esp + 7244 # . save registers + 7245 50/push-eax + 7246 51/push-ecx + 7247 52/push-edx + 7248 53/push-ebx + 7249 # ecx = vars + 7250 8b/-> *(ebp+0xc) 1/r32/ecx + 7251 # var eax: int = vars->top + 7252 8b/-> *ecx 0/r32/eax + 7253 # var min/ecx: (address (handle var)) = vars->data + 7254 81 0/subop/add %ecx 8/imm32 + 7255 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] + 7256 81 5/subop/subtract %eax 4/imm32 + 7257 8d/copy-address *(ecx+eax) 0/r32/eax + 7258 # edx = depth + 7259 8b/-> *(ebp+0x10) 2/r32/edx + 7260 { + 7261 $emit-unconditional-jump-to-depth:loop: + 7262 # if (curr < min) break + 7263 39/compare %eax 1/r32/ecx + 7264 0f 82/jump-if-addr< break/disp32 + 7265 # var v/ebx: (handle var) = *curr + 7266 8b/-> *eax 3/r32/ebx + 7267 # if (v->block-depth < until-block-depth) break + 7268 39/compare *(ebx+8) 2/r32/edx # Var-block-depth + 7269 0f 8c/jump-if-< break/disp32 + 7270 { + 7271 $emit-unconditional-jump-to-depth:check: + 7272 # if v->block-depth != until-block-depth, continue + 7273 39/compare *(ebx+8) 2/r32/edx # Var-block-depth + 7274 0f 85/jump-if-!= break/disp32 + 7275 $emit-unconditional-jump-to-depth:depth-found: + 7276 # if v is not a literal, continue + 7277 # . var eax: int = size-of(v) + 7278 50/push-eax + 7279 (size-of %ebx) # => eax + 7280 # . if (eax != 0) continue + 7281 3d/compare-eax-and 0/imm32 + 7282 58/pop-to-eax + 7283 # + 7284 0f 85/jump-if-!= break/disp32 + 7285 $emit-unconditional-jump-to-depth:label-found: + 7286 # emit unconditional jump, then return + 7287 (emit-indent *(ebp+8) *Curr-block-depth) + 7288 (write-buffered *(ebp+8) "e9/jump ") + 7289 (write-buffered *(ebp+8) *ebx) # Var-name + 7290 (write-buffered *(ebp+8) ":") + 7291 (write-buffered *(ebp+8) *(ebp+0x14)) + 7292 (write-buffered *(ebp+8) "/disp32\n") + 7293 eb/jump $emit-unconditional-jump-to-depth:end/disp8 + 7294 } + 7295 # curr -= 4 + 7296 2d/subtract-from-eax 4/imm32 + 7297 e9/jump loop/disp32 + 7298 } + 7299 # TODO: error if no label at 'depth' was found + 7300 $emit-unconditional-jump-to-depth:end: + 7301 # . restore registers + 7302 5b/pop-to-ebx + 7303 5a/pop-to-edx + 7304 59/pop-to-ecx + 7305 58/pop-to-eax + 7306 # . epilogue + 7307 89/<- %esp 5/r32/ebp + 7308 5d/pop-to-ebp + 7309 c3/return + 7310 + 7311 # emit clean-up code for 'vars' until some block depth + 7312 # doesn't actually modify 'vars' so we need traverse manually inside the stack + 7313 emit-cleanup-code-until-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-depth: int + 7314 # . prologue + 7315 55/push-ebp + 7316 89/<- %ebp 4/r32/esp + 7317 # . save registers + 7318 50/push-eax + 7319 51/push-ecx + 7320 52/push-edx + 7321 53/push-ebx + 7322 # ecx = vars + 7323 8b/-> *(ebp+0xc) 1/r32/ecx + 7324 # var eax: int = vars->top + 7325 8b/-> *ecx 0/r32/eax + 7326 # var min/ecx: (address (handle var)) = vars->data + 7327 81 0/subop/add %ecx 8/imm32 + 7328 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] + 7329 81 5/subop/subtract %eax 4/imm32 + 7330 8d/copy-address *(ecx+eax) 0/r32/eax + 7331 # edx = until-block-depth + 7332 8b/-> *(ebp+0x10) 2/r32/edx + 7333 { + 7334 $emit-cleanup-code-until-depth:loop: + 7335 # if (curr < min) break + 7336 39/compare %eax 1/r32/ecx + 7337 0f 82/jump-if-addr< break/disp32 + 7338 # var v/ebx: (handle var) = *curr + 7339 8b/-> *eax 3/r32/ebx + 7340 # if (v->block-depth < until-block-depth) break + 7341 39/compare *(ebx+8) 2/r32/edx # Var-block-depth + 7342 0f 8c/jump-if-< break/disp32 + 7343 # if v is in a register + 7344 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register + 7345 { + 7346 0f 84/jump-if-= break/disp32 + 7347 50/push-eax + 7348 { + 7349 $emit-cleanup-code-until-depth:check-for-previous-spill: + 7350 (same-register-spilled-before? %ebx *(ebp+0xc) %eax) # => eax + 7351 3d/compare-eax-and 0/imm32/false + 7352 0f 85/jump-if-!= break/disp32 + 7353 $emit-cleanup-code-until-depth:reclaim-var-in-register: + 7354 (emit-indent *(ebp+8) *Curr-block-depth) + 7355 (write-buffered *(ebp+8) "8f 0/subop/pop %") + 7356 (write-buffered *(ebp+8) *(ebx+0x10)) + 7357 (write-buffered *(ebp+8) Newline) + 7358 } + 7359 58/pop-to-eax + 7360 eb/jump $emit-cleanup-code-until-depth:continue/disp8 + 7361 } + 7362 # otherwise v is on the stack + 7363 { + 7364 75/jump-if-!= break/disp8 + 7365 $emit-cleanup-code-until-depth:reclaim-var-on-stack: + 7366 50/push-eax + 7367 (size-of %ebx) # => eax + 7368 # don't emit code for labels + 7369 3d/compare-eax-and 0/imm32 + 7370 74/jump-if-= break/disp8 + 7371 # + 7372 (emit-indent *(ebp+8) *Curr-block-depth) + 7373 (write-buffered *(ebp+8) "81 0/subop/add %esp ") + 7374 (print-int32-buffered *(ebp+8) %eax) + 7375 (write-buffered *(ebp+8) "/imm32\n") + 7376 58/pop-to-eax + 7377 } + 7378 $emit-cleanup-code-until-depth:continue: + 7379 # curr -= 4 + 7380 2d/subtract-from-eax 4/imm32 + 7381 e9/jump loop/disp32 + 7382 } + 7383 $emit-cleanup-code-until-depth:end: + 7384 # . restore registers + 7385 5b/pop-to-ebx + 7386 5a/pop-to-edx + 7387 59/pop-to-ecx + 7388 58/pop-to-eax + 7389 # . epilogue + 7390 89/<- %esp 5/r32/ebp + 7391 5d/pop-to-ebp + 7392 c3/return + 7393 + 7394 # emit clean-up code for 'vars' until a given label is encountered + 7395 # doesn't actually modify 'vars' so we need traverse manually inside the stack + 7396 emit-cleanup-code-until-target: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-label: (addr array byte) + 7397 # . prologue + 7398 55/push-ebp + 7399 89/<- %ebp 4/r32/esp + 7400 # . save registers + 7401 50/push-eax + 7402 51/push-ecx + 7403 52/push-edx + 7404 53/push-ebx + 7405 # ecx = vars + 7406 8b/-> *(ebp+0xc) 1/r32/ecx + 7407 # var eax: int = vars->top + 7408 8b/-> *ecx 0/r32/eax + 7409 # var min/ecx: (address (handle var)) = vars->data + 7410 81 0/subop/add %ecx 8/imm32 + 7411 # var curr/edx: (address (handle var)) = &vars->data[vars->top - 4] + 7412 81 5/subop/subtract %eax 4/imm32 + 7413 8d/copy-address *(ecx+eax) 2/r32/edx + 7414 { + 7415 $emit-cleanup-code-until-target:loop: + 7416 # if (curr < min) break + 7417 39/compare %edx 1/r32/ecx + 7418 0f 82/jump-if-addr< break/disp32 + 7419 # var v/ebx: (handle var) = *curr + 7420 8b/-> *edx 3/r32/ebx + 7421 # if (v->name == until-block-label) break + 7422 (string-equal? *ebx *(ebp+0x10)) # => eax + 7423 3d/compare-eax-and 0/imm32/false + 7424 0f 85/jump-if-!= break/disp32 + 7425 # if v is in a register + 7426 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register + 7427 { + 7428 74/jump-if-= break/disp8 + 7429 50/push-eax + 7430 { + 7431 $emit-cleanup-code-until-target:check-for-previous-spill: + 7432 (same-register-spilled-before? %ebx *(ebp+0xc) %edx) # => eax + 7433 3d/compare-eax-and 0/imm32/false + 7434 75/jump-if-!= break/disp8 + 7435 $emit-cleanup-code-until-target:reclaim-var-in-register: + 7436 (emit-indent *(ebp+8) *Curr-block-depth) + 7437 (write-buffered *(ebp+8) "8f 0/subop/pop %") + 7438 (write-buffered *(ebp+8) *(ebx+0x10)) + 7439 (write-buffered *(ebp+8) Newline) + 7440 } + 7441 58/pop-to-eax + 7442 eb/jump $emit-cleanup-code-until-target:continue/disp8 + 7443 } + 7444 # otherwise v is on the stack + 7445 { + 7446 75/jump-if-!= break/disp8 + 7447 $emit-cleanup-code-until-target:reclaim-var-on-stack: + 7448 (size-of %ebx) # => eax + 7449 # don't emit code for labels + 7450 3d/compare-eax-and 0/imm32 + 7451 74/jump-if-= break/disp8 + 7452 # + 7453 (emit-indent *(ebp+8) *Curr-block-depth) + 7454 (write-buffered *(ebp+8) "81 0/subop/add %esp ") + 7455 (print-int32-buffered *(ebp+8) %eax) + 7456 (write-buffered *(ebp+8) "/imm32\n") + 7457 } + 7458 $emit-cleanup-code-until-target:continue: + 7459 # curr -= 4 + 7460 81 5/subop/subtract %edx 4/imm32 + 7461 e9/jump loop/disp32 + 7462 } + 7463 $emit-cleanup-code-until-target:end: + 7464 # . restore registers + 7465 5b/pop-to-ebx + 7466 5a/pop-to-edx + 7467 59/pop-to-ecx + 7468 58/pop-to-eax + 7469 # . epilogue + 7470 89/<- %esp 5/r32/ebp + 7471 5d/pop-to-ebp + 7472 c3/return + 7473 + 7474 # is there already a var with the same block-depth and register as 'v' on the 'vars' stack? + 7475 # v is guaranteed not to be within vars + 7476 already-spilled-this-block?: # v: (handle var), vars: (addr stack (handle var)) -> result/eax: boolean + 7477 # . prologue + 7478 55/push-ebp + 7479 89/<- %ebp 4/r32/esp + 7480 # . save registers + 7481 51/push-ecx + 7482 52/push-edx + 7483 53/push-ebx + 7484 56/push-esi + 7485 57/push-edi + 7486 # ecx = vars + 7487 8b/-> *(ebp+0xc) 1/r32/ecx + 7488 # var eax: int = vars->top + 7489 8b/-> *ecx 0/r32/eax + 7490 # var min/ecx: (address (handle var)) = vars->data + 7491 81 0/subop/add %ecx 8/imm32 + 7492 # var curr/edx: (address (handle var)) = &vars->data[vars->top - 4] + 7493 81 5/subop/subtract %eax 4/imm32 + 7494 8d/copy-address *(ecx+eax) 2/r32/edx + 7495 # var depth/ebx: int = v->block-depth + 7496 8b/-> *(ebp+8) 3/r32/ebx + 7497 8b/-> *(ebx+8) 3/r32/ebx # Var-block-depth + 7498 # var needle/esi: (handle array byte) = v->register + 7499 8b/-> *(ebp+8) 6/r32/esi + 7500 8b/-> *(esi+0x10) 6/r32/esi # Var-register + 7501 { + 7502 $already-spilled-this-block?:loop: + 7503 # if (curr < min) break + 7504 39/compare %edx 1/r32/ecx + 7505 0f 82/jump-if-addr< break/disp32 + 7506 # var cand/edi: (handle var) = *curr + 7507 8b/-> *edx 7/r32/edi + 7508 # if (cand->block-depth < depth) break + 7509 39/compare *(edi+8) 3/r32/ebx # Var-block-depth + 7510 0f 8c/jump-if-< break/disp32 + 7511 # var cand-reg/edi: (handle array byte) = cand->reg + 7512 8b/-> *(edi+0x10) 7/r32/edi + 7513 # if (cand-reg == null) continue + 7514 { + 7515 $already-spilled-this-block?:check-reg: + 7516 81 7/subop/compare %edi 0/imm32 + 7517 74/jump-if-= break/disp8 + 7518 # if (cand-reg == needle) return true + 7519 (string-equal? %esi %edi) # => eax + 7520 3d/compare-eax-and 0/imm32/false + 7521 74/jump-if-= break/disp8 + 7522 b8/copy-to-eax 1/imm32/true + 7523 eb/jump $already-spilled-this-block?:end/disp8 + 7524 } + 7525 $already-spilled-this-block?:continue: + 7526 # curr -= 4 + 7527 81 5/subop/subtract %edx 4/imm32 + 7528 e9/jump loop/disp32 + 7529 } + 7530 # return false + 7531 b8/copy-to-eax 0/imm32/false + 7532 $already-spilled-this-block?:end: + 7533 # . restore registers + 7534 5f/pop-to-edi + 7535 5e/pop-to-esi + 7536 5b/pop-to-ebx + 7537 5a/pop-to-edx + 7538 59/pop-to-ecx + 7539 # . epilogue + 7540 89/<- %esp 5/r32/ebp + 7541 5d/pop-to-ebp + 7542 c3/return + 7543 + 7544 # is there a var before 'v' with the same block-depth and register on the 'vars' stack? + 7545 # v is guaranteed to be within vars + 7546 # 'start' is provided as an optimization, a pointer within vars + 7547 # *start == v + 7548 same-register-spilled-before?: # v: (handle var), vars: (addr stack (handle var)), start: (addr (handle var)) -> result/eax: boolean + 7549 # . prologue + 7550 55/push-ebp + 7551 89/<- %ebp 4/r32/esp + 7552 # . save registers + 7553 51/push-ecx + 7554 52/push-edx + 7555 53/push-ebx + 7556 56/push-esi + 7557 57/push-edi + 7558 # ecx = v + 7559 8b/-> *(ebp+8) 1/r32/ecx + 7560 # var reg/edx: (handle array byte) = v->register + 7561 8b/-> *(ecx+0x10) 2/r32/edx # Var-register + 7562 # var depth/ebx: int = v->block-depth + 7563 8b/-> *(ecx+8) 3/r32/ebx # Var-block-depth + 7564 # var min/ecx: (address (handle var)) = vars->data + 7565 8b/-> *(ebp+0xc) 1/r32/ecx + 7566 81 0/subop/add %ecx 8/imm32 + 7567 # TODO: check that start >= min and start < &vars->data[top] + 7568 # TODO: check that *start == v + 7569 # var curr/esi: (address (handle var)) = start + 7570 8b/-> *(ebp+0x10) 6/r32/esi + 7571 # curr -= 4 + 7572 81 5/subop/subtract %esi 4/imm32 + 7573 { + 7574 $same-register-spilled-before?:loop: + 7575 # if (curr < min) break + 7576 39/compare %esi 1/r32/ecx + 7577 0f 82/jump-if-addr< break/disp32 + 7578 # var x/eax: (handle var) = *curr + 7579 8b/-> *esi 0/r32/eax + 7580 # if (x->block-depth < depth) break + 7581 39/compare *(eax+8) 3/r32/ebx # Var-block-depth + 7582 0f 8c/jump-if-< break/disp32 + 7583 # if (x->register == 0) continue + 7584 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register + 7585 74/jump-if-= $same-register-spilled-before?:continue/disp8 + 7586 # if (x->register == reg) return true + 7587 (string-equal? *(eax+0x10) %edx) # Var-register => eax + 7588 3d/compare-eax-and 0/imm32/false + 7589 75/jump-if-!= $same-register-spilled-before?:end/disp8 + 7590 $same-register-spilled-before?:continue: + 7591 # curr -= 4 + 7592 81 5/subop/subtract %esi 4/imm32 + 7593 e9/jump loop/disp32 + 7594 } + 7595 $same-register-spilled-before?:false: + 7596 b8/copy-to-eax 0/imm32/false + 7597 $same-register-spilled-before?:end: + 7598 # . restore registers + 7599 5f/pop-to-edi + 7600 5e/pop-to-esi + 7601 5b/pop-to-ebx + 7602 5a/pop-to-edx + 7603 59/pop-to-ecx + 7604 # . epilogue + 7605 89/<- %esp 5/r32/ebp + 7606 5d/pop-to-ebp + 7607 c3/return + 7608 + 7609 # clean up global state for 'vars' until some block depth + 7610 clean-up-blocks: # vars: (addr stack (handle var)), until-block-depth: int + 7611 # . prologue + 7612 55/push-ebp + 7613 89/<- %ebp 4/r32/esp + 7614 # . save registers + 7615 50/push-eax 7616 51/push-ecx - 7617 # var base/ecx: (handle var) = stmt->inouts[0] - 7618 8b/-> *(ebp+0xc) 1/r32/ecx - 7619 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts - 7620 8b/-> *ecx 1/r32/ecx # Stmt-var-value - 7621 # if (var->register) do one thing + 7617 56/push-esi + 7618 # esi = vars + 7619 8b/-> *(ebp+8) 6/r32/esi + 7620 # ecx = until-block-depth + 7621 8b/-> *(ebp+0xc) 1/r32/ecx 7622 { - 7623 81 7/subop/compare *(ecx+0x10) 0/imm32 # Var-register - 7624 74/jump-if-= break/disp8 - 7625 # TODO: ensure there's no dereference - 7626 (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc)) - 7627 eb/jump $translate-mu-index-stmt:end/disp8 - 7628 } - 7629 # if (var->offset) do a different thing - 7630 { - 7631 81 7/subop/compare *(ecx+0xc) 0/imm32 # Var-offset - 7632 74/jump-if-= break/disp8 - 7633 # TODO: ensure there's no dereference - 7634 (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc)) - 7635 eb/jump $translate-mu-index-stmt:end/disp8 - 7636 } - 7637 $translate-mu-index-stmt:end: - 7638 # . restore registers - 7639 59/pop-to-ecx - 7640 # . epilogue - 7641 89/<- %esp 5/r32/ebp - 7642 5d/pop-to-ebp - 7643 c3/return - 7644 - 7645 $translate-mu-index-stmt-with-array:error1: - 7646 (write-buffered Stderr "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n") - 7647 (flush Stderr) - 7648 # . syscall(exit, 1) - 7649 bb/copy-to-ebx 1/imm32 - 7650 b8/copy-to-eax 1/imm32/exit - 7651 cd/syscall 0x80/imm8 - 7652 # never gets here - 7653 - 7654 $translate-mu-index-stmt-with-array:error2: - 7655 (write-buffered Stderr "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n") - 7656 (flush Stderr) - 7657 # . syscall(exit, 1) - 7658 bb/copy-to-ebx 1/imm32 - 7659 b8/copy-to-eax 1/imm32/exit - 7660 cd/syscall 0x80/imm8 - 7661 # never gets here - 7662 - 7663 translate-mu-index-stmt-with-array-in-register: # out: (address buffered-file), stmt: (handle stmt) - 7664 # . prologue - 7665 55/push-ebp - 7666 89/<- %ebp 4/r32/esp - 7667 # . save registers - 7668 50/push-eax - 7669 51/push-ecx - 7670 52/push-edx - 7671 53/push-ebx - 7672 # - 7673 (emit-indent *(ebp+8) *Curr-block-depth) - 7674 (write-buffered *(ebp+8) "8d/copy-address *(") - 7675 # TODO: ensure inouts[0] is in a register and not dereferenced - 7676 $translate-mu-index-stmt-with-array-in-register:emit-base: - 7677 # ecx = stmt - 7678 8b/-> *(ebp+0xc) 1/r32/ecx - 7679 # var base/ebx: (handle var) = inouts[0] - 7680 8b/-> *(ecx+8) 3/r32/ebx # Stmt1-inouts - 7681 8b/-> *ebx 3/r32/ebx # Stmt-var-value - 7682 # print base->register " + " - 7683 (write-buffered *(ebp+8) *(ebx+0x10)) # Var-register - 7684 # - 7685 (write-buffered *(ebp+8) " + ") - 7686 # var index/edx: (handle var) = inouts[1] - 7687 8b/-> *(ecx+8) 2/r32/edx # Stmt1-inouts - 7688 8b/-> *(edx+4) 2/r32/edx # Stmt-var-next - 7689 8b/-> *edx 2/r32/edx # Stmt-var-value - 7690 # if index->register - 7691 81 7/subop/compare *(edx+0x10) 0/imm32 # Var-register - 7692 { - 7693 0f 84/jump-if-= break/disp32 - 7694 $translate-mu-index-stmt-with-array-in-register:emit-register-index: - 7695 # if index is an int - 7696 (is-simple-mu-type? *(edx+4) 1) # Var-type, int => eax - 7697 3d/compare-eax-and 0/imm32/false - 7698 { - 7699 0f 84/jump-if-= break/disp32 - 7700 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index: - 7701 # print index->register "<<" log2(size-of(element(base->type))) " + 4) " - 7702 # . index->register "<<" - 7703 (write-buffered *(ebp+8) *(edx+0x10)) # Var-register - 7704 (write-buffered *(ebp+8) "<<") - 7705 # . log2(size-of(element(base->type))) - 7706 # TODO: ensure size is a power of 2 - 7707 (array-element-type-id %ebx) # => eax - 7708 (size-of-type-id %eax) # => eax - 7709 (num-shift-rights %eax) # => eax - 7710 (print-int32-buffered *(ebp+8) %eax) - 7711 e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32 - 7712 } - 7713 # if index->type is any other atom, abort - 7714 8b/-> *(edx+4) 0/r32/eax # Var-type - 7715 8b/-> *eax 0/r32/eax # Tree-left or Atom-value - 7716 3b/compare 0/r32/eax *Max-type-id - 7717 0f 82/jump-if-addr< $translate-mu-index-stmt-with-array:error2/disp32 - 7718 # if index has type (offset ...) - 7719 (is-simple-mu-type? %eax 7) # offset => eax - 7720 3d/compare-eax-and 0/imm32/false - 7721 { - 7722 0f 84/jump-if-= break/disp32 - 7723 # print index->register " + 4) " - 7724 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index: - 7725 (write-buffered *(ebp+8) *(edx+0x10)) # Var-register - 7726 } - 7727 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done: - 7728 (write-buffered *(ebp+8) " + 4) ") - 7729 e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32 - 7730 } - 7731 # otherwise if index is a literal - 7732 (is-simple-mu-type? *(edx+4) 0) # Var-type => eax - 7733 3d/compare-eax-and 0/imm32/false + 7623 $clean-up-blocks:reclaim-loop: + 7624 # if (vars->top <= 0) break + 7625 81 7/subop/compare *esi 0/imm32 # Stack-top + 7626 7e/jump-if-<= break/disp8 + 7627 # var v/eax: (handle var) = top(vars) + 7628 (top %esi) # => eax + 7629 # if (v->block-depth < until-block-depth) break + 7630 39/compare *(eax+8) 1/r32/ecx # Var-block-depth + 7631 7c/jump-if-< break/disp8 + 7632 # if v is on the stack, update Curr-local-stack-offset + 7633 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register + 7634 { + 7635 75/jump-if-!= break/disp8 + 7636 $clean-up-blocks:reclaim-var-on-stack: + 7637 (size-of %eax) # => eax + 7638 01/add-to *Curr-local-stack-offset 0/r32/eax + 7639 } + 7640 (pop %esi) + 7641 e9/jump loop/disp32 + 7642 } + 7643 $clean-up-blocks:end: + 7644 # . restore registers + 7645 5e/pop-to-esi + 7646 59/pop-to-ecx + 7647 58/pop-to-eax + 7648 # . epilogue + 7649 89/<- %esp 5/r32/ebp + 7650 5d/pop-to-ebp + 7651 c3/return + 7652 + 7653 emit-subx-var-def: # out: (addr buffered-file), stmt: (handle stmt) + 7654 # . prologue + 7655 55/push-ebp + 7656 89/<- %ebp 4/r32/esp + 7657 # . save registers + 7658 50/push-eax + 7659 51/push-ecx + 7660 52/push-edx + 7661 # eax = stmt + 7662 8b/-> *(ebp+0xc) 0/r32/eax + 7663 # var v/ecx: (handle var) + 7664 8b/-> *(eax+4) 1/r32/ecx # Vardef-var + 7665 # v->block-depth = *Curr-block-depth + 7666 8b/-> *Curr-block-depth 0/r32/eax + 7667 89/<- *(ecx+8) 0/r32/eax # Var-block-depth + 7668 # var n/edx: int = size-of(stmt->var) + 7669 (size-of %ecx) # => eax + 7670 89/<- %edx 0/r32/eax + 7671 # *Curr-local-stack-offset -= n + 7672 29/subtract-from *Curr-local-stack-offset 2/r32/edx + 7673 # v->offset = *Curr-local-stack-offset + 7674 8b/-> *Curr-local-stack-offset 0/r32/eax + 7675 89/<- *(ecx+0xc) 0/r32/eax # Var-offset + 7676 # if v is an array, do something special + 7677 { + 7678 (is-mu-array? *(ecx+4)) # Var-type => eax + 7679 3d/compare-eax-and 0/imm32/false + 7680 0f 84/jump-if-= break/disp32 + 7681 # var array-size-without-size/edx: int = n-4 + 7682 81 5/subop/subtract %edx 4/imm32 + 7683 (emit-indent *(ebp+8) *Curr-block-depth) + 7684 (write-buffered *(ebp+8) "(push-n-zero-bytes ") + 7685 (print-int32-buffered *(ebp+8) %edx) + 7686 (write-buffered *(ebp+8) ")\n") + 7687 (emit-indent *(ebp+8) *Curr-block-depth) + 7688 (write-buffered *(ebp+8) "68/push ") + 7689 (print-int32-buffered *(ebp+8) %edx) + 7690 (write-buffered *(ebp+8) "/imm32\n") + 7691 eb/jump $emit-subx-var-def:end/disp8 + 7692 } + 7693 # while n > 0 + 7694 { + 7695 81 7/subop/compare %edx 0/imm32 + 7696 7e/jump-if-<= break/disp8 + 7697 (emit-indent *(ebp+8) *Curr-block-depth) + 7698 (write-buffered *(ebp+8) "68/push 0/imm32\n") + 7699 # n -= 4 + 7700 81 5/subop/subtract %edx 4/imm32 + 7701 # + 7702 eb/jump loop/disp8 + 7703 } + 7704 $emit-subx-var-def:end: + 7705 # . restore registers + 7706 5a/pop-to-edx + 7707 59/pop-to-ecx + 7708 58/pop-to-eax + 7709 # . epilogue + 7710 89/<- %esp 5/r32/ebp + 7711 5d/pop-to-ebp + 7712 c3/return + 7713 + 7714 emit-subx-stmt: # out: (addr buffered-file), stmt: (handle stmt), primitives: (handle primitive) + 7715 # . prologue + 7716 55/push-ebp + 7717 89/<- %ebp 4/r32/esp + 7718 # . save registers + 7719 50/push-eax + 7720 51/push-ecx + 7721 # - some special-case primitives that don't actually use the 'primitives' data structure + 7722 # ecx = stmt + 7723 8b/-> *(ebp+0xc) 1/r32/ecx + 7724 # array size + 7725 { + 7726 # if (!string-equal?(stmt->operation, "length")) break + 7727 (string-equal? *(ecx+4) "length") # Stmt1-operation => eax + 7728 3d/compare-eax-and 0/imm32 + 7729 0f 84/jump-if-= break/disp32 + 7730 (translate-mu-length-stmt *(ebp+8) *(ebp+0xc)) + 7731 e9/jump $emit-subx-stmt:end/disp32 + 7732 } + 7733 # index into array 7734 { - 7735 0f 84/jump-if-= break/disp32 - 7736 $translate-mu-index-stmt-with-array-in-register:emit-literal-index: - 7737 # var index-value/edx: int = parse-hex-int(index->name) - 7738 (parse-hex-int *edx) # Var-name => eax - 7739 89/<- %edx 0/r32/eax - 7740 # offset = idx-value * size-of(element(base->type)) - 7741 (array-element-type-id %ebx) # => eax - 7742 (size-of-type-id %eax) # => eax - 7743 f7 4/subop/multiply-into-eax %edx # clobbers edx - 7744 # offset += 4 for array size - 7745 05/add-to-eax 4/imm32 - 7746 # TODO: check edx for overflow - 7747 # print offset - 7748 (print-int32-buffered *(ebp+8) %eax) - 7749 (write-buffered *(ebp+8) ") ") - 7750 e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32 - 7751 } - 7752 # otherwise abort - 7753 e9/jump $translate-mu-index-stmt-with-array:error1/disp32 - 7754 $translate-mu-index-stmt-with-array-in-register:emit-output: - 7755 # outputs[0] "/r32" - 7756 8b/-> *(ebp+0xc) 1/r32/ecx - 7757 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs - 7758 8b/-> *eax 0/r32/eax # Stmt-var-value - 7759 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax - 7760 (print-int32-buffered *(ebp+8) *eax) - 7761 (write-buffered *(ebp+8) "/r32\n") - 7762 $translate-mu-index-stmt-with-array-in-register:end: - 7763 # . restore registers - 7764 5b/pop-to-ebx - 7765 5a/pop-to-edx - 7766 59/pop-to-ecx - 7767 58/pop-to-eax - 7768 # . epilogue - 7769 89/<- %esp 5/r32/ebp - 7770 5d/pop-to-ebp - 7771 c3/return - 7772 - 7773 translate-mu-index-stmt-with-array-on-stack: # out: (address buffered-file), stmt: (handle stmt) - 7774 # . prologue - 7775 55/push-ebp - 7776 89/<- %ebp 4/r32/esp - 7777 # . save registers - 7778 50/push-eax - 7779 51/push-ecx - 7780 52/push-edx - 7781 53/push-ebx - 7782 # - 7783 (emit-indent *(ebp+8) *Curr-block-depth) - 7784 (write-buffered *(ebp+8) "8d/copy-address *(ebp + ") - 7785 # var curr/eax = stmt->inouts - 7786 8b/-> *(ebp+0xc) 0/r32/eax - 7787 # var base/ecx: (handle var) = stmt->inouts[0] - 7788 8b/-> *(eax+8) 0/r32/eax # Stmt1-inouts - 7789 8b/-> *eax 1/r32/ecx # Stmt-var-value - 7790 # curr = curr->next - 7791 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next - 7792 # var index/edx: (handle var) = stmt->inouts[1] - 7793 8b/-> *eax 2/r32/edx # Stmt-var-value - 7794 # if index->register - 7795 81 7/subop/compare *(edx+0x10) 0/imm32 # Var-register - 7796 { - 7797 0f 84/jump-if-= break/disp32 - 7798 $translate-mu-index-stmt-with-array-on-stack:emit-register-index: - 7799 # if index is an int - 7800 (is-simple-mu-type? *(edx+4) 1) # Var-type, int => eax - 7801 3d/compare-eax-and 0/imm32/false - 7802 { - 7803 0f 84/jump-if-= break/disp32 - 7804 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index: - 7805 # print index->register "<<" log2(size-of(element-type(base))) " + " base->offset+4 - 7806 # . inouts[1]->register "<<" - 7807 (write-buffered *(ebp+8) *(edx+0x10)) # Var-register - 7808 (write-buffered *(ebp+8) "<<") - 7809 # . log2(size-of(element(base))) - 7810 # TODO: ensure size is a power of 2 - 7811 (array-element-type-id %ecx) # => eax - 7812 (size-of-type-id %eax) # => eax - 7813 (num-shift-rights %eax) # => eax - 7814 (print-int32-buffered *(ebp+8) %eax) - 7815 # - 7816 (write-buffered *(ebp+8) " + ") - 7817 # - 7818 8b/-> *(ecx+0xc) 0/r32/eax # Var-offset - 7819 05/add-to-eax 4/imm32 - 7820 (print-int32-buffered *(ebp+8) %eax) - 7821 e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32 - 7822 } - 7823 # if index->type is any other atom, abort - 7824 8b/-> *(edx+4) 0/r32/eax # Var-type - 7825 8b/-> *eax 0/r32/eax # Tree-left or Atom-value - 7826 3b/compare 0/r32/eax *Max-type-id - 7827 0f 82/jump-if-addr< $translate-mu-index-stmt-with-array:error2/disp32 - 7828 # if index has type (offset ...) - 7829 (is-simple-mu-type? %eax 7) # offset => eax - 7830 3d/compare-eax-and 0/imm32/false - 7831 { - 7832 0f 84/jump-if-= break/disp32 - 7833 # print index->register - 7834 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index: - 7835 (write-buffered *(ebp+8) *(edx+0x10)) # Var-register - 7836 } - 7837 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done: - 7838 (write-buffered *(ebp+8) ") ") - 7839 e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32 - 7840 } - 7841 # otherwise if index is a literal - 7842 (is-simple-mu-type? *(edx+4) 0) # Var-type => eax - 7843 3d/compare-eax-and 0/imm32/false - 7844 { - 7845 0f 84/jump-if-= break/disp32 - 7846 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index: - 7847 # var idx-value/edx: int = parse-hex-int(index->name) - 7848 (parse-hex-int *edx) # Var-name => eax - 7849 89/<- %ebx 0/r32/eax - 7850 # offset = idx-value * size-of(element-type(base->type)) - 7851 (array-element-type-id %ecx) # => eax - 7852 (size-of-type-id %eax) # => eax - 7853 f7 4/subop/multiply-into-eax %ebx # clobbers edx - 7854 # offset += base->offset - 7855 03/add-to 0/r32/eax *(ecx+0xc) # Var-offset - 7856 # offset += 4 for array size - 7857 05/add-to-eax 4/imm32 - 7858 # TODO: check edx for overflow - 7859 # print offset - 7860 (print-int32-buffered *(ebp+8) %eax) - 7861 (write-buffered *(ebp+8) ") ") - 7862 e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32 - 7863 } - 7864 # otherwise abort - 7865 e9/jump $translate-mu-index-stmt-with-array:error1/disp32 - 7866 $translate-mu-index-stmt-with-array-on-stack:emit-output: - 7867 # outputs[0] "/r32" - 7868 8b/-> *(ebp+0xc) 0/r32/eax - 7869 8b/-> *(eax+0xc) 0/r32/eax # Stmt1-outputs - 7870 8b/-> *eax 0/r32/eax # Stmt-var-value - 7871 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax - 7872 (print-int32-buffered *(ebp+8) *eax) - 7873 (write-buffered *(ebp+8) "/r32\n") - 7874 $translate-mu-index-stmt-with-array-on-stack:end: - 7875 # . restore registers - 7876 5b/pop-to-ebx - 7877 5a/pop-to-edx - 7878 59/pop-to-ecx - 7879 58/pop-to-eax - 7880 # . epilogue - 7881 89/<- %esp 5/r32/ebp - 7882 5d/pop-to-ebp - 7883 c3/return - 7884 - 7885 translate-mu-compute-index-stmt: # out: (address buffered-file), stmt: (handle stmt) - 7886 # . prologue - 7887 55/push-ebp - 7888 89/<- %ebp 4/r32/esp - 7889 # . save registers - 7890 50/push-eax - 7891 51/push-ecx - 7892 52/push-edx - 7893 53/push-ebx - 7894 # - 7895 (emit-indent *(ebp+8) *Curr-block-depth) - 7896 (write-buffered *(ebp+8) "69/multiply ") - 7897 $translate-mu-compute-index-stmt:emit-elem-size: - 7898 # ecx = stmt - 7899 8b/-> *(ebp+0xc) 1/r32/ecx - 7900 # var first-inout/edx: (handle stmt-var) = stmt->inouts[0] - 7901 8b/-> *(ecx+8) 2/r32/edx # Stmt1-inouts - 7902 # var base/ebx: (handle var) - 7903 8b/-> *edx 3/r32/ebx # Stmt-var-value - 7904 # print size-of(element(base->type)) - 7905 (array-element-type-id %ebx) # => eax - 7906 (size-of-type-id %eax) # => eax - 7907 (print-int32-buffered *(ebp+8) %eax) - 7908 (write-buffered *(ebp+8) "/imm32") - 7909 $translate-mu-compute-index-stmt:emit-index: - 7910 (emit-subx-var-as-rm32 *(ebp+8) *(edx+4)) # Stmt-var-next - 7911 (write-buffered *(ebp+8) Space) - 7912 $translate-mu-compute-index-stmt:emit-output: - 7913 # outputs[0] "/r32" - 7914 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs - 7915 8b/-> *eax 0/r32/eax # Stmt-var-value - 7916 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax - 7917 (print-int32-buffered *(ebp+8) *eax) - 7918 (write-buffered *(ebp+8) "/r32\n") - 7919 $translate-mu-compute-index-stmt:end: - 7920 # . restore registers - 7921 5b/pop-to-ebx - 7922 5a/pop-to-edx - 7923 59/pop-to-ecx - 7924 58/pop-to-eax - 7925 # . epilogue - 7926 89/<- %esp 5/r32/ebp - 7927 5d/pop-to-ebp - 7928 c3/return - 7929 - 7930 translate-mu-get-stmt: # out: (address buffered-file), stmt: (handle stmt) - 7931 # . prologue - 7932 55/push-ebp - 7933 89/<- %ebp 4/r32/esp - 7934 # . save registers - 7935 50/push-eax - 7936 51/push-ecx - 7937 52/push-edx - 7938 # - 7939 (emit-indent *(ebp+8) *Curr-block-depth) - 7940 (write-buffered *(ebp+8) "8d/copy-address ") - 7941 # ecx = stmt - 7942 8b/-> *(ebp+0xc) 1/r32/ecx - 7943 # var offset/edx: int = get offset of stmt - 7944 (mu-get-offset %ecx) # => eax - 7945 89/<- %edx 0/r32/eax - 7946 # var base/eax: (handle var) = stmt->inouts[0] - 7947 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts - 7948 8b/-> *eax 0/r32/eax # Stmt-var-value - 7949 # if base is in a register - 7950 81 7/subop/compare *(eax+0x10) 0/imm32 - 7951 { - 7952 0f 84/jump-if-= break/disp32 - 7953 $translate-mu-get-stmt:emit-register-input: - 7954 # "*(" inouts[0]->register " + " offset ")" - 7955 (write-buffered *(ebp+8) "*(") - 7956 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register - 7957 (write-buffered *(ebp+8) " + ") - 7958 (print-int32-buffered *(ebp+8) %edx) - 7959 (write-buffered *(ebp+8) ") ") - 7960 e9/jump $translate-mu-get-stmt:emit-output/disp32 - 7961 } - 7962 # otherwise base is on the stack - 7963 { - 7964 $translate-mu-get-stmt:emit-stack-input: - 7965 # "*(ebp + " inouts[0]->offset + offset ")" - 7966 (write-buffered *(ebp+8) "*(ebp+") - 7967 03/add-from *(eax+0xc) 2/r32/edx # Var-offset - 7968 (print-int32-buffered *(ebp+8) %edx) - 7969 (write-buffered *(ebp+8) ") ") - 7970 eb/jump $translate-mu-get-stmt:emit-output/disp8 - 7971 } - 7972 $translate-mu-get-stmt:emit-output: + 7735 # if (!string-equal?(var->operation, "index")) break + 7736 (string-equal? *(ecx+4) "index") # Stmt1-operation => eax + 7737 3d/compare-eax-and 0/imm32 + 7738 0f 84/jump-if-= break/disp32 + 7739 (translate-mu-index-stmt *(ebp+8) *(ebp+0xc)) + 7740 e9/jump $emit-subx-stmt:end/disp32 + 7741 } + 7742 # compute-offset for index into array + 7743 { + 7744 # if (!string-equal?(var->operation, "compute-offset")) break + 7745 (string-equal? *(ecx+4) "compute-offset") # Stmt1-operation => eax + 7746 3d/compare-eax-and 0/imm32 + 7747 0f 84/jump-if-= break/disp32 + 7748 (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc)) + 7749 e9/jump $emit-subx-stmt:end/disp32 + 7750 } + 7751 # get field from record + 7752 { + 7753 # if (!string-equal?(var->operation, "get")) break + 7754 (string-equal? *(ecx+4) "get") # Stmt1-operation => eax + 7755 3d/compare-eax-and 0/imm32 + 7756 0f 84/jump-if-= break/disp32 + 7757 (translate-mu-get-stmt *(ebp+8) *(ebp+0xc)) + 7758 e9/jump $emit-subx-stmt:end/disp32 + 7759 } + 7760 # - if stmt matches a primitive, emit it + 7761 { + 7762 $emit-subx-stmt:check-for-primitive: + 7763 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => curr/eax + 7764 3d/compare-eax-and 0/imm32 + 7765 74/jump-if-= break/disp8 + 7766 $emit-subx-stmt:primitive: + 7767 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr + 7768 e9/jump $emit-subx-stmt:end/disp32 + 7769 } + 7770 # - otherwise emit a call + 7771 # TODO: type-checking + 7772 $emit-subx-stmt:call: + 7773 (emit-call *(ebp+8) *(ebp+0xc)) + 7774 $emit-subx-stmt:end: + 7775 # . restore registers + 7776 59/pop-to-ecx + 7777 58/pop-to-eax + 7778 # . epilogue + 7779 89/<- %esp 5/r32/ebp + 7780 5d/pop-to-ebp + 7781 c3/return + 7782 + 7783 translate-mu-length-stmt: # out: (address buffered-file), stmt: (handle stmt) + 7784 # . prologue + 7785 55/push-ebp + 7786 89/<- %ebp 4/r32/esp + 7787 # . save registers + 7788 50/push-eax + 7789 51/push-ecx + 7790 # ecx = stmt + 7791 8b/-> *(ebp+0xc) 1/r32/ecx + 7792 # + 7793 (emit-indent *(ebp+8) *Curr-block-depth) + 7794 (write-buffered *(ebp+8) "8b/-> *") + 7795 # var base/eax: (handle var) = inouts[0] + 7796 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts + 7797 8b/-> *eax 0/r32/eax # Stmt-var-value + 7798 # if base is an (address array ...) in a register + 7799 { + 7800 81 7/subop/compare *(eax+0x10)) 0/imm32 # Var-register + 7801 74/jump-if-= break/disp8 + 7802 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register + 7803 eb/jump $translate-mu-length-stmt:emit-output/disp8 + 7804 } + 7805 # otherwise if base is an (array ...) on the stack + 7806 { + 7807 81 7/subop/compare *(eax+0xc)) 0/imm32 # Var-offset + 7808 74/jump-if-= break/disp8 + 7809 (write-buffered *(ebp+8) "(ebp+") + 7810 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-offset + 7811 (write-buffered *(ebp+8) ")") + 7812 } + 7813 $translate-mu-length-stmt:emit-output: + 7814 (write-buffered *(ebp+8) " ") + 7815 # outputs[0] "/r32" + 7816 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs + 7817 8b/-> *eax 0/r32/eax # Stmt-var-value + 7818 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax + 7819 (print-int32-buffered *(ebp+8) *eax) + 7820 (write-buffered *(ebp+8) "/r32\n") + 7821 $translate-mu-length-stmt:end: + 7822 # . restore registers + 7823 59/pop-to-ecx + 7824 58/pop-to-eax + 7825 # . epilogue + 7826 89/<- %esp 5/r32/ebp + 7827 5d/pop-to-ebp + 7828 c3/return + 7829 + 7830 translate-mu-index-stmt: # out: (address buffered-file), stmt: (handle stmt) + 7831 # . prologue + 7832 55/push-ebp + 7833 89/<- %ebp 4/r32/esp + 7834 # . save registers + 7835 51/push-ecx + 7836 # var base/ecx: (handle var) = stmt->inouts[0] + 7837 8b/-> *(ebp+0xc) 1/r32/ecx + 7838 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts + 7839 8b/-> *ecx 1/r32/ecx # Stmt-var-value + 7840 # if (var->register) do one thing + 7841 { + 7842 81 7/subop/compare *(ecx+0x10) 0/imm32 # Var-register + 7843 74/jump-if-= break/disp8 + 7844 # TODO: ensure there's no dereference + 7845 (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc)) + 7846 eb/jump $translate-mu-index-stmt:end/disp8 + 7847 } + 7848 # if (var->offset) do a different thing + 7849 { + 7850 81 7/subop/compare *(ecx+0xc) 0/imm32 # Var-offset + 7851 74/jump-if-= break/disp8 + 7852 # TODO: ensure there's no dereference + 7853 (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc)) + 7854 eb/jump $translate-mu-index-stmt:end/disp8 + 7855 } + 7856 $translate-mu-index-stmt:end: + 7857 # . restore registers + 7858 59/pop-to-ecx + 7859 # . epilogue + 7860 89/<- %esp 5/r32/ebp + 7861 5d/pop-to-ebp + 7862 c3/return + 7863 + 7864 $translate-mu-index-stmt-with-array:error1: + 7865 (write-buffered Stderr "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n") + 7866 (flush Stderr) + 7867 # . syscall(exit, 1) + 7868 bb/copy-to-ebx 1/imm32 + 7869 b8/copy-to-eax 1/imm32/exit + 7870 cd/syscall 0x80/imm8 + 7871 # never gets here + 7872 + 7873 $translate-mu-index-stmt-with-array:error2: + 7874 (write-buffered Stderr "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n") + 7875 (flush Stderr) + 7876 # . syscall(exit, 1) + 7877 bb/copy-to-ebx 1/imm32 + 7878 b8/copy-to-eax 1/imm32/exit + 7879 cd/syscall 0x80/imm8 + 7880 # never gets here + 7881 + 7882 translate-mu-index-stmt-with-array-in-register: # out: (address buffered-file), stmt: (handle stmt) + 7883 # . prologue + 7884 55/push-ebp + 7885 89/<- %ebp 4/r32/esp + 7886 # . save registers + 7887 50/push-eax + 7888 51/push-ecx + 7889 52/push-edx + 7890 53/push-ebx + 7891 # + 7892 (emit-indent *(ebp+8) *Curr-block-depth) + 7893 (write-buffered *(ebp+8) "8d/copy-address *(") + 7894 # TODO: ensure inouts[0] is in a register and not dereferenced + 7895 $translate-mu-index-stmt-with-array-in-register:emit-base: + 7896 # ecx = stmt + 7897 8b/-> *(ebp+0xc) 1/r32/ecx + 7898 # var base/ebx: (handle var) = inouts[0] + 7899 8b/-> *(ecx+8) 3/r32/ebx # Stmt1-inouts + 7900 8b/-> *ebx 3/r32/ebx # Stmt-var-value + 7901 # print base->register " + " + 7902 (write-buffered *(ebp+8) *(ebx+0x10)) # Var-register + 7903 # + 7904 (write-buffered *(ebp+8) " + ") + 7905 # var index/edx: (handle var) = inouts[1] + 7906 8b/-> *(ecx+8) 2/r32/edx # Stmt1-inouts + 7907 8b/-> *(edx+4) 2/r32/edx # Stmt-var-next + 7908 8b/-> *edx 2/r32/edx # Stmt-var-value + 7909 # if index->register + 7910 81 7/subop/compare *(edx+0x10) 0/imm32 # Var-register + 7911 { + 7912 0f 84/jump-if-= break/disp32 + 7913 $translate-mu-index-stmt-with-array-in-register:emit-register-index: + 7914 # if index is an int + 7915 (is-simple-mu-type? *(edx+4) 1) # Var-type, int => eax + 7916 3d/compare-eax-and 0/imm32/false + 7917 { + 7918 0f 84/jump-if-= break/disp32 + 7919 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index: + 7920 # print index->register "<<" log2(size-of(element(base->type))) " + 4) " + 7921 # . index->register "<<" + 7922 (write-buffered *(ebp+8) *(edx+0x10)) # Var-register + 7923 (write-buffered *(ebp+8) "<<") + 7924 # . log2(size-of(element(base->type))) + 7925 # TODO: ensure size is a power of 2 + 7926 (array-element-type-id %ebx) # => eax + 7927 (size-of-type-id %eax) # => eax + 7928 (num-shift-rights %eax) # => eax + 7929 (print-int32-buffered *(ebp+8) %eax) + 7930 e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32 + 7931 } + 7932 # if index->type is any other atom, abort + 7933 8b/-> *(edx+4) 0/r32/eax # Var-type + 7934 81 7/subop/compare *eax 0/imm32/false # Tree-is-atom + 7935 0f 85/jump-if-!= $translate-mu-index-stmt-with-array:error2/disp32 + 7936 # if index has type (offset ...) + 7937 (is-simple-mu-type? *(eax+4) 7) # Tree-left, offset => eax + 7938 3d/compare-eax-and 0/imm32/false + 7939 { + 7940 0f 84/jump-if-= break/disp32 + 7941 # print index->register " + 4) " + 7942 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index: + 7943 (write-buffered *(ebp+8) *(edx+0x10)) # Var-register + 7944 } + 7945 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done: + 7946 (write-buffered *(ebp+8) " + 4) ") + 7947 e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32 + 7948 } + 7949 # otherwise if index is a literal + 7950 (is-simple-mu-type? *(edx+4) 0) # Var-type => eax + 7951 3d/compare-eax-and 0/imm32/false + 7952 { + 7953 0f 84/jump-if-= break/disp32 + 7954 $translate-mu-index-stmt-with-array-in-register:emit-literal-index: + 7955 # var index-value/edx: int = parse-hex-int(index->name) + 7956 (parse-hex-int *edx) # Var-name => eax + 7957 89/<- %edx 0/r32/eax + 7958 # offset = idx-value * size-of(element(base->type)) + 7959 (array-element-type-id %ebx) # => eax + 7960 (size-of-type-id %eax) # => eax + 7961 f7 4/subop/multiply-into-eax %edx # clobbers edx + 7962 # offset += 4 for array size + 7963 05/add-to-eax 4/imm32 + 7964 # TODO: check edx for overflow + 7965 # print offset + 7966 (print-int32-buffered *(ebp+8) %eax) + 7967 (write-buffered *(ebp+8) ") ") + 7968 e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32 + 7969 } + 7970 # otherwise abort + 7971 e9/jump $translate-mu-index-stmt-with-array:error1/disp32 + 7972 $translate-mu-index-stmt-with-array-in-register:emit-output: 7973 # outputs[0] "/r32" - 7974 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs - 7975 8b/-> *eax 0/r32/eax # Stmt-var-value - 7976 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax - 7977 (print-int32-buffered *(ebp+8) *eax) - 7978 (write-buffered *(ebp+8) "/r32\n") - 7979 $translate-mu-get-stmt:end: - 7980 # . restore registers - 7981 5a/pop-to-edx - 7982 59/pop-to-ecx - 7983 58/pop-to-eax - 7984 # . epilogue - 7985 89/<- %esp 5/r32/ebp - 7986 5d/pop-to-ebp - 7987 c3/return - 7988 - 7989 array-element-type-id: # v: (handle var) -> result/eax: type-id - 7990 # precondition: n is positive - 7991 # . prologue - 7992 55/push-ebp - 7993 89/<- %ebp 4/r32/esp - 7994 # - 7995 8b/-> *(ebp+8) 0/r32/eax - 7996 8b/-> *(eax+4) 0/r32/eax # Var-type - 7997 # TODO: ensure type->left is 'addr' - 7998 8b/-> *(eax+4) 0/r32/eax # Tree-right - 7999 # TODO: ensure that type->right is non-null - 8000 # TODO: ensure that type->right->left is 'array' - 8001 8b/-> *(eax+4) 0/r32/eax # Tree-right - 8002 # TODO: ensure that type->right->right is non-null - 8003 8b/-> *eax 0/r32/eax # Tree-left - 8004 8b/-> *eax 0/r32/eax # Atom-value - 8005 $array-element-type-id:end: - 8006 # . epilogue - 8007 89/<- %esp 5/r32/ebp - 8008 5d/pop-to-ebp - 8009 c3/return - 8010 - 8011 power-of-2?: # n: int -> result/eax: boolean - 8012 # precondition: n is positive - 8013 # . prologue - 8014 55/push-ebp - 8015 89/<- %ebp 4/r32/esp - 8016 # var tmp/eax: int = n-1 - 8017 8b/-> *(ebp+8) 0/r32/eax - 8018 48/decrement-eax - 8019 # var tmp2/eax: int = n & tmp - 8020 0b/and-> *(ebp+8) 0/r32/eax - 8021 # return (tmp2 == 0) - 8022 3d/compare-eax-and 0/imm32 - 8023 0f 94/set-byte-if-= %al - 8024 81 4/subop/and %eax 0xff/imm32 - 8025 $power-of-2?:end: - 8026 # . epilogue - 8027 89/<- %esp 5/r32/ebp - 8028 5d/pop-to-ebp - 8029 c3/return - 8030 - 8031 num-shift-rights: # n: int -> result/eax: int - 8032 # precondition: n is a positive power of 2 - 8033 # . prologue - 8034 55/push-ebp - 8035 89/<- %ebp 4/r32/esp - 8036 # . save registers - 8037 51/push-ecx - 8038 # var curr/ecx: int = n - 8039 8b/-> *(ebp+8) 1/r32/ecx - 8040 # result = 0 - 8041 b8/copy-to-eax 0/imm32 - 8042 { - 8043 # if (curr <= 1) break - 8044 81 7/subop/compare %ecx 1/imm32 - 8045 7e/jump-if-<= break/disp8 - 8046 40/increment-eax - 8047 c1/shift 5/subop/arithmetic-right %ecx 1/imm8 - 8048 eb/jump loop/disp8 - 8049 } - 8050 $num-shift-rights:end: - 8051 # . restore registers - 8052 59/pop-to-ecx - 8053 # . epilogue - 8054 89/<- %esp 5/r32/ebp - 8055 5d/pop-to-ebp - 8056 c3/return - 8057 - 8058 mu-get-offset: # stmt: (handle stmt) -> result/eax: int - 8059 # . prologue - 8060 55/push-ebp - 8061 89/<- %ebp 4/r32/esp - 8062 # var second-inout/eax: (handle stmt-var) = stmt->inouts->next - 8063 8b/-> *(ebp+8) 0/r32/eax - 8064 8b/-> *(eax+8) 0/r32/eax # Stmt1-inouts - 8065 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next - 8066 # var output-var/eax: (handle var) = second-inout->value - 8067 8b/-> *eax 0/r32/eax # Stmt-var-value - 8068 # return output-var->offset - 8069 8b/-> *(eax+0xc) 0/r32/eax # Var-offset - 8070 $emit-get-offset:end: - 8071 # . epilogue - 8072 89/<- %esp 5/r32/ebp - 8073 5d/pop-to-ebp - 8074 c3/return - 8075 - 8076 emit-subx-block: # out: (addr buffered-file), block: (handle block), vars: (addr stack (handle var)) - 8077 # . prologue - 8078 55/push-ebp - 8079 89/<- %ebp 4/r32/esp - 8080 # . save registers - 8081 50/push-eax - 8082 51/push-ecx - 8083 56/push-esi - 8084 # esi = block - 8085 8b/-> *(ebp+0xc) 6/r32/esi - 8086 # block->var->block-depth = *Curr-block-depth - 8087 8b/-> *(esi+8) 0/r32/eax # Block-var - 8088 8b/-> *Curr-block-depth 1/r32/ecx - 8089 89/<- *(eax+8) 1/r32/ecx # Var-block-depth - 8090 # var stmts/eax: (handle list stmt) = block->statements - 8091 8b/-> *(esi+4) 0/r32/eax # Block-stmts - 8092 # - 8093 { - 8094 $emit-subx-block:check-empty: - 8095 3d/compare-eax-and 0/imm32 - 8096 0f 84/jump-if-= break/disp32 - 8097 (emit-indent *(ebp+8) *Curr-block-depth) - 8098 (write-buffered *(ebp+8) "{\n") - 8099 # var v/ecx: (handle var) - 8100 8b/-> *(esi+8) 1/r32/ecx # Block-var - 8101 # - 8102 (write-buffered *(ebp+8) *ecx) # Var-name - 8103 (write-buffered *(ebp+8) ":loop:\n") - 8104 ff 0/subop/increment *Curr-block-depth - 8105 (push *(ebp+0x10) %ecx) - 8106 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10)) - 8107 (pop *(ebp+0x10)) # => eax - 8108 ff 1/subop/decrement *Curr-block-depth - 8109 (emit-indent *(ebp+8) *Curr-block-depth) - 8110 (write-buffered *(ebp+8) "}\n") - 8111 (write-buffered *(ebp+8) *ecx) # Var-name - 8112 (write-buffered *(ebp+8) ":break:\n") - 8113 } - 8114 $emit-subx-block:end: - 8115 # . restore registers - 8116 5e/pop-to-esi - 8117 59/pop-to-ecx - 8118 58/pop-to-eax - 8119 # . epilogue - 8120 89/<- %esp 5/r32/ebp - 8121 5d/pop-to-ebp - 8122 c3/return - 8123 - 8124 # Primitives supported - 8125 # For each operation, put variants with hard-coded registers before flexible ones. - 8126 == data - 8127 Primitives: - 8128 # - increment/decrement - 8129 _Primitive-inc-eax: - 8130 # var/eax <- increment => 40/increment-eax - 8131 "increment"/imm32/name - 8132 0/imm32/no-inouts - 8133 Single-int-var-in-eax/imm32/outputs - 8134 "40/increment-eax"/imm32/subx-name - 8135 0/imm32/no-rm32 - 8136 0/imm32/no-r32 - 8137 0/imm32/no-imm32 - 8138 0/imm32/no-disp32 - 8139 0/imm32/output-is-write-only - 8140 _Primitive-inc-ecx/imm32/next - 8141 _Primitive-inc-ecx: - 8142 # var/ecx <- increment => 41/increment-ecx - 8143 "increment"/imm32/name - 8144 0/imm32/no-inouts - 8145 Single-int-var-in-ecx/imm32/outputs - 8146 "41/increment-ecx"/imm32/subx-name - 8147 0/imm32/no-rm32 - 8148 0/imm32/no-r32 - 8149 0/imm32/no-imm32 - 8150 0/imm32/no-disp32 - 8151 0/imm32/output-is-write-only - 8152 _Primitive-inc-edx/imm32/next - 8153 _Primitive-inc-edx: - 8154 # var/edx <- increment => 42/increment-edx - 8155 "increment"/imm32/name - 8156 0/imm32/no-inouts - 8157 Single-int-var-in-edx/imm32/outputs - 8158 "42/increment-edx"/imm32/subx-name - 8159 0/imm32/no-rm32 - 8160 0/imm32/no-r32 - 8161 0/imm32/no-imm32 - 8162 0/imm32/no-disp32 - 8163 0/imm32/output-is-write-only - 8164 _Primitive-inc-ebx/imm32/next - 8165 _Primitive-inc-ebx: - 8166 # var/ebx <- increment => 43/increment-ebx - 8167 "increment"/imm32/name - 8168 0/imm32/no-inouts - 8169 Single-int-var-in-ebx/imm32/outputs - 8170 "43/increment-ebx"/imm32/subx-name - 8171 0/imm32/no-rm32 - 8172 0/imm32/no-r32 - 8173 0/imm32/no-imm32 - 8174 0/imm32/no-disp32 - 8175 0/imm32/output-is-write-only - 8176 _Primitive-inc-esi/imm32/next - 8177 _Primitive-inc-esi: - 8178 # var/esi <- increment => 46/increment-esi - 8179 "increment"/imm32/name - 8180 0/imm32/no-inouts - 8181 Single-int-var-in-esi/imm32/outputs - 8182 "46/increment-esi"/imm32/subx-name - 8183 0/imm32/no-rm32 - 8184 0/imm32/no-r32 - 8185 0/imm32/no-imm32 - 8186 0/imm32/no-disp32 - 8187 0/imm32/output-is-write-only - 8188 _Primitive-inc-edi/imm32/next - 8189 _Primitive-inc-edi: - 8190 # var/edi <- increment => 47/increment-edi - 8191 "increment"/imm32/name - 8192 0/imm32/no-inouts - 8193 Single-int-var-in-edi/imm32/outputs - 8194 "47/increment-edi"/imm32/subx-name - 8195 0/imm32/no-rm32 - 8196 0/imm32/no-r32 - 8197 0/imm32/no-imm32 - 8198 0/imm32/no-disp32 - 8199 0/imm32/output-is-write-only - 8200 _Primitive-dec-eax/imm32/next - 8201 _Primitive-dec-eax: - 8202 # var/eax <- decrement => 48/decrement-eax - 8203 "decrement"/imm32/name - 8204 0/imm32/no-inouts - 8205 Single-int-var-in-eax/imm32/outputs - 8206 "48/decrement-eax"/imm32/subx-name - 8207 0/imm32/no-rm32 - 8208 0/imm32/no-r32 - 8209 0/imm32/no-imm32 - 8210 0/imm32/no-disp32 - 8211 0/imm32/output-is-write-only - 8212 _Primitive-dec-ecx/imm32/next - 8213 _Primitive-dec-ecx: - 8214 # var/ecx <- decrement => 49/decrement-ecx - 8215 "decrement"/imm32/name - 8216 0/imm32/no-inouts - 8217 Single-int-var-in-ecx/imm32/outputs - 8218 "49/decrement-ecx"/imm32/subx-name - 8219 0/imm32/no-rm32 - 8220 0/imm32/no-r32 - 8221 0/imm32/no-imm32 - 8222 0/imm32/no-disp32 - 8223 0/imm32/output-is-write-only - 8224 _Primitive-dec-edx/imm32/next - 8225 _Primitive-dec-edx: - 8226 # var/edx <- decrement => 4a/decrement-edx - 8227 "decrement"/imm32/name - 8228 0/imm32/no-inouts - 8229 Single-int-var-in-edx/imm32/outputs - 8230 "4a/decrement-edx"/imm32/subx-name - 8231 0/imm32/no-rm32 - 8232 0/imm32/no-r32 - 8233 0/imm32/no-imm32 - 8234 0/imm32/no-disp32 - 8235 0/imm32/output-is-write-only - 8236 _Primitive-dec-ebx/imm32/next - 8237 _Primitive-dec-ebx: - 8238 # var/ebx <- decrement => 4b/decrement-ebx - 8239 "decrement"/imm32/name - 8240 0/imm32/no-inouts - 8241 Single-int-var-in-ebx/imm32/outputs - 8242 "4b/decrement-ebx"/imm32/subx-name - 8243 0/imm32/no-rm32 - 8244 0/imm32/no-r32 - 8245 0/imm32/no-imm32 - 8246 0/imm32/no-disp32 - 8247 0/imm32/output-is-write-only - 8248 _Primitive-dec-esi/imm32/next - 8249 _Primitive-dec-esi: - 8250 # var/esi <- decrement => 4e/decrement-esi - 8251 "decrement"/imm32/name - 8252 0/imm32/no-inouts - 8253 Single-int-var-in-esi/imm32/outputs - 8254 "4e/decrement-esi"/imm32/subx-name - 8255 0/imm32/no-rm32 - 8256 0/imm32/no-r32 - 8257 0/imm32/no-imm32 - 8258 0/imm32/no-disp32 - 8259 0/imm32/output-is-write-only - 8260 _Primitive-dec-edi/imm32/next - 8261 _Primitive-dec-edi: - 8262 # var/edi <- decrement => 4f/decrement-edi - 8263 "decrement"/imm32/name - 8264 0/imm32/no-inouts - 8265 Single-int-var-in-edi/imm32/outputs - 8266 "4f/decrement-edi"/imm32/subx-name - 8267 0/imm32/no-rm32 - 8268 0/imm32/no-r32 - 8269 0/imm32/no-imm32 - 8270 0/imm32/no-disp32 - 8271 0/imm32/output-is-write-only - 8272 _Primitive-inc-mem/imm32/next - 8273 _Primitive-inc-mem: - 8274 # increment var => ff 0/subop/increment *(ebp+__) - 8275 "increment"/imm32/name - 8276 Single-int-var-in-mem/imm32/inouts - 8277 0/imm32/no-outputs - 8278 "ff 0/subop/increment"/imm32/subx-name - 8279 1/imm32/rm32-is-first-inout - 8280 0/imm32/no-r32 - 8281 0/imm32/no-imm32 - 8282 0/imm32/no-disp32 - 8283 0/imm32/output-is-write-only - 8284 _Primitive-inc-reg/imm32/next - 8285 _Primitive-inc-reg: - 8286 # var/reg <- increment => ff 0/subop/increment %__ - 8287 "increment"/imm32/name - 8288 0/imm32/no-inouts - 8289 Single-int-var-in-some-register/imm32/outputs - 8290 "ff 0/subop/increment"/imm32/subx-name - 8291 3/imm32/rm32-is-first-output - 8292 0/imm32/no-r32 - 8293 0/imm32/no-imm32 - 8294 0/imm32/no-disp32 - 8295 0/imm32/output-is-write-only - 8296 _Primitive-dec-mem/imm32/next - 8297 _Primitive-dec-mem: - 8298 # decrement var => ff 1/subop/decrement *(ebp+__) - 8299 "decrement"/imm32/name - 8300 Single-int-var-in-mem/imm32/inouts - 8301 0/imm32/no-outputs - 8302 "ff 1/subop/decrement"/imm32/subx-name - 8303 1/imm32/rm32-is-first-inout - 8304 0/imm32/no-r32 - 8305 0/imm32/no-imm32 - 8306 0/imm32/no-disp32 - 8307 0/imm32/output-is-write-only - 8308 _Primitive-dec-reg/imm32/next - 8309 _Primitive-dec-reg: - 8310 # var/reg <- decrement => ff 1/subop/decrement %__ - 8311 "decrement"/imm32/name - 8312 0/imm32/no-inouts - 8313 Single-int-var-in-some-register/imm32/outputs - 8314 "ff 1/subop/decrement"/imm32/subx-name - 8315 3/imm32/rm32-is-first-output - 8316 0/imm32/no-r32 - 8317 0/imm32/no-imm32 - 8318 0/imm32/no-disp32 - 8319 0/imm32/output-is-write-only - 8320 _Primitive-add-to-eax/imm32/next - 8321 # - add - 8322 _Primitive-add-to-eax: - 8323 # var/eax <- add lit => 05/add-to-eax lit/imm32 - 8324 "add"/imm32/name - 8325 Single-lit-var/imm32/inouts - 8326 Single-int-var-in-eax/imm32/outputs - 8327 "05/add-to-eax"/imm32/subx-name - 8328 0/imm32/no-rm32 - 8329 0/imm32/no-r32 - 8330 1/imm32/imm32-is-first-inout - 8331 0/imm32/no-disp32 - 8332 0/imm32/output-is-write-only - 8333 _Primitive-add-reg-to-reg/imm32/next - 8334 _Primitive-add-reg-to-reg: - 8335 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 - 8336 "add"/imm32/name - 8337 Single-int-var-in-some-register/imm32/inouts - 8338 Single-int-var-in-some-register/imm32/outputs - 8339 "01/add-to"/imm32/subx-name - 8340 3/imm32/rm32-is-first-output - 8341 1/imm32/r32-is-first-inout - 8342 0/imm32/no-imm32 - 8343 0/imm32/no-disp32 - 8344 0/imm32/output-is-write-only - 8345 _Primitive-add-reg-to-mem/imm32/next - 8346 _Primitive-add-reg-to-mem: - 8347 # add-to var1 var2/reg => 01/add-to var1 var2/r32 - 8348 "add-to"/imm32/name - 8349 Two-args-int-stack-int-reg/imm32/inouts - 8350 0/imm32/outputs - 8351 "01/add-to"/imm32/subx-name - 8352 1/imm32/rm32-is-first-inout - 8353 2/imm32/r32-is-second-inout - 8354 0/imm32/no-imm32 - 8355 0/imm32/no-disp32 - 8356 0/imm32/output-is-write-only - 8357 _Primitive-add-mem-to-reg/imm32/next - 8358 _Primitive-add-mem-to-reg: - 8359 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 - 8360 "add"/imm32/name - 8361 Single-int-var-in-mem/imm32/inouts - 8362 Single-int-var-in-some-register/imm32/outputs - 8363 "03/add"/imm32/subx-name - 8364 1/imm32/rm32-is-first-inout - 8365 3/imm32/r32-is-first-output - 8366 0/imm32/no-imm32 - 8367 0/imm32/no-disp32 - 8368 0/imm32/output-is-write-only - 8369 _Primitive-add-lit-to-reg/imm32/next - 8370 _Primitive-add-lit-to-reg: - 8371 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 - 8372 "add"/imm32/name - 8373 Single-lit-var/imm32/inouts - 8374 Single-int-var-in-some-register/imm32/outputs - 8375 "81 0/subop/add"/imm32/subx-name - 8376 3/imm32/rm32-is-first-output - 8377 0/imm32/no-r32 - 8378 1/imm32/imm32-is-first-inout - 8379 0/imm32/no-disp32 - 8380 0/imm32/output-is-write-only - 8381 _Primitive-add-lit-to-mem/imm32/next - 8382 _Primitive-add-lit-to-mem: - 8383 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 - 8384 "add-to"/imm32/name - 8385 Int-var-and-literal/imm32/inouts - 8386 0/imm32/outputs - 8387 "81 0/subop/add"/imm32/subx-name - 8388 1/imm32/rm32-is-first-inout - 8389 0/imm32/no-r32 - 8390 2/imm32/imm32-is-second-inout - 8391 0/imm32/no-disp32 - 8392 0/imm32/output-is-write-only - 8393 _Primitive-subtract-from-eax/imm32/next - 8394 # - subtract - 8395 _Primitive-subtract-from-eax: - 8396 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 - 8397 "subtract"/imm32/name - 8398 Single-lit-var/imm32/inouts - 8399 Single-int-var-in-eax/imm32/outputs - 8400 "2d/subtract-from-eax"/imm32/subx-name - 8401 0/imm32/no-rm32 - 8402 0/imm32/no-r32 - 8403 1/imm32/imm32-is-first-inout - 8404 0/imm32/no-disp32 - 8405 0/imm32/output-is-write-only - 8406 _Primitive-subtract-reg-from-reg/imm32/next - 8407 _Primitive-subtract-reg-from-reg: - 8408 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 - 8409 "subtract"/imm32/name - 8410 Single-int-var-in-some-register/imm32/inouts - 8411 Single-int-var-in-some-register/imm32/outputs - 8412 "29/subtract-from"/imm32/subx-name - 8413 3/imm32/rm32-is-first-output - 8414 1/imm32/r32-is-first-inout - 8415 0/imm32/no-imm32 - 8416 0/imm32/no-disp32 - 8417 0/imm32/output-is-write-only - 8418 _Primitive-subtract-reg-from-mem/imm32/next - 8419 _Primitive-subtract-reg-from-mem: - 8420 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 - 8421 "subtract-from"/imm32/name - 8422 Two-args-int-stack-int-reg/imm32/inouts - 8423 0/imm32/outputs - 8424 "29/subtract-from"/imm32/subx-name - 8425 1/imm32/rm32-is-first-inout - 8426 2/imm32/r32-is-second-inout - 8427 0/imm32/no-imm32 - 8428 0/imm32/no-disp32 - 8429 0/imm32/output-is-write-only - 8430 _Primitive-subtract-mem-from-reg/imm32/next - 8431 _Primitive-subtract-mem-from-reg: - 8432 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 - 8433 "subtract"/imm32/name - 8434 Single-int-var-in-mem/imm32/inouts - 8435 Single-int-var-in-some-register/imm32/outputs - 8436 "2b/subtract"/imm32/subx-name - 8437 1/imm32/rm32-is-first-inout - 8438 3/imm32/r32-is-first-output - 8439 0/imm32/no-imm32 - 8440 0/imm32/no-disp32 - 8441 0/imm32/output-is-write-only - 8442 _Primitive-subtract-lit-from-reg/imm32/next - 8443 _Primitive-subtract-lit-from-reg: - 8444 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 - 8445 "subtract"/imm32/name - 8446 Single-lit-var/imm32/inouts - 8447 Single-int-var-in-some-register/imm32/outputs - 8448 "81 5/subop/subtract"/imm32/subx-name - 8449 3/imm32/rm32-is-first-output - 8450 0/imm32/no-r32 - 8451 1/imm32/imm32-is-first-inout - 8452 0/imm32/no-disp32 - 8453 0/imm32/output-is-write-only - 8454 _Primitive-subtract-lit-from-mem/imm32/next - 8455 _Primitive-subtract-lit-from-mem: - 8456 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 - 8457 "subtract-from"/imm32/name - 8458 Int-var-and-literal/imm32/inouts - 8459 0/imm32/outputs - 8460 "81 5/subop/subtract"/imm32/subx-name - 8461 1/imm32/rm32-is-first-inout - 8462 0/imm32/no-r32 - 8463 2/imm32/imm32-is-first-inout - 8464 0/imm32/no-disp32 - 8465 0/imm32/output-is-write-only - 8466 _Primitive-and-with-eax/imm32/next - 8467 # - and - 8468 _Primitive-and-with-eax: - 8469 # var/eax <- and lit => 25/and-with-eax lit/imm32 - 8470 "and"/imm32/name - 8471 Single-lit-var/imm32/inouts - 8472 Single-int-var-in-eax/imm32/outputs - 8473 "25/and-with-eax"/imm32/subx-name - 8474 0/imm32/no-rm32 - 8475 0/imm32/no-r32 - 8476 1/imm32/imm32-is-first-inout - 8477 0/imm32/no-disp32 - 8478 0/imm32/output-is-write-only - 8479 _Primitive-and-reg-with-reg/imm32/next - 8480 _Primitive-and-reg-with-reg: - 8481 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 - 8482 "and"/imm32/name - 8483 Single-int-var-in-some-register/imm32/inouts - 8484 Single-int-var-in-some-register/imm32/outputs - 8485 "21/and-with"/imm32/subx-name - 8486 3/imm32/rm32-is-first-output - 8487 1/imm32/r32-is-first-inout - 8488 0/imm32/no-imm32 - 8489 0/imm32/no-disp32 - 8490 0/imm32/output-is-write-only - 8491 _Primitive-and-reg-with-mem/imm32/next - 8492 _Primitive-and-reg-with-mem: - 8493 # and-with var1 var2/reg => 21/and-with var1 var2/r32 - 8494 "and-with"/imm32/name - 8495 Two-args-int-stack-int-reg/imm32/inouts - 8496 0/imm32/outputs - 8497 "21/and-with"/imm32/subx-name - 8498 1/imm32/rm32-is-first-inout - 8499 2/imm32/r32-is-second-inout - 8500 0/imm32/no-imm32 - 8501 0/imm32/no-disp32 - 8502 0/imm32/output-is-write-only - 8503 _Primitive-and-mem-with-reg/imm32/next - 8504 _Primitive-and-mem-with-reg: - 8505 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 - 8506 "and"/imm32/name - 8507 Single-int-var-in-mem/imm32/inouts - 8508 Single-int-var-in-some-register/imm32/outputs - 8509 "23/and"/imm32/subx-name - 8510 1/imm32/rm32-is-first-inout - 8511 3/imm32/r32-is-first-output - 8512 0/imm32/no-imm32 - 8513 0/imm32/no-disp32 - 8514 0/imm32/output-is-write-only - 8515 _Primitive-and-lit-with-reg/imm32/next - 8516 _Primitive-and-lit-with-reg: - 8517 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 - 8518 "and"/imm32/name - 8519 Single-lit-var/imm32/inouts - 8520 Single-int-var-in-some-register/imm32/outputs - 8521 "81 4/subop/and"/imm32/subx-name - 8522 3/imm32/rm32-is-first-output - 8523 0/imm32/no-r32 - 8524 1/imm32/imm32-is-first-inout - 8525 0/imm32/no-disp32 - 8526 0/imm32/output-is-write-only - 8527 _Primitive-and-lit-with-mem/imm32/next - 8528 _Primitive-and-lit-with-mem: - 8529 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 - 8530 "and-with"/imm32/name - 8531 Int-var-and-literal/imm32/inouts - 8532 0/imm32/outputs - 8533 "81 4/subop/and"/imm32/subx-name - 8534 1/imm32/rm32-is-first-inout - 8535 0/imm32/no-r32 - 8536 2/imm32/imm32-is-first-inout - 8537 0/imm32/no-disp32 - 8538 0/imm32/output-is-write-only - 8539 _Primitive-or-with-eax/imm32/next - 8540 # - or - 8541 _Primitive-or-with-eax: - 8542 # var/eax <- or lit => 0d/or-with-eax lit/imm32 - 8543 "or"/imm32/name - 8544 Single-lit-var/imm32/inouts - 8545 Single-int-var-in-eax/imm32/outputs - 8546 "0d/or-with-eax"/imm32/subx-name - 8547 0/imm32/no-rm32 - 8548 0/imm32/no-r32 - 8549 1/imm32/imm32-is-first-inout - 8550 0/imm32/no-disp32 - 8551 0/imm32/output-is-write-only - 8552 _Primitive-or-reg-with-reg/imm32/next - 8553 _Primitive-or-reg-with-reg: - 8554 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 - 8555 "or"/imm32/name - 8556 Single-int-var-in-some-register/imm32/inouts - 8557 Single-int-var-in-some-register/imm32/outputs - 8558 "09/or-with"/imm32/subx-name - 8559 3/imm32/rm32-is-first-output - 8560 1/imm32/r32-is-first-inout - 8561 0/imm32/no-imm32 - 8562 0/imm32/no-disp32 - 8563 0/imm32/output-is-write-only - 8564 _Primitive-or-reg-with-mem/imm32/next - 8565 _Primitive-or-reg-with-mem: - 8566 # or-with var1 var2/reg => 09/or-with var1 var2/r32 - 8567 "or-with"/imm32/name - 8568 Two-args-int-stack-int-reg/imm32/inouts - 8569 0/imm32/outputs - 8570 "09/or-with"/imm32/subx-name - 8571 1/imm32/rm32-is-first-inout - 8572 2/imm32/r32-is-second-inout - 8573 0/imm32/no-imm32 - 8574 0/imm32/no-disp32 - 8575 0/imm32/output-is-write-only - 8576 _Primitive-or-mem-with-reg/imm32/next - 8577 _Primitive-or-mem-with-reg: - 8578 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 - 8579 "or"/imm32/name - 8580 Single-int-var-in-mem/imm32/inouts - 8581 Single-int-var-in-some-register/imm32/outputs - 8582 "0b/or"/imm32/subx-name - 8583 1/imm32/rm32-is-first-inout - 8584 3/imm32/r32-is-first-output - 8585 0/imm32/no-imm32 - 8586 0/imm32/no-disp32 - 8587 0/imm32/output-is-write-only - 8588 _Primitive-or-lit-with-reg/imm32/next - 8589 _Primitive-or-lit-with-reg: - 8590 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 - 8591 "or"/imm32/name - 8592 Single-lit-var/imm32/inouts - 8593 Single-int-var-in-some-register/imm32/outputs - 8594 "81 1/subop/or"/imm32/subx-name - 8595 3/imm32/rm32-is-first-output - 8596 0/imm32/no-r32 - 8597 1/imm32/imm32-is-first-inout - 8598 0/imm32/no-disp32 - 8599 0/imm32/output-is-write-only - 8600 _Primitive-or-lit-with-mem/imm32/next - 8601 _Primitive-or-lit-with-mem: - 8602 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 - 8603 "or-with"/imm32/name - 8604 Int-var-and-literal/imm32/inouts - 8605 0/imm32/outputs - 8606 "81 1/subop/or"/imm32/subx-name - 8607 1/imm32/rm32-is-first-inout - 8608 0/imm32/no-r32 - 8609 2/imm32/imm32-is-second-inout - 8610 0/imm32/no-disp32 - 8611 0/imm32/output-is-write-only - 8612 _Primitive-xor-with-eax/imm32/next - 8613 # - xor - 8614 _Primitive-xor-with-eax: - 8615 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 - 8616 "xor"/imm32/name - 8617 Single-lit-var/imm32/inouts - 8618 Single-int-var-in-eax/imm32/outputs - 8619 "35/xor-with-eax"/imm32/subx-name - 8620 0/imm32/no-rm32 - 8621 0/imm32/no-r32 - 8622 1/imm32/imm32-is-first-inout - 8623 0/imm32/no-disp32 - 8624 0/imm32/output-is-write-only - 8625 _Primitive-xor-reg-with-reg/imm32/next - 8626 _Primitive-xor-reg-with-reg: - 8627 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 - 8628 "xor"/imm32/name - 8629 Single-int-var-in-some-register/imm32/inouts - 8630 Single-int-var-in-some-register/imm32/outputs - 8631 "31/xor-with"/imm32/subx-name - 8632 3/imm32/rm32-is-first-output - 8633 1/imm32/r32-is-first-inout - 8634 0/imm32/no-imm32 - 8635 0/imm32/no-disp32 - 8636 0/imm32/output-is-write-only - 8637 _Primitive-xor-reg-with-mem/imm32/next - 8638 _Primitive-xor-reg-with-mem: - 8639 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 - 8640 "xor-with"/imm32/name - 8641 Two-args-int-stack-int-reg/imm32/inouts - 8642 0/imm32/outputs - 8643 "31/xor-with"/imm32/subx-name - 8644 1/imm32/rm32-is-first-inout - 8645 2/imm32/r32-is-second-inout - 8646 0/imm32/no-imm32 - 8647 0/imm32/no-disp32 - 8648 0/imm32/output-is-write-only - 8649 _Primitive-xor-mem-with-reg/imm32/next - 8650 _Primitive-xor-mem-with-reg: - 8651 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 - 8652 "xor"/imm32/name - 8653 Single-int-var-in-mem/imm32/inouts - 8654 Single-int-var-in-some-register/imm32/outputs - 8655 "33/xor"/imm32/subx-name - 8656 1/imm32/rm32-is-first-inout - 8657 3/imm32/r32-is-first-output - 8658 0/imm32/no-imm32 - 8659 0/imm32/no-disp32 - 8660 0/imm32/output-is-write-only - 8661 _Primitive-xor-lit-with-reg/imm32/next - 8662 _Primitive-xor-lit-with-reg: - 8663 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 - 8664 "xor"/imm32/name - 8665 Single-lit-var/imm32/inouts - 8666 Single-int-var-in-some-register/imm32/outputs - 8667 "81 6/subop/xor"/imm32/subx-name - 8668 3/imm32/rm32-is-first-output - 8669 0/imm32/no-r32 - 8670 1/imm32/imm32-is-first-inout - 8671 0/imm32/no-disp32 - 8672 0/imm32/output-is-write-only - 8673 _Primitive-xor-lit-with-mem/imm32/next - 8674 _Primitive-xor-lit-with-mem: - 8675 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 - 8676 "xor-with"/imm32/name - 8677 Int-var-and-literal/imm32/inouts - 8678 0/imm32/outputs - 8679 "81 6/subop/xor"/imm32/subx-name - 8680 1/imm32/rm32-is-first-inout - 8681 0/imm32/no-r32 - 8682 2/imm32/imm32-is-first-inout - 8683 0/imm32/no-disp32 - 8684 0/imm32/output-is-write-only - 8685 _Primitive-copy-to-eax/imm32/next - 8686 # - copy - 8687 _Primitive-copy-to-eax: - 8688 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 - 8689 "copy"/imm32/name - 8690 Single-lit-var/imm32/inouts - 8691 Single-int-var-in-eax/imm32/outputs - 8692 "b8/copy-to-eax"/imm32/subx-name - 8693 0/imm32/no-rm32 - 8694 0/imm32/no-r32 - 8695 1/imm32/imm32-is-first-inout - 8696 0/imm32/no-disp32 - 8697 1/imm32/output-is-write-only - 8698 _Primitive-copy-to-ecx/imm32/next - 8699 _Primitive-copy-to-ecx: - 8700 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 - 8701 "copy"/imm32/name - 8702 Single-lit-var/imm32/inouts - 8703 Single-int-var-in-ecx/imm32/outputs - 8704 "b9/copy-to-ecx"/imm32/subx-name - 8705 0/imm32/no-rm32 - 8706 0/imm32/no-r32 - 8707 1/imm32/imm32-is-first-inout - 8708 0/imm32/no-disp32 - 8709 1/imm32/output-is-write-only - 8710 _Primitive-copy-to-edx/imm32/next - 8711 _Primitive-copy-to-edx: - 8712 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 - 8713 "copy"/imm32/name - 8714 Single-lit-var/imm32/inouts - 8715 Single-int-var-in-edx/imm32/outputs - 8716 "ba/copy-to-edx"/imm32/subx-name - 8717 0/imm32/no-rm32 - 8718 0/imm32/no-r32 - 8719 1/imm32/imm32-is-first-inout - 8720 0/imm32/no-disp32 - 8721 1/imm32/output-is-write-only - 8722 _Primitive-copy-to-ebx/imm32/next - 8723 _Primitive-copy-to-ebx: - 8724 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 - 8725 "copy"/imm32/name - 8726 Single-lit-var/imm32/inouts - 8727 Single-int-var-in-ebx/imm32/outputs - 8728 "bb/copy-to-ebx"/imm32/subx-name - 8729 0/imm32/no-rm32 - 8730 0/imm32/no-r32 - 8731 1/imm32/imm32-is-first-inout - 8732 0/imm32/no-disp32 - 8733 1/imm32/output-is-write-only - 8734 _Primitive-copy-to-esi/imm32/next - 8735 _Primitive-copy-to-esi: - 8736 # var/esi <- copy lit => be/copy-to-esi lit/imm32 - 8737 "copy"/imm32/name - 8738 Single-lit-var/imm32/inouts - 8739 Single-int-var-in-esi/imm32/outputs - 8740 "be/copy-to-esi"/imm32/subx-name - 8741 0/imm32/no-rm32 - 8742 0/imm32/no-r32 - 8743 1/imm32/imm32-is-first-inout - 8744 0/imm32/no-disp32 - 8745 1/imm32/output-is-write-only - 8746 _Primitive-copy-to-edi/imm32/next - 8747 _Primitive-copy-to-edi: - 8748 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 - 8749 "copy"/imm32/name - 8750 Single-lit-var/imm32/inouts - 8751 Single-int-var-in-edi/imm32/outputs - 8752 "bf/copy-to-edi"/imm32/subx-name - 8753 0/imm32/no-rm32 - 8754 0/imm32/no-r32 - 8755 1/imm32/imm32-is-first-inout - 8756 0/imm32/no-disp32 - 8757 1/imm32/output-is-write-only - 8758 _Primitive-copy-reg-to-reg/imm32/next - 8759 _Primitive-copy-reg-to-reg: - 8760 # var1/reg <- copy var2/reg => 89/copy-to var1/rm32 var2/r32 - 8761 "copy"/imm32/name - 8762 Single-int-var-in-some-register/imm32/inouts - 8763 Single-int-var-in-some-register/imm32/outputs - 8764 "89/copy-to"/imm32/subx-name - 8765 3/imm32/rm32-is-first-output - 8766 1/imm32/r32-is-first-inout - 8767 0/imm32/no-imm32 - 8768 0/imm32/no-disp32 - 8769 1/imm32/output-is-write-only - 8770 _Primitive-copy-reg-to-mem/imm32/next - 8771 _Primitive-copy-reg-to-mem: - 8772 # copy-to var1 var2/reg => 89/copy-to var1 var2/r32 - 8773 "copy-to"/imm32/name - 8774 Two-args-int-stack-int-reg/imm32/inouts - 8775 0/imm32/outputs - 8776 "89/copy-to"/imm32/subx-name - 8777 1/imm32/rm32-is-first-inout - 8778 2/imm32/r32-is-second-inout - 8779 0/imm32/no-imm32 - 8780 0/imm32/no-disp32 - 8781 1/imm32/output-is-write-only - 8782 _Primitive-copy-mem-to-reg/imm32/next - 8783 _Primitive-copy-mem-to-reg: - 8784 # var1/reg <- copy var2 => 8b/copy-from var2/rm32 var1/r32 - 8785 "copy"/imm32/name - 8786 Single-int-var-in-mem/imm32/inouts - 8787 Single-int-var-in-some-register/imm32/outputs - 8788 "8b/copy-from"/imm32/subx-name - 8789 1/imm32/rm32-is-first-inout - 8790 3/imm32/r32-is-first-output - 8791 0/imm32/no-imm32 - 8792 0/imm32/no-disp32 - 8793 1/imm32/output-is-write-only - 8794 _Primitive-copy-lit-to-reg/imm32/next - 8795 _Primitive-copy-lit-to-reg: - 8796 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 - 8797 "copy"/imm32/name - 8798 Single-lit-var/imm32/inouts - 8799 Single-int-var-in-some-register/imm32/outputs - 8800 "c7 0/subop/copy"/imm32/subx-name - 8801 3/imm32/rm32-is-first-output - 8802 0/imm32/no-r32 - 8803 1/imm32/imm32-is-first-inout - 8804 0/imm32/no-disp32 - 8805 1/imm32/output-is-write-only - 8806 _Primitive-copy-lit-to-mem/imm32/next - 8807 _Primitive-copy-lit-to-mem: - 8808 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 - 8809 "copy-to"/imm32/name - 8810 Int-var-and-literal/imm32/inouts - 8811 0/imm32/outputs - 8812 "c7 0/subop/copy"/imm32/subx-name - 8813 1/imm32/rm32-is-first-inout - 8814 0/imm32/no-r32 - 8815 2/imm32/imm32-is-first-inout - 8816 0/imm32/no-disp32 - 8817 1/imm32/output-is-write-only - 8818 _Primitive-address/imm32/next - 8819 # - address - 8820 _Primitive-address: - 8821 # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32 - 8822 "address"/imm32/name - 8823 Single-int-var-in-mem/imm32/inouts - 8824 Single-addr-var-in-some-register/imm32/outputs - 8825 "8d/copy-address"/imm32/subx-name - 8826 1/imm32/rm32-is-first-inout - 8827 3/imm32/r32-is-first-output - 8828 0/imm32/no-imm32 - 8829 0/imm32/no-disp32 - 8830 1/imm32/output-is-write-only - 8831 _Primitive-compare-mem-with-reg/imm32/next - 8832 # - compare - 8833 _Primitive-compare-mem-with-reg: - 8834 # compare var1 var2/reg => 39/compare-> var1/rm32 var2/r32 - 8835 "compare"/imm32/name - 8836 Two-args-int-stack-int-reg/imm32/inouts - 8837 0/imm32/outputs - 8838 "39/compare->"/imm32/subx-name - 8839 1/imm32/rm32-is-first-inout - 8840 2/imm32/r32-is-second-inout - 8841 0/imm32/no-imm32 - 8842 0/imm32/no-disp32 - 8843 0/imm32/output-is-write-only - 8844 _Primitive-compare-reg-with-mem/imm32/next - 8845 _Primitive-compare-reg-with-mem: - 8846 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 - 8847 "compare"/imm32/name - 8848 Two-args-int-reg-int-stack/imm32/inouts - 8849 0/imm32/outputs - 8850 "3b/compare<-"/imm32/subx-name - 8851 2/imm32/rm32-is-second-inout - 8852 1/imm32/r32-is-first-inout - 8853 0/imm32/no-imm32 - 8854 0/imm32/no-disp32 - 8855 0/imm32/output-is-write-only - 8856 _Primitive-compare-eax-with-literal/imm32/next - 8857 _Primitive-compare-eax-with-literal: - 8858 # compare var1/eax n => 3d/compare-eax-with n/imm32 - 8859 "compare"/imm32/name - 8860 Two-args-int-eax-int-literal/imm32/inouts - 8861 0/imm32/outputs - 8862 "3d/compare-eax-with"/imm32/subx-name - 8863 0/imm32/no-rm32 - 8864 0/imm32/no-r32 - 8865 2/imm32/imm32-is-second-inout - 8866 0/imm32/no-disp32 - 8867 0/imm32/output-is-write-only - 8868 _Primitive-compare-reg-with-literal/imm32/next - 8869 _Primitive-compare-reg-with-literal: - 8870 # compare var1/reg n => 81 7/subop/compare %reg n/imm32 - 8871 "compare"/imm32/name - 8872 Int-var-in-register-and-literal/imm32/inouts - 8873 0/imm32/outputs - 8874 "81 7/subop/compare"/imm32/subx-name - 8875 1/imm32/rm32-is-first-inout - 8876 0/imm32/no-r32 - 8877 2/imm32/imm32-is-second-inout - 8878 0/imm32/no-disp32 - 8879 0/imm32/output-is-write-only - 8880 _Primitive-compare-mem-with-literal/imm32/next - 8881 _Primitive-compare-mem-with-literal: - 8882 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 - 8883 "compare"/imm32/name - 8884 Int-var-and-literal/imm32/inouts - 8885 0/imm32/outputs - 8886 "81 7/subop/compare"/imm32/subx-name - 8887 1/imm32/rm32-is-first-inout - 8888 0/imm32/no-r32 - 8889 2/imm32/imm32-is-second-inout - 8890 0/imm32/no-disp32 - 8891 0/imm32/output-is-write-only - 8892 _Primitive-multiply-reg-by-mem/imm32/next - 8893 # - multiply - 8894 _Primitive-multiply-reg-by-mem: - 8895 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 - 8896 "multiply"/imm32/name - 8897 Single-int-var-in-mem/imm32/inouts - 8898 Single-int-var-in-some-register/imm32/outputs - 8899 "0f af/multiply"/imm32/subx-name - 8900 1/imm32/rm32-is-first-inout - 8901 3/imm32/r32-is-first-output - 8902 0/imm32/no-imm32 - 8903 0/imm32/no-disp32 - 8904 0/imm32/output-is-write-only - 8905 _Primitive-break-if-addr</imm32/next - 8906 # - branches - 8907 _Primitive-break-if-addr<: - 8908 "break-if-addr<"/imm32/name - 8909 0/imm32/inouts - 8910 0/imm32/outputs - 8911 "0f 82/jump-if-addr< break/disp32"/imm32/subx-name - 8912 0/imm32/no-rm32 - 8913 0/imm32/no-r32 - 8914 0/imm32/no-imm32 - 8915 0/imm32/no-disp32 - 8916 0/imm32/no-output - 8917 _Primitive-break-if-addr>=/imm32/next - 8918 _Primitive-break-if-addr>=: - 8919 "break-if-addr>="/imm32/name - 8920 0/imm32/inouts - 8921 0/imm32/outputs - 8922 "0f 83/jump-if-addr>= break/disp32"/imm32/subx-name - 8923 0/imm32/no-rm32 - 8924 0/imm32/no-r32 - 8925 0/imm32/no-imm32 - 8926 0/imm32/no-disp32 - 8927 0/imm32/no-output - 8928 _Primitive-break-if-=/imm32/next - 8929 _Primitive-break-if-=: - 8930 "break-if-="/imm32/name - 8931 0/imm32/inouts - 8932 0/imm32/outputs - 8933 "0f 84/jump-if-= break/disp32"/imm32/subx-name - 8934 0/imm32/no-rm32 - 8935 0/imm32/no-r32 - 8936 0/imm32/no-imm32 - 8937 0/imm32/no-disp32 - 8938 0/imm32/no-output - 8939 _Primitive-break-if-!=/imm32/next - 8940 _Primitive-break-if-!=: - 8941 "break-if-!="/imm32/name - 8942 0/imm32/inouts - 8943 0/imm32/outputs - 8944 "0f 85/jump-if-!= break/disp32"/imm32/subx-name - 8945 0/imm32/no-rm32 - 8946 0/imm32/no-r32 - 8947 0/imm32/no-imm32 - 8948 0/imm32/no-disp32 - 8949 0/imm32/no-output - 8950 _Primitive-break-if-addr<=/imm32/next - 8951 _Primitive-break-if-addr<=: - 8952 "break-if-addr<="/imm32/name - 8953 0/imm32/inouts - 8954 0/imm32/outputs - 8955 "0f 86/jump-if-addr<= break/disp32"/imm32/subx-name - 8956 0/imm32/no-rm32 - 8957 0/imm32/no-r32 - 8958 0/imm32/no-imm32 - 8959 0/imm32/no-disp32 - 8960 0/imm32/no-output - 8961 _Primitive-break-if-addr>/imm32/next - 8962 _Primitive-break-if-addr>: - 8963 "break-if-addr>"/imm32/name - 8964 0/imm32/inouts - 8965 0/imm32/outputs - 8966 "0f 87/jump-if-addr> break/disp32"/imm32/subx-name - 8967 0/imm32/no-rm32 - 8968 0/imm32/no-r32 - 8969 0/imm32/no-imm32 - 8970 0/imm32/no-disp32 - 8971 0/imm32/no-output - 8972 _Primitive-break-if-</imm32/next - 8973 _Primitive-break-if-<: - 8974 "break-if-<"/imm32/name - 8975 0/imm32/inouts - 8976 0/imm32/outputs - 8977 "0f 8c/jump-if-< break/disp32"/imm32/subx-name - 8978 0/imm32/no-rm32 - 8979 0/imm32/no-r32 - 8980 0/imm32/no-imm32 - 8981 0/imm32/no-disp32 - 8982 0/imm32/no-output - 8983 _Primitive-break-if->=/imm32/next - 8984 _Primitive-break-if->=: - 8985 "break-if->="/imm32/name - 8986 0/imm32/inouts - 8987 0/imm32/outputs - 8988 "0f 8d/jump-if->= break/disp32"/imm32/subx-name - 8989 0/imm32/no-rm32 - 8990 0/imm32/no-r32 - 8991 0/imm32/no-imm32 - 8992 0/imm32/no-disp32 - 8993 0/imm32/no-output - 8994 _Primitive-break-if-<=/imm32/next - 8995 _Primitive-break-if-<=: - 8996 "break-if-<="/imm32/name - 8997 0/imm32/inouts - 8998 0/imm32/outputs - 8999 "0f 8e/jump-if-<= break/disp32"/imm32/subx-name - 9000 0/imm32/no-rm32 - 9001 0/imm32/no-r32 - 9002 0/imm32/no-imm32 - 9003 0/imm32/no-disp32 - 9004 0/imm32/no-output - 9005 _Primitive-break-if->/imm32/next - 9006 _Primitive-break-if->: - 9007 "break-if->"/imm32/name - 9008 0/imm32/inouts - 9009 0/imm32/outputs - 9010 "0f 8f/jump-if-> break/disp32"/imm32/subx-name - 9011 0/imm32/no-rm32 - 9012 0/imm32/no-r32 - 9013 0/imm32/no-imm32 - 9014 0/imm32/no-disp32 - 9015 0/imm32/no-output - 9016 _Primitive-break/imm32/next - 9017 _Primitive-break: - 9018 "break"/imm32/name - 9019 0/imm32/inouts - 9020 0/imm32/outputs - 9021 "e9/jump break/disp32"/imm32/subx-name - 9022 0/imm32/no-rm32 - 9023 0/imm32/no-r32 - 9024 0/imm32/no-imm32 - 9025 0/imm32/no-disp32 - 9026 0/imm32/no-output - 9027 _Primitive-loop-if-addr</imm32/next - 9028 _Primitive-loop-if-addr<: - 9029 "loop-if-addr<"/imm32/name - 9030 0/imm32/inouts - 9031 0/imm32/outputs - 9032 "0f 82/jump-if-addr< loop/disp32"/imm32/subx-name - 9033 0/imm32/no-rm32 - 9034 0/imm32/no-r32 - 9035 0/imm32/no-imm32 - 9036 0/imm32/no-disp32 - 9037 0/imm32/no-output - 9038 _Primitive-loop-if-addr>=/imm32/next - 9039 _Primitive-loop-if-addr>=: - 9040 "loop-if-addr>="/imm32/name - 9041 0/imm32/inouts - 9042 0/imm32/outputs - 9043 "0f 83/jump-if-addr>= loop/disp32"/imm32/subx-name - 9044 0/imm32/no-rm32 - 9045 0/imm32/no-r32 - 9046 0/imm32/no-imm32 - 9047 0/imm32/no-disp32 - 9048 0/imm32/no-output - 9049 _Primitive-loop-if-=/imm32/next - 9050 _Primitive-loop-if-=: - 9051 "loop-if-="/imm32/name - 9052 0/imm32/inouts - 9053 0/imm32/outputs - 9054 "0f 84/jump-if-= loop/disp32"/imm32/subx-name - 9055 0/imm32/no-rm32 - 9056 0/imm32/no-r32 - 9057 0/imm32/no-imm32 - 9058 0/imm32/no-disp32 - 9059 0/imm32/no-output - 9060 _Primitive-loop-if-!=/imm32/next - 9061 _Primitive-loop-if-!=: - 9062 "loop-if-!="/imm32/name - 9063 0/imm32/inouts - 9064 0/imm32/outputs - 9065 "0f 85/jump-if-!= loop/disp32"/imm32/subx-name - 9066 0/imm32/no-rm32 - 9067 0/imm32/no-r32 - 9068 0/imm32/no-imm32 - 9069 0/imm32/no-disp32 - 9070 0/imm32/no-output - 9071 _Primitive-loop-if-addr<=/imm32/next - 9072 _Primitive-loop-if-addr<=: - 9073 "loop-if-addr<="/imm32/name - 9074 0/imm32/inouts - 9075 0/imm32/outputs - 9076 "0f 86/jump-if-addr<= loop/disp32"/imm32/subx-name - 9077 0/imm32/no-rm32 - 9078 0/imm32/no-r32 - 9079 0/imm32/no-imm32 - 9080 0/imm32/no-disp32 - 9081 0/imm32/no-output - 9082 _Primitive-loop-if-addr>/imm32/next - 9083 _Primitive-loop-if-addr>: - 9084 "loop-if-addr>"/imm32/name - 9085 0/imm32/inouts - 9086 0/imm32/outputs - 9087 "0f 87/jump-if-addr> loop/disp32"/imm32/subx-name - 9088 0/imm32/no-rm32 - 9089 0/imm32/no-r32 - 9090 0/imm32/no-imm32 - 9091 0/imm32/no-disp32 - 9092 0/imm32/no-output - 9093 _Primitive-loop-if-</imm32/next - 9094 _Primitive-loop-if-<: - 9095 "loop-if-<"/imm32/name - 9096 0/imm32/inouts - 9097 0/imm32/outputs - 9098 "0f 8c/jump-if-< loop/disp32"/imm32/subx-name - 9099 0/imm32/no-rm32 - 9100 0/imm32/no-r32 - 9101 0/imm32/no-imm32 - 9102 0/imm32/no-disp32 - 9103 0/imm32/no-output - 9104 _Primitive-loop-if->=/imm32/next - 9105 _Primitive-loop-if->=: - 9106 "loop-if->="/imm32/name - 9107 0/imm32/inouts - 9108 0/imm32/outputs - 9109 "0f 8d/jump-if->= loop/disp32"/imm32/subx-name - 9110 0/imm32/no-rm32 - 9111 0/imm32/no-r32 - 9112 0/imm32/no-imm32 - 9113 0/imm32/no-disp32 - 9114 0/imm32/no-output - 9115 _Primitive-loop-if-<=/imm32/next - 9116 _Primitive-loop-if-<=: - 9117 "loop-if-<="/imm32/name - 9118 0/imm32/inouts - 9119 0/imm32/outputs - 9120 "0f 8e/jump-if-<= loop/disp32"/imm32/subx-name - 9121 0/imm32/no-rm32 - 9122 0/imm32/no-r32 - 9123 0/imm32/no-imm32 - 9124 0/imm32/no-disp32 - 9125 0/imm32/no-output - 9126 _Primitive-loop-if->/imm32/next - 9127 _Primitive-loop-if->: - 9128 "loop-if->"/imm32/name - 9129 0/imm32/inouts - 9130 0/imm32/outputs - 9131 "0f 8f/jump-if-> loop/disp32"/imm32/subx-name - 9132 0/imm32/no-rm32 - 9133 0/imm32/no-r32 - 9134 0/imm32/no-imm32 - 9135 0/imm32/no-disp32 - 9136 0/imm32/no-output - 9137 _Primitive-loop/imm32/next # we probably don't need an unconditional break - 9138 _Primitive-loop: - 9139 "loop"/imm32/name - 9140 0/imm32/inouts - 9141 0/imm32/outputs - 9142 "e9/jump loop/disp32"/imm32/subx-name - 9143 0/imm32/no-rm32 - 9144 0/imm32/no-r32 - 9145 0/imm32/no-imm32 - 9146 0/imm32/no-disp32 - 9147 0/imm32/no-output - 9148 _Primitive-break-if-addr<-named/imm32/next - 9149 # - branches to named blocks - 9150 _Primitive-break-if-addr<-named: - 9151 "break-if-addr<"/imm32/name - 9152 Single-lit-var/imm32/inouts - 9153 0/imm32/outputs - 9154 "0f 82/jump-if-addr<"/imm32/subx-name - 9155 0/imm32/no-rm32 - 9156 0/imm32/no-r32 - 9157 0/imm32/no-imm32 - 9158 1/imm32/disp32-is-first-inout - 9159 0/imm32/no-output - 9160 _Primitive-break-if-addr>=-named/imm32/next - 9161 _Primitive-break-if-addr>=-named: - 9162 "break-if-addr>="/imm32/name - 9163 Single-lit-var/imm32/inouts - 9164 0/imm32/outputs - 9165 "0f 83/jump-if-addr>="/imm32/subx-name - 9166 0/imm32/no-rm32 - 9167 0/imm32/no-r32 - 9168 0/imm32/no-imm32 - 9169 1/imm32/disp32-is-first-inout - 9170 0/imm32/no-output - 9171 _Primitive-break-if-=-named/imm32/next - 9172 _Primitive-break-if-=-named: - 9173 "break-if-="/imm32/name - 9174 Single-lit-var/imm32/inouts - 9175 0/imm32/outputs - 9176 "0f 84/jump-if-="/imm32/subx-name - 9177 0/imm32/no-rm32 - 9178 0/imm32/no-r32 - 9179 0/imm32/no-imm32 - 9180 1/imm32/disp32-is-first-inout - 9181 0/imm32/no-output - 9182 _Primitive-break-if-!=-named/imm32/next - 9183 _Primitive-break-if-!=-named: - 9184 "break-if-!="/imm32/name - 9185 Single-lit-var/imm32/inouts - 9186 0/imm32/outputs - 9187 "0f 85/jump-if-!="/imm32/subx-name - 9188 0/imm32/no-rm32 - 9189 0/imm32/no-r32 - 9190 0/imm32/no-imm32 - 9191 1/imm32/disp32-is-first-inout - 9192 0/imm32/no-output - 9193 _Primitive-break-if-addr<=-named/imm32/next - 9194 _Primitive-break-if-addr<=-named: - 9195 "break-if-addr<="/imm32/name - 9196 Single-lit-var/imm32/inouts - 9197 0/imm32/outputs - 9198 "0f 86/jump-if-addr<="/imm32/subx-name - 9199 0/imm32/no-rm32 - 9200 0/imm32/no-r32 - 9201 0/imm32/no-imm32 - 9202 1/imm32/disp32-is-first-inout - 9203 0/imm32/no-output - 9204 _Primitive-break-if-addr>-named/imm32/next - 9205 _Primitive-break-if-addr>-named: - 9206 "break-if-addr>"/imm32/name - 9207 Single-lit-var/imm32/inouts - 9208 0/imm32/outputs - 9209 "0f 87/jump-if-addr>"/imm32/subx-name - 9210 0/imm32/no-rm32 - 9211 0/imm32/no-r32 - 9212 0/imm32/no-imm32 - 9213 1/imm32/disp32-is-first-inout - 9214 0/imm32/no-output - 9215 _Primitive-break-if-<-named/imm32/next - 9216 _Primitive-break-if-<-named: - 9217 "break-if-<"/imm32/name - 9218 Single-lit-var/imm32/inouts - 9219 0/imm32/outputs - 9220 "0f 8c/jump-if-<"/imm32/subx-name - 9221 0/imm32/no-rm32 - 9222 0/imm32/no-r32 - 9223 0/imm32/no-imm32 - 9224 1/imm32/disp32-is-first-inout - 9225 0/imm32/no-output - 9226 _Primitive-break-if->=-named/imm32/next - 9227 _Primitive-break-if->=-named: - 9228 "break-if->="/imm32/name - 9229 Single-lit-var/imm32/inouts - 9230 0/imm32/outputs - 9231 "0f 8d/jump-if->="/imm32/subx-name - 9232 0/imm32/no-rm32 - 9233 0/imm32/no-r32 - 9234 0/imm32/no-imm32 - 9235 1/imm32/disp32-is-first-inout - 9236 0/imm32/no-output - 9237 _Primitive-break-if-<=-named/imm32/next - 9238 _Primitive-break-if-<=-named: - 9239 "break-if-<="/imm32/name - 9240 Single-lit-var/imm32/inouts - 9241 0/imm32/outputs - 9242 "0f 8e/jump-if-<="/imm32/subx-name - 9243 0/imm32/no-rm32 - 9244 0/imm32/no-r32 - 9245 0/imm32/no-imm32 - 9246 1/imm32/disp32-is-first-inout - 9247 0/imm32/no-output - 9248 _Primitive-break-if->-named/imm32/next - 9249 _Primitive-break-if->-named: - 9250 "break-if->"/imm32/name - 9251 Single-lit-var/imm32/inouts - 9252 0/imm32/outputs - 9253 "0f 8f/jump-if->"/imm32/subx-name - 9254 0/imm32/no-rm32 - 9255 0/imm32/no-r32 - 9256 0/imm32/no-imm32 - 9257 1/imm32/disp32-is-first-inout - 9258 0/imm32/no-output - 9259 _Primitive-break-named/imm32/next - 9260 _Primitive-break-named: - 9261 "break"/imm32/name - 9262 Single-lit-var/imm32/inouts - 9263 0/imm32/outputs - 9264 "e9/jump"/imm32/subx-name - 9265 0/imm32/no-rm32 - 9266 0/imm32/no-r32 - 9267 0/imm32/no-imm32 - 9268 1/imm32/disp32-is-first-inout - 9269 0/imm32/no-output - 9270 _Primitive-loop-if-addr<-named/imm32/next - 9271 _Primitive-loop-if-addr<-named: - 9272 "loop-if-addr<"/imm32/name - 9273 Single-lit-var/imm32/inouts - 9274 0/imm32/outputs - 9275 "0f 82/jump-if-addr<"/imm32/subx-name - 9276 0/imm32/no-rm32 - 9277 0/imm32/no-r32 - 9278 0/imm32/no-imm32 - 9279 1/imm32/disp32-is-first-inout - 9280 0/imm32/no-output - 9281 _Primitive-loop-if-addr>=-named/imm32/next - 9282 _Primitive-loop-if-addr>=-named: - 9283 "loop-if-addr>="/imm32/name - 9284 Single-lit-var/imm32/inouts - 9285 0/imm32/outputs - 9286 "0f 83/jump-if-addr>="/imm32/subx-name - 9287 0/imm32/no-rm32 - 9288 0/imm32/no-r32 - 9289 0/imm32/no-imm32 - 9290 1/imm32/disp32-is-first-inout - 9291 0/imm32/no-output - 9292 _Primitive-loop-if-=-named/imm32/next - 9293 _Primitive-loop-if-=-named: - 9294 "loop-if-="/imm32/name - 9295 Single-lit-var/imm32/inouts - 9296 0/imm32/outputs - 9297 "0f 84/jump-if-="/imm32/subx-name - 9298 0/imm32/no-rm32 - 9299 0/imm32/no-r32 - 9300 0/imm32/no-imm32 - 9301 1/imm32/disp32-is-first-inout - 9302 0/imm32/no-output - 9303 _Primitive-loop-if-!=-named/imm32/next - 9304 _Primitive-loop-if-!=-named: - 9305 "loop-if-!="/imm32/name - 9306 Single-lit-var/imm32/inouts - 9307 0/imm32/outputs - 9308 "0f 85/jump-if-!="/imm32/subx-name - 9309 0/imm32/no-rm32 - 9310 0/imm32/no-r32 - 9311 0/imm32/no-imm32 - 9312 1/imm32/disp32-is-first-inout - 9313 0/imm32/no-output - 9314 _Primitive-loop-if-addr<=-named/imm32/next - 9315 _Primitive-loop-if-addr<=-named: - 9316 "loop-if-addr<="/imm32/name - 9317 Single-lit-var/imm32/inouts - 9318 0/imm32/outputs - 9319 "0f 86/jump-if-addr<="/imm32/subx-name - 9320 0/imm32/no-rm32 - 9321 0/imm32/no-r32 - 9322 0/imm32/no-imm32 - 9323 1/imm32/disp32-is-first-inout - 9324 0/imm32/no-output - 9325 _Primitive-loop-if-addr>-named/imm32/next - 9326 _Primitive-loop-if-addr>-named: - 9327 "loop-if-addr>"/imm32/name - 9328 Single-lit-var/imm32/inouts - 9329 0/imm32/outputs - 9330 "0f 87/jump-if-addr>"/imm32/subx-name - 9331 0/imm32/no-rm32 - 9332 0/imm32/no-r32 - 9333 0/imm32/no-imm32 - 9334 1/imm32/disp32-is-first-inout - 9335 0/imm32/no-output - 9336 _Primitive-loop-if-<-named/imm32/next - 9337 _Primitive-loop-if-<-named: - 9338 "loop-if-<"/imm32/name - 9339 Single-lit-var/imm32/inouts - 9340 0/imm32/outputs - 9341 "0f 8c/jump-if-<"/imm32/subx-name - 9342 0/imm32/no-rm32 - 9343 0/imm32/no-r32 - 9344 0/imm32/no-imm32 - 9345 1/imm32/disp32-is-first-inout - 9346 0/imm32/no-output - 9347 _Primitive-loop-if->=-named/imm32/next - 9348 _Primitive-loop-if->=-named: - 9349 "loop-if->="/imm32/name - 9350 Single-lit-var/imm32/inouts - 9351 0/imm32/outputs - 9352 "0f 8d/jump-if->="/imm32/subx-name - 9353 0/imm32/no-rm32 - 9354 0/imm32/no-r32 - 9355 0/imm32/no-imm32 - 9356 1/imm32/disp32-is-first-inout - 9357 0/imm32/no-output - 9358 _Primitive-loop-if-<=-named/imm32/next - 9359 _Primitive-loop-if-<=-named: - 9360 "loop-if-<="/imm32/name - 9361 Single-lit-var/imm32/inouts - 9362 0/imm32/outputs - 9363 "0f 8e/jump-if-<="/imm32/subx-name - 9364 0/imm32/no-rm32 - 9365 0/imm32/no-r32 - 9366 0/imm32/no-imm32 - 9367 1/imm32/disp32-is-first-inout - 9368 0/imm32/no-output - 9369 _Primitive-loop-if->-named/imm32/next - 9370 _Primitive-loop-if->-named: - 9371 "loop-if->"/imm32/name - 9372 Single-lit-var/imm32/inouts - 9373 0/imm32/outputs - 9374 "0f 8f/jump-if->"/imm32/subx-name - 9375 0/imm32/no-rm32 - 9376 0/imm32/no-r32 - 9377 0/imm32/no-imm32 - 9378 1/imm32/disp32-is-first-inout - 9379 0/imm32/no-output - 9380 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break - 9381 _Primitive-loop-named: - 9382 "loop"/imm32/name - 9383 Single-lit-var/imm32/inouts - 9384 0/imm32/outputs - 9385 "e9/jump"/imm32/subx-name - 9386 0/imm32/no-rm32 - 9387 0/imm32/no-r32 - 9388 0/imm32/no-imm32 - 9389 1/imm32/disp32-is-first-inout - 9390 0/imm32/no-output - 9391 0/imm32/next - 9392 - 9393 Single-int-var-in-mem: - 9394 Int-var-in-mem/imm32 - 9395 0/imm32/next - 9396 - 9397 Int-var-in-mem: - 9398 "arg1"/imm32/name - 9399 Type-int/imm32 - 9400 1/imm32/some-block-depth - 9401 1/imm32/some-stack-offset - 9402 0/imm32/no-register - 9403 - 9404 Two-args-int-stack-int-reg: - 9405 Int-var-in-mem/imm32 - 9406 Single-int-var-in-some-register/imm32/next - 9407 - 9408 Two-args-int-reg-int-stack: - 9409 Int-var-in-some-register/imm32 - 9410 Single-int-var-in-mem/imm32/next - 9411 - 9412 Two-args-int-eax-int-literal: - 9413 Int-var-in-eax/imm32 - 9414 Single-lit-var/imm32/next - 9415 - 9416 Int-var-and-literal: - 9417 Int-var-in-mem/imm32 - 9418 Single-lit-var/imm32/next - 9419 - 9420 Int-var-in-register-and-literal: - 9421 Int-var-in-some-register/imm32 - 9422 Single-lit-var/imm32/next - 9423 - 9424 Single-int-var-in-some-register: - 9425 Int-var-in-some-register/imm32 - 9426 0/imm32/next - 9427 - 9428 Single-addr-var-in-some-register: - 9429 Addr-var-in-some-register/imm32 - 9430 0/imm32/next - 9431 - 9432 Int-var-in-some-register: - 9433 "arg1"/imm32/name - 9434 Type-int/imm32 - 9435 1/imm32/some-block-depth - 9436 0/imm32/no-stack-offset - 9437 Any-register/imm32 - 9438 - 9439 Addr-var-in-some-register: - 9440 "arg1"/imm32/name - 9441 Type-addr/imm32 - 9442 1/imm32/some-block-depth - 9443 0/imm32/no-stack-offset - 9444 Any-register/imm32 - 9445 - 9446 Single-int-var-in-eax: - 9447 Int-var-in-eax/imm32 - 9448 0/imm32/next - 9449 - 9450 Int-var-in-eax: - 9451 "arg1"/imm32/name - 9452 Type-int/imm32 - 9453 1/imm32/some-block-depth - 9454 0/imm32/no-stack-offset - 9455 "eax"/imm32/register - 9456 - 9457 Single-int-var-in-ecx: - 9458 Int-var-in-ecx/imm32 - 9459 0/imm32/next - 9460 - 9461 Int-var-in-ecx: - 9462 "arg1"/imm32/name - 9463 Type-int/imm32 - 9464 1/imm32/some-block-depth - 9465 0/imm32/no-stack-offset - 9466 "ecx"/imm32/register - 9467 - 9468 Single-int-var-in-edx: - 9469 Int-var-in-edx/imm32 - 9470 0/imm32/next - 9471 - 9472 Int-var-in-edx: - 9473 "arg1"/imm32/name - 9474 Type-int/imm32 - 9475 1/imm32/some-block-depth - 9476 0/imm32/no-stack-offset - 9477 "edx"/imm32/register - 9478 - 9479 Single-int-var-in-ebx: - 9480 Int-var-in-ebx/imm32 - 9481 0/imm32/next - 9482 - 9483 Int-var-in-ebx: - 9484 "arg1"/imm32/name - 9485 Type-int/imm32 - 9486 1/imm32/some-block-depth - 9487 0/imm32/no-stack-offset - 9488 "ebx"/imm32/register - 9489 - 9490 Single-int-var-in-esi: - 9491 Int-var-in-esi/imm32 - 9492 0/imm32/next - 9493 - 9494 Int-var-in-esi: - 9495 "arg1"/imm32/name - 9496 Type-int/imm32 - 9497 1/imm32/some-block-depth - 9498 0/imm32/no-stack-offset - 9499 "esi"/imm32/register - 9500 - 9501 Single-int-var-in-edi: - 9502 Int-var-in-edi/imm32 - 9503 0/imm32/next - 9504 - 9505 Int-var-in-edi: - 9506 "arg1"/imm32/name - 9507 Type-int/imm32 - 9508 1/imm32/some-block-depth - 9509 0/imm32/no-stack-offset - 9510 "edi"/imm32/register - 9511 - 9512 Single-lit-var: - 9513 Lit-var/imm32 - 9514 0/imm32/next - 9515 - 9516 Lit-var: - 9517 "literal"/imm32/name - 9518 Type-literal/imm32 - 9519 1/imm32/some-block-depth - 9520 0/imm32/no-stack-offset - 9521 0/imm32/no-register - 9522 - 9523 Type-int: - 9524 1/imm32/left/int - 9525 0/imm32/right/null - 9526 - 9527 Type-literal: - 9528 0/imm32/left/literal - 9529 0/imm32/right/null - 9530 - 9531 Type-addr: - 9532 2/imm32/left/addr - 9533 0/imm32/right/null - 9534 - 9535 == code - 9536 emit-subx-primitive: # out: (addr buffered-file), stmt: (handle stmt), primitive: (handle function) - 9537 # . prologue - 9538 55/push-ebp - 9539 89/<- %ebp 4/r32/esp - 9540 # . save registers - 9541 50/push-eax - 9542 51/push-ecx - 9543 # ecx = primitive - 9544 8b/-> *(ebp+0x10) 1/r32/ecx - 9545 # emit primitive name - 9546 (emit-indent *(ebp+8) *Curr-block-depth) - 9547 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name - 9548 # emit rm32 if necessary - 9549 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt - 9550 # emit r32 if necessary - 9551 (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt - 9552 # emit imm32 if necessary - 9553 (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt - 9554 # emit disp32 if necessary - 9555 (emit-subx-disp32 *(ebp+8) *(ecx+0x1c) *(ebp+0xc)) # out, Primitive-subx-disp32, stmt - 9556 (write-buffered *(ebp+8) Newline) - 9557 $emit-subx-primitive:end: - 9558 # . restore registers - 9559 59/pop-to-ecx - 9560 58/pop-to-eax - 9561 # . epilogue - 9562 89/<- %esp 5/r32/ebp - 9563 5d/pop-to-ebp - 9564 c3/return - 9565 - 9566 emit-subx-rm32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) - 9567 # . prologue - 9568 55/push-ebp - 9569 89/<- %ebp 4/r32/esp - 9570 # . save registers - 9571 50/push-eax - 9572 # if (l == 0) return - 9573 81 7/subop/compare *(ebp+0xc) 0/imm32 - 9574 74/jump-if-= $emit-subx-rm32:end/disp8 - 9575 # var v/eax: (handle var) - 9576 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax - 9577 (emit-subx-var-as-rm32 *(ebp+8) %eax) - 9578 $emit-subx-rm32:end: - 9579 # . restore registers - 9580 58/pop-to-eax - 9581 # . epilogue - 9582 89/<- %esp 5/r32/ebp - 9583 5d/pop-to-ebp - 9584 c3/return - 9585 - 9586 get-stmt-operand-from-arg-location: # stmt: (handle stmt), l: arg-location -> var/eax: (handle stmt-var) - 9587 # . prologue - 9588 55/push-ebp - 9589 89/<- %ebp 4/r32/esp - 9590 # . save registers - 9591 51/push-ecx - 9592 # eax = l - 9593 8b/-> *(ebp+0xc) 0/r32/eax - 9594 # ecx = stmt - 9595 8b/-> *(ebp+8) 1/r32/ecx - 9596 # if (l == 1) return stmt->inouts - 9597 { - 9598 3d/compare-eax-and 1/imm32 - 9599 75/jump-if-!= break/disp8 - 9600 $get-stmt-operand-from-arg-location:1: - 9601 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts - 9602 eb/jump $get-stmt-operand-from-arg-location:end/disp8 - 9603 } - 9604 # if (l == 2) return stmt->inouts->next - 9605 { - 9606 3d/compare-eax-and 2/imm32 - 9607 75/jump-if-!= break/disp8 - 9608 $get-stmt-operand-from-arg-location:2: - 9609 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts - 9610 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next - 9611 eb/jump $get-stmt-operand-from-arg-location:end/disp8 - 9612 } - 9613 # if (l == 3) return stmt->outputs - 9614 { - 9615 3d/compare-eax-and 3/imm32 - 9616 75/jump-if-!= break/disp8 - 9617 $get-stmt-operand-from-arg-location:3: - 9618 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs - 9619 eb/jump $get-stmt-operand-from-arg-location:end/disp8 - 9620 } - 9621 # abort - 9622 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 - 9623 $get-stmt-operand-from-arg-location:end: - 9624 # . restore registers - 9625 59/pop-to-ecx - 9626 # . epilogue - 9627 89/<- %esp 5/r32/ebp - 9628 5d/pop-to-ebp - 9629 c3/return - 9630 - 9631 $get-stmt-operand-from-arg-location:abort: - 9632 # error("invalid arg-location " eax) - 9633 (write-buffered Stderr "invalid arg-location ") - 9634 (print-int32-buffered Stderr %eax) - 9635 (write-buffered Stderr Newline) - 9636 (flush Stderr) - 9637 # . syscall(exit, 1) - 9638 bb/copy-to-ebx 1/imm32 - 9639 b8/copy-to-eax 1/imm32/exit - 9640 cd/syscall 0x80/imm8 - 9641 # never gets here + 7974 8b/-> *(ebp+0xc) 1/r32/ecx + 7975 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs + 7976 8b/-> *eax 0/r32/eax # Stmt-var-value + 7977 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax + 7978 (print-int32-buffered *(ebp+8) *eax) + 7979 (write-buffered *(ebp+8) "/r32\n") + 7980 $translate-mu-index-stmt-with-array-in-register:end: + 7981 # . restore registers + 7982 5b/pop-to-ebx + 7983 5a/pop-to-edx + 7984 59/pop-to-ecx + 7985 58/pop-to-eax + 7986 # . epilogue + 7987 89/<- %esp 5/r32/ebp + 7988 5d/pop-to-ebp + 7989 c3/return + 7990 + 7991 translate-mu-index-stmt-with-array-on-stack: # out: (address buffered-file), stmt: (handle stmt) + 7992 # . prologue + 7993 55/push-ebp + 7994 89/<- %ebp 4/r32/esp + 7995 # . save registers + 7996 50/push-eax + 7997 51/push-ecx + 7998 52/push-edx + 7999 53/push-ebx + 8000 # + 8001 (emit-indent *(ebp+8) *Curr-block-depth) + 8002 (write-buffered *(ebp+8) "8d/copy-address *(ebp + ") + 8003 # var curr/eax = stmt->inouts + 8004 8b/-> *(ebp+0xc) 0/r32/eax + 8005 # var base/ecx: (handle var) = stmt->inouts[0] + 8006 8b/-> *(eax+8) 0/r32/eax # Stmt1-inouts + 8007 8b/-> *eax 1/r32/ecx # Stmt-var-value + 8008 # curr = curr->next + 8009 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next + 8010 # var index/edx: (handle var) = stmt->inouts[1] + 8011 8b/-> *eax 2/r32/edx # Stmt-var-value + 8012 # if index->register + 8013 81 7/subop/compare *(edx+0x10) 0/imm32 # Var-register + 8014 { + 8015 0f 84/jump-if-= break/disp32 + 8016 $translate-mu-index-stmt-with-array-on-stack:emit-register-index: + 8017 # if index is an int + 8018 (is-simple-mu-type? *(edx+4) 1) # Var-type, int => eax + 8019 3d/compare-eax-and 0/imm32/false + 8020 { + 8021 0f 84/jump-if-= break/disp32 + 8022 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index: + 8023 # print index->register "<<" log2(size-of(element-type(base))) " + " base->offset+4 + 8024 # . inouts[1]->register "<<" + 8025 (write-buffered *(ebp+8) *(edx+0x10)) # Var-register + 8026 (write-buffered *(ebp+8) "<<") + 8027 # . log2(size-of(element(base))) + 8028 # TODO: ensure size is a power of 2 + 8029 (array-element-type-id %ecx) # => eax + 8030 (size-of-type-id %eax) # => eax + 8031 (num-shift-rights %eax) # => eax + 8032 (print-int32-buffered *(ebp+8) %eax) + 8033 # + 8034 (write-buffered *(ebp+8) " + ") + 8035 # + 8036 8b/-> *(ecx+0xc) 0/r32/eax # Var-offset + 8037 05/add-to-eax 4/imm32 + 8038 (print-int32-buffered *(ebp+8) %eax) + 8039 e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32 + 8040 } + 8041 # if index->type is any other atom, abort + 8042 8b/-> *(edx+4) 0/r32/eax # Var-type + 8043 81 7/subop/compare *eax 0/imm32/false # Tree-is-atom + 8044 0f 85/jump-if-!= $translate-mu-index-stmt-with-array:error2/disp32 + 8045 # if index has type (offset ...) + 8046 (is-simple-mu-type? *(eax+4) 7) # Tree-left, offset => eax + 8047 3d/compare-eax-and 0/imm32/false + 8048 { + 8049 0f 84/jump-if-= break/disp32 + 8050 # print index->register + 8051 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index: + 8052 (write-buffered *(ebp+8) *(edx+0x10)) # Var-register + 8053 } + 8054 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done: + 8055 (write-buffered *(ebp+8) ") ") + 8056 e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32 + 8057 } + 8058 # otherwise if index is a literal + 8059 (is-simple-mu-type? *(edx+4) 0) # Var-type => eax + 8060 3d/compare-eax-and 0/imm32/false + 8061 { + 8062 0f 84/jump-if-= break/disp32 + 8063 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index: + 8064 # var idx-value/edx: int = parse-hex-int(index->name) + 8065 (parse-hex-int *edx) # Var-name => eax + 8066 89/<- %ebx 0/r32/eax + 8067 # offset = idx-value * size-of(element-type(base->type)) + 8068 (array-element-type-id %ecx) # => eax + 8069 (size-of-type-id %eax) # => eax + 8070 f7 4/subop/multiply-into-eax %ebx # clobbers edx + 8071 # offset += base->offset + 8072 03/add *(ecx+0xc) 0/r32/eax # Var-offset + 8073 # offset += 4 for array size + 8074 05/add-to-eax 4/imm32 + 8075 # TODO: check edx for overflow + 8076 # print offset + 8077 (print-int32-buffered *(ebp+8) %eax) + 8078 (write-buffered *(ebp+8) ") ") + 8079 e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32 + 8080 } + 8081 # otherwise abort + 8082 e9/jump $translate-mu-index-stmt-with-array:error1/disp32 + 8083 $translate-mu-index-stmt-with-array-on-stack:emit-output: + 8084 # outputs[0] "/r32" + 8085 8b/-> *(ebp+0xc) 0/r32/eax + 8086 8b/-> *(eax+0xc) 0/r32/eax # Stmt1-outputs + 8087 8b/-> *eax 0/r32/eax # Stmt-var-value + 8088 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax + 8089 (print-int32-buffered *(ebp+8) *eax) + 8090 (write-buffered *(ebp+8) "/r32\n") + 8091 $translate-mu-index-stmt-with-array-on-stack:end: + 8092 # . restore registers + 8093 5b/pop-to-ebx + 8094 5a/pop-to-edx + 8095 59/pop-to-ecx + 8096 58/pop-to-eax + 8097 # . epilogue + 8098 89/<- %esp 5/r32/ebp + 8099 5d/pop-to-ebp + 8100 c3/return + 8101 + 8102 translate-mu-compute-index-stmt: # out: (address buffered-file), stmt: (handle stmt) + 8103 # . prologue + 8104 55/push-ebp + 8105 89/<- %ebp 4/r32/esp + 8106 # . save registers + 8107 50/push-eax + 8108 51/push-ecx + 8109 52/push-edx + 8110 53/push-ebx + 8111 # + 8112 (emit-indent *(ebp+8) *Curr-block-depth) + 8113 (write-buffered *(ebp+8) "69/multiply") + 8114 # ecx = stmt + 8115 8b/-> *(ebp+0xc) 1/r32/ecx + 8116 # var first-inout/edx: (handle stmt-var) = stmt->inouts[0] + 8117 8b/-> *(ecx+8) 2/r32/edx # Stmt1-inouts + 8118 $translate-mu-compute-index-stmt:emit-index: + 8119 (emit-subx-var-as-rm32 *(ebp+8) *(edx+4)) # Stmt-var-next + 8120 (write-buffered *(ebp+8) Space) + 8121 $translate-mu-compute-index-stmt:emit-elem-size: + 8122 # var base/ebx: (handle var) + 8123 8b/-> *edx 3/r32/ebx # Stmt-var-value + 8124 # print size-of(element(base->type)) + 8125 (array-element-type-id %ebx) # => eax + 8126 (size-of-type-id %eax) # => eax + 8127 (print-int32-buffered *(ebp+8) %eax) + 8128 (write-buffered *(ebp+8) "/imm32 ") + 8129 $translate-mu-compute-index-stmt:emit-output: + 8130 # outputs[0] "/r32" + 8131 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs + 8132 8b/-> *eax 0/r32/eax # Stmt-var-value + 8133 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax + 8134 (print-int32-buffered *(ebp+8) *eax) + 8135 (write-buffered *(ebp+8) "/r32\n") + 8136 $translate-mu-compute-index-stmt:end: + 8137 # . restore registers + 8138 5b/pop-to-ebx + 8139 5a/pop-to-edx + 8140 59/pop-to-ecx + 8141 58/pop-to-eax + 8142 # . epilogue + 8143 89/<- %esp 5/r32/ebp + 8144 5d/pop-to-ebp + 8145 c3/return + 8146 + 8147 translate-mu-get-stmt: # out: (address buffered-file), stmt: (handle stmt) + 8148 # . prologue + 8149 55/push-ebp + 8150 89/<- %ebp 4/r32/esp + 8151 # . save registers + 8152 50/push-eax + 8153 51/push-ecx + 8154 52/push-edx + 8155 # + 8156 (emit-indent *(ebp+8) *Curr-block-depth) + 8157 (write-buffered *(ebp+8) "8d/copy-address ") + 8158 # ecx = stmt + 8159 8b/-> *(ebp+0xc) 1/r32/ecx + 8160 # var offset/edx: int = get offset of stmt + 8161 (mu-get-offset %ecx) # => eax + 8162 89/<- %edx 0/r32/eax + 8163 # var base/eax: (handle var) = stmt->inouts[0] + 8164 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts + 8165 8b/-> *eax 0/r32/eax # Stmt-var-value + 8166 # if base is in a register + 8167 81 7/subop/compare *(eax+0x10) 0/imm32 + 8168 { + 8169 0f 84/jump-if-= break/disp32 + 8170 $translate-mu-get-stmt:emit-register-input: + 8171 # "*(" inouts[0]->register " + " offset ")" + 8172 (write-buffered *(ebp+8) "*(") + 8173 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register + 8174 (write-buffered *(ebp+8) " + ") + 8175 (print-int32-buffered *(ebp+8) %edx) + 8176 (write-buffered *(ebp+8) ") ") + 8177 e9/jump $translate-mu-get-stmt:emit-output/disp32 + 8178 } + 8179 # otherwise base is on the stack + 8180 { + 8181 $translate-mu-get-stmt:emit-stack-input: + 8182 # "*(ebp + " inouts[0]->offset + offset ")" + 8183 (write-buffered *(ebp+8) "*(ebp+") + 8184 03/add *(eax+0xc) 2/r32/edx # Var-offset + 8185 (print-int32-buffered *(ebp+8) %edx) + 8186 (write-buffered *(ebp+8) ") ") + 8187 eb/jump $translate-mu-get-stmt:emit-output/disp8 + 8188 } + 8189 $translate-mu-get-stmt:emit-output: + 8190 # outputs[0] "/r32" + 8191 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs + 8192 8b/-> *eax 0/r32/eax # Stmt-var-value + 8193 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax + 8194 (print-int32-buffered *(ebp+8) *eax) + 8195 (write-buffered *(ebp+8) "/r32\n") + 8196 $translate-mu-get-stmt:end: + 8197 # . restore registers + 8198 5a/pop-to-edx + 8199 59/pop-to-ecx + 8200 58/pop-to-eax + 8201 # . epilogue + 8202 89/<- %esp 5/r32/ebp + 8203 5d/pop-to-ebp + 8204 c3/return + 8205 + 8206 array-element-type-id: # v: (handle var) -> result/eax: type-id + 8207 # precondition: n is positive + 8208 # . prologue + 8209 55/push-ebp + 8210 89/<- %ebp 4/r32/esp + 8211 # + 8212 8b/-> *(ebp+8) 0/r32/eax + 8213 8b/-> *(eax+4) 0/r32/eax # Var-type + 8214 # TODO: ensure type->left is 'addr' + 8215 8b/-> *(eax+8) 0/r32/eax # Tree-right + 8216 # TODO: ensure that type->right is non-null + 8217 # TODO: ensure that type->right->left is 'array' + 8218 8b/-> *(eax+8) 0/r32/eax # Tree-right + 8219 # TODO: ensure that type->right->right is non-null + 8220 8b/-> *(eax+4) 0/r32/eax # Tree-left + 8221 8b/-> *(eax+4) 0/r32/eax # Tree-value + 8222 $array-element-type-id:end: + 8223 # . epilogue + 8224 89/<- %esp 5/r32/ebp + 8225 5d/pop-to-ebp + 8226 c3/return + 8227 + 8228 num-shift-rights: # n: int -> result/eax: int + 8229 # precondition: n is a positive power of 2 + 8230 # . prologue + 8231 55/push-ebp + 8232 89/<- %ebp 4/r32/esp + 8233 # . save registers + 8234 51/push-ecx + 8235 # var curr/ecx: int = n + 8236 8b/-> *(ebp+8) 1/r32/ecx + 8237 # result = 0 + 8238 b8/copy-to-eax 0/imm32 + 8239 { + 8240 # if (curr <= 1) break + 8241 81 7/subop/compare %ecx 1/imm32 + 8242 7e/jump-if-<= break/disp8 + 8243 40/increment-eax + 8244 c1/shift 5/subop/arithmetic-right %ecx 1/imm8 + 8245 eb/jump loop/disp8 + 8246 } + 8247 $num-shift-rights:end: + 8248 # . restore registers + 8249 59/pop-to-ecx + 8250 # . epilogue + 8251 89/<- %esp 5/r32/ebp + 8252 5d/pop-to-ebp + 8253 c3/return + 8254 + 8255 mu-get-offset: # stmt: (handle stmt) -> result/eax: int + 8256 # . prologue + 8257 55/push-ebp + 8258 89/<- %ebp 4/r32/esp + 8259 # var second-inout/eax: (handle stmt-var) = stmt->inouts->next + 8260 8b/-> *(ebp+8) 0/r32/eax + 8261 8b/-> *(eax+8) 0/r32/eax # Stmt1-inouts + 8262 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next + 8263 # var output-var/eax: (handle var) = second-inout->value + 8264 8b/-> *eax 0/r32/eax # Stmt-var-value + 8265 # return output-var->offset + 8266 8b/-> *(eax+0xc) 0/r32/eax # Var-offset + 8267 $emit-get-offset:end: + 8268 # . epilogue + 8269 89/<- %esp 5/r32/ebp + 8270 5d/pop-to-ebp + 8271 c3/return + 8272 + 8273 emit-subx-block: # out: (addr buffered-file), block: (handle block), vars: (addr stack (handle var)) + 8274 # . prologue + 8275 55/push-ebp + 8276 89/<- %ebp 4/r32/esp + 8277 # . save registers + 8278 50/push-eax + 8279 51/push-ecx + 8280 56/push-esi + 8281 # esi = block + 8282 8b/-> *(ebp+0xc) 6/r32/esi + 8283 # block->var->block-depth = *Curr-block-depth + 8284 8b/-> *(esi+8) 0/r32/eax # Block-var + 8285 8b/-> *Curr-block-depth 1/r32/ecx + 8286 89/<- *(eax+8) 1/r32/ecx # Var-block-depth + 8287 # var stmts/eax: (handle list stmt) = block->statements + 8288 8b/-> *(esi+4) 0/r32/eax # Block-stmts + 8289 # + 8290 { + 8291 $emit-subx-block:check-empty: + 8292 3d/compare-eax-and 0/imm32 + 8293 0f 84/jump-if-= break/disp32 + 8294 (emit-indent *(ebp+8) *Curr-block-depth) + 8295 (write-buffered *(ebp+8) "{\n") + 8296 # var v/ecx: (handle var) + 8297 8b/-> *(esi+8) 1/r32/ecx # Block-var + 8298 # + 8299 (write-buffered *(ebp+8) *ecx) # Var-name + 8300 (write-buffered *(ebp+8) ":loop:\n") + 8301 ff 0/subop/increment *Curr-block-depth + 8302 (push *(ebp+0x10) %ecx) + 8303 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10)) + 8304 (pop *(ebp+0x10)) # => eax + 8305 ff 1/subop/decrement *Curr-block-depth + 8306 (emit-indent *(ebp+8) *Curr-block-depth) + 8307 (write-buffered *(ebp+8) "}\n") + 8308 (write-buffered *(ebp+8) *ecx) # Var-name + 8309 (write-buffered *(ebp+8) ":break:\n") + 8310 } + 8311 $emit-subx-block:end: + 8312 # . restore registers + 8313 5e/pop-to-esi + 8314 59/pop-to-ecx + 8315 58/pop-to-eax + 8316 # . epilogue + 8317 89/<- %esp 5/r32/ebp + 8318 5d/pop-to-ebp + 8319 c3/return + 8320 + 8321 # Primitives supported + 8322 # For each operation, put variants with hard-coded registers before flexible ones. + 8323 == data + 8324 Primitives: + 8325 # - increment/decrement + 8326 _Primitive-inc-eax: + 8327 # var/eax <- increment => 40/increment-eax + 8328 "increment"/imm32/name + 8329 0/imm32/no-inouts + 8330 Single-int-var-in-eax/imm32/outputs + 8331 "40/increment-eax"/imm32/subx-name + 8332 0/imm32/no-rm32 + 8333 0/imm32/no-r32 + 8334 0/imm32/no-imm32 + 8335 0/imm32/no-disp32 + 8336 0/imm32/output-is-write-only + 8337 _Primitive-inc-ecx/imm32/next + 8338 _Primitive-inc-ecx: + 8339 # var/ecx <- increment => 41/increment-ecx + 8340 "increment"/imm32/name + 8341 0/imm32/no-inouts + 8342 Single-int-var-in-ecx/imm32/outputs + 8343 "41/increment-ecx"/imm32/subx-name + 8344 0/imm32/no-rm32 + 8345 0/imm32/no-r32 + 8346 0/imm32/no-imm32 + 8347 0/imm32/no-disp32 + 8348 0/imm32/output-is-write-only + 8349 _Primitive-inc-edx/imm32/next + 8350 _Primitive-inc-edx: + 8351 # var/edx <- increment => 42/increment-edx + 8352 "increment"/imm32/name + 8353 0/imm32/no-inouts + 8354 Single-int-var-in-edx/imm32/outputs + 8355 "42/increment-edx"/imm32/subx-name + 8356 0/imm32/no-rm32 + 8357 0/imm32/no-r32 + 8358 0/imm32/no-imm32 + 8359 0/imm32/no-disp32 + 8360 0/imm32/output-is-write-only + 8361 _Primitive-inc-ebx/imm32/next + 8362 _Primitive-inc-ebx: + 8363 # var/ebx <- increment => 43/increment-ebx + 8364 "increment"/imm32/name + 8365 0/imm32/no-inouts + 8366 Single-int-var-in-ebx/imm32/outputs + 8367 "43/increment-ebx"/imm32/subx-name + 8368 0/imm32/no-rm32 + 8369 0/imm32/no-r32 + 8370 0/imm32/no-imm32 + 8371 0/imm32/no-disp32 + 8372 0/imm32/output-is-write-only + 8373 _Primitive-inc-esi/imm32/next + 8374 _Primitive-inc-esi: + 8375 # var/esi <- increment => 46/increment-esi + 8376 "increment"/imm32/name + 8377 0/imm32/no-inouts + 8378 Single-int-var-in-esi/imm32/outputs + 8379 "46/increment-esi"/imm32/subx-name + 8380 0/imm32/no-rm32 + 8381 0/imm32/no-r32 + 8382 0/imm32/no-imm32 + 8383 0/imm32/no-disp32 + 8384 0/imm32/output-is-write-only + 8385 _Primitive-inc-edi/imm32/next + 8386 _Primitive-inc-edi: + 8387 # var/edi <- increment => 47/increment-edi + 8388 "increment"/imm32/name + 8389 0/imm32/no-inouts + 8390 Single-int-var-in-edi/imm32/outputs + 8391 "47/increment-edi"/imm32/subx-name + 8392 0/imm32/no-rm32 + 8393 0/imm32/no-r32 + 8394 0/imm32/no-imm32 + 8395 0/imm32/no-disp32 + 8396 0/imm32/output-is-write-only + 8397 _Primitive-dec-eax/imm32/next + 8398 _Primitive-dec-eax: + 8399 # var/eax <- decrement => 48/decrement-eax + 8400 "decrement"/imm32/name + 8401 0/imm32/no-inouts + 8402 Single-int-var-in-eax/imm32/outputs + 8403 "48/decrement-eax"/imm32/subx-name + 8404 0/imm32/no-rm32 + 8405 0/imm32/no-r32 + 8406 0/imm32/no-imm32 + 8407 0/imm32/no-disp32 + 8408 0/imm32/output-is-write-only + 8409 _Primitive-dec-ecx/imm32/next + 8410 _Primitive-dec-ecx: + 8411 # var/ecx <- decrement => 49/decrement-ecx + 8412 "decrement"/imm32/name + 8413 0/imm32/no-inouts + 8414 Single-int-var-in-ecx/imm32/outputs + 8415 "49/decrement-ecx"/imm32/subx-name + 8416 0/imm32/no-rm32 + 8417 0/imm32/no-r32 + 8418 0/imm32/no-imm32 + 8419 0/imm32/no-disp32 + 8420 0/imm32/output-is-write-only + 8421 _Primitive-dec-edx/imm32/next + 8422 _Primitive-dec-edx: + 8423 # var/edx <- decrement => 4a/decrement-edx + 8424 "decrement"/imm32/name + 8425 0/imm32/no-inouts + 8426 Single-int-var-in-edx/imm32/outputs + 8427 "4a/decrement-edx"/imm32/subx-name + 8428 0/imm32/no-rm32 + 8429 0/imm32/no-r32 + 8430 0/imm32/no-imm32 + 8431 0/imm32/no-disp32 + 8432 0/imm32/output-is-write-only + 8433 _Primitive-dec-ebx/imm32/next + 8434 _Primitive-dec-ebx: + 8435 # var/ebx <- decrement => 4b/decrement-ebx + 8436 "decrement"/imm32/name + 8437 0/imm32/no-inouts + 8438 Single-int-var-in-ebx/imm32/outputs + 8439 "4b/decrement-ebx"/imm32/subx-name + 8440 0/imm32/no-rm32 + 8441 0/imm32/no-r32 + 8442 0/imm32/no-imm32 + 8443 0/imm32/no-disp32 + 8444 0/imm32/output-is-write-only + 8445 _Primitive-dec-esi/imm32/next + 8446 _Primitive-dec-esi: + 8447 # var/esi <- decrement => 4e/decrement-esi + 8448 "decrement"/imm32/name + 8449 0/imm32/no-inouts + 8450 Single-int-var-in-esi/imm32/outputs + 8451 "4e/decrement-esi"/imm32/subx-name + 8452 0/imm32/no-rm32 + 8453 0/imm32/no-r32 + 8454 0/imm32/no-imm32 + 8455 0/imm32/no-disp32 + 8456 0/imm32/output-is-write-only + 8457 _Primitive-dec-edi/imm32/next + 8458 _Primitive-dec-edi: + 8459 # var/edi <- decrement => 4f/decrement-edi + 8460 "decrement"/imm32/name + 8461 0/imm32/no-inouts + 8462 Single-int-var-in-edi/imm32/outputs + 8463 "4f/decrement-edi"/imm32/subx-name + 8464 0/imm32/no-rm32 + 8465 0/imm32/no-r32 + 8466 0/imm32/no-imm32 + 8467 0/imm32/no-disp32 + 8468 0/imm32/output-is-write-only + 8469 _Primitive-inc-mem/imm32/next + 8470 _Primitive-inc-mem: + 8471 # increment var => ff 0/subop/increment *(ebp+__) + 8472 "increment"/imm32/name + 8473 Single-int-var-in-mem/imm32/inouts + 8474 0/imm32/no-outputs + 8475 "ff 0/subop/increment"/imm32/subx-name + 8476 1/imm32/rm32-is-first-inout + 8477 0/imm32/no-r32 + 8478 0/imm32/no-imm32 + 8479 0/imm32/no-disp32 + 8480 0/imm32/output-is-write-only + 8481 _Primitive-inc-reg/imm32/next + 8482 _Primitive-inc-reg: + 8483 # var/reg <- increment => ff 0/subop/increment %__ + 8484 "increment"/imm32/name + 8485 0/imm32/no-inouts + 8486 Single-int-var-in-some-register/imm32/outputs + 8487 "ff 0/subop/increment"/imm32/subx-name + 8488 3/imm32/rm32-is-first-output + 8489 0/imm32/no-r32 + 8490 0/imm32/no-imm32 + 8491 0/imm32/no-disp32 + 8492 0/imm32/output-is-write-only + 8493 _Primitive-dec-mem/imm32/next + 8494 _Primitive-dec-mem: + 8495 # decrement var => ff 1/subop/decrement *(ebp+__) + 8496 "decrement"/imm32/name + 8497 Single-int-var-in-mem/imm32/inouts + 8498 0/imm32/no-outputs + 8499 "ff 1/subop/decrement"/imm32/subx-name + 8500 1/imm32/rm32-is-first-inout + 8501 0/imm32/no-r32 + 8502 0/imm32/no-imm32 + 8503 0/imm32/no-disp32 + 8504 0/imm32/output-is-write-only + 8505 _Primitive-dec-reg/imm32/next + 8506 _Primitive-dec-reg: + 8507 # var/reg <- decrement => ff 1/subop/decrement %__ + 8508 "decrement"/imm32/name + 8509 0/imm32/no-inouts + 8510 Single-int-var-in-some-register/imm32/outputs + 8511 "ff 1/subop/decrement"/imm32/subx-name + 8512 3/imm32/rm32-is-first-output + 8513 0/imm32/no-r32 + 8514 0/imm32/no-imm32 + 8515 0/imm32/no-disp32 + 8516 0/imm32/output-is-write-only + 8517 _Primitive-add-to-eax/imm32/next + 8518 # - add + 8519 _Primitive-add-to-eax: + 8520 # var/eax <- add lit => 05/add-to-eax lit/imm32 + 8521 "add"/imm32/name + 8522 Single-lit-var/imm32/inouts + 8523 Single-int-var-in-eax/imm32/outputs + 8524 "05/add-to-eax"/imm32/subx-name + 8525 0/imm32/no-rm32 + 8526 0/imm32/no-r32 + 8527 1/imm32/imm32-is-first-inout + 8528 0/imm32/no-disp32 + 8529 0/imm32/output-is-write-only + 8530 _Primitive-add-reg-to-reg/imm32/next + 8531 _Primitive-add-reg-to-reg: + 8532 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 + 8533 "add"/imm32/name + 8534 Single-int-var-in-some-register/imm32/inouts + 8535 Single-int-var-in-some-register/imm32/outputs + 8536 "01/add-to"/imm32/subx-name + 8537 3/imm32/rm32-is-first-output + 8538 1/imm32/r32-is-first-inout + 8539 0/imm32/no-imm32 + 8540 0/imm32/no-disp32 + 8541 0/imm32/output-is-write-only + 8542 _Primitive-add-reg-to-mem/imm32/next + 8543 _Primitive-add-reg-to-mem: + 8544 # add-to var1 var2/reg => 01/add-to var1 var2/r32 + 8545 "add-to"/imm32/name + 8546 Two-args-int-stack-int-reg/imm32/inouts + 8547 0/imm32/outputs + 8548 "01/add-to"/imm32/subx-name + 8549 1/imm32/rm32-is-first-inout + 8550 2/imm32/r32-is-second-inout + 8551 0/imm32/no-imm32 + 8552 0/imm32/no-disp32 + 8553 0/imm32/output-is-write-only + 8554 _Primitive-add-mem-to-reg/imm32/next + 8555 _Primitive-add-mem-to-reg: + 8556 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 + 8557 "add"/imm32/name + 8558 Single-int-var-in-mem/imm32/inouts + 8559 Single-int-var-in-some-register/imm32/outputs + 8560 "03/add"/imm32/subx-name + 8561 1/imm32/rm32-is-first-inout + 8562 3/imm32/r32-is-first-output + 8563 0/imm32/no-imm32 + 8564 0/imm32/no-disp32 + 8565 0/imm32/output-is-write-only + 8566 _Primitive-add-lit-to-reg/imm32/next + 8567 _Primitive-add-lit-to-reg: + 8568 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 + 8569 "add"/imm32/name + 8570 Single-lit-var/imm32/inouts + 8571 Single-int-var-in-some-register/imm32/outputs + 8572 "81 0/subop/add"/imm32/subx-name + 8573 3/imm32/rm32-is-first-output + 8574 0/imm32/no-r32 + 8575 1/imm32/imm32-is-first-inout + 8576 0/imm32/no-disp32 + 8577 0/imm32/output-is-write-only + 8578 _Primitive-add-lit-to-mem/imm32/next + 8579 _Primitive-add-lit-to-mem: + 8580 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 + 8581 "add-to"/imm32/name + 8582 Int-var-and-literal/imm32/inouts + 8583 0/imm32/outputs + 8584 "81 0/subop/add"/imm32/subx-name + 8585 1/imm32/rm32-is-first-inout + 8586 0/imm32/no-r32 + 8587 2/imm32/imm32-is-second-inout + 8588 0/imm32/no-disp32 + 8589 0/imm32/output-is-write-only + 8590 _Primitive-subtract-from-eax/imm32/next + 8591 # - subtract + 8592 _Primitive-subtract-from-eax: + 8593 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 + 8594 "subtract"/imm32/name + 8595 Single-lit-var/imm32/inouts + 8596 Single-int-var-in-eax/imm32/outputs + 8597 "2d/subtract-from-eax"/imm32/subx-name + 8598 0/imm32/no-rm32 + 8599 0/imm32/no-r32 + 8600 1/imm32/imm32-is-first-inout + 8601 0/imm32/no-disp32 + 8602 0/imm32/output-is-write-only + 8603 _Primitive-subtract-reg-from-reg/imm32/next + 8604 _Primitive-subtract-reg-from-reg: + 8605 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 + 8606 "subtract"/imm32/name + 8607 Single-int-var-in-some-register/imm32/inouts + 8608 Single-int-var-in-some-register/imm32/outputs + 8609 "29/subtract-from"/imm32/subx-name + 8610 3/imm32/rm32-is-first-output + 8611 1/imm32/r32-is-first-inout + 8612 0/imm32/no-imm32 + 8613 0/imm32/no-disp32 + 8614 0/imm32/output-is-write-only + 8615 _Primitive-subtract-reg-from-mem/imm32/next + 8616 _Primitive-subtract-reg-from-mem: + 8617 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 + 8618 "subtract-from"/imm32/name + 8619 Two-args-int-stack-int-reg/imm32/inouts + 8620 0/imm32/outputs + 8621 "29/subtract-from"/imm32/subx-name + 8622 1/imm32/rm32-is-first-inout + 8623 2/imm32/r32-is-second-inout + 8624 0/imm32/no-imm32 + 8625 0/imm32/no-disp32 + 8626 0/imm32/output-is-write-only + 8627 _Primitive-subtract-mem-from-reg/imm32/next + 8628 _Primitive-subtract-mem-from-reg: + 8629 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 + 8630 "subtract"/imm32/name + 8631 Single-int-var-in-mem/imm32/inouts + 8632 Single-int-var-in-some-register/imm32/outputs + 8633 "2b/subtract"/imm32/subx-name + 8634 1/imm32/rm32-is-first-inout + 8635 3/imm32/r32-is-first-output + 8636 0/imm32/no-imm32 + 8637 0/imm32/no-disp32 + 8638 0/imm32/output-is-write-only + 8639 _Primitive-subtract-lit-from-reg/imm32/next + 8640 _Primitive-subtract-lit-from-reg: + 8641 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 + 8642 "subtract"/imm32/name + 8643 Single-lit-var/imm32/inouts + 8644 Single-int-var-in-some-register/imm32/outputs + 8645 "81 5/subop/subtract"/imm32/subx-name + 8646 3/imm32/rm32-is-first-output + 8647 0/imm32/no-r32 + 8648 1/imm32/imm32-is-first-inout + 8649 0/imm32/no-disp32 + 8650 0/imm32/output-is-write-only + 8651 _Primitive-subtract-lit-from-mem/imm32/next + 8652 _Primitive-subtract-lit-from-mem: + 8653 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 + 8654 "subtract-from"/imm32/name + 8655 Int-var-and-literal/imm32/inouts + 8656 0/imm32/outputs + 8657 "81 5/subop/subtract"/imm32/subx-name + 8658 1/imm32/rm32-is-first-inout + 8659 0/imm32/no-r32 + 8660 2/imm32/imm32-is-first-inout + 8661 0/imm32/no-disp32 + 8662 0/imm32/output-is-write-only + 8663 _Primitive-and-with-eax/imm32/next + 8664 # - and + 8665 _Primitive-and-with-eax: + 8666 # var/eax <- and lit => 25/and-with-eax lit/imm32 + 8667 "and"/imm32/name + 8668 Single-lit-var/imm32/inouts + 8669 Single-int-var-in-eax/imm32/outputs + 8670 "25/and-with-eax"/imm32/subx-name + 8671 0/imm32/no-rm32 + 8672 0/imm32/no-r32 + 8673 1/imm32/imm32-is-first-inout + 8674 0/imm32/no-disp32 + 8675 0/imm32/output-is-write-only + 8676 _Primitive-and-reg-with-reg/imm32/next + 8677 _Primitive-and-reg-with-reg: + 8678 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 + 8679 "and"/imm32/name + 8680 Single-int-var-in-some-register/imm32/inouts + 8681 Single-int-var-in-some-register/imm32/outputs + 8682 "21/and-with"/imm32/subx-name + 8683 3/imm32/rm32-is-first-output + 8684 1/imm32/r32-is-first-inout + 8685 0/imm32/no-imm32 + 8686 0/imm32/no-disp32 + 8687 0/imm32/output-is-write-only + 8688 _Primitive-and-reg-with-mem/imm32/next + 8689 _Primitive-and-reg-with-mem: + 8690 # and-with var1 var2/reg => 21/and-with var1 var2/r32 + 8691 "and-with"/imm32/name + 8692 Two-args-int-stack-int-reg/imm32/inouts + 8693 0/imm32/outputs + 8694 "21/and-with"/imm32/subx-name + 8695 1/imm32/rm32-is-first-inout + 8696 2/imm32/r32-is-second-inout + 8697 0/imm32/no-imm32 + 8698 0/imm32/no-disp32 + 8699 0/imm32/output-is-write-only + 8700 _Primitive-and-mem-with-reg/imm32/next + 8701 _Primitive-and-mem-with-reg: + 8702 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 + 8703 "and"/imm32/name + 8704 Single-int-var-in-mem/imm32/inouts + 8705 Single-int-var-in-some-register/imm32/outputs + 8706 "23/and"/imm32/subx-name + 8707 1/imm32/rm32-is-first-inout + 8708 3/imm32/r32-is-first-output + 8709 0/imm32/no-imm32 + 8710 0/imm32/no-disp32 + 8711 0/imm32/output-is-write-only + 8712 _Primitive-and-lit-with-reg/imm32/next + 8713 _Primitive-and-lit-with-reg: + 8714 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 + 8715 "and"/imm32/name + 8716 Single-lit-var/imm32/inouts + 8717 Single-int-var-in-some-register/imm32/outputs + 8718 "81 4/subop/and"/imm32/subx-name + 8719 3/imm32/rm32-is-first-output + 8720 0/imm32/no-r32 + 8721 1/imm32/imm32-is-first-inout + 8722 0/imm32/no-disp32 + 8723 0/imm32/output-is-write-only + 8724 _Primitive-and-lit-with-mem/imm32/next + 8725 _Primitive-and-lit-with-mem: + 8726 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 + 8727 "and-with"/imm32/name + 8728 Int-var-and-literal/imm32/inouts + 8729 0/imm32/outputs + 8730 "81 4/subop/and"/imm32/subx-name + 8731 1/imm32/rm32-is-first-inout + 8732 0/imm32/no-r32 + 8733 2/imm32/imm32-is-first-inout + 8734 0/imm32/no-disp32 + 8735 0/imm32/output-is-write-only + 8736 _Primitive-or-with-eax/imm32/next + 8737 # - or + 8738 _Primitive-or-with-eax: + 8739 # var/eax <- or lit => 0d/or-with-eax lit/imm32 + 8740 "or"/imm32/name + 8741 Single-lit-var/imm32/inouts + 8742 Single-int-var-in-eax/imm32/outputs + 8743 "0d/or-with-eax"/imm32/subx-name + 8744 0/imm32/no-rm32 + 8745 0/imm32/no-r32 + 8746 1/imm32/imm32-is-first-inout + 8747 0/imm32/no-disp32 + 8748 0/imm32/output-is-write-only + 8749 _Primitive-or-reg-with-reg/imm32/next + 8750 _Primitive-or-reg-with-reg: + 8751 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 + 8752 "or"/imm32/name + 8753 Single-int-var-in-some-register/imm32/inouts + 8754 Single-int-var-in-some-register/imm32/outputs + 8755 "09/or-with"/imm32/subx-name + 8756 3/imm32/rm32-is-first-output + 8757 1/imm32/r32-is-first-inout + 8758 0/imm32/no-imm32 + 8759 0/imm32/no-disp32 + 8760 0/imm32/output-is-write-only + 8761 _Primitive-or-reg-with-mem/imm32/next + 8762 _Primitive-or-reg-with-mem: + 8763 # or-with var1 var2/reg => 09/or-with var1 var2/r32 + 8764 "or-with"/imm32/name + 8765 Two-args-int-stack-int-reg/imm32/inouts + 8766 0/imm32/outputs + 8767 "09/or-with"/imm32/subx-name + 8768 1/imm32/rm32-is-first-inout + 8769 2/imm32/r32-is-second-inout + 8770 0/imm32/no-imm32 + 8771 0/imm32/no-disp32 + 8772 0/imm32/output-is-write-only + 8773 _Primitive-or-mem-with-reg/imm32/next + 8774 _Primitive-or-mem-with-reg: + 8775 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 + 8776 "or"/imm32/name + 8777 Single-int-var-in-mem/imm32/inouts + 8778 Single-int-var-in-some-register/imm32/outputs + 8779 "0b/or"/imm32/subx-name + 8780 1/imm32/rm32-is-first-inout + 8781 3/imm32/r32-is-first-output + 8782 0/imm32/no-imm32 + 8783 0/imm32/no-disp32 + 8784 0/imm32/output-is-write-only + 8785 _Primitive-or-lit-with-reg/imm32/next + 8786 _Primitive-or-lit-with-reg: + 8787 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 + 8788 "or"/imm32/name + 8789 Single-lit-var/imm32/inouts + 8790 Single-int-var-in-some-register/imm32/outputs + 8791 "81 1/subop/or"/imm32/subx-name + 8792 3/imm32/rm32-is-first-output + 8793 0/imm32/no-r32 + 8794 1/imm32/imm32-is-first-inout + 8795 0/imm32/no-disp32 + 8796 0/imm32/output-is-write-only + 8797 _Primitive-or-lit-with-mem/imm32/next + 8798 _Primitive-or-lit-with-mem: + 8799 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 + 8800 "or-with"/imm32/name + 8801 Int-var-and-literal/imm32/inouts + 8802 0/imm32/outputs + 8803 "81 1/subop/or"/imm32/subx-name + 8804 1/imm32/rm32-is-first-inout + 8805 0/imm32/no-r32 + 8806 2/imm32/imm32-is-second-inout + 8807 0/imm32/no-disp32 + 8808 0/imm32/output-is-write-only + 8809 _Primitive-xor-with-eax/imm32/next + 8810 # - xor + 8811 _Primitive-xor-with-eax: + 8812 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 + 8813 "xor"/imm32/name + 8814 Single-lit-var/imm32/inouts + 8815 Single-int-var-in-eax/imm32/outputs + 8816 "35/xor-with-eax"/imm32/subx-name + 8817 0/imm32/no-rm32 + 8818 0/imm32/no-r32 + 8819 1/imm32/imm32-is-first-inout + 8820 0/imm32/no-disp32 + 8821 0/imm32/output-is-write-only + 8822 _Primitive-xor-reg-with-reg/imm32/next + 8823 _Primitive-xor-reg-with-reg: + 8824 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 + 8825 "xor"/imm32/name + 8826 Single-int-var-in-some-register/imm32/inouts + 8827 Single-int-var-in-some-register/imm32/outputs + 8828 "31/xor-with"/imm32/subx-name + 8829 3/imm32/rm32-is-first-output + 8830 1/imm32/r32-is-first-inout + 8831 0/imm32/no-imm32 + 8832 0/imm32/no-disp32 + 8833 0/imm32/output-is-write-only + 8834 _Primitive-xor-reg-with-mem/imm32/next + 8835 _Primitive-xor-reg-with-mem: + 8836 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 + 8837 "xor-with"/imm32/name + 8838 Two-args-int-stack-int-reg/imm32/inouts + 8839 0/imm32/outputs + 8840 "31/xor-with"/imm32/subx-name + 8841 1/imm32/rm32-is-first-inout + 8842 2/imm32/r32-is-second-inout + 8843 0/imm32/no-imm32 + 8844 0/imm32/no-disp32 + 8845 0/imm32/output-is-write-only + 8846 _Primitive-xor-mem-with-reg/imm32/next + 8847 _Primitive-xor-mem-with-reg: + 8848 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 + 8849 "xor"/imm32/name + 8850 Single-int-var-in-mem/imm32/inouts + 8851 Single-int-var-in-some-register/imm32/outputs + 8852 "33/xor"/imm32/subx-name + 8853 1/imm32/rm32-is-first-inout + 8854 3/imm32/r32-is-first-output + 8855 0/imm32/no-imm32 + 8856 0/imm32/no-disp32 + 8857 0/imm32/output-is-write-only + 8858 _Primitive-xor-lit-with-reg/imm32/next + 8859 _Primitive-xor-lit-with-reg: + 8860 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 + 8861 "xor"/imm32/name + 8862 Single-lit-var/imm32/inouts + 8863 Single-int-var-in-some-register/imm32/outputs + 8864 "81 6/subop/xor"/imm32/subx-name + 8865 3/imm32/rm32-is-first-output + 8866 0/imm32/no-r32 + 8867 1/imm32/imm32-is-first-inout + 8868 0/imm32/no-disp32 + 8869 0/imm32/output-is-write-only + 8870 _Primitive-xor-lit-with-mem/imm32/next + 8871 _Primitive-xor-lit-with-mem: + 8872 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 + 8873 "xor-with"/imm32/name + 8874 Int-var-and-literal/imm32/inouts + 8875 0/imm32/outputs + 8876 "81 6/subop/xor"/imm32/subx-name + 8877 1/imm32/rm32-is-first-inout + 8878 0/imm32/no-r32 + 8879 2/imm32/imm32-is-first-inout + 8880 0/imm32/no-disp32 + 8881 0/imm32/output-is-write-only + 8882 _Primitive-copy-to-eax/imm32/next + 8883 # - copy + 8884 _Primitive-copy-to-eax: + 8885 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 + 8886 "copy"/imm32/name + 8887 Single-lit-var/imm32/inouts + 8888 Single-int-var-in-eax/imm32/outputs + 8889 "b8/copy-to-eax"/imm32/subx-name + 8890 0/imm32/no-rm32 + 8891 0/imm32/no-r32 + 8892 1/imm32/imm32-is-first-inout + 8893 0/imm32/no-disp32 + 8894 1/imm32/output-is-write-only + 8895 _Primitive-copy-to-ecx/imm32/next + 8896 _Primitive-copy-to-ecx: + 8897 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 + 8898 "copy"/imm32/name + 8899 Single-lit-var/imm32/inouts + 8900 Single-int-var-in-ecx/imm32/outputs + 8901 "b9/copy-to-ecx"/imm32/subx-name + 8902 0/imm32/no-rm32 + 8903 0/imm32/no-r32 + 8904 1/imm32/imm32-is-first-inout + 8905 0/imm32/no-disp32 + 8906 1/imm32/output-is-write-only + 8907 _Primitive-copy-to-edx/imm32/next + 8908 _Primitive-copy-to-edx: + 8909 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 + 8910 "copy"/imm32/name + 8911 Single-lit-var/imm32/inouts + 8912 Single-int-var-in-edx/imm32/outputs + 8913 "ba/copy-to-edx"/imm32/subx-name + 8914 0/imm32/no-rm32 + 8915 0/imm32/no-r32 + 8916 1/imm32/imm32-is-first-inout + 8917 0/imm32/no-disp32 + 8918 1/imm32/output-is-write-only + 8919 _Primitive-copy-to-ebx/imm32/next + 8920 _Primitive-copy-to-ebx: + 8921 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 + 8922 "copy"/imm32/name + 8923 Single-lit-var/imm32/inouts + 8924 Single-int-var-in-ebx/imm32/outputs + 8925 "bb/copy-to-ebx"/imm32/subx-name + 8926 0/imm32/no-rm32 + 8927 0/imm32/no-r32 + 8928 1/imm32/imm32-is-first-inout + 8929 0/imm32/no-disp32 + 8930 1/imm32/output-is-write-only + 8931 _Primitive-copy-to-esi/imm32/next + 8932 _Primitive-copy-to-esi: + 8933 # var/esi <- copy lit => be/copy-to-esi lit/imm32 + 8934 "copy"/imm32/name + 8935 Single-lit-var/imm32/inouts + 8936 Single-int-var-in-esi/imm32/outputs + 8937 "be/copy-to-esi"/imm32/subx-name + 8938 0/imm32/no-rm32 + 8939 0/imm32/no-r32 + 8940 1/imm32/imm32-is-first-inout + 8941 0/imm32/no-disp32 + 8942 1/imm32/output-is-write-only + 8943 _Primitive-copy-to-edi/imm32/next + 8944 _Primitive-copy-to-edi: + 8945 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 + 8946 "copy"/imm32/name + 8947 Single-lit-var/imm32/inouts + 8948 Single-int-var-in-edi/imm32/outputs + 8949 "bf/copy-to-edi"/imm32/subx-name + 8950 0/imm32/no-rm32 + 8951 0/imm32/no-r32 + 8952 1/imm32/imm32-is-first-inout + 8953 0/imm32/no-disp32 + 8954 1/imm32/output-is-write-only + 8955 _Primitive-copy-reg-to-reg/imm32/next + 8956 _Primitive-copy-reg-to-reg: + 8957 # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32 + 8958 "copy"/imm32/name + 8959 Single-int-var-in-some-register/imm32/inouts + 8960 Single-int-var-in-some-register/imm32/outputs + 8961 "89/<-"/imm32/subx-name + 8962 3/imm32/rm32-is-first-output + 8963 1/imm32/r32-is-first-inout + 8964 0/imm32/no-imm32 + 8965 0/imm32/no-disp32 + 8966 1/imm32/output-is-write-only + 8967 _Primitive-copy-reg-to-mem/imm32/next + 8968 _Primitive-copy-reg-to-mem: + 8969 # copy-to var1 var2/reg => 89/<- var1 var2/r32 + 8970 "copy-to"/imm32/name + 8971 Two-args-int-stack-int-reg/imm32/inouts + 8972 0/imm32/outputs + 8973 "89/<-"/imm32/subx-name + 8974 1/imm32/rm32-is-first-inout + 8975 2/imm32/r32-is-second-inout + 8976 0/imm32/no-imm32 + 8977 0/imm32/no-disp32 + 8978 1/imm32/output-is-write-only + 8979 _Primitive-copy-mem-to-reg/imm32/next + 8980 _Primitive-copy-mem-to-reg: + 8981 # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32 + 8982 "copy"/imm32/name + 8983 Single-int-var-in-mem/imm32/inouts + 8984 Single-int-var-in-some-register/imm32/outputs + 8985 "8b/->"/imm32/subx-name + 8986 1/imm32/rm32-is-first-inout + 8987 3/imm32/r32-is-first-output + 8988 0/imm32/no-imm32 + 8989 0/imm32/no-disp32 + 8990 1/imm32/output-is-write-only + 8991 _Primitive-copy-lit-to-reg/imm32/next + 8992 _Primitive-copy-lit-to-reg: + 8993 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 + 8994 "copy"/imm32/name + 8995 Single-lit-var/imm32/inouts + 8996 Single-int-var-in-some-register/imm32/outputs + 8997 "c7 0/subop/copy"/imm32/subx-name + 8998 3/imm32/rm32-is-first-output + 8999 0/imm32/no-r32 + 9000 1/imm32/imm32-is-first-inout + 9001 0/imm32/no-disp32 + 9002 1/imm32/output-is-write-only + 9003 _Primitive-copy-lit-to-mem/imm32/next + 9004 _Primitive-copy-lit-to-mem: + 9005 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 + 9006 "copy-to"/imm32/name + 9007 Int-var-and-literal/imm32/inouts + 9008 0/imm32/outputs + 9009 "c7 0/subop/copy"/imm32/subx-name + 9010 1/imm32/rm32-is-first-inout + 9011 0/imm32/no-r32 + 9012 2/imm32/imm32-is-first-inout + 9013 0/imm32/no-disp32 + 9014 1/imm32/output-is-write-only + 9015 _Primitive-address/imm32/next + 9016 # - address + 9017 _Primitive-address: + 9018 # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32 + 9019 "address"/imm32/name + 9020 Single-int-var-in-mem/imm32/inouts + 9021 Single-addr-var-in-some-register/imm32/outputs + 9022 "8d/copy-address"/imm32/subx-name + 9023 1/imm32/rm32-is-first-inout + 9024 3/imm32/r32-is-first-output + 9025 0/imm32/no-imm32 + 9026 0/imm32/no-disp32 + 9027 1/imm32/output-is-write-only + 9028 _Primitive-compare-mem-with-reg/imm32/next + 9029 # - compare + 9030 _Primitive-compare-mem-with-reg: + 9031 # compare var1 var2/reg => 39/compare var1/rm32 var2/r32 + 9032 "compare"/imm32/name + 9033 Two-args-int-stack-int-reg/imm32/inouts + 9034 0/imm32/outputs + 9035 "39/compare->"/imm32/subx-name + 9036 1/imm32/rm32-is-first-inout + 9037 2/imm32/r32-is-second-inout + 9038 0/imm32/no-imm32 + 9039 0/imm32/no-disp32 + 9040 0/imm32/output-is-write-only + 9041 _Primitive-compare-reg-with-mem/imm32/next + 9042 _Primitive-compare-reg-with-mem: + 9043 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 + 9044 "compare"/imm32/name + 9045 Two-args-int-reg-int-stack/imm32/inouts + 9046 0/imm32/outputs + 9047 "3b/compare<-"/imm32/subx-name + 9048 2/imm32/rm32-is-second-inout + 9049 1/imm32/r32-is-first-inout + 9050 0/imm32/no-imm32 + 9051 0/imm32/no-disp32 + 9052 0/imm32/output-is-write-only + 9053 _Primitive-compare-eax-with-literal/imm32/next + 9054 _Primitive-compare-eax-with-literal: + 9055 # compare var1/eax n => 3d/compare-eax-with n/imm32 + 9056 "compare"/imm32/name + 9057 Two-args-int-eax-int-literal/imm32/inouts + 9058 0/imm32/outputs + 9059 "3d/compare-eax-with"/imm32/subx-name + 9060 0/imm32/no-rm32 + 9061 0/imm32/no-r32 + 9062 2/imm32/imm32-is-second-inout + 9063 0/imm32/no-disp32 + 9064 0/imm32/output-is-write-only + 9065 _Primitive-compare-reg-with-literal/imm32/next + 9066 _Primitive-compare-reg-with-literal: + 9067 # compare var1/reg n => 81 7/subop/compare %reg n/imm32 + 9068 "compare"/imm32/name + 9069 Int-var-in-register-and-literal/imm32/inouts + 9070 0/imm32/outputs + 9071 "81 7/subop/compare"/imm32/subx-name + 9072 1/imm32/rm32-is-first-inout + 9073 0/imm32/no-r32 + 9074 2/imm32/imm32-is-second-inout + 9075 0/imm32/no-disp32 + 9076 0/imm32/output-is-write-only + 9077 _Primitive-compare-mem-with-literal/imm32/next + 9078 _Primitive-compare-mem-with-literal: + 9079 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 + 9080 "compare"/imm32/name + 9081 Int-var-and-literal/imm32/inouts + 9082 0/imm32/outputs + 9083 "81 7/subop/compare"/imm32/subx-name + 9084 1/imm32/rm32-is-first-inout + 9085 0/imm32/no-r32 + 9086 2/imm32/imm32-is-second-inout + 9087 0/imm32/no-disp32 + 9088 0/imm32/output-is-write-only + 9089 _Primitive-multiply-reg-by-mem/imm32/next + 9090 # - multiply + 9091 _Primitive-multiply-reg-by-mem: + 9092 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 + 9093 "multiply"/imm32/name + 9094 Single-int-var-in-mem/imm32/inouts + 9095 Single-int-var-in-some-register/imm32/outputs + 9096 "0f af/multiply"/imm32/subx-name + 9097 1/imm32/rm32-is-first-inout + 9098 3/imm32/r32-is-first-output + 9099 0/imm32/no-imm32 + 9100 0/imm32/no-disp32 + 9101 0/imm32/output-is-write-only + 9102 _Primitive-break-if-addr</imm32/next + 9103 # - branches + 9104 _Primitive-break-if-addr<: + 9105 "break-if-addr<"/imm32/name + 9106 0/imm32/inouts + 9107 0/imm32/outputs + 9108 "0f 82/jump-if-addr< break/disp32"/imm32/subx-name + 9109 0/imm32/no-rm32 + 9110 0/imm32/no-r32 + 9111 0/imm32/no-imm32 + 9112 0/imm32/no-disp32 + 9113 0/imm32/no-output + 9114 _Primitive-break-if-addr>=/imm32/next + 9115 _Primitive-break-if-addr>=: + 9116 "break-if-addr>="/imm32/name + 9117 0/imm32/inouts + 9118 0/imm32/outputs + 9119 "0f 83/jump-if-addr>= break/disp32"/imm32/subx-name + 9120 0/imm32/no-rm32 + 9121 0/imm32/no-r32 + 9122 0/imm32/no-imm32 + 9123 0/imm32/no-disp32 + 9124 0/imm32/no-output + 9125 _Primitive-break-if-=/imm32/next + 9126 _Primitive-break-if-=: + 9127 "break-if-="/imm32/name + 9128 0/imm32/inouts + 9129 0/imm32/outputs + 9130 "0f 84/jump-if-= break/disp32"/imm32/subx-name + 9131 0/imm32/no-rm32 + 9132 0/imm32/no-r32 + 9133 0/imm32/no-imm32 + 9134 0/imm32/no-disp32 + 9135 0/imm32/no-output + 9136 _Primitive-break-if-!=/imm32/next + 9137 _Primitive-break-if-!=: + 9138 "break-if-!="/imm32/name + 9139 0/imm32/inouts + 9140 0/imm32/outputs + 9141 "0f 85/jump-if-!= break/disp32"/imm32/subx-name + 9142 0/imm32/no-rm32 + 9143 0/imm32/no-r32 + 9144 0/imm32/no-imm32 + 9145 0/imm32/no-disp32 + 9146 0/imm32/no-output + 9147 _Primitive-break-if-addr<=/imm32/next + 9148 _Primitive-break-if-addr<=: + 9149 "break-if-addr<="/imm32/name + 9150 0/imm32/inouts + 9151 0/imm32/outputs + 9152 "0f 86/jump-if-addr<= break/disp32"/imm32/subx-name + 9153 0/imm32/no-rm32 + 9154 0/imm32/no-r32 + 9155 0/imm32/no-imm32 + 9156 0/imm32/no-disp32 + 9157 0/imm32/no-output + 9158 _Primitive-break-if-addr>/imm32/next + 9159 _Primitive-break-if-addr>: + 9160 "break-if-addr>"/imm32/name + 9161 0/imm32/inouts + 9162 0/imm32/outputs + 9163 "0f 87/jump-if-addr> break/disp32"/imm32/subx-name + 9164 0/imm32/no-rm32 + 9165 0/imm32/no-r32 + 9166 0/imm32/no-imm32 + 9167 0/imm32/no-disp32 + 9168 0/imm32/no-output + 9169 _Primitive-break-if-</imm32/next + 9170 _Primitive-break-if-<: + 9171 "break-if-<"/imm32/name + 9172 0/imm32/inouts + 9173 0/imm32/outputs + 9174 "0f 8c/jump-if-< break/disp32"/imm32/subx-name + 9175 0/imm32/no-rm32 + 9176 0/imm32/no-r32 + 9177 0/imm32/no-imm32 + 9178 0/imm32/no-disp32 + 9179 0/imm32/no-output + 9180 _Primitive-break-if->=/imm32/next + 9181 _Primitive-break-if->=: + 9182 "break-if->="/imm32/name + 9183 0/imm32/inouts + 9184 0/imm32/outputs + 9185 "0f 8d/jump-if->= break/disp32"/imm32/subx-name + 9186 0/imm32/no-rm32 + 9187 0/imm32/no-r32 + 9188 0/imm32/no-imm32 + 9189 0/imm32/no-disp32 + 9190 0/imm32/no-output + 9191 _Primitive-break-if-<=/imm32/next + 9192 _Primitive-break-if-<=: + 9193 "break-if-<="/imm32/name + 9194 0/imm32/inouts + 9195 0/imm32/outputs + 9196 "0f 8e/jump-if-<= break/disp32"/imm32/subx-name + 9197 0/imm32/no-rm32 + 9198 0/imm32/no-r32 + 9199 0/imm32/no-imm32 + 9200 0/imm32/no-disp32 + 9201 0/imm32/no-output + 9202 _Primitive-break-if->/imm32/next + 9203 _Primitive-break-if->: + 9204 "break-if->"/imm32/name + 9205 0/imm32/inouts + 9206 0/imm32/outputs + 9207 "0f 8f/jump-if-> break/disp32"/imm32/subx-name + 9208 0/imm32/no-rm32 + 9209 0/imm32/no-r32 + 9210 0/imm32/no-imm32 + 9211 0/imm32/no-disp32 + 9212 0/imm32/no-output + 9213 _Primitive-break/imm32/next + 9214 _Primitive-break: + 9215 "break"/imm32/name + 9216 0/imm32/inouts + 9217 0/imm32/outputs + 9218 "e9/jump break/disp32"/imm32/subx-name + 9219 0/imm32/no-rm32 + 9220 0/imm32/no-r32 + 9221 0/imm32/no-imm32 + 9222 0/imm32/no-disp32 + 9223 0/imm32/no-output + 9224 _Primitive-loop-if-addr</imm32/next + 9225 _Primitive-loop-if-addr<: + 9226 "loop-if-addr<"/imm32/name + 9227 0/imm32/inouts + 9228 0/imm32/outputs + 9229 "0f 82/jump-if-addr< loop/disp32"/imm32/subx-name + 9230 0/imm32/no-rm32 + 9231 0/imm32/no-r32 + 9232 0/imm32/no-imm32 + 9233 0/imm32/no-disp32 + 9234 0/imm32/no-output + 9235 _Primitive-loop-if-addr>=/imm32/next + 9236 _Primitive-loop-if-addr>=: + 9237 "loop-if-addr>="/imm32/name + 9238 0/imm32/inouts + 9239 0/imm32/outputs + 9240 "0f 83/jump-if-addr>= loop/disp32"/imm32/subx-name + 9241 0/imm32/no-rm32 + 9242 0/imm32/no-r32 + 9243 0/imm32/no-imm32 + 9244 0/imm32/no-disp32 + 9245 0/imm32/no-output + 9246 _Primitive-loop-if-=/imm32/next + 9247 _Primitive-loop-if-=: + 9248 "loop-if-="/imm32/name + 9249 0/imm32/inouts + 9250 0/imm32/outputs + 9251 "0f 84/jump-if-= loop/disp32"/imm32/subx-name + 9252 0/imm32/no-rm32 + 9253 0/imm32/no-r32 + 9254 0/imm32/no-imm32 + 9255 0/imm32/no-disp32 + 9256 0/imm32/no-output + 9257 _Primitive-loop-if-!=/imm32/next + 9258 _Primitive-loop-if-!=: + 9259 "loop-if-!="/imm32/name + 9260 0/imm32/inouts + 9261 0/imm32/outputs + 9262 "0f 85/jump-if-!= loop/disp32"/imm32/subx-name + 9263 0/imm32/no-rm32 + 9264 0/imm32/no-r32 + 9265 0/imm32/no-imm32 + 9266 0/imm32/no-disp32 + 9267 0/imm32/no-output + 9268 _Primitive-loop-if-addr<=/imm32/next + 9269 _Primitive-loop-if-addr<=: + 9270 "loop-if-addr<="/imm32/name + 9271 0/imm32/inouts + 9272 0/imm32/outputs + 9273 "0f 86/jump-if-addr<= loop/disp32"/imm32/subx-name + 9274 0/imm32/no-rm32 + 9275 0/imm32/no-r32 + 9276 0/imm32/no-imm32 + 9277 0/imm32/no-disp32 + 9278 0/imm32/no-output + 9279 _Primitive-loop-if-addr>/imm32/next + 9280 _Primitive-loop-if-addr>: + 9281 "loop-if-addr>"/imm32/name + 9282 0/imm32/inouts + 9283 0/imm32/outputs + 9284 "0f 87/jump-if-addr> loop/disp32"/imm32/subx-name + 9285 0/imm32/no-rm32 + 9286 0/imm32/no-r32 + 9287 0/imm32/no-imm32 + 9288 0/imm32/no-disp32 + 9289 0/imm32/no-output + 9290 _Primitive-loop-if-</imm32/next + 9291 _Primitive-loop-if-<: + 9292 "loop-if-<"/imm32/name + 9293 0/imm32/inouts + 9294 0/imm32/outputs + 9295 "0f 8c/jump-if-< loop/disp32"/imm32/subx-name + 9296 0/imm32/no-rm32 + 9297 0/imm32/no-r32 + 9298 0/imm32/no-imm32 + 9299 0/imm32/no-disp32 + 9300 0/imm32/no-output + 9301 _Primitive-loop-if->=/imm32/next + 9302 _Primitive-loop-if->=: + 9303 "loop-if->="/imm32/name + 9304 0/imm32/inouts + 9305 0/imm32/outputs + 9306 "0f 8d/jump-if->= loop/disp32"/imm32/subx-name + 9307 0/imm32/no-rm32 + 9308 0/imm32/no-r32 + 9309 0/imm32/no-imm32 + 9310 0/imm32/no-disp32 + 9311 0/imm32/no-output + 9312 _Primitive-loop-if-<=/imm32/next + 9313 _Primitive-loop-if-<=: + 9314 "loop-if-<="/imm32/name + 9315 0/imm32/inouts + 9316 0/imm32/outputs + 9317 "0f 8e/jump-if-<= loop/disp32"/imm32/subx-name + 9318 0/imm32/no-rm32 + 9319 0/imm32/no-r32 + 9320 0/imm32/no-imm32 + 9321 0/imm32/no-disp32 + 9322 0/imm32/no-output + 9323 _Primitive-loop-if->/imm32/next + 9324 _Primitive-loop-if->: + 9325 "loop-if->"/imm32/name + 9326 0/imm32/inouts + 9327 0/imm32/outputs + 9328 "0f 8f/jump-if-> loop/disp32"/imm32/subx-name + 9329 0/imm32/no-rm32 + 9330 0/imm32/no-r32 + 9331 0/imm32/no-imm32 + 9332 0/imm32/no-disp32 + 9333 0/imm32/no-output + 9334 _Primitive-loop/imm32/next # we probably don't need an unconditional break + 9335 _Primitive-loop: + 9336 "loop"/imm32/name + 9337 0/imm32/inouts + 9338 0/imm32/outputs + 9339 "e9/jump loop/disp32"/imm32/subx-name + 9340 0/imm32/no-rm32 + 9341 0/imm32/no-r32 + 9342 0/imm32/no-imm32 + 9343 0/imm32/no-disp32 + 9344 0/imm32/no-output + 9345 _Primitive-break-if-addr<-named/imm32/next + 9346 # - branches to named blocks + 9347 _Primitive-break-if-addr<-named: + 9348 "break-if-addr<"/imm32/name + 9349 Single-lit-var/imm32/inouts + 9350 0/imm32/outputs + 9351 "0f 82/jump-if-addr<"/imm32/subx-name + 9352 0/imm32/no-rm32 + 9353 0/imm32/no-r32 + 9354 0/imm32/no-imm32 + 9355 1/imm32/disp32-is-first-inout + 9356 0/imm32/no-output + 9357 _Primitive-break-if-addr>=-named/imm32/next + 9358 _Primitive-break-if-addr>=-named: + 9359 "break-if-addr>="/imm32/name + 9360 Single-lit-var/imm32/inouts + 9361 0/imm32/outputs + 9362 "0f 83/jump-if-addr>="/imm32/subx-name + 9363 0/imm32/no-rm32 + 9364 0/imm32/no-r32 + 9365 0/imm32/no-imm32 + 9366 1/imm32/disp32-is-first-inout + 9367 0/imm32/no-output + 9368 _Primitive-break-if-=-named/imm32/next + 9369 _Primitive-break-if-=-named: + 9370 "break-if-="/imm32/name + 9371 Single-lit-var/imm32/inouts + 9372 0/imm32/outputs + 9373 "0f 84/jump-if-="/imm32/subx-name + 9374 0/imm32/no-rm32 + 9375 0/imm32/no-r32 + 9376 0/imm32/no-imm32 + 9377 1/imm32/disp32-is-first-inout + 9378 0/imm32/no-output + 9379 _Primitive-break-if-!=-named/imm32/next + 9380 _Primitive-break-if-!=-named: + 9381 "break-if-!="/imm32/name + 9382 Single-lit-var/imm32/inouts + 9383 0/imm32/outputs + 9384 "0f 85/jump-if-!="/imm32/subx-name + 9385 0/imm32/no-rm32 + 9386 0/imm32/no-r32 + 9387 0/imm32/no-imm32 + 9388 1/imm32/disp32-is-first-inout + 9389 0/imm32/no-output + 9390 _Primitive-break-if-addr<=-named/imm32/next + 9391 _Primitive-break-if-addr<=-named: + 9392 "break-if-addr<="/imm32/name + 9393 Single-lit-var/imm32/inouts + 9394 0/imm32/outputs + 9395 "0f 86/jump-if-addr<="/imm32/subx-name + 9396 0/imm32/no-rm32 + 9397 0/imm32/no-r32 + 9398 0/imm32/no-imm32 + 9399 1/imm32/disp32-is-first-inout + 9400 0/imm32/no-output + 9401 _Primitive-break-if-addr>-named/imm32/next + 9402 _Primitive-break-if-addr>-named: + 9403 "break-if-addr>"/imm32/name + 9404 Single-lit-var/imm32/inouts + 9405 0/imm32/outputs + 9406 "0f 87/jump-if-addr>"/imm32/subx-name + 9407 0/imm32/no-rm32 + 9408 0/imm32/no-r32 + 9409 0/imm32/no-imm32 + 9410 1/imm32/disp32-is-first-inout + 9411 0/imm32/no-output + 9412 _Primitive-break-if-<-named/imm32/next + 9413 _Primitive-break-if-<-named: + 9414 "break-if-<"/imm32/name + 9415 Single-lit-var/imm32/inouts + 9416 0/imm32/outputs + 9417 "0f 8c/jump-if-<"/imm32/subx-name + 9418 0/imm32/no-rm32 + 9419 0/imm32/no-r32 + 9420 0/imm32/no-imm32 + 9421 1/imm32/disp32-is-first-inout + 9422 0/imm32/no-output + 9423 _Primitive-break-if->=-named/imm32/next + 9424 _Primitive-break-if->=-named: + 9425 "break-if->="/imm32/name + 9426 Single-lit-var/imm32/inouts + 9427 0/imm32/outputs + 9428 "0f 8d/jump-if->="/imm32/subx-name + 9429 0/imm32/no-rm32 + 9430 0/imm32/no-r32 + 9431 0/imm32/no-imm32 + 9432 1/imm32/disp32-is-first-inout + 9433 0/imm32/no-output + 9434 _Primitive-break-if-<=-named/imm32/next + 9435 _Primitive-break-if-<=-named: + 9436 "break-if-<="/imm32/name + 9437 Single-lit-var/imm32/inouts + 9438 0/imm32/outputs + 9439 "0f 8e/jump-if-<="/imm32/subx-name + 9440 0/imm32/no-rm32 + 9441 0/imm32/no-r32 + 9442 0/imm32/no-imm32 + 9443 1/imm32/disp32-is-first-inout + 9444 0/imm32/no-output + 9445 _Primitive-break-if->-named/imm32/next + 9446 _Primitive-break-if->-named: + 9447 "break-if->"/imm32/name + 9448 Single-lit-var/imm32/inouts + 9449 0/imm32/outputs + 9450 "0f 8f/jump-if->"/imm32/subx-name + 9451 0/imm32/no-rm32 + 9452 0/imm32/no-r32 + 9453 0/imm32/no-imm32 + 9454 1/imm32/disp32-is-first-inout + 9455 0/imm32/no-output + 9456 _Primitive-break-named/imm32/next + 9457 _Primitive-break-named: + 9458 "break"/imm32/name + 9459 Single-lit-var/imm32/inouts + 9460 0/imm32/outputs + 9461 "e9/jump"/imm32/subx-name + 9462 0/imm32/no-rm32 + 9463 0/imm32/no-r32 + 9464 0/imm32/no-imm32 + 9465 1/imm32/disp32-is-first-inout + 9466 0/imm32/no-output + 9467 _Primitive-loop-if-addr<-named/imm32/next + 9468 _Primitive-loop-if-addr<-named: + 9469 "loop-if-addr<"/imm32/name + 9470 Single-lit-var/imm32/inouts + 9471 0/imm32/outputs + 9472 "0f 82/jump-if-addr<"/imm32/subx-name + 9473 0/imm32/no-rm32 + 9474 0/imm32/no-r32 + 9475 0/imm32/no-imm32 + 9476 1/imm32/disp32-is-first-inout + 9477 0/imm32/no-output + 9478 _Primitive-loop-if-addr>=-named/imm32/next + 9479 _Primitive-loop-if-addr>=-named: + 9480 "loop-if-addr>="/imm32/name + 9481 Single-lit-var/imm32/inouts + 9482 0/imm32/outputs + 9483 "0f 83/jump-if-addr>="/imm32/subx-name + 9484 0/imm32/no-rm32 + 9485 0/imm32/no-r32 + 9486 0/imm32/no-imm32 + 9487 1/imm32/disp32-is-first-inout + 9488 0/imm32/no-output + 9489 _Primitive-loop-if-=-named/imm32/next + 9490 _Primitive-loop-if-=-named: + 9491 "loop-if-="/imm32/name + 9492 Single-lit-var/imm32/inouts + 9493 0/imm32/outputs + 9494 "0f 84/jump-if-="/imm32/subx-name + 9495 0/imm32/no-rm32 + 9496 0/imm32/no-r32 + 9497 0/imm32/no-imm32 + 9498 1/imm32/disp32-is-first-inout + 9499 0/imm32/no-output + 9500 _Primitive-loop-if-!=-named/imm32/next + 9501 _Primitive-loop-if-!=-named: + 9502 "loop-if-!="/imm32/name + 9503 Single-lit-var/imm32/inouts + 9504 0/imm32/outputs + 9505 "0f 85/jump-if-!="/imm32/subx-name + 9506 0/imm32/no-rm32 + 9507 0/imm32/no-r32 + 9508 0/imm32/no-imm32 + 9509 1/imm32/disp32-is-first-inout + 9510 0/imm32/no-output + 9511 _Primitive-loop-if-addr<=-named/imm32/next + 9512 _Primitive-loop-if-addr<=-named: + 9513 "loop-if-addr<="/imm32/name + 9514 Single-lit-var/imm32/inouts + 9515 0/imm32/outputs + 9516 "0f 86/jump-if-addr<="/imm32/subx-name + 9517 0/imm32/no-rm32 + 9518 0/imm32/no-r32 + 9519 0/imm32/no-imm32 + 9520 1/imm32/disp32-is-first-inout + 9521 0/imm32/no-output + 9522 _Primitive-loop-if-addr>-named/imm32/next + 9523 _Primitive-loop-if-addr>-named: + 9524 "loop-if-addr>"/imm32/name + 9525 Single-lit-var/imm32/inouts + 9526 0/imm32/outputs + 9527 "0f 87/jump-if-addr>"/imm32/subx-name + 9528 0/imm32/no-rm32 + 9529 0/imm32/no-r32 + 9530 0/imm32/no-imm32 + 9531 1/imm32/disp32-is-first-inout + 9532 0/imm32/no-output + 9533 _Primitive-loop-if-<-named/imm32/next + 9534 _Primitive-loop-if-<-named: + 9535 "loop-if-<"/imm32/name + 9536 Single-lit-var/imm32/inouts + 9537 0/imm32/outputs + 9538 "0f 8c/jump-if-<"/imm32/subx-name + 9539 0/imm32/no-rm32 + 9540 0/imm32/no-r32 + 9541 0/imm32/no-imm32 + 9542 1/imm32/disp32-is-first-inout + 9543 0/imm32/no-output + 9544 _Primitive-loop-if->=-named/imm32/next + 9545 _Primitive-loop-if->=-named: + 9546 "loop-if->="/imm32/name + 9547 Single-lit-var/imm32/inouts + 9548 0/imm32/outputs + 9549 "0f 8d/jump-if->="/imm32/subx-name + 9550 0/imm32/no-rm32 + 9551 0/imm32/no-r32 + 9552 0/imm32/no-imm32 + 9553 1/imm32/disp32-is-first-inout + 9554 0/imm32/no-output + 9555 _Primitive-loop-if-<=-named/imm32/next + 9556 _Primitive-loop-if-<=-named: + 9557 "loop-if-<="/imm32/name + 9558 Single-lit-var/imm32/inouts + 9559 0/imm32/outputs + 9560 "0f 8e/jump-if-<="/imm32/subx-name + 9561 0/imm32/no-rm32 + 9562 0/imm32/no-r32 + 9563 0/imm32/no-imm32 + 9564 1/imm32/disp32-is-first-inout + 9565 0/imm32/no-output + 9566 _Primitive-loop-if->-named/imm32/next + 9567 _Primitive-loop-if->-named: + 9568 "loop-if->"/imm32/name + 9569 Single-lit-var/imm32/inouts + 9570 0/imm32/outputs + 9571 "0f 8f/jump-if->"/imm32/subx-name + 9572 0/imm32/no-rm32 + 9573 0/imm32/no-r32 + 9574 0/imm32/no-imm32 + 9575 1/imm32/disp32-is-first-inout + 9576 0/imm32/no-output + 9577 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break + 9578 _Primitive-loop-named: + 9579 "loop"/imm32/name + 9580 Single-lit-var/imm32/inouts + 9581 0/imm32/outputs + 9582 "e9/jump"/imm32/subx-name + 9583 0/imm32/no-rm32 + 9584 0/imm32/no-r32 + 9585 0/imm32/no-imm32 + 9586 1/imm32/disp32-is-first-inout + 9587 0/imm32/no-output + 9588 0/imm32/next + 9589 + 9590 Single-int-var-in-mem: + 9591 Int-var-in-mem/imm32 + 9592 0/imm32/next + 9593 + 9594 Int-var-in-mem: + 9595 "arg1"/imm32/name + 9596 Type-int/imm32 + 9597 1/imm32/some-block-depth + 9598 1/imm32/some-stack-offset + 9599 0/imm32/no-register + 9600 + 9601 Two-args-int-stack-int-reg: + 9602 Int-var-in-mem/imm32 + 9603 Single-int-var-in-some-register/imm32/next + 9604 + 9605 Two-args-int-reg-int-stack: + 9606 Int-var-in-some-register/imm32 + 9607 Single-int-var-in-mem/imm32/next + 9608 + 9609 Two-args-int-eax-int-literal: + 9610 Int-var-in-eax/imm32 + 9611 Single-lit-var/imm32/next + 9612 + 9613 Int-var-and-literal: + 9614 Int-var-in-mem/imm32 + 9615 Single-lit-var/imm32/next + 9616 + 9617 Int-var-in-register-and-literal: + 9618 Int-var-in-some-register/imm32 + 9619 Single-lit-var/imm32/next + 9620 + 9621 Single-int-var-in-some-register: + 9622 Int-var-in-some-register/imm32 + 9623 0/imm32/next + 9624 + 9625 Single-addr-var-in-some-register: + 9626 Addr-var-in-some-register/imm32 + 9627 0/imm32/next + 9628 + 9629 Int-var-in-some-register: + 9630 "arg1"/imm32/name + 9631 Type-int/imm32 + 9632 1/imm32/some-block-depth + 9633 0/imm32/no-stack-offset + 9634 Any-register/imm32 + 9635 + 9636 Addr-var-in-some-register: + 9637 "arg1"/imm32/name + 9638 Type-addr/imm32 + 9639 1/imm32/some-block-depth + 9640 0/imm32/no-stack-offset + 9641 Any-register/imm32 9642 - 9643 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) - 9644 # . prologue - 9645 55/push-ebp - 9646 89/<- %ebp 4/r32/esp - 9647 # . save registers - 9648 50/push-eax - 9649 51/push-ecx - 9650 # if (location == 0) return - 9651 81 7/subop/compare *(ebp+0xc) 0/imm32 - 9652 0f 84/jump-if-= $emit-subx-r32:end/disp32 - 9653 # var v/eax: (handle var) - 9654 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax - 9655 8b/-> *eax 0/r32/eax # Stmt-var-value - 9656 (maybe-get Registers *(eax+0x10) 8) # Var-register => eax: (addr register-index) - 9657 (write-buffered *(ebp+8) Space) - 9658 (print-int32-buffered *(ebp+8) *eax) - 9659 (write-buffered *(ebp+8) "/r32") - 9660 $emit-subx-r32:end: - 9661 # . restore registers - 9662 59/pop-to-ecx - 9663 58/pop-to-eax - 9664 # . epilogue - 9665 89/<- %esp 5/r32/ebp - 9666 5d/pop-to-ebp - 9667 c3/return + 9643 Single-int-var-in-eax: + 9644 Int-var-in-eax/imm32 + 9645 0/imm32/next + 9646 + 9647 Int-var-in-eax: + 9648 "arg1"/imm32/name + 9649 Type-int/imm32 + 9650 1/imm32/some-block-depth + 9651 0/imm32/no-stack-offset + 9652 "eax"/imm32/register + 9653 + 9654 Single-int-var-in-ecx: + 9655 Int-var-in-ecx/imm32 + 9656 0/imm32/next + 9657 + 9658 Int-var-in-ecx: + 9659 "arg1"/imm32/name + 9660 Type-int/imm32 + 9661 1/imm32/some-block-depth + 9662 0/imm32/no-stack-offset + 9663 "ecx"/imm32/register + 9664 + 9665 Single-int-var-in-edx: + 9666 Int-var-in-edx/imm32 + 9667 0/imm32/next 9668 - 9669 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) - 9670 # . prologue - 9671 55/push-ebp - 9672 89/<- %ebp 4/r32/esp - 9673 # . save registers - 9674 50/push-eax - 9675 51/push-ecx - 9676 # if (location == 0) return - 9677 81 7/subop/compare *(ebp+0xc) 0/imm32 - 9678 74/jump-if-= $emit-subx-imm32:end/disp8 - 9679 # var v/eax: (handle var) - 9680 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax - 9681 8b/-> *eax 0/r32/eax # Stmt-var-value - 9682 (write-buffered *(ebp+8) Space) - 9683 (write-buffered *(ebp+8) *eax) # Var-name - 9684 (write-buffered *(ebp+8) "/imm32") - 9685 $emit-subx-imm32:end: - 9686 # . restore registers - 9687 59/pop-to-ecx - 9688 58/pop-to-eax - 9689 # . epilogue - 9690 89/<- %esp 5/r32/ebp - 9691 5d/pop-to-ebp - 9692 c3/return - 9693 - 9694 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) - 9695 # . prologue - 9696 55/push-ebp - 9697 89/<- %ebp 4/r32/esp - 9698 # . save registers - 9699 50/push-eax - 9700 51/push-ecx - 9701 # if (location == 0) return - 9702 81 7/subop/compare *(ebp+0xc) 0/imm32 - 9703 0f 84/jump-if-= $emit-subx-disp32:end/disp32 - 9704 # var v/eax: (handle var) - 9705 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax - 9706 8b/-> *eax 0/r32/eax # Stmt-var-value - 9707 (write-buffered *(ebp+8) Space) - 9708 (write-buffered *(ebp+8) *eax) # Var-name - 9709 # hack: if instruction operation starts with "break", emit ":break" - 9710 # var name/ecx: (addr array byte) = stmt->operation - 9711 8b/-> *(ebp+0x10) 0/r32/eax - 9712 8b/-> *(eax+4) 1/r32/ecx - 9713 { - 9714 (string-starts-with? %ecx "break") # => eax - 9715 3d/compare-eax-and 0/imm32/false - 9716 74/jump-if-= break/disp8 - 9717 (write-buffered *(ebp+8) ":break") - 9718 } - 9719 # hack: if instruction operation starts with "loop", emit ":loop" - 9720 { - 9721 (string-starts-with? %ecx "loop") # => eax - 9722 3d/compare-eax-and 0/imm32/false - 9723 74/jump-if-= break/disp8 - 9724 (write-buffered *(ebp+8) ":loop") - 9725 } - 9726 (write-buffered *(ebp+8) "/disp32") - 9727 $emit-subx-disp32:end: - 9728 # . restore registers - 9729 59/pop-to-ecx - 9730 58/pop-to-eax - 9731 # . epilogue - 9732 89/<- %esp 5/r32/ebp - 9733 5d/pop-to-ebp - 9734 c3/return - 9735 - 9736 emit-subx-call: # out: (addr buffered-file), stmt: (handle stmt), callee: (handle function) + 9669 Int-var-in-edx: + 9670 "arg1"/imm32/name + 9671 Type-int/imm32 + 9672 1/imm32/some-block-depth + 9673 0/imm32/no-stack-offset + 9674 "edx"/imm32/register + 9675 + 9676 Single-int-var-in-ebx: + 9677 Int-var-in-ebx/imm32 + 9678 0/imm32/next + 9679 + 9680 Int-var-in-ebx: + 9681 "arg1"/imm32/name + 9682 Type-int/imm32 + 9683 1/imm32/some-block-depth + 9684 0/imm32/no-stack-offset + 9685 "ebx"/imm32/register + 9686 + 9687 Single-int-var-in-esi: + 9688 Int-var-in-esi/imm32 + 9689 0/imm32/next + 9690 + 9691 Int-var-in-esi: + 9692 "arg1"/imm32/name + 9693 Type-int/imm32 + 9694 1/imm32/some-block-depth + 9695 0/imm32/no-stack-offset + 9696 "esi"/imm32/register + 9697 + 9698 Single-int-var-in-edi: + 9699 Int-var-in-edi/imm32 + 9700 0/imm32/next + 9701 + 9702 Int-var-in-edi: + 9703 "arg1"/imm32/name + 9704 Type-int/imm32 + 9705 1/imm32/some-block-depth + 9706 0/imm32/no-stack-offset + 9707 "edi"/imm32/register + 9708 + 9709 Single-lit-var: + 9710 Lit-var/imm32 + 9711 0/imm32/next + 9712 + 9713 Lit-var: + 9714 "literal"/imm32/name + 9715 Type-literal/imm32 + 9716 1/imm32/some-block-depth + 9717 0/imm32/no-stack-offset + 9718 0/imm32/no-register + 9719 + 9720 Type-int: + 9721 1/imm32/left-is-atom + 9722 1/imm32/left/int + 9723 0/imm32/right/null + 9724 + 9725 Type-literal: + 9726 1/imm32/left-is-atom + 9727 0/imm32/left/literal + 9728 0/imm32/right/null + 9729 + 9730 Type-addr: + 9731 1/imm32/left-is-atom + 9732 2/imm32/left/addr + 9733 0/imm32/right/null + 9734 + 9735 == code + 9736 emit-subx-primitive: # out: (addr buffered-file), stmt: (handle stmt), primitive: (handle function) 9737 # . prologue 9738 55/push-ebp 9739 89/<- %ebp 4/r32/esp 9740 # . save registers - 9741 51/push-ecx - 9742 # - 9743 (emit-indent *(ebp+8) *Curr-block-depth) - 9744 (write-buffered *(ebp+8) "(") - 9745 # - emit function name - 9746 8b/-> *(ebp+0x10) 1/r32/ecx - 9747 (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name - 9748 # - emit arguments - 9749 # var curr/ecx: (handle stmt-var) = stmt->inouts - 9750 8b/-> *(ebp+0xc) 1/r32/ecx - 9751 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts - 9752 { - 9753 # if (curr == null) break - 9754 81 7/subop/compare %ecx 0/imm32 - 9755 74/jump-if-= break/disp8 - 9756 # - 9757 (emit-subx-call-operand *(ebp+8) %ecx) - 9758 # curr = curr->next - 9759 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next - 9760 eb/jump loop/disp8 - 9761 } - 9762 # - 9763 (write-buffered *(ebp+8) ")\n") - 9764 $emit-subx-call:end: - 9765 # . restore registers - 9766 59/pop-to-ecx - 9767 # . epilogue - 9768 89/<- %esp 5/r32/ebp - 9769 5d/pop-to-ebp - 9770 c3/return - 9771 - 9772 # like a function call, except we have no idea what function it is - 9773 # we hope it's defined in SubX and that the types are ok - 9774 emit-hailmary-call: # out: (addr buffered-file), stmt: (handle stmt) - 9775 # . prologue - 9776 55/push-ebp - 9777 89/<- %ebp 4/r32/esp - 9778 # . save registers - 9779 51/push-ecx - 9780 # - 9781 (emit-indent *(ebp+8) *Curr-block-depth) - 9782 (write-buffered *(ebp+8) "(") - 9783 # ecx = stmt - 9784 8b/-> *(ebp+0xc) 1/r32/ecx - 9785 # - emit function name - 9786 (write-buffered *(ebp+8) *(ecx+4)) # Stmt1-operation - 9787 # - emit arguments - 9788 # var curr/ecx: (handle stmt-var) = stmt->inouts - 9789 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts - 9790 { - 9791 # if (curr == null) break - 9792 81 7/subop/compare %ecx 0/imm32 - 9793 74/jump-if-= break/disp8 - 9794 # - 9795 (emit-subx-call-operand *(ebp+8) %ecx) - 9796 # curr = curr->next - 9797 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next - 9798 eb/jump loop/disp8 - 9799 } - 9800 # - 9801 (write-buffered *(ebp+8) ")\n") - 9802 $emit-hailmary-call:end: - 9803 # . restore registers - 9804 59/pop-to-ecx - 9805 # . epilogue - 9806 89/<- %esp 5/r32/ebp - 9807 5d/pop-to-ebp - 9808 c3/return - 9809 - 9810 emit-subx-call-operand: # out: (addr buffered-file), s: (handle stmt-var) - 9811 # shares code with emit-subx-var-as-rm32 - 9812 # . prologue - 9813 55/push-ebp - 9814 89/<- %ebp 4/r32/esp - 9815 # . save registers - 9816 50/push-eax - 9817 51/push-ecx - 9818 56/push-esi - 9819 # ecx = s - 9820 8b/-> *(ebp+0xc) 1/r32/ecx - 9821 # var operand/esi: (handle var) = s->value - 9822 8b/-> *ecx 6/r32/esi # Stmt-var-value - 9823 # if (operand->register && s->is-deref?) emit "*__" - 9824 { - 9825 $emit-subx-call-operand:check-for-register-indirect: - 9826 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register - 9827 74/jump-if-= break/disp8 - 9828 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref - 9829 74/jump-if-= break/disp8 - 9830 $emit-subx-call-operand:register-indirect: - 9831 (write-buffered *(ebp+8) " *") - 9832 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register - 9833 e9/jump $emit-subx-call-operand:end/disp32 - 9834 } - 9835 # if (operand->register && !s->is-deref?) emit "%__" - 9836 { - 9837 $emit-subx-call-operand:check-for-register-direct: - 9838 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register - 9839 74/jump-if-= break/disp8 - 9840 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref - 9841 75/jump-if-!= break/disp8 - 9842 $emit-subx-call-operand:register-direct: - 9843 (write-buffered *(ebp+8) " %") - 9844 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register - 9845 e9/jump $emit-subx-call-operand:end/disp32 - 9846 } - 9847 # else if (operand->stack-offset) emit "*(ebp+__)" - 9848 { - 9849 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-offset - 9850 74/jump-if-= break/disp8 - 9851 $emit-subx-call-operand:stack: - 9852 (write-buffered *(ebp+8) Space) - 9853 (write-buffered *(ebp+8) "*(ebp+") - 9854 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-offset - 9855 (write-buffered *(ebp+8) ")") - 9856 e9/jump $emit-subx-call-operand:end/disp32 - 9857 } - 9858 # else if (operand->type == literal) emit "__" - 9859 { - 9860 8b/-> *(esi+4) 0/r32/eax # Var-type - 9861 81 7/subop/compare *eax 0/imm32 # Tree-left - 9862 75/jump-if-!= break/disp8 - 9863 $emit-subx-call-operand:literal: - 9864 (write-buffered *(ebp+8) Space) - 9865 (write-buffered *(ebp+8) *esi) - 9866 } - 9867 $emit-subx-call-operand:end: - 9868 # . restore registers - 9869 5e/pop-to-esi - 9870 59/pop-to-ecx - 9871 58/pop-to-eax - 9872 # . epilogue - 9873 89/<- %esp 5/r32/ebp - 9874 5d/pop-to-ebp - 9875 c3/return - 9876 - 9877 emit-subx-var-as-rm32: # out: (addr buffered-file), s: (handle stmt-var) - 9878 # . prologue - 9879 55/push-ebp - 9880 89/<- %ebp 4/r32/esp - 9881 # . save registers - 9882 50/push-eax - 9883 51/push-ecx - 9884 56/push-esi - 9885 # ecx = s - 9886 8b/-> *(ebp+0xc) 1/r32/ecx - 9887 # var operand/esi: (handle var) = s->value - 9888 8b/-> *ecx 6/r32/esi # Stmt-var-value - 9889 # if (operand->register && s->is-deref?) emit "*__" - 9890 { - 9891 $emit-subx-var-as-rm32:check-for-register-indirect: - 9892 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register - 9893 74/jump-if-= break/disp8 - 9894 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref - 9895 74/jump-if-= break/disp8 - 9896 $emit-subx-var-as-rm32:register-indirect: - 9897 (write-buffered *(ebp+8) " *") - 9898 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register - 9899 } - 9900 # if (operand->register && !s->is-deref?) emit "%__" - 9901 { - 9902 $emit-subx-var-as-rm32:check-for-register-direct: - 9903 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register - 9904 74/jump-if-= break/disp8 - 9905 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref - 9906 75/jump-if-!= break/disp8 - 9907 $emit-subx-var-as-rm32:register-direct: - 9908 (write-buffered *(ebp+8) " %") - 9909 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register - 9910 } - 9911 # else if (operand->stack-offset) emit "*(ebp+__)" - 9912 { - 9913 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-offset - 9914 74/jump-if-= break/disp8 - 9915 $emit-subx-var-as-rm32:stack: - 9916 (write-buffered *(ebp+8) Space) - 9917 (write-buffered *(ebp+8) "*(ebp+") - 9918 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-offset - 9919 (write-buffered *(ebp+8) ")") - 9920 } - 9921 $emit-subx-var-as-rm32:end: - 9922 # . restore registers - 9923 5e/pop-to-esi - 9924 59/pop-to-ecx - 9925 58/pop-to-eax - 9926 # . epilogue - 9927 89/<- %esp 5/r32/ebp - 9928 5d/pop-to-ebp - 9929 c3/return - 9930 - 9931 find-matching-function: # functions: (addr function), stmt: (handle stmt) -> result/eax: (handle function) - 9932 # . prologue - 9933 55/push-ebp - 9934 89/<- %ebp 4/r32/esp - 9935 # . save registers - 9936 51/push-ecx - 9937 # var curr/ecx: (handle function) = functions - 9938 8b/-> *(ebp+8) 1/r32/ecx - 9939 { - 9940 # if (curr == null) break - 9941 81 7/subop/compare %ecx 0/imm32 - 9942 74/jump-if-= break/disp8 - 9943 # if match(stmt, curr) return curr - 9944 { - 9945 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax - 9946 3d/compare-eax-and 0/imm32/false - 9947 74/jump-if-= break/disp8 - 9948 89/<- %eax 1/r32/ecx - 9949 eb/jump $find-matching-function:end/disp8 - 9950 } - 9951 # curr = curr->next - 9952 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next - 9953 eb/jump loop/disp8 - 9954 } - 9955 # return null - 9956 b8/copy-to-eax 0/imm32 - 9957 $find-matching-function:end: - 9958 # . restore registers - 9959 59/pop-to-ecx - 9960 # . epilogue - 9961 89/<- %esp 5/r32/ebp - 9962 5d/pop-to-ebp - 9963 c3/return - 9964 - 9965 find-matching-primitive: # primitives: (handle primitive), stmt: (handle stmt) -> result/eax: (handle primitive) - 9966 # . prologue - 9967 55/push-ebp - 9968 89/<- %ebp 4/r32/esp - 9969 # . save registers - 9970 51/push-ecx - 9971 # var curr/ecx: (handle primitive) = primitives - 9972 8b/-> *(ebp+8) 1/r32/ecx - 9973 { - 9974 $find-matching-primitive:loop: - 9975 # if (curr == null) break - 9976 81 7/subop/compare %ecx 0/imm32 - 9977 0f 84/jump-if-= break/disp32 - 9978 #? (write-buffered Stderr "prim: ") - 9979 #? (write-buffered Stderr *ecx) # Primitive-name - 9980 #? (write-buffered Stderr " => ") - 9981 #? (write-buffered Stderr *(ecx+0xc)) # Primitive-subx-name - 9982 #? (write-buffered Stderr Newline) - 9983 #? (flush Stderr) - 9984 # if match(curr, stmt) return curr - 9985 { - 9986 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax - 9987 3d/compare-eax-and 0/imm32/false - 9988 74/jump-if-= break/disp8 - 9989 89/<- %eax 1/r32/ecx - 9990 eb/jump $find-matching-primitive:end/disp8 - 9991 } - 9992 $find-matching-primitive:next-primitive: - 9993 # curr = curr->next - 9994 8b/-> *(ecx+0x24) 1/r32/ecx # Primitive-next - 9995 e9/jump loop/disp32 + 9741 50/push-eax + 9742 51/push-ecx + 9743 # ecx = primitive + 9744 8b/-> *(ebp+0x10) 1/r32/ecx + 9745 # emit primitive name + 9746 (emit-indent *(ebp+8) *Curr-block-depth) + 9747 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name + 9748 # emit rm32 if necessary + 9749 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt + 9750 # emit r32 if necessary + 9751 (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt + 9752 # emit imm32 if necessary + 9753 (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt + 9754 # emit disp32 if necessary + 9755 (emit-subx-disp32 *(ebp+8) *(ecx+0x1c) *(ebp+0xc)) # out, Primitive-subx-disp32, stmt + 9756 (write-buffered *(ebp+8) Newline) + 9757 $emit-subx-primitive:end: + 9758 # . restore registers + 9759 59/pop-to-ecx + 9760 58/pop-to-eax + 9761 # . epilogue + 9762 89/<- %esp 5/r32/ebp + 9763 5d/pop-to-ebp + 9764 c3/return + 9765 + 9766 emit-subx-rm32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) + 9767 # . prologue + 9768 55/push-ebp + 9769 89/<- %ebp 4/r32/esp + 9770 # . save registers + 9771 50/push-eax + 9772 # if (l == 0) return + 9773 81 7/subop/compare *(ebp+0xc) 0/imm32 + 9774 74/jump-if-= $emit-subx-rm32:end/disp8 + 9775 # var v/eax: (handle var) + 9776 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax + 9777 (emit-subx-var-as-rm32 *(ebp+8) %eax) + 9778 $emit-subx-rm32:end: + 9779 # . restore registers + 9780 58/pop-to-eax + 9781 # . epilogue + 9782 89/<- %esp 5/r32/ebp + 9783 5d/pop-to-ebp + 9784 c3/return + 9785 + 9786 get-stmt-operand-from-arg-location: # stmt: (handle stmt), l: arg-location -> var/eax: (handle stmt-var) + 9787 # . prologue + 9788 55/push-ebp + 9789 89/<- %ebp 4/r32/esp + 9790 # . save registers + 9791 51/push-ecx + 9792 # eax = l + 9793 8b/-> *(ebp+0xc) 0/r32/eax + 9794 # ecx = stmt + 9795 8b/-> *(ebp+8) 1/r32/ecx + 9796 # if (l == 1) return stmt->inouts + 9797 { + 9798 3d/compare-eax-and 1/imm32 + 9799 75/jump-if-!= break/disp8 + 9800 $get-stmt-operand-from-arg-location:1: + 9801 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts + 9802 eb/jump $get-stmt-operand-from-arg-location:end/disp8 + 9803 } + 9804 # if (l == 2) return stmt->inouts->next + 9805 { + 9806 3d/compare-eax-and 2/imm32 + 9807 75/jump-if-!= break/disp8 + 9808 $get-stmt-operand-from-arg-location:2: + 9809 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts + 9810 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next + 9811 eb/jump $get-stmt-operand-from-arg-location:end/disp8 + 9812 } + 9813 # if (l == 3) return stmt->outputs + 9814 { + 9815 3d/compare-eax-and 3/imm32 + 9816 75/jump-if-!= break/disp8 + 9817 $get-stmt-operand-from-arg-location:3: + 9818 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs + 9819 eb/jump $get-stmt-operand-from-arg-location:end/disp8 + 9820 } + 9821 # abort + 9822 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 + 9823 $get-stmt-operand-from-arg-location:end: + 9824 # . restore registers + 9825 59/pop-to-ecx + 9826 # . epilogue + 9827 89/<- %esp 5/r32/ebp + 9828 5d/pop-to-ebp + 9829 c3/return + 9830 + 9831 $get-stmt-operand-from-arg-location:abort: + 9832 # error("invalid arg-location " eax) + 9833 (write-buffered Stderr "invalid arg-location ") + 9834 (print-int32-buffered Stderr %eax) + 9835 (write-buffered Stderr Newline) + 9836 (flush Stderr) + 9837 # . syscall(exit, 1) + 9838 bb/copy-to-ebx 1/imm32 + 9839 b8/copy-to-eax 1/imm32/exit + 9840 cd/syscall 0x80/imm8 + 9841 # never gets here + 9842 + 9843 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) + 9844 # . prologue + 9845 55/push-ebp + 9846 89/<- %ebp 4/r32/esp + 9847 # . save registers + 9848 50/push-eax + 9849 51/push-ecx + 9850 # if (location == 0) return + 9851 81 7/subop/compare *(ebp+0xc) 0/imm32 + 9852 0f 84/jump-if-= $emit-subx-r32:end/disp32 + 9853 # var v/eax: (handle var) + 9854 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax + 9855 8b/-> *eax 0/r32/eax # Stmt-var-value + 9856 (maybe-get Registers *(eax+0x10) 8) # Var-register => eax: (addr register-index) + 9857 (write-buffered *(ebp+8) Space) + 9858 (print-int32-buffered *(ebp+8) *eax) + 9859 (write-buffered *(ebp+8) "/r32") + 9860 $emit-subx-r32:end: + 9861 # . restore registers + 9862 59/pop-to-ecx + 9863 58/pop-to-eax + 9864 # . epilogue + 9865 89/<- %esp 5/r32/ebp + 9866 5d/pop-to-ebp + 9867 c3/return + 9868 + 9869 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) + 9870 # . prologue + 9871 55/push-ebp + 9872 89/<- %ebp 4/r32/esp + 9873 # . save registers + 9874 50/push-eax + 9875 51/push-ecx + 9876 # if (location == 0) return + 9877 81 7/subop/compare *(ebp+0xc) 0/imm32 + 9878 74/jump-if-= $emit-subx-imm32:end/disp8 + 9879 # var v/eax: (handle var) + 9880 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax + 9881 8b/-> *eax 0/r32/eax # Stmt-var-value + 9882 (write-buffered *(ebp+8) Space) + 9883 (write-buffered *(ebp+8) *eax) # Var-name + 9884 (write-buffered *(ebp+8) "/imm32") + 9885 $emit-subx-imm32:end: + 9886 # . restore registers + 9887 59/pop-to-ecx + 9888 58/pop-to-eax + 9889 # . epilogue + 9890 89/<- %esp 5/r32/ebp + 9891 5d/pop-to-ebp + 9892 c3/return + 9893 + 9894 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) + 9895 # . prologue + 9896 55/push-ebp + 9897 89/<- %ebp 4/r32/esp + 9898 # . save registers + 9899 50/push-eax + 9900 51/push-ecx + 9901 # if (location == 0) return + 9902 81 7/subop/compare *(ebp+0xc) 0/imm32 + 9903 0f 84/jump-if-= $emit-subx-disp32:end/disp32 + 9904 # var v/eax: (handle var) + 9905 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax + 9906 8b/-> *eax 0/r32/eax # Stmt-var-value + 9907 (write-buffered *(ebp+8) Space) + 9908 (write-buffered *(ebp+8) *eax) # Var-name + 9909 # hack: if instruction operation starts with "break", emit ":break" + 9910 # var name/ecx: (addr array byte) = stmt->operation + 9911 8b/-> *(ebp+0x10) 0/r32/eax + 9912 8b/-> *(eax+4) 1/r32/ecx + 9913 { + 9914 (string-starts-with? %ecx "break") # => eax + 9915 3d/compare-eax-and 0/imm32/false + 9916 74/jump-if-= break/disp8 + 9917 (write-buffered *(ebp+8) ":break") + 9918 } + 9919 # hack: if instruction operation starts with "loop", emit ":loop" + 9920 { + 9921 (string-starts-with? %ecx "loop") # => eax + 9922 3d/compare-eax-and 0/imm32/false + 9923 74/jump-if-= break/disp8 + 9924 (write-buffered *(ebp+8) ":loop") + 9925 } + 9926 (write-buffered *(ebp+8) "/disp32") + 9927 $emit-subx-disp32:end: + 9928 # . restore registers + 9929 59/pop-to-ecx + 9930 58/pop-to-eax + 9931 # . epilogue + 9932 89/<- %esp 5/r32/ebp + 9933 5d/pop-to-ebp + 9934 c3/return + 9935 + 9936 emit-call: # out: (addr buffered-file), stmt: (handle stmt) + 9937 # . prologue + 9938 55/push-ebp + 9939 89/<- %ebp 4/r32/esp + 9940 # . save registers + 9941 51/push-ecx + 9942 # + 9943 (emit-indent *(ebp+8) *Curr-block-depth) + 9944 (write-buffered *(ebp+8) "(") + 9945 # ecx = stmt + 9946 8b/-> *(ebp+0xc) 1/r32/ecx + 9947 # - emit function name + 9948 (write-buffered *(ebp+8) *(ecx+4)) # Stmt1-operation + 9949 # - emit arguments + 9950 # var curr/ecx: (handle stmt-var) = stmt->inouts + 9951 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts + 9952 { + 9953 # if (curr == null) break + 9954 81 7/subop/compare %ecx 0/imm32 + 9955 74/jump-if-= break/disp8 + 9956 # + 9957 (emit-subx-call-operand *(ebp+8) %ecx) + 9958 # curr = curr->next + 9959 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next + 9960 eb/jump loop/disp8 + 9961 } + 9962 # + 9963 (write-buffered *(ebp+8) ")\n") + 9964 $emit-call:end: + 9965 # . restore registers + 9966 59/pop-to-ecx + 9967 # . epilogue + 9968 89/<- %esp 5/r32/ebp + 9969 5d/pop-to-ebp + 9970 c3/return + 9971 + 9972 emit-subx-call-operand: # out: (addr buffered-file), s: (handle stmt-var) + 9973 # shares code with emit-subx-var-as-rm32 + 9974 # . prologue + 9975 55/push-ebp + 9976 89/<- %ebp 4/r32/esp + 9977 # . save registers + 9978 50/push-eax + 9979 51/push-ecx + 9980 56/push-esi + 9981 # ecx = s + 9982 8b/-> *(ebp+0xc) 1/r32/ecx + 9983 # var operand/esi: (handle var) = s->value + 9984 8b/-> *ecx 6/r32/esi # Stmt-var-value + 9985 # if (operand->register && !s->is-deref?) emit "%__" + 9986 { + 9987 $emit-subx-call-operand:check-for-register-direct: + 9988 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register + 9989 74/jump-if-= break/disp8 + 9990 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref + 9991 75/jump-if-!= break/disp8 + 9992 $emit-subx-call-operand:register-direct: + 9993 (write-buffered *(ebp+8) " %") + 9994 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register + 9995 e9/jump $emit-subx-call-operand:end/disp32 9996 } - 9997 # return null - 9998 b8/copy-to-eax 0/imm32 - 9999 $find-matching-primitive:end: -10000 # . restore registers -10001 59/pop-to-ecx -10002 # . epilogue -10003 89/<- %esp 5/r32/ebp -10004 5d/pop-to-ebp -10005 c3/return -10006 -10007 mu-stmt-matches-function?: # stmt: (handle stmt), function: (handle function) -> result/eax: boolean -10008 # . prologue -10009 55/push-ebp -10010 89/<- %ebp 4/r32/esp -10011 # . save registers -10012 51/push-ecx -10013 # return function->name == stmt->operation -10014 8b/-> *(ebp+8) 1/r32/ecx -10015 8b/-> *(ebp+0xc) 0/r32/eax -10016 (string-equal? *(ecx+4) *eax) # Stmt1-operation, Function-name => eax -10017 $mu-stmt-matches-function?:end: -10018 # . restore registers -10019 59/pop-to-ecx -10020 # . epilogue -10021 89/<- %esp 5/r32/ebp -10022 5d/pop-to-ebp -10023 c3/return -10024 -10025 mu-stmt-matches-primitive?: # stmt: (handle stmt), primitive: (handle primitive) -> result/eax: boolean -10026 # A mu stmt matches a primitive if the name matches, all the inout vars -10027 # match, and all the output vars match. -10028 # Vars match if types match and registers match. -10029 # In addition, a stmt output matches a primitive's output if types match -10030 # and the primitive has a wildcard register. -10031 # . prologue -10032 55/push-ebp -10033 89/<- %ebp 4/r32/esp -10034 # . save registers -10035 51/push-ecx -10036 52/push-edx -10037 53/push-ebx -10038 56/push-esi -10039 57/push-edi -10040 # ecx = stmt -10041 8b/-> *(ebp+8) 1/r32/ecx -10042 # edx = primitive -10043 8b/-> *(ebp+0xc) 2/r32/edx -10044 { -10045 $mu-stmt-matches-primitive?:check-name: -10046 # if (primitive->name != stmt->operation) return false -10047 (string-equal? *(ecx+4) *edx) # Stmt1-operation, Primitive-name => eax -10048 3d/compare-eax-and 0/imm32/false -10049 75/jump-if-!= break/disp8 -10050 b8/copy-to-eax 0/imm32 -10051 e9/jump $mu-stmt-matches-primitive?:end/disp32 -10052 } -10053 $mu-stmt-matches-primitive?:check-inouts: -10054 # for (curr/esi in stmt->inouts, curr2/edi in primitive->inouts) -10055 8b/-> *(ecx+8) 6/r32/esi # Stmt1-inouts or Regvardef-inouts -10056 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts -10057 { -10058 # if (curr == 0 && curr2 == 0) move on to check outputs -10059 { -10060 81 7/subop/compare %esi 0/imm32 -10061 75/jump-if-!= break/disp8 -10062 $mu-stmt-matches-primitive?:stmt-inout-is-null: -10063 { -10064 81 7/subop/compare %edi 0/imm32 -10065 75/jump-if-!= break/disp8 -10066 # -10067 e9/jump $mu-stmt-matches-primitive?:check-outputs/disp32 -10068 } -10069 # return false -10070 b8/copy-to-eax 0/imm32/false -10071 e9/jump $mu-stmt-matches-primitive?:end/disp32 -10072 } -10073 # if (curr2 == 0) return false -10074 { -10075 81 7/subop/compare %edi 0/imm32 -10076 75/jump-if-!= break/disp8 -10077 $mu-stmt-matches-primitive?:prim-inout-is-null: -10078 b8/copy-to-eax 0/imm32/false -10079 e9/jump $mu-stmt-matches-primitive?:end/disp32 -10080 } -10081 # if (curr != curr2) return false -10082 { -10083 (operand-matches-primitive? %esi *edi) # List-value => eax -10084 3d/compare-eax-and 0/imm32/false -10085 75/jump-if-!= break/disp8 -10086 b8/copy-to-eax 0/imm32/false -10087 e9/jump $mu-stmt-matches-primitive?:end/disp32 -10088 } -10089 # curr=curr->next -10090 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next -10091 # curr2=curr2->next -10092 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next -10093 eb/jump loop/disp8 -10094 } -10095 $mu-stmt-matches-primitive?:check-outputs: -10096 # for (curr/esi in stmt->outputs, curr2/edi in primitive->outputs) -10097 8b/-> *(ecx+0xc) 6/r32/esi # Stmt1-outputs -10098 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs -10099 { -10100 # if (curr == 0) return (curr2 == 0) -10101 { -10102 $mu-stmt-matches-primitive?:check-output: -10103 81 7/subop/compare %esi 0/imm32 -10104 75/jump-if-!= break/disp8 -10105 { -10106 81 7/subop/compare %edi 0/imm32 -10107 75/jump-if-!= break/disp8 -10108 # return true -10109 b8/copy-to-eax 1/imm32 -10110 e9/jump $mu-stmt-matches-primitive?:end/disp32 -10111 } -10112 # return false -10113 b8/copy-to-eax 0/imm32 -10114 e9/jump $mu-stmt-matches-primitive?:end/disp32 -10115 } -10116 # if (curr2 == 0) return false -10117 { -10118 81 7/subop/compare %edi 0/imm32 -10119 75/jump-if-!= break/disp8 -10120 b8/copy-to-eax 0/imm32 -10121 e9/jump $mu-stmt-matches-primitive?:end/disp32 -10122 } -10123 # if (curr != curr2) return false -10124 { -10125 (operand-matches-primitive? %esi *edi) # List-value => eax -10126 3d/compare-eax-and 0/imm32/false -10127 75/jump-if-!= break/disp8 -10128 b8/copy-to-eax 0/imm32 -10129 e9/jump $mu-stmt-matches-primitive?:end/disp32 -10130 } -10131 # curr=curr->next -10132 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next -10133 # curr2=curr2->next -10134 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next -10135 eb/jump loop/disp8 -10136 } -10137 $mu-stmt-matches-primitive?:return-true: -10138 b8/copy-to-eax 1/imm32 -10139 $mu-stmt-matches-primitive?:end: -10140 # . restore registers -10141 5f/pop-to-edi -10142 5e/pop-to-esi -10143 5b/pop-to-ebx -10144 5a/pop-to-edx -10145 59/pop-to-ecx -10146 # . epilogue -10147 89/<- %esp 5/r32/ebp -10148 5d/pop-to-ebp -10149 c3/return -10150 -10151 operand-matches-primitive?: # s: (handle stmt-var), prim-var: (handle var) -> result/eax: boolean -10152 # . prologue -10153 55/push-ebp -10154 89/<- %ebp 4/r32/esp -10155 # . save registers -10156 51/push-ecx -10157 56/push-esi -10158 57/push-edi -10159 # ecx = s -10160 8b/-> *(ebp+8) 1/r32/ecx -10161 # var var/esi : (handle var) = s->value -10162 8b/-> *ecx 6/r32/esi # Stmt-var-value -10163 # edi = prim-var -10164 8b/-> *(ebp+0xc) 7/r32/edi -10165 $operand-matches-primitive?:check-type: -10166 # if (var->type != prim-var->type) return false -10167 (subx-type-equal? *(esi+4) *(edi+4)) # Var-type, Var-type => eax -10168 3d/compare-eax-and 0/imm32/false -10169 b8/copy-to-eax 0/imm32/false -10170 0f 84/jump-if-= $operand-matches-primitive?:end/disp32 -10171 { -10172 $operand-matches-primitive?:check-register: -10173 # if prim-var is in memory and var is in register but dereference, match -10174 { -10175 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register -10176 0f 85/jump-if-!= break/disp32 -10177 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register -10178 74/jump-if-= break/disp8 -10179 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref -10180 74/jump-if-= break/disp8 -10181 e9/jump $operand-matches-primitive?:return-true/disp32 -10182 } -10183 # if prim-var is in register and var is in register but dereference, no match -10184 { -10185 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register -10186 0f 84/jump-if-= break/disp32 -10187 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register -10188 0f 84/jump-if-= break/disp32 -10189 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref -10190 74/jump-if-= break/disp8 -10191 e9/jump $operand-matches-primitive?:return-false/disp32 -10192 } -10193 # return false if var->register doesn't match prim-var->register -10194 { -10195 # if register addresses are equal, it's a match -10196 8b/-> *(esi+0x10) 0/r32/eax # Var-register -10197 39/compare *(edi+0x10) 0/r32/eax # Var-register -10198 74/jump-if-= break/disp8 -10199 # if either address is 0, return false -10200 3d/compare-eax-and 0/imm32 -10201 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result -10202 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register -10203 74/jump-if-= $operand-matches-primitive?:return-false/disp8 -10204 # if prim-var->register is wildcard, it's a match -10205 (string-equal? *(edi+0x10) Any-register) # Var-register => eax -10206 3d/compare-eax-and 0/imm32/false -10207 75/jump-if-!= break/disp8 -10208 # if string contents aren't equal, return false -10209 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register => eax -10210 3d/compare-eax-and 0/imm32/false -10211 74/jump-if-= $operand-matches-primitive?:return-false/disp8 -10212 } -10213 } -10214 $operand-matches-primitive?:return-true: -10215 b8/copy-to-eax 1/imm32/true -10216 eb/jump $operand-matches-primitive?:end/disp8 -10217 $operand-matches-primitive?:return-false: -10218 b8/copy-to-eax 0/imm32/false -10219 $operand-matches-primitive?:end: -10220 # . restore registers -10221 5f/pop-to-edi -10222 5e/pop-to-esi -10223 59/pop-to-ecx -10224 # . epilogue -10225 89/<- %esp 5/r32/ebp -10226 5d/pop-to-ebp -10227 c3/return -10228 -10229 subx-type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean -10230 # . prologue -10231 55/push-ebp -10232 89/<- %ebp 4/r32/esp -10233 # . save registers -10234 51/push-ecx -10235 # var alit/ecx: boolean = is-literal-type?(a) -10236 (is-simple-mu-type? *(ebp+8) 0) # => eax -10237 89/<- %ecx 0/r32/eax -10238 # var blit/eax: boolean = is-literal-type?(b) -10239 (is-simple-mu-type? *(ebp+0xc) 0) # => eax -10240 # return alit == blit -10241 39/compare %eax 1/r32/ecx -10242 0f 94/set-byte-if-= %al -10243 81 4/subop/and %eax 0xff/imm32 -10244 $subx-type-equal?:end: -10245 # . restore registers -10246 59/pop-to-ecx -10247 # . epilogue -10248 89/<- %esp 5/r32/ebp -10249 5d/pop-to-ebp -10250 c3/return -10251 -10252 is-simple-mu-type?: # a: (handle tree type-id), n: type-id -> result/eax: boolean -10253 # . prologue -10254 55/push-ebp -10255 89/<- %ebp 4/r32/esp -10256 # . save registers -10257 51/push-ecx -10258 # ecx = n -10259 8b/-> *(ebp+0xc) 1/r32/ecx -10260 # return (a->value == n) -10261 8b/-> *(ebp+8) 0/r32/eax -10262 39/compare *eax 1/r32/ecx # Atom-type -10263 0f 94/set-byte-if-= %al -10264 81 4/subop/and %eax 0xff/imm32 -10265 $is-simple-mu-type?:end: -10266 # . restore registers -10267 59/pop-to-ecx -10268 # . epilogue -10269 89/<- %esp 5/r32/ebp -10270 5d/pop-to-ebp -10271 c3/return -10272 -10273 test-emit-subx-stmt-primitive: -10274 # Primitive operation on a variable on the stack. -10275 # increment foo -10276 # => -10277 # ff 0/subop/increment *(ebp-8) -10278 # -10279 # There's a variable on the var stack as follows: -10280 # name: 'foo' -10281 # type: int -10282 # stack-offset: -8 -10283 # -10284 # There's a primitive with this info: -10285 # name: 'increment' -10286 # inouts: int/mem -10287 # value: 'ff 0/subop/increment' -10288 # -10289 # There's nothing in functions. -10290 # -10291 # . prologue -10292 55/push-ebp -10293 89/<- %ebp 4/r32/esp -10294 # setup -10295 (clear-stream _test-output-stream) -10296 (clear-stream $_test-output-buffered-file->buffer) -10297 # var type/ecx: (handle tree type-id) = int -10298 68/push 0/imm32/right/null -10299 68/push 1/imm32/left/int -10300 89/<- %ecx 4/r32/esp -10301 # var var-foo/ecx: var -10302 68/push 0/imm32/no-register -10303 68/push -8/imm32/stack-offset -10304 68/push 1/imm32/block-depth -10305 51/push-ecx -10306 68/push "foo"/imm32 -10307 89/<- %ecx 4/r32/esp -10308 # var operand/ebx: (handle stmt-var) -10309 68/push 0/imm32/is-deref:false -10310 68/push 0/imm32/next -10311 51/push-ecx/var-foo -10312 89/<- %ebx 4/r32/esp -10313 # var stmt/esi: statement -10314 68/push 0/imm32/next -10315 68/push 0/imm32/outputs -10316 53/push-ebx/operands -10317 68/push "increment"/imm32/operation -10318 68/push 1/imm32 -10319 89/<- %esi 4/r32/esp -10320 # var primitives/ebx: primitive -10321 68/push 0/imm32/next -10322 68/push 0/imm32/output-is-write-only -10323 68/push 0/imm32/no-disp32 -10324 68/push 0/imm32/no-imm32 -10325 68/push 0/imm32/no-r32 -10326 68/push 1/imm32/rm32-is-first-inout -10327 68/push "ff 0/subop/increment"/imm32/subx-name -10328 68/push 0/imm32/outputs -10329 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call -10330 68/push "increment"/imm32/name -10331 89/<- %ebx 4/r32/esp -10332 # convert -10333 c7 0/subop/copy *Curr-block-depth 0/imm32 -10334 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) -10335 (flush _test-output-buffered-file) -10336 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10342 # check output -10343 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive") -10344 # . epilogue -10345 89/<- %esp 5/r32/ebp -10346 5d/pop-to-ebp -10347 c3/return -10348 -10349 test-emit-subx-stmt-primitive-register: -10350 # Primitive operation on a variable in a register. -10351 # foo <- increment -10352 # => -10353 # ff 0/subop/increment %eax # sub-optimal, but should suffice -10354 # -10355 # There's a variable on the var stack as follows: -10356 # name: 'foo' -10357 # type: int -10358 # register: 'eax' -10359 # -10360 # There's a primitive with this info: -10361 # name: 'increment' -10362 # out: int/reg -10363 # value: 'ff 0/subop/increment' -10364 # -10365 # There's nothing in functions. -10366 # -10367 # . prologue -10368 55/push-ebp -10369 89/<- %ebp 4/r32/esp -10370 # setup -10371 (clear-stream _test-output-stream) -10372 (clear-stream $_test-output-buffered-file->buffer) -10373 # var type/ecx: (handle tree type-id) = int -10374 68/push 0/imm32/right/null -10375 68/push 1/imm32/left/int -10376 89/<- %ecx 4/r32/esp -10377 # var var-foo/ecx: var in eax -10378 68/push "eax"/imm32/register -10379 68/push 0/imm32/no-stack-offset -10380 68/push 1/imm32/block-depth -10381 51/push-ecx -10382 68/push "foo"/imm32 -10383 89/<- %ecx 4/r32/esp -10384 # var operand/ebx: (handle stmt-var) -10385 68/push 0/imm32/is-deref:false -10386 68/push 0/imm32/next -10387 51/push-ecx/var-foo -10388 89/<- %ebx 4/r32/esp -10389 # var stmt/esi: statement -10390 68/push 0/imm32/next -10391 53/push-ebx/outputs -10392 68/push 0/imm32/inouts -10393 68/push "increment"/imm32/operation -10394 68/push 1/imm32 -10395 89/<- %esi 4/r32/esp -10396 # var formal-var/ebx: var in any register -10397 68/push Any-register/imm32 -10398 68/push 0/imm32/no-stack-offset -10399 68/push 1/imm32/block-depth -10400 ff 6/subop/push *(ecx+4) # Var-type -10401 68/push "dummy"/imm32 -10402 89/<- %ebx 4/r32/esp -10403 # var operand/ebx: (handle stmt-var) -10404 68/push 0/imm32/is-deref:false -10405 68/push 0/imm32/next -10406 53/push-ebx/formal-var -10407 89/<- %ebx 4/r32/esp -10408 # var primitives/ebx: primitive -10409 68/push 0/imm32/next -10410 68/push 0/imm32/output-is-write-only -10411 68/push 0/imm32/no-disp32 -10412 68/push 0/imm32/no-imm32 -10413 68/push 0/imm32/no-r32 -10414 68/push 3/imm32/rm32-in-first-output -10415 68/push "ff 0/subop/increment"/imm32/subx-name -10416 53/push-ebx/outputs -10417 68/push 0/imm32/inouts -10418 68/push "increment"/imm32/name -10419 89/<- %ebx 4/r32/esp -10420 # convert -10421 c7 0/subop/copy *Curr-block-depth 0/imm32 -10422 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) -10423 (flush _test-output-buffered-file) -10424 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10430 # check output -10431 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register") -10432 # . epilogue -10433 89/<- %esp 5/r32/ebp -10434 5d/pop-to-ebp -10435 c3/return -10436 -10437 test-emit-subx-stmt-select-primitive: -10438 # Select the right primitive between overloads. -10439 # foo <- increment -10440 # => -10441 # ff 0/subop/increment %eax # sub-optimal, but should suffice -10442 # -10443 # There's a variable on the var stack as follows: -10444 # name: 'foo' -10445 # type: int -10446 # register: 'eax' -10447 # -10448 # There's two primitives, as follows: -10449 # - name: 'increment' -10450 # out: int/reg -10451 # value: 'ff 0/subop/increment' -10452 # - name: 'increment' -10453 # inout: int/mem -10454 # value: 'ff 0/subop/increment' -10455 # -10456 # There's nothing in functions. -10457 # -10458 # . prologue -10459 55/push-ebp -10460 89/<- %ebp 4/r32/esp -10461 # setup -10462 (clear-stream _test-output-stream) -10463 (clear-stream $_test-output-buffered-file->buffer) -10464 # var type/ecx: (handle tree type-id) = int -10465 68/push 0/imm32/right/null -10466 68/push 1/imm32/left/int -10467 89/<- %ecx 4/r32/esp -10468 # var var-foo/ecx: var in eax -10469 68/push "eax"/imm32/register -10470 68/push 0/imm32/no-stack-offset -10471 68/push 1/imm32/block-depth -10472 51/push-ecx -10473 68/push "foo"/imm32 -10474 89/<- %ecx 4/r32/esp -10475 # var real-outputs/edi: (handle stmt-var) -10476 68/push 0/imm32/is-deref:false -10477 68/push 0/imm32/next -10478 51/push-ecx/var-foo -10479 89/<- %edi 4/r32/esp -10480 # var stmt/esi: statement -10481 68/push 0/imm32/next -10482 57/push-edi/outputs -10483 68/push 0/imm32/inouts -10484 68/push "increment"/imm32/operation -10485 68/push 1/imm32 -10486 89/<- %esi 4/r32/esp -10487 # var formal-var/ebx: var in any register -10488 68/push Any-register/imm32 -10489 68/push 0/imm32/no-stack-offset -10490 68/push 1/imm32/block-depth -10491 ff 6/subop/push *(ecx+4) # Var-type -10492 68/push "dummy"/imm32 -10493 89/<- %ebx 4/r32/esp -10494 # var formal-outputs/ebx: (handle stmt-var) -10495 68/push 0/imm32/is-deref:false + 9997 # else if (operand->register && s->is-deref?) emit "*__" + 9998 { + 9999 $emit-subx-call-operand:check-for-register-indirect: +10000 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +10001 74/jump-if-= break/disp8 +10002 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +10003 74/jump-if-= break/disp8 +10004 $emit-subx-call-operand:register-indirect: +10005 (emit-subx-call-operand-register-indirect *(ebp+8) %esi) +10006 e9/jump $emit-subx-call-operand:end/disp32 +10007 } +10008 # else if (operand->stack-offset) emit "*(ebp+__)" +10009 { +10010 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-offset +10011 74/jump-if-= break/disp8 +10012 $emit-subx-call-operand:stack: +10013 (emit-subx-call-operand-stack *(ebp+8) %esi) +10014 e9/jump $emit-subx-call-operand:end/disp32 +10015 } +10016 # else if (operand->type == literal) emit "__" +10017 { +10018 8b/-> *(esi+4) 0/r32/eax # Var-type +10019 81 7/subop/compare *(eax+4) 0/imm32 # Tree-left +10020 75/jump-if-!= break/disp8 +10021 $emit-subx-call-operand:literal: +10022 (write-buffered *(ebp+8) Space) +10023 (write-buffered *(ebp+8) *esi) +10024 } +10025 $emit-subx-call-operand:end: +10026 # . restore registers +10027 5e/pop-to-esi +10028 59/pop-to-ecx +10029 58/pop-to-eax +10030 # . epilogue +10031 89/<- %esp 5/r32/ebp +10032 5d/pop-to-ebp +10033 c3/return +10034 +10035 emit-subx-call-operand-register-indirect: # out: (addr buffered-file), v: (handle var) +10036 # . prologue +10037 55/push-ebp +10038 89/<- %ebp 4/r32/esp +10039 # . save registers +10040 50/push-eax +10041 51/push-ecx +10042 56/push-esi +10043 # esi = v +10044 8b/-> *(ebp+0xc) 6/r32/esi +10045 # var size/ecx: int = size-of-deref(v) +10046 (size-of-deref %esi) # => eax +10047 89/<- %ecx 0/r32/eax +10048 # TODO: assert size is a multiple of 4 +10049 # var i/eax: int = 0 +10050 b8/copy-to-eax 0/imm32 +10051 { +10052 $emit-subx-call-operand-register-indirect:loop: +10053 # if (i >= size) break +10054 39/compare %eax 1/r32/ecx +10055 7d/jump-if->= break/disp8 +10056 # emit " *(" v->register "+" i ")" +10057 (write-buffered *(ebp+8) " *(") +10058 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register +10059 (write-buffered *(ebp+8) "+") +10060 (print-int32-buffered *(ebp+8) %eax) +10061 (write-buffered *(ebp+8) ")") +10062 # i += 4 +10063 05/add-to-eax 4/imm32 +10064 # +10065 eb/jump loop/disp8 +10066 } +10067 $emit-subx-call-operand-register-indirect:end: +10068 # . restore registers +10069 5e/pop-to-esi +10070 59/pop-to-ecx +10071 58/pop-to-eax +10072 # . epilogue +10073 89/<- %esp 5/r32/ebp +10074 5d/pop-to-ebp +10075 c3/return +10076 +10077 emit-subx-call-operand-stack: # out: (addr buffered-file), v: (handle var) +10078 # . prologue +10079 55/push-ebp +10080 89/<- %ebp 4/r32/esp +10081 # . save registers +10082 50/push-eax +10083 51/push-ecx +10084 56/push-esi +10085 # esi = v +10086 8b/-> *(ebp+0xc) 6/r32/esi +10087 # var curr/ecx: int = v->offset +10088 8b/-> *(esi+0xc) 1/r32/ecx # Var-offset +10089 # var max/eax: int = v->offset + size-of(v) +10090 (size-of %esi) # => eax +10091 # TODO: assert size is a multiple of 4 +10092 01/add-to %eax 1/r32/ecx +10093 { +10094 $emit-subx-call-operand-stack:loop: +10095 # if (curr >= max) break +10096 39/compare %ecx 0/r32/eax +10097 7d/jump-if->= break/disp8 +10098 # emit " *(ebp+" curr ")" +10099 (write-buffered *(ebp+8) " *(ebp+") +10100 (print-int32-buffered *(ebp+8) %ecx) +10101 (write-buffered *(ebp+8) ")") +10102 # i += 4 +10103 81 0/subop/add %ecx 4/imm32 +10104 # +10105 eb/jump loop/disp8 +10106 } +10107 $emit-subx-call-operand-stack:end: +10108 # . restore registers +10109 5e/pop-to-esi +10110 59/pop-to-ecx +10111 58/pop-to-eax +10112 # . epilogue +10113 89/<- %esp 5/r32/ebp +10114 5d/pop-to-ebp +10115 c3/return +10116 +10117 emit-subx-var-as-rm32: # out: (addr buffered-file), s: (handle stmt-var) +10118 # . prologue +10119 55/push-ebp +10120 89/<- %ebp 4/r32/esp +10121 # . save registers +10122 50/push-eax +10123 51/push-ecx +10124 56/push-esi +10125 # ecx = s +10126 8b/-> *(ebp+0xc) 1/r32/ecx +10127 # var operand/esi: (handle var) = s->value +10128 8b/-> *ecx 6/r32/esi # Stmt-var-value +10129 # if (operand->register && s->is-deref?) emit "*__" +10130 { +10131 $emit-subx-var-as-rm32:check-for-register-indirect: +10132 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +10133 74/jump-if-= break/disp8 +10134 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +10135 74/jump-if-= break/disp8 +10136 $emit-subx-var-as-rm32:register-indirect: +10137 (write-buffered *(ebp+8) " *") +10138 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register +10139 } +10140 # if (operand->register && !s->is-deref?) emit "%__" +10141 { +10142 $emit-subx-var-as-rm32:check-for-register-direct: +10143 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +10144 74/jump-if-= break/disp8 +10145 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +10146 75/jump-if-!= break/disp8 +10147 $emit-subx-var-as-rm32:register-direct: +10148 (write-buffered *(ebp+8) " %") +10149 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register +10150 } +10151 # else if (operand->stack-offset) emit "*(ebp+__)" +10152 { +10153 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-offset +10154 74/jump-if-= break/disp8 +10155 $emit-subx-var-as-rm32:stack: +10156 (write-buffered *(ebp+8) Space) +10157 (write-buffered *(ebp+8) "*(ebp+") +10158 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-offset +10159 (write-buffered *(ebp+8) ")") +10160 } +10161 $emit-subx-var-as-rm32:end: +10162 # . restore registers +10163 5e/pop-to-esi +10164 59/pop-to-ecx +10165 58/pop-to-eax +10166 # . epilogue +10167 89/<- %esp 5/r32/ebp +10168 5d/pop-to-ebp +10169 c3/return +10170 +10171 find-matching-primitive: # primitives: (handle primitive), stmt: (handle stmt) -> result/eax: (handle primitive) +10172 # . prologue +10173 55/push-ebp +10174 89/<- %ebp 4/r32/esp +10175 # . save registers +10176 51/push-ecx +10177 # var curr/ecx: (handle primitive) = primitives +10178 8b/-> *(ebp+8) 1/r32/ecx +10179 { +10180 $find-matching-primitive:loop: +10181 # if (curr == null) break +10182 81 7/subop/compare %ecx 0/imm32 +10183 0f 84/jump-if-= break/disp32 +10184 # if match(curr, stmt) return curr +10185 { +10186 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax +10187 3d/compare-eax-and 0/imm32/false +10188 74/jump-if-= break/disp8 +10189 89/<- %eax 1/r32/ecx +10190 eb/jump $find-matching-primitive:end/disp8 +10191 } +10192 $find-matching-primitive:next-primitive: +10193 # curr = curr->next +10194 8b/-> *(ecx+0x24) 1/r32/ecx # Primitive-next +10195 e9/jump loop/disp32 +10196 } +10197 # return null +10198 b8/copy-to-eax 0/imm32 +10199 $find-matching-primitive:end: +10200 # . restore registers +10201 59/pop-to-ecx +10202 # . epilogue +10203 89/<- %esp 5/r32/ebp +10204 5d/pop-to-ebp +10205 c3/return +10206 +10207 mu-stmt-matches-primitive?: # stmt: (handle stmt), primitive: (handle primitive) -> result/eax: boolean +10208 # A mu stmt matches a primitive if the name matches, all the inout vars +10209 # match, and all the output vars match. +10210 # Vars match if types match and registers match. +10211 # In addition, a stmt output matches a primitive's output if types match +10212 # and the primitive has a wildcard register. +10213 # . prologue +10214 55/push-ebp +10215 89/<- %ebp 4/r32/esp +10216 # . save registers +10217 51/push-ecx +10218 52/push-edx +10219 53/push-ebx +10220 56/push-esi +10221 57/push-edi +10222 # ecx = stmt +10223 8b/-> *(ebp+8) 1/r32/ecx +10224 # edx = primitive +10225 8b/-> *(ebp+0xc) 2/r32/edx +10226 { +10227 $mu-stmt-matches-primitive?:check-name: +10228 # if (primitive->name != stmt->operation) return false +10229 (string-equal? *(ecx+4) *edx) # Stmt1-operation, Primitive-name => eax +10230 3d/compare-eax-and 0/imm32/false +10231 75/jump-if-!= break/disp8 +10232 b8/copy-to-eax 0/imm32 +10233 e9/jump $mu-stmt-matches-primitive?:end/disp32 +10234 } +10235 $mu-stmt-matches-primitive?:check-inouts: +10236 # for (curr/esi in stmt->inouts, curr2/edi in primitive->inouts) +10237 8b/-> *(ecx+8) 6/r32/esi # Stmt1-inouts or Regvardef-inouts +10238 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts +10239 { +10240 # if (curr == 0 && curr2 == 0) move on to check outputs +10241 { +10242 81 7/subop/compare %esi 0/imm32 +10243 75/jump-if-!= break/disp8 +10244 $mu-stmt-matches-primitive?:stmt-inout-is-null: +10245 { +10246 81 7/subop/compare %edi 0/imm32 +10247 75/jump-if-!= break/disp8 +10248 # +10249 e9/jump $mu-stmt-matches-primitive?:check-outputs/disp32 +10250 } +10251 # return false +10252 b8/copy-to-eax 0/imm32/false +10253 e9/jump $mu-stmt-matches-primitive?:end/disp32 +10254 } +10255 # if (curr2 == 0) return false +10256 { +10257 81 7/subop/compare %edi 0/imm32 +10258 75/jump-if-!= break/disp8 +10259 $mu-stmt-matches-primitive?:prim-inout-is-null: +10260 b8/copy-to-eax 0/imm32/false +10261 e9/jump $mu-stmt-matches-primitive?:end/disp32 +10262 } +10263 # if (curr != curr2) return false +10264 { +10265 (operand-matches-primitive? %esi *edi) # List-value => eax +10266 3d/compare-eax-and 0/imm32/false +10267 75/jump-if-!= break/disp8 +10268 b8/copy-to-eax 0/imm32/false +10269 e9/jump $mu-stmt-matches-primitive?:end/disp32 +10270 } +10271 # curr=curr->next +10272 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next +10273 # curr2=curr2->next +10274 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next +10275 eb/jump loop/disp8 +10276 } +10277 $mu-stmt-matches-primitive?:check-outputs: +10278 # for (curr/esi in stmt->outputs, curr2/edi in primitive->outputs) +10279 8b/-> *(ecx+0xc) 6/r32/esi # Stmt1-outputs +10280 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs +10281 { +10282 # if (curr == 0) return (curr2 == 0) +10283 { +10284 $mu-stmt-matches-primitive?:check-output: +10285 81 7/subop/compare %esi 0/imm32 +10286 75/jump-if-!= break/disp8 +10287 { +10288 81 7/subop/compare %edi 0/imm32 +10289 75/jump-if-!= break/disp8 +10290 # return true +10291 b8/copy-to-eax 1/imm32 +10292 e9/jump $mu-stmt-matches-primitive?:end/disp32 +10293 } +10294 # return false +10295 b8/copy-to-eax 0/imm32 +10296 e9/jump $mu-stmt-matches-primitive?:end/disp32 +10297 } +10298 # if (curr2 == 0) return false +10299 { +10300 81 7/subop/compare %edi 0/imm32 +10301 75/jump-if-!= break/disp8 +10302 b8/copy-to-eax 0/imm32 +10303 e9/jump $mu-stmt-matches-primitive?:end/disp32 +10304 } +10305 # if (curr != curr2) return false +10306 { +10307 (operand-matches-primitive? %esi *edi) # List-value => eax +10308 3d/compare-eax-and 0/imm32/false +10309 75/jump-if-!= break/disp8 +10310 b8/copy-to-eax 0/imm32 +10311 e9/jump $mu-stmt-matches-primitive?:end/disp32 +10312 } +10313 # curr=curr->next +10314 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next +10315 # curr2=curr2->next +10316 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next +10317 eb/jump loop/disp8 +10318 } +10319 $mu-stmt-matches-primitive?:return-true: +10320 b8/copy-to-eax 1/imm32 +10321 $mu-stmt-matches-primitive?:end: +10322 # . restore registers +10323 5f/pop-to-edi +10324 5e/pop-to-esi +10325 5b/pop-to-ebx +10326 5a/pop-to-edx +10327 59/pop-to-ecx +10328 # . epilogue +10329 89/<- %esp 5/r32/ebp +10330 5d/pop-to-ebp +10331 c3/return +10332 +10333 operand-matches-primitive?: # s: (handle stmt-var), prim-var: (handle var) -> result/eax: boolean +10334 # . prologue +10335 55/push-ebp +10336 89/<- %ebp 4/r32/esp +10337 # . save registers +10338 51/push-ecx +10339 56/push-esi +10340 57/push-edi +10341 # ecx = s +10342 8b/-> *(ebp+8) 1/r32/ecx +10343 # var var/esi : (handle var) = s->value +10344 8b/-> *ecx 6/r32/esi # Stmt-var-value +10345 # edi = prim-var +10346 8b/-> *(ebp+0xc) 7/r32/edi +10347 $operand-matches-primitive?:check-type: +10348 # if (var->type != prim-var->type) return false +10349 (subx-type-equal? *(esi+4) *(edi+4)) # Var-type, Var-type => eax +10350 3d/compare-eax-and 0/imm32/false +10351 b8/copy-to-eax 0/imm32/false +10352 0f 84/jump-if-= $operand-matches-primitive?:end/disp32 +10353 { +10354 $operand-matches-primitive?:check-register: +10355 # if prim-var is in memory and var is in register but dereference, match +10356 { +10357 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register +10358 0f 85/jump-if-!= break/disp32 +10359 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +10360 74/jump-if-= break/disp8 +10361 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +10362 74/jump-if-= break/disp8 +10363 e9/jump $operand-matches-primitive?:return-true/disp32 +10364 } +10365 # if prim-var is in register and var is in register but dereference, no match +10366 { +10367 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register +10368 0f 84/jump-if-= break/disp32 +10369 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +10370 0f 84/jump-if-= break/disp32 +10371 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +10372 74/jump-if-= break/disp8 +10373 e9/jump $operand-matches-primitive?:return-false/disp32 +10374 } +10375 # return false if var->register doesn't match prim-var->register +10376 { +10377 # if register addresses are equal, it's a match +10378 8b/-> *(esi+0x10) 0/r32/eax # Var-register +10379 39/compare *(edi+0x10) 0/r32/eax # Var-register +10380 74/jump-if-= break/disp8 +10381 # if either address is 0, return false +10382 3d/compare-eax-and 0/imm32 +10383 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result +10384 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register +10385 74/jump-if-= $operand-matches-primitive?:return-false/disp8 +10386 # if prim-var->register is wildcard, it's a match +10387 (string-equal? *(edi+0x10) Any-register) # Var-register => eax +10388 3d/compare-eax-and 0/imm32/false +10389 75/jump-if-!= break/disp8 +10390 # if string contents aren't equal, return false +10391 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register => eax +10392 3d/compare-eax-and 0/imm32/false +10393 74/jump-if-= $operand-matches-primitive?:return-false/disp8 +10394 } +10395 } +10396 $operand-matches-primitive?:return-true: +10397 b8/copy-to-eax 1/imm32/true +10398 eb/jump $operand-matches-primitive?:end/disp8 +10399 $operand-matches-primitive?:return-false: +10400 b8/copy-to-eax 0/imm32/false +10401 $operand-matches-primitive?:end: +10402 # . restore registers +10403 5f/pop-to-edi +10404 5e/pop-to-esi +10405 59/pop-to-ecx +10406 # . epilogue +10407 89/<- %esp 5/r32/ebp +10408 5d/pop-to-ebp +10409 c3/return +10410 +10411 subx-type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean +10412 # . prologue +10413 55/push-ebp +10414 89/<- %ebp 4/r32/esp +10415 # . save registers +10416 51/push-ecx +10417 # var alit/ecx: boolean = is-literal-type?(a) +10418 (is-simple-mu-type? *(ebp+8) 0) # => eax +10419 89/<- %ecx 0/r32/eax +10420 # var blit/eax: boolean = is-literal-type?(b) +10421 (is-simple-mu-type? *(ebp+0xc) 0) # => eax +10422 # return alit == blit +10423 39/compare %eax 1/r32/ecx +10424 0f 94/set-byte-if-= %al +10425 81 4/subop/and %eax 0xff/imm32 +10426 $subx-type-equal?:end: +10427 # . restore registers +10428 59/pop-to-ecx +10429 # . epilogue +10430 89/<- %esp 5/r32/ebp +10431 5d/pop-to-ebp +10432 c3/return +10433 +10434 is-simple-mu-type?: # a: (handle tree type-id), n: type-id -> result/eax: boolean +10435 # . prologue +10436 55/push-ebp +10437 89/<- %ebp 4/r32/esp +10438 # . save registers +10439 51/push-ecx +10440 # ecx = n +10441 8b/-> *(ebp+0xc) 1/r32/ecx +10442 # return (a->value == n) +10443 8b/-> *(ebp+8) 0/r32/eax +10444 39/compare *(eax+4) 1/r32/ecx # Tree-value +10445 0f 94/set-byte-if-= %al +10446 81 4/subop/and %eax 0xff/imm32 +10447 $is-simple-mu-type?:end: +10448 # . restore registers +10449 59/pop-to-ecx +10450 # . epilogue +10451 89/<- %esp 5/r32/ebp +10452 5d/pop-to-ebp +10453 c3/return +10454 +10455 test-emit-subx-stmt-primitive: +10456 # Primitive operation on a variable on the stack. +10457 # increment foo +10458 # => +10459 # ff 0/subop/increment *(ebp-8) +10460 # +10461 # There's a variable on the var stack as follows: +10462 # name: 'foo' +10463 # type: int +10464 # stack-offset: -8 +10465 # +10466 # There's a primitive with this info: +10467 # name: 'increment' +10468 # inouts: int/mem +10469 # value: 'ff 0/subop/increment' +10470 # +10471 # There's nothing in functions. +10472 # +10473 # . prologue +10474 55/push-ebp +10475 89/<- %ebp 4/r32/esp +10476 # setup +10477 (clear-stream _test-output-stream) +10478 (clear-stream $_test-output-buffered-file->buffer) +10479 # var type/ecx: (handle tree type-id) = int +10480 68/push 0/imm32/right/null +10481 68/push 1/imm32/left/int +10482 89/<- %ecx 4/r32/esp +10483 # var var-foo/ecx: var +10484 68/push 0/imm32/no-register +10485 68/push -8/imm32/stack-offset +10486 68/push 1/imm32/block-depth +10487 51/push-ecx +10488 68/push "foo"/imm32 +10489 89/<- %ecx 4/r32/esp +10490 # var operand/ebx: (handle stmt-var) +10491 68/push 0/imm32/is-deref:false +10492 68/push 0/imm32/next +10493 51/push-ecx/var-foo +10494 89/<- %ebx 4/r32/esp +10495 # var stmt/esi: statement 10496 68/push 0/imm32/next -10497 53/push-ebx/formal-var -10498 89/<- %ebx 4/r32/esp -10499 # var primitive1/ebx: primitive -10500 68/push 0/imm32/next -10501 68/push 0/imm32/output-is-write-only -10502 68/push 0/imm32/no-disp32 -10503 68/push 0/imm32/no-imm32 -10504 68/push 0/imm32/no-r32 -10505 68/push 3/imm32/rm32-in-first-output -10506 68/push "ff 0/subop/increment"/imm32/subx-name -10507 53/push-ebx/outputs/formal-outputs -10508 68/push 0/imm32/inouts -10509 68/push "increment"/imm32/name -10510 89/<- %ebx 4/r32/esp -10511 # var primitives/ebx: primitive -10512 53/push-ebx/next -10513 68/push 0/imm32/output-is-write-only -10514 68/push 0/imm32/no-disp32 -10515 68/push 0/imm32/no-imm32 -10516 68/push 0/imm32/no-r32 -10517 68/push 1/imm32/rm32-is-first-inout -10518 68/push "ff 0/subop/increment"/imm32/subx-name -10519 68/push 0/imm32/outputs -10520 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -10521 68/push "increment"/imm32/name -10522 89/<- %ebx 4/r32/esp -10523 # convert -10524 c7 0/subop/copy *Curr-block-depth 0/imm32 -10525 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) -10526 (flush _test-output-buffered-file) -10527 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10533 # check output -10534 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive") -10535 # . epilogue -10536 89/<- %esp 5/r32/ebp -10537 5d/pop-to-ebp -10538 c3/return -10539 -10540 test-emit-subx-stmt-select-primitive-2: -10541 # Select the right primitive between overloads. -10542 # foo <- increment -10543 # => -10544 # ff 0/subop/increment %eax # sub-optimal, but should suffice -10545 # -10546 # There's a variable on the var stack as follows: -10547 # name: 'foo' -10548 # type: int -10549 # register: 'eax' -10550 # -10551 # There's two primitives, as follows: -10552 # - name: 'increment' -10553 # out: int/reg -10554 # value: 'ff 0/subop/increment' -10555 # - name: 'increment' -10556 # inout: int/mem -10557 # value: 'ff 0/subop/increment' -10558 # -10559 # There's nothing in functions. -10560 # -10561 # . prologue -10562 55/push-ebp -10563 89/<- %ebp 4/r32/esp -10564 # setup -10565 (clear-stream _test-output-stream) -10566 (clear-stream $_test-output-buffered-file->buffer) -10567 # var type/ecx: (handle tree type-id) = int -10568 68/push 0/imm32/right/null -10569 68/push 1/imm32/left/int -10570 89/<- %ecx 4/r32/esp -10571 # var var-foo/ecx: var in eax -10572 68/push "eax"/imm32/register -10573 68/push 0/imm32/no-stack-offset -10574 68/push 1/imm32/block-depth -10575 51/push-ecx -10576 68/push "foo"/imm32 -10577 89/<- %ecx 4/r32/esp -10578 # var inouts/edi: (handle stmt-var) -10579 68/push 0/imm32/is-deref:false -10580 68/push 0/imm32/next -10581 51/push-ecx/var-foo -10582 89/<- %edi 4/r32/esp -10583 # var stmt/esi: statement -10584 68/push 0/imm32/next -10585 68/push 0/imm32/outputs -10586 57/push-edi/inouts -10587 68/push "increment"/imm32/operation -10588 68/push 1/imm32 -10589 89/<- %esi 4/r32/esp -10590 # var formal-var/ebx: var in any register -10591 68/push Any-register/imm32 -10592 68/push 0/imm32/no-stack-offset -10593 68/push 1/imm32/block-depth -10594 ff 6/subop/push *(ecx+4) # Var-type -10595 68/push "dummy"/imm32 -10596 89/<- %ebx 4/r32/esp -10597 # var operand/ebx: (handle stmt-var) -10598 68/push 0/imm32/is-deref:false -10599 68/push 0/imm32/next -10600 53/push-ebx/formal-var +10497 68/push 0/imm32/outputs +10498 53/push-ebx/operands +10499 68/push "increment"/imm32/operation +10500 68/push 1/imm32 +10501 89/<- %esi 4/r32/esp +10502 # var primitives/ebx: primitive +10503 68/push 0/imm32/next +10504 68/push 0/imm32/output-is-write-only +10505 68/push 0/imm32/no-disp32 +10506 68/push 0/imm32/no-imm32 +10507 68/push 0/imm32/no-r32 +10508 68/push 1/imm32/rm32-is-first-inout +10509 68/push "ff 0/subop/increment"/imm32/subx-name +10510 68/push 0/imm32/outputs +10511 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call +10512 68/push "increment"/imm32/name +10513 89/<- %ebx 4/r32/esp +10514 # convert +10515 c7 0/subop/copy *Curr-block-depth 0/imm32 +10516 (emit-subx-stmt _test-output-buffered-file %esi %ebx) +10517 (flush _test-output-buffered-file) +10518 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +10524 # check output +10525 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive") +10526 # . epilogue +10527 89/<- %esp 5/r32/ebp +10528 5d/pop-to-ebp +10529 c3/return +10530 +10531 test-emit-subx-stmt-primitive-register: +10532 # Primitive operation on a variable in a register. +10533 # foo <- increment +10534 # => +10535 # ff 0/subop/increment %eax # sub-optimal, but should suffice +10536 # +10537 # There's a variable on the var stack as follows: +10538 # name: 'foo' +10539 # type: int +10540 # register: 'eax' +10541 # +10542 # There's a primitive with this info: +10543 # name: 'increment' +10544 # out: int/reg +10545 # value: 'ff 0/subop/increment' +10546 # +10547 # There's nothing in functions. +10548 # +10549 # . prologue +10550 55/push-ebp +10551 89/<- %ebp 4/r32/esp +10552 # setup +10553 (clear-stream _test-output-stream) +10554 (clear-stream $_test-output-buffered-file->buffer) +10555 # var type/ecx: (handle tree type-id) = int +10556 68/push 0/imm32/right/null +10557 68/push 1/imm32/left/int +10558 89/<- %ecx 4/r32/esp +10559 # var var-foo/ecx: var in eax +10560 68/push "eax"/imm32/register +10561 68/push 0/imm32/no-stack-offset +10562 68/push 1/imm32/block-depth +10563 51/push-ecx +10564 68/push "foo"/imm32 +10565 89/<- %ecx 4/r32/esp +10566 # var operand/ebx: (handle stmt-var) +10567 68/push 0/imm32/is-deref:false +10568 68/push 0/imm32/next +10569 51/push-ecx/var-foo +10570 89/<- %ebx 4/r32/esp +10571 # var stmt/esi: statement +10572 68/push 0/imm32/next +10573 53/push-ebx/outputs +10574 68/push 0/imm32/inouts +10575 68/push "increment"/imm32/operation +10576 68/push 1/imm32 +10577 89/<- %esi 4/r32/esp +10578 # var formal-var/ebx: var in any register +10579 68/push Any-register/imm32 +10580 68/push 0/imm32/no-stack-offset +10581 68/push 1/imm32/block-depth +10582 ff 6/subop/push *(ecx+4) # Var-type +10583 68/push "dummy"/imm32 +10584 89/<- %ebx 4/r32/esp +10585 # var operand/ebx: (handle stmt-var) +10586 68/push 0/imm32/is-deref:false +10587 68/push 0/imm32/next +10588 53/push-ebx/formal-var +10589 89/<- %ebx 4/r32/esp +10590 # var primitives/ebx: primitive +10591 68/push 0/imm32/next +10592 68/push 0/imm32/output-is-write-only +10593 68/push 0/imm32/no-disp32 +10594 68/push 0/imm32/no-imm32 +10595 68/push 0/imm32/no-r32 +10596 68/push 3/imm32/rm32-in-first-output +10597 68/push "ff 0/subop/increment"/imm32/subx-name +10598 53/push-ebx/outputs +10599 68/push 0/imm32/inouts +10600 68/push "increment"/imm32/name 10601 89/<- %ebx 4/r32/esp -10602 # var primitive1/ebx: primitive -10603 68/push 0/imm32/next -10604 68/push 0/imm32/output-is-write-only -10605 68/push 0/imm32/no-disp32 -10606 68/push 0/imm32/no-imm32 -10607 68/push 0/imm32/no-r32 -10608 68/push 3/imm32/rm32-in-first-output -10609 68/push "ff 0/subop/increment"/imm32/subx-name -10610 53/push-ebx/outputs/formal-outputs -10611 68/push 0/imm32/inouts -10612 68/push "increment"/imm32/name -10613 89/<- %ebx 4/r32/esp -10614 # var primitives/ebx: primitive -10615 53/push-ebx/next -10616 68/push 0/imm32/output-is-write-only -10617 68/push 0/imm32/no-disp32 -10618 68/push 0/imm32/no-imm32 -10619 68/push 0/imm32/no-r32 -10620 68/push 1/imm32/rm32-is-first-inout -10621 68/push "ff 0/subop/increment"/imm32/subx-name -10622 68/push 0/imm32/outputs -10623 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -10624 68/push "increment"/imm32/name -10625 89/<- %ebx 4/r32/esp -10626 # convert -10627 c7 0/subop/copy *Curr-block-depth 0/imm32 -10628 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) -10629 (flush _test-output-buffered-file) -10630 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10636 # check output -10637 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2") -10638 # . epilogue -10639 89/<- %esp 5/r32/ebp -10640 5d/pop-to-ebp -10641 c3/return -10642 -10643 test-increment-register: -10644 # Select the right register between overloads. -10645 # foo <- increment -10646 # => -10647 # 50/increment-eax -10648 # -10649 # There's a variable on the var stack as follows: -10650 # name: 'foo' -10651 # type: int -10652 # register: 'eax' -10653 # -10654 # Primitives are the global definitions. -10655 # -10656 # There are no functions defined. -10657 # -10658 # . prologue -10659 55/push-ebp -10660 89/<- %ebp 4/r32/esp -10661 # setup -10662 (clear-stream _test-output-stream) -10663 (clear-stream $_test-output-buffered-file->buffer) -10664 # var type/ecx: (handle tree type-id) = int -10665 68/push 0/imm32/right/null -10666 68/push 1/imm32/left/int -10667 89/<- %ecx 4/r32/esp -10668 # var var-foo/ecx: var in eax -10669 68/push "eax"/imm32/register -10670 68/push 0/imm32/no-stack-offset -10671 68/push 1/imm32/block-depth -10672 51/push-ecx -10673 68/push "foo"/imm32 -10674 89/<- %ecx 4/r32/esp -10675 # var real-outputs/edi: (handle stmt-var) -10676 68/push 0/imm32/is-deref:false -10677 68/push 0/imm32/next -10678 51/push-ecx/var-foo -10679 89/<- %edi 4/r32/esp -10680 # var stmt/esi: statement -10681 68/push 0/imm32/next -10682 57/push-edi/outputs -10683 68/push 0/imm32/inouts -10684 68/push "increment"/imm32/operation -10685 68/push 1/imm32/regular-stmt -10686 89/<- %esi 4/r32/esp -10687 # convert -10688 c7 0/subop/copy *Curr-block-depth 0/imm32 -10689 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -10690 (flush _test-output-buffered-file) -10691 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10697 # check output -10698 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") -10699 # . epilogue -10700 89/<- %esp 5/r32/ebp -10701 5d/pop-to-ebp -10702 c3/return -10703 -10704 test-increment-var: -10705 # Select the right primitive between overloads. -10706 # foo <- increment -10707 # => -10708 # ff 0/subop/increment %eax # sub-optimal, but should suffice -10709 # -10710 # There's a variable on the var stack as follows: -10711 # name: 'foo' -10712 # type: int -10713 # register: 'eax' -10714 # -10715 # Primitives are the global definitions. -10716 # -10717 # There are no functions defined. -10718 # -10719 # . prologue -10720 55/push-ebp -10721 89/<- %ebp 4/r32/esp -10722 # setup -10723 (clear-stream _test-output-stream) -10724 (clear-stream $_test-output-buffered-file->buffer) -10725 # var type/ecx: (handle tree type-id) = int -10726 68/push 0/imm32/right/null -10727 68/push 1/imm32/left/int -10728 89/<- %ecx 4/r32/esp -10729 # var var-foo/ecx: var in eax -10730 68/push "eax"/imm32/register -10731 68/push 0/imm32/no-stack-offset -10732 68/push 1/imm32/block-depth -10733 51/push-ecx -10734 68/push "foo"/imm32 -10735 89/<- %ecx 4/r32/esp -10736 # var inouts/edi: (handle stmt-var) -10737 68/push 0/imm32/is-deref:false -10738 68/push 0/imm32/next -10739 51/push-ecx/var-foo -10740 89/<- %edi 4/r32/esp -10741 # var stmt/esi: statement -10742 68/push 0/imm32/next -10743 57/push-edi/outputs -10744 68/push 0/imm32/inouts -10745 68/push "increment"/imm32/operation -10746 68/push 1/imm32 -10747 89/<- %esi 4/r32/esp -10748 # convert -10749 c7 0/subop/copy *Curr-block-depth 0/imm32 -10750 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -10751 (flush _test-output-buffered-file) -10752 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10758 # check output -10759 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-var") -10760 # . epilogue -10761 89/<- %esp 5/r32/ebp -10762 5d/pop-to-ebp -10763 c3/return -10764 -10765 test-add-reg-to-reg: -10766 # var1/reg <- add var2/reg -10767 # => -10768 # 01/add %var1 var2 -10769 # -10770 # . prologue -10771 55/push-ebp -10772 89/<- %ebp 4/r32/esp -10773 # setup -10774 (clear-stream _test-output-stream) -10775 (clear-stream $_test-output-buffered-file->buffer) -10776 # var type/ecx: (handle tree type-id) = int -10777 68/push 0/imm32/right/null -10778 68/push 1/imm32/left/int -10779 89/<- %ecx 4/r32/esp -10780 # var var-var1/ecx: var in eax -10781 68/push "eax"/imm32/register -10782 68/push 0/imm32/no-stack-offset -10783 68/push 1/imm32/block-depth -10784 51/push-ecx -10785 68/push "var1"/imm32 -10786 89/<- %ecx 4/r32/esp -10787 # var var-var2/edx: var in ecx -10788 68/push "ecx"/imm32/register -10789 68/push 0/imm32/no-stack-offset -10790 68/push 1/imm32/block-depth -10791 ff 6/subop/push *(ecx+4) # Var-type -10792 68/push "var2"/imm32 -10793 89/<- %edx 4/r32/esp -10794 # var inouts/esi: (handle stmt-var) = [var2] -10795 68/push 0/imm32/is-deref:false -10796 68/push 0/imm32/next -10797 52/push-edx/var-var2 -10798 89/<- %esi 4/r32/esp -10799 # var outputs/edi: (handle stmt-var) = [var1, var2] -10800 68/push 0/imm32/is-deref:false -10801 68/push 0/imm32/next -10802 51/push-ecx/var-var1 -10803 89/<- %edi 4/r32/esp -10804 # var stmt/esi: statement -10805 68/push 0/imm32/next -10806 57/push-edi/outputs -10807 56/push-esi/inouts -10808 68/push "add"/imm32/operation -10809 68/push 1/imm32 -10810 89/<- %esi 4/r32/esp -10811 # convert -10812 c7 0/subop/copy *Curr-block-depth 0/imm32 -10813 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -10814 (flush _test-output-buffered-file) -10815 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10821 # check output -10822 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") -10823 # . epilogue -10824 89/<- %esp 5/r32/ebp -10825 5d/pop-to-ebp -10826 c3/return -10827 -10828 test-add-reg-to-mem: -10829 # add-to var1 var2/reg -10830 # => -10831 # 01/add *(ebp+__) var2 -10832 # -10833 # . prologue -10834 55/push-ebp -10835 89/<- %ebp 4/r32/esp -10836 # setup -10837 (clear-stream _test-output-stream) -10838 (clear-stream $_test-output-buffered-file->buffer) -10839 # var type/ecx: (handle tree type-id) = int -10840 68/push 0/imm32/right/null -10841 68/push 1/imm32/left/int -10842 89/<- %ecx 4/r32/esp -10843 # var var-var1/ecx: var -10844 68/push 0/imm32/no-register -10845 68/push 8/imm32/stack-offset -10846 68/push 1/imm32/block-depth -10847 51/push-ecx -10848 68/push "var1"/imm32 -10849 89/<- %ecx 4/r32/esp -10850 # var var-var2/edx: var in ecx -10851 68/push "ecx"/imm32/register -10852 68/push 0/imm32/no-stack-offset -10853 68/push 1/imm32/block-depth -10854 ff 6/subop/push *(ecx+4) # Var-type -10855 68/push "var2"/imm32 -10856 89/<- %edx 4/r32/esp -10857 # var inouts/esi: (handle stmt-var) = [var2] -10858 68/push 0/imm32/is-deref:false -10859 68/push 0/imm32/next -10860 52/push-edx/var-var2 -10861 89/<- %esi 4/r32/esp -10862 # var inouts = (handle stmt-var) = [var1, var2] -10863 56/push-esi/next -10864 51/push-ecx/var-var1 -10865 89/<- %esi 4/r32/esp -10866 # var stmt/esi: statement -10867 68/push 0/imm32/next -10868 68/push 0/imm32/outputs -10869 56/push-esi/inouts -10870 68/push "add-to"/imm32/operation -10871 68/push 1/imm32 -10872 89/<- %esi 4/r32/esp -10873 # convert -10874 c7 0/subop/copy *Curr-block-depth 0/imm32 -10875 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -10876 (flush _test-output-buffered-file) -10877 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10883 # check output -10884 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") -10885 # . epilogue -10886 89/<- %esp 5/r32/ebp -10887 5d/pop-to-ebp -10888 c3/return -10889 -10890 test-add-mem-to-reg: -10891 # var1/reg <- add var2 -10892 # => -10893 # 03/add *(ebp+__) var1 -10894 # -10895 # . prologue -10896 55/push-ebp -10897 89/<- %ebp 4/r32/esp -10898 # setup -10899 (clear-stream _test-output-stream) -10900 (clear-stream $_test-output-buffered-file->buffer) -10901 # var type/ecx: (handle tree type-id) = int -10902 68/push 0/imm32/right/null -10903 68/push 1/imm32/left/int -10904 89/<- %ecx 4/r32/esp -10905 # var var-var1/ecx: var in eax -10906 68/push "eax"/imm32/register -10907 68/push 0/imm32/no-stack-offset -10908 68/push 1/imm32/block-depth -10909 51/push-ecx -10910 68/push "var1"/imm32 -10911 89/<- %ecx 4/r32/esp -10912 # var var-var2/edx: var -10913 68/push 0/imm32/no-register -10914 68/push 8/imm32/stack-offset -10915 68/push 1/imm32/block-depth -10916 ff 6/subop/push *(ecx+4) # Var-type -10917 68/push "var2"/imm32 -10918 89/<- %edx 4/r32/esp -10919 # var inouts/esi: (handle stmt-var) = [var2] -10920 68/push 0/imm32/is-deref:false -10921 68/push 0/imm32/next -10922 52/push-edx/var-var2 -10923 89/<- %esi 4/r32/esp -10924 # var outputs/edi = (handle stmt-var) = [var1] -10925 68/push 0/imm32/is-deref:false +10602 # convert +10603 c7 0/subop/copy *Curr-block-depth 0/imm32 +10604 (emit-subx-stmt _test-output-buffered-file %esi %ebx) +10605 (flush _test-output-buffered-file) +10606 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +10612 # check output +10613 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register") +10614 # . epilogue +10615 89/<- %esp 5/r32/ebp +10616 5d/pop-to-ebp +10617 c3/return +10618 +10619 test-emit-subx-stmt-select-primitive: +10620 # Select the right primitive between overloads. +10621 # foo <- increment +10622 # => +10623 # ff 0/subop/increment %eax # sub-optimal, but should suffice +10624 # +10625 # There's a variable on the var stack as follows: +10626 # name: 'foo' +10627 # type: int +10628 # register: 'eax' +10629 # +10630 # There's two primitives, as follows: +10631 # - name: 'increment' +10632 # out: int/reg +10633 # value: 'ff 0/subop/increment' +10634 # - name: 'increment' +10635 # inout: int/mem +10636 # value: 'ff 0/subop/increment' +10637 # +10638 # There's nothing in functions. +10639 # +10640 # . prologue +10641 55/push-ebp +10642 89/<- %ebp 4/r32/esp +10643 # setup +10644 (clear-stream _test-output-stream) +10645 (clear-stream $_test-output-buffered-file->buffer) +10646 # var type/ecx: (handle tree type-id) = int +10647 68/push 0/imm32/right/null +10648 68/push 1/imm32/left/int +10649 89/<- %ecx 4/r32/esp +10650 # var var-foo/ecx: var in eax +10651 68/push "eax"/imm32/register +10652 68/push 0/imm32/no-stack-offset +10653 68/push 1/imm32/block-depth +10654 51/push-ecx +10655 68/push "foo"/imm32 +10656 89/<- %ecx 4/r32/esp +10657 # var real-outputs/edi: (handle stmt-var) +10658 68/push 0/imm32/is-deref:false +10659 68/push 0/imm32/next +10660 51/push-ecx/var-foo +10661 89/<- %edi 4/r32/esp +10662 # var stmt/esi: statement +10663 68/push 0/imm32/next +10664 57/push-edi/outputs +10665 68/push 0/imm32/inouts +10666 68/push "increment"/imm32/operation +10667 68/push 1/imm32 +10668 89/<- %esi 4/r32/esp +10669 # var formal-var/ebx: var in any register +10670 68/push Any-register/imm32 +10671 68/push 0/imm32/no-stack-offset +10672 68/push 1/imm32/block-depth +10673 ff 6/subop/push *(ecx+4) # Var-type +10674 68/push "dummy"/imm32 +10675 89/<- %ebx 4/r32/esp +10676 # var formal-outputs/ebx: (handle stmt-var) +10677 68/push 0/imm32/is-deref:false +10678 68/push 0/imm32/next +10679 53/push-ebx/formal-var +10680 89/<- %ebx 4/r32/esp +10681 # var primitive1/ebx: primitive +10682 68/push 0/imm32/next +10683 68/push 0/imm32/output-is-write-only +10684 68/push 0/imm32/no-disp32 +10685 68/push 0/imm32/no-imm32 +10686 68/push 0/imm32/no-r32 +10687 68/push 3/imm32/rm32-in-first-output +10688 68/push "ff 0/subop/increment"/imm32/subx-name +10689 53/push-ebx/outputs/formal-outputs +10690 68/push 0/imm32/inouts +10691 68/push "increment"/imm32/name +10692 89/<- %ebx 4/r32/esp +10693 # var primitives/ebx: primitive +10694 53/push-ebx/next +10695 68/push 0/imm32/output-is-write-only +10696 68/push 0/imm32/no-disp32 +10697 68/push 0/imm32/no-imm32 +10698 68/push 0/imm32/no-r32 +10699 68/push 1/imm32/rm32-is-first-inout +10700 68/push "ff 0/subop/increment"/imm32/subx-name +10701 68/push 0/imm32/outputs +10702 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call +10703 68/push "increment"/imm32/name +10704 89/<- %ebx 4/r32/esp +10705 # convert +10706 c7 0/subop/copy *Curr-block-depth 0/imm32 +10707 (emit-subx-stmt _test-output-buffered-file %esi %ebx) +10708 (flush _test-output-buffered-file) +10709 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +10715 # check output +10716 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive") +10717 # . epilogue +10718 89/<- %esp 5/r32/ebp +10719 5d/pop-to-ebp +10720 c3/return +10721 +10722 test-emit-subx-stmt-select-primitive-2: +10723 # Select the right primitive between overloads. +10724 # foo <- increment +10725 # => +10726 # ff 0/subop/increment %eax # sub-optimal, but should suffice +10727 # +10728 # There's a variable on the var stack as follows: +10729 # name: 'foo' +10730 # type: int +10731 # register: 'eax' +10732 # +10733 # There's two primitives, as follows: +10734 # - name: 'increment' +10735 # out: int/reg +10736 # value: 'ff 0/subop/increment' +10737 # - name: 'increment' +10738 # inout: int/mem +10739 # value: 'ff 0/subop/increment' +10740 # +10741 # There's nothing in functions. +10742 # +10743 # . prologue +10744 55/push-ebp +10745 89/<- %ebp 4/r32/esp +10746 # setup +10747 (clear-stream _test-output-stream) +10748 (clear-stream $_test-output-buffered-file->buffer) +10749 # var type/ecx: (handle tree type-id) = int +10750 68/push 0/imm32/right/null +10751 68/push 1/imm32/left/int +10752 89/<- %ecx 4/r32/esp +10753 # var var-foo/ecx: var in eax +10754 68/push "eax"/imm32/register +10755 68/push 0/imm32/no-stack-offset +10756 68/push 1/imm32/block-depth +10757 51/push-ecx +10758 68/push "foo"/imm32 +10759 89/<- %ecx 4/r32/esp +10760 # var inouts/edi: (handle stmt-var) +10761 68/push 0/imm32/is-deref:false +10762 68/push 0/imm32/next +10763 51/push-ecx/var-foo +10764 89/<- %edi 4/r32/esp +10765 # var stmt/esi: statement +10766 68/push 0/imm32/next +10767 68/push 0/imm32/outputs +10768 57/push-edi/inouts +10769 68/push "increment"/imm32/operation +10770 68/push 1/imm32 +10771 89/<- %esi 4/r32/esp +10772 # var formal-var/ebx: var in any register +10773 68/push Any-register/imm32 +10774 68/push 0/imm32/no-stack-offset +10775 68/push 1/imm32/block-depth +10776 ff 6/subop/push *(ecx+4) # Var-type +10777 68/push "dummy"/imm32 +10778 89/<- %ebx 4/r32/esp +10779 # var operand/ebx: (handle stmt-var) +10780 68/push 0/imm32/is-deref:false +10781 68/push 0/imm32/next +10782 53/push-ebx/formal-var +10783 89/<- %ebx 4/r32/esp +10784 # var primitive1/ebx: primitive +10785 68/push 0/imm32/next +10786 68/push 0/imm32/output-is-write-only +10787 68/push 0/imm32/no-disp32 +10788 68/push 0/imm32/no-imm32 +10789 68/push 0/imm32/no-r32 +10790 68/push 3/imm32/rm32-in-first-output +10791 68/push "ff 0/subop/increment"/imm32/subx-name +10792 53/push-ebx/outputs/formal-outputs +10793 68/push 0/imm32/inouts +10794 68/push "increment"/imm32/name +10795 89/<- %ebx 4/r32/esp +10796 # var primitives/ebx: primitive +10797 53/push-ebx/next +10798 68/push 0/imm32/output-is-write-only +10799 68/push 0/imm32/no-disp32 +10800 68/push 0/imm32/no-imm32 +10801 68/push 0/imm32/no-r32 +10802 68/push 1/imm32/rm32-is-first-inout +10803 68/push "ff 0/subop/increment"/imm32/subx-name +10804 68/push 0/imm32/outputs +10805 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call +10806 68/push "increment"/imm32/name +10807 89/<- %ebx 4/r32/esp +10808 # convert +10809 c7 0/subop/copy *Curr-block-depth 0/imm32 +10810 (emit-subx-stmt _test-output-buffered-file %esi %ebx) +10811 (flush _test-output-buffered-file) +10812 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +10818 # check output +10819 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2") +10820 # . epilogue +10821 89/<- %esp 5/r32/ebp +10822 5d/pop-to-ebp +10823 c3/return +10824 +10825 test-increment-register: +10826 # Select the right register between overloads. +10827 # foo <- increment +10828 # => +10829 # 50/increment-eax +10830 # +10831 # There's a variable on the var stack as follows: +10832 # name: 'foo' +10833 # type: int +10834 # register: 'eax' +10835 # +10836 # Primitives are the global definitions. +10837 # +10838 # There are no functions defined. +10839 # +10840 # . prologue +10841 55/push-ebp +10842 89/<- %ebp 4/r32/esp +10843 # setup +10844 (clear-stream _test-output-stream) +10845 (clear-stream $_test-output-buffered-file->buffer) +10846 # var type/ecx: (handle tree type-id) = int +10847 68/push 0/imm32/right/null +10848 68/push 1/imm32/left/int +10849 68/push 1/imm32/is-atom +10850 89/<- %ecx 4/r32/esp +10851 # var var-foo/ecx: var in eax +10852 68/push "eax"/imm32/register +10853 68/push 0/imm32/no-stack-offset +10854 68/push 1/imm32/block-depth +10855 51/push-ecx +10856 68/push "foo"/imm32 +10857 89/<- %ecx 4/r32/esp +10858 # var real-outputs/edi: (handle stmt-var) +10859 68/push 0/imm32/is-deref:false +10860 68/push 0/imm32/next +10861 51/push-ecx/var-foo +10862 89/<- %edi 4/r32/esp +10863 # var stmt/esi: statement +10864 68/push 0/imm32/next +10865 57/push-edi/outputs +10866 68/push 0/imm32/inouts +10867 68/push "increment"/imm32/operation +10868 68/push 1/imm32/regular-stmt +10869 89/<- %esi 4/r32/esp +10870 # convert +10871 c7 0/subop/copy *Curr-block-depth 0/imm32 +10872 (emit-subx-stmt _test-output-buffered-file %esi Primitives) +10873 (flush _test-output-buffered-file) +10874 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +10880 # check output +10881 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") +10882 # . epilogue +10883 89/<- %esp 5/r32/ebp +10884 5d/pop-to-ebp +10885 c3/return +10886 +10887 test-increment-var: +10888 # Select the right primitive between overloads. +10889 # foo <- increment +10890 # => +10891 # ff 0/subop/increment %eax # sub-optimal, but should suffice +10892 # +10893 # There's a variable on the var stack as follows: +10894 # name: 'foo' +10895 # type: int +10896 # register: 'eax' +10897 # +10898 # Primitives are the global definitions. +10899 # +10900 # There are no functions defined. +10901 # +10902 # . prologue +10903 55/push-ebp +10904 89/<- %ebp 4/r32/esp +10905 # setup +10906 (clear-stream _test-output-stream) +10907 (clear-stream $_test-output-buffered-file->buffer) +10908 # var type/ecx: (handle tree type-id) = int +10909 68/push 0/imm32/right/null +10910 68/push 1/imm32/left/int +10911 68/push 1/imm32/is-atom +10912 89/<- %ecx 4/r32/esp +10913 # var var-foo/ecx: var in eax +10914 68/push "eax"/imm32/register +10915 68/push 0/imm32/no-stack-offset +10916 68/push 1/imm32/block-depth +10917 51/push-ecx +10918 68/push "foo"/imm32 +10919 89/<- %ecx 4/r32/esp +10920 # var inouts/edi: (handle stmt-var) +10921 68/push 0/imm32/is-deref:false +10922 68/push 0/imm32/next +10923 51/push-ecx/var-foo +10924 89/<- %edi 4/r32/esp +10925 # var stmt/esi: statement 10926 68/push 0/imm32/next -10927 51/push-ecx/var-var1 -10928 89/<- %edi 4/r32/esp -10929 # var stmt/esi: statement -10930 68/push 0/imm32/next -10931 57/push-edi/outputs -10932 56/push-esi/inouts -10933 68/push "add"/imm32/operation -10934 68/push 1/imm32 -10935 89/<- %esi 4/r32/esp -10936 # convert -10937 c7 0/subop/copy *Curr-block-depth 0/imm32 -10938 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -10939 (flush _test-output-buffered-file) -10940 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10946 # check output -10947 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") -10948 # . epilogue -10949 89/<- %esp 5/r32/ebp -10950 5d/pop-to-ebp -10951 c3/return -10952 -10953 test-add-literal-to-eax: -10954 # var1/eax <- add 0x34 -10955 # => -10956 # 05/add-to-eax 0x34/imm32 -10957 # -10958 # . prologue -10959 55/push-ebp -10960 89/<- %ebp 4/r32/esp -10961 # setup -10962 (clear-stream _test-output-stream) -10963 (clear-stream $_test-output-buffered-file->buffer) -10964 # var type/ecx: (handle tree type-id) = int -10965 68/push 0/imm32/right/null -10966 68/push 1/imm32/left/int -10967 89/<- %ecx 4/r32/esp -10968 # var var-var1/ecx: var in eax -10969 68/push "eax"/imm32/register -10970 68/push 0/imm32/no-stack-offset -10971 68/push 1/imm32/block-depth -10972 51/push-ecx -10973 68/push "var1"/imm32 -10974 89/<- %ecx 4/r32/esp -10975 # var type/edx: (handle tree type-id) = literal -10976 68/push 0/imm32/right/null -10977 68/push 0/imm32/left/literal +10927 57/push-edi/outputs +10928 68/push 0/imm32/inouts +10929 68/push "increment"/imm32/operation +10930 68/push 1/imm32 +10931 89/<- %esi 4/r32/esp +10932 # convert +10933 c7 0/subop/copy *Curr-block-depth 0/imm32 +10934 (emit-subx-stmt _test-output-buffered-file %esi Primitives) +10935 (flush _test-output-buffered-file) +10936 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +10942 # check output +10943 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-var") +10944 # . epilogue +10945 89/<- %esp 5/r32/ebp +10946 5d/pop-to-ebp +10947 c3/return +10948 +10949 test-add-reg-to-reg: +10950 # var1/reg <- add var2/reg +10951 # => +10952 # 01/add-to %var1 var2 +10953 # +10954 # . prologue +10955 55/push-ebp +10956 89/<- %ebp 4/r32/esp +10957 # setup +10958 (clear-stream _test-output-stream) +10959 (clear-stream $_test-output-buffered-file->buffer) +10960 # var type/ecx: (handle tree type-id) = int +10961 68/push 0/imm32/right/null +10962 68/push 1/imm32/left/int +10963 68/push 1/imm32/is-atom +10964 89/<- %ecx 4/r32/esp +10965 # var var-var1/ecx: var in eax +10966 68/push "eax"/imm32/register +10967 68/push 0/imm32/no-stack-offset +10968 68/push 1/imm32/block-depth +10969 51/push-ecx +10970 68/push "var1"/imm32 +10971 89/<- %ecx 4/r32/esp +10972 # var var-var2/edx: var in ecx +10973 68/push "ecx"/imm32/register +10974 68/push 0/imm32/no-stack-offset +10975 68/push 1/imm32/block-depth +10976 ff 6/subop/push *(ecx+4) # Var-type +10977 68/push "var2"/imm32 10978 89/<- %edx 4/r32/esp -10979 # var var-var2/edx: var literal -10980 68/push 0/imm32/no-register -10981 68/push 0/imm32/no-stack-offset -10982 68/push 1/imm32/block-depth -10983 52/push-edx -10984 68/push "0x34"/imm32 -10985 89/<- %edx 4/r32/esp -10986 # var inouts/esi: (handle stmt-var) = [var2] -10987 68/push 0/imm32/is-deref:false -10988 68/push 0/imm32/next -10989 52/push-edx/var-var2 -10990 89/<- %esi 4/r32/esp -10991 # var outputs/edi: (handle stmt-var) = [var1] -10992 68/push 0/imm32/is-deref:false -10993 68/push 0/imm32/next -10994 51/push-ecx/var-var1 -10995 89/<- %edi 4/r32/esp -10996 # var stmt/esi: statement -10997 68/push 0/imm32/next -10998 57/push-edi/outputs -10999 56/push-esi/inouts -11000 68/push "add"/imm32/operation -11001 68/push 1/imm32 -11002 89/<- %esi 4/r32/esp -11003 # convert -11004 c7 0/subop/copy *Curr-block-depth 0/imm32 -11005 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -11006 (flush _test-output-buffered-file) -11007 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -11013 # check output -11014 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") -11015 # . epilogue -11016 89/<- %esp 5/r32/ebp -11017 5d/pop-to-ebp -11018 c3/return -11019 -11020 test-add-literal-to-reg: -11021 # var1/ecx <- add 0x34 -11022 # => -11023 # 81 0/subop/add %ecx 0x34/imm32 -11024 # -11025 # . prologue -11026 55/push-ebp -11027 89/<- %ebp 4/r32/esp -11028 # setup -11029 (clear-stream _test-output-stream) -11030 (clear-stream $_test-output-buffered-file->buffer) -11031 # var type/ecx: (handle tree type-id) = int -11032 68/push 0/imm32/right/null -11033 68/push 1/imm32/left/int -11034 89/<- %ecx 4/r32/esp -11035 # var var-var1/ecx: var in ecx -11036 68/push "ecx"/imm32/register -11037 68/push 0/imm32/no-stack-offset -11038 68/push 1/imm32/block-depth -11039 51/push-ecx -11040 68/push "var1"/imm32 -11041 89/<- %ecx 4/r32/esp -11042 # var type/edx: (handle tree type-id) = literal -11043 68/push 0/imm32/right/null -11044 68/push 0/imm32/left/literal -11045 89/<- %edx 4/r32/esp -11046 # var var-var2/edx: var literal -11047 68/push 0/imm32/no-register -11048 68/push 0/imm32/no-stack-offset -11049 68/push 1/imm32/block-depth -11050 52/push-edx -11051 68/push "0x34"/imm32 -11052 89/<- %edx 4/r32/esp -11053 # var inouts/esi: (handle stmt-var) = [var2] -11054 68/push 0/imm32/is-deref:false -11055 68/push 0/imm32/next -11056 52/push-edx/var-var2 -11057 89/<- %esi 4/r32/esp -11058 # var outputs/edi: (handle stmt-var) = [var1] -11059 68/push 0/imm32/is-deref:false -11060 68/push 0/imm32/next -11061 51/push-ecx/var-var1 -11062 89/<- %edi 4/r32/esp -11063 # var stmt/esi: statement -11064 68/push 0/imm32/next -11065 57/push-edi/outputs -11066 56/push-esi/inouts -11067 68/push "add"/imm32/operation -11068 68/push 1/imm32 -11069 89/<- %esi 4/r32/esp -11070 # convert -11071 c7 0/subop/copy *Curr-block-depth 0/imm32 -11072 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -11073 (flush _test-output-buffered-file) -11074 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -11080 # check output -11081 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") -11082 # . epilogue -11083 89/<- %esp 5/r32/ebp -11084 5d/pop-to-ebp -11085 c3/return -11086 -11087 test-add-literal-to-mem: -11088 # add-to var1, 0x34 -11089 # => -11090 # 81 0/subop/add %eax 0x34/imm32 -11091 # -11092 # . prologue -11093 55/push-ebp -11094 89/<- %ebp 4/r32/esp -11095 # setup -11096 (clear-stream _test-output-stream) -11097 (clear-stream $_test-output-buffered-file->buffer) -11098 # var type/ecx: (handle tree type-id) = int -11099 68/push 0/imm32/right/null -11100 68/push 1/imm32/left/int -11101 89/<- %ecx 4/r32/esp -11102 # var var-var1/ecx: var -11103 68/push 0/imm32/no-register -11104 68/push 8/imm32/stack-offset -11105 68/push 1/imm32/block-depth -11106 51/push-ecx -11107 68/push "var1"/imm32 -11108 89/<- %ecx 4/r32/esp -11109 # var type/edx: (handle tree type-id) = literal -11110 68/push 0/imm32/right/null -11111 68/push 0/imm32/left/literal -11112 89/<- %edx 4/r32/esp -11113 # var var-var2/edx: var literal -11114 68/push 0/imm32/no-register -11115 68/push 0/imm32/no-stack-offset -11116 68/push 1/imm32/block-depth -11117 52/push-edx -11118 68/push "0x34"/imm32 -11119 89/<- %edx 4/r32/esp -11120 # var inouts/esi: (handle stmt-var) = [var2] -11121 68/push 0/imm32/is-deref:false -11122 68/push 0/imm32/next -11123 52/push-edx/var-var2 -11124 89/<- %esi 4/r32/esp -11125 # var inouts = (handle stmt-var) = [var1, var2] -11126 68/push 0/imm32/is-deref:false -11127 56/push-esi/next -11128 51/push-ecx/var-var1 -11129 89/<- %esi 4/r32/esp -11130 # var stmt/esi: statement -11131 68/push 0/imm32/next -11132 68/push 0/imm32/outputs -11133 56/push-esi/inouts -11134 68/push "add-to"/imm32/operation -11135 68/push 1/imm32 -11136 89/<- %esi 4/r32/esp -11137 # convert -11138 c7 0/subop/copy *Curr-block-depth 0/imm32 -11139 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -11140 (flush _test-output-buffered-file) -11141 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -11147 # check output -11148 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") -11149 # . epilogue -11150 89/<- %esp 5/r32/ebp -11151 5d/pop-to-ebp -11152 c3/return -11153 -11154 test-compare-mem-with-reg: -11155 # compare var1, var2/eax -11156 # => -11157 # 39/compare *(ebp+___) 0/r32/eax -11158 # -11159 # . prologue -11160 55/push-ebp -11161 89/<- %ebp 4/r32/esp -11162 # setup -11163 (clear-stream _test-output-stream) -11164 (clear-stream $_test-output-buffered-file->buffer) -11165 # var type/ecx: (handle tree type-id) = int -11166 68/push 0/imm32/right/null -11167 68/push 1/imm32/left/int -11168 89/<- %ecx 4/r32/esp -11169 # var var-var2/ecx: var in eax -11170 68/push "eax"/imm32/register -11171 68/push 0/imm32/no-stack-offset -11172 68/push 1/imm32/block-depth -11173 51/push-ecx -11174 68/push "var2"/imm32 -11175 89/<- %ecx 4/r32/esp -11176 # var var-var1/edx: var -11177 68/push 0/imm32/no-register -11178 68/push 8/imm32/stack-offset -11179 68/push 1/imm32/block-depth -11180 ff 6/subop/push *(ecx+4) # Var-type -11181 68/push "var1"/imm32 -11182 89/<- %edx 4/r32/esp -11183 # var inouts/esi: (handle stmt-var) = [var2] -11184 68/push 0/imm32/is-deref:false +10979 # var inouts/esi: (handle stmt-var) = [var2] +10980 68/push 0/imm32/is-deref:false +10981 68/push 0/imm32/next +10982 52/push-edx/var-var2 +10983 89/<- %esi 4/r32/esp +10984 # var outputs/edi: (handle stmt-var) = [var1, var2] +10985 68/push 0/imm32/is-deref:false +10986 68/push 0/imm32/next +10987 51/push-ecx/var-var1 +10988 89/<- %edi 4/r32/esp +10989 # var stmt/esi: statement +10990 68/push 0/imm32/next +10991 57/push-edi/outputs +10992 56/push-esi/inouts +10993 68/push "add"/imm32/operation +10994 68/push 1/imm32 +10995 89/<- %esi 4/r32/esp +10996 # convert +10997 c7 0/subop/copy *Curr-block-depth 0/imm32 +10998 (emit-subx-stmt _test-output-buffered-file %esi Primitives) +10999 (flush _test-output-buffered-file) +11000 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +11006 # check output +11007 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") +11008 # . epilogue +11009 89/<- %esp 5/r32/ebp +11010 5d/pop-to-ebp +11011 c3/return +11012 +11013 test-add-reg-to-mem: +11014 # add-to var1 var2/reg +11015 # => +11016 # 01/add-to *(ebp+__) var2 +11017 # +11018 # . prologue +11019 55/push-ebp +11020 89/<- %ebp 4/r32/esp +11021 # setup +11022 (clear-stream _test-output-stream) +11023 (clear-stream $_test-output-buffered-file->buffer) +11024 # var type/ecx: (handle tree type-id) = int +11025 68/push 0/imm32/right/null +11026 68/push 1/imm32/left/int +11027 68/push 1/imm32/is-atom +11028 89/<- %ecx 4/r32/esp +11029 # var var-var1/ecx: var +11030 68/push 0/imm32/no-register +11031 68/push 8/imm32/stack-offset +11032 68/push 1/imm32/block-depth +11033 51/push-ecx +11034 68/push "var1"/imm32 +11035 89/<- %ecx 4/r32/esp +11036 # var var-var2/edx: var in ecx +11037 68/push "ecx"/imm32/register +11038 68/push 0/imm32/no-stack-offset +11039 68/push 1/imm32/block-depth +11040 ff 6/subop/push *(ecx+4) # Var-type +11041 68/push "var2"/imm32 +11042 89/<- %edx 4/r32/esp +11043 # var inouts/esi: (handle stmt-var) = [var2] +11044 68/push 0/imm32/is-deref:false +11045 68/push 0/imm32/next +11046 52/push-edx/var-var2 +11047 89/<- %esi 4/r32/esp +11048 # var inouts = (handle stmt-var) = [var1, var2] +11049 56/push-esi/next +11050 51/push-ecx/var-var1 +11051 89/<- %esi 4/r32/esp +11052 # var stmt/esi: statement +11053 68/push 0/imm32/next +11054 68/push 0/imm32/outputs +11055 56/push-esi/inouts +11056 68/push "add-to"/imm32/operation +11057 68/push 1/imm32 +11058 89/<- %esi 4/r32/esp +11059 # convert +11060 c7 0/subop/copy *Curr-block-depth 0/imm32 +11061 (emit-subx-stmt _test-output-buffered-file %esi Primitives) +11062 (flush _test-output-buffered-file) +11063 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +11069 # check output +11070 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") +11071 # . epilogue +11072 89/<- %esp 5/r32/ebp +11073 5d/pop-to-ebp +11074 c3/return +11075 +11076 test-add-mem-to-reg: +11077 # var1/reg <- add var2 +11078 # => +11079 # 03/add *(ebp+__) var1 +11080 # +11081 # . prologue +11082 55/push-ebp +11083 89/<- %ebp 4/r32/esp +11084 # setup +11085 (clear-stream _test-output-stream) +11086 (clear-stream $_test-output-buffered-file->buffer) +11087 # var type/ecx: (handle tree type-id) = int +11088 68/push 0/imm32/right/null +11089 68/push 1/imm32/left/int +11090 68/push 1/imm32/is-atom +11091 89/<- %ecx 4/r32/esp +11092 # var var-var1/ecx: var in eax +11093 68/push "eax"/imm32/register +11094 68/push 0/imm32/no-stack-offset +11095 68/push 1/imm32/block-depth +11096 51/push-ecx +11097 68/push "var1"/imm32 +11098 89/<- %ecx 4/r32/esp +11099 # var var-var2/edx: var +11100 68/push 0/imm32/no-register +11101 68/push 8/imm32/stack-offset +11102 68/push 1/imm32/block-depth +11103 ff 6/subop/push *(ecx+4) # Var-type +11104 68/push "var2"/imm32 +11105 89/<- %edx 4/r32/esp +11106 # var inouts/esi: (handle stmt-var) = [var2] +11107 68/push 0/imm32/is-deref:false +11108 68/push 0/imm32/next +11109 52/push-edx/var-var2 +11110 89/<- %esi 4/r32/esp +11111 # var outputs/edi = (handle stmt-var) = [var1] +11112 68/push 0/imm32/is-deref:false +11113 68/push 0/imm32/next +11114 51/push-ecx/var-var1 +11115 89/<- %edi 4/r32/esp +11116 # var stmt/esi: statement +11117 68/push 0/imm32/next +11118 57/push-edi/outputs +11119 56/push-esi/inouts +11120 68/push "add"/imm32/operation +11121 68/push 1/imm32 +11122 89/<- %esi 4/r32/esp +11123 # convert +11124 c7 0/subop/copy *Curr-block-depth 0/imm32 +11125 (emit-subx-stmt _test-output-buffered-file %esi Primitives) +11126 (flush _test-output-buffered-file) +11127 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +11133 # check output +11134 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") +11135 # . epilogue +11136 89/<- %esp 5/r32/ebp +11137 5d/pop-to-ebp +11138 c3/return +11139 +11140 test-add-literal-to-eax: +11141 # var1/eax <- add 0x34 +11142 # => +11143 # 05/add-to-eax 0x34/imm32 +11144 # +11145 # . prologue +11146 55/push-ebp +11147 89/<- %ebp 4/r32/esp +11148 # setup +11149 (clear-stream _test-output-stream) +11150 (clear-stream $_test-output-buffered-file->buffer) +11151 # var type/ecx: (handle tree type-id) = int +11152 68/push 0/imm32/right/null +11153 68/push 1/imm32/left/int +11154 68/push 1/imm32/is-atom +11155 89/<- %ecx 4/r32/esp +11156 # var var-var1/ecx: var in eax +11157 68/push "eax"/imm32/register +11158 68/push 0/imm32/no-stack-offset +11159 68/push 1/imm32/block-depth +11160 51/push-ecx +11161 68/push "var1"/imm32 +11162 89/<- %ecx 4/r32/esp +11163 # var type/edx: (handle tree type-id) = literal +11164 68/push 0/imm32/right/null +11165 68/push 0/imm32/left/literal +11166 89/<- %edx 4/r32/esp +11167 # var var-var2/edx: var literal +11168 68/push 0/imm32/no-register +11169 68/push 0/imm32/no-stack-offset +11170 68/push 1/imm32/block-depth +11171 52/push-edx +11172 68/push "0x34"/imm32 +11173 89/<- %edx 4/r32/esp +11174 # var inouts/esi: (handle stmt-var) = [var2] +11175 68/push 0/imm32/is-deref:false +11176 68/push 0/imm32/next +11177 52/push-edx/var-var2 +11178 89/<- %esi 4/r32/esp +11179 # var outputs/edi: (handle stmt-var) = [var1] +11180 68/push 0/imm32/is-deref:false +11181 68/push 0/imm32/next +11182 51/push-ecx/var-var1 +11183 89/<- %edi 4/r32/esp +11184 # var stmt/esi: statement 11185 68/push 0/imm32/next -11186 51/push-ecx/var-var2 -11187 89/<- %esi 4/r32/esp -11188 # inouts = [var1, var2] -11189 68/push 0/imm32/is-deref:false -11190 56/push-esi -11191 52/push-edx/var-var1 -11192 89/<- %esi 4/r32/esp -11193 # var stmt/esi: statement -11194 68/push 0/imm32/next -11195 68/push 0/imm32/outputs -11196 56/push-esi/inouts -11197 68/push "compare"/imm32/operation -11198 68/push 1/imm32 -11199 89/<- %esi 4/r32/esp -11200 # convert -11201 c7 0/subop/copy *Curr-block-depth 0/imm32 -11202 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -11203 (flush _test-output-buffered-file) -11204 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -11210 # check output -11211 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") -11212 # . epilogue -11213 89/<- %esp 5/r32/ebp -11214 5d/pop-to-ebp -11215 c3/return -11216 -11217 test-compare-reg-with-mem: -11218 # compare var1/eax, var2 -11219 # => -11220 # 3b/compare *(ebp+___) 0/r32/eax -11221 # -11222 # . prologue -11223 55/push-ebp -11224 89/<- %ebp 4/r32/esp -11225 # setup -11226 (clear-stream _test-output-stream) -11227 (clear-stream $_test-output-buffered-file->buffer) -11228 # var type/ecx: (handle tree type-id) = int -11229 68/push 0/imm32/right/null -11230 68/push 1/imm32/left/int -11231 89/<- %ecx 4/r32/esp -11232 # var var-var1/ecx: var in eax -11233 68/push "eax"/imm32/register -11234 68/push 0/imm32/no-stack-offset -11235 68/push 1/imm32/block-depth -11236 51/push-ecx -11237 68/push "var1"/imm32 -11238 89/<- %ecx 4/r32/esp -11239 # var var-var2/edx: var -11240 68/push 0/imm32/no-register -11241 68/push 8/imm32/stack-offset -11242 68/push 1/imm32/block-depth -11243 ff 6/subop/push *(ecx+4) # Var-type -11244 68/push "var2"/imm32 -11245 89/<- %edx 4/r32/esp -11246 # var inouts/esi: (handle stmt-var) = [var2] -11247 68/push 0/imm32/is-deref:false -11248 68/push 0/imm32/next -11249 52/push-edx/var-var2 -11250 89/<- %esi 4/r32/esp -11251 # inouts = [var1, var2] -11252 68/push 0/imm32/is-deref:false -11253 56/push-esi -11254 51/push-ecx/var-var1 -11255 89/<- %esi 4/r32/esp -11256 # var stmt/esi: statement -11257 68/push 0/imm32/next -11258 68/push 0/imm32/outputs -11259 56/push-esi/inouts -11260 68/push "compare"/imm32/operation -11261 68/push 1/imm32 -11262 89/<- %esi 4/r32/esp -11263 # convert -11264 c7 0/subop/copy *Curr-block-depth 0/imm32 -11265 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -11266 (flush _test-output-buffered-file) -11267 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -11273 # check output -11274 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") -11275 # . epilogue -11276 89/<- %esp 5/r32/ebp -11277 5d/pop-to-ebp -11278 c3/return -11279 -11280 test-compare-mem-with-literal: -11281 # compare var1, 0x34 -11282 # => -11283 # 81 7/subop/compare *(ebp+___) 0x34/imm32 -11284 # -11285 # . prologue -11286 55/push-ebp -11287 89/<- %ebp 4/r32/esp -11288 # setup -11289 (clear-stream _test-output-stream) -11290 (clear-stream $_test-output-buffered-file->buffer) -11291 # var type/ecx: (handle tree type-id) = int -11292 68/push 0/imm32/right/null -11293 68/push 1/imm32/left/int -11294 89/<- %ecx 4/r32/esp -11295 # var var-var1/ecx: var -11296 68/push 0/imm32/no-register -11297 68/push 8/imm32/stack-offset -11298 68/push 1/imm32/block-depth -11299 51/push-ecx -11300 68/push "var1"/imm32 -11301 89/<- %ecx 4/r32/esp -11302 # var type/edx: (handle tree type-id) = literal -11303 68/push 0/imm32/right/null -11304 68/push 0/imm32/left/literal -11305 89/<- %edx 4/r32/esp -11306 # var var-var2/edx: var literal -11307 68/push 0/imm32/no-register -11308 68/push 0/imm32/no-stack-offset -11309 68/push 1/imm32/block-depth -11310 52/push-edx -11311 68/push "0x34"/imm32 -11312 89/<- %edx 4/r32/esp -11313 # var inouts/esi: (handle stmt-var) = [var2] -11314 68/push 0/imm32/is-deref:false -11315 68/push 0/imm32/next -11316 52/push-edx/var-var2 -11317 89/<- %esi 4/r32/esp -11318 # inouts = [var1, var2] -11319 68/push 0/imm32/is-deref:false -11320 56/push-esi/next -11321 51/push-ecx/var-var1 -11322 89/<- %esi 4/r32/esp -11323 # var stmt/esi: statement -11324 68/push 0/imm32/next -11325 68/push 0/imm32/outputs -11326 56/push-esi/inouts -11327 68/push "compare"/imm32/operation -11328 68/push 1/imm32 -11329 89/<- %esi 4/r32/esp -11330 # convert -11331 c7 0/subop/copy *Curr-block-depth 0/imm32 -11332 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -11333 (flush _test-output-buffered-file) -11334 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -11340 # check output -11341 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") -11342 # . epilogue -11343 89/<- %esp 5/r32/ebp -11344 5d/pop-to-ebp -11345 c3/return -11346 -11347 test-compare-eax-with-literal: -11348 # compare var1/eax 0x34 -11349 # => -11350 # 3d/compare-eax-with 0x34/imm32 -11351 # -11352 # . prologue -11353 55/push-ebp -11354 89/<- %ebp 4/r32/esp -11355 # setup -11356 (clear-stream _test-output-stream) -11357 (clear-stream $_test-output-buffered-file->buffer) -11358 # var type/ecx: (handle tree type-id) = int -11359 68/push 0/imm32/right/null -11360 68/push 1/imm32/left/int -11361 89/<- %ecx 4/r32/esp -11362 # var var-var1/ecx: var in eax -11363 68/push "eax"/imm32/register -11364 68/push 0/imm32/no-stack-offset -11365 68/push 1/imm32/block-depth -11366 51/push-ecx -11367 68/push "var1"/imm32 -11368 89/<- %ecx 4/r32/esp -11369 # var type/edx: (handle tree type-id) = literal -11370 68/push 0/imm32/right/null -11371 68/push 0/imm32/left/literal -11372 89/<- %edx 4/r32/esp -11373 # var var-var2/edx: var literal -11374 68/push 0/imm32/no-register -11375 68/push 0/imm32/no-stack-offset -11376 68/push 1/imm32/block-depth -11377 52/push-edx -11378 68/push "0x34"/imm32 -11379 89/<- %edx 4/r32/esp -11380 # var inouts/esi: (handle stmt-var) = [var2] -11381 68/push 0/imm32/is-deref:false -11382 68/push 0/imm32/next -11383 52/push-edx/var-var2 -11384 89/<- %esi 4/r32/esp -11385 # inouts = [var1, var2] -11386 68/push 0/imm32/is-deref:false -11387 56/push-esi/next -11388 51/push-ecx/var-var1 -11389 89/<- %esi 4/r32/esp -11390 # var stmt/esi: statement -11391 68/push 0/imm32/next -11392 68/push 0/imm32/outputs -11393 56/push-esi/inouts -11394 68/push "compare"/imm32/operation -11395 68/push 1/imm32/regular-stmt -11396 89/<- %esi 4/r32/esp -11397 # convert -11398 c7 0/subop/copy *Curr-block-depth 0/imm32 -11399 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -11400 (flush _test-output-buffered-file) -11401 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -11407 # check output -11408 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") -11409 # . epilogue -11410 89/<- %esp 5/r32/ebp -11411 5d/pop-to-ebp -11412 c3/return -11413 -11414 test-compare-reg-with-literal: -11415 # compare var1/ecx 0x34 -11416 # => -11417 # 81 7/subop/compare %ecx 0x34/imm32 -11418 # -11419 # . prologue -11420 55/push-ebp -11421 89/<- %ebp 4/r32/esp -11422 # setup -11423 (clear-stream _test-output-stream) -11424 (clear-stream $_test-output-buffered-file->buffer) -11425 # var type/ecx: (handle tree type-id) = int -11426 68/push 0/imm32/right/null -11427 68/push 1/imm32/left/int -11428 89/<- %ecx 4/r32/esp -11429 # var var-var1/ecx: var in ecx -11430 68/push "ecx"/imm32/register -11431 68/push 0/imm32/no-stack-offset -11432 68/push 1/imm32/block-depth -11433 51/push-ecx -11434 68/push "var1"/imm32 -11435 89/<- %ecx 4/r32/esp -11436 # var type/edx: (handle tree type-id) = literal -11437 68/push 0/imm32/right/null -11438 68/push 0/imm32/left/literal -11439 89/<- %edx 4/r32/esp -11440 # var var-var2/edx: var literal -11441 68/push 0/imm32/no-register -11442 68/push 0/imm32/no-stack-offset -11443 68/push 1/imm32/block-depth -11444 52/push-edx -11445 68/push "0x34"/imm32 -11446 89/<- %edx 4/r32/esp -11447 # var inouts/esi: (handle stmt-var) = [var2] -11448 68/push 0/imm32/is-deref:false +11186 57/push-edi/outputs +11187 56/push-esi/inouts +11188 68/push "add"/imm32/operation +11189 68/push 1/imm32 +11190 89/<- %esi 4/r32/esp +11191 # convert +11192 c7 0/subop/copy *Curr-block-depth 0/imm32 +11193 (emit-subx-stmt _test-output-buffered-file %esi Primitives) +11194 (flush _test-output-buffered-file) +11195 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +11201 # check output +11202 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") +11203 # . epilogue +11204 89/<- %esp 5/r32/ebp +11205 5d/pop-to-ebp +11206 c3/return +11207 +11208 test-add-literal-to-reg: +11209 # var1/ecx <- add 0x34 +11210 # => +11211 # 81 0/subop/add %ecx 0x34/imm32 +11212 # +11213 # . prologue +11214 55/push-ebp +11215 89/<- %ebp 4/r32/esp +11216 # setup +11217 (clear-stream _test-output-stream) +11218 (clear-stream $_test-output-buffered-file->buffer) +11219 # var type/ecx: (handle tree type-id) = int +11220 68/push 0/imm32/right/null +11221 68/push 1/imm32/left/int +11222 68/push 1/imm32/is-atom +11223 89/<- %ecx 4/r32/esp +11224 # var var-var1/ecx: var in ecx +11225 68/push "ecx"/imm32/register +11226 68/push 0/imm32/no-stack-offset +11227 68/push 1/imm32/block-depth +11228 51/push-ecx +11229 68/push "var1"/imm32 +11230 89/<- %ecx 4/r32/esp +11231 # var type/edx: (handle tree type-id) = literal +11232 68/push 0/imm32/right/null +11233 68/push 0/imm32/left/literal +11234 89/<- %edx 4/r32/esp +11235 # var var-var2/edx: var literal +11236 68/push 0/imm32/no-register +11237 68/push 0/imm32/no-stack-offset +11238 68/push 1/imm32/block-depth +11239 52/push-edx +11240 68/push "0x34"/imm32 +11241 89/<- %edx 4/r32/esp +11242 # var inouts/esi: (handle stmt-var) = [var2] +11243 68/push 0/imm32/is-deref:false +11244 68/push 0/imm32/next +11245 52/push-edx/var-var2 +11246 89/<- %esi 4/r32/esp +11247 # var outputs/edi: (handle stmt-var) = [var1] +11248 68/push 0/imm32/is-deref:false +11249 68/push 0/imm32/next +11250 51/push-ecx/var-var1 +11251 89/<- %edi 4/r32/esp +11252 # var stmt/esi: statement +11253 68/push 0/imm32/next +11254 57/push-edi/outputs +11255 56/push-esi/inouts +11256 68/push "add"/imm32/operation +11257 68/push 1/imm32 +11258 89/<- %esi 4/r32/esp +11259 # convert +11260 c7 0/subop/copy *Curr-block-depth 0/imm32 +11261 (emit-subx-stmt _test-output-buffered-file %esi Primitives) +11262 (flush _test-output-buffered-file) +11263 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +11269 # check output +11270 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") +11271 # . epilogue +11272 89/<- %esp 5/r32/ebp +11273 5d/pop-to-ebp +11274 c3/return +11275 +11276 test-add-literal-to-mem: +11277 # add-to var1, 0x34 +11278 # => +11279 # 81 0/subop/add %eax 0x34/imm32 +11280 # +11281 # . prologue +11282 55/push-ebp +11283 89/<- %ebp 4/r32/esp +11284 # setup +11285 (clear-stream _test-output-stream) +11286 (clear-stream $_test-output-buffered-file->buffer) +11287 # var type/ecx: (handle tree type-id) = int +11288 68/push 0/imm32/right/null +11289 68/push 1/imm32/left/int +11290 68/push 1/imm32/is-atom +11291 89/<- %ecx 4/r32/esp +11292 # var var-var1/ecx: var +11293 68/push 0/imm32/no-register +11294 68/push 8/imm32/stack-offset +11295 68/push 1/imm32/block-depth +11296 51/push-ecx +11297 68/push "var1"/imm32 +11298 89/<- %ecx 4/r32/esp +11299 # var type/edx: (handle tree type-id) = literal +11300 68/push 0/imm32/right/null +11301 68/push 0/imm32/left/literal +11302 89/<- %edx 4/r32/esp +11303 # var var-var2/edx: var literal +11304 68/push 0/imm32/no-register +11305 68/push 0/imm32/no-stack-offset +11306 68/push 1/imm32/block-depth +11307 52/push-edx +11308 68/push "0x34"/imm32 +11309 89/<- %edx 4/r32/esp +11310 # var inouts/esi: (handle stmt-var) = [var2] +11311 68/push 0/imm32/is-deref:false +11312 68/push 0/imm32/next +11313 52/push-edx/var-var2 +11314 89/<- %esi 4/r32/esp +11315 # var inouts = (handle stmt-var) = [var1, var2] +11316 68/push 0/imm32/is-deref:false +11317 56/push-esi/next +11318 51/push-ecx/var-var1 +11319 89/<- %esi 4/r32/esp +11320 # var stmt/esi: statement +11321 68/push 0/imm32/next +11322 68/push 0/imm32/outputs +11323 56/push-esi/inouts +11324 68/push "add-to"/imm32/operation +11325 68/push 1/imm32 +11326 89/<- %esi 4/r32/esp +11327 # convert +11328 c7 0/subop/copy *Curr-block-depth 0/imm32 +11329 (emit-subx-stmt _test-output-buffered-file %esi Primitives) +11330 (flush _test-output-buffered-file) +11331 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +11337 # check output +11338 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") +11339 # . epilogue +11340 89/<- %esp 5/r32/ebp +11341 5d/pop-to-ebp +11342 c3/return +11343 +11344 test-compare-mem-with-reg: +11345 # compare var1, var2/eax +11346 # => +11347 # 39/compare *(ebp+___) 0/r32/eax +11348 # +11349 # . prologue +11350 55/push-ebp +11351 89/<- %ebp 4/r32/esp +11352 # setup +11353 (clear-stream _test-output-stream) +11354 (clear-stream $_test-output-buffered-file->buffer) +11355 # var type/ecx: (handle tree type-id) = int +11356 68/push 0/imm32/right/null +11357 68/push 1/imm32/left/int +11358 68/push 1/imm32/is-atom +11359 89/<- %ecx 4/r32/esp +11360 # var var-var2/ecx: var in eax +11361 68/push "eax"/imm32/register +11362 68/push 0/imm32/no-stack-offset +11363 68/push 1/imm32/block-depth +11364 51/push-ecx +11365 68/push "var2"/imm32 +11366 89/<- %ecx 4/r32/esp +11367 # var var-var1/edx: var +11368 68/push 0/imm32/no-register +11369 68/push 8/imm32/stack-offset +11370 68/push 1/imm32/block-depth +11371 ff 6/subop/push *(ecx+4) # Var-type +11372 68/push "var1"/imm32 +11373 89/<- %edx 4/r32/esp +11374 # var inouts/esi: (handle stmt-var) = [var2] +11375 68/push 0/imm32/is-deref:false +11376 68/push 0/imm32/next +11377 51/push-ecx/var-var2 +11378 89/<- %esi 4/r32/esp +11379 # inouts = [var1, var2] +11380 68/push 0/imm32/is-deref:false +11381 56/push-esi +11382 52/push-edx/var-var1 +11383 89/<- %esi 4/r32/esp +11384 # var stmt/esi: statement +11385 68/push 0/imm32/next +11386 68/push 0/imm32/outputs +11387 56/push-esi/inouts +11388 68/push "compare"/imm32/operation +11389 68/push 1/imm32 +11390 89/<- %esi 4/r32/esp +11391 # convert +11392 c7 0/subop/copy *Curr-block-depth 0/imm32 +11393 (emit-subx-stmt _test-output-buffered-file %esi Primitives) +11394 (flush _test-output-buffered-file) +11395 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +11401 # check output +11402 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") +11403 # . epilogue +11404 89/<- %esp 5/r32/ebp +11405 5d/pop-to-ebp +11406 c3/return +11407 +11408 test-compare-reg-with-mem: +11409 # compare var1/eax, var2 +11410 # => +11411 # 3b/compare<- *(ebp+___) 0/r32/eax +11412 # +11413 # . prologue +11414 55/push-ebp +11415 89/<- %ebp 4/r32/esp +11416 # setup +11417 (clear-stream _test-output-stream) +11418 (clear-stream $_test-output-buffered-file->buffer) +11419 # var type/ecx: (handle tree type-id) = int +11420 68/push 0/imm32/right/null +11421 68/push 1/imm32/left/int +11422 68/push 1/imm32/is-atom +11423 89/<- %ecx 4/r32/esp +11424 # var var-var1/ecx: var in eax +11425 68/push "eax"/imm32/register +11426 68/push 0/imm32/no-stack-offset +11427 68/push 1/imm32/block-depth +11428 51/push-ecx +11429 68/push "var1"/imm32 +11430 89/<- %ecx 4/r32/esp +11431 # var var-var2/edx: var +11432 68/push 0/imm32/no-register +11433 68/push 8/imm32/stack-offset +11434 68/push 1/imm32/block-depth +11435 ff 6/subop/push *(ecx+4) # Var-type +11436 68/push "var2"/imm32 +11437 89/<- %edx 4/r32/esp +11438 # var inouts/esi: (handle stmt-var) = [var2] +11439 68/push 0/imm32/is-deref:false +11440 68/push 0/imm32/next +11441 52/push-edx/var-var2 +11442 89/<- %esi 4/r32/esp +11443 # inouts = [var1, var2] +11444 68/push 0/imm32/is-deref:false +11445 56/push-esi +11446 51/push-ecx/var-var1 +11447 89/<- %esi 4/r32/esp +11448 # var stmt/esi: statement 11449 68/push 0/imm32/next -11450 52/push-edx/var-var2 -11451 89/<- %esi 4/r32/esp -11452 # inouts = [var1, var2] -11453 68/push 0/imm32/is-deref:false -11454 56/push-esi/next -11455 51/push-ecx/var-var1 -11456 89/<- %esi 4/r32/esp -11457 # var stmt/esi: statement -11458 68/push 0/imm32/next -11459 68/push 0/imm32/outputs -11460 56/push-esi/inouts -11461 68/push "compare"/imm32/operation -11462 68/push 1/imm32/regular-stmt -11463 89/<- %esi 4/r32/esp -11464 # convert -11465 c7 0/subop/copy *Curr-block-depth 0/imm32 -11466 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -11467 (flush _test-output-buffered-file) -11468 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -11474 # check output -11475 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") -11476 # . epilogue -11477 89/<- %esp 5/r32/ebp -11478 5d/pop-to-ebp -11479 c3/return -11480 -11481 test-emit-subx-stmt-function-call: -11482 # Call a function on a variable on the stack. -11483 # f foo -11484 # => -11485 # (f2 *(ebp-8)) -11486 # (Changing the function name supports overloading in general, but here it -11487 # just serves to help disambiguate things.) -11488 # -11489 # There's a variable on the var stack as follows: -11490 # name: 'foo' -11491 # type: int -11492 # stack-offset: -8 -11493 # -11494 # There's nothing in primitives. -11495 # -11496 # There's a function with this info: -11497 # name: 'f' -11498 # inout: int/mem -11499 # value: 'f2' -11500 # -11501 # . prologue -11502 55/push-ebp -11503 89/<- %ebp 4/r32/esp -11504 # setup -11505 (clear-stream _test-output-stream) -11506 (clear-stream $_test-output-buffered-file->buffer) -11507 # var type/ecx: (handle tree type-id) = int -11508 68/push 0/imm32/right/null -11509 68/push 1/imm32/left/int -11510 89/<- %ecx 4/r32/esp -11511 # var var-foo/ecx: var -11512 68/push 0/imm32/no-register -11513 68/push -8/imm32/stack-offset -11514 68/push 0/imm32/block-depth -11515 51/push-ecx -11516 68/push "foo"/imm32 -11517 89/<- %ecx 4/r32/esp -11518 # var inouts/esi: (handle stmt-var) -11519 68/push 0/imm32/is-deref:false -11520 68/push 0/imm32/next -11521 51/push-ecx/var-foo +11450 68/push 0/imm32/outputs +11451 56/push-esi/inouts +11452 68/push "compare"/imm32/operation +11453 68/push 1/imm32 +11454 89/<- %esi 4/r32/esp +11455 # convert +11456 c7 0/subop/copy *Curr-block-depth 0/imm32 +11457 (emit-subx-stmt _test-output-buffered-file %esi Primitives) +11458 (flush _test-output-buffered-file) +11459 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +11465 # check output +11466 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") +11467 # . epilogue +11468 89/<- %esp 5/r32/ebp +11469 5d/pop-to-ebp +11470 c3/return +11471 +11472 test-compare-mem-with-literal: +11473 # compare var1, 0x34 +11474 # => +11475 # 81 7/subop/compare *(ebp+___) 0x34/imm32 +11476 # +11477 # . prologue +11478 55/push-ebp +11479 89/<- %ebp 4/r32/esp +11480 # setup +11481 (clear-stream _test-output-stream) +11482 (clear-stream $_test-output-buffered-file->buffer) +11483 # var type/ecx: (handle tree type-id) = int +11484 68/push 0/imm32/right/null +11485 68/push 1/imm32/left/int +11486 68/push 1/imm32/is-atom +11487 89/<- %ecx 4/r32/esp +11488 # var var-var1/ecx: var +11489 68/push 0/imm32/no-register +11490 68/push 8/imm32/stack-offset +11491 68/push 1/imm32/block-depth +11492 51/push-ecx +11493 68/push "var1"/imm32 +11494 89/<- %ecx 4/r32/esp +11495 # var type/edx: (handle tree type-id) = literal +11496 68/push 0/imm32/right/null +11497 68/push 0/imm32/left/literal +11498 89/<- %edx 4/r32/esp +11499 # var var-var2/edx: var literal +11500 68/push 0/imm32/no-register +11501 68/push 0/imm32/no-stack-offset +11502 68/push 1/imm32/block-depth +11503 52/push-edx +11504 68/push "0x34"/imm32 +11505 89/<- %edx 4/r32/esp +11506 # var inouts/esi: (handle stmt-var) = [var2] +11507 68/push 0/imm32/is-deref:false +11508 68/push 0/imm32/next +11509 52/push-edx/var-var2 +11510 89/<- %esi 4/r32/esp +11511 # inouts = [var1, var2] +11512 68/push 0/imm32/is-deref:false +11513 56/push-esi/next +11514 51/push-ecx/var-var1 +11515 89/<- %esi 4/r32/esp +11516 # var stmt/esi: statement +11517 68/push 0/imm32/next +11518 68/push 0/imm32/outputs +11519 56/push-esi/inouts +11520 68/push "compare"/imm32/operation +11521 68/push 1/imm32 11522 89/<- %esi 4/r32/esp -11523 # var stmt/esi: statement -11524 68/push 0/imm32/next -11525 68/push 0/imm32/outputs -11526 56/push-esi/inouts -11527 68/push "f"/imm32/operation -11528 68/push 1/imm32 -11529 89/<- %esi 4/r32/esp -11530 # var functions/ebx: function -11531 68/push 0/imm32/next -11532 68/push 0/imm32/body -11533 68/push 0/imm32/outputs -11534 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -11535 68/push "f2"/imm32/subx-name -11536 68/push "f"/imm32/name -11537 89/<- %ebx 4/r32/esp -11538 # convert -11539 c7 0/subop/copy *Curr-block-depth 0/imm32 -11540 (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx) -11541 (flush _test-output-buffered-file) -11542 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -11548 # check output -11549 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call") -11550 # . epilogue -11551 89/<- %esp 5/r32/ebp -11552 5d/pop-to-ebp -11553 c3/return -11554 -11555 test-emit-subx-stmt-function-call-with-literal-arg: -11556 # Call a function on a literal. -11557 # f 34 -11558 # => -11559 # (f2 34) -11560 # -11561 # . prologue -11562 55/push-ebp -11563 89/<- %ebp 4/r32/esp -11564 # setup -11565 (clear-stream _test-output-stream) -11566 (clear-stream $_test-output-buffered-file->buffer) -11567 # var type/ecx: (handle tree type-id) = literal -11568 68/push 0/imm32/right/null -11569 68/push 0/imm32/left/literal -11570 89/<- %ecx 4/r32/esp -11571 # var var-foo/ecx: var literal -11572 68/push 0/imm32/no-register -11573 68/push 0/imm32/no-stack-offset -11574 68/push 0/imm32/block-depth -11575 51/push-ecx -11576 68/push "34"/imm32 -11577 89/<- %ecx 4/r32/esp -11578 # var inouts/esi: (handle stmt-var) -11579 68/push 0/imm32/is-deref:false -11580 68/push 0/imm32/next -11581 51/push-ecx/var-foo -11582 89/<- %esi 4/r32/esp -11583 # var stmt/esi: statement -11584 68/push 0/imm32/next -11585 68/push 0/imm32/outputs -11586 56/push-esi/inouts -11587 68/push "f"/imm32/operation -11588 68/push 1/imm32 -11589 89/<- %esi 4/r32/esp -11590 # var functions/ebx: function -11591 68/push 0/imm32/next -11592 68/push 0/imm32/body -11593 68/push 0/imm32/outputs -11594 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -11595 68/push "f2"/imm32/subx-name -11596 68/push "f"/imm32/name -11597 89/<- %ebx 4/r32/esp -11598 # convert -11599 c7 0/subop/copy *Curr-block-depth 0/imm32 -11600 (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx) -11601 (flush _test-output-buffered-file) -11602 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -11608 # check output -11609 (check-next-stream-line-equal _test-output-stream "(f2 34)" "F - test-emit-subx-stmt-function-call-with-literal-arg") -11610 # . epilogue -11611 89/<- %esp 5/r32/ebp -11612 5d/pop-to-ebp -11613 c3/return -11614 -11615 emit-indent: # out: (addr buffered-file), n: int -11616 # . prologue -11617 55/push-ebp -11618 89/<- %ebp 4/r32/esp -11619 # . save registers -11620 50/push-eax -11621 # var i/eax: int = n -11622 8b/-> *(ebp+0xc) 0/r32/eax -11623 { -11624 # if (i <= 0) break -11625 3d/compare-eax-with 0/imm32 -11626 7e/jump-if-<= break/disp8 -11627 (write-buffered *(ebp+8) " ") -11628 48/decrement-eax -11629 eb/jump loop/disp8 -11630 } -11631 $emit-indent:end: -11632 # . restore registers -11633 58/pop-to-eax -11634 # . epilogue -11635 89/<- %esp 5/r32/ebp -11636 5d/pop-to-ebp -11637 c3/return -11638 -11639 emit-subx-prologue: # out: (addr buffered-file) -11640 # . prologue -11641 55/push-ebp -11642 89/<- %ebp 4/r32/esp -11643 # -11644 (write-buffered *(ebp+8) " # . prologue\n") -11645 (write-buffered *(ebp+8) " 55/push-ebp\n") -11646 (write-buffered *(ebp+8) " 89/<- %ebp 4/r32/esp\n") -11647 $emit-subx-prologue:end: -11648 # . epilogue -11649 89/<- %esp 5/r32/ebp -11650 5d/pop-to-ebp -11651 c3/return -11652 -11653 emit-subx-epilogue: # out: (addr buffered-file) -11654 # . prologue -11655 55/push-ebp -11656 89/<- %ebp 4/r32/esp -11657 # -11658 (write-buffered *(ebp+8) " # . epilogue\n") -11659 (write-buffered *(ebp+8) " 89/<- %esp 5/r32/ebp\n") -11660 (write-buffered *(ebp+8) " 5d/pop-to-ebp\n") -11661 (write-buffered *(ebp+8) " c3/return\n") -11662 $emit-subx-epilogue:end: -11663 # . epilogue -11664 89/<- %esp 5/r32/ebp -11665 5d/pop-to-ebp -11666 c3/return +11523 # convert +11524 c7 0/subop/copy *Curr-block-depth 0/imm32 +11525 (emit-subx-stmt _test-output-buffered-file %esi Primitives) +11526 (flush _test-output-buffered-file) +11527 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +11533 # check output +11534 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") +11535 # . epilogue +11536 89/<- %esp 5/r32/ebp +11537 5d/pop-to-ebp +11538 c3/return +11539 +11540 test-compare-eax-with-literal: +11541 # compare var1/eax 0x34 +11542 # => +11543 # 3d/compare-eax-with 0x34/imm32 +11544 # +11545 # . prologue +11546 55/push-ebp +11547 89/<- %ebp 4/r32/esp +11548 # setup +11549 (clear-stream _test-output-stream) +11550 (clear-stream $_test-output-buffered-file->buffer) +11551 # var type/ecx: (handle tree type-id) = int +11552 68/push 0/imm32/right/null +11553 68/push 1/imm32/left/int +11554 68/push 1/imm32/is-atom +11555 89/<- %ecx 4/r32/esp +11556 # var var-var1/ecx: var in eax +11557 68/push "eax"/imm32/register +11558 68/push 0/imm32/no-stack-offset +11559 68/push 1/imm32/block-depth +11560 51/push-ecx +11561 68/push "var1"/imm32 +11562 89/<- %ecx 4/r32/esp +11563 # var type/edx: (handle tree type-id) = literal +11564 68/push 0/imm32/right/null +11565 68/push 0/imm32/left/literal +11566 89/<- %edx 4/r32/esp +11567 # var var-var2/edx: var literal +11568 68/push 0/imm32/no-register +11569 68/push 0/imm32/no-stack-offset +11570 68/push 1/imm32/block-depth +11571 52/push-edx +11572 68/push "0x34"/imm32 +11573 89/<- %edx 4/r32/esp +11574 # var inouts/esi: (handle stmt-var) = [var2] +11575 68/push 0/imm32/is-deref:false +11576 68/push 0/imm32/next +11577 52/push-edx/var-var2 +11578 89/<- %esi 4/r32/esp +11579 # inouts = [var1, var2] +11580 68/push 0/imm32/is-deref:false +11581 56/push-esi/next +11582 51/push-ecx/var-var1 +11583 89/<- %esi 4/r32/esp +11584 # var stmt/esi: statement +11585 68/push 0/imm32/next +11586 68/push 0/imm32/outputs +11587 56/push-esi/inouts +11588 68/push "compare"/imm32/operation +11589 68/push 1/imm32/regular-stmt +11590 89/<- %esi 4/r32/esp +11591 # convert +11592 c7 0/subop/copy *Curr-block-depth 0/imm32 +11593 (emit-subx-stmt _test-output-buffered-file %esi Primitives) +11594 (flush _test-output-buffered-file) +11595 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +11601 # check output +11602 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") +11603 # . epilogue +11604 89/<- %esp 5/r32/ebp +11605 5d/pop-to-ebp +11606 c3/return +11607 +11608 test-compare-reg-with-literal: +11609 # compare var1/ecx 0x34 +11610 # => +11611 # 81 7/subop/compare %ecx 0x34/imm32 +11612 # +11613 # . prologue +11614 55/push-ebp +11615 89/<- %ebp 4/r32/esp +11616 # setup +11617 (clear-stream _test-output-stream) +11618 (clear-stream $_test-output-buffered-file->buffer) +11619 # var type/ecx: (handle tree type-id) = int +11620 68/push 0/imm32/right/null +11621 68/push 1/imm32/left/int +11622 68/push 1/imm32/is-atom +11623 89/<- %ecx 4/r32/esp +11624 # var var-var1/ecx: var in ecx +11625 68/push "ecx"/imm32/register +11626 68/push 0/imm32/no-stack-offset +11627 68/push 1/imm32/block-depth +11628 51/push-ecx +11629 68/push "var1"/imm32 +11630 89/<- %ecx 4/r32/esp +11631 # var type/edx: (handle tree type-id) = literal +11632 68/push 0/imm32/right/null +11633 68/push 0/imm32/left/literal +11634 89/<- %edx 4/r32/esp +11635 # var var-var2/edx: var literal +11636 68/push 0/imm32/no-register +11637 68/push 0/imm32/no-stack-offset +11638 68/push 1/imm32/block-depth +11639 52/push-edx +11640 68/push "0x34"/imm32 +11641 89/<- %edx 4/r32/esp +11642 # var inouts/esi: (handle stmt-var) = [var2] +11643 68/push 0/imm32/is-deref:false +11644 68/push 0/imm32/next +11645 52/push-edx/var-var2 +11646 89/<- %esi 4/r32/esp +11647 # inouts = [var1, var2] +11648 68/push 0/imm32/is-deref:false +11649 56/push-esi/next +11650 51/push-ecx/var-var1 +11651 89/<- %esi 4/r32/esp +11652 # var stmt/esi: statement +11653 68/push 0/imm32/next +11654 68/push 0/imm32/outputs +11655 56/push-esi/inouts +11656 68/push "compare"/imm32/operation +11657 68/push 1/imm32/regular-stmt +11658 89/<- %esi 4/r32/esp +11659 # convert +11660 c7 0/subop/copy *Curr-block-depth 0/imm32 +11661 (emit-subx-stmt _test-output-buffered-file %esi Primitives) +11662 (flush _test-output-buffered-file) +11663 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +11669 # check output +11670 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") +11671 # . epilogue +11672 89/<- %esp 5/r32/ebp +11673 5d/pop-to-ebp +11674 c3/return +11675 +11676 test-emit-subx-stmt-function-call: +11677 # Call a function on a variable on the stack. +11678 # f foo +11679 # => +11680 # (f *(ebp-8)) +11681 # (Changing the function name supports overloading in general, but here it +11682 # just serves to help disambiguate things.) +11683 # +11684 # There's a variable on the var stack as follows: +11685 # name: 'foo' +11686 # type: int +11687 # stack-offset: -8 +11688 # +11689 # There's nothing in primitives. +11690 # +11691 # We don't perform any checking here on the type of 'f'. +11692 # +11693 # . prologue +11694 55/push-ebp +11695 89/<- %ebp 4/r32/esp +11696 # setup +11697 (clear-stream _test-output-stream) +11698 (clear-stream $_test-output-buffered-file->buffer) +11699 # var type/ecx: (handle tree type-id) = int +11700 68/push 0/imm32/right/null +11701 68/push 1/imm32/left/int +11702 68/push 1/imm32/is-atom +11703 89/<- %ecx 4/r32/esp +11704 # var var-foo/ecx: var +11705 68/push 0/imm32/no-register +11706 68/push -8/imm32/stack-offset +11707 68/push 0/imm32/block-depth +11708 51/push-ecx +11709 68/push "foo"/imm32 +11710 89/<- %ecx 4/r32/esp +11711 # var inouts/esi: (handle stmt-var) +11712 68/push 0/imm32/is-deref:false +11713 68/push 0/imm32/next +11714 51/push-ecx/var-foo +11715 89/<- %esi 4/r32/esp +11716 # var stmt/esi: statement +11717 68/push 0/imm32/next +11718 68/push 0/imm32/outputs +11719 56/push-esi/inouts +11720 68/push "f"/imm32/operation +11721 68/push 1/imm32 +11722 89/<- %esi 4/r32/esp +11723 # convert +11724 c7 0/subop/copy *Curr-block-depth 0/imm32 +11725 (emit-subx-stmt _test-output-buffered-file %esi 0) +11726 (flush _test-output-buffered-file) +11727 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +11733 # check output +11734 (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call") +11735 # . epilogue +11736 89/<- %esp 5/r32/ebp +11737 5d/pop-to-ebp +11738 c3/return +11739 +11740 test-emit-subx-stmt-function-call-with-literal-arg: +11741 # Call a function on a literal. +11742 # f 34 +11743 # => +11744 # (f2 34) +11745 # +11746 # . prologue +11747 55/push-ebp +11748 89/<- %ebp 4/r32/esp +11749 # setup +11750 (clear-stream _test-output-stream) +11751 (clear-stream $_test-output-buffered-file->buffer) +11752 # var type/ecx: (handle tree type-id) = literal +11753 68/push 0/imm32/right/null +11754 68/push 0/imm32/left/literal +11755 89/<- %ecx 4/r32/esp +11756 # var var-foo/ecx: var literal +11757 68/push 0/imm32/no-register +11758 68/push 0/imm32/no-stack-offset +11759 68/push 0/imm32/block-depth +11760 51/push-ecx +11761 68/push "34"/imm32 +11762 89/<- %ecx 4/r32/esp +11763 # var inouts/esi: (handle stmt-var) +11764 68/push 0/imm32/is-deref:false +11765 68/push 0/imm32/next +11766 51/push-ecx/var-foo +11767 89/<- %esi 4/r32/esp +11768 # var stmt/esi: statement +11769 68/push 0/imm32/next +11770 68/push 0/imm32/outputs +11771 56/push-esi/inouts +11772 68/push "f"/imm32/operation +11773 68/push 1/imm32 +11774 89/<- %esi 4/r32/esp +11775 # convert +11776 c7 0/subop/copy *Curr-block-depth 0/imm32 +11777 (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx) +11778 (flush _test-output-buffered-file) +11779 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +11785 # check output +11786 (check-next-stream-line-equal _test-output-stream "(f 34)" "F - test-emit-subx-stmt-function-call-with-literal-arg") +11787 # . epilogue +11788 89/<- %esp 5/r32/ebp +11789 5d/pop-to-ebp +11790 c3/return +11791 +11792 emit-indent: # out: (addr buffered-file), n: int +11793 # . prologue +11794 55/push-ebp +11795 89/<- %ebp 4/r32/esp +11796 # . save registers +11797 50/push-eax +11798 # var i/eax: int = n +11799 8b/-> *(ebp+0xc) 0/r32/eax +11800 { +11801 # if (i <= 0) break +11802 3d/compare-eax-with 0/imm32 +11803 7e/jump-if-<= break/disp8 +11804 (write-buffered *(ebp+8) " ") +11805 48/decrement-eax +11806 eb/jump loop/disp8 +11807 } +11808 $emit-indent:end: +11809 # . restore registers +11810 58/pop-to-eax +11811 # . epilogue +11812 89/<- %esp 5/r32/ebp +11813 5d/pop-to-ebp +11814 c3/return +11815 +11816 emit-subx-prologue: # out: (addr buffered-file) +11817 # . prologue +11818 55/push-ebp +11819 89/<- %ebp 4/r32/esp +11820 # +11821 (write-buffered *(ebp+8) " # . prologue\n") +11822 (write-buffered *(ebp+8) " 55/push-ebp\n") +11823 (write-buffered *(ebp+8) " 89/<- %ebp 4/r32/esp\n") +11824 $emit-subx-prologue:end: +11825 # . epilogue +11826 89/<- %esp 5/r32/ebp +11827 5d/pop-to-ebp +11828 c3/return +11829 +11830 emit-subx-epilogue: # out: (addr buffered-file) +11831 # . prologue +11832 55/push-ebp +11833 89/<- %ebp 4/r32/esp +11834 # +11835 (write-buffered *(ebp+8) " # . epilogue\n") +11836 (write-buffered *(ebp+8) " 89/<- %esp 5/r32/ebp\n") +11837 (write-buffered *(ebp+8) " 5d/pop-to-ebp\n") +11838 (write-buffered *(ebp+8) " c3/return\n") +11839 $emit-subx-epilogue:end: +11840 # . epilogue +11841 89/<- %esp 5/r32/ebp +11842 5d/pop-to-ebp +11843 c3/return -- cgit 1.4.1-2-gfad0