From f59df9cb75123f02e670aade75fe16abb25f4d83 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Thu, 20 Feb 2020 18:46:19 -0800 Subject: 6038 --- html/apps/mu.subx.html | 16425 ++++++++++++++++++++++++----------------------- 1 file changed, 8313 insertions(+), 8112 deletions(-) (limited to 'html/apps') diff --git a/html/apps/mu.subx.html b/html/apps/mu.subx.html index 6373baf8..97ded5df 100644 --- a/html/apps/mu.subx.html +++ b/html/apps/mu.subx.html @@ -355,9 +355,9 @@ if ('onhashchange' in window) { 293 294 Stmt1-operation: # (handle array byte) 295 4/imm32 - 296 Stmt1-inouts: # (handle list var) + 296 Stmt1-inouts: # (handle stmt-var) 297 8/imm32 - 298 Stmt1-outputs: # (handle list var) + 298 Stmt1-outputs: # (handle stmt-var) 299 0xc/imm32 300 301 Vardef-var: # (handle var) @@ -365,9 +365,9 @@ if ('onhashchange' in window) { 303 304 Regvardef-operation: # (handle array byte) 305 4/imm32 - 306 Regvardef-inouts: # (handle list var) + 306 Regvardef-inouts: # (handle stmt-var) 307 8/imm32 - 308 Regvardef-outputs: # (handle list var) # will have exactly one element + 308 Regvardef-outputs: # (handle stmt-var) # will have exactly one element 309 0xc/imm32 310 311 Stmt-size: # (addr int) @@ -386,7 +386,7 @@ if ('onhashchange' in window) { 324 Var-size: # (addr int) 325 0x14/imm32 326 - 327 Any-register: # "*" + 327 Any-register: # wildcard 328 # size 329 1/imm32 330 # data @@ -399,3942 +399,3937 @@ if ('onhashchange' in window) { 337 List-size: # (addr int) 338 8/imm32 339 - 340 # Types are expressed as trees (s-expressions) of type-ids (ints). - 341 # However, there's no need for singletons, so we can assume (int) == int - 342 # - if x->right == nil, x is an atom - 343 # - x->left contains either a pointer to a pair, or an atomic type-id directly. - 344 # type ids will be less than 0x10000 (MAX_TYPE_ID). - 345 - 346 Tree-left: # either type-id or (addr tree type-id) - 347 0/imm32 - 348 Tree-right: # (addr tree type-id) - 349 4/imm32 - 350 Tree-size: # (addr int) - 351 8/imm32 - 352 - 353 Max-type-id: - 354 0x10000/imm32 + 340 # A stmt-var is like a list of vars with call-site specific metadata + 341 Stmt-var-value: # (handle var) + 342 0/imm32 + 343 Stmt-var-next: # (handle stmt-var) + 344 4/imm32 + 345 Stmt-var-is-deref: # boolean + 346 8/imm32 + 347 Stmt-var-size: # (addr int) + 348 0xc/imm32 + 349 + 350 # Types are expressed as trees (s-expressions) of type-ids (ints). + 351 # However, there's no need for singletons, so we can assume (int) == int + 352 # - if x->right == nil, x is an atom + 353 # - x->left contains either a pointer to a pair, or an atomic type-id directly. + 354 # type ids will be less than 0x10000 (MAX_TYPE_ID). 355 - 356 == code - 357 - 358 Entry: - 359 # . prologue - 360 89/<- %ebp 4/r32/esp - 361 (new-segment *Heap-size Heap) - 362 # if (argv[1] == "test') run-tests() - 363 { - 364 # if (argc <= 1) break - 365 81 7/subop/compare *ebp 1/imm32 - 366 7e/jump-if-<= break/disp8 - 367 # if (argv[1] != "test") break - 368 (kernel-string-equal? *(ebp+8) "test") # => eax - 369 3d/compare-eax-and 0/imm32/false - 370 74/jump-if-= break/disp8 - 371 # - 372 (run-tests) - 373 # syscall(exit, *Num-test-failures) - 374 8b/-> *Num-test-failures 3/r32/ebx - 375 eb/jump $mu-main:end/disp8 - 376 } - 377 # otherwise convert Stdin - 378 (convert-mu Stdin Stdout) - 379 (flush Stdout) - 380 # syscall(exit, 0) - 381 bb/copy-to-ebx 0/imm32 - 382 $mu-main:end: - 383 b8/copy-to-eax 1/imm32/exit - 384 cd/syscall 0x80/imm8 - 385 - 386 convert-mu: # in: (addr buffered-file), out: (addr buffered-file) - 387 # . prologue - 388 55/push-ebp - 389 89/<- %ebp 4/r32/esp - 390 # - 391 (parse-mu *(ebp+8)) - 392 (check-mu-types) - 393 (emit-subx *(ebp+0xc)) - 394 $convert-mu:end: - 395 # . epilogue - 396 89/<- %esp 5/r32/ebp - 397 5d/pop-to-ebp - 398 c3/return - 399 - 400 test-convert-empty-input: - 401 # empty input => empty output - 402 # . prologue - 403 55/push-ebp - 404 89/<- %ebp 4/r32/esp - 405 # setup - 406 (clear-stream _test-input-stream) - 407 (clear-stream $_test-input-buffered-file->buffer) - 408 (clear-stream _test-output-stream) - 409 (clear-stream $_test-output-buffered-file->buffer) - 410 # - 411 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 412 (flush _test-output-buffered-file) - 413 (check-stream-equal _test-output-stream "" "F - test-convert-empty-input") - 414 # . epilogue - 415 89/<- %esp 5/r32/ebp - 416 5d/pop-to-ebp - 417 c3/return - 418 - 419 test-convert-function-skeleton: - 420 # . prologue - 421 55/push-ebp - 422 89/<- %ebp 4/r32/esp - 423 # setup - 424 (clear-stream _test-input-stream) - 425 (clear-stream $_test-input-buffered-file->buffer) - 426 (clear-stream _test-output-stream) - 427 (clear-stream $_test-output-buffered-file->buffer) - 428 # - 429 (write _test-input-stream "fn foo {\n") - 430 (write _test-input-stream "}\n") - 431 # convert - 432 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 433 (flush _test-output-buffered-file) - 434 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 440 # check output - 441 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-skeleton/0") - 442 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-skeleton/1") - 443 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-skeleton/2") - 444 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-skeleton/3") - 445 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-skeleton/4") - 446 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-skeleton/5") - 447 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-skeleton/6") - 448 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-skeleton/7") - 449 # . epilogue - 450 89/<- %esp 5/r32/ebp - 451 5d/pop-to-ebp - 452 c3/return - 453 - 454 test-convert-multiple-function-skeletons: - 455 # . prologue - 456 55/push-ebp - 457 89/<- %ebp 4/r32/esp - 458 # setup - 459 (clear-stream _test-input-stream) - 460 (clear-stream $_test-input-buffered-file->buffer) - 461 (clear-stream _test-output-stream) - 462 (clear-stream $_test-output-buffered-file->buffer) - 463 # - 464 (write _test-input-stream "fn foo {\n") - 465 (write _test-input-stream "}\n") - 466 (write _test-input-stream "fn bar {\n") - 467 (write _test-input-stream "}\n") - 468 # convert - 469 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 470 (flush _test-output-buffered-file) - 471 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 477 # check first function - 478 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-multiple-function-skeletons/0") - 479 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/1") - 480 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/2") - 481 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/3") - 482 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/4") - 483 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/5") - 484 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/6") - 485 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/7") - 486 # check second function - 487 (check-next-stream-line-equal _test-output-stream "bar:" "F - test-convert-multiple-function-skeletons/10") - 488 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/11") - 489 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/12") - 490 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/13") - 491 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/14") - 492 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/15") - 493 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/16") - 494 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/17") - 495 # . epilogue - 496 89/<- %esp 5/r32/ebp - 497 5d/pop-to-ebp - 498 c3/return - 499 - 500 test-convert-function-with-arg: - 501 # . prologue - 502 55/push-ebp - 503 89/<- %ebp 4/r32/esp - 504 # setup - 505 (clear-stream _test-input-stream) - 506 (clear-stream $_test-input-buffered-file->buffer) - 507 (clear-stream _test-output-stream) - 508 (clear-stream $_test-output-buffered-file->buffer) - 509 # - 510 (write _test-input-stream "fn foo n: int {\n") - 511 (write _test-input-stream "}\n") - 512 # convert - 513 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 514 (flush _test-output-buffered-file) - 515 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 521 # check output - 522 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg/0") - 523 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg/1") - 524 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg/2") - 525 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg/3") - 526 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg/4") - 527 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg/5") - 528 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg/6") - 529 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg/7") - 530 # . epilogue - 531 89/<- %esp 5/r32/ebp - 532 5d/pop-to-ebp - 533 c3/return - 534 - 535 test-convert-function-with-arg-and-body: - 536 # . prologue - 537 55/push-ebp - 538 89/<- %ebp 4/r32/esp - 539 # setup - 540 (clear-stream _test-input-stream) - 541 (clear-stream $_test-input-buffered-file->buffer) - 542 (clear-stream _test-output-stream) - 543 (clear-stream $_test-output-buffered-file->buffer) - 544 c7 0/subop/copy *Next-block-index 1/imm32 - 545 # - 546 (write _test-input-stream "fn foo n: int {\n") - 547 (write _test-input-stream " increment n\n") - 548 (write _test-input-stream "}\n") - 549 # convert - 550 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 551 (flush _test-output-buffered-file) - 552 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 558 # check output - 559 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg-and-body/0") - 560 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg-and-body/1") - 561 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg-and-body/2") - 562 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg-and-body/3") - 563 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-arg-and-body/4") - 564 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-arg-and-body/5") - 565 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-arg-and-body/6") - 566 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-arg-and-body/7") - 567 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-arg-and-body/8") - 568 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg-and-body/9") - 569 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg-and-body/10") - 570 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg-and-body/11") - 571 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg-and-body/12") - 572 # . epilogue - 573 89/<- %esp 5/r32/ebp - 574 5d/pop-to-ebp - 575 c3/return - 576 - 577 test-convert-function-distinguishes-args: - 578 # . prologue - 579 55/push-ebp - 580 89/<- %ebp 4/r32/esp - 581 # setup - 582 (clear-stream _test-input-stream) - 583 (clear-stream $_test-input-buffered-file->buffer) - 584 (clear-stream _test-output-stream) - 585 (clear-stream $_test-output-buffered-file->buffer) - 586 c7 0/subop/copy *Next-block-index 1/imm32 - 587 # - 588 (write _test-input-stream "fn foo a: int, b: int {\n") - 589 (write _test-input-stream " increment b\n") - 590 (write _test-input-stream "}\n") - 591 # convert - 592 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 593 (flush _test-output-buffered-file) - 594 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 600 # check output - 601 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-distinguishes-args/0") - 602 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-distinguishes-args/1") - 603 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-distinguishes-args/2") - 604 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-distinguishes-args/3") - 605 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-distinguishes-args/4") - 606 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-distinguishes-args/5") - 607 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x0000000c)" "F - test-convert-function-distinguishes-args/6") - 608 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-distinguishes-args/7") - 609 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-distinguishes-args/8") - 610 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-distinguishes-args/9") - 611 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-distinguishes-args/10") - 612 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-distinguishes-args/11") - 613 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-distinguishes-args/12") - 614 # . epilogue - 615 89/<- %esp 5/r32/ebp - 616 5d/pop-to-ebp - 617 c3/return - 618 - 619 test-convert-function-returns-result: - 620 # . prologue - 621 55/push-ebp - 622 89/<- %ebp 4/r32/esp - 623 # setup - 624 (clear-stream _test-input-stream) - 625 (clear-stream $_test-input-buffered-file->buffer) - 626 (clear-stream _test-output-stream) - 627 (clear-stream $_test-output-buffered-file->buffer) - 628 c7 0/subop/copy *Next-block-index 1/imm32 - 629 # - 630 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") - 631 (write _test-input-stream " result <- copy a\n") - 632 (write _test-input-stream " result <- increment\n") - 633 (write _test-input-stream "}\n") - 634 # convert - 635 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 636 (flush _test-output-buffered-file) - 637 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 643 # check output - 644 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-returns-result/0") - 645 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-returns-result/1") - 646 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-returns-result/2") - 647 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-returns-result/3") - 648 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-returns-result/4") - 649 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-returns-result/5") - 650 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-returns-result/6") - 651 (check-next-stream-line-equal _test-output-stream " 40/increment-eax" "F - test-convert-function-returns-result/7") - 652 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-returns-result/8") - 653 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-returns-result/9") - 654 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-returns-result/10") - 655 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-returns-result/11") - 656 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-returns-result/12") - 657 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-returns-result/13") - 658 # . epilogue - 659 89/<- %esp 5/r32/ebp - 660 5d/pop-to-ebp - 661 c3/return - 662 - 663 test-convert-function-literal-arg: - 664 # . prologue - 665 55/push-ebp - 666 89/<- %ebp 4/r32/esp - 667 # setup - 668 (clear-stream _test-input-stream) - 669 (clear-stream $_test-input-buffered-file->buffer) - 670 (clear-stream _test-output-stream) - 671 (clear-stream $_test-output-buffered-file->buffer) - 672 c7 0/subop/copy *Next-block-index 1/imm32 - 673 # - 674 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") - 675 (write _test-input-stream " result <- copy a\n") - 676 (write _test-input-stream " result <- add 1\n") - 677 (write _test-input-stream "}\n") - 678 # convert - 679 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 680 (flush _test-output-buffered-file) - 681 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 687 # check output - 688 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-literal-arg/0") - 689 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-literal-arg/1") - 690 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-literal-arg/2") - 691 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-literal-arg/3") - 692 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-literal-arg/4") - 693 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-literal-arg/5") - 694 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-literal-arg/6") - 695 (check-next-stream-line-equal _test-output-stream " 05/add-to-eax 1/imm32" "F - test-convert-function-literal-arg/7") - 696 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-literal-arg/8") - 697 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-literal-arg/9") - 698 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-literal-arg/10") - 699 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-literal-arg/11") - 700 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-literal-arg/12") - 701 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-literal-arg/13") - 702 # . epilogue - 703 89/<- %esp 5/r32/ebp - 704 5d/pop-to-ebp - 705 c3/return - 706 - 707 test-convert-function-literal-arg-2: - 708 # . prologue - 709 55/push-ebp - 710 89/<- %ebp 4/r32/esp - 711 # setup - 712 (clear-stream _test-input-stream) - 713 (clear-stream $_test-input-buffered-file->buffer) - 714 (clear-stream _test-output-stream) - 715 (clear-stream $_test-output-buffered-file->buffer) - 716 c7 0/subop/copy *Next-block-index 1/imm32 - 717 # - 718 (write _test-input-stream "fn foo a: int, b: int -> result/ebx: int {\n") - 719 (write _test-input-stream " result <- copy a\n") - 720 (write _test-input-stream " result <- add 1\n") - 721 (write _test-input-stream "}\n") - 722 # convert - 723 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 724 (flush _test-output-buffered-file) - 725 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 731 # check output - 732 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-literal-arg-2/0") - 733 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-literal-arg-2/1") - 734 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-literal-arg-2/2") - 735 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-literal-arg-2/3") - 736 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-literal-arg-2/4") - 737 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-literal-arg-2/5") - 738 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-literal-arg-2/6") - 739 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %ebx 1/imm32" "F - test-convert-function-literal-arg-2/7") - 740 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-literal-arg-2/8") - 741 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-literal-arg-2/9") - 742 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-literal-arg-2/10") - 743 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-literal-arg-2/11") - 744 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-literal-arg-2/12") - 745 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-literal-arg-2/13") - 746 # . epilogue - 747 89/<- %esp 5/r32/ebp - 748 5d/pop-to-ebp - 749 c3/return - 750 - 751 test-convert-function-call-with-literal-arg: - 752 # . prologue - 753 55/push-ebp - 754 89/<- %ebp 4/r32/esp - 755 # setup - 756 (clear-stream _test-input-stream) - 757 (clear-stream $_test-input-buffered-file->buffer) - 758 (clear-stream _test-output-stream) - 759 (clear-stream $_test-output-buffered-file->buffer) - 760 c7 0/subop/copy *Next-block-index 1/imm32 - 761 # - 762 (write _test-input-stream "fn main -> result/ebx: int {\n") - 763 (write _test-input-stream " result <- do-add 3 4\n") - 764 (write _test-input-stream "}\n") - 765 (write _test-input-stream "fn do-add a: int, b: int -> result/ebx: int {\n") - 766 (write _test-input-stream " result <- copy a\n") - 767 (write _test-input-stream " result <- add b\n") - 768 (write _test-input-stream "}\n") - 769 # convert - 770 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 771 (flush _test-output-buffered-file) - 772 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 778 # check output - 779 (check-next-stream-line-equal _test-output-stream "main:" "F - test-convert-function-call-with-literal-arg/0") - 780 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/1") - 781 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/2") - 782 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/3") - 783 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/4") - 784 (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:" "F - test-convert-function-call-with-literal-arg/5") - 785 (check-next-stream-line-equal _test-output-stream " (do-add 3 4)" "F - test-convert-function-call-with-literal-arg/6") - 786 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/7") - 787 (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/8") - 788 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/9") - 789 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/10") - 790 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/11") - 791 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/12") - 792 (check-next-stream-line-equal _test-output-stream "do-add:" "F - test-convert-function-call-with-literal-arg/13") - 793 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/14") - 794 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/15") - 795 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/16") - 796 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/17") - 797 (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:" "F - test-convert-function-call-with-literal-arg/18") - 798 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/19") - 799 (check-next-stream-line-equal _test-output-stream " 03/add *(ebp+0x0000000c) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/20") - 800 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/21") - 801 (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:" "F - test-convert-function-call-with-literal-arg/22") - 802 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/23") - 803 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/24") - 804 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/25") - 805 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/26") - 806 # . epilogue - 807 89/<- %esp 5/r32/ebp - 808 5d/pop-to-ebp - 809 c3/return - 810 - 811 test-convert-function-with-local-var-in-mem: - 812 # . prologue - 813 55/push-ebp - 814 89/<- %ebp 4/r32/esp - 815 # setup - 816 (clear-stream _test-input-stream) - 817 (clear-stream $_test-input-buffered-file->buffer) - 818 (clear-stream _test-output-stream) - 819 (clear-stream $_test-output-buffered-file->buffer) - 820 c7 0/subop/copy *Next-block-index 1/imm32 - 821 # - 822 (write _test-input-stream "fn foo {\n") - 823 (write _test-input-stream " var x: int\n") - 824 (write _test-input-stream " increment x\n") - 825 (write _test-input-stream "}\n") - 826 # convert - 827 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 828 (flush _test-output-buffered-file) - 829 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 835 # check output - 836 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-mem/0") - 837 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-mem/1") - 838 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-mem/2") - 839 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-mem/3") - 840 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-mem/4") - 841 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-mem/5") - 842 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-mem/6") - 843 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-mem/7") - 844 (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") - 845 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-mem/9") - 846 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-mem/10") - 847 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-mem/11") - 848 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-mem/12") - 849 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-mem/13") - 850 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-mem/14") - 851 # . epilogue - 852 89/<- %esp 5/r32/ebp - 853 5d/pop-to-ebp - 854 c3/return - 855 - 856 test-convert-function-with-local-var-in-reg: - 857 # . prologue - 858 55/push-ebp - 859 89/<- %ebp 4/r32/esp - 860 # setup - 861 (clear-stream _test-input-stream) - 862 (clear-stream $_test-input-buffered-file->buffer) - 863 (clear-stream _test-output-stream) - 864 (clear-stream $_test-output-buffered-file->buffer) - 865 c7 0/subop/copy *Next-block-index 1/imm32 - 866 # - 867 (write _test-input-stream "fn foo {\n") - 868 (write _test-input-stream " var x/ecx: int <- copy 3\n") - 869 (write _test-input-stream " x <- increment\n") - 870 (write _test-input-stream "}\n") - 871 # convert - 872 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 873 (flush _test-output-buffered-file) - 874 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 880 # check output - 881 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-reg/0") - 882 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-reg/1") - 883 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-reg/2") - 884 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-reg/3") - 885 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-reg/4") - 886 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-reg/5") - 887 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-local-var-in-reg/6") - 888 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-function-with-local-var-in-reg/7") - 889 (check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-convert-function-with-local-var-in-reg/8") - 890 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9") - 891 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-reg/10") - 892 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-reg/11") - 893 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-reg/12") - 894 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-reg/13") - 895 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-reg/14") - 896 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-reg/15") - 897 # . epilogue - 898 89/<- %esp 5/r32/ebp - 899 5d/pop-to-ebp - 900 c3/return - 901 - 902 test-convert-function-with-local-var-in-block: - 903 # . prologue - 904 55/push-ebp - 905 89/<- %ebp 4/r32/esp - 906 # setup - 907 (clear-stream _test-input-stream) - 908 (clear-stream $_test-input-buffered-file->buffer) - 909 (clear-stream _test-output-stream) - 910 (clear-stream $_test-output-buffered-file->buffer) - 911 c7 0/subop/copy *Next-block-index 1/imm32 - 912 # - 913 (write _test-input-stream "fn foo {\n") - 914 (write _test-input-stream " {\n") - 915 (write _test-input-stream " var x: int\n") - 916 (write _test-input-stream " increment x\n") - 917 (write _test-input-stream " }\n") - 918 (write _test-input-stream "}\n") - 919 # convert - 920 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 921 (flush _test-output-buffered-file) - 922 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 928 # check output - 929 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-block/0") - 930 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-block/1") - 931 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-block/2") - 932 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-block/3") - 933 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/4") - 934 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-block/5") - 935 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/6") - 936 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-local-var-in-block/7") - 937 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-block/8") - 938 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-block/9") - 939 (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") - 940 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/11") - 941 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-local-var-in-block/12") - 942 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/13") - 943 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-block/14") - 944 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-block/15") - 945 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-block/16") - 946 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-block/17") - 947 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-block/18") - 948 # . epilogue - 949 89/<- %esp 5/r32/ebp - 950 5d/pop-to-ebp - 951 c3/return - 952 - 953 test-convert-function-with-local-var-in-named-block: - 954 # . prologue - 955 55/push-ebp - 956 89/<- %ebp 4/r32/esp - 957 # setup - 958 (clear-stream _test-input-stream) - 959 (clear-stream $_test-input-buffered-file->buffer) - 960 (clear-stream _test-output-stream) - 961 (clear-stream $_test-output-buffered-file->buffer) - 962 c7 0/subop/copy *Next-block-index 1/imm32 - 963 # - 964 (write _test-input-stream "fn foo {\n") - 965 (write _test-input-stream " $bar: {\n") - 966 (write _test-input-stream " var x: int\n") - 967 (write _test-input-stream " increment x\n") - 968 (write _test-input-stream " }\n") - 969 (write _test-input-stream "}\n") - 970 # convert - 971 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 972 (flush _test-output-buffered-file) - 973 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 979 # check output - 980 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-named-block/0") - 981 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-named-block/1") - 982 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-named-block/2") - 983 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-named-block/3") - 984 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/4") - 985 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-named-block/5") - 986 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/6") - 987 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-local-var-in-named-block/7") - 988 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-named-block/8") - 989 (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") - 990 (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") - 991 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/11") - 992 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-local-var-in-named-block/12") - 993 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/13") - 994 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-named-block/14") - 995 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-named-block/15") - 996 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-named-block/16") - 997 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-named-block/17") - 998 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-named-block/18") - 999 # . epilogue -1000 89/<- %esp 5/r32/ebp -1001 5d/pop-to-ebp -1002 c3/return -1003 -1004 test-convert-function-with-branches-in-block: -1005 # . prologue -1006 55/push-ebp -1007 89/<- %ebp 4/r32/esp -1008 # setup -1009 (clear-stream _test-input-stream) -1010 (clear-stream $_test-input-buffered-file->buffer) -1011 (clear-stream _test-output-stream) -1012 (clear-stream $_test-output-buffered-file->buffer) -1013 c7 0/subop/copy *Next-block-index 1/imm32 -1014 # -1015 (write _test-input-stream "fn foo x: int {\n") -1016 (write _test-input-stream " {\n") -1017 (write _test-input-stream " break-if->=\n") -1018 (write _test-input-stream " loop-if-addr<\n") -1019 (write _test-input-stream " increment x\n") -1020 (write _test-input-stream " loop\n") -1021 (write _test-input-stream " }\n") -1022 (write _test-input-stream "}\n") -1023 # convert -1024 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1025 (flush _test-output-buffered-file) -1026 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1032 # check output -1033 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-block/0") -1034 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-block/1") -1035 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-block/2") -1036 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-block/3") -1037 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/4") -1038 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-in-block/5") -1039 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/6") -1040 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-in-block/7") -1041 (check-next-stream-line-equal _test-output-stream " 0f 8d/jump-if->= break/disp32" "F - test-convert-function-with-branches-in-block/8") -1042 (check-next-stream-line-equal _test-output-stream " 0f 82/jump-if-addr< loop/disp32" "F - test-convert-function-with-branches-in-block/9") -1043 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-block/10") -1044 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-block/11") -1045 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/12") -1046 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-in-block/13") -1047 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/14") -1048 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-in-block/15") -1049 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-block/16") -1050 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-block/17") -1051 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-block/18") -1052 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-block/19") -1053 # . epilogue -1054 89/<- %esp 5/r32/ebp -1055 5d/pop-to-ebp -1056 c3/return -1057 -1058 test-convert-function-with-branches-in-named-block: -1059 # . prologue -1060 55/push-ebp -1061 89/<- %ebp 4/r32/esp -1062 # setup -1063 (clear-stream _test-input-stream) -1064 (clear-stream $_test-input-buffered-file->buffer) -1065 (clear-stream _test-output-stream) -1066 (clear-stream $_test-output-buffered-file->buffer) -1067 c7 0/subop/copy *Next-block-index 1/imm32 -1068 # -1069 (write _test-input-stream "fn foo x: int {\n") -1070 (write _test-input-stream " $bar: {\n") -1071 (write _test-input-stream " break-if->= $bar\n") -1072 (write _test-input-stream " loop-if-addr< $bar\n") -1073 (write _test-input-stream " increment x\n") -1074 (write _test-input-stream " loop\n") -1075 (write _test-input-stream " }\n") -1076 (write _test-input-stream "}\n") -1077 # convert -1078 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1079 (flush _test-output-buffered-file) -1080 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1086 # check output -1087 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-named-block/0") -1088 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-named-block/1") -1089 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-named-block/2") -1090 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-named-block/3") -1091 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/4") -1092 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-in-named-block/5") -1093 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/6") -1094 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-branches-in-named-block/7") -1095 (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") -1096 (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") -1097 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-named-block/10") -1098 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-named-block/11") -1099 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/12") -1100 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-branches-in-named-block/13") -1101 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/14") -1102 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-in-named-block/15") -1103 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-named-block/16") -1104 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-named-block/17") -1105 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-named-block/18") -1106 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-named-block/19") -1107 # . epilogue -1108 89/<- %esp 5/r32/ebp -1109 5d/pop-to-ebp -1110 c3/return -1111 -1112 test-convert-function-with-var-in-nested-block: -1113 # . prologue -1114 55/push-ebp -1115 89/<- %ebp 4/r32/esp -1116 # setup -1117 (clear-stream _test-input-stream) -1118 (clear-stream $_test-input-buffered-file->buffer) -1119 (clear-stream _test-output-stream) -1120 (clear-stream $_test-output-buffered-file->buffer) -1121 c7 0/subop/copy *Next-block-index 1/imm32 -1122 # -1123 (write _test-input-stream "fn foo x: int {\n") -1124 (write _test-input-stream " {\n") -1125 (write _test-input-stream " {\n") -1126 (write _test-input-stream " var x: int\n") -1127 (write _test-input-stream " increment x\n") -1128 (write _test-input-stream " }\n") -1129 (write _test-input-stream " }\n") -1130 (write _test-input-stream "}\n") -1131 # convert -1132 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1133 (flush _test-output-buffered-file) -1134 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1140 # check output -1141 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-var-in-nested-block/0") -1142 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-var-in-nested-block/1") -1143 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-var-in-nested-block/2") -1144 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-var-in-nested-block/3") -1145 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/4") -1146 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-var-in-nested-block/5") -1147 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/6") -1148 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-var-in-nested-block/7") -1149 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/8") -1150 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-var-in-nested-block/9") -1151 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10") -1152 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-var-in-nested-block/11") -1153 (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") -1154 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/13") -1155 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-var-in-nested-block/14") -1156 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/15") -1157 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-var-in-nested-block/16") -1158 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/17") -1159 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-var-in-nested-block/18") -1160 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-var-in-nested-block/19") -1161 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-var-in-nested-block/20") -1162 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-var-in-nested-block/21") -1163 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-var-in-nested-block/22") -1164 # . epilogue -1165 89/<- %esp 5/r32/ebp -1166 5d/pop-to-ebp -1167 c3/return -1168 -1169 test-convert-function-with-multiple-vars-in-nested-blocks: -1170 # . prologue -1171 55/push-ebp -1172 89/<- %ebp 4/r32/esp -1173 # setup -1174 (clear-stream _test-input-stream) -1175 (clear-stream $_test-input-buffered-file->buffer) -1176 (clear-stream _test-output-stream) -1177 (clear-stream $_test-output-buffered-file->buffer) -1178 c7 0/subop/copy *Next-block-index 1/imm32 -1179 # -1180 (write _test-input-stream "fn foo x: int {\n") -1181 (write _test-input-stream " {\n") -1182 (write _test-input-stream " var x/eax: int <- copy 0\n") -1183 (write _test-input-stream " {\n") -1184 (write _test-input-stream " var y: int\n") -1185 (write _test-input-stream " x <- add y\n") -1186 (write _test-input-stream " }\n") -1187 (write _test-input-stream " }\n") -1188 (write _test-input-stream "}\n") -1189 # convert -1190 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1191 (flush _test-output-buffered-file) -1192 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1198 # check output -1199 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/0") -1200 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-multiple-vars-in-nested-blocks/1") -1201 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/2") -1202 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/3") -1203 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/4") -1204 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/5") -1205 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/6") -1206 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/7") -1207 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-with-multiple-vars-in-nested-blocks/8") -1208 (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") -1209 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/10") -1210 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/11") -1211 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12") -1212 (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") -1213 (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") -1214 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/15") -1215 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/16") -1216 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-with-multiple-vars-in-nested-blocks/17") -1217 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/18") -1218 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/19") -1219 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/20") -1220 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/21") -1221 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-multiple-vars-in-nested-blocks/22") -1222 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/23") -1223 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/24") -1224 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-multiple-vars-in-nested-blocks/25") -1225 # . epilogue -1226 89/<- %esp 5/r32/ebp -1227 5d/pop-to-ebp -1228 c3/return -1229 -1230 test-convert-function-with-branches-and-local-vars: -1231 # A conditional 'break' after a 'var' in a block is converted into a -1232 # nested block that performs all necessary cleanup before jumping. This -1233 # results in some ugly code duplication. -1234 # . prologue -1235 55/push-ebp -1236 89/<- %ebp 4/r32/esp -1237 # setup -1238 (clear-stream _test-input-stream) -1239 (clear-stream $_test-input-buffered-file->buffer) -1240 (clear-stream _test-output-stream) -1241 (clear-stream $_test-output-buffered-file->buffer) -1242 c7 0/subop/copy *Next-block-index 1/imm32 -1243 # -1244 (write _test-input-stream "fn foo {\n") -1245 (write _test-input-stream " {\n") -1246 (write _test-input-stream " var x: int\n") -1247 (write _test-input-stream " break-if->=\n") -1248 (write _test-input-stream " increment x\n") -1249 (write _test-input-stream " }\n") -1250 (write _test-input-stream "}\n") -1251 # convert -1252 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1253 (flush _test-output-buffered-file) -1254 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1260 # check output -1261 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-local-vars/0") -1262 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-local-vars/1") -1263 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-local-vars/2") -1264 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-and-local-vars/3") -1265 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/4") -1266 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-and-local-vars/5") -1267 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/6") -1268 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-and-local-vars/7") -1269 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-local-vars/8") -1270 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/9") -1271 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-branches-and-local-vars/10") -1272 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-branches-and-local-vars/11") -1273 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:break/disp32" "F - test-convert-function-with-branches-and-local-vars/12") -1274 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/13") -1275 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-branches-and-local-vars/14") -1276 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-branches-and-local-vars/15") -1277 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/16") -1278 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-and-local-vars/17") -1279 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/18") -1280 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-and-local-vars/19") -1281 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-local-vars/20") -1282 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-and-local-vars/21") -1283 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-local-vars/22") -1284 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-local-vars/23") -1285 # . epilogue -1286 89/<- %esp 5/r32/ebp -1287 5d/pop-to-ebp -1288 c3/return -1289 -1290 test-convert-function-with-conditional-loops-and-local-vars: -1291 # A conditional 'loop' after a 'var' in a block is converted into a nested -1292 # block that performs all necessary cleanup before jumping. This results -1293 # in some ugly code duplication. -1294 # . prologue -1295 55/push-ebp -1296 89/<- %ebp 4/r32/esp -1297 # setup -1298 (clear-stream _test-input-stream) -1299 (clear-stream $_test-input-buffered-file->buffer) -1300 (clear-stream _test-output-stream) -1301 (clear-stream $_test-output-buffered-file->buffer) -1302 c7 0/subop/copy *Next-block-index 1/imm32 -1303 # -1304 (write _test-input-stream "fn foo {\n") -1305 (write _test-input-stream " {\n") -1306 (write _test-input-stream " var x: int\n") -1307 (write _test-input-stream " loop-if->=\n") -1308 (write _test-input-stream " increment x\n") -1309 (write _test-input-stream " }\n") -1310 (write _test-input-stream "}\n") -1311 # convert -1312 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1313 (flush _test-output-buffered-file) -1314 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1320 # check output -1321 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-conditional-loops-and-local-vars/0") -1322 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-conditional-loops-and-local-vars/1") -1323 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/2") -1324 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-conditional-loops-and-local-vars/3") -1325 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/4") -1326 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-conditional-loops-and-local-vars/5") -1327 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/6") -1328 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-conditional-loops-and-local-vars/7") -1329 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-conditional-loops-and-local-vars/8") -1330 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/9") -1331 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-conditional-loops-and-local-vars/10") -1332 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-conditional-loops-and-local-vars/11") -1333 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:loop/disp32" "F - test-convert-function-with-conditional-loops-and-local-vars/12") -1334 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/13") -1335 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-conditional-loops-and-local-vars/14") -1336 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-conditional-loops-and-local-vars/15") -1337 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/16") -1338 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-conditional-loops-and-local-vars/17") -1339 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/18") -1340 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-conditional-loops-and-local-vars/19") -1341 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-conditional-loops-and-local-vars/20") -1342 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/21") -1343 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/22") -1344 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-conditional-loops-and-local-vars/23") -1345 # . epilogue -1346 89/<- %esp 5/r32/ebp -1347 5d/pop-to-ebp -1348 c3/return -1349 -1350 test-convert-function-with-unconditional-loops-and-local-vars: -1351 # An unconditional 'loop' after a 'var' in a block is emitted _after_ the -1352 # regular block cleanup. Any instructions after 'loop' are dead and -1353 # therefore skipped. -1354 # . prologue -1355 55/push-ebp -1356 89/<- %ebp 4/r32/esp -1357 # setup -1358 (clear-stream _test-input-stream) -1359 (clear-stream $_test-input-buffered-file->buffer) -1360 (clear-stream _test-output-stream) -1361 (clear-stream $_test-output-buffered-file->buffer) -1362 c7 0/subop/copy *Next-block-index 1/imm32 -1363 # -1364 (write _test-input-stream "fn foo {\n") -1365 (write _test-input-stream " {\n") -1366 (write _test-input-stream " var x: int\n") -1367 (write _test-input-stream " loop\n") -1368 (write _test-input-stream " increment x\n") -1369 (write _test-input-stream " }\n") -1370 (write _test-input-stream "}\n") -1371 # convert -1372 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1373 (flush _test-output-buffered-file) -1374 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1380 # check output -1381 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-unconditional-loops-and-local-vars/0") -1382 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-unconditional-loops-and-local-vars/1") -1383 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/2") -1384 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-unconditional-loops-and-local-vars/3") -1385 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-loops-and-local-vars/4") -1386 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-unconditional-loops-and-local-vars/5") -1387 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-loops-and-local-vars/6") -1388 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-unconditional-loops-and-local-vars/7") -1389 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-loops-and-local-vars/8") -1390 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-unconditional-loops-and-local-vars/9") -1391 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-unconditional-loops-and-local-vars/10") -1392 # not emitted: ff 0/subop/increment *(ebp+0xfffffffc) -1393 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-loops-and-local-vars/11") -1394 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-unconditional-loops-and-local-vars/12") -1395 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-loops-and-local-vars/13") -1396 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-unconditional-loops-and-local-vars/14") -1397 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-unconditional-loops-and-local-vars/15") -1398 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/16") -1399 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/17") -1400 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-unconditional-loops-and-local-vars/18") + 356 Tree-left: # either type-id or (addr tree type-id) + 357 0/imm32 + 358 Tree-right: # (addr tree type-id) + 359 4/imm32 + 360 Tree-size: # (addr int) + 361 8/imm32 + 362 + 363 Max-type-id: + 364 0x10000/imm32 + 365 + 366 == code + 367 + 368 Entry: + 369 # . prologue + 370 89/<- %ebp 4/r32/esp + 371 (new-segment *Heap-size Heap) + 372 # if (argv[1] == "test') run-tests() + 373 { + 374 # if (argc <= 1) break + 375 81 7/subop/compare *ebp 1/imm32 + 376 7e/jump-if-<= break/disp8 + 377 # if (argv[1] != "test") break + 378 (kernel-string-equal? *(ebp+8) "test") # => eax + 379 3d/compare-eax-and 0/imm32/false + 380 74/jump-if-= break/disp8 + 381 # + 382 (run-tests) + 383 # syscall(exit, *Num-test-failures) + 384 8b/-> *Num-test-failures 3/r32/ebx + 385 eb/jump $mu-main:end/disp8 + 386 } + 387 # otherwise convert Stdin + 388 (convert-mu Stdin Stdout) + 389 (flush Stdout) + 390 # syscall(exit, 0) + 391 bb/copy-to-ebx 0/imm32 + 392 $mu-main:end: + 393 b8/copy-to-eax 1/imm32/exit + 394 cd/syscall 0x80/imm8 + 395 + 396 convert-mu: # in: (addr buffered-file), out: (addr buffered-file) + 397 # . prologue + 398 55/push-ebp + 399 89/<- %ebp 4/r32/esp + 400 # + 401 (parse-mu *(ebp+8)) + 402 (check-mu-types) + 403 (emit-subx *(ebp+0xc)) + 404 $convert-mu:end: + 405 # . epilogue + 406 89/<- %esp 5/r32/ebp + 407 5d/pop-to-ebp + 408 c3/return + 409 + 410 test-convert-empty-input: + 411 # empty input => empty output + 412 # . prologue + 413 55/push-ebp + 414 89/<- %ebp 4/r32/esp + 415 # setup + 416 (clear-stream _test-input-stream) + 417 (clear-stream $_test-input-buffered-file->buffer) + 418 (clear-stream _test-output-stream) + 419 (clear-stream $_test-output-buffered-file->buffer) + 420 # + 421 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 422 (flush _test-output-buffered-file) + 423 (check-stream-equal _test-output-stream "" "F - test-convert-empty-input") + 424 # . epilogue + 425 89/<- %esp 5/r32/ebp + 426 5d/pop-to-ebp + 427 c3/return + 428 + 429 test-convert-function-skeleton: + 430 # . prologue + 431 55/push-ebp + 432 89/<- %ebp 4/r32/esp + 433 # setup + 434 (clear-stream _test-input-stream) + 435 (clear-stream $_test-input-buffered-file->buffer) + 436 (clear-stream _test-output-stream) + 437 (clear-stream $_test-output-buffered-file->buffer) + 438 # + 439 (write _test-input-stream "fn foo {\n") + 440 (write _test-input-stream "}\n") + 441 # convert + 442 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 443 (flush _test-output-buffered-file) + 444 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 450 # check output + 451 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-skeleton/0") + 452 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-skeleton/1") + 453 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-skeleton/2") + 454 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-skeleton/3") + 455 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-skeleton/4") + 456 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-skeleton/5") + 457 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-skeleton/6") + 458 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-skeleton/7") + 459 # . epilogue + 460 89/<- %esp 5/r32/ebp + 461 5d/pop-to-ebp + 462 c3/return + 463 + 464 test-convert-multiple-function-skeletons: + 465 # . prologue + 466 55/push-ebp + 467 89/<- %ebp 4/r32/esp + 468 # setup + 469 (clear-stream _test-input-stream) + 470 (clear-stream $_test-input-buffered-file->buffer) + 471 (clear-stream _test-output-stream) + 472 (clear-stream $_test-output-buffered-file->buffer) + 473 # + 474 (write _test-input-stream "fn foo {\n") + 475 (write _test-input-stream "}\n") + 476 (write _test-input-stream "fn bar {\n") + 477 (write _test-input-stream "}\n") + 478 # convert + 479 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 480 (flush _test-output-buffered-file) + 481 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 487 # check first function + 488 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-multiple-function-skeletons/0") + 489 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/1") + 490 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/2") + 491 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/3") + 492 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/4") + 493 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/5") + 494 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/6") + 495 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/7") + 496 # check second function + 497 (check-next-stream-line-equal _test-output-stream "bar:" "F - test-convert-multiple-function-skeletons/10") + 498 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/11") + 499 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/12") + 500 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/13") + 501 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/14") + 502 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/15") + 503 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/16") + 504 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/17") + 505 # . epilogue + 506 89/<- %esp 5/r32/ebp + 507 5d/pop-to-ebp + 508 c3/return + 509 + 510 test-convert-function-with-arg: + 511 # . prologue + 512 55/push-ebp + 513 89/<- %ebp 4/r32/esp + 514 # setup + 515 (clear-stream _test-input-stream) + 516 (clear-stream $_test-input-buffered-file->buffer) + 517 (clear-stream _test-output-stream) + 518 (clear-stream $_test-output-buffered-file->buffer) + 519 # + 520 (write _test-input-stream "fn foo n: int {\n") + 521 (write _test-input-stream "}\n") + 522 # convert + 523 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 524 (flush _test-output-buffered-file) + 525 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 531 # check output + 532 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg/0") + 533 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg/1") + 534 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg/2") + 535 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg/3") + 536 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg/4") + 537 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg/5") + 538 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg/6") + 539 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg/7") + 540 # . epilogue + 541 89/<- %esp 5/r32/ebp + 542 5d/pop-to-ebp + 543 c3/return + 544 + 545 test-convert-function-with-arg-and-body: + 546 # . prologue + 547 55/push-ebp + 548 89/<- %ebp 4/r32/esp + 549 # setup + 550 (clear-stream _test-input-stream) + 551 (clear-stream $_test-input-buffered-file->buffer) + 552 (clear-stream _test-output-stream) + 553 (clear-stream $_test-output-buffered-file->buffer) + 554 c7 0/subop/copy *Next-block-index 1/imm32 + 555 # + 556 (write _test-input-stream "fn foo n: int {\n") + 557 (write _test-input-stream " increment n\n") + 558 (write _test-input-stream "}\n") + 559 # convert + 560 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 561 (flush _test-output-buffered-file) + 562 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 568 # check output + 569 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg-and-body/0") + 570 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg-and-body/1") + 571 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg-and-body/2") + 572 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg-and-body/3") + 573 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-arg-and-body/4") + 574 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-arg-and-body/5") + 575 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-arg-and-body/6") + 576 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-arg-and-body/7") + 577 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-arg-and-body/8") + 578 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg-and-body/9") + 579 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg-and-body/10") + 580 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg-and-body/11") + 581 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg-and-body/12") + 582 # . epilogue + 583 89/<- %esp 5/r32/ebp + 584 5d/pop-to-ebp + 585 c3/return + 586 + 587 test-convert-function-distinguishes-args: + 588 # . prologue + 589 55/push-ebp + 590 89/<- %ebp 4/r32/esp + 591 # setup + 592 (clear-stream _test-input-stream) + 593 (clear-stream $_test-input-buffered-file->buffer) + 594 (clear-stream _test-output-stream) + 595 (clear-stream $_test-output-buffered-file->buffer) + 596 c7 0/subop/copy *Next-block-index 1/imm32 + 597 # + 598 (write _test-input-stream "fn foo a: int, b: int {\n") + 599 (write _test-input-stream " increment b\n") + 600 (write _test-input-stream "}\n") + 601 # convert + 602 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 603 (flush _test-output-buffered-file) + 604 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 610 # check output + 611 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-distinguishes-args/0") + 612 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-distinguishes-args/1") + 613 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-distinguishes-args/2") + 614 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-distinguishes-args/3") + 615 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-distinguishes-args/4") + 616 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-distinguishes-args/5") + 617 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x0000000c)" "F - test-convert-function-distinguishes-args/6") + 618 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-distinguishes-args/7") + 619 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-distinguishes-args/8") + 620 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-distinguishes-args/9") + 621 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-distinguishes-args/10") + 622 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-distinguishes-args/11") + 623 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-distinguishes-args/12") + 624 # . epilogue + 625 89/<- %esp 5/r32/ebp + 626 5d/pop-to-ebp + 627 c3/return + 628 + 629 test-convert-function-returns-result: + 630 # . prologue + 631 55/push-ebp + 632 89/<- %ebp 4/r32/esp + 633 # setup + 634 (clear-stream _test-input-stream) + 635 (clear-stream $_test-input-buffered-file->buffer) + 636 (clear-stream _test-output-stream) + 637 (clear-stream $_test-output-buffered-file->buffer) + 638 c7 0/subop/copy *Next-block-index 1/imm32 + 639 # + 640 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") + 641 (write _test-input-stream " result <- copy a\n") + 642 (write _test-input-stream " result <- increment\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-returns-result/0") + 655 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-returns-result/1") + 656 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-returns-result/2") + 657 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-returns-result/3") + 658 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-returns-result/4") + 659 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-returns-result/5") + 660 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-returns-result/6") + 661 (check-next-stream-line-equal _test-output-stream " 40/increment-eax" "F - test-convert-function-returns-result/7") + 662 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-returns-result/8") + 663 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-returns-result/9") + 664 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-returns-result/10") + 665 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-returns-result/11") + 666 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-returns-result/12") + 667 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-returns-result/13") + 668 # . epilogue + 669 89/<- %esp 5/r32/ebp + 670 5d/pop-to-ebp + 671 c3/return + 672 + 673 test-convert-function-literal-arg: + 674 # . prologue + 675 55/push-ebp + 676 89/<- %ebp 4/r32/esp + 677 # setup + 678 (clear-stream _test-input-stream) + 679 (clear-stream $_test-input-buffered-file->buffer) + 680 (clear-stream _test-output-stream) + 681 (clear-stream $_test-output-buffered-file->buffer) + 682 c7 0/subop/copy *Next-block-index 1/imm32 + 683 # + 684 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") + 685 (write _test-input-stream " result <- copy a\n") + 686 (write _test-input-stream " result <- add 1\n") + 687 (write _test-input-stream "}\n") + 688 # convert + 689 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 690 (flush _test-output-buffered-file) + 691 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 697 # check output + 698 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-literal-arg/0") + 699 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-literal-arg/1") + 700 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-literal-arg/2") + 701 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-literal-arg/3") + 702 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-literal-arg/4") + 703 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-literal-arg/5") + 704 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-literal-arg/6") + 705 (check-next-stream-line-equal _test-output-stream " 05/add-to-eax 1/imm32" "F - test-convert-function-literal-arg/7") + 706 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-literal-arg/8") + 707 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-literal-arg/9") + 708 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-literal-arg/10") + 709 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-literal-arg/11") + 710 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-literal-arg/12") + 711 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-literal-arg/13") + 712 # . epilogue + 713 89/<- %esp 5/r32/ebp + 714 5d/pop-to-ebp + 715 c3/return + 716 + 717 test-convert-function-literal-arg-2: + 718 # . prologue + 719 55/push-ebp + 720 89/<- %ebp 4/r32/esp + 721 # setup + 722 (clear-stream _test-input-stream) + 723 (clear-stream $_test-input-buffered-file->buffer) + 724 (clear-stream _test-output-stream) + 725 (clear-stream $_test-output-buffered-file->buffer) + 726 c7 0/subop/copy *Next-block-index 1/imm32 + 727 # + 728 (write _test-input-stream "fn foo a: int, b: int -> result/ebx: int {\n") + 729 (write _test-input-stream " result <- copy a\n") + 730 (write _test-input-stream " result <- add 1\n") + 731 (write _test-input-stream "}\n") + 732 # convert + 733 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 734 (flush _test-output-buffered-file) + 735 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 741 # check output + 742 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-literal-arg-2/0") + 743 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-literal-arg-2/1") + 744 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-literal-arg-2/2") + 745 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-literal-arg-2/3") + 746 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-literal-arg-2/4") + 747 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-literal-arg-2/5") + 748 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-literal-arg-2/6") + 749 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %ebx 1/imm32" "F - test-convert-function-literal-arg-2/7") + 750 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-literal-arg-2/8") + 751 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-literal-arg-2/9") + 752 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-literal-arg-2/10") + 753 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-literal-arg-2/11") + 754 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-literal-arg-2/12") + 755 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-literal-arg-2/13") + 756 # . epilogue + 757 89/<- %esp 5/r32/ebp + 758 5d/pop-to-ebp + 759 c3/return + 760 + 761 test-convert-function-call-with-literal-arg: + 762 # . prologue + 763 55/push-ebp + 764 89/<- %ebp 4/r32/esp + 765 # setup + 766 (clear-stream _test-input-stream) + 767 (clear-stream $_test-input-buffered-file->buffer) + 768 (clear-stream _test-output-stream) + 769 (clear-stream $_test-output-buffered-file->buffer) + 770 c7 0/subop/copy *Next-block-index 1/imm32 + 771 # + 772 (write _test-input-stream "fn main -> result/ebx: int {\n") + 773 (write _test-input-stream " result <- do-add 3 4\n") + 774 (write _test-input-stream "}\n") + 775 (write _test-input-stream "fn do-add a: int, b: int -> result/ebx: int {\n") + 776 (write _test-input-stream " result <- copy a\n") + 777 (write _test-input-stream " result <- add b\n") + 778 (write _test-input-stream "}\n") + 779 # convert + 780 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 781 (flush _test-output-buffered-file) + 782 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 788 # check output + 789 (check-next-stream-line-equal _test-output-stream "main:" "F - test-convert-function-call-with-literal-arg/0") + 790 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/1") + 791 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/2") + 792 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/3") + 793 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/4") + 794 (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:" "F - test-convert-function-call-with-literal-arg/5") + 795 (check-next-stream-line-equal _test-output-stream " (do-add 3 4)" "F - test-convert-function-call-with-literal-arg/6") + 796 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/7") + 797 (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/8") + 798 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/9") + 799 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/10") + 800 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/11") + 801 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/12") + 802 (check-next-stream-line-equal _test-output-stream "do-add:" "F - test-convert-function-call-with-literal-arg/13") + 803 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/14") + 804 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/15") + 805 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/16") + 806 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/17") + 807 (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:" "F - test-convert-function-call-with-literal-arg/18") + 808 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/19") + 809 (check-next-stream-line-equal _test-output-stream " 03/add *(ebp+0x0000000c) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/20") + 810 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/21") + 811 (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:" "F - test-convert-function-call-with-literal-arg/22") + 812 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/23") + 813 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/24") + 814 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/25") + 815 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/26") + 816 # . epilogue + 817 89/<- %esp 5/r32/ebp + 818 5d/pop-to-ebp + 819 c3/return + 820 + 821 test-convert-function-with-local-var-in-mem: + 822 # . prologue + 823 55/push-ebp + 824 89/<- %ebp 4/r32/esp + 825 # setup + 826 (clear-stream _test-input-stream) + 827 (clear-stream $_test-input-buffered-file->buffer) + 828 (clear-stream _test-output-stream) + 829 (clear-stream $_test-output-buffered-file->buffer) + 830 c7 0/subop/copy *Next-block-index 1/imm32 + 831 # + 832 (write _test-input-stream "fn foo {\n") + 833 (write _test-input-stream " var x: int\n") + 834 (write _test-input-stream " increment x\n") + 835 (write _test-input-stream "}\n") + 836 # convert + 837 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 838 (flush _test-output-buffered-file) + 839 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 845 # check output + 846 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-mem/0") + 847 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-mem/1") + 848 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-mem/2") + 849 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-mem/3") + 850 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-mem/4") + 851 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-mem/5") + 852 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-mem/6") + 853 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-mem/7") + 854 (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") + 855 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-mem/9") + 856 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-mem/10") + 857 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-mem/11") + 858 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-mem/12") + 859 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-mem/13") + 860 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-mem/14") + 861 # . epilogue + 862 89/<- %esp 5/r32/ebp + 863 5d/pop-to-ebp + 864 c3/return + 865 + 866 test-convert-function-with-local-var-in-reg: + 867 # . prologue + 868 55/push-ebp + 869 89/<- %ebp 4/r32/esp + 870 # setup + 871 (clear-stream _test-input-stream) + 872 (clear-stream $_test-input-buffered-file->buffer) + 873 (clear-stream _test-output-stream) + 874 (clear-stream $_test-output-buffered-file->buffer) + 875 c7 0/subop/copy *Next-block-index 1/imm32 + 876 # + 877 (write _test-input-stream "fn foo {\n") + 878 (write _test-input-stream " var x/ecx: int <- copy 3\n") + 879 (write _test-input-stream " x <- increment\n") + 880 (write _test-input-stream "}\n") + 881 # convert + 882 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 883 (flush _test-output-buffered-file) + 884 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 890 # check output + 891 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-reg/0") + 892 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-reg/1") + 893 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-reg/2") + 894 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-reg/3") + 895 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-reg/4") + 896 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-reg/5") + 897 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-local-var-in-reg/6") + 898 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-function-with-local-var-in-reg/7") + 899 (check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-convert-function-with-local-var-in-reg/8") + 900 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9") + 901 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-reg/10") + 902 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-reg/11") + 903 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-reg/12") + 904 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-reg/13") + 905 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-reg/14") + 906 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-reg/15") + 907 # . epilogue + 908 89/<- %esp 5/r32/ebp + 909 5d/pop-to-ebp + 910 c3/return + 911 + 912 test-convert-function-with-local-var-dereferenced: + 913 # . prologue + 914 55/push-ebp + 915 89/<- %ebp 4/r32/esp + 916 # setup + 917 (clear-stream _test-input-stream) + 918 (clear-stream $_test-input-buffered-file->buffer) + 919 (clear-stream _test-output-stream) + 920 (clear-stream $_test-output-buffered-file->buffer) + 921 c7 0/subop/copy *Next-block-index 1/imm32 + 922 # + 923 (write _test-input-stream "fn foo {\n") + 924 (write _test-input-stream " var x/ecx: (addr int) <- copy 0\n") + 925 (write _test-input-stream " increment *x\n") + 926 (write _test-input-stream "}\n") + 927 # convert + 928 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 929 (flush _test-output-buffered-file) + 930 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 936 # check output + 937 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-dereferenced/0") + 938 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-dereferenced/1") + 939 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-dereferenced/2") + 940 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-dereferenced/3") + 941 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-dereferenced/4") + 942 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-dereferenced/5") + 943 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-local-var-dereferenced/6") + 944 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-function-with-local-var-dereferenced/7") + 945 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *ecx" "F - test-convert-function-with-local-var-dereferenced/8") + 946 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9") + 947 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-dereferenced/10") + 948 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-dereferenced/11") + 949 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-dereferenced/12") + 950 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-dereferenced/13") + 951 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-dereferenced/14") + 952 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-dereferenced/15") + 953 # . epilogue + 954 89/<- %esp 5/r32/ebp + 955 5d/pop-to-ebp + 956 c3/return + 957 + 958 test-convert-function-with-local-var-in-block: + 959 # . prologue + 960 55/push-ebp + 961 89/<- %ebp 4/r32/esp + 962 # setup + 963 (clear-stream _test-input-stream) + 964 (clear-stream $_test-input-buffered-file->buffer) + 965 (clear-stream _test-output-stream) + 966 (clear-stream $_test-output-buffered-file->buffer) + 967 c7 0/subop/copy *Next-block-index 1/imm32 + 968 # + 969 (write _test-input-stream "fn foo {\n") + 970 (write _test-input-stream " {\n") + 971 (write _test-input-stream " var x: int\n") + 972 (write _test-input-stream " increment x\n") + 973 (write _test-input-stream " }\n") + 974 (write _test-input-stream "}\n") + 975 # convert + 976 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 977 (flush _test-output-buffered-file) + 978 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 984 # check output + 985 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-block/0") + 986 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-block/1") + 987 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-block/2") + 988 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-block/3") + 989 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/4") + 990 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-block/5") + 991 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/6") + 992 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-local-var-in-block/7") + 993 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-block/8") + 994 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-block/9") + 995 (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") + 996 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/11") + 997 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-local-var-in-block/12") + 998 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/13") + 999 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-block/14") +1000 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-block/15") +1001 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-block/16") +1002 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-block/17") +1003 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-block/18") +1004 # . epilogue +1005 89/<- %esp 5/r32/ebp +1006 5d/pop-to-ebp +1007 c3/return +1008 +1009 test-convert-function-with-local-var-in-named-block: +1010 # . prologue +1011 55/push-ebp +1012 89/<- %ebp 4/r32/esp +1013 # setup +1014 (clear-stream _test-input-stream) +1015 (clear-stream $_test-input-buffered-file->buffer) +1016 (clear-stream _test-output-stream) +1017 (clear-stream $_test-output-buffered-file->buffer) +1018 c7 0/subop/copy *Next-block-index 1/imm32 +1019 # +1020 (write _test-input-stream "fn foo {\n") +1021 (write _test-input-stream " $bar: {\n") +1022 (write _test-input-stream " var x: int\n") +1023 (write _test-input-stream " increment x\n") +1024 (write _test-input-stream " }\n") +1025 (write _test-input-stream "}\n") +1026 # convert +1027 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1028 (flush _test-output-buffered-file) +1029 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1035 # check output +1036 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-named-block/0") +1037 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-named-block/1") +1038 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-named-block/2") +1039 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-named-block/3") +1040 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/4") +1041 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-named-block/5") +1042 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/6") +1043 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-local-var-in-named-block/7") +1044 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-named-block/8") +1045 (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") +1046 (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") +1047 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/11") +1048 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-local-var-in-named-block/12") +1049 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/13") +1050 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-named-block/14") +1051 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-named-block/15") +1052 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-named-block/16") +1053 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-named-block/17") +1054 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-named-block/18") +1055 # . epilogue +1056 89/<- %esp 5/r32/ebp +1057 5d/pop-to-ebp +1058 c3/return +1059 +1060 test-convert-function-with-branches-in-block: +1061 # . prologue +1062 55/push-ebp +1063 89/<- %ebp 4/r32/esp +1064 # setup +1065 (clear-stream _test-input-stream) +1066 (clear-stream $_test-input-buffered-file->buffer) +1067 (clear-stream _test-output-stream) +1068 (clear-stream $_test-output-buffered-file->buffer) +1069 c7 0/subop/copy *Next-block-index 1/imm32 +1070 # +1071 (write _test-input-stream "fn foo x: int {\n") +1072 (write _test-input-stream " {\n") +1073 (write _test-input-stream " break-if->=\n") +1074 (write _test-input-stream " loop-if-addr<\n") +1075 (write _test-input-stream " increment x\n") +1076 (write _test-input-stream " loop\n") +1077 (write _test-input-stream " }\n") +1078 (write _test-input-stream "}\n") +1079 # convert +1080 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1081 (flush _test-output-buffered-file) +1082 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1088 # check output +1089 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-block/0") +1090 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-block/1") +1091 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-block/2") +1092 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-block/3") +1093 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/4") +1094 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-in-block/5") +1095 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/6") +1096 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-in-block/7") +1097 (check-next-stream-line-equal _test-output-stream " 0f 8d/jump-if->= break/disp32" "F - test-convert-function-with-branches-in-block/8") +1098 (check-next-stream-line-equal _test-output-stream " 0f 82/jump-if-addr< loop/disp32" "F - test-convert-function-with-branches-in-block/9") +1099 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-block/10") +1100 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-block/11") +1101 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/12") +1102 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-in-block/13") +1103 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/14") +1104 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-in-block/15") +1105 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-block/16") +1106 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-block/17") +1107 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-block/18") +1108 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-block/19") +1109 # . epilogue +1110 89/<- %esp 5/r32/ebp +1111 5d/pop-to-ebp +1112 c3/return +1113 +1114 test-convert-function-with-branches-in-named-block: +1115 # . prologue +1116 55/push-ebp +1117 89/<- %ebp 4/r32/esp +1118 # setup +1119 (clear-stream _test-input-stream) +1120 (clear-stream $_test-input-buffered-file->buffer) +1121 (clear-stream _test-output-stream) +1122 (clear-stream $_test-output-buffered-file->buffer) +1123 c7 0/subop/copy *Next-block-index 1/imm32 +1124 # +1125 (write _test-input-stream "fn foo x: int {\n") +1126 (write _test-input-stream " $bar: {\n") +1127 (write _test-input-stream " break-if->= $bar\n") +1128 (write _test-input-stream " loop-if-addr< $bar\n") +1129 (write _test-input-stream " increment x\n") +1130 (write _test-input-stream " loop\n") +1131 (write _test-input-stream " }\n") +1132 (write _test-input-stream "}\n") +1133 # convert +1134 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1135 (flush _test-output-buffered-file) +1136 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1142 # check output +1143 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-named-block/0") +1144 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-named-block/1") +1145 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-named-block/2") +1146 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-named-block/3") +1147 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/4") +1148 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-in-named-block/5") +1149 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/6") +1150 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-branches-in-named-block/7") +1151 (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") +1152 (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") +1153 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-named-block/10") +1154 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-named-block/11") +1155 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/12") +1156 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-branches-in-named-block/13") +1157 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/14") +1158 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-in-named-block/15") +1159 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-named-block/16") +1160 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-named-block/17") +1161 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-named-block/18") +1162 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-named-block/19") +1163 # . epilogue +1164 89/<- %esp 5/r32/ebp +1165 5d/pop-to-ebp +1166 c3/return +1167 +1168 test-convert-function-with-var-in-nested-block: +1169 # . prologue +1170 55/push-ebp +1171 89/<- %ebp 4/r32/esp +1172 # setup +1173 (clear-stream _test-input-stream) +1174 (clear-stream $_test-input-buffered-file->buffer) +1175 (clear-stream _test-output-stream) +1176 (clear-stream $_test-output-buffered-file->buffer) +1177 c7 0/subop/copy *Next-block-index 1/imm32 +1178 # +1179 (write _test-input-stream "fn foo x: int {\n") +1180 (write _test-input-stream " {\n") +1181 (write _test-input-stream " {\n") +1182 (write _test-input-stream " var x: int\n") +1183 (write _test-input-stream " increment x\n") +1184 (write _test-input-stream " }\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-var-in-nested-block/0") +1198 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-var-in-nested-block/1") +1199 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-var-in-nested-block/2") +1200 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-var-in-nested-block/3") +1201 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/4") +1202 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-var-in-nested-block/5") +1203 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/6") +1204 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-var-in-nested-block/7") +1205 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/8") +1206 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-var-in-nested-block/9") +1207 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10") +1208 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-var-in-nested-block/11") +1209 (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") +1210 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/13") +1211 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-var-in-nested-block/14") +1212 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/15") +1213 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-var-in-nested-block/16") +1214 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/17") +1215 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-var-in-nested-block/18") +1216 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-var-in-nested-block/19") +1217 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-var-in-nested-block/20") +1218 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-var-in-nested-block/21") +1219 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-var-in-nested-block/22") +1220 # . epilogue +1221 89/<- %esp 5/r32/ebp +1222 5d/pop-to-ebp +1223 c3/return +1224 +1225 test-convert-function-with-multiple-vars-in-nested-blocks: +1226 # . prologue +1227 55/push-ebp +1228 89/<- %ebp 4/r32/esp +1229 # setup +1230 (clear-stream _test-input-stream) +1231 (clear-stream $_test-input-buffered-file->buffer) +1232 (clear-stream _test-output-stream) +1233 (clear-stream $_test-output-buffered-file->buffer) +1234 c7 0/subop/copy *Next-block-index 1/imm32 +1235 # +1236 (write _test-input-stream "fn foo x: int {\n") +1237 (write _test-input-stream " {\n") +1238 (write _test-input-stream " var x/eax: int <- copy 0\n") +1239 (write _test-input-stream " {\n") +1240 (write _test-input-stream " var y: int\n") +1241 (write _test-input-stream " x <- add y\n") +1242 (write _test-input-stream " }\n") +1243 (write _test-input-stream " }\n") +1244 (write _test-input-stream "}\n") +1245 # convert +1246 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1247 (flush _test-output-buffered-file) +1248 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1254 # check output +1255 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/0") +1256 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-multiple-vars-in-nested-blocks/1") +1257 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/2") +1258 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/3") +1259 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/4") +1260 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/5") +1261 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/6") +1262 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/7") +1263 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-with-multiple-vars-in-nested-blocks/8") +1264 (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") +1265 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/10") +1266 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/11") +1267 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12") +1268 (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") +1269 (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") +1270 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/15") +1271 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/16") +1272 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-with-multiple-vars-in-nested-blocks/17") +1273 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/18") +1274 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/19") +1275 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/20") +1276 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/21") +1277 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-multiple-vars-in-nested-blocks/22") +1278 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/23") +1279 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/24") +1280 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-multiple-vars-in-nested-blocks/25") +1281 # . epilogue +1282 89/<- %esp 5/r32/ebp +1283 5d/pop-to-ebp +1284 c3/return +1285 +1286 test-convert-function-with-branches-and-local-vars: +1287 # A conditional 'break' after a 'var' in a block is converted into a +1288 # nested block that performs all necessary cleanup before jumping. This +1289 # results in some ugly code duplication. +1290 # . prologue +1291 55/push-ebp +1292 89/<- %ebp 4/r32/esp +1293 # setup +1294 (clear-stream _test-input-stream) +1295 (clear-stream $_test-input-buffered-file->buffer) +1296 (clear-stream _test-output-stream) +1297 (clear-stream $_test-output-buffered-file->buffer) +1298 c7 0/subop/copy *Next-block-index 1/imm32 +1299 # +1300 (write _test-input-stream "fn foo {\n") +1301 (write _test-input-stream " {\n") +1302 (write _test-input-stream " var x: int\n") +1303 (write _test-input-stream " break-if->=\n") +1304 (write _test-input-stream " increment x\n") +1305 (write _test-input-stream " }\n") +1306 (write _test-input-stream "}\n") +1307 # convert +1308 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1309 (flush _test-output-buffered-file) +1310 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1316 # check output +1317 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-local-vars/0") +1318 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-local-vars/1") +1319 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-local-vars/2") +1320 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-and-local-vars/3") +1321 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/4") +1322 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-and-local-vars/5") +1323 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/6") +1324 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-and-local-vars/7") +1325 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-local-vars/8") +1326 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/9") +1327 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-branches-and-local-vars/10") +1328 (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") +1329 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:break/disp32" "F - test-convert-function-with-branches-and-local-vars/12") +1330 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/13") +1331 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-branches-and-local-vars/14") +1332 (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") +1333 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/16") +1334 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-and-local-vars/17") +1335 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/18") +1336 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-and-local-vars/19") +1337 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-local-vars/20") +1338 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-and-local-vars/21") +1339 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-local-vars/22") +1340 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-local-vars/23") +1341 # . epilogue +1342 89/<- %esp 5/r32/ebp +1343 5d/pop-to-ebp +1344 c3/return +1345 +1346 test-convert-function-with-conditional-loops-and-local-vars: +1347 # A conditional 'loop' after a 'var' in a block is converted into a nested +1348 # block that performs all necessary cleanup before jumping. This results +1349 # in some ugly code duplication. +1350 # . prologue +1351 55/push-ebp +1352 89/<- %ebp 4/r32/esp +1353 # setup +1354 (clear-stream _test-input-stream) +1355 (clear-stream $_test-input-buffered-file->buffer) +1356 (clear-stream _test-output-stream) +1357 (clear-stream $_test-output-buffered-file->buffer) +1358 c7 0/subop/copy *Next-block-index 1/imm32 +1359 # +1360 (write _test-input-stream "fn foo {\n") +1361 (write _test-input-stream " {\n") +1362 (write _test-input-stream " var x: int\n") +1363 (write _test-input-stream " loop-if->=\n") +1364 (write _test-input-stream " increment x\n") +1365 (write _test-input-stream " }\n") +1366 (write _test-input-stream "}\n") +1367 # convert +1368 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1369 (flush _test-output-buffered-file) +1370 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1376 # check output +1377 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-conditional-loops-and-local-vars/0") +1378 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-conditional-loops-and-local-vars/1") +1379 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/2") +1380 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-conditional-loops-and-local-vars/3") +1381 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/4") +1382 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-conditional-loops-and-local-vars/5") +1383 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/6") +1384 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-conditional-loops-and-local-vars/7") +1385 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-conditional-loops-and-local-vars/8") +1386 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/9") +1387 (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") +1388 (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") +1389 (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") +1390 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/13") +1391 (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") +1392 (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") +1393 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/16") +1394 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-conditional-loops-and-local-vars/17") +1395 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/18") +1396 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-conditional-loops-and-local-vars/19") +1397 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-conditional-loops-and-local-vars/20") +1398 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/21") +1399 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/22") +1400 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-conditional-loops-and-local-vars/23") 1401 # . epilogue 1402 89/<- %esp 5/r32/ebp 1403 5d/pop-to-ebp 1404 c3/return 1405 -1406 test-convert-function-with-branches-and-loops-and-local-vars: -1407 # . prologue -1408 55/push-ebp -1409 89/<- %ebp 4/r32/esp -1410 # setup -1411 (clear-stream _test-input-stream) -1412 (clear-stream $_test-input-buffered-file->buffer) -1413 (clear-stream _test-output-stream) -1414 (clear-stream $_test-output-buffered-file->buffer) -1415 c7 0/subop/copy *Next-block-index 1/imm32 -1416 # -1417 (write _test-input-stream "fn foo {\n") -1418 (write _test-input-stream " {\n") -1419 (write _test-input-stream " var x: int\n") -1420 (write _test-input-stream " break-if->=\n") -1421 (write _test-input-stream " increment x\n") -1422 (write _test-input-stream " loop\n") -1423 (write _test-input-stream " }\n") -1424 (write _test-input-stream "}\n") -1425 # convert -1426 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1427 (flush _test-output-buffered-file) -1428 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1434 # check output -1435 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-loops-and-local-vars/0") -1436 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-loops-and-local-vars/1") -1437 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/2") -1438 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-and-loops-and-local-vars/3") -1439 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/4") -1440 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-and-loops-and-local-vars/5") -1441 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/6") -1442 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-and-loops-and-local-vars/7") -1443 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-loops-and-local-vars/8") -1444 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/9") -1445 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-branches-and-loops-and-local-vars/10") -1446 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-branches-and-loops-and-local-vars/11") -1447 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:break/disp32" "F - test-convert-function-with-branches-and-loops-and-local-vars/12") -1448 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/13") -1449 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-branches-and-loops-and-local-vars/14") -1450 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-branches-and-loops-and-local-vars/15") -1451 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-and-loops-and-local-vars/16") -1452 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/17") -1453 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-and-loops-and-local-vars/18") -1454 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/19") -1455 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-and-loops-and-local-vars/20") -1456 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-loops-and-local-vars/21") -1457 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/22") -1458 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/23") -1459 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-loops-and-local-vars/24") -1460 # . epilogue -1461 89/<- %esp 5/r32/ebp -1462 5d/pop-to-ebp -1463 c3/return -1464 -1465 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars: -1466 # . prologue -1467 55/push-ebp -1468 89/<- %ebp 4/r32/esp -1469 # setup -1470 (clear-stream _test-input-stream) -1471 (clear-stream $_test-input-buffered-file->buffer) -1472 (clear-stream _test-output-stream) -1473 (clear-stream $_test-output-buffered-file->buffer) -1474 c7 0/subop/copy *Next-block-index 1/imm32 -1475 # -1476 (write _test-input-stream "fn foo {\n") -1477 (write _test-input-stream " a: {\n") -1478 (write _test-input-stream " var x: int\n") -1479 (write _test-input-stream " {\n") -1480 (write _test-input-stream " var y: int\n") -1481 (write _test-input-stream " break-if->= a\n") -1482 (write _test-input-stream " increment x\n") -1483 (write _test-input-stream " loop\n") -1484 (write _test-input-stream " }\n") -1485 (write _test-input-stream " }\n") -1486 (write _test-input-stream "}\n") -1487 # convert -1488 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1489 (flush _test-output-buffered-file) -1490 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1496 # check output -1497 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0") -1498 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1") -1499 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2") -1500 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/3") -1501 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4") -1502 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5") -1503 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6") -1504 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7") -1505 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/8") -1506 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9") -1507 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10") -1508 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/11") -1509 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12") -1510 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/13") -1511 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/14") -1512 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/15") -1513 (check-next-stream-line-equal _test-output-stream " e9/jump a:break/disp32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/16") -1514 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17") -1515 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/18") -1516 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/19") -1517 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/20") -1518 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21") -1519 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22") -1520 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/23") -1521 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24") -1522 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25") -1523 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26") -1524 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27") -1525 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28") -1526 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/29") -1527 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/30") -1528 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31") -1529 # . epilogue -1530 89/<- %esp 5/r32/ebp -1531 5d/pop-to-ebp -1532 c3/return -1533 -1534 test-convert-function-with-nonlocal-unconditional-break-and-local-vars: -1535 # . prologue -1536 55/push-ebp -1537 89/<- %ebp 4/r32/esp -1538 # setup -1539 (clear-stream _test-input-stream) -1540 (clear-stream $_test-input-buffered-file->buffer) -1541 (clear-stream _test-output-stream) -1542 (clear-stream $_test-output-buffered-file->buffer) -1543 c7 0/subop/copy *Next-block-index 1/imm32 -1544 # -1545 (write _test-input-stream "fn foo {\n") -1546 (write _test-input-stream " a: {\n") -1547 (write _test-input-stream " var x: int\n") -1548 (write _test-input-stream " {\n") -1549 (write _test-input-stream " var y: int\n") -1550 (write _test-input-stream " break a\n") -1551 (write _test-input-stream " increment x\n") -1552 (write _test-input-stream " }\n") -1553 (write _test-input-stream " }\n") -1554 (write _test-input-stream "}\n") -1555 # convert -1556 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1557 (flush _test-output-buffered-file) -1558 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1564 # check output -1565 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0") -1566 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1") -1567 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2") -1568 (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") -1569 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4") -1570 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5") -1571 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6") -1572 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7") -1573 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8") -1574 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9") -1575 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10") -1576 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11") -1577 (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") -1578 (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") -1579 (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") -1580 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15") -1581 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16") -1582 (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") -1583 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18") -1584 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19") -1585 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20") -1586 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21") -1587 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22") -1588 (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") -1589 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24") -1590 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25") -1591 # . epilogue -1592 89/<- %esp 5/r32/ebp -1593 5d/pop-to-ebp -1594 c3/return -1595 -1596 test-convert-function-with-unconditional-break-and-local-vars: -1597 # . prologue -1598 55/push-ebp -1599 89/<- %ebp 4/r32/esp -1600 # setup -1601 (clear-stream _test-input-stream) -1602 (clear-stream $_test-input-buffered-file->buffer) -1603 (clear-stream _test-output-stream) -1604 (clear-stream $_test-output-buffered-file->buffer) -1605 c7 0/subop/copy *Next-block-index 1/imm32 -1606 # -1607 (write _test-input-stream "fn foo {\n") -1608 (write _test-input-stream " {\n") -1609 (write _test-input-stream " var x: int\n") -1610 (write _test-input-stream " {\n") -1611 (write _test-input-stream " var y: int\n") -1612 (write _test-input-stream " break\n") -1613 (write _test-input-stream " increment x\n") -1614 (write _test-input-stream " }\n") -1615 (write _test-input-stream " }\n") -1616 (write _test-input-stream "}\n") -1617 # convert -1618 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1619 (flush _test-output-buffered-file) -1620 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1626 # check output -1627 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-unconditional-break-and-local-vars/0") -1628 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-unconditional-break-and-local-vars/1") -1629 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/2") -1630 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-unconditional-break-and-local-vars/3") -1631 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/4") -1632 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/5") -1633 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/6") -1634 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/7") -1635 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/8") -1636 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/9") -1637 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/10") -1638 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11") -1639 (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") -1640 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/13") -1641 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/14") -1642 (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") -1643 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/16") -1644 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/17") -1645 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/18") -1646 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/19") -1647 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-unconditional-break-and-local-vars/20") -1648 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/21") -1649 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/22") -1650 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-unconditional-break-and-local-vars/23") -1651 # . epilogue -1652 89/<- %esp 5/r32/ebp -1653 5d/pop-to-ebp -1654 c3/return -1655 -1656 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars: -1657 # . prologue -1658 55/push-ebp -1659 89/<- %ebp 4/r32/esp -1660 # setup -1661 (clear-stream _test-input-stream) -1662 (clear-stream $_test-input-buffered-file->buffer) -1663 (clear-stream _test-output-stream) -1664 (clear-stream $_test-output-buffered-file->buffer) -1665 c7 0/subop/copy *Next-block-index 1/imm32 -1666 # -1667 (write _test-input-stream "fn foo {\n") -1668 (write _test-input-stream " a: {\n") -1669 (write _test-input-stream " var x: int\n") -1670 (write _test-input-stream " {\n") -1671 (write _test-input-stream " var y: int\n") -1672 (write _test-input-stream " loop a\n") -1673 (write _test-input-stream " increment x\n") -1674 (write _test-input-stream " }\n") -1675 (write _test-input-stream " }\n") -1676 (write _test-input-stream "}\n") -1677 # convert -1678 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1679 (flush _test-output-buffered-file) -1680 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1686 # check output -1687 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0") -1688 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1") -1689 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2") -1690 (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") -1691 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4") -1692 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5") -1693 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6") -1694 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7") -1695 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8") -1696 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9") -1697 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10") -1698 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11") -1699 (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") -1700 (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") -1701 (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") -1702 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15") -1703 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16") -1704 (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") -1705 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18") -1706 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19") -1707 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20") -1708 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21") -1709 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22") -1710 (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") -1711 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24") -1712 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25") -1713 # . epilogue -1714 89/<- %esp 5/r32/ebp -1715 5d/pop-to-ebp -1716 c3/return -1717 -1718 test-convert-length-of-array: -1719 # . prologue -1720 55/push-ebp -1721 89/<- %ebp 4/r32/esp -1722 # setup -1723 (clear-stream _test-input-stream) -1724 (clear-stream $_test-input-buffered-file->buffer) -1725 (clear-stream _test-output-stream) -1726 (clear-stream $_test-output-buffered-file->buffer) -1727 c7 0/subop/copy *Next-block-index 1/imm32 -1728 # -1729 (write _test-input-stream "fn foo a: (addr array int) {\n") -1730 (write _test-input-stream " var b/eax: (addr array int) <- copy a\n") -1731 (write _test-input-stream " var c/eax: int <- length b\n") +1406 test-convert-function-with-unconditional-loops-and-local-vars: +1407 # An unconditional 'loop' after a 'var' in a block is emitted _after_ the +1408 # regular block cleanup. Any instructions after 'loop' are dead and +1409 # therefore skipped. +1410 # . prologue +1411 55/push-ebp +1412 89/<- %ebp 4/r32/esp +1413 # setup +1414 (clear-stream _test-input-stream) +1415 (clear-stream $_test-input-buffered-file->buffer) +1416 (clear-stream _test-output-stream) +1417 (clear-stream $_test-output-buffered-file->buffer) +1418 c7 0/subop/copy *Next-block-index 1/imm32 +1419 # +1420 (write _test-input-stream "fn foo {\n") +1421 (write _test-input-stream " {\n") +1422 (write _test-input-stream " var x: int\n") +1423 (write _test-input-stream " loop\n") +1424 (write _test-input-stream " increment x\n") +1425 (write _test-input-stream " }\n") +1426 (write _test-input-stream "}\n") +1427 # convert +1428 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1429 (flush _test-output-buffered-file) +1430 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1436 # check output +1437 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-unconditional-loops-and-local-vars/0") +1438 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-unconditional-loops-and-local-vars/1") +1439 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/2") +1440 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-unconditional-loops-and-local-vars/3") +1441 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-loops-and-local-vars/4") +1442 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-unconditional-loops-and-local-vars/5") +1443 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-loops-and-local-vars/6") +1444 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-unconditional-loops-and-local-vars/7") +1445 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-loops-and-local-vars/8") +1446 (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") +1447 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-unconditional-loops-and-local-vars/10") +1448 # not emitted: ff 0/subop/increment *(ebp+0xfffffffc) +1449 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-loops-and-local-vars/11") +1450 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-unconditional-loops-and-local-vars/12") +1451 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-loops-and-local-vars/13") +1452 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-unconditional-loops-and-local-vars/14") +1453 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-unconditional-loops-and-local-vars/15") +1454 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/16") +1455 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/17") +1456 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-unconditional-loops-and-local-vars/18") +1457 # . epilogue +1458 89/<- %esp 5/r32/ebp +1459 5d/pop-to-ebp +1460 c3/return +1461 +1462 test-convert-function-with-branches-and-loops-and-local-vars: +1463 # . prologue +1464 55/push-ebp +1465 89/<- %ebp 4/r32/esp +1466 # setup +1467 (clear-stream _test-input-stream) +1468 (clear-stream $_test-input-buffered-file->buffer) +1469 (clear-stream _test-output-stream) +1470 (clear-stream $_test-output-buffered-file->buffer) +1471 c7 0/subop/copy *Next-block-index 1/imm32 +1472 # +1473 (write _test-input-stream "fn foo {\n") +1474 (write _test-input-stream " {\n") +1475 (write _test-input-stream " var x: int\n") +1476 (write _test-input-stream " break-if->=\n") +1477 (write _test-input-stream " increment x\n") +1478 (write _test-input-stream " loop\n") +1479 (write _test-input-stream " }\n") +1480 (write _test-input-stream "}\n") +1481 # convert +1482 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1483 (flush _test-output-buffered-file) +1484 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1490 # check output +1491 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-loops-and-local-vars/0") +1492 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-loops-and-local-vars/1") +1493 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/2") +1494 (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") +1495 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/4") +1496 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-and-loops-and-local-vars/5") +1497 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/6") +1498 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-and-loops-and-local-vars/7") +1499 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-loops-and-local-vars/8") +1500 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/9") +1501 (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") +1502 (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") +1503 (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") +1504 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/13") +1505 (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") +1506 (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") +1507 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-and-loops-and-local-vars/16") +1508 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/17") +1509 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-and-loops-and-local-vars/18") +1510 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/19") +1511 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-and-loops-and-local-vars/20") +1512 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-loops-and-local-vars/21") +1513 (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") +1514 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/23") +1515 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-loops-and-local-vars/24") +1516 # . epilogue +1517 89/<- %esp 5/r32/ebp +1518 5d/pop-to-ebp +1519 c3/return +1520 +1521 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars: +1522 # . prologue +1523 55/push-ebp +1524 89/<- %ebp 4/r32/esp +1525 # setup +1526 (clear-stream _test-input-stream) +1527 (clear-stream $_test-input-buffered-file->buffer) +1528 (clear-stream _test-output-stream) +1529 (clear-stream $_test-output-buffered-file->buffer) +1530 c7 0/subop/copy *Next-block-index 1/imm32 +1531 # +1532 (write _test-input-stream "fn foo {\n") +1533 (write _test-input-stream " a: {\n") +1534 (write _test-input-stream " var x: int\n") +1535 (write _test-input-stream " {\n") +1536 (write _test-input-stream " var y: int\n") +1537 (write _test-input-stream " break-if->= a\n") +1538 (write _test-input-stream " increment x\n") +1539 (write _test-input-stream " loop\n") +1540 (write _test-input-stream " }\n") +1541 (write _test-input-stream " }\n") +1542 (write _test-input-stream "}\n") +1543 # convert +1544 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1545 (flush _test-output-buffered-file) +1546 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1552 # check output +1553 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0") +1554 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1") +1555 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2") +1556 (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") +1557 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4") +1558 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5") +1559 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6") +1560 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7") +1561 (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") +1562 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9") +1563 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10") +1564 (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") +1565 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12") +1566 (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") +1567 (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") +1568 (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") +1569 (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") +1570 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17") +1571 (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") +1572 (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") +1573 (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") +1574 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21") +1575 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22") +1576 (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") +1577 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24") +1578 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25") +1579 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26") +1580 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27") +1581 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28") +1582 (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") +1583 (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") +1584 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31") +1585 # . epilogue +1586 89/<- %esp 5/r32/ebp +1587 5d/pop-to-ebp +1588 c3/return +1589 +1590 test-convert-function-with-nonlocal-unconditional-break-and-local-vars: +1591 # . prologue +1592 55/push-ebp +1593 89/<- %ebp 4/r32/esp +1594 # setup +1595 (clear-stream _test-input-stream) +1596 (clear-stream $_test-input-buffered-file->buffer) +1597 (clear-stream _test-output-stream) +1598 (clear-stream $_test-output-buffered-file->buffer) +1599 c7 0/subop/copy *Next-block-index 1/imm32 +1600 # +1601 (write _test-input-stream "fn foo {\n") +1602 (write _test-input-stream " a: {\n") +1603 (write _test-input-stream " var x: int\n") +1604 (write _test-input-stream " {\n") +1605 (write _test-input-stream " var y: int\n") +1606 (write _test-input-stream " break a\n") +1607 (write _test-input-stream " increment x\n") +1608 (write _test-input-stream " }\n") +1609 (write _test-input-stream " }\n") +1610 (write _test-input-stream "}\n") +1611 # convert +1612 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1613 (flush _test-output-buffered-file) +1614 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1620 # check output +1621 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0") +1622 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1") +1623 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2") +1624 (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") +1625 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4") +1626 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5") +1627 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6") +1628 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7") +1629 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8") +1630 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9") +1631 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10") +1632 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11") +1633 (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") +1634 (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") +1635 (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") +1636 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15") +1637 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16") +1638 (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") +1639 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18") +1640 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19") +1641 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20") +1642 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21") +1643 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22") +1644 (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") +1645 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24") +1646 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25") +1647 # . epilogue +1648 89/<- %esp 5/r32/ebp +1649 5d/pop-to-ebp +1650 c3/return +1651 +1652 test-convert-function-with-unconditional-break-and-local-vars: +1653 # . prologue +1654 55/push-ebp +1655 89/<- %ebp 4/r32/esp +1656 # setup +1657 (clear-stream _test-input-stream) +1658 (clear-stream $_test-input-buffered-file->buffer) +1659 (clear-stream _test-output-stream) +1660 (clear-stream $_test-output-buffered-file->buffer) +1661 c7 0/subop/copy *Next-block-index 1/imm32 +1662 # +1663 (write _test-input-stream "fn foo {\n") +1664 (write _test-input-stream " {\n") +1665 (write _test-input-stream " var x: int\n") +1666 (write _test-input-stream " {\n") +1667 (write _test-input-stream " var y: int\n") +1668 (write _test-input-stream " break\n") +1669 (write _test-input-stream " increment x\n") +1670 (write _test-input-stream " }\n") +1671 (write _test-input-stream " }\n") +1672 (write _test-input-stream "}\n") +1673 # convert +1674 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1675 (flush _test-output-buffered-file) +1676 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1682 # check output +1683 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-unconditional-break-and-local-vars/0") +1684 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-unconditional-break-and-local-vars/1") +1685 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/2") +1686 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-unconditional-break-and-local-vars/3") +1687 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/4") +1688 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/5") +1689 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/6") +1690 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/7") +1691 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/8") +1692 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/9") +1693 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/10") +1694 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11") +1695 (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") +1696 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/13") +1697 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/14") +1698 (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") +1699 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/16") +1700 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/17") +1701 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/18") +1702 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/19") +1703 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-unconditional-break-and-local-vars/20") +1704 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/21") +1705 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/22") +1706 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-unconditional-break-and-local-vars/23") +1707 # . epilogue +1708 89/<- %esp 5/r32/ebp +1709 5d/pop-to-ebp +1710 c3/return +1711 +1712 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars: +1713 # . prologue +1714 55/push-ebp +1715 89/<- %ebp 4/r32/esp +1716 # setup +1717 (clear-stream _test-input-stream) +1718 (clear-stream $_test-input-buffered-file->buffer) +1719 (clear-stream _test-output-stream) +1720 (clear-stream $_test-output-buffered-file->buffer) +1721 c7 0/subop/copy *Next-block-index 1/imm32 +1722 # +1723 (write _test-input-stream "fn foo {\n") +1724 (write _test-input-stream " a: {\n") +1725 (write _test-input-stream " var x: int\n") +1726 (write _test-input-stream " {\n") +1727 (write _test-input-stream " var y: int\n") +1728 (write _test-input-stream " loop a\n") +1729 (write _test-input-stream " increment x\n") +1730 (write _test-input-stream " }\n") +1731 (write _test-input-stream " }\n") 1732 (write _test-input-stream "}\n") 1733 # convert -1734 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1734 (convert-mu _test-input-buffered-file _test-output-buffered-file) 1735 (flush _test-output-buffered-file) 1736 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 1742 # check output -1743 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array/0") -1744 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array/1") -1745 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array/2") -1746 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array/3") -1747 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array/4") -1748 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array/5") -1749 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/6") -1750 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-length-of-array/7") -1751 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/8") -1752 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *eax 0x00000000/r32" "F - test-convert-length-of-array/9") -1753 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/10") -1754 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/11") -1755 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array/12") -1756 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array/13") -1757 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array/14") -1758 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array/15") -1759 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array/16") -1760 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array/17") -1761 # . epilogue -1762 89/<- %esp 5/r32/ebp -1763 5d/pop-to-ebp -1764 c3/return -1765 -1766 ####################################################### -1767 # Parsing -1768 ####################################################### -1769 -1770 parse-mu: # in: (addr buffered-file) -1771 # pseudocode -1772 # var curr-function: (addr (handle function)) = Program -1773 # var line: (stream byte 512) -1774 # var word-slice: slice -1775 # while true # line loop -1776 # clear-stream(line) -1777 # read-line-buffered(in, line) -1778 # if (line->write == 0) break # end of file -1779 # word-slice = next-mu-token(line) -1780 # if slice-empty?(word-slice) # end of line -1781 # continue -1782 # else if slice-starts-with?(word-slice, "#") # comment -1783 # continue # end of line -1784 # else if slice-equal(word-slice, "fn") -1785 # var new-function: (handle function) = allocate(function) -1786 # var vars: (stack (addr var) 256) -1787 # populate-mu-function-header(in, new-function, vars) -1788 # populate-mu-function-body(in, new-function, vars) -1789 # assert(vars->top == 0) -1790 # *curr-function = new-function -1791 # curr-function = &new-function->next -1792 # else -1793 # abort() -1794 # -1795 # . prologue -1796 55/push-ebp -1797 89/<- %ebp 4/r32/esp -1798 # . save registers -1799 50/push-eax -1800 51/push-ecx -1801 52/push-edx -1802 53/push-ebx -1803 57/push-edi -1804 # var line/ecx: (stream byte 512) -1805 81 5/subop/subtract %esp 0x200/imm32 -1806 68/push 0x200/imm32/length -1807 68/push 0/imm32/read -1808 68/push 0/imm32/write -1809 89/<- %ecx 4/r32/esp -1810 # var word-slice/edx: slice -1811 68/push 0/imm32/end -1812 68/push 0/imm32/start -1813 89/<- %edx 4/r32/esp -1814 # var curr-function/edi: (addr (handle function)) = Program -1815 bf/copy-to-edi Program/imm32 -1816 # var vars/ebx: (stack (addr var) 256) -1817 81 5/subop/subtract %esp 0x400/imm32 -1818 68/push 0x400/imm32/length -1819 68/push 0/imm32/top -1820 89/<- %ebx 4/r32/esp -1821 { -1822 $parse-mu:line-loop: -1823 (clear-stream %ecx) -1824 (read-line-buffered *(ebp+8) %ecx) -1825 # if (line->write == 0) break -1826 81 7/subop/compare *ecx 0/imm32 -1827 0f 84/jump-if-= break/disp32 -1828 +-- 6 lines: #? # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------ -1834 (next-mu-token %ecx %edx) -1835 # if slice-empty?(word-slice) continue -1836 (slice-empty? %edx) -1837 3d/compare-eax-and 0/imm32/false -1838 0f 85/jump-if-!= loop/disp32 -1839 # if (*word-slice->start == "#") continue -1840 # . eax = *word-slice->start -1841 8b/-> *edx 0/r32/eax -1842 8a/copy-byte *eax 0/r32/AL -1843 81 4/subop/and %eax 0xff/imm32 -1844 # . if (eax == '#') continue -1845 3d/compare-eax-and 0x23/imm32/hash -1846 0f 84/jump-if-= loop/disp32 -1847 # if (slice-equal?(word-slice, "fn")) parse a function -1848 { -1849 $parse-mu:fn: -1850 (slice-equal? %edx "fn") -1851 3d/compare-eax-and 0/imm32/false -1852 0f 84/jump-if-= break/disp32 -1853 # var new-function/eax: (handle function) = populate-mu-function(in, new-function, vars) -1854 (allocate Heap *Function-size) # => eax -1855 (zero-out %eax *Function-size) -1856 (clear-stack %ebx) -1857 (populate-mu-function-header %ecx %eax %ebx) -1858 (populate-mu-function-body *(ebp+8) %eax %ebx) -1859 # *curr-function = new-function -1860 89/<- *edi 0/r32/eax -1861 # curr-function = &new-function->next -1862 8d/address-> *(eax+0x14) 7/r32/edi # Function-next -1863 e9/jump $parse-mu:line-loop/disp32 -1864 } -1865 # otherwise abort -1866 e9/jump $parse-mu:error1/disp32 -1867 } # end line loop -1868 $parse-mu:end: -1869 # . reclaim locals -1870 81 0/subop/add %esp 0x630/imm32 -1871 # . restore registers -1872 5f/pop-to-edi -1873 5b/pop-to-ebx -1874 5a/pop-to-edx -1875 59/pop-to-ecx -1876 58/pop-to-eax -1877 # . epilogue -1878 89/<- %esp 5/r32/ebp -1879 5d/pop-to-ebp -1880 c3/return -1881 -1882 $parse-mu:error1: -1883 # error("unexpected top-level command: " word-slice "\n") -1884 (write-buffered Stderr "unexpected top-level command: ") -1885 (write-slice-buffered Stderr %edx) -1886 (write-buffered Stderr "\n") -1887 (flush Stderr) -1888 # . syscall(exit, 1) -1889 bb/copy-to-ebx 1/imm32 -1890 b8/copy-to-eax 1/imm32/exit -1891 cd/syscall 0x80/imm8 -1892 # never gets here -1893 -1894 $parse-mu:error2: -1895 # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n") -1896 (print-int32-buffered Stderr *ebx) -1897 (write-buffered Stderr " vars not reclaimed after fn '") -1898 (write-slice-buffered Stderr *eax) # Function-name -1899 (write-buffered Stderr "'\n") -1900 (flush Stderr) -1901 # . syscall(exit, 1) -1902 bb/copy-to-ebx 1/imm32 -1903 b8/copy-to-eax 1/imm32/exit -1904 cd/syscall 0x80/imm8 -1905 # never gets here -1906 -1907 # scenarios considered: -1908 # ✗ fn foo # no block -1909 # ✓ fn foo { -1910 # ✗ fn foo { { -1911 # ✗ fn foo { } -1912 # ✗ fn foo { } { -1913 # ✗ fn foo x { -1914 # ✗ fn foo x: { -1915 # ✓ fn foo x: int { -1916 # ✓ fn foo x: int { -1917 # ✓ fn foo x: int -> y/eax: int { -1918 populate-mu-function-header: # first-line: (addr stream byte), out: (handle function), vars: (addr stack (handle var)) -1919 # pseudocode: -1920 # var name: slice -1921 # next-mu-token(first-line, name) -1922 # assert(name not in '{' '}' '->') -1923 # out->name = slice-to-string(name) -1924 # var next-offset: int = 8 -1925 # ## inouts -1926 # while true -1927 # ## name -1928 # name = next-mu-token(first-line) -1929 # if (name == '{') goto done -1930 # if (name == '->') break -1931 # assert(name != '}') -1932 # var v: (handle var) = parse-var-with-type(name, first-line) -1933 # assert(v->register == null) -1934 # v->stack-offset = next-offset -1935 # next-offset += size-of(v) -1936 # # v->block-depth is implicitly 0 -1937 # out->inouts = append(out->inouts, v) -1938 # push(vars, v) -1939 # ## outputs -1940 # while true -1941 # ## name -1942 # name = next-mu-token(first-line) -1943 # assert(name not in '{' '}' '->') -1944 # var v: (handle var) = parse-var-with-type(name, first-line) -1945 # assert(v->register != null) -1946 # out->outputs = append(out->outputs, v) -1947 # done: -1948 # -1949 # . prologue -1950 55/push-ebp -1951 89/<- %ebp 4/r32/esp -1952 # . save registers -1953 50/push-eax -1954 51/push-ecx -1955 52/push-edx -1956 53/push-ebx -1957 57/push-edi -1958 # edi = out -1959 8b/-> *(ebp+0xc) 7/r32/edi -1960 # var word-slice/ecx: slice -1961 68/push 0/imm32/end -1962 68/push 0/imm32/start -1963 89/<- %ecx 4/r32/esp -1964 # var next-offset/edx = 8 -1965 ba/copy-to-edx 8/imm32 -1966 # read function name -1967 (next-mu-token *(ebp+8) %ecx) -1968 # error checking -1969 # TODO: error if name starts with 'break' or 'loop' -1970 # if (word-slice == '{') abort -1971 (slice-equal? %ecx "{") # => eax -1972 3d/compare-eax-and 0/imm32/false -1973 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1974 # if (word-slice == '->') abort -1975 (slice-equal? %ecx "->") # => eax -1976 3d/compare-eax-and 0/imm32/false -1977 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1978 # if (word-slice == '}') abort -1979 (slice-equal? %ecx "}") # => eax -1980 3d/compare-eax-and 0/imm32/false -1981 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -1982 # save function name -1983 (slice-to-string Heap %ecx) # => eax -1984 89/<- *edi 0/r32/eax # Function-name -1985 # initialize default subx-name as well -1986 89/<- *(edi+4) 0/r32/eax # Function-subx-name -1987 # save function inouts -1988 { -1989 $populate-mu-function-header:check-for-inout: -1990 (next-mu-token *(ebp+8) %ecx) -1991 # if (word-slice == '{') goto done -1992 (slice-equal? %ecx "{") # => eax -1993 3d/compare-eax-and 0/imm32/false -1994 0f 85/jump-if-!= $populate-mu-function-header:done/disp32 -1995 # if (word-slice == '->') break -1996 (slice-equal? %ecx "->") # => eax -1997 3d/compare-eax-and 0/imm32/false -1998 0f 85/jump-if-!= break/disp32 -1999 # if (word-slice == '}') abort -2000 (slice-equal? %ecx "}") # => eax -2001 3d/compare-eax-and 0/imm32/false -2002 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -2003 # var v/ebx: (handle var) = parse-var-with-type(word-slice, first-line) -2004 (parse-var-with-type %ecx *(ebp+8)) # => eax -2005 89/<- %ebx 0/r32/eax -2006 # assert(v->register == null) -2007 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -2008 0f 85/jump-if-!= $populate-mu-function-header:error2/disp32 -2009 # v->stack-offset = next-offset -2010 89/<- *(ebx+0xc) 2/r32/edx # Var-stack-offset -2011 # next-offset += size-of(v) -2012 (size-of %ebx) # => eax -2013 01/add %edx 0/r32/eax -2014 # v->block-depth is implicitly 0 -2015 # -2016 (append-list Heap %ebx *(edi+8)) # Function-inouts => eax -2017 89/<- *(edi+8) 0/r32/eax # Function-inouts -2018 (push *(ebp+0x10) %ebx) -2019 # -2020 e9/jump loop/disp32 -2021 } -2022 # save function outputs -2023 { -2024 $populate-mu-function-header:check-for-out: -2025 (next-mu-token *(ebp+8) %ecx) -2026 # if (word-slice == '{') break -2027 (slice-equal? %ecx "{") # => eax -2028 3d/compare-eax-and 0/imm32/false -2029 0f 85/jump-if-!= break/disp32 -2030 # if (word-slice == '->') abort -2031 (slice-equal? %ecx "->") # => eax -2032 3d/compare-eax-and 0/imm32/false -2033 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -2034 # if (word-slice == '}') abort -2035 (slice-equal? %ecx "}") # => eax -2036 3d/compare-eax-and 0/imm32/false -2037 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -2038 # -2039 (parse-var-with-type %ecx *(ebp+8)) # => eax -2040 89/<- %ebx 0/r32/eax -2041 # assert(var->register != null) -2042 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -2043 0f 84/jump-if-= $populate-mu-function-header:error3/disp32 -2044 (append-list Heap %ebx *(edi+0xc)) # Function-outputs => eax -2045 89/<- *(edi+0xc) 0/r32/eax # Function-outputs -2046 e9/jump loop/disp32 -2047 } -2048 $populate-mu-function-header:done: -2049 (check-no-tokens-left *(ebp+8)) -2050 $populate-mu-function-header:end: -2051 # . reclaim locals -2052 81 0/subop/add %esp 8/imm32 -2053 # . restore registers -2054 5f/pop-to-edi -2055 5b/pop-to-ebx -2056 5a/pop-to-edx -2057 59/pop-to-ecx -2058 58/pop-to-eax -2059 # . epilogue -2060 89/<- %esp 5/r32/ebp -2061 5d/pop-to-ebp -2062 c3/return -2063 -2064 $populate-mu-function-header:error1: -2065 # error("function header not in form 'fn <name> {'") -2066 (write-buffered Stderr "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '") -2067 (flush Stderr) -2068 (rewind-stream *(ebp+8)) -2069 (write-stream 2 *(ebp+8)) -2070 (write-buffered Stderr "'\n") -2071 (flush Stderr) -2072 # . syscall(exit, 1) -2073 bb/copy-to-ebx 1/imm32 -2074 b8/copy-to-eax 1/imm32/exit -2075 cd/syscall 0x80/imm8 -2076 # never gets here -2077 -2078 $populate-mu-function-header:error2: -2079 # error("function input '" var "' cannot be in a register") -2080 (write-buffered Stderr "function input '") -2081 (write-buffered Stderr *ebx) # Var-name -2082 (write-buffered Stderr "' cannot be in a register") -2083 (flush Stderr) -2084 # . syscall(exit, 1) -2085 bb/copy-to-ebx 1/imm32 -2086 b8/copy-to-eax 1/imm32/exit -2087 cd/syscall 0x80/imm8 -2088 # never gets here -2089 -2090 $populate-mu-function-header:error3: -2091 # error("function input '" var "' must be in a register") -2092 (write-buffered Stderr "function input '") -2093 (write-buffered Stderr *eax) # Var-name -2094 (write-buffered Stderr " must be in a register'") -2095 (flush Stderr) -2096 (rewind-stream *(ebp+8)) -2097 (write-stream 2 *(ebp+8)) -2098 (write-buffered Stderr "'\n") -2099 (flush Stderr) -2100 # . syscall(exit, 1) -2101 bb/copy-to-ebx 1/imm32 -2102 b8/copy-to-eax 1/imm32/exit -2103 cd/syscall 0x80/imm8 -2104 # never gets here -2105 -2106 test-function-header-with-arg: -2107 # . prologue -2108 55/push-ebp -2109 89/<- %ebp 4/r32/esp -2110 # setup -2111 (clear-stream _test-input-stream) -2112 (write _test-input-stream "foo n: int {\n") -2113 # var result/ecx: function -2114 2b/subtract-> *Function-size 4/r32/esp -2115 89/<- %ecx 4/r32/esp -2116 (zero-out %ecx *Function-size) -2117 # var vars/ebx: (stack (addr var) 16) -2118 81 5/subop/subtract %esp 0x10/imm32 -2119 68/push 0x10/imm32/length -2120 68/push 0/imm32/top -2121 89/<- %ebx 4/r32/esp -2122 # convert -2123 (populate-mu-function-header _test-input-stream %ecx %ebx) -2124 # check result -2125 (check-strings-equal *ecx "foo" "F - test-function-header-with-arg/name") # Function-name -2126 # edx: (handle list var) = result->inouts -2127 8b/-> *(ecx+8) 2/r32/edx # Function-inouts -2128 # ebx: (handle var) = result->inouts->value -2129 8b/-> *edx 3/r32/ebx # List-value -2130 (check-strings-equal *ebx "n" "F - test-function-header-with-arg/inout:0") # Var-name -2131 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2132 (check-ints-equal *ebx 1 "F - test-function-header-with-arg/inout:0/type:0") # Tree-left -2133 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-arg/inout:0/type:1") # Tree-right -2134 # . epilogue -2135 89/<- %esp 5/r32/ebp -2136 5d/pop-to-ebp -2137 c3/return -2138 -2139 test-function-header-with-multiple-args: -2140 # . prologue -2141 55/push-ebp -2142 89/<- %ebp 4/r32/esp -2143 # setup -2144 (clear-stream _test-input-stream) -2145 (write _test-input-stream "foo a: int, b: int c: int {\n") -2146 # result/ecx: (handle function) -2147 2b/subtract-> *Function-size 4/r32/esp -2148 89/<- %ecx 4/r32/esp -2149 (zero-out %ecx *Function-size) -2150 # var vars/ebx: (stack (addr var) 16) -2151 81 5/subop/subtract %esp 0x10/imm32 -2152 68/push 0x10/imm32/length -2153 68/push 0/imm32/top -2154 89/<- %ebx 4/r32/esp -2155 # convert -2156 (populate-mu-function-header _test-input-stream %ecx %ebx) -2157 # check result -2158 (check-strings-equal *ecx "foo") # Function-name -2159 # edx: (handle list var) = result->inouts -2160 8b/-> *(ecx+8) 2/r32/edx # Function-inouts -2161 $test-function-header-with-multiple-args:inout0: -2162 # ebx: (handle var) = result->inouts->value -2163 8b/-> *edx 3/r32/ebx # List-value -2164 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name -2165 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2166 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:0/type:0") # Tree-left -2167 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:0/type:1") # Tree-right -2168 # edx = result->inouts->next -2169 8b/-> *(edx+4) 2/r32/edx # List-next -2170 $test-function-header-with-multiple-args:inout1: -2171 # ebx = result->inouts->next->value -2172 8b/-> *edx 3/r32/ebx # List-value -2173 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args/inout:1") # Var-name -2174 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2175 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:1/type:0") # Tree-left -2176 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:1/type:1") # Tree-right -2177 # edx = result->inouts->next->next -2178 8b/-> *(edx+4) 2/r32/edx # List-next -2179 $test-function-header-with-multiple-args:inout2: -2180 # ebx = result->inouts->next->next->value -2181 8b/-> *edx 3/r32/ebx # List-value -2182 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args/inout:2") # Var-name -2183 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2184 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:2/type:0") # Tree-left -2185 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:2/type:1") # Tree-right -2186 # . epilogue -2187 89/<- %esp 5/r32/ebp -2188 5d/pop-to-ebp -2189 c3/return -2190 -2191 test-function-with-multiple-args-and-outputs: -2192 # . prologue -2193 55/push-ebp -2194 89/<- %ebp 4/r32/esp -2195 # setup -2196 (clear-stream _test-input-stream) -2197 (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx: int {\n") -2198 # result/ecx: (handle function) -2199 2b/subtract-> *Function-size 4/r32/esp -2200 89/<- %ecx 4/r32/esp -2201 (zero-out %ecx *Function-size) -2202 # var vars/ebx: (stack (addr var) 16) -2203 81 5/subop/subtract %esp 0x10/imm32 -2204 68/push 0x10/imm32/length -2205 68/push 0/imm32/top -2206 89/<- %ebx 4/r32/esp -2207 # convert -2208 (populate-mu-function-header _test-input-stream %ecx %ebx) -2209 # check result -2210 (check-strings-equal *ecx "foo") # Function-name -2211 # edx: (handle list var) = result->inouts -2212 8b/-> *(ecx+8) 2/r32/edx # Function-inouts -2213 # ebx: (handle var) = result->inouts->value -2214 8b/-> *edx 3/r32/ebx # List-value -2215 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0") # Var-name -2216 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2217 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0") # Tree-left -2218 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1") # Tree-right -2219 # edx = result->inouts->next -2220 8b/-> *(edx+4) 2/r32/edx # List-next -2221 # ebx = result->inouts->next->value -2222 8b/-> *edx 3/r32/ebx # List-value -2223 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1") # Var-name -2224 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2225 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0") # Tree-left -2226 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1") # Tree-right -2227 # edx = result->inouts->next->next -2228 8b/-> *(edx+4) 2/r32/edx # List-next -2229 # ebx = result->inouts->next->next->value -2230 8b/-> *edx 3/r32/ebx # List-value -2231 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2") # Var-name -2232 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2233 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0") # Tree-left -2234 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1") # Tree-right -2235 # edx: (handle list var) = result->outputs -2236 8b/-> *(ecx+0xc) 2/r32/edx # Function-outputs -2237 # ebx: (handle var) = result->outputs->value -2238 8b/-> *edx 3/r32/ebx # List-value -2239 (check-strings-equal *ebx "x" "F - test-function-header-with-multiple-args-and-outputs/output:0") # Var-name -2240 (check-strings-equal *(ebx+0x10) "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register -2241 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2242 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-left -2243 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-right -2244 # edx = result->outputs->next -2245 8b/-> *(edx+4) 2/r32/edx # List-next -2246 # ebx = result->outputs->next->value -2247 8b/-> *edx 3/r32/ebx # List-value -2248 (check-strings-equal *ebx "y" "F - test-function-header-with-multiple-args-and-outputs/output:1") # Var-name -2249 (check-strings-equal *(ebx+0x10) "edx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register -2250 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2251 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-left -2252 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-right -2253 # . epilogue -2254 89/<- %esp 5/r32/ebp -2255 5d/pop-to-ebp -2256 c3/return -2257 -2258 # format for variables with types -2259 # x: int -2260 # x: int, -2261 # x/eax: int -2262 # x/eax: int, -2263 # ignores at most one trailing comma -2264 # WARNING: modifies name -2265 parse-var-with-type: # name: (addr slice), first-line: (addr stream byte) -> result/eax: (handle var) -2266 # pseudocode: -2267 # var v: (handle var) = allocate(Heap, Var-size) -2268 # var s: slice -2269 # if (!slice-ends-with(name, ":")) -2270 # abort -2271 # --name->end to skip ':' -2272 # next-token-from-slice(name->start, name->end, '/', s) -2273 # v->name = slice-to-string(s) -2274 # ## register -2275 # next-token-from-slice(s->end, name->end, '/', s) -2276 # if (!slice-empty?(s)) -2277 # v->register = slice-to-string(s) -2278 # ## type -2279 # var type: (handle tree type-id) = parse-type(first-line) -2280 # v->type = type -2281 # return v -2282 # -2283 # . prologue -2284 55/push-ebp -2285 89/<- %ebp 4/r32/esp -2286 # . save registers -2287 51/push-ecx -2288 52/push-edx -2289 53/push-ebx -2290 56/push-esi -2291 57/push-edi -2292 # esi = name -2293 8b/-> *(ebp+8) 6/r32/esi -2294 # if (!slice-ends-with?(name, ":")) abort -2295 8b/-> *(esi+4) 1/r32/ecx # Slice-end -2296 49/decrement-ecx -2297 8a/copy-byte *ecx 1/r32/CL -2298 81 4/subop/and %ecx 0xff/imm32 -2299 81 7/subop/compare %ecx 0x3a/imm32/colon -2300 0f 85/jump-if-!= $parse-var-with-type:abort/disp32 -2301 # --name->end to skip ':' -2302 ff 1/subop/decrement *(esi+4) -2303 # var result/edi: (handle var) = allocate(Heap, Var-size) -2304 (allocate Heap *Var-size) # => eax -2305 (zero-out %eax *Var-size) -2306 89/<- %edi 0/r32/eax -2307 # var s/ecx: slice -2308 68/push 0/imm32/end -2309 68/push 0/imm32/start -2310 89/<- %ecx 4/r32/esp -2311 $parse-var-with-type:save-name: -2312 # save v->name -2313 (next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/' -2314 # . end/edx = s->end -2315 8b/-> *(ecx+4) 2/r32/edx -2316 $parse-var-with-type:write-name: -2317 (slice-to-string Heap %ecx) # => eax -2318 89/<- *edi 0/r32/eax # Var-name -2319 # save v->register -2320 $parse-var-with-type:save-register: -2321 (next-token-from-slice %edx *(esi+4) 0x2f %ecx) # end, name->end, '/' -2322 # if (!slice-empty?(s)) v->register = slice-to-string(s) -2323 { -2324 $parse-var-with-type:write-register: -2325 (slice-empty? %ecx) # => eax -2326 3d/compare-eax-and 0/imm32/false -2327 75/jump-if-!= break/disp8 -2328 (slice-to-string Heap %ecx) -2329 89/<- *(edi+0x10) 0/r32/eax # Var-register -2330 } -2331 $parse-var-with-type:save-type: -2332 (parse-type Heap *(ebp+0xc)) # => eax -2333 89/<- *(edi+4) 0/r32/eax # Var-type -2334 $parse-var-with-type:end: -2335 # return result -2336 89/<- %eax 7/r32/edi -2337 # . reclaim locals -2338 81 0/subop/add %esp 8/imm32 -2339 # . restore registers -2340 5f/pop-to-edi -2341 5e/pop-to-esi -2342 5b/pop-to-ebx -2343 5a/pop-to-edx -2344 59/pop-to-ecx -2345 # . epilogue -2346 89/<- %esp 5/r32/ebp -2347 5d/pop-to-ebp -2348 c3/return -2349 -2350 $parse-var-with-type:abort: -2351 # error("var should have form 'name: type' in '" line "'\n") -2352 (write-buffered Stderr "var should have form 'name: type' in '") -2353 (flush Stderr) -2354 (rewind-stream *(ebp+0xc)) -2355 (write-stream 2 *(ebp+0xc)) -2356 (write-buffered Stderr "'\n") -2357 (flush Stderr) -2358 # . syscall(exit, 1) -2359 bb/copy-to-ebx 1/imm32 -2360 b8/copy-to-eax 1/imm32/exit -2361 cd/syscall 0x80/imm8 -2362 # never gets here -2363 -2364 parse-type: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) -2365 # pseudocode: -2366 # var s: slice = next-mu-token(in) -2367 # assert s != "" -2368 # assert s != "->" -2369 # assert s != "{" -2370 # assert s != "}" -2371 # if s == ")" -2372 # return 0 -2373 # result = allocate(Tree) -2374 # zero-out(result, *Tree-size) -2375 # if s != "(" -2376 # result->left = pos-slice(Type-id, s) -2377 # return -2378 # result->left = parse-type(ad, in) -2379 # result->right = parse-type-tree(ad, in) -2380 # -2381 # . prologue -2382 55/push-ebp -2383 89/<- %ebp 4/r32/esp -2384 # . save registers -2385 51/push-ecx -2386 52/push-edx -2387 # var s/ecx: slice -2388 68/push 0/imm32 -2389 68/push 0/imm32 -2390 89/<- %ecx 4/r32/esp -2391 # s = next-mu-token(in) -2392 (next-mu-token *(ebp+0xc) %ecx) -2393 #? (write-buffered Stderr "tok: ") -2394 #? (write-slice-buffered Stderr %ecx) -2395 #? (write-buffered Stderr "$\n") -2396 #? (flush Stderr) -2397 # assert s != "" -2398 (slice-equal? %ecx "") -2399 3d/compare-eax-and 0/imm32/false -2400 0f 85/jump-if-!= $parse-type:abort/disp32 -2401 # assert s != "{" -2402 (slice-equal? %ecx "{") -2403 3d/compare-eax-and 0/imm32/false -2404 0f 85/jump-if-!= $parse-type:abort/disp32 -2405 # assert s != "}" -2406 (slice-equal? %ecx "}") -2407 3d/compare-eax-and 0/imm32/false -2408 0f 85/jump-if-!= $parse-type:abort/disp32 -2409 # assert s != "->" -2410 (slice-equal? %ecx "->") -2411 3d/compare-eax-and 0/imm32/false -2412 0f 85/jump-if-!= $parse-type:abort/disp32 -2413 # if (s == ")") return 0 -2414 (slice-equal? %ecx ")") -2415 3d/compare-eax-and 0/imm32/false -2416 b8/copy-to-eax 0/imm32 -2417 0f 85/jump-if-!= $parse-type:end/disp32 -2418 # var result/edx: (handle tree type-id) -2419 (allocate *(ebp+8) *Tree-size) # => eax -2420 (zero-out %eax *Tree-size) -2421 89/<- %edx 0/r32/eax -2422 { -2423 # if (s != "(") break -2424 (slice-equal? %ecx "(") -2425 3d/compare-eax-and 0/imm32/false -2426 75/jump-if-!= break/disp8 -2427 # result->left = pos-slice(Type-id, s) -2428 (pos-slice Type-id %ecx) -2429 #? (write-buffered Stderr "=> {") -2430 #? (print-int32-buffered Stderr %eax) -2431 #? (write-buffered Stderr ", 0}\n") -2432 #? (flush Stderr) -2433 89/<- *edx 0/r32/eax # Tree-left -2434 e9/jump $parse-type:return-edx/disp32 -2435 } -2436 # otherwise s == "(" -2437 # result->left = parse-type(ad, in) -2438 (parse-type *(ebp+8) *(ebp+0xc)) -2439 #? (write-buffered Stderr "=> {") -2440 #? (print-int32-buffered Stderr %eax) -2441 89/<- *edx 0/r32/eax # Tree-left -2442 # result->right = parse-type-tree(ad, in) -2443 (parse-type-tree *(ebp+8) *(ebp+0xc)) -2444 #? (write-buffered Stderr Space) -2445 #? (print-int32-buffered Stderr %eax) -2446 #? (write-buffered Stderr "}\n") -2447 #? (flush Stderr) -2448 89/<- *(edx+4) 0/r32/eax # Tree-right -2449 $parse-type:return-edx: -2450 89/<- %eax 2/r32/edx -2451 $parse-type:end: -2452 # . reclaim locals -2453 81 0/subop/add %esp 8/imm32 -2454 # . restore registers -2455 5a/pop-to-edx -2456 59/pop-to-ecx -2457 # . epilogue -2458 89/<- %esp 5/r32/ebp -2459 5d/pop-to-ebp -2460 c3/return -2461 -2462 $parse-type:abort: -2463 # error("unexpected token when parsing type: '" s "'\n") -2464 (write-buffered Stderr "unexpected token when parsing type: '") -2465 (write-slice-buffered Stderr %ecx) -2466 (write-buffered Stderr "'\n") -2467 (flush Stderr) -2468 # . syscall(exit, 1) -2469 bb/copy-to-ebx 1/imm32 -2470 b8/copy-to-eax 1/imm32/exit -2471 cd/syscall 0x80/imm8 -2472 # never gets here -2473 -2474 parse-type-tree: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) -2475 # pseudocode: -2476 # var tmp: (handle tree type-id) = parse-type(ad, in) -2477 # if tmp == 0 -2478 # return 0 -2479 # result = allocate(Tree) -2480 # zero-out(result, *Tree-size) -2481 # result->left = tmp -2482 # result->right = parse-type-tree(ad, in) -2483 # -2484 # . prologue -2485 55/push-ebp -2486 89/<- %ebp 4/r32/esp -2487 # . save registers -2488 51/push-ecx -2489 52/push-edx -2490 # var tmp/eax: (handle tree type-id) = parse-type(ad, in) -2491 (parse-type *(ebp+8) *(ebp+0xc)) -2492 # if (tmp == 0) return tmp -2493 3d/compare-eax-and 0/imm32 -2494 74/jump-if-= $parse-type-tree:end/disp8 -2495 # var tmp2/ecx = tmp -2496 89/<- %ecx 0/r32/eax -2497 # var result/edx: (handle tree type-id) -2498 (allocate *(ebp+8) *Tree-size) # => eax -2499 (zero-out %eax *Tree-size) -2500 89/<- %edx 0/r32/eax -2501 # result->left = tmp2 -2502 89/<- *edx 1/r32/ecx # Tree-left -2503 # result->right = parse-type-tree(ad, in) -2504 (parse-type-tree *(ebp+8) *(ebp+0xc)) -2505 89/<- *(edx+4) 0/r32/eax # Tree-right -2506 $parse-type-tree:return-edx: -2507 89/<- %eax 2/r32/edx -2508 $parse-type-tree:end: -2509 # . restore registers -2510 5a/pop-to-edx -2511 59/pop-to-ecx -2512 # . epilogue -2513 89/<- %esp 5/r32/ebp -2514 5d/pop-to-ebp -2515 c3/return -2516 -2517 next-mu-token: # in: (addr stream byte), out: (addr slice) -2518 # pseudocode: -2519 # start: -2520 # skip-chars-matching-whitespace(in) -2521 # if in->read >= in->write # end of in -2522 # out = {0, 0} -2523 # return -2524 # out->start = &in->data[in->read] -2525 # var curr-byte/eax: byte = in->data[in->read] -2526 # if curr->byte == ',' # comment token -2527 # ++in->read -2528 # goto start -2529 # if curr-byte == '#' # comment -2530 # goto done # treat as eof -2531 # if curr-byte == '"' # string literal -2532 # skip-string(in) -2533 # goto done # no metadata -2534 # if curr-byte == '(' -2535 # ++in->read -2536 # goto done -2537 # if curr-byte == ')' -2538 # ++in->read -2539 # goto done -2540 # # read a word -2541 # while true -2542 # if in->read >= in->write -2543 # break -2544 # curr-byte = in->data[in->read] -2545 # if curr-byte == ' ' -2546 # break -2547 # if curr-byte == '\r' -2548 # break -2549 # if curr-byte == '\n' -2550 # break -2551 # if curr-byte == '(' -2552 # break -2553 # if curr-byte == ')' -2554 # break -2555 # if curr-byte == ',' -2556 # break -2557 # ++in->read -2558 # done: -2559 # out->end = &in->data[in->read] -2560 # -2561 # . prologue -2562 55/push-ebp -2563 89/<- %ebp 4/r32/esp -2564 # . save registers -2565 50/push-eax -2566 51/push-ecx -2567 56/push-esi -2568 57/push-edi -2569 # esi = in -2570 8b/-> *(ebp+8) 6/r32/esi -2571 # edi = out -2572 8b/-> *(ebp+0xc) 7/r32/edi -2573 $next-mu-token:start: -2574 (skip-chars-matching-whitespace %esi) -2575 $next-mu-token:check0: -2576 # if (in->read >= in->write) return out = {0, 0} -2577 # . ecx = in->read -2578 8b/-> *(esi+4) 1/r32/ecx -2579 # . if (ecx >= in->write) return out = {0, 0} -2580 3b/compare 1/r32/ecx *esi -2581 c7 0/subop/copy *edi 0/imm32 -2582 c7 0/subop/copy *(edi+4) 0/imm32 -2583 0f 8d/jump-if->= $next-mu-token:end/disp32 -2584 # out->start = &in->data[in->read] -2585 8d/copy-address *(esi+ecx+0xc) 0/r32/eax -2586 89/<- *edi 0/r32/eax -2587 # var curr-byte/eax: byte = in->data[in->read] -2588 31/xor %eax 0/r32/eax -2589 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -2590 { -2591 $next-mu-token:check-for-comma: -2592 # if (curr-byte != ',') break -2593 3d/compare-eax-and 0x2c/imm32/comma -2594 75/jump-if-!= break/disp8 -2595 # ++in->read -2596 ff 0/subop/increment *(esi+4) -2597 # restart -2598 e9/jump $next-mu-token:start/disp32 -2599 } -2600 { -2601 $next-mu-token:check-for-comment: -2602 # if (curr-byte != '#') break -2603 3d/compare-eax-and 0x23/imm32/pound -2604 75/jump-if-!= break/disp8 -2605 # return eof -2606 e9/jump $next-mu-token:done/disp32 -2607 } -2608 { -2609 $next-mu-token:check-for-string-literal: -2610 # if (curr-byte != '"') break -2611 3d/compare-eax-and 0x22/imm32/dquote -2612 75/jump-if-!= break/disp8 -2613 (skip-string %esi) -2614 # return -2615 e9/jump $next-mu-token:done/disp32 -2616 } -2617 { -2618 $next-mu-token:check-for-open-paren: -2619 # if (curr-byte != '(') break -2620 3d/compare-eax-and 0x28/imm32/open-paren -2621 75/jump-if-!= break/disp8 -2622 # ++in->read -2623 ff 0/subop/increment *(esi+4) -2624 # return -2625 e9/jump $next-mu-token:done/disp32 -2626 } -2627 { -2628 $next-mu-token:check-for-close-paren: -2629 # if (curr-byte != ')') break -2630 3d/compare-eax-and 0x29/imm32/close-paren -2631 75/jump-if-!= break/disp8 -2632 # ++in->read -2633 ff 0/subop/increment *(esi+4) -2634 # return -2635 e9/jump $next-mu-token:done/disp32 -2636 } -2637 { -2638 $next-mu-token:regular-word-without-metadata: -2639 # if (in->read >= in->write) break -2640 # . ecx = in->read -2641 8b/-> *(esi+4) 1/r32/ecx -2642 # . if (ecx >= in->write) break -2643 3b/compare *esi 1/r32/ecx -2644 7d/jump-if->= break/disp8 -2645 # var c/eax: byte = in->data[in->read] -2646 31/xor %eax 0/r32/eax -2647 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -2648 # if (c == ' ') break -2649 3d/compare-eax-and 0x20/imm32/space -2650 74/jump-if-= break/disp8 -2651 # if (c == '\r') break -2652 3d/compare-eax-and 0xd/imm32/carriage-return -2653 74/jump-if-= break/disp8 -2654 # if (c == '\n') break -2655 3d/compare-eax-and 0xa/imm32/newline -2656 74/jump-if-= break/disp8 -2657 # if (c == '(') break -2658 3d/compare-eax-and 0x28/imm32/open-paren -2659 0f 84/jump-if-= break/disp32 -2660 # if (c == ')') break -2661 3d/compare-eax-and 0x29/imm32/close-paren -2662 0f 84/jump-if-= break/disp32 -2663 # if (c == ',') break -2664 3d/compare-eax-and 0x2c/imm32/comma -2665 0f 84/jump-if-= break/disp32 -2666 # ++in->read -2667 ff 0/subop/increment *(esi+4) -2668 # -2669 e9/jump loop/disp32 -2670 } -2671 $next-mu-token:done: -2672 # out->end = &in->data[in->read] -2673 8b/-> *(esi+4) 1/r32/ecx -2674 8d/copy-address *(esi+ecx+0xc) 0/r32/eax -2675 89/<- *(edi+4) 0/r32/eax -2676 $next-mu-token:end: -2677 # . restore registers -2678 5f/pop-to-edi -2679 5e/pop-to-esi -2680 59/pop-to-ecx -2681 58/pop-to-eax -2682 # . epilogue -2683 89/<- %esp 5/r32/ebp -2684 5d/pop-to-ebp -2685 c3/return -2686 -2687 # return the index in an array of strings matching 's' -2688 # index is denominated in elements, not bytes -2689 pos-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int -2690 # . prologue -2691 55/push-ebp -2692 89/<- %ebp 4/r32/esp -2693 # . save registers -2694 51/push-ecx -2695 52/push-edx -2696 53/push-ebx -2697 56/push-esi -2698 #? (write-buffered Stderr "pos-slice: ") -2699 #? (write-slice-buffered Stderr *(ebp+0xc)) -2700 #? (write-buffered Stderr "\n") -2701 #? (flush Stderr) -2702 # esi = arr -2703 8b/-> *(ebp+8) 6/r32/esi -2704 # var index/ecx: int = 0 -2705 b9/copy-to-ecx 0/imm32 -2706 # var curr/edx: (addr (addr array byte)) = arr->data -2707 8d/copy-address *(esi+0xc) 2/r32/edx -2708 # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write] -2709 8b/-> *esi 3/r32/ebx -2710 8d/copy-address *(esi+ebx+0xc) 3/r32/ebx -2711 { -2712 #? (write-buffered Stderr " ") -2713 #? (print-int32-buffered Stderr %ecx) -2714 #? (write-buffered Stderr "\n") -2715 #? (flush Stderr) -2716 # if (curr >= max) return -1 -2717 39/compare %edx 3/r32/ebx -2718 b8/copy-to-eax -1/imm32 -2719 73/jump-if-addr>= $pos-slice:end/disp8 -2720 # if (slice-equal?(s, *curr)) break -2721 (slice-equal? *(ebp+0xc) *edx) # => eax -2722 3d/compare-eax-and 0/imm32/false -2723 75/jump-if-!= break/disp8 -2724 # ++index -2725 41/increment-ecx -2726 # curr += 4 -2727 81 0/subop/add %edx 4/imm32 -2728 # -2729 eb/jump loop/disp8 -2730 } -2731 # return index -2732 89/<- %eax 1/r32/ecx -2733 $pos-slice:end: -2734 #? (write-buffered Stderr "=> ") -2735 #? (print-int32-buffered Stderr %eax) -2736 #? (write-buffered Stderr "\n") -2737 # . restore registers -2738 5e/pop-to-esi -2739 5b/pop-to-ebx -2740 5a/pop-to-edx -2741 59/pop-to-ecx -2742 # . epilogue -2743 89/<- %esp 5/r32/ebp -2744 5d/pop-to-ebp -2745 c3/return -2746 -2747 == data -2748 -2749 Type-id: # (stream (address array byte)) -2750 0x18/imm32/write -2751 0/imm32/read -2752 0x100/imm32/length -2753 # data -2754 "literal"/imm32 # 0 -2755 "int"/imm32 # 1 -2756 "addr"/imm32 # 2 -2757 "array"/imm32 # 3 -2758 "handle"/imm32 # 4 -2759 "bool"/imm32 # 5 -2760 0/imm32 -2761 0/imm32 -2762 # 0x20 -2763 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2764 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2765 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2766 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2767 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2768 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2769 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2770 -2771 == code -2772 -2773 test-parse-var-with-type: -2774 # . prologue -2775 55/push-ebp -2776 89/<- %ebp 4/r32/esp -2777 # (eax..ecx) = "x:" -2778 b8/copy-to-eax "x:"/imm32 -2779 8b/-> *eax 1/r32/ecx -2780 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2781 05/add-to-eax 4/imm32 -2782 # var slice/ecx: slice = {eax, ecx} -2783 51/push-ecx -2784 50/push-eax -2785 89/<- %ecx 4/r32/esp -2786 # _test-input-stream contains "int" -2787 (clear-stream _test-input-stream) -2788 (write _test-input-stream "int") -2789 # -2790 (parse-var-with-type %ecx _test-input-stream) -2791 8b/-> *eax 2/r32/edx # Var-name -2792 (check-strings-equal %edx "x" "F - test-var-with-type/name") -2793 8b/-> *(eax+4) 2/r32/edx # Var-type -2794 (check-ints-equal *edx 1 "F - test-var-with-type/type") -2795 (check-ints-equal *(edx+4) 0 "F - test-var-with-type/type") -2796 # . epilogue -2797 89/<- %esp 5/r32/ebp -2798 5d/pop-to-ebp -2799 c3/return -2800 -2801 test-parse-var-with-type-and-register: -2802 # . prologue -2803 55/push-ebp -2804 89/<- %ebp 4/r32/esp -2805 # (eax..ecx) = "x/eax:" -2806 b8/copy-to-eax "x/eax:"/imm32 -2807 8b/-> *eax 1/r32/ecx -2808 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2809 05/add-to-eax 4/imm32 -2810 # var slice/ecx: slice = {eax, ecx} -2811 51/push-ecx -2812 50/push-eax -2813 89/<- %ecx 4/r32/esp -2814 # _test-input-stream contains "int" -2815 (clear-stream _test-input-stream) -2816 (write _test-input-stream "int") -2817 # -2818 (parse-var-with-type %ecx _test-input-stream) -2819 8b/-> *eax 2/r32/edx # Var-name -2820 (check-strings-equal %edx "x" "F - test-var-with-type-and-register/name") -2821 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2822 (check-strings-equal %edx "eax" "F - test-var-with-type-and-register/register") -2823 8b/-> *(eax+4) 2/r32/edx # Var-type -2824 (check-ints-equal *edx 1 "F - test-var-with-type-and-register/type") -2825 (check-ints-equal *(edx+4) 0 "F - test-var-with-type-and-register/type") -2826 # . epilogue -2827 89/<- %esp 5/r32/ebp -2828 5d/pop-to-ebp -2829 c3/return -2830 -2831 test-parse-var-with-trailing-characters: -2832 # . prologue -2833 55/push-ebp -2834 89/<- %ebp 4/r32/esp -2835 # (eax..ecx) = "x:" -2836 b8/copy-to-eax "x:"/imm32 -2837 8b/-> *eax 1/r32/ecx -2838 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2839 05/add-to-eax 4/imm32 -2840 # var slice/ecx: slice = {eax, ecx} -2841 51/push-ecx -2842 50/push-eax -2843 89/<- %ecx 4/r32/esp -2844 # _test-input-stream contains "int," -2845 (clear-stream _test-input-stream) -2846 (write _test-input-stream "int,") -2847 # -2848 (parse-var-with-type %ecx _test-input-stream) -2849 8b/-> *eax 2/r32/edx # Var-name -2850 (check-strings-equal %edx "x" "F - test-var-with-trailing-characters/name") -2851 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2852 (check-ints-equal %edx 0 "F - test-var-with-trailing-characters/register") -2853 8b/-> *(eax+4) 2/r32/edx # Var-type -2854 (check-ints-equal *edx 1 "F - test-var-with-trailing-characters/type") -2855 (check-ints-equal *(edx+4) 0 "F - test-var-with-trailing-characters/type") -2856 # . epilogue -2857 89/<- %esp 5/r32/ebp -2858 5d/pop-to-ebp -2859 c3/return -2860 -2861 test-parse-var-with-register-and-trailing-characters: -2862 # . prologue -2863 55/push-ebp -2864 89/<- %ebp 4/r32/esp -2865 # (eax..ecx) = "x/eax:" -2866 b8/copy-to-eax "x/eax:"/imm32 -2867 8b/-> *eax 1/r32/ecx -2868 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2869 05/add-to-eax 4/imm32 -2870 # var slice/ecx: slice = {eax, ecx} -2871 51/push-ecx -2872 50/push-eax -2873 89/<- %ecx 4/r32/esp -2874 # _test-input-stream contains "int," -2875 (clear-stream _test-input-stream) -2876 (write _test-input-stream "int,") -2877 # -2878 (parse-var-with-type %ecx _test-input-stream) -2879 8b/-> *eax 2/r32/edx # Var-name -2880 (check-strings-equal %edx "x" "F - test-var-with-register-and-trailing-characters/name") -2881 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2882 (check-strings-equal %edx "eax" "F - test-var-with-register-and-trailing-characters/register") -2883 8b/-> *(eax+4) 2/r32/edx # Var-type -2884 (check-ints-equal *edx 1 "F - test-var-with-register-and-trailing-characters/type") -2885 (check-ints-equal *(edx+4) 0 "F - test-var-with-register-and-trailing-characters/type") -2886 # . epilogue -2887 89/<- %esp 5/r32/ebp -2888 5d/pop-to-ebp -2889 c3/return -2890 -2891 test-parse-var-with-compound-type: -2892 # . prologue -2893 55/push-ebp -2894 89/<- %ebp 4/r32/esp -2895 # (eax..ecx) = "x:" -2896 b8/copy-to-eax "x:"/imm32 -2897 8b/-> *eax 1/r32/ecx -2898 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2899 05/add-to-eax 4/imm32 -2900 # var slice/ecx: slice = {eax, ecx} -2901 51/push-ecx -2902 50/push-eax -2903 89/<- %ecx 4/r32/esp -2904 # _test-input-stream contains "(addr int)" -2905 (clear-stream _test-input-stream) -2906 (write _test-input-stream "(addr int)") -2907 # -2908 (parse-var-with-type %ecx _test-input-stream) -2909 8b/-> *eax 2/r32/edx # Var-name -2910 (check-strings-equal %edx "x" "F - test-var-with-compound-type/name") -2911 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2912 (check-ints-equal %edx 0 "F - test-var-with-compound-type/register") -2913 # var type/edx: (handle tree type-id) = var->type -2914 8b/-> *(eax+4) 2/r32/edx # Var-type -2915 # type->left == atom(addr) -2916 8b/-> *edx 0/r32/eax # Atom-value -2917 (check-ints-equal *eax 2 "F - test-var-with-compound-type/type:0") # Tree-left -2918 # type->right->left == atom(int) -2919 8b/-> *(edx+4) 2/r32/edx # Tree-right -2920 8b/-> *edx 0/r32/eax # Tree-left -2921 (check-ints-equal *eax 1 "F - test-var-with-compound-type/type:1") # Atom-value -2922 # type->right->right == null -2923 (check-ints-equal *(edx+4) 0 "F - test-var-with-compound-type/type:2") # Tree-right -2924 # . epilogue -2925 89/<- %esp 5/r32/ebp -2926 5d/pop-to-ebp -2927 c3/return -2928 -2929 # identifier starts with a letter or '$' or '_' -2930 # no constraints at the moment on later letters -2931 # all we really want to do so far is exclude '{', '}' and '->' -2932 is-identifier?: # in: (addr slice) -> result/eax: boolean -2933 # . prologue -2934 55/push-ebp -2935 89/<- %ebp 4/r32/esp -2936 # if (slice-empty?(in)) return false -2937 (slice-empty? *(ebp+8)) # => eax -2938 3d/compare-eax-and 0/imm32/false -2939 75/jump-if-!= $is-identifier?:false/disp8 -2940 # var c/eax: byte = *in->start -2941 8b/-> *(ebp+8) 0/r32/eax -2942 8b/-> *eax 0/r32/eax -2943 8a/copy-byte *eax 0/r32/AL -2944 81 4/subop/and %eax 0xff/imm32 -2945 # if (c == '$') return true -2946 3d/compare-eax-and 0x24/imm32/$ -2947 74/jump-if-= $is-identifier?:true/disp8 -2948 # if (c == '_') return true -2949 3d/compare-eax-and 0x5f/imm32/_ -2950 74/jump-if-= $is-identifier?:true/disp8 -2951 # drop case -2952 25/and-eax-with 0x5f/imm32 -2953 # if (c < 'A') return false -2954 3d/compare-eax-and 0x41/imm32/A -2955 7c/jump-if-< $is-identifier?:false/disp8 -2956 # if (c > 'Z') return false -2957 3d/compare-eax-and 0x5a/imm32/Z -2958 7f/jump-if-> $is-identifier?:false/disp8 -2959 # otherwise return true -2960 $is-identifier?:true: -2961 b8/copy-to-eax 1/imm32/true -2962 eb/jump $is-identifier?:end/disp8 -2963 $is-identifier?:false: -2964 b8/copy-to-eax 0/imm32/false -2965 $is-identifier?:end: -2966 # . epilogue -2967 89/<- %esp 5/r32/ebp -2968 5d/pop-to-ebp -2969 c3/return -2970 -2971 test-is-identifier-dollar: -2972 # . prologue -2973 55/push-ebp -2974 89/<- %ebp 4/r32/esp -2975 # (eax..ecx) = "$a" -2976 b8/copy-to-eax "$a"/imm32 -2977 8b/-> *eax 1/r32/ecx -2978 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2979 05/add-to-eax 4/imm32 -2980 # var slice/ecx: slice = {eax, ecx} -2981 51/push-ecx -2982 50/push-eax -2983 89/<- %ecx 4/r32/esp -2984 # -2985 (is-identifier? %ecx) -2986 (check-ints-equal %eax 1 "F - test-is-identifier-dollar") -2987 # . epilogue -2988 89/<- %esp 5/r32/ebp -2989 5d/pop-to-ebp -2990 c3/return -2991 -2992 test-is-identifier-underscore: -2993 # . prologue -2994 55/push-ebp -2995 89/<- %ebp 4/r32/esp -2996 # (eax..ecx) = "_a" -2997 b8/copy-to-eax "_a"/imm32 -2998 8b/-> *eax 1/r32/ecx -2999 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3000 05/add-to-eax 4/imm32 -3001 # var slice/ecx: slice = {eax, ecx} -3002 51/push-ecx -3003 50/push-eax -3004 89/<- %ecx 4/r32/esp -3005 # -3006 (is-identifier? %ecx) -3007 (check-ints-equal %eax 1 "F - test-is-identifier-underscore") -3008 # . epilogue -3009 89/<- %esp 5/r32/ebp -3010 5d/pop-to-ebp -3011 c3/return -3012 -3013 test-is-identifier-a: -3014 # . prologue -3015 55/push-ebp -3016 89/<- %ebp 4/r32/esp -3017 # (eax..ecx) = "a$" -3018 b8/copy-to-eax "a$"/imm32 -3019 8b/-> *eax 1/r32/ecx -3020 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3021 05/add-to-eax 4/imm32 -3022 # var slice/ecx: slice = {eax, ecx} -3023 51/push-ecx -3024 50/push-eax -3025 89/<- %ecx 4/r32/esp -3026 # -3027 (is-identifier? %ecx) -3028 (check-ints-equal %eax 1 "F - test-is-identifier-a") -3029 # . epilogue -3030 89/<- %esp 5/r32/ebp -3031 5d/pop-to-ebp -3032 c3/return -3033 -3034 test-is-identifier-z: -3035 # . prologue -3036 55/push-ebp -3037 89/<- %ebp 4/r32/esp -3038 # (eax..ecx) = "z$" -3039 b8/copy-to-eax "z$"/imm32 -3040 8b/-> *eax 1/r32/ecx -3041 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3042 05/add-to-eax 4/imm32 -3043 # var slice/ecx: slice = {eax, ecx} -3044 51/push-ecx -3045 50/push-eax -3046 89/<- %ecx 4/r32/esp -3047 # -3048 (is-identifier? %ecx) -3049 (check-ints-equal %eax 1 "F - test-is-identifier-z") -3050 # . epilogue -3051 89/<- %esp 5/r32/ebp -3052 5d/pop-to-ebp -3053 c3/return -3054 -3055 test-is-identifier-A: -3056 # . prologue -3057 55/push-ebp -3058 89/<- %ebp 4/r32/esp -3059 # (eax..ecx) = "A$" -3060 b8/copy-to-eax "A$"/imm32 -3061 8b/-> *eax 1/r32/ecx -3062 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3063 05/add-to-eax 4/imm32 -3064 # var slice/ecx: slice = {eax, ecx} -3065 51/push-ecx -3066 50/push-eax -3067 89/<- %ecx 4/r32/esp -3068 # -3069 (is-identifier? %ecx) -3070 (check-ints-equal %eax 1 "F - test-is-identifier-A") -3071 # . epilogue -3072 89/<- %esp 5/r32/ebp -3073 5d/pop-to-ebp -3074 c3/return -3075 -3076 test-is-identifier-Z: -3077 # . prologue -3078 55/push-ebp -3079 89/<- %ebp 4/r32/esp -3080 # (eax..ecx) = "Z$" -3081 b8/copy-to-eax "Z$"/imm32 -3082 8b/-> *eax 1/r32/ecx -3083 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3084 05/add-to-eax 4/imm32 -3085 # var slice/ecx: slice = {eax, ecx} -3086 51/push-ecx -3087 50/push-eax -3088 89/<- %ecx 4/r32/esp -3089 # -3090 (is-identifier? %ecx) -3091 (check-ints-equal %eax 1 "F - test-is-identifier-Z") -3092 # . epilogue -3093 89/<- %esp 5/r32/ebp -3094 5d/pop-to-ebp -3095 c3/return -3096 -3097 test-is-identifier-@: -3098 # character before 'A' is invalid -3099 # . prologue -3100 55/push-ebp -3101 89/<- %ebp 4/r32/esp -3102 # (eax..ecx) = "@a" -3103 b8/copy-to-eax "@a"/imm32 -3104 8b/-> *eax 1/r32/ecx -3105 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3106 05/add-to-eax 4/imm32 -3107 # var slice/ecx: slice = {eax, ecx} -3108 51/push-ecx -3109 50/push-eax -3110 89/<- %ecx 4/r32/esp -3111 # -3112 (is-identifier? %ecx) -3113 (check-ints-equal %eax 0 "F - test-is-identifier-@") -3114 # . epilogue -3115 89/<- %esp 5/r32/ebp -3116 5d/pop-to-ebp -3117 c3/return -3118 -3119 test-is-identifier-square-bracket: -3120 # character after 'Z' is invalid -3121 # . prologue -3122 55/push-ebp -3123 89/<- %ebp 4/r32/esp -3124 # (eax..ecx) = "[a" -3125 b8/copy-to-eax "[a"/imm32 -3126 8b/-> *eax 1/r32/ecx -3127 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3128 05/add-to-eax 4/imm32 -3129 # var slice/ecx: slice = {eax, ecx} -3130 51/push-ecx -3131 50/push-eax -3132 89/<- %ecx 4/r32/esp -3133 # -3134 (is-identifier? %ecx) -3135 (check-ints-equal %eax 0 "F - test-is-identifier-@") -3136 # . epilogue -3137 89/<- %esp 5/r32/ebp -3138 5d/pop-to-ebp -3139 c3/return -3140 -3141 test-is-identifier-backtick: -3142 # character before 'a' is invalid -3143 # . prologue -3144 55/push-ebp -3145 89/<- %ebp 4/r32/esp -3146 # (eax..ecx) = "`a" -3147 b8/copy-to-eax "`a"/imm32 -3148 8b/-> *eax 1/r32/ecx -3149 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3150 05/add-to-eax 4/imm32 -3151 # var slice/ecx: slice = {eax, ecx} -3152 51/push-ecx -3153 50/push-eax -3154 89/<- %ecx 4/r32/esp -3155 # -3156 (is-identifier? %ecx) -3157 (check-ints-equal %eax 0 "F - test-is-identifier-backtick") -3158 # . epilogue -3159 89/<- %esp 5/r32/ebp -3160 5d/pop-to-ebp -3161 c3/return -3162 -3163 test-is-identifier-curly-brace-open: -3164 # character after 'z' is invalid; also used for blocks -3165 # . prologue -3166 55/push-ebp -3167 89/<- %ebp 4/r32/esp -3168 # (eax..ecx) = "{a" -3169 b8/copy-to-eax "{a"/imm32 -3170 8b/-> *eax 1/r32/ecx -3171 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3172 05/add-to-eax 4/imm32 -3173 # var slice/ecx: slice = {eax, ecx} -3174 51/push-ecx -3175 50/push-eax -3176 89/<- %ecx 4/r32/esp -3177 # -3178 (is-identifier? %ecx) -3179 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open") -3180 # . epilogue -3181 89/<- %esp 5/r32/ebp -3182 5d/pop-to-ebp -3183 c3/return -3184 -3185 test-is-identifier-curly-brace-close: -3186 # . prologue -3187 55/push-ebp -3188 89/<- %ebp 4/r32/esp -3189 # (eax..ecx) = "}a" -3190 b8/copy-to-eax "}a"/imm32 -3191 8b/-> *eax 1/r32/ecx -3192 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3193 05/add-to-eax 4/imm32 -3194 # var slice/ecx: slice = {eax, ecx} -3195 51/push-ecx -3196 50/push-eax -3197 89/<- %ecx 4/r32/esp -3198 # -3199 (is-identifier? %ecx) -3200 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close") -3201 # . epilogue -3202 89/<- %esp 5/r32/ebp -3203 5d/pop-to-ebp -3204 c3/return -3205 -3206 test-is-identifier-hyphen: -3207 # disallow leading '-' since '->' has special meaning -3208 # . prologue -3209 55/push-ebp -3210 89/<- %ebp 4/r32/esp -3211 # (eax..ecx) = "-a" -3212 b8/copy-to-eax "-a"/imm32 -3213 8b/-> *eax 1/r32/ecx -3214 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3215 05/add-to-eax 4/imm32 -3216 # var slice/ecx: slice = {eax, ecx} -3217 51/push-ecx -3218 50/push-eax -3219 89/<- %ecx 4/r32/esp -3220 # -3221 (is-identifier? %ecx) -3222 (check-ints-equal %eax 0 "F - test-is-identifier-hyphen") -3223 # . epilogue -3224 89/<- %esp 5/r32/ebp -3225 5d/pop-to-ebp -3226 c3/return -3227 -3228 populate-mu-function-body: # in: (addr buffered-file), out: (handle function), vars: (addr stack (handle var)) -3229 # . prologue -3230 55/push-ebp -3231 89/<- %ebp 4/r32/esp -3232 # . save registers -3233 50/push-eax -3234 56/push-esi -3235 57/push-edi -3236 # esi = in -3237 8b/-> *(ebp+8) 6/r32/esi -3238 # edi = out -3239 8b/-> *(ebp+0xc) 7/r32/edi -3240 # initialize some global state -3241 c7 0/subop/copy *Curr-block-depth 1/imm32 -3242 c7 0/subop/copy *Next-local-stack-offset -4/imm32 -3243 # var eax: (handle block) = parse-mu-block(in, vars, fn) -3244 (parse-mu-block %esi *(ebp+0x10) %edi) # => eax -3245 # out->body = eax -3246 89/<- *(edi+0x10) 0/r32/eax # Function-body -3247 $populate-mu-function-body:end: -3248 # . restore registers -3249 5f/pop-to-edi -3250 5e/pop-to-esi -3251 58/pop-to-eax -3252 # . epilogue -3253 89/<- %esp 5/r32/ebp -3254 5d/pop-to-ebp -3255 c3/return -3256 -3257 == data -3258 -3259 # Global state added to each var record when parsing a function -3260 -3261 Curr-block-depth: # (addr int) -3262 0/imm32 -3263 Next-local-stack-offset: # (addr int) -3264 -4/imm32 -3265 -3266 Next-block-index: # (addr int) -3267 1/imm32 -3268 -3269 == code -3270 -3271 # parses a block, assuming that the leading '{' has already been read by the caller -3272 parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle block) -3273 # pseudocode: -3274 # var line: (stream byte 512) -3275 # var word-slice: slice -3276 # increment *Curr-block-depth -3277 # result/eax = allocate(Heap, Stmt-size) -3278 # result->tag = 0/block -3279 # result->name = some unique name -3280 # while true # line loop -3281 # clear-stream(line) -3282 # read-line-buffered(in, line) -3283 # if (line->write == 0) break # end of file -3284 # word-slice = next-mu-token(line) -3285 # if slice-empty?(word-slice) # end of line -3286 # continue -3287 # else if slice-starts-with?(word-slice, "#") -3288 # continue -3289 # else if slice-equal?(word-slice, "{") -3290 # assert(no-tokens-in(line)) -3291 # block = parse-mu-block(in, vars, fn) -3292 # append-to-block(result, block) -3293 # else if slice-equal?(word-slice, "}") -3294 # break -3295 # else if slice-ends-with?(word-slice, ":") -3296 # # TODO: error-check the rest of 'line' -3297 # --word-slice->end to skip ':' -3298 # named-block = parse-mu-named-block(word-slice, in, vars, fn) -3299 # append-to-block(result, named-block) -3300 # else if slice-equal?(word-slice, "var") -3301 # var-def = parse-mu-var-def(line, vars) -3302 # append-to-block(result, var-def) -3303 # else -3304 # stmt = parse-mu-stmt(line, vars, fn) -3305 # append-to-block(result, stmt) -3306 # decrement *Curr-block-depth -3307 # return result -3308 # -3309 # . prologue -3310 55/push-ebp -3311 89/<- %ebp 4/r32/esp -3312 # . save registers -3313 51/push-ecx -3314 52/push-edx -3315 53/push-ebx -3316 57/push-edi -3317 # var line/ecx: (stream byte 512) -3318 81 5/subop/subtract %esp 0x200/imm32 -3319 68/push 0x200/imm32/length -3320 68/push 0/imm32/read -3321 68/push 0/imm32/write -3322 89/<- %ecx 4/r32/esp -3323 # var word-slice/edx: slice -3324 68/push 0/imm32/end -3325 68/push 0/imm32/start -3326 89/<- %edx 4/r32/esp -3327 # edi = result -3328 (allocate Heap *Stmt-size) # => eax -3329 (zero-out %eax *Stmt-size) -3330 89/<- %edi 0/r32/eax -3331 # set result->tag -3332 c7 0/subop/copy *edi 0/imm32/block # Stmt-tag -3333 # set result->var -3334 (new-block-name *(ebp+0x10)) # => eax -3335 89/<- *(edi+8) 0/r32/eax # Block-var -3336 # push result->var to vars -3337 (push *(ebp+0xc) %eax) -3338 # increment *Curr-block-depth -3339 ff 0/subop/increment *Curr-block-depth -3340 { -3341 $parse-mu-block:line-loop: -3342 # line = read-line-buffered(in) -3343 (clear-stream %ecx) -3344 (read-line-buffered *(ebp+8) %ecx) -3345 #? (write-buffered Stderr "line: ") -3346 #? (write-stream-data Stderr %ecx) -3347 #? (write-buffered Stderr Newline) -3348 #? (flush Stderr) -3349 # if (line->write == 0) break -3350 81 7/subop/compare *ecx 0/imm32 -3351 0f 84/jump-if-= break/disp32 -3352 # word-slice = next-mu-token(line) -3353 (next-mu-token %ecx %edx) -3354 #? (write-buffered Stderr "word: ") -3355 #? (write-slice-buffered Stderr %edx) -3356 #? (write-buffered Stderr Newline) -3357 #? (flush Stderr) -3358 # if slice-empty?(word-slice) continue -3359 (slice-empty? %edx) -3360 3d/compare-eax-and 0/imm32/false -3361 0f 85/jump-if-!= loop/disp32 -3362 # if (slice-starts-with?(word-slice, '#') continue -3363 # . eax = *word-slice->start -3364 8b/-> *edx 0/r32/eax -3365 8a/copy-byte *eax 0/r32/AL -3366 81 4/subop/and %eax 0xff/imm32 -3367 # . if (eax == '#') continue -3368 3d/compare-eax-and 0x23/imm32/hash -3369 0f 84/jump-if-= loop/disp32 -3370 # if slice-equal?(word-slice, "{") -3371 { -3372 $parse-mu-block:check-for-block: -3373 (slice-equal? %edx "{") -3374 3d/compare-eax-and 0/imm32/false -3375 74/jump-if-= break/disp8 -3376 (check-no-tokens-left %ecx) -3377 # parse new block and append -3378 (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax -3379 (append-to-block Heap %edi %eax) -3380 e9/jump $parse-mu-block:line-loop/disp32 -3381 } -3382 # if slice-equal?(word-slice, "}") break -3383 $parse-mu-block:check-for-end: -3384 (slice-equal? %edx "}") -3385 3d/compare-eax-and 0/imm32/false -3386 0f 85/jump-if-!= break/disp32 -3387 # if slice-ends-with?(word-slice, ":") parse named block and append -3388 { -3389 $parse-mu-block:check-for-named-block: -3390 # . eax = *(word-slice->end-1) -3391 8b/-> *(edx+4) 0/r32/eax -3392 48/decrement-eax -3393 8a/copy-byte *eax 0/r32/AL -3394 81 4/subop/and %eax 0xff/imm32 -3395 # . if (eax != ':') break -3396 3d/compare-eax-and 0x3a/imm32/colon -3397 0f 85/jump-if-!= break/disp32 -3398 # TODO: error-check the rest of 'line' -3399 # -3400 # skip ':' -3401 ff 1/subop/decrement *(edx+4) # Slice-end -3402 # -3403 (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax -3404 (append-to-block Heap %edi %eax) -3405 e9/jump $parse-mu-block:line-loop/disp32 -3406 } -3407 # if slice-equal?(word-slice, "var") -3408 { -3409 $parse-mu-block:check-for-var: -3410 (slice-equal? %edx "var") -3411 3d/compare-eax-and 0/imm32/false -3412 74/jump-if-= break/disp8 -3413 # -3414 (parse-mu-var-def %ecx *(ebp+0xc)) # => eax -3415 (append-to-block Heap %edi %eax) -3416 e9/jump $parse-mu-block:line-loop/disp32 -3417 } -3418 $parse-mu-block:regular-stmt: -3419 # otherwise -3420 (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10)) # => eax -3421 (append-to-block Heap %edi %eax) -3422 e9/jump loop/disp32 -3423 } # end line loop -3424 # decrement *Curr-block-depth -3425 ff 1/subop/decrement *Curr-block-depth -3426 # -3427 (pop *(ebp+0xc)) # => eax -3428 # return result -3429 89/<- %eax 7/r32/edi -3430 $parse-mu-block:end: -3431 # . reclaim locals -3432 81 0/subop/add %esp 0x214/imm32 -3433 # . restore registers -3434 5f/pop-to-edi -3435 5b/pop-to-ebx -3436 5a/pop-to-edx -3437 59/pop-to-ecx -3438 # . epilogue -3439 89/<- %esp 5/r32/ebp -3440 5d/pop-to-ebp -3441 c3/return -3442 -3443 $parse-mu-block:abort: -3444 # error("'{' or '}' should be on its own line, but got '") -3445 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") -3446 (rewind-stream %ecx) -3447 (write-stream 2 %ecx) -3448 (write-buffered Stderr "'\n") -3449 (flush Stderr) -3450 # . syscall(exit, 1) -3451 bb/copy-to-ebx 1/imm32 -3452 b8/copy-to-eax 1/imm32/exit -3453 cd/syscall 0x80/imm8 -3454 # never gets here -3455 -3456 new-block-name: # fn: (handle function) -> result/eax: (handle var) -3457 # . prologue -3458 55/push-ebp -3459 89/<- %ebp 4/r32/esp -3460 # . save registers -3461 51/push-ecx -3462 52/push-edx -3463 # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:' -3464 8b/-> *(ebp+8) 0/r32/eax -3465 8b/-> *eax 0/r32/eax # Function-name -3466 8b/-> *eax 0/r32/eax # String-length -3467 05/add-to-eax 0xd/imm32 # 10 + 2 for '$:' -3468 89/<- %ecx 0/r32/eax -3469 # var name/edx: (stream byte n) -3470 29/subtract %esp 1/r32/ecx -3471 ff 6/subop/push %ecx -3472 68/push 0/imm32/read -3473 68/push 0/imm32/write -3474 89/<- %edx 4/r32/esp -3475 (clear-stream %edx) -3476 # eax = fn->name -3477 8b/-> *(ebp+8) 0/r32/eax -3478 8b/-> *eax 0/r32/eax # Function-name -3479 # construct result using Next-block-index (and increment it) -3480 (write %edx "$") -3481 (write %edx %eax) -3482 (write %edx ":") -3483 (print-int32 %edx *Next-block-index) -3484 ff 0/subop/increment *Next-block-index -3485 # var s/eax: slice = {name->data, name->data + name->write} (clobbering edx) -3486 # . eax = name->write -3487 8b/-> *edx 0/r32/eax -3488 # . edx = name->data -3489 8d/copy-address *(edx+0xc) 2/r32/edx -3490 # . eax = name->write + name->data -3491 01/add %eax 2/r32/edx -3492 # . push {edx, eax} -3493 ff 6/subop/push %eax -3494 ff 6/subop/push %edx -3495 89/<- %eax 4/r32/esp -3496 # var final-name/edx: (addr array byte) = slice-to-string(s) -3497 (slice-to-string Heap %eax) # => eax -3498 89/<- %edx 0/r32/eax -3499 # set result->var -3500 # . var type/eax: (handle tree type-id) = literal -3501 (allocate Heap *Tree-size) # => eax -3502 (zero-out %eax *Tree-size) # default type is 'literal' -3503 # . var result/eax: (handle var) = new-var(final-name, type) -3504 (new-var Heap %edx %eax *Curr-block-depth 0 0) # => eax -3505 $new-block-name:end: -3506 # . reclaim locals -3507 81 0/subop/add %ecx 0xc/imm32 # name.{read/write/len} -3508 81 0/subop/add %ecx 8/imm32 # slice -3509 01/add %esp 1/r32/ecx -3510 # . restore registers -3511 5a/pop-to-edx -3512 59/pop-to-ecx -3513 # . epilogue -3514 89/<- %esp 5/r32/ebp -3515 5d/pop-to-ebp -3516 c3/return -3517 -3518 check-no-tokens-left: # line: (addr stream byte) -3519 # . prologue -3520 55/push-ebp -3521 89/<- %ebp 4/r32/esp -3522 # . save registers -3523 50/push-eax -3524 51/push-ecx -3525 # var s/ecx: slice -3526 68/push 0/imm32/end -3527 68/push 0/imm32/start -3528 89/<- %ecx 4/r32/esp -3529 # -3530 (next-mu-token *(ebp+8) %ecx) -3531 # if slice-empty?(s) return -3532 (slice-empty? %ecx) -3533 3d/compare-eax-and 0/imm32/false -3534 75/jump-if-!= $check-no-tokens-left:end/disp8 -3535 # if (slice-starts-with?(s, '#') return -3536 # . eax = *s->start -3537 8b/-> *edx 0/r32/eax -3538 8a/copy-byte *eax 0/r32/AL -3539 81 4/subop/and %eax 0xff/imm32 -3540 # . if (eax == '#') continue -3541 3d/compare-eax-and 0x23/imm32/hash -3542 74/jump-if-= $check-no-tokens-left:end/disp8 -3543 # abort -3544 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") -3545 (rewind-stream %ecx) -3546 (write-stream 2 %ecx) -3547 (write-buffered Stderr "'\n") -3548 (flush Stderr) -3549 # . syscall(exit, 1) -3550 bb/copy-to-ebx 1/imm32 -3551 b8/copy-to-eax 1/imm32/exit -3552 cd/syscall 0x80/imm8 -3553 # never gets here -3554 $check-no-tokens-left:end: -3555 # . reclaim locals -3556 81 0/subop/add %esp 8/imm32 -3557 # . restore registers -3558 59/pop-to-ecx -3559 58/pop-to-eax -3560 # . epilogue -3561 89/<- %esp 5/r32/ebp -3562 5d/pop-to-ebp -3563 c3/return -3564 -3565 parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) -3566 # pseudocode: -3567 # var s: (addr array byte) = slice-to-string(name) -3568 # var v: (handle var) = new-var(s, 0) -3569 # v->block-depth = *Curr-block-depth # containing block depth -3570 # push(vars, v) -3571 # result = parse-mu-block(in, vars, fn) -3572 # pop(vars) -3573 # result->name = s -3574 # return result -3575 # -3576 # . prologue -3577 55/push-ebp -3578 89/<- %ebp 4/r32/esp -3579 # . save registers +1743 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0") +1744 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1") +1745 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2") +1746 (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") +1747 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4") +1748 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5") +1749 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6") +1750 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7") +1751 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8") +1752 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9") +1753 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10") +1754 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11") +1755 (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") +1756 (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") +1757 (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") +1758 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15") +1759 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16") +1760 (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") +1761 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18") +1762 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19") +1763 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20") +1764 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21") +1765 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22") +1766 (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") +1767 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24") +1768 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25") +1769 # . epilogue +1770 89/<- %esp 5/r32/ebp +1771 5d/pop-to-ebp +1772 c3/return +1773 +1774 test-convert-length-of-array: +1775 # . prologue +1776 55/push-ebp +1777 89/<- %ebp 4/r32/esp +1778 # setup +1779 (clear-stream _test-input-stream) +1780 (clear-stream $_test-input-buffered-file->buffer) +1781 (clear-stream _test-output-stream) +1782 (clear-stream $_test-output-buffered-file->buffer) +1783 c7 0/subop/copy *Next-block-index 1/imm32 +1784 # +1785 (write _test-input-stream "fn foo a: (addr array int) {\n") +1786 (write _test-input-stream " var b/eax: (addr array int) <- copy a\n") +1787 (write _test-input-stream " var c/eax: int <- length b\n") +1788 (write _test-input-stream "}\n") +1789 # convert +1790 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1791 (flush _test-output-buffered-file) +1792 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1798 # check output +1799 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array/0") +1800 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array/1") +1801 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array/2") +1802 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array/3") +1803 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array/4") +1804 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array/5") +1805 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/6") +1806 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-length-of-array/7") +1807 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/8") +1808 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *eax 0x00000000/r32" "F - test-convert-length-of-array/9") +1809 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/10") +1810 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/11") +1811 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array/12") +1812 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array/13") +1813 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array/14") +1814 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array/15") +1815 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array/16") +1816 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array/17") +1817 # . epilogue +1818 89/<- %esp 5/r32/ebp +1819 5d/pop-to-ebp +1820 c3/return +1821 +1822 ####################################################### +1823 # Parsing +1824 ####################################################### +1825 +1826 parse-mu: # in: (addr buffered-file) +1827 # pseudocode +1828 # var curr-function: (addr (handle function)) = Program +1829 # var line: (stream byte 512) +1830 # var word-slice: slice +1831 # while true # line loop +1832 # clear-stream(line) +1833 # read-line-buffered(in, line) +1834 # if (line->write == 0) break # end of file +1835 # word-slice = next-mu-token(line) +1836 # if slice-empty?(word-slice) # end of line +1837 # continue +1838 # else if slice-starts-with?(word-slice, "#") # comment +1839 # continue # end of line +1840 # else if slice-equal(word-slice, "fn") +1841 # var new-function: (handle function) = allocate(function) +1842 # var vars: (stack (addr var) 256) +1843 # populate-mu-function-header(in, new-function, vars) +1844 # populate-mu-function-body(in, new-function, vars) +1845 # assert(vars->top == 0) +1846 # *curr-function = new-function +1847 # curr-function = &new-function->next +1848 # else +1849 # abort() +1850 # +1851 # . prologue +1852 55/push-ebp +1853 89/<- %ebp 4/r32/esp +1854 # . save registers +1855 50/push-eax +1856 51/push-ecx +1857 52/push-edx +1858 53/push-ebx +1859 57/push-edi +1860 # var line/ecx: (stream byte 512) +1861 81 5/subop/subtract %esp 0x200/imm32 +1862 68/push 0x200/imm32/length +1863 68/push 0/imm32/read +1864 68/push 0/imm32/write +1865 89/<- %ecx 4/r32/esp +1866 # var word-slice/edx: slice +1867 68/push 0/imm32/end +1868 68/push 0/imm32/start +1869 89/<- %edx 4/r32/esp +1870 # var curr-function/edi: (addr (handle function)) = Program +1871 bf/copy-to-edi Program/imm32 +1872 # var vars/ebx: (stack (addr var) 256) +1873 81 5/subop/subtract %esp 0x400/imm32 +1874 68/push 0x400/imm32/length +1875 68/push 0/imm32/top +1876 89/<- %ebx 4/r32/esp +1877 { +1878 $parse-mu:line-loop: +1879 (clear-stream %ecx) +1880 (read-line-buffered *(ebp+8) %ecx) +1881 # if (line->write == 0) break +1882 81 7/subop/compare *ecx 0/imm32 +1883 0f 84/jump-if-= break/disp32 +1884 +-- 6 lines: #? # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------ +1890 (next-mu-token %ecx %edx) +1891 # if slice-empty?(word-slice) continue +1892 (slice-empty? %edx) +1893 3d/compare-eax-and 0/imm32/false +1894 0f 85/jump-if-!= loop/disp32 +1895 # if (*word-slice->start == "#") continue +1896 # . eax = *word-slice->start +1897 8b/-> *edx 0/r32/eax +1898 8a/copy-byte *eax 0/r32/AL +1899 81 4/subop/and %eax 0xff/imm32 +1900 # . if (eax == '#') continue +1901 3d/compare-eax-and 0x23/imm32/hash +1902 0f 84/jump-if-= loop/disp32 +1903 # if (slice-equal?(word-slice, "fn")) parse a function +1904 { +1905 $parse-mu:fn: +1906 (slice-equal? %edx "fn") +1907 3d/compare-eax-and 0/imm32/false +1908 0f 84/jump-if-= break/disp32 +1909 # var new-function/eax: (handle function) = populate-mu-function(in, new-function, vars) +1910 (allocate Heap *Function-size) # => eax +1911 (zero-out %eax *Function-size) +1912 (clear-stack %ebx) +1913 (populate-mu-function-header %ecx %eax %ebx) +1914 (populate-mu-function-body *(ebp+8) %eax %ebx) +1915 # *curr-function = new-function +1916 89/<- *edi 0/r32/eax +1917 # curr-function = &new-function->next +1918 8d/address-> *(eax+0x14) 7/r32/edi # Function-next +1919 e9/jump $parse-mu:line-loop/disp32 +1920 } +1921 # otherwise abort +1922 e9/jump $parse-mu:error1/disp32 +1923 } # end line loop +1924 $parse-mu:end: +1925 # . reclaim locals +1926 81 0/subop/add %esp 0x630/imm32 +1927 # . restore registers +1928 5f/pop-to-edi +1929 5b/pop-to-ebx +1930 5a/pop-to-edx +1931 59/pop-to-ecx +1932 58/pop-to-eax +1933 # . epilogue +1934 89/<- %esp 5/r32/ebp +1935 5d/pop-to-ebp +1936 c3/return +1937 +1938 $parse-mu:error1: +1939 # error("unexpected top-level command: " word-slice "\n") +1940 (write-buffered Stderr "unexpected top-level command: ") +1941 (write-slice-buffered Stderr %edx) +1942 (write-buffered Stderr "\n") +1943 (flush Stderr) +1944 # . syscall(exit, 1) +1945 bb/copy-to-ebx 1/imm32 +1946 b8/copy-to-eax 1/imm32/exit +1947 cd/syscall 0x80/imm8 +1948 # never gets here +1949 +1950 $parse-mu:error2: +1951 # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n") +1952 (print-int32-buffered Stderr *ebx) +1953 (write-buffered Stderr " vars not reclaimed after fn '") +1954 (write-slice-buffered Stderr *eax) # Function-name +1955 (write-buffered Stderr "'\n") +1956 (flush Stderr) +1957 # . syscall(exit, 1) +1958 bb/copy-to-ebx 1/imm32 +1959 b8/copy-to-eax 1/imm32/exit +1960 cd/syscall 0x80/imm8 +1961 # never gets here +1962 +1963 # scenarios considered: +1964 # ✗ fn foo # no block +1965 # ✓ fn foo { +1966 # ✗ fn foo { { +1967 # ✗ fn foo { } +1968 # ✗ fn foo { } { +1969 # ✗ fn foo x { +1970 # ✗ fn foo x: { +1971 # ✓ fn foo x: int { +1972 # ✓ fn foo x: int { +1973 # ✓ fn foo x: int -> y/eax: int { +1974 populate-mu-function-header: # first-line: (addr stream byte), out: (handle function), vars: (addr stack (handle var)) +1975 # pseudocode: +1976 # var name: slice +1977 # next-mu-token(first-line, name) +1978 # assert(name not in '{' '}' '->') +1979 # out->name = slice-to-string(name) +1980 # var next-offset: int = 8 +1981 # ## inouts +1982 # while true +1983 # ## name +1984 # name = next-mu-token(first-line) +1985 # if (name == '{') goto done +1986 # if (name == '->') break +1987 # assert(name != '}') +1988 # var v: (handle var) = parse-var-with-type(name, first-line) +1989 # assert(v->register == null) +1990 # v->stack-offset = next-offset +1991 # next-offset += size-of(v) +1992 # # v->block-depth is implicitly 0 +1993 # out->inouts = append(out->inouts, v) +1994 # push(vars, v) +1995 # ## outputs +1996 # while true +1997 # ## name +1998 # name = next-mu-token(first-line) +1999 # assert(name not in '{' '}' '->') +2000 # var v: (handle var) = parse-var-with-type(name, first-line) +2001 # assert(v->register != null) +2002 # out->outputs = append(out->outputs, v) +2003 # done: +2004 # +2005 # . prologue +2006 55/push-ebp +2007 89/<- %ebp 4/r32/esp +2008 # . save registers +2009 50/push-eax +2010 51/push-ecx +2011 52/push-edx +2012 53/push-ebx +2013 57/push-edi +2014 # edi = out +2015 8b/-> *(ebp+0xc) 7/r32/edi +2016 # var word-slice/ecx: slice +2017 68/push 0/imm32/end +2018 68/push 0/imm32/start +2019 89/<- %ecx 4/r32/esp +2020 # var next-offset/edx = 8 +2021 ba/copy-to-edx 8/imm32 +2022 # read function name +2023 (next-mu-token *(ebp+8) %ecx) +2024 # error checking +2025 # TODO: error if name starts with 'break' or 'loop' +2026 # if (word-slice == '{') abort +2027 (slice-equal? %ecx "{") # => eax +2028 3d/compare-eax-and 0/imm32/false +2029 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +2030 # if (word-slice == '->') abort +2031 (slice-equal? %ecx "->") # => eax +2032 3d/compare-eax-and 0/imm32/false +2033 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +2034 # if (word-slice == '}') abort +2035 (slice-equal? %ecx "}") # => eax +2036 3d/compare-eax-and 0/imm32/false +2037 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +2038 # save function name +2039 (slice-to-string Heap %ecx) # => eax +2040 89/<- *edi 0/r32/eax # Function-name +2041 # initialize default subx-name as well +2042 89/<- *(edi+4) 0/r32/eax # Function-subx-name +2043 # save function inouts +2044 { +2045 $populate-mu-function-header:check-for-inout: +2046 (next-mu-token *(ebp+8) %ecx) +2047 # if (word-slice == '{') goto done +2048 (slice-equal? %ecx "{") # => eax +2049 3d/compare-eax-and 0/imm32/false +2050 0f 85/jump-if-!= $populate-mu-function-header:done/disp32 +2051 # if (word-slice == '->') break +2052 (slice-equal? %ecx "->") # => eax +2053 3d/compare-eax-and 0/imm32/false +2054 0f 85/jump-if-!= break/disp32 +2055 # if (word-slice == '}') abort +2056 (slice-equal? %ecx "}") # => eax +2057 3d/compare-eax-and 0/imm32/false +2058 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +2059 # var v/ebx: (handle var) = parse-var-with-type(word-slice, first-line) +2060 (parse-var-with-type %ecx *(ebp+8)) # => eax +2061 89/<- %ebx 0/r32/eax +2062 # assert(v->register == null) +2063 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register +2064 0f 85/jump-if-!= $populate-mu-function-header:error2/disp32 +2065 # v->stack-offset = next-offset +2066 89/<- *(ebx+0xc) 2/r32/edx # Var-stack-offset +2067 # next-offset += size-of(v) +2068 (size-of %ebx) # => eax +2069 01/add %edx 0/r32/eax +2070 # v->block-depth is implicitly 0 +2071 # +2072 (append-list Heap %ebx *(edi+8)) # Function-inouts => eax +2073 89/<- *(edi+8) 0/r32/eax # Function-inouts +2074 (push *(ebp+0x10) %ebx) +2075 # +2076 e9/jump loop/disp32 +2077 } +2078 # save function outputs +2079 { +2080 $populate-mu-function-header:check-for-out: +2081 (next-mu-token *(ebp+8) %ecx) +2082 # if (word-slice == '{') break +2083 (slice-equal? %ecx "{") # => eax +2084 3d/compare-eax-and 0/imm32/false +2085 0f 85/jump-if-!= break/disp32 +2086 # if (word-slice == '->') abort +2087 (slice-equal? %ecx "->") # => eax +2088 3d/compare-eax-and 0/imm32/false +2089 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +2090 # if (word-slice == '}') abort +2091 (slice-equal? %ecx "}") # => eax +2092 3d/compare-eax-and 0/imm32/false +2093 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +2094 # +2095 (parse-var-with-type %ecx *(ebp+8)) # => eax +2096 89/<- %ebx 0/r32/eax +2097 # assert(var->register != null) +2098 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register +2099 0f 84/jump-if-= $populate-mu-function-header:error3/disp32 +2100 (append-list Heap %ebx *(edi+0xc)) # Function-outputs => eax +2101 89/<- *(edi+0xc) 0/r32/eax # Function-outputs +2102 e9/jump loop/disp32 +2103 } +2104 $populate-mu-function-header:done: +2105 (check-no-tokens-left *(ebp+8)) +2106 $populate-mu-function-header:end: +2107 # . reclaim locals +2108 81 0/subop/add %esp 8/imm32 +2109 # . restore registers +2110 5f/pop-to-edi +2111 5b/pop-to-ebx +2112 5a/pop-to-edx +2113 59/pop-to-ecx +2114 58/pop-to-eax +2115 # . epilogue +2116 89/<- %esp 5/r32/ebp +2117 5d/pop-to-ebp +2118 c3/return +2119 +2120 $populate-mu-function-header:error1: +2121 # error("function header not in form 'fn <name> {'") +2122 (write-buffered Stderr "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '") +2123 (flush Stderr) +2124 (rewind-stream *(ebp+8)) +2125 (write-stream 2 *(ebp+8)) +2126 (write-buffered Stderr "'\n") +2127 (flush Stderr) +2128 # . syscall(exit, 1) +2129 bb/copy-to-ebx 1/imm32 +2130 b8/copy-to-eax 1/imm32/exit +2131 cd/syscall 0x80/imm8 +2132 # never gets here +2133 +2134 $populate-mu-function-header:error2: +2135 # error("function input '" var "' cannot be in a register") +2136 (write-buffered Stderr "function input '") +2137 (write-buffered Stderr *ebx) # Var-name +2138 (write-buffered Stderr "' cannot be in a register") +2139 (flush Stderr) +2140 # . syscall(exit, 1) +2141 bb/copy-to-ebx 1/imm32 +2142 b8/copy-to-eax 1/imm32/exit +2143 cd/syscall 0x80/imm8 +2144 # never gets here +2145 +2146 $populate-mu-function-header:error3: +2147 # error("function input '" var "' must be in a register") +2148 (write-buffered Stderr "function input '") +2149 (write-buffered Stderr *eax) # Var-name +2150 (write-buffered Stderr " must be in a register'") +2151 (flush Stderr) +2152 (rewind-stream *(ebp+8)) +2153 (write-stream 2 *(ebp+8)) +2154 (write-buffered Stderr "'\n") +2155 (flush Stderr) +2156 # . syscall(exit, 1) +2157 bb/copy-to-ebx 1/imm32 +2158 b8/copy-to-eax 1/imm32/exit +2159 cd/syscall 0x80/imm8 +2160 # never gets here +2161 +2162 test-function-header-with-arg: +2163 # . prologue +2164 55/push-ebp +2165 89/<- %ebp 4/r32/esp +2166 # setup +2167 (clear-stream _test-input-stream) +2168 (write _test-input-stream "foo n: int {\n") +2169 # var result/ecx: function +2170 2b/subtract-> *Function-size 4/r32/esp +2171 89/<- %ecx 4/r32/esp +2172 (zero-out %ecx *Function-size) +2173 # var vars/ebx: (stack (addr var) 16) +2174 81 5/subop/subtract %esp 0x10/imm32 +2175 68/push 0x10/imm32/length +2176 68/push 0/imm32/top +2177 89/<- %ebx 4/r32/esp +2178 # convert +2179 (populate-mu-function-header _test-input-stream %ecx %ebx) +2180 # check result +2181 (check-strings-equal *ecx "foo" "F - test-function-header-with-arg/name") # Function-name +2182 # edx: (handle list var) = result->inouts +2183 8b/-> *(ecx+8) 2/r32/edx # Function-inouts +2184 # ebx: (handle var) = result->inouts->value +2185 8b/-> *edx 3/r32/ebx # List-value +2186 (check-strings-equal *ebx "n" "F - test-function-header-with-arg/inout:0") # Var-name +2187 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2188 (check-ints-equal *ebx 1 "F - test-function-header-with-arg/inout:0/type:0") # Tree-left +2189 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-arg/inout:0/type:1") # Tree-right +2190 # . epilogue +2191 89/<- %esp 5/r32/ebp +2192 5d/pop-to-ebp +2193 c3/return +2194 +2195 test-function-header-with-multiple-args: +2196 # . prologue +2197 55/push-ebp +2198 89/<- %ebp 4/r32/esp +2199 # setup +2200 (clear-stream _test-input-stream) +2201 (write _test-input-stream "foo a: int, b: int c: int {\n") +2202 # result/ecx: (handle function) +2203 2b/subtract-> *Function-size 4/r32/esp +2204 89/<- %ecx 4/r32/esp +2205 (zero-out %ecx *Function-size) +2206 # var vars/ebx: (stack (addr var) 16) +2207 81 5/subop/subtract %esp 0x10/imm32 +2208 68/push 0x10/imm32/length +2209 68/push 0/imm32/top +2210 89/<- %ebx 4/r32/esp +2211 # convert +2212 (populate-mu-function-header _test-input-stream %ecx %ebx) +2213 # check result +2214 (check-strings-equal *ecx "foo") # Function-name +2215 # edx: (handle list var) = result->inouts +2216 8b/-> *(ecx+8) 2/r32/edx # Function-inouts +2217 $test-function-header-with-multiple-args:inout0: +2218 # ebx: (handle var) = result->inouts->value +2219 8b/-> *edx 3/r32/ebx # List-value +2220 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name +2221 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2222 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:0/type:0") # Tree-left +2223 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:0/type:1") # Tree-right +2224 # edx = result->inouts->next +2225 8b/-> *(edx+4) 2/r32/edx # List-next +2226 $test-function-header-with-multiple-args:inout1: +2227 # ebx = result->inouts->next->value +2228 8b/-> *edx 3/r32/ebx # List-value +2229 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args/inout:1") # Var-name +2230 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2231 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:1/type:0") # Tree-left +2232 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:1/type:1") # Tree-right +2233 # edx = result->inouts->next->next +2234 8b/-> *(edx+4) 2/r32/edx # List-next +2235 $test-function-header-with-multiple-args:inout2: +2236 # ebx = result->inouts->next->next->value +2237 8b/-> *edx 3/r32/ebx # List-value +2238 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args/inout:2") # Var-name +2239 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2240 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:2/type:0") # Tree-left +2241 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:2/type:1") # Tree-right +2242 # . epilogue +2243 89/<- %esp 5/r32/ebp +2244 5d/pop-to-ebp +2245 c3/return +2246 +2247 test-function-with-multiple-args-and-outputs: +2248 # . prologue +2249 55/push-ebp +2250 89/<- %ebp 4/r32/esp +2251 # setup +2252 (clear-stream _test-input-stream) +2253 (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx: int {\n") +2254 # result/ecx: (handle function) +2255 2b/subtract-> *Function-size 4/r32/esp +2256 89/<- %ecx 4/r32/esp +2257 (zero-out %ecx *Function-size) +2258 # var vars/ebx: (stack (addr var) 16) +2259 81 5/subop/subtract %esp 0x10/imm32 +2260 68/push 0x10/imm32/length +2261 68/push 0/imm32/top +2262 89/<- %ebx 4/r32/esp +2263 # convert +2264 (populate-mu-function-header _test-input-stream %ecx %ebx) +2265 # check result +2266 (check-strings-equal *ecx "foo") # Function-name +2267 # edx: (handle list var) = result->inouts +2268 8b/-> *(ecx+8) 2/r32/edx # Function-inouts +2269 # ebx: (handle var) = result->inouts->value +2270 8b/-> *edx 3/r32/ebx # List-value +2271 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0") # Var-name +2272 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2273 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0") # Tree-left +2274 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1") # Tree-right +2275 # edx = result->inouts->next +2276 8b/-> *(edx+4) 2/r32/edx # List-next +2277 # ebx = result->inouts->next->value +2278 8b/-> *edx 3/r32/ebx # List-value +2279 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1") # Var-name +2280 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2281 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0") # Tree-left +2282 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1") # Tree-right +2283 # edx = result->inouts->next->next +2284 8b/-> *(edx+4) 2/r32/edx # List-next +2285 # ebx = result->inouts->next->next->value +2286 8b/-> *edx 3/r32/ebx # List-value +2287 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2") # Var-name +2288 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2289 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0") # Tree-left +2290 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1") # Tree-right +2291 # edx: (handle list var) = result->outputs +2292 8b/-> *(ecx+0xc) 2/r32/edx # Function-outputs +2293 # ebx: (handle var) = result->outputs->value +2294 8b/-> *edx 3/r32/ebx # List-value +2295 (check-strings-equal *ebx "x" "F - test-function-header-with-multiple-args-and-outputs/output:0") # Var-name +2296 (check-strings-equal *(ebx+0x10) "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register +2297 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2298 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-left +2299 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-right +2300 # edx = result->outputs->next +2301 8b/-> *(edx+4) 2/r32/edx # List-next +2302 # ebx = result->outputs->next->value +2303 8b/-> *edx 3/r32/ebx # List-value +2304 (check-strings-equal *ebx "y" "F - test-function-header-with-multiple-args-and-outputs/output:1") # Var-name +2305 (check-strings-equal *(ebx+0x10) "edx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register +2306 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2307 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-left +2308 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-right +2309 # . epilogue +2310 89/<- %esp 5/r32/ebp +2311 5d/pop-to-ebp +2312 c3/return +2313 +2314 # format for variables with types +2315 # x: int +2316 # x: int, +2317 # x/eax: int +2318 # x/eax: int, +2319 # ignores at most one trailing comma +2320 # WARNING: modifies name +2321 parse-var-with-type: # name: (addr slice), first-line: (addr stream byte) -> result/eax: (handle var) +2322 # pseudocode: +2323 # var v: (handle var) = allocate(Heap, Var-size) +2324 # var s: slice +2325 # if (!slice-ends-with(name, ":")) +2326 # abort +2327 # --name->end to skip ':' +2328 # next-token-from-slice(name->start, name->end, '/', s) +2329 # v->name = slice-to-string(s) +2330 # ## register +2331 # next-token-from-slice(s->end, name->end, '/', s) +2332 # if (!slice-empty?(s)) +2333 # v->register = slice-to-string(s) +2334 # ## type +2335 # var type: (handle tree type-id) = parse-type(first-line) +2336 # v->type = type +2337 # return v +2338 # +2339 # . prologue +2340 55/push-ebp +2341 89/<- %ebp 4/r32/esp +2342 # . save registers +2343 51/push-ecx +2344 52/push-edx +2345 53/push-ebx +2346 56/push-esi +2347 57/push-edi +2348 # esi = name +2349 8b/-> *(ebp+8) 6/r32/esi +2350 # if (!slice-ends-with?(name, ":")) abort +2351 8b/-> *(esi+4) 1/r32/ecx # Slice-end +2352 49/decrement-ecx +2353 8a/copy-byte *ecx 1/r32/CL +2354 81 4/subop/and %ecx 0xff/imm32 +2355 81 7/subop/compare %ecx 0x3a/imm32/colon +2356 0f 85/jump-if-!= $parse-var-with-type:abort/disp32 +2357 # --name->end to skip ':' +2358 ff 1/subop/decrement *(esi+4) +2359 # var result/edi: (handle var) = allocate(Heap, Var-size) +2360 (allocate Heap *Var-size) # => eax +2361 (zero-out %eax *Var-size) +2362 89/<- %edi 0/r32/eax +2363 # var s/ecx: slice +2364 68/push 0/imm32/end +2365 68/push 0/imm32/start +2366 89/<- %ecx 4/r32/esp +2367 $parse-var-with-type:save-name: +2368 # save v->name +2369 (next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/' +2370 # . end/edx = s->end +2371 8b/-> *(ecx+4) 2/r32/edx +2372 $parse-var-with-type:write-name: +2373 (slice-to-string Heap %ecx) # => eax +2374 89/<- *edi 0/r32/eax # Var-name +2375 # save v->register +2376 $parse-var-with-type:save-register: +2377 (next-token-from-slice %edx *(esi+4) 0x2f %ecx) # end, name->end, '/' +2378 # if (!slice-empty?(s)) v->register = slice-to-string(s) +2379 { +2380 $parse-var-with-type:write-register: +2381 (slice-empty? %ecx) # => eax +2382 3d/compare-eax-and 0/imm32/false +2383 75/jump-if-!= break/disp8 +2384 (slice-to-string Heap %ecx) +2385 89/<- *(edi+0x10) 0/r32/eax # Var-register +2386 } +2387 $parse-var-with-type:save-type: +2388 (parse-type Heap *(ebp+0xc)) # => eax +2389 89/<- *(edi+4) 0/r32/eax # Var-type +2390 $parse-var-with-type:end: +2391 # return result +2392 89/<- %eax 7/r32/edi +2393 # . reclaim locals +2394 81 0/subop/add %esp 8/imm32 +2395 # . restore registers +2396 5f/pop-to-edi +2397 5e/pop-to-esi +2398 5b/pop-to-ebx +2399 5a/pop-to-edx +2400 59/pop-to-ecx +2401 # . epilogue +2402 89/<- %esp 5/r32/ebp +2403 5d/pop-to-ebp +2404 c3/return +2405 +2406 $parse-var-with-type:abort: +2407 # error("var should have form 'name: type' in '" line "'\n") +2408 (write-buffered Stderr "var should have form 'name: type' in '") +2409 (flush Stderr) +2410 (rewind-stream *(ebp+0xc)) +2411 (write-stream 2 *(ebp+0xc)) +2412 (write-buffered Stderr "'\n") +2413 (flush Stderr) +2414 # . syscall(exit, 1) +2415 bb/copy-to-ebx 1/imm32 +2416 b8/copy-to-eax 1/imm32/exit +2417 cd/syscall 0x80/imm8 +2418 # never gets here +2419 +2420 parse-type: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) +2421 # pseudocode: +2422 # var s: slice = next-mu-token(in) +2423 # assert s != "" +2424 # assert s != "->" +2425 # assert s != "{" +2426 # assert s != "}" +2427 # if s == ")" +2428 # return 0 +2429 # result = allocate(Tree) +2430 # zero-out(result, *Tree-size) +2431 # if s != "(" +2432 # result->left = pos-slice(Type-id, s) +2433 # return +2434 # result->left = parse-type(ad, in) +2435 # result->right = parse-type-tree(ad, in) +2436 # +2437 # . prologue +2438 55/push-ebp +2439 89/<- %ebp 4/r32/esp +2440 # . save registers +2441 51/push-ecx +2442 52/push-edx +2443 # var s/ecx: slice +2444 68/push 0/imm32 +2445 68/push 0/imm32 +2446 89/<- %ecx 4/r32/esp +2447 # s = next-mu-token(in) +2448 (next-mu-token *(ebp+0xc) %ecx) +2449 #? (write-buffered Stderr "tok: ") +2450 #? (write-slice-buffered Stderr %ecx) +2451 #? (write-buffered Stderr "$\n") +2452 #? (flush Stderr) +2453 # assert s != "" +2454 (slice-equal? %ecx "") +2455 3d/compare-eax-and 0/imm32/false +2456 0f 85/jump-if-!= $parse-type:abort/disp32 +2457 # assert s != "{" +2458 (slice-equal? %ecx "{") +2459 3d/compare-eax-and 0/imm32/false +2460 0f 85/jump-if-!= $parse-type:abort/disp32 +2461 # assert s != "}" +2462 (slice-equal? %ecx "}") +2463 3d/compare-eax-and 0/imm32/false +2464 0f 85/jump-if-!= $parse-type:abort/disp32 +2465 # assert s != "->" +2466 (slice-equal? %ecx "->") +2467 3d/compare-eax-and 0/imm32/false +2468 0f 85/jump-if-!= $parse-type:abort/disp32 +2469 # if (s == ")") return 0 +2470 (slice-equal? %ecx ")") +2471 3d/compare-eax-and 0/imm32/false +2472 b8/copy-to-eax 0/imm32 +2473 0f 85/jump-if-!= $parse-type:end/disp32 +2474 # var result/edx: (handle tree type-id) +2475 (allocate *(ebp+8) *Tree-size) # => eax +2476 (zero-out %eax *Tree-size) +2477 89/<- %edx 0/r32/eax +2478 { +2479 # if (s != "(") break +2480 (slice-equal? %ecx "(") +2481 3d/compare-eax-and 0/imm32/false +2482 75/jump-if-!= break/disp8 +2483 # result->left = pos-slice(Type-id, s) +2484 (pos-slice Type-id %ecx) +2485 #? (write-buffered Stderr "=> {") +2486 #? (print-int32-buffered Stderr %eax) +2487 #? (write-buffered Stderr ", 0}\n") +2488 #? (flush Stderr) +2489 89/<- *edx 0/r32/eax # Tree-left +2490 e9/jump $parse-type:return-edx/disp32 +2491 } +2492 # otherwise s == "(" +2493 # result->left = parse-type(ad, in) +2494 (parse-type *(ebp+8) *(ebp+0xc)) +2495 #? (write-buffered Stderr "=> {") +2496 #? (print-int32-buffered Stderr %eax) +2497 89/<- *edx 0/r32/eax # Tree-left +2498 # result->right = parse-type-tree(ad, in) +2499 (parse-type-tree *(ebp+8) *(ebp+0xc)) +2500 #? (write-buffered Stderr Space) +2501 #? (print-int32-buffered Stderr %eax) +2502 #? (write-buffered Stderr "}\n") +2503 #? (flush Stderr) +2504 89/<- *(edx+4) 0/r32/eax # Tree-right +2505 $parse-type:return-edx: +2506 89/<- %eax 2/r32/edx +2507 $parse-type:end: +2508 # . reclaim locals +2509 81 0/subop/add %esp 8/imm32 +2510 # . restore registers +2511 5a/pop-to-edx +2512 59/pop-to-ecx +2513 # . epilogue +2514 89/<- %esp 5/r32/ebp +2515 5d/pop-to-ebp +2516 c3/return +2517 +2518 $parse-type:abort: +2519 # error("unexpected token when parsing type: '" s "'\n") +2520 (write-buffered Stderr "unexpected token when parsing type: '") +2521 (write-slice-buffered Stderr %ecx) +2522 (write-buffered Stderr "'\n") +2523 (flush Stderr) +2524 # . syscall(exit, 1) +2525 bb/copy-to-ebx 1/imm32 +2526 b8/copy-to-eax 1/imm32/exit +2527 cd/syscall 0x80/imm8 +2528 # never gets here +2529 +2530 parse-type-tree: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) +2531 # pseudocode: +2532 # var tmp: (handle tree type-id) = parse-type(ad, in) +2533 # if tmp == 0 +2534 # return 0 +2535 # result = allocate(Tree) +2536 # zero-out(result, *Tree-size) +2537 # result->left = tmp +2538 # result->right = parse-type-tree(ad, in) +2539 # +2540 # . prologue +2541 55/push-ebp +2542 89/<- %ebp 4/r32/esp +2543 # . save registers +2544 51/push-ecx +2545 52/push-edx +2546 # var tmp/eax: (handle tree type-id) = parse-type(ad, in) +2547 (parse-type *(ebp+8) *(ebp+0xc)) +2548 # if (tmp == 0) return tmp +2549 3d/compare-eax-and 0/imm32 +2550 74/jump-if-= $parse-type-tree:end/disp8 +2551 # var tmp2/ecx = tmp +2552 89/<- %ecx 0/r32/eax +2553 # var result/edx: (handle tree type-id) +2554 (allocate *(ebp+8) *Tree-size) # => eax +2555 (zero-out %eax *Tree-size) +2556 89/<- %edx 0/r32/eax +2557 # result->left = tmp2 +2558 89/<- *edx 1/r32/ecx # Tree-left +2559 # result->right = parse-type-tree(ad, in) +2560 (parse-type-tree *(ebp+8) *(ebp+0xc)) +2561 89/<- *(edx+4) 0/r32/eax # Tree-right +2562 $parse-type-tree:return-edx: +2563 89/<- %eax 2/r32/edx +2564 $parse-type-tree:end: +2565 # . restore registers +2566 5a/pop-to-edx +2567 59/pop-to-ecx +2568 # . epilogue +2569 89/<- %esp 5/r32/ebp +2570 5d/pop-to-ebp +2571 c3/return +2572 +2573 next-mu-token: # in: (addr stream byte), out: (addr slice) +2574 # pseudocode: +2575 # start: +2576 # skip-chars-matching-whitespace(in) +2577 # if in->read >= in->write # end of in +2578 # out = {0, 0} +2579 # return +2580 # out->start = &in->data[in->read] +2581 # var curr-byte/eax: byte = in->data[in->read] +2582 # if curr->byte == ',' # comment token +2583 # ++in->read +2584 # goto start +2585 # if curr-byte == '#' # comment +2586 # goto done # treat as eof +2587 # if curr-byte == '"' # string literal +2588 # skip-string(in) +2589 # goto done # no metadata +2590 # if curr-byte == '(' +2591 # ++in->read +2592 # goto done +2593 # if curr-byte == ')' +2594 # ++in->read +2595 # goto done +2596 # # read a word +2597 # while true +2598 # if in->read >= in->write +2599 # break +2600 # curr-byte = in->data[in->read] +2601 # if curr-byte == ' ' +2602 # break +2603 # if curr-byte == '\r' +2604 # break +2605 # if curr-byte == '\n' +2606 # break +2607 # if curr-byte == '(' +2608 # break +2609 # if curr-byte == ')' +2610 # break +2611 # if curr-byte == ',' +2612 # break +2613 # ++in->read +2614 # done: +2615 # out->end = &in->data[in->read] +2616 # +2617 # . prologue +2618 55/push-ebp +2619 89/<- %ebp 4/r32/esp +2620 # . save registers +2621 50/push-eax +2622 51/push-ecx +2623 56/push-esi +2624 57/push-edi +2625 # esi = in +2626 8b/-> *(ebp+8) 6/r32/esi +2627 # edi = out +2628 8b/-> *(ebp+0xc) 7/r32/edi +2629 $next-mu-token:start: +2630 (skip-chars-matching-whitespace %esi) +2631 $next-mu-token:check0: +2632 # if (in->read >= in->write) return out = {0, 0} +2633 # . ecx = in->read +2634 8b/-> *(esi+4) 1/r32/ecx +2635 # . if (ecx >= in->write) return out = {0, 0} +2636 3b/compare 1/r32/ecx *esi +2637 c7 0/subop/copy *edi 0/imm32 +2638 c7 0/subop/copy *(edi+4) 0/imm32 +2639 0f 8d/jump-if->= $next-mu-token:end/disp32 +2640 # out->start = &in->data[in->read] +2641 8d/copy-address *(esi+ecx+0xc) 0/r32/eax +2642 89/<- *edi 0/r32/eax +2643 # var curr-byte/eax: byte = in->data[in->read] +2644 31/xor %eax 0/r32/eax +2645 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL +2646 { +2647 $next-mu-token:check-for-comma: +2648 # if (curr-byte != ',') break +2649 3d/compare-eax-and 0x2c/imm32/comma +2650 75/jump-if-!= break/disp8 +2651 # ++in->read +2652 ff 0/subop/increment *(esi+4) +2653 # restart +2654 e9/jump $next-mu-token:start/disp32 +2655 } +2656 { +2657 $next-mu-token:check-for-comment: +2658 # if (curr-byte != '#') break +2659 3d/compare-eax-and 0x23/imm32/pound +2660 75/jump-if-!= break/disp8 +2661 # return eof +2662 e9/jump $next-mu-token:done/disp32 +2663 } +2664 { +2665 $next-mu-token:check-for-string-literal: +2666 # if (curr-byte != '"') break +2667 3d/compare-eax-and 0x22/imm32/dquote +2668 75/jump-if-!= break/disp8 +2669 (skip-string %esi) +2670 # return +2671 e9/jump $next-mu-token:done/disp32 +2672 } +2673 { +2674 $next-mu-token:check-for-open-paren: +2675 # if (curr-byte != '(') break +2676 3d/compare-eax-and 0x28/imm32/open-paren +2677 75/jump-if-!= break/disp8 +2678 # ++in->read +2679 ff 0/subop/increment *(esi+4) +2680 # return +2681 e9/jump $next-mu-token:done/disp32 +2682 } +2683 { +2684 $next-mu-token:check-for-close-paren: +2685 # if (curr-byte != ')') break +2686 3d/compare-eax-and 0x29/imm32/close-paren +2687 75/jump-if-!= break/disp8 +2688 # ++in->read +2689 ff 0/subop/increment *(esi+4) +2690 # return +2691 e9/jump $next-mu-token:done/disp32 +2692 } +2693 { +2694 $next-mu-token:regular-word-without-metadata: +2695 # if (in->read >= in->write) break +2696 # . ecx = in->read +2697 8b/-> *(esi+4) 1/r32/ecx +2698 # . if (ecx >= in->write) break +2699 3b/compare *esi 1/r32/ecx +2700 7d/jump-if->= break/disp8 +2701 # var c/eax: byte = in->data[in->read] +2702 31/xor %eax 0/r32/eax +2703 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL +2704 # if (c == ' ') break +2705 3d/compare-eax-and 0x20/imm32/space +2706 74/jump-if-= break/disp8 +2707 # if (c == '\r') break +2708 3d/compare-eax-and 0xd/imm32/carriage-return +2709 74/jump-if-= break/disp8 +2710 # if (c == '\n') break +2711 3d/compare-eax-and 0xa/imm32/newline +2712 74/jump-if-= break/disp8 +2713 # if (c == '(') break +2714 3d/compare-eax-and 0x28/imm32/open-paren +2715 0f 84/jump-if-= break/disp32 +2716 # if (c == ')') break +2717 3d/compare-eax-and 0x29/imm32/close-paren +2718 0f 84/jump-if-= break/disp32 +2719 # if (c == ',') break +2720 3d/compare-eax-and 0x2c/imm32/comma +2721 0f 84/jump-if-= break/disp32 +2722 # ++in->read +2723 ff 0/subop/increment *(esi+4) +2724 # +2725 e9/jump loop/disp32 +2726 } +2727 $next-mu-token:done: +2728 # out->end = &in->data[in->read] +2729 8b/-> *(esi+4) 1/r32/ecx +2730 8d/copy-address *(esi+ecx+0xc) 0/r32/eax +2731 89/<- *(edi+4) 0/r32/eax +2732 $next-mu-token:end: +2733 # . restore registers +2734 5f/pop-to-edi +2735 5e/pop-to-esi +2736 59/pop-to-ecx +2737 58/pop-to-eax +2738 # . epilogue +2739 89/<- %esp 5/r32/ebp +2740 5d/pop-to-ebp +2741 c3/return +2742 +2743 # return the index in an array of strings matching 's' +2744 # index is denominated in elements, not bytes +2745 pos-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int +2746 # . prologue +2747 55/push-ebp +2748 89/<- %ebp 4/r32/esp +2749 # . save registers +2750 51/push-ecx +2751 52/push-edx +2752 53/push-ebx +2753 56/push-esi +2754 #? (write-buffered Stderr "pos-slice: ") +2755 #? (write-slice-buffered Stderr *(ebp+0xc)) +2756 #? (write-buffered Stderr "\n") +2757 #? (flush Stderr) +2758 # esi = arr +2759 8b/-> *(ebp+8) 6/r32/esi +2760 # var index/ecx: int = 0 +2761 b9/copy-to-ecx 0/imm32 +2762 # var curr/edx: (addr (addr array byte)) = arr->data +2763 8d/copy-address *(esi+0xc) 2/r32/edx +2764 # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write] +2765 8b/-> *esi 3/r32/ebx +2766 8d/copy-address *(esi+ebx+0xc) 3/r32/ebx +2767 { +2768 #? (write-buffered Stderr " ") +2769 #? (print-int32-buffered Stderr %ecx) +2770 #? (write-buffered Stderr "\n") +2771 #? (flush Stderr) +2772 # if (curr >= max) return -1 +2773 39/compare %edx 3/r32/ebx +2774 b8/copy-to-eax -1/imm32 +2775 73/jump-if-addr>= $pos-slice:end/disp8 +2776 # if (slice-equal?(s, *curr)) break +2777 (slice-equal? *(ebp+0xc) *edx) # => eax +2778 3d/compare-eax-and 0/imm32/false +2779 75/jump-if-!= break/disp8 +2780 # ++index +2781 41/increment-ecx +2782 # curr += 4 +2783 81 0/subop/add %edx 4/imm32 +2784 # +2785 eb/jump loop/disp8 +2786 } +2787 # return index +2788 89/<- %eax 1/r32/ecx +2789 $pos-slice:end: +2790 #? (write-buffered Stderr "=> ") +2791 #? (print-int32-buffered Stderr %eax) +2792 #? (write-buffered Stderr "\n") +2793 # . restore registers +2794 5e/pop-to-esi +2795 5b/pop-to-ebx +2796 5a/pop-to-edx +2797 59/pop-to-ecx +2798 # . epilogue +2799 89/<- %esp 5/r32/ebp +2800 5d/pop-to-ebp +2801 c3/return +2802 +2803 == data +2804 +2805 Type-id: # (stream (address array byte)) +2806 0x18/imm32/write +2807 0/imm32/read +2808 0x100/imm32/length +2809 # data +2810 "literal"/imm32 # 0 +2811 "int"/imm32 # 1 +2812 "addr"/imm32 # 2 +2813 "array"/imm32 # 3 +2814 "handle"/imm32 # 4 +2815 "bool"/imm32 # 5 +2816 0/imm32 +2817 0/imm32 +2818 # 0x20 +2819 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2820 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2821 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2822 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2823 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2824 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2825 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2826 +2827 == code +2828 +2829 test-parse-var-with-type: +2830 # . prologue +2831 55/push-ebp +2832 89/<- %ebp 4/r32/esp +2833 # (eax..ecx) = "x:" +2834 b8/copy-to-eax "x:"/imm32 +2835 8b/-> *eax 1/r32/ecx +2836 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2837 05/add-to-eax 4/imm32 +2838 # var slice/ecx: slice = {eax, ecx} +2839 51/push-ecx +2840 50/push-eax +2841 89/<- %ecx 4/r32/esp +2842 # _test-input-stream contains "int" +2843 (clear-stream _test-input-stream) +2844 (write _test-input-stream "int") +2845 # +2846 (parse-var-with-type %ecx _test-input-stream) +2847 8b/-> *eax 2/r32/edx # Var-name +2848 (check-strings-equal %edx "x" "F - test-var-with-type/name") +2849 8b/-> *(eax+4) 2/r32/edx # Var-type +2850 (check-ints-equal *edx 1 "F - test-var-with-type/type") +2851 (check-ints-equal *(edx+4) 0 "F - test-var-with-type/type") +2852 # . epilogue +2853 89/<- %esp 5/r32/ebp +2854 5d/pop-to-ebp +2855 c3/return +2856 +2857 test-parse-var-with-type-and-register: +2858 # . prologue +2859 55/push-ebp +2860 89/<- %ebp 4/r32/esp +2861 # (eax..ecx) = "x/eax:" +2862 b8/copy-to-eax "x/eax:"/imm32 +2863 8b/-> *eax 1/r32/ecx +2864 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2865 05/add-to-eax 4/imm32 +2866 # var slice/ecx: slice = {eax, ecx} +2867 51/push-ecx +2868 50/push-eax +2869 89/<- %ecx 4/r32/esp +2870 # _test-input-stream contains "int" +2871 (clear-stream _test-input-stream) +2872 (write _test-input-stream "int") +2873 # +2874 (parse-var-with-type %ecx _test-input-stream) +2875 8b/-> *eax 2/r32/edx # Var-name +2876 (check-strings-equal %edx "x" "F - test-var-with-type-and-register/name") +2877 8b/-> *(eax+0x10) 2/r32/edx # Var-register +2878 (check-strings-equal %edx "eax" "F - test-var-with-type-and-register/register") +2879 8b/-> *(eax+4) 2/r32/edx # Var-type +2880 (check-ints-equal *edx 1 "F - test-var-with-type-and-register/type") +2881 (check-ints-equal *(edx+4) 0 "F - test-var-with-type-and-register/type") +2882 # . epilogue +2883 89/<- %esp 5/r32/ebp +2884 5d/pop-to-ebp +2885 c3/return +2886 +2887 test-parse-var-with-trailing-characters: +2888 # . prologue +2889 55/push-ebp +2890 89/<- %ebp 4/r32/esp +2891 # (eax..ecx) = "x:" +2892 b8/copy-to-eax "x:"/imm32 +2893 8b/-> *eax 1/r32/ecx +2894 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2895 05/add-to-eax 4/imm32 +2896 # var slice/ecx: slice = {eax, ecx} +2897 51/push-ecx +2898 50/push-eax +2899 89/<- %ecx 4/r32/esp +2900 # _test-input-stream contains "int," +2901 (clear-stream _test-input-stream) +2902 (write _test-input-stream "int,") +2903 # +2904 (parse-var-with-type %ecx _test-input-stream) +2905 8b/-> *eax 2/r32/edx # Var-name +2906 (check-strings-equal %edx "x" "F - test-var-with-trailing-characters/name") +2907 8b/-> *(eax+0x10) 2/r32/edx # Var-register +2908 (check-ints-equal %edx 0 "F - test-var-with-trailing-characters/register") +2909 8b/-> *(eax+4) 2/r32/edx # Var-type +2910 (check-ints-equal *edx 1 "F - test-var-with-trailing-characters/type") +2911 (check-ints-equal *(edx+4) 0 "F - test-var-with-trailing-characters/type") +2912 # . epilogue +2913 89/<- %esp 5/r32/ebp +2914 5d/pop-to-ebp +2915 c3/return +2916 +2917 test-parse-var-with-register-and-trailing-characters: +2918 # . prologue +2919 55/push-ebp +2920 89/<- %ebp 4/r32/esp +2921 # (eax..ecx) = "x/eax:" +2922 b8/copy-to-eax "x/eax:"/imm32 +2923 8b/-> *eax 1/r32/ecx +2924 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2925 05/add-to-eax 4/imm32 +2926 # var slice/ecx: slice = {eax, ecx} +2927 51/push-ecx +2928 50/push-eax +2929 89/<- %ecx 4/r32/esp +2930 # _test-input-stream contains "int," +2931 (clear-stream _test-input-stream) +2932 (write _test-input-stream "int,") +2933 # +2934 (parse-var-with-type %ecx _test-input-stream) +2935 8b/-> *eax 2/r32/edx # Var-name +2936 (check-strings-equal %edx "x" "F - test-var-with-register-and-trailing-characters/name") +2937 8b/-> *(eax+0x10) 2/r32/edx # Var-register +2938 (check-strings-equal %edx "eax" "F - test-var-with-register-and-trailing-characters/register") +2939 8b/-> *(eax+4) 2/r32/edx # Var-type +2940 (check-ints-equal *edx 1 "F - test-var-with-register-and-trailing-characters/type") +2941 (check-ints-equal *(edx+4) 0 "F - test-var-with-register-and-trailing-characters/type") +2942 # . epilogue +2943 89/<- %esp 5/r32/ebp +2944 5d/pop-to-ebp +2945 c3/return +2946 +2947 test-parse-var-with-compound-type: +2948 # . prologue +2949 55/push-ebp +2950 89/<- %ebp 4/r32/esp +2951 # (eax..ecx) = "x:" +2952 b8/copy-to-eax "x:"/imm32 +2953 8b/-> *eax 1/r32/ecx +2954 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2955 05/add-to-eax 4/imm32 +2956 # var slice/ecx: slice = {eax, ecx} +2957 51/push-ecx +2958 50/push-eax +2959 89/<- %ecx 4/r32/esp +2960 # _test-input-stream contains "(addr int)" +2961 (clear-stream _test-input-stream) +2962 (write _test-input-stream "(addr int)") +2963 # +2964 (parse-var-with-type %ecx _test-input-stream) +2965 8b/-> *eax 2/r32/edx # Var-name +2966 (check-strings-equal %edx "x" "F - test-var-with-compound-type/name") +2967 8b/-> *(eax+0x10) 2/r32/edx # Var-register +2968 (check-ints-equal %edx 0 "F - test-var-with-compound-type/register") +2969 # var type/edx: (handle tree type-id) = var->type +2970 8b/-> *(eax+4) 2/r32/edx # Var-type +2971 # type->left == atom(addr) +2972 8b/-> *edx 0/r32/eax # Atom-value +2973 (check-ints-equal *eax 2 "F - test-var-with-compound-type/type:0") # Tree-left +2974 # type->right->left == atom(int) +2975 8b/-> *(edx+4) 2/r32/edx # Tree-right +2976 8b/-> *edx 0/r32/eax # Tree-left +2977 (check-ints-equal *eax 1 "F - test-var-with-compound-type/type:1") # Atom-value +2978 # type->right->right == null +2979 (check-ints-equal *(edx+4) 0 "F - test-var-with-compound-type/type:2") # Tree-right +2980 # . epilogue +2981 89/<- %esp 5/r32/ebp +2982 5d/pop-to-ebp +2983 c3/return +2984 +2985 # identifier starts with a letter or '$' or '_' +2986 # no constraints at the moment on later letters +2987 # all we really want to do so far is exclude '{', '}' and '->' +2988 is-identifier?: # in: (addr slice) -> result/eax: boolean +2989 # . prologue +2990 55/push-ebp +2991 89/<- %ebp 4/r32/esp +2992 # if (slice-empty?(in)) return false +2993 (slice-empty? *(ebp+8)) # => eax +2994 3d/compare-eax-and 0/imm32/false +2995 75/jump-if-!= $is-identifier?:false/disp8 +2996 # var c/eax: byte = *in->start +2997 8b/-> *(ebp+8) 0/r32/eax +2998 8b/-> *eax 0/r32/eax +2999 8a/copy-byte *eax 0/r32/AL +3000 81 4/subop/and %eax 0xff/imm32 +3001 # if (c == '$') return true +3002 3d/compare-eax-and 0x24/imm32/$ +3003 74/jump-if-= $is-identifier?:true/disp8 +3004 # if (c == '_') return true +3005 3d/compare-eax-and 0x5f/imm32/_ +3006 74/jump-if-= $is-identifier?:true/disp8 +3007 # drop case +3008 25/and-eax-with 0x5f/imm32 +3009 # if (c < 'A') return false +3010 3d/compare-eax-and 0x41/imm32/A +3011 7c/jump-if-< $is-identifier?:false/disp8 +3012 # if (c > 'Z') return false +3013 3d/compare-eax-and 0x5a/imm32/Z +3014 7f/jump-if-> $is-identifier?:false/disp8 +3015 # otherwise return true +3016 $is-identifier?:true: +3017 b8/copy-to-eax 1/imm32/true +3018 eb/jump $is-identifier?:end/disp8 +3019 $is-identifier?:false: +3020 b8/copy-to-eax 0/imm32/false +3021 $is-identifier?:end: +3022 # . epilogue +3023 89/<- %esp 5/r32/ebp +3024 5d/pop-to-ebp +3025 c3/return +3026 +3027 test-is-identifier-dollar: +3028 # . prologue +3029 55/push-ebp +3030 89/<- %ebp 4/r32/esp +3031 # (eax..ecx) = "$a" +3032 b8/copy-to-eax "$a"/imm32 +3033 8b/-> *eax 1/r32/ecx +3034 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3035 05/add-to-eax 4/imm32 +3036 # var slice/ecx: slice = {eax, ecx} +3037 51/push-ecx +3038 50/push-eax +3039 89/<- %ecx 4/r32/esp +3040 # +3041 (is-identifier? %ecx) +3042 (check-ints-equal %eax 1 "F - test-is-identifier-dollar") +3043 # . epilogue +3044 89/<- %esp 5/r32/ebp +3045 5d/pop-to-ebp +3046 c3/return +3047 +3048 test-is-identifier-underscore: +3049 # . prologue +3050 55/push-ebp +3051 89/<- %ebp 4/r32/esp +3052 # (eax..ecx) = "_a" +3053 b8/copy-to-eax "_a"/imm32 +3054 8b/-> *eax 1/r32/ecx +3055 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3056 05/add-to-eax 4/imm32 +3057 # var slice/ecx: slice = {eax, ecx} +3058 51/push-ecx +3059 50/push-eax +3060 89/<- %ecx 4/r32/esp +3061 # +3062 (is-identifier? %ecx) +3063 (check-ints-equal %eax 1 "F - test-is-identifier-underscore") +3064 # . epilogue +3065 89/<- %esp 5/r32/ebp +3066 5d/pop-to-ebp +3067 c3/return +3068 +3069 test-is-identifier-a: +3070 # . prologue +3071 55/push-ebp +3072 89/<- %ebp 4/r32/esp +3073 # (eax..ecx) = "a$" +3074 b8/copy-to-eax "a$"/imm32 +3075 8b/-> *eax 1/r32/ecx +3076 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3077 05/add-to-eax 4/imm32 +3078 # var slice/ecx: slice = {eax, ecx} +3079 51/push-ecx +3080 50/push-eax +3081 89/<- %ecx 4/r32/esp +3082 # +3083 (is-identifier? %ecx) +3084 (check-ints-equal %eax 1 "F - test-is-identifier-a") +3085 # . epilogue +3086 89/<- %esp 5/r32/ebp +3087 5d/pop-to-ebp +3088 c3/return +3089 +3090 test-is-identifier-z: +3091 # . prologue +3092 55/push-ebp +3093 89/<- %ebp 4/r32/esp +3094 # (eax..ecx) = "z$" +3095 b8/copy-to-eax "z$"/imm32 +3096 8b/-> *eax 1/r32/ecx +3097 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3098 05/add-to-eax 4/imm32 +3099 # var slice/ecx: slice = {eax, ecx} +3100 51/push-ecx +3101 50/push-eax +3102 89/<- %ecx 4/r32/esp +3103 # +3104 (is-identifier? %ecx) +3105 (check-ints-equal %eax 1 "F - test-is-identifier-z") +3106 # . epilogue +3107 89/<- %esp 5/r32/ebp +3108 5d/pop-to-ebp +3109 c3/return +3110 +3111 test-is-identifier-A: +3112 # . prologue +3113 55/push-ebp +3114 89/<- %ebp 4/r32/esp +3115 # (eax..ecx) = "A$" +3116 b8/copy-to-eax "A$"/imm32 +3117 8b/-> *eax 1/r32/ecx +3118 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3119 05/add-to-eax 4/imm32 +3120 # var slice/ecx: slice = {eax, ecx} +3121 51/push-ecx +3122 50/push-eax +3123 89/<- %ecx 4/r32/esp +3124 # +3125 (is-identifier? %ecx) +3126 (check-ints-equal %eax 1 "F - test-is-identifier-A") +3127 # . epilogue +3128 89/<- %esp 5/r32/ebp +3129 5d/pop-to-ebp +3130 c3/return +3131 +3132 test-is-identifier-Z: +3133 # . prologue +3134 55/push-ebp +3135 89/<- %ebp 4/r32/esp +3136 # (eax..ecx) = "Z$" +3137 b8/copy-to-eax "Z$"/imm32 +3138 8b/-> *eax 1/r32/ecx +3139 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3140 05/add-to-eax 4/imm32 +3141 # var slice/ecx: slice = {eax, ecx} +3142 51/push-ecx +3143 50/push-eax +3144 89/<- %ecx 4/r32/esp +3145 # +3146 (is-identifier? %ecx) +3147 (check-ints-equal %eax 1 "F - test-is-identifier-Z") +3148 # . epilogue +3149 89/<- %esp 5/r32/ebp +3150 5d/pop-to-ebp +3151 c3/return +3152 +3153 test-is-identifier-@: +3154 # character before 'A' is invalid +3155 # . prologue +3156 55/push-ebp +3157 89/<- %ebp 4/r32/esp +3158 # (eax..ecx) = "@a" +3159 b8/copy-to-eax "@a"/imm32 +3160 8b/-> *eax 1/r32/ecx +3161 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3162 05/add-to-eax 4/imm32 +3163 # var slice/ecx: slice = {eax, ecx} +3164 51/push-ecx +3165 50/push-eax +3166 89/<- %ecx 4/r32/esp +3167 # +3168 (is-identifier? %ecx) +3169 (check-ints-equal %eax 0 "F - test-is-identifier-@") +3170 # . epilogue +3171 89/<- %esp 5/r32/ebp +3172 5d/pop-to-ebp +3173 c3/return +3174 +3175 test-is-identifier-square-bracket: +3176 # character after 'Z' is invalid +3177 # . prologue +3178 55/push-ebp +3179 89/<- %ebp 4/r32/esp +3180 # (eax..ecx) = "[a" +3181 b8/copy-to-eax "[a"/imm32 +3182 8b/-> *eax 1/r32/ecx +3183 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3184 05/add-to-eax 4/imm32 +3185 # var slice/ecx: slice = {eax, ecx} +3186 51/push-ecx +3187 50/push-eax +3188 89/<- %ecx 4/r32/esp +3189 # +3190 (is-identifier? %ecx) +3191 (check-ints-equal %eax 0 "F - test-is-identifier-@") +3192 # . epilogue +3193 89/<- %esp 5/r32/ebp +3194 5d/pop-to-ebp +3195 c3/return +3196 +3197 test-is-identifier-backtick: +3198 # character before 'a' is invalid +3199 # . prologue +3200 55/push-ebp +3201 89/<- %ebp 4/r32/esp +3202 # (eax..ecx) = "`a" +3203 b8/copy-to-eax "`a"/imm32 +3204 8b/-> *eax 1/r32/ecx +3205 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3206 05/add-to-eax 4/imm32 +3207 # var slice/ecx: slice = {eax, ecx} +3208 51/push-ecx +3209 50/push-eax +3210 89/<- %ecx 4/r32/esp +3211 # +3212 (is-identifier? %ecx) +3213 (check-ints-equal %eax 0 "F - test-is-identifier-backtick") +3214 # . epilogue +3215 89/<- %esp 5/r32/ebp +3216 5d/pop-to-ebp +3217 c3/return +3218 +3219 test-is-identifier-curly-brace-open: +3220 # character after 'z' is invalid; also used for blocks +3221 # . prologue +3222 55/push-ebp +3223 89/<- %ebp 4/r32/esp +3224 # (eax..ecx) = "{a" +3225 b8/copy-to-eax "{a"/imm32 +3226 8b/-> *eax 1/r32/ecx +3227 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3228 05/add-to-eax 4/imm32 +3229 # var slice/ecx: slice = {eax, ecx} +3230 51/push-ecx +3231 50/push-eax +3232 89/<- %ecx 4/r32/esp +3233 # +3234 (is-identifier? %ecx) +3235 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open") +3236 # . epilogue +3237 89/<- %esp 5/r32/ebp +3238 5d/pop-to-ebp +3239 c3/return +3240 +3241 test-is-identifier-curly-brace-close: +3242 # . prologue +3243 55/push-ebp +3244 89/<- %ebp 4/r32/esp +3245 # (eax..ecx) = "}a" +3246 b8/copy-to-eax "}a"/imm32 +3247 8b/-> *eax 1/r32/ecx +3248 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3249 05/add-to-eax 4/imm32 +3250 # var slice/ecx: slice = {eax, ecx} +3251 51/push-ecx +3252 50/push-eax +3253 89/<- %ecx 4/r32/esp +3254 # +3255 (is-identifier? %ecx) +3256 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close") +3257 # . epilogue +3258 89/<- %esp 5/r32/ebp +3259 5d/pop-to-ebp +3260 c3/return +3261 +3262 test-is-identifier-hyphen: +3263 # disallow leading '-' since '->' has special meaning +3264 # . prologue +3265 55/push-ebp +3266 89/<- %ebp 4/r32/esp +3267 # (eax..ecx) = "-a" +3268 b8/copy-to-eax "-a"/imm32 +3269 8b/-> *eax 1/r32/ecx +3270 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3271 05/add-to-eax 4/imm32 +3272 # var slice/ecx: slice = {eax, ecx} +3273 51/push-ecx +3274 50/push-eax +3275 89/<- %ecx 4/r32/esp +3276 # +3277 (is-identifier? %ecx) +3278 (check-ints-equal %eax 0 "F - test-is-identifier-hyphen") +3279 # . epilogue +3280 89/<- %esp 5/r32/ebp +3281 5d/pop-to-ebp +3282 c3/return +3283 +3284 populate-mu-function-body: # in: (addr buffered-file), out: (handle function), vars: (addr stack (handle var)) +3285 # . prologue +3286 55/push-ebp +3287 89/<- %ebp 4/r32/esp +3288 # . save registers +3289 50/push-eax +3290 56/push-esi +3291 57/push-edi +3292 # esi = in +3293 8b/-> *(ebp+8) 6/r32/esi +3294 # edi = out +3295 8b/-> *(ebp+0xc) 7/r32/edi +3296 # initialize some global state +3297 c7 0/subop/copy *Curr-block-depth 1/imm32 +3298 c7 0/subop/copy *Next-local-stack-offset -4/imm32 +3299 # var eax: (handle block) = parse-mu-block(in, vars, fn) +3300 (parse-mu-block %esi *(ebp+0x10) %edi) # => eax +3301 # out->body = eax +3302 89/<- *(edi+0x10) 0/r32/eax # Function-body +3303 $populate-mu-function-body:end: +3304 # . restore registers +3305 5f/pop-to-edi +3306 5e/pop-to-esi +3307 58/pop-to-eax +3308 # . epilogue +3309 89/<- %esp 5/r32/ebp +3310 5d/pop-to-ebp +3311 c3/return +3312 +3313 == data +3314 +3315 # Global state added to each var record when parsing a function +3316 +3317 Curr-block-depth: # (addr int) +3318 0/imm32 +3319 Next-local-stack-offset: # (addr int) +3320 -4/imm32 +3321 +3322 Next-block-index: # (addr int) +3323 1/imm32 +3324 +3325 == code +3326 +3327 # parses a block, assuming that the leading '{' has already been read by the caller +3328 parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle block) +3329 # pseudocode: +3330 # var line: (stream byte 512) +3331 # var word-slice: slice +3332 # increment *Curr-block-depth +3333 # result/eax = allocate(Heap, Stmt-size) +3334 # result->tag = 0/block +3335 # result->name = some unique name +3336 # while true # line loop +3337 # clear-stream(line) +3338 # read-line-buffered(in, line) +3339 # if (line->write == 0) break # end of file +3340 # word-slice = next-mu-token(line) +3341 # if slice-empty?(word-slice) # end of line +3342 # continue +3343 # else if slice-starts-with?(word-slice, "#") +3344 # continue +3345 # else if slice-equal?(word-slice, "{") +3346 # assert(no-tokens-in(line)) +3347 # block = parse-mu-block(in, vars, fn) +3348 # append-to-block(result, block) +3349 # else if slice-equal?(word-slice, "}") +3350 # break +3351 # else if slice-ends-with?(word-slice, ":") +3352 # # TODO: error-check the rest of 'line' +3353 # --word-slice->end to skip ':' +3354 # named-block = parse-mu-named-block(word-slice, in, vars, fn) +3355 # append-to-block(result, named-block) +3356 # else if slice-equal?(word-slice, "var") +3357 # var-def = parse-mu-var-def(line, vars) +3358 # append-to-block(result, var-def) +3359 # else +3360 # stmt = parse-mu-stmt(line, vars, fn) +3361 # append-to-block(result, stmt) +3362 # decrement *Curr-block-depth +3363 # return result +3364 # +3365 # . prologue +3366 55/push-ebp +3367 89/<- %ebp 4/r32/esp +3368 # . save registers +3369 51/push-ecx +3370 52/push-edx +3371 53/push-ebx +3372 57/push-edi +3373 # var line/ecx: (stream byte 512) +3374 81 5/subop/subtract %esp 0x200/imm32 +3375 68/push 0x200/imm32/length +3376 68/push 0/imm32/read +3377 68/push 0/imm32/write +3378 89/<- %ecx 4/r32/esp +3379 # var word-slice/edx: slice +3380 68/push 0/imm32/end +3381 68/push 0/imm32/start +3382 89/<- %edx 4/r32/esp +3383 # edi = result +3384 (allocate Heap *Stmt-size) # => eax +3385 (zero-out %eax *Stmt-size) +3386 89/<- %edi 0/r32/eax +3387 # set result->tag +3388 c7 0/subop/copy *edi 0/imm32/block # Stmt-tag +3389 # set result->var +3390 (new-block-name *(ebp+0x10)) # => eax +3391 89/<- *(edi+8) 0/r32/eax # Block-var +3392 # push result->var to vars +3393 (push *(ebp+0xc) %eax) +3394 # increment *Curr-block-depth +3395 ff 0/subop/increment *Curr-block-depth +3396 { +3397 $parse-mu-block:line-loop: +3398 # line = read-line-buffered(in) +3399 (clear-stream %ecx) +3400 (read-line-buffered *(ebp+8) %ecx) +3401 #? (write-buffered Stderr "line: ") +3402 #? (write-stream-data Stderr %ecx) +3403 #? (write-buffered Stderr Newline) +3404 #? (flush Stderr) +3405 # if (line->write == 0) break +3406 81 7/subop/compare *ecx 0/imm32 +3407 0f 84/jump-if-= break/disp32 +3408 # word-slice = next-mu-token(line) +3409 (next-mu-token %ecx %edx) +3410 #? (write-buffered Stderr "word: ") +3411 #? (write-slice-buffered Stderr %edx) +3412 #? (write-buffered Stderr Newline) +3413 #? (flush Stderr) +3414 # if slice-empty?(word-slice) continue +3415 (slice-empty? %edx) +3416 3d/compare-eax-and 0/imm32/false +3417 0f 85/jump-if-!= loop/disp32 +3418 # if (slice-starts-with?(word-slice, '#') continue +3419 # . eax = *word-slice->start +3420 8b/-> *edx 0/r32/eax +3421 8a/copy-byte *eax 0/r32/AL +3422 81 4/subop/and %eax 0xff/imm32 +3423 # . if (eax == '#') continue +3424 3d/compare-eax-and 0x23/imm32/hash +3425 0f 84/jump-if-= loop/disp32 +3426 # if slice-equal?(word-slice, "{") +3427 { +3428 $parse-mu-block:check-for-block: +3429 (slice-equal? %edx "{") +3430 3d/compare-eax-and 0/imm32/false +3431 74/jump-if-= break/disp8 +3432 (check-no-tokens-left %ecx) +3433 # parse new block and append +3434 (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax +3435 (append-to-block Heap %edi %eax) +3436 e9/jump $parse-mu-block:line-loop/disp32 +3437 } +3438 # if slice-equal?(word-slice, "}") break +3439 $parse-mu-block:check-for-end: +3440 (slice-equal? %edx "}") +3441 3d/compare-eax-and 0/imm32/false +3442 0f 85/jump-if-!= break/disp32 +3443 # if slice-ends-with?(word-slice, ":") parse named block and append +3444 { +3445 $parse-mu-block:check-for-named-block: +3446 # . eax = *(word-slice->end-1) +3447 8b/-> *(edx+4) 0/r32/eax +3448 48/decrement-eax +3449 8a/copy-byte *eax 0/r32/AL +3450 81 4/subop/and %eax 0xff/imm32 +3451 # . if (eax != ':') break +3452 3d/compare-eax-and 0x3a/imm32/colon +3453 0f 85/jump-if-!= break/disp32 +3454 # TODO: error-check the rest of 'line' +3455 # +3456 # skip ':' +3457 ff 1/subop/decrement *(edx+4) # Slice-end +3458 # +3459 (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax +3460 (append-to-block Heap %edi %eax) +3461 e9/jump $parse-mu-block:line-loop/disp32 +3462 } +3463 # if slice-equal?(word-slice, "var") +3464 { +3465 $parse-mu-block:check-for-var: +3466 (slice-equal? %edx "var") +3467 3d/compare-eax-and 0/imm32/false +3468 74/jump-if-= break/disp8 +3469 # +3470 (parse-mu-var-def %ecx *(ebp+0xc)) # => eax +3471 (append-to-block Heap %edi %eax) +3472 e9/jump $parse-mu-block:line-loop/disp32 +3473 } +3474 $parse-mu-block:regular-stmt: +3475 # otherwise +3476 (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10)) # => eax +3477 (append-to-block Heap %edi %eax) +3478 e9/jump loop/disp32 +3479 } # end line loop +3480 # decrement *Curr-block-depth +3481 ff 1/subop/decrement *Curr-block-depth +3482 # +3483 (pop *(ebp+0xc)) # => eax +3484 # return result +3485 89/<- %eax 7/r32/edi +3486 $parse-mu-block:end: +3487 # . reclaim locals +3488 81 0/subop/add %esp 0x214/imm32 +3489 # . restore registers +3490 5f/pop-to-edi +3491 5b/pop-to-ebx +3492 5a/pop-to-edx +3493 59/pop-to-ecx +3494 # . epilogue +3495 89/<- %esp 5/r32/ebp +3496 5d/pop-to-ebp +3497 c3/return +3498 +3499 $parse-mu-block:abort: +3500 # error("'{' or '}' should be on its own line, but got '") +3501 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") +3502 (rewind-stream %ecx) +3503 (write-stream 2 %ecx) +3504 (write-buffered Stderr "'\n") +3505 (flush Stderr) +3506 # . syscall(exit, 1) +3507 bb/copy-to-ebx 1/imm32 +3508 b8/copy-to-eax 1/imm32/exit +3509 cd/syscall 0x80/imm8 +3510 # never gets here +3511 +3512 new-block-name: # fn: (handle function) -> result/eax: (handle var) +3513 # . prologue +3514 55/push-ebp +3515 89/<- %ebp 4/r32/esp +3516 # . save registers +3517 51/push-ecx +3518 52/push-edx +3519 # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:' +3520 8b/-> *(ebp+8) 0/r32/eax +3521 8b/-> *eax 0/r32/eax # Function-name +3522 8b/-> *eax 0/r32/eax # String-length +3523 05/add-to-eax 0xd/imm32 # 10 + 2 for '$:' +3524 89/<- %ecx 0/r32/eax +3525 # var name/edx: (stream byte n) +3526 29/subtract %esp 1/r32/ecx +3527 ff 6/subop/push %ecx +3528 68/push 0/imm32/read +3529 68/push 0/imm32/write +3530 89/<- %edx 4/r32/esp +3531 (clear-stream %edx) +3532 # eax = fn->name +3533 8b/-> *(ebp+8) 0/r32/eax +3534 8b/-> *eax 0/r32/eax # Function-name +3535 # construct result using Next-block-index (and increment it) +3536 (write %edx "$") +3537 (write %edx %eax) +3538 (write %edx ":") +3539 (print-int32 %edx *Next-block-index) +3540 ff 0/subop/increment *Next-block-index +3541 # var s/eax: slice = {name->data, name->data + name->write} (clobbering edx) +3542 # . eax = name->write +3543 8b/-> *edx 0/r32/eax +3544 # . edx = name->data +3545 8d/copy-address *(edx+0xc) 2/r32/edx +3546 # . eax = name->write + name->data +3547 01/add %eax 2/r32/edx +3548 # . push {edx, eax} +3549 ff 6/subop/push %eax +3550 ff 6/subop/push %edx +3551 89/<- %eax 4/r32/esp +3552 # var final-name/edx: (addr array byte) = slice-to-string(s) +3553 (slice-to-string Heap %eax) # => eax +3554 89/<- %edx 0/r32/eax +3555 # set result->var +3556 # . var type/eax: (handle tree type-id) = literal +3557 (allocate Heap *Tree-size) # => eax +3558 (zero-out %eax *Tree-size) # default type is 'literal' +3559 # . var result/eax: (handle var) = new-var(final-name, type) +3560 (new-var Heap %edx %eax *Curr-block-depth 0 0) # => eax +3561 $new-block-name:end: +3562 # . reclaim locals +3563 81 0/subop/add %ecx 0xc/imm32 # name.{read/write/len} +3564 81 0/subop/add %ecx 8/imm32 # slice +3565 01/add %esp 1/r32/ecx +3566 # . restore registers +3567 5a/pop-to-edx +3568 59/pop-to-ecx +3569 # . epilogue +3570 89/<- %esp 5/r32/ebp +3571 5d/pop-to-ebp +3572 c3/return +3573 +3574 check-no-tokens-left: # line: (addr stream byte) +3575 # . prologue +3576 55/push-ebp +3577 89/<- %ebp 4/r32/esp +3578 # . save registers +3579 50/push-eax 3580 51/push-ecx -3581 # var s/ecx: (addr array byte) = slice-to-string(name) -3582 (slice-to-string Heap *(ebp+8)) # => eax -3583 89/<- %ecx 0/r32/eax -3584 # var type/eax: (handle tree type-id) = literal -3585 (allocate Heap *Tree-size) # => eax -3586 (zero-out %eax *Tree-size) # default type is 'literal' -3587 # var v/ecx: (handle var) = new-var(s, type) -3588 (new-var Heap %ecx %eax *Curr-block-depth 0 0) # => eax -3589 89/<- %ecx 0/r32/eax -3590 # push(vars, v) -3591 (push *(ebp+0x10) %ecx) -3592 # eax = result -3593 (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) # => eax -3594 # pop the var -3595 50/push-eax -3596 (pop *(ebp+0x10)) # => eax -3597 58/pop-to-eax -3598 # result->tag = named-block -3599 c7 0/subop/copy *eax 0/imm32/block # Stmt-tag -3600 # result->var = v -3601 89/<- *(eax+8) 1/r32/ecx # Block-var -3602 $parse-mu-named-block:end: -3603 # . restore registers -3604 59/pop-to-ecx -3605 # . epilogue -3606 89/<- %esp 5/r32/ebp -3607 5d/pop-to-ebp -3608 c3/return -3609 -3610 parse-mu-var-def: # line: (addr stream byte), vars: (addr stack (handle var)) -> result/eax: (handle stmt) -3611 # . prologue -3612 55/push-ebp -3613 89/<- %ebp 4/r32/esp -3614 # . save registers -3615 51/push-ecx -3616 52/push-edx -3617 # var word-slice/ecx: slice -3618 68/push 0/imm32/end -3619 68/push 0/imm32/start -3620 89/<- %ecx 4/r32/esp -3621 # var v/edx: (handle var) = parse-var-with-type(line) -3622 (next-mu-token *(ebp+8) %ecx) -3623 (parse-var-with-type %ecx *(ebp+8)) # => eax -3624 89/<- %edx 0/r32/eax -3625 # v->block-depth = *Curr-block-depth -3626 8b/-> *Curr-block-depth 0/r32/eax -3627 89/<- *(edx+8) 0/r32/eax -3628 # -3629 (push *(ebp+0xc) %edx) -3630 # either v has no register and there's no more to this line -3631 8b/-> *(edx+0x10) 0/r32/eax # Var-register -3632 3d/compare-eax-and 0/imm32 -3633 { -3634 75/jump-if-!= break/disp8 -3635 # v->stack-offset = *Next-local-stack-offset -3636 8b/-> *Next-local-stack-offset 0/r32/eax -3637 89/<- *(edx+0xc) 0/r32/eax # Var-stack-offset -3638 # TODO: ensure that there's nothing else on this line -3639 (new-vardef Heap %edx) # => eax -3640 eb/jump $parse-mu-var-def:end/disp8 -3641 } -3642 # or v has a register and there's more to this line -3643 { -3644 74/jump-if-= break/disp8 -3645 # ensure that the next word is '<-' -3646 (next-mu-token *(ebp+8) %ecx) -3647 (slice-equal? %ecx "<-") # => eax -3648 3d/compare-eax-and 0/imm32/false -3649 74/jump-if-= $parse-mu-var-def:abort/disp8 -3650 # -3651 (new-regvardef Heap %edx) # => eax -3652 (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc)) -3653 } -3654 $parse-mu-var-def:end: -3655 # *Next-local-stack-offset -= size-of(v) -3656 50/push-eax -3657 (size-of %edx) # => eax -3658 29/subtract-from *Next-local-stack-offset 0/r32/eax -3659 58/pop-to-eax -3660 # . reclaim locals -3661 81 0/subop/add %esp 8/imm32 -3662 # . restore registers -3663 5a/pop-to-edx -3664 59/pop-to-ecx -3665 # . epilogue -3666 89/<- %esp 5/r32/ebp -3667 5d/pop-to-ebp -3668 c3/return -3669 -3670 $parse-mu-var-def:abort: -3671 (rewind-stream *(ebp+8)) -3672 # error("register variable requires a valid instruction to initialize but got '" line "'\n") -3673 (write-buffered Stderr "register variable requires a valid instruction to initialize but got '") -3674 (flush Stderr) -3675 (write-stream 2 *(ebp+8)) -3676 (write-buffered Stderr "'\n") -3677 (flush Stderr) -3678 # . syscall(exit, 1) -3679 bb/copy-to-ebx 1/imm32 -3680 b8/copy-to-eax 1/imm32/exit -3681 cd/syscall 0x80/imm8 -3682 # never gets here -3683 -3684 test-parse-mu-var-def: -3685 # 'var n: int' -3686 # . prologue -3687 55/push-ebp -3688 89/<- %ebp 4/r32/esp -3689 # setup -3690 (clear-stream _test-input-stream) -3691 (write _test-input-stream "n: int\n") # caller has consumed the 'var' -3692 c7 0/subop/copy *Curr-block-depth 1/imm32 -3693 c7 0/subop/copy *Next-local-stack-offset -4/imm32 -3694 # var vars/ecx: (stack (addr var) 4) -3695 81 5/subop/subtract %esp 0x10/imm32 -3696 68/push 0x10/imm32/length -3697 68/push 0/imm32/top -3698 89/<- %ecx 4/r32/esp -3699 (clear-stack %ecx) -3700 # convert -3701 (parse-mu-var-def _test-input-stream %ecx) # => eax -3702 # check result -3703 (check-ints-equal *eax 2 "F - test-parse-mu-var-def/tag") # Stmt-tag is vardef -3704 8b/-> *(eax+4) 0/r32/eax # Vardef-var -3705 (check-strings-equal *eax "n" "F - test-parse-mu-var-def/var-name") # Var-name -3706 (check-ints-equal *(eax+0x10) 0 "F - test-parse-mu-var-def/var-register") # Var-register -3707 (check-ints-equal *(eax+8) 1 "F - test-parse-mu-reg-var-def/output-block-depth") # Var-block-depth -3708 (check-ints-equal *(eax+0xc) -4 "F - test-parse-mu-reg-var-def/output-stack-offset") # Var-stack-offset -3709 # ensure type is int -3710 8b/-> *(eax+4) 0/r32/eax # Var-type -3711 (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0") # Tree-left -3712 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-var-def/var-type:0") # Tree-right -3713 # globals -3714 (check-ints-equal *Next-local-stack-offset -8 "F - test-parse-mu-reg-var-def/Next-local-stack-offset") -3715 # . epilogue -3716 89/<- %esp 5/r32/ebp -3717 5d/pop-to-ebp -3718 c3/return -3719 -3720 test-parse-mu-reg-var-def: -3721 # 'var n/eax: int <- copy 0' -3722 # . prologue -3723 55/push-ebp -3724 89/<- %ebp 4/r32/esp -3725 # setup -3726 (clear-stream _test-input-stream) -3727 (write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var' -3728 c7 0/subop/copy *Curr-block-depth 1/imm32 -3729 c7 0/subop/copy *Next-local-stack-offset -4/imm32 -3730 # var vars/ecx: (stack (addr var) 4) -3731 81 5/subop/subtract %esp 0x10/imm32 -3732 68/push 0x10/imm32/length -3733 68/push 0/imm32/top -3734 89/<- %ecx 4/r32/esp -3735 (clear-stack %ecx) -3736 # convert -3737 (parse-mu-var-def _test-input-stream %ecx) # => eax -3738 # check result -3739 (check-ints-equal *eax 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is regvardef -3740 8b/-> *(eax+0xc) 0/r32/eax # Regvardef-outputs -3741 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/single-output") # List-next -3742 8b/-> *eax 0/r32/eax # List-value -3743 (check-strings-equal *eax "n" "F - test-parse-mu-reg-var-def/output-name") # Var-name -3744 (check-strings-equal *(eax+0x10) "eax" "F - test-parse-mu-reg-var-def/output-register") # Var-register -3745 (check-ints-equal *(eax+8) 1 "F - test-parse-mu-reg-var-def/output-block-depth") # Var-block-depth -3746 (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-stack-offset") # Var-stack-offset -3747 # ensure type is int -3748 8b/-> *(eax+4) 0/r32/eax # Var-type -3749 (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-left -3750 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-right -3751 # globals -3752 (check-ints-equal *Next-local-stack-offset -8 "F - test-parse-mu-reg-var-def/Next-local-stack-offset") -3753 # . epilogue -3754 89/<- %esp 5/r32/ebp -3755 5d/pop-to-ebp -3756 c3/return -3757 -3758 parse-mu-stmt: # line: (addr stream byte), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) -3759 # pseudocode: -3760 # var name: slice -3761 # result = allocate(Heap, Stmt-size) -3762 # if stmt-has-outputs?(line) -3763 # while true -3764 # name = next-mu-token(line) -3765 # if (name == '<-') break -3766 # assert(is-identifier?(name)) -3767 # var v: (handle var) = lookup-or-define-var(name, vars, fn) # regular stmts may define vars in fn outputs -3768 # result->outputs = append(result->outputs, v) -3769 # add-operation-and-inputs-to-stmt(result, line, vars) -3770 # -3771 # . prologue -3772 55/push-ebp -3773 89/<- %ebp 4/r32/esp -3774 # . save registers -3775 51/push-ecx -3776 57/push-edi -3777 # var name/ecx: slice -3778 68/push 0/imm32/end -3779 68/push 0/imm32/start -3780 89/<- %ecx 4/r32/esp -3781 # result/edi: (handle stmt) -3782 (allocate Heap *Stmt-size) # => eax -3783 (zero-out %eax *Stmt-size) -3784 89/<- %edi 0/r32/eax -3785 # result->tag = 1/stmt -3786 c7 0/subop/copy *edi 1/imm32/stmt1 # Stmt-tag -3787 { -3788 (stmt-has-outputs? *(ebp+8)) -3789 3d/compare-eax-and 0/imm32/false -3790 0f 84/jump-if-= break/disp32 -3791 { -3792 $parse-mu-stmt:read-outputs: -3793 # name = next-mu-token(line) -3794 (next-mu-token *(ebp+8) %ecx) -3795 # if slice-empty?(word-slice) break -3796 (slice-empty? %ecx) -3797 3d/compare-eax-and 0/imm32/false -3798 0f 85/jump-if-!= break/disp32 -3799 # if (name == "<-") break -3800 (slice-equal? %ecx "<-") -3801 3d/compare-eax-and 0/imm32/false -3802 75/jump-if-!= break/disp8 -3803 # assert(is-identifier?(name)) -3804 (is-identifier? %ecx) -3805 3d/compare-eax-and 0/imm32/false -3806 0f 84/jump-if-= $parse-mu-stmt:abort/disp32 -3807 # -3808 (lookup-or-define-var %ecx *(ebp+0xc) *(ebp+0x10)) # => eax -3809 (append-list Heap %eax *(edi+0xc)) # Stmt1-outputs => eax -3810 89/<- *(edi+0xc) 0/r32/eax # Stmt1-outputs -3811 e9/jump loop/disp32 -3812 } -3813 } -3814 (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc)) -3815 $parse-mu-stmt:end: -3816 # return result -3817 89/<- %eax 7/r32/edi -3818 # . reclaim locals -3819 81 0/subop/add %esp 8/imm32 -3820 # . restore registers -3821 5f/pop-to-edi -3822 59/pop-to-ecx -3823 # . epilogue -3824 89/<- %esp 5/r32/ebp -3825 5d/pop-to-ebp -3826 c3/return -3827 -3828 $parse-mu-stmt:abort: -3829 # error("invalid identifier '" name "'\n") -3830 (write-buffered Stderr "invalid identifier '") -3831 (write-slice-buffered Stderr %ecx) -3832 (write-buffered Stderr "'\n") -3833 (flush Stderr) -3834 # . syscall(exit, 1) -3835 bb/copy-to-ebx 1/imm32 -3836 b8/copy-to-eax 1/imm32/exit -3837 cd/syscall 0x80/imm8 -3838 # never gets here -3839 -3840 add-operation-and-inputs-to-stmt: # stmt: (handle stmt), line: (addr stream byte), vars: (addr stack (handle var)) -3841 # pseudocode: -3842 # stmt->name = slice-to-string(next-mu-token(line)) -3843 # while true -3844 # name = next-mu-token(line) -3845 # v = lookup-var-or-literal(name) -3846 # stmt->inouts = append(stmt->inouts, v) -3847 # -3848 # . prologue -3849 55/push-ebp -3850 89/<- %ebp 4/r32/esp -3851 # . save registers -3852 50/push-eax -3853 51/push-ecx -3854 57/push-edi -3855 # edi = stmt -3856 8b/-> *(ebp+8) 7/r32/edi -3857 # var name/ecx: slice -3858 68/push 0/imm32/end -3859 68/push 0/imm32/start -3860 89/<- %ecx 4/r32/esp -3861 $add-operation-and-inputs-to-stmt:read-operation: -3862 (next-mu-token *(ebp+0xc) %ecx) -3863 (slice-to-string Heap %ecx) # => eax -3864 89/<- *(edi+4) 0/r32/eax # Stmt1-operation or Regvardef-operation -3865 { -3866 $add-operation-and-inputs-to-stmt:read-inouts: -3867 # name = next-mu-token(line) -3868 (next-mu-token *(ebp+0xc) %ecx) -3869 # if slice-empty?(word-slice) break -3870 (slice-empty? %ecx) # => eax -3871 3d/compare-eax-and 0/imm32/false -3872 0f 85/jump-if-!= break/disp32 -3873 # if (name == "<-") abort -3874 (slice-equal? %ecx "<-") -3875 3d/compare-eax-and 0/imm32/false -3876 0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32 -3877 # -3878 (lookup-var-or-literal %ecx *(ebp+0x10)) # => eax -3879 (append-list Heap %eax *(edi+8)) # Stmt1-inouts or Regvardef-inouts => eax -3880 89/<- *(edi+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts -3881 e9/jump loop/disp32 -3882 } -3883 $add-operation-and-inputs-to-stmt:end: -3884 # . reclaim locals -3885 81 0/subop/add %esp 8/imm32 -3886 # . restore registers -3887 5f/pop-to-edi -3888 59/pop-to-ecx -3889 58/pop-to-eax -3890 # . epilogue -3891 89/<- %esp 5/r32/ebp -3892 5d/pop-to-ebp -3893 c3/return -3894 -3895 $add-operation-and-inputs-to-stmt:abort: -3896 # error("invalid statement '" line "'\n") -3897 (rewind-stream *(ebp+8)) -3898 (write-buffered Stderr "invalid identifier '") -3899 (flush Stderr) -3900 (write-stream 2 *(ebp+8)) -3901 (write-buffered Stderr "'\n") -3902 (flush Stderr) -3903 # . syscall(exit, 1) -3904 bb/copy-to-ebx 1/imm32 -3905 b8/copy-to-eax 1/imm32/exit -3906 cd/syscall 0x80/imm8 -3907 # never gets here -3908 -3909 stmt-has-outputs?: # line: (addr stream byte) -> result/eax: boolean -3910 # . prologue -3911 55/push-ebp -3912 89/<- %ebp 4/r32/esp -3913 # . save registers -3914 51/push-ecx -3915 # var word-slice/ecx: slice -3916 68/push 0/imm32/end -3917 68/push 0/imm32/start -3918 89/<- %ecx 4/r32/esp -3919 # result = false -3920 b8/copy-to-eax 0/imm32/false -3921 (rewind-stream *(ebp+8)) -3922 { -3923 (next-mu-token *(ebp+8) %ecx) -3924 # if slice-empty?(word-slice) break -3925 (slice-empty? %ecx) -3926 3d/compare-eax-and 0/imm32/false -3927 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) -3928 0f 85/jump-if-!= break/disp32 -3929 # if slice-starts-with?(word-slice, '#') break -3930 # . eax = *word-slice->start -3931 8b/-> *ecx 0/r32/eax -3932 8a/copy-byte *eax 0/r32/AL -3933 81 4/subop/and %eax 0xff/imm32 -3934 # . if (eax == '#') break -3935 3d/compare-eax-and 0x23/imm32/hash -3936 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) -3937 0f 84/jump-if-= break/disp32 -3938 # if slice-equal?(word-slice, '<-') return true -3939 (slice-equal? %ecx "<-") -3940 3d/compare-eax-and 0/imm32/false -3941 74/jump-if-= loop/disp8 -3942 b8/copy-to-eax 1/imm32/true -3943 } -3944 $stmt-has-outputs:end: -3945 (rewind-stream *(ebp+8)) -3946 # . reclaim locals -3947 81 0/subop/add %esp 8/imm32 -3948 # . restore registers -3949 59/pop-to-ecx -3950 # . epilogue -3951 89/<- %esp 5/r32/ebp -3952 5d/pop-to-ebp -3953 c3/return -3954 -3955 # if 'name' starts with a digit, create a new literal var for it -3956 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found -3957 lookup-var-or-literal: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) -3958 # . prologue -3959 55/push-ebp -3960 89/<- %ebp 4/r32/esp -3961 # . save registers -3962 51/push-ecx -3963 56/push-esi -3964 # esi = name -3965 8b/-> *(ebp+8) 6/r32/esi -3966 # if slice-empty?(name) abort -3967 (slice-empty? %esi) # => eax -3968 3d/compare-eax-and 0/imm32/false -3969 0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32 -3970 # var c/ecx: byte = *name->start -3971 8b/-> *esi 1/r32/ecx -3972 8a/copy-byte *ecx 1/r32/CL -3973 81 4/subop/and %ecx 0xff/imm32 -3974 # if is-decimal-digit?(c) return new var(name) -3975 { -3976 (is-decimal-digit? %ecx) # => eax -3977 81 7/subop/compare %eax 0/imm32/false -3978 74/jump-if-= break/disp8 -3979 (new-literal-integer Heap %esi) # => eax -3980 eb/jump $lookup-var-or-literal:end/disp8 -3981 } -3982 # else if (c == '"') return new var(name) -3983 { -3984 81 7/subop/compare %ecx 0x22/imm32/dquote -3985 75/jump-if-!= break/disp8 -3986 (new-literal-string Heap %esi) # => eax -3987 eb/jump $lookup-var-or-literal:end/disp8 -3988 } -3989 # otherwise return lookup-var(name, vars) -3990 { -3991 (lookup-var %esi *(ebp+0xc)) # => eax -3992 } -3993 $lookup-var-or-literal:end: -3994 # . restore registers -3995 5e/pop-to-esi -3996 59/pop-to-ecx -3997 # . epilogue -3998 89/<- %esp 5/r32/ebp -3999 5d/pop-to-ebp -4000 c3/return -4001 -4002 $lookup-var-or-literal:abort: -4003 (write-buffered Stderr "empty variable!") -4004 (flush Stderr) -4005 # . syscall(exit, 1) -4006 bb/copy-to-ebx 1/imm32 -4007 b8/copy-to-eax 1/imm32/exit -4008 cd/syscall 0x80/imm8 -4009 # never gets here -4010 -4011 # return first 'name' from the top (back) of 'vars' and abort if not found -4012 lookup-var: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) -4013 # . prologue -4014 55/push-ebp -4015 89/<- %ebp 4/r32/esp -4016 # var target/eax: (handle array byte) = slice-to-string(name) -4017 (slice-to-string Heap *(ebp+8)) # => eax -4018 # -4019 (lookup-var-helper %eax *(ebp+0xc)) # => eax -4020 # if (result == 0) abort -4021 3d/compare-eax-and 0/imm32 -4022 74/jump-if-= $lookup-var:abort/disp8 -4023 $lookup-var:end: -4024 # . epilogue -4025 89/<- %esp 5/r32/ebp -4026 5d/pop-to-ebp -4027 c3/return -4028 -4029 $lookup-var:abort: -4030 (write-buffered Stderr "unknown variable '") -4031 (write-slice-buffered Stderr *(ebp+8)) -4032 (write-buffered Stderr "'\n") -4033 (flush Stderr) -4034 # . syscall(exit, 1) -4035 bb/copy-to-ebx 1/imm32 -4036 b8/copy-to-eax 1/imm32/exit -4037 cd/syscall 0x80/imm8 -4038 # never gets here -4039 -4040 # return first 'name' from the top (back) of 'vars', and 0/null if not found -4041 lookup-var-helper: # name: (addr array byte), vars: (addr stack (handle var)) -> result/eax: (handle var) -4042 # pseudocode: -4043 # var curr: (addr handle var) = &vars->data[vars->top - 4] -4044 # var min = vars->data -4045 # while curr >= min -4046 # var v: (handle var) = *curr -4047 # if v->name == name -4048 # return v -4049 # return 0 -4050 # -4051 # . prologue -4052 55/push-ebp -4053 89/<- %ebp 4/r32/esp -4054 # . save registers -4055 52/push-edx -4056 53/push-ebx -4057 56/push-esi -4058 # esi = vars -4059 8b/-> *(ebp+0xc) 6/r32/esi -4060 # ebx = vars->top -4061 8b/-> *esi 3/r32/ebx -4062 # if (vars->top > vars->length) abort -4063 3b/compare 0/r32/eax *(esi+4) -4064 0f 8f/jump-if-> $lookup-var-helper:error1/disp32 -4065 # var min/edx: (addr handle var) = vars->data -4066 8d/copy-address *(esi+8) 2/r32/edx -4067 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 4] -4068 81 5/subop/subtract %ebx 4/imm32 -4069 8d/copy-address *(esi+ebx+8) 3/r32/ebx +3581 # var s/ecx: slice +3582 68/push 0/imm32/end +3583 68/push 0/imm32/start +3584 89/<- %ecx 4/r32/esp +3585 # +3586 (next-mu-token *(ebp+8) %ecx) +3587 # if slice-empty?(s) return +3588 (slice-empty? %ecx) +3589 3d/compare-eax-and 0/imm32/false +3590 75/jump-if-!= $check-no-tokens-left:end/disp8 +3591 # if (slice-starts-with?(s, '#') return +3592 # . eax = *s->start +3593 8b/-> *edx 0/r32/eax +3594 8a/copy-byte *eax 0/r32/AL +3595 81 4/subop/and %eax 0xff/imm32 +3596 # . if (eax == '#') continue +3597 3d/compare-eax-and 0x23/imm32/hash +3598 74/jump-if-= $check-no-tokens-left:end/disp8 +3599 # abort +3600 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") +3601 (rewind-stream %ecx) +3602 (write-stream 2 %ecx) +3603 (write-buffered Stderr "'\n") +3604 (flush Stderr) +3605 # . syscall(exit, 1) +3606 bb/copy-to-ebx 1/imm32 +3607 b8/copy-to-eax 1/imm32/exit +3608 cd/syscall 0x80/imm8 +3609 # never gets here +3610 $check-no-tokens-left:end: +3611 # . reclaim locals +3612 81 0/subop/add %esp 8/imm32 +3613 # . restore registers +3614 59/pop-to-ecx +3615 58/pop-to-eax +3616 # . epilogue +3617 89/<- %esp 5/r32/ebp +3618 5d/pop-to-ebp +3619 c3/return +3620 +3621 parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) +3622 # pseudocode: +3623 # var s: (addr array byte) = slice-to-string(name) +3624 # var v: (handle var) = new-var(s, 0) +3625 # v->block-depth = *Curr-block-depth # containing block depth +3626 # push(vars, v) +3627 # result = parse-mu-block(in, vars, fn) +3628 # pop(vars) +3629 # result->name = s +3630 # return result +3631 # +3632 # . prologue +3633 55/push-ebp +3634 89/<- %ebp 4/r32/esp +3635 # . save registers +3636 51/push-ecx +3637 # var s/ecx: (addr array byte) = slice-to-string(name) +3638 (slice-to-string Heap *(ebp+8)) # => eax +3639 89/<- %ecx 0/r32/eax +3640 # var type/eax: (handle tree type-id) = literal +3641 (allocate Heap *Tree-size) # => eax +3642 (zero-out %eax *Tree-size) # default type is 'literal' +3643 # var v/ecx: (handle var) = new-var(s, type) +3644 (new-var Heap %ecx %eax *Curr-block-depth 0 0) # => eax +3645 89/<- %ecx 0/r32/eax +3646 # push(vars, v) +3647 (push *(ebp+0x10) %ecx) +3648 # eax = result +3649 (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) # => eax +3650 # pop the var +3651 50/push-eax +3652 (pop *(ebp+0x10)) # => eax +3653 58/pop-to-eax +3654 # result->tag = named-block +3655 c7 0/subop/copy *eax 0/imm32/block # Stmt-tag +3656 # result->var = v +3657 89/<- *(eax+8) 1/r32/ecx # Block-var +3658 $parse-mu-named-block:end: +3659 # . restore registers +3660 59/pop-to-ecx +3661 # . epilogue +3662 89/<- %esp 5/r32/ebp +3663 5d/pop-to-ebp +3664 c3/return +3665 +3666 parse-mu-var-def: # line: (addr stream byte), vars: (addr stack (handle var)) -> result/eax: (handle stmt) +3667 # . prologue +3668 55/push-ebp +3669 89/<- %ebp 4/r32/esp +3670 # . save registers +3671 51/push-ecx +3672 52/push-edx +3673 # var word-slice/ecx: slice +3674 68/push 0/imm32/end +3675 68/push 0/imm32/start +3676 89/<- %ecx 4/r32/esp +3677 # var v/edx: (handle var) = parse-var-with-type(line) +3678 (next-mu-token *(ebp+8) %ecx) +3679 (parse-var-with-type %ecx *(ebp+8)) # => eax +3680 89/<- %edx 0/r32/eax +3681 # v->block-depth = *Curr-block-depth +3682 8b/-> *Curr-block-depth 0/r32/eax +3683 89/<- *(edx+8) 0/r32/eax +3684 # +3685 (push *(ebp+0xc) %edx) +3686 # either v has no register and there's no more to this line +3687 8b/-> *(edx+0x10) 0/r32/eax # Var-register +3688 3d/compare-eax-and 0/imm32 +3689 { +3690 75/jump-if-!= break/disp8 +3691 # v->stack-offset = *Next-local-stack-offset +3692 8b/-> *Next-local-stack-offset 0/r32/eax +3693 89/<- *(edx+0xc) 0/r32/eax # Var-stack-offset +3694 # TODO: ensure that there's nothing else on this line +3695 (new-vardef Heap %edx) # => eax +3696 eb/jump $parse-mu-var-def:end/disp8 +3697 } +3698 # or v has a register and there's more to this line +3699 { +3700 74/jump-if-= break/disp8 +3701 # ensure that the next word is '<-' +3702 (next-mu-token *(ebp+8) %ecx) +3703 (slice-equal? %ecx "<-") # => eax +3704 3d/compare-eax-and 0/imm32/false +3705 74/jump-if-= $parse-mu-var-def:abort/disp8 +3706 # +3707 (new-regvardef Heap %edx) # => eax +3708 (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc)) +3709 } +3710 $parse-mu-var-def:end: +3711 # *Next-local-stack-offset -= size-of(v) +3712 50/push-eax +3713 (size-of %edx) # => eax +3714 29/subtract-from *Next-local-stack-offset 0/r32/eax +3715 58/pop-to-eax +3716 # . reclaim locals +3717 81 0/subop/add %esp 8/imm32 +3718 # . restore registers +3719 5a/pop-to-edx +3720 59/pop-to-ecx +3721 # . epilogue +3722 89/<- %esp 5/r32/ebp +3723 5d/pop-to-ebp +3724 c3/return +3725 +3726 $parse-mu-var-def:abort: +3727 (rewind-stream *(ebp+8)) +3728 # error("register variable requires a valid instruction to initialize but got '" line "'\n") +3729 (write-buffered Stderr "register variable requires a valid instruction to initialize but got '") +3730 (flush Stderr) +3731 (write-stream 2 *(ebp+8)) +3732 (write-buffered Stderr "'\n") +3733 (flush Stderr) +3734 # . syscall(exit, 1) +3735 bb/copy-to-ebx 1/imm32 +3736 b8/copy-to-eax 1/imm32/exit +3737 cd/syscall 0x80/imm8 +3738 # never gets here +3739 +3740 test-parse-mu-var-def: +3741 # 'var n: int' +3742 # . prologue +3743 55/push-ebp +3744 89/<- %ebp 4/r32/esp +3745 # setup +3746 (clear-stream _test-input-stream) +3747 (write _test-input-stream "n: int\n") # caller has consumed the 'var' +3748 c7 0/subop/copy *Curr-block-depth 1/imm32 +3749 c7 0/subop/copy *Next-local-stack-offset -4/imm32 +3750 # var vars/ecx: (stack (addr var) 4) +3751 81 5/subop/subtract %esp 0x10/imm32 +3752 68/push 0x10/imm32/length +3753 68/push 0/imm32/top +3754 89/<- %ecx 4/r32/esp +3755 (clear-stack %ecx) +3756 # convert +3757 (parse-mu-var-def _test-input-stream %ecx) # => eax +3758 # check result +3759 (check-ints-equal *eax 2 "F - test-parse-mu-var-def/tag") # Stmt-tag is vardef +3760 8b/-> *(eax+4) 0/r32/eax # Vardef-var +3761 (check-strings-equal *eax "n" "F - test-parse-mu-var-def/var-name") # Var-name +3762 (check-ints-equal *(eax+0x10) 0 "F - test-parse-mu-var-def/var-register") # Var-register +3763 (check-ints-equal *(eax+8) 1 "F - test-parse-mu-reg-var-def/output-block-depth") # Var-block-depth +3764 (check-ints-equal *(eax+0xc) -4 "F - test-parse-mu-reg-var-def/output-stack-offset") # Var-stack-offset +3765 # ensure type is int +3766 8b/-> *(eax+4) 0/r32/eax # Var-type +3767 (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0") # Tree-left +3768 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-var-def/var-type:0") # Tree-right +3769 # globals +3770 (check-ints-equal *Next-local-stack-offset -8 "F - test-parse-mu-reg-var-def/Next-local-stack-offset") +3771 # . epilogue +3772 89/<- %esp 5/r32/ebp +3773 5d/pop-to-ebp +3774 c3/return +3775 +3776 test-parse-mu-reg-var-def: +3777 # 'var n/eax: int <- copy 0' +3778 # . prologue +3779 55/push-ebp +3780 89/<- %ebp 4/r32/esp +3781 # setup +3782 (clear-stream _test-input-stream) +3783 (write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var' +3784 c7 0/subop/copy *Curr-block-depth 1/imm32 +3785 c7 0/subop/copy *Next-local-stack-offset -4/imm32 +3786 # var vars/ecx: (stack (addr var) 4) +3787 81 5/subop/subtract %esp 0x10/imm32 +3788 68/push 0x10/imm32/length +3789 68/push 0/imm32/top +3790 89/<- %ecx 4/r32/esp +3791 (clear-stack %ecx) +3792 # convert +3793 (parse-mu-var-def _test-input-stream %ecx) # => eax +3794 # check result +3795 (check-ints-equal *eax 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is regvardef +3796 8b/-> *(eax+0xc) 0/r32/eax # Regvardef-outputs +3797 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/single-output") # List-next +3798 8b/-> *eax 0/r32/eax # Stmt-var-value +3799 (check-strings-equal *eax "n" "F - test-parse-mu-reg-var-def/output-name") # Var-name +3800 (check-strings-equal *(eax+0x10) "eax" "F - test-parse-mu-reg-var-def/output-register") # Var-register +3801 (check-ints-equal *(eax+8) 1 "F - test-parse-mu-reg-var-def/output-block-depth") # Var-block-depth +3802 (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-stack-offset") # Var-stack-offset +3803 # ensure type is int +3804 8b/-> *(eax+4) 0/r32/eax # Var-type +3805 (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-left +3806 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-right +3807 # globals +3808 (check-ints-equal *Next-local-stack-offset -8 "F - test-parse-mu-reg-var-def/Next-local-stack-offset") +3809 # . epilogue +3810 89/<- %esp 5/r32/ebp +3811 5d/pop-to-ebp +3812 c3/return +3813 +3814 parse-mu-stmt: # line: (addr stream byte), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) +3815 # pseudocode: +3816 # var name: slice +3817 # result = allocate(Heap, Stmt-size) +3818 # if stmt-has-outputs?(line) +3819 # while true +3820 # name = next-mu-token(line) +3821 # if (name == '<-') break +3822 # assert(is-identifier?(name)) +3823 # var v: (handle var) = lookup-or-define-var(name, vars, fn) # regular stmts may define vars in fn outputs +3824 # result->outputs = append(result->outputs, v) +3825 # add-operation-and-inputs-to-stmt(result, line, vars) +3826 # +3827 # . prologue +3828 55/push-ebp +3829 89/<- %ebp 4/r32/esp +3830 # . save registers +3831 51/push-ecx +3832 52/push-edx +3833 57/push-edi +3834 # var name/ecx: slice +3835 68/push 0/imm32/end +3836 68/push 0/imm32/start +3837 89/<- %ecx 4/r32/esp +3838 # var is-deref?/edx: boolean = false +3839 ba/copy-to-edx 0/imm32/false +3840 # result/edi: (handle stmt) +3841 (allocate Heap *Stmt-size) # => eax +3842 (zero-out %eax *Stmt-size) +3843 89/<- %edi 0/r32/eax +3844 # result->tag = 1/stmt +3845 c7 0/subop/copy *edi 1/imm32/stmt1 # Stmt-tag +3846 { +3847 (stmt-has-outputs? *(ebp+8)) +3848 3d/compare-eax-and 0/imm32/false +3849 0f 84/jump-if-= break/disp32 +3850 { +3851 $parse-mu-stmt:read-outputs: +3852 # name = next-mu-token(line) +3853 (next-mu-token *(ebp+8) %ecx) +3854 # if slice-empty?(word-slice) break +3855 (slice-empty? %ecx) # => eax +3856 3d/compare-eax-and 0/imm32/false +3857 0f 85/jump-if-!= break/disp32 +3858 # if (name == "<-") break +3859 (slice-equal? %ecx "<-") # => eax +3860 3d/compare-eax-and 0/imm32/false +3861 0f 85/jump-if-!= break/disp32 +3862 # is-deref? = false +3863 ba/copy-to-edx 0/imm32/false +3864 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? +3865 8b/-> *ecx 0/r32/eax # Slice-start +3866 8a/copy-byte *eax 0/r32/AL +3867 81 4/subop/and %eax 0xff/imm32 +3868 3d/compare-eax-and 0x2a/imm32/asterisk +3869 { +3870 75/jump-if-!= break/disp8 +3871 ff 0/subop/increment *ecx +3872 ba/copy-to-edx 1/imm32/true +3873 } +3874 # assert(is-identifier?(name)) +3875 (is-identifier? %ecx) # => eax +3876 3d/compare-eax-and 0/imm32/false +3877 0f 84/jump-if-= $parse-mu-stmt:abort/disp32 +3878 # result->outputs = new stmt-var(lookup(name, vars, fn), result->outputs, is-deref?) +3879 (lookup-or-define-var %ecx *(ebp+0xc) *(ebp+0x10)) # => eax +3880 (append-stmt-var Heap %eax *(edi+0xc) %edx) # Stmt1-outputs => eax +3881 89/<- *(edi+0xc) 0/r32/eax # Stmt1-outputs +3882 e9/jump loop/disp32 +3883 } +3884 } +3885 (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc)) +3886 $parse-mu-stmt:end: +3887 # return result +3888 89/<- %eax 7/r32/edi +3889 # . reclaim locals +3890 81 0/subop/add %esp 8/imm32 +3891 # . restore registers +3892 5f/pop-to-edi +3893 5a/pop-to-edx +3894 59/pop-to-ecx +3895 # . epilogue +3896 89/<- %esp 5/r32/ebp +3897 5d/pop-to-ebp +3898 c3/return +3899 +3900 $parse-mu-stmt:abort: +3901 # error("invalid identifier '" name "'\n") +3902 (write-buffered Stderr "invalid identifier '") +3903 (write-slice-buffered Stderr %ecx) +3904 (write-buffered Stderr "'\n") +3905 (flush Stderr) +3906 # . syscall(exit, 1) +3907 bb/copy-to-ebx 1/imm32 +3908 b8/copy-to-eax 1/imm32/exit +3909 cd/syscall 0x80/imm8 +3910 # never gets here +3911 +3912 add-operation-and-inputs-to-stmt: # stmt: (handle stmt), line: (addr stream byte), vars: (addr stack (handle var)) +3913 # pseudocode: +3914 # stmt->name = slice-to-string(next-mu-token(line)) +3915 # while true +3916 # name = next-mu-token(line) +3917 # v = lookup-var-or-literal(name) +3918 # stmt->inouts = append(stmt->inouts, v) +3919 # +3920 # . prologue +3921 55/push-ebp +3922 89/<- %ebp 4/r32/esp +3923 # . save registers +3924 50/push-eax +3925 51/push-ecx +3926 52/push-edx +3927 57/push-edi +3928 # edi = stmt +3929 8b/-> *(ebp+8) 7/r32/edi +3930 # var name/ecx: slice +3931 68/push 0/imm32/end +3932 68/push 0/imm32/start +3933 89/<- %ecx 4/r32/esp +3934 # var is-deref?/edx: boolean = false +3935 ba/copy-to-edx 0/imm32/false +3936 $add-operation-and-inputs-to-stmt:read-operation: +3937 (next-mu-token *(ebp+0xc) %ecx) +3938 (slice-to-string Heap %ecx) # => eax +3939 89/<- *(edi+4) 0/r32/eax # Stmt1-operation or Regvardef-operation +3940 { +3941 $add-operation-and-inputs-to-stmt:read-inouts: +3942 # name = next-mu-token(line) +3943 (next-mu-token *(ebp+0xc) %ecx) +3944 # if slice-empty?(word-slice) break +3945 (slice-empty? %ecx) # => eax +3946 3d/compare-eax-and 0/imm32/false +3947 0f 85/jump-if-!= break/disp32 +3948 # if (name == "<-") abort +3949 (slice-equal? %ecx "<-") +3950 3d/compare-eax-and 0/imm32/false +3951 0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32 +3952 # is-deref? = false +3953 ba/copy-to-edx 0/imm32/false +3954 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? +3955 8b/-> *ecx 0/r32/eax # Slice-start +3956 8a/copy-byte *eax 0/r32/AL +3957 81 4/subop/and %eax 0xff/imm32 +3958 3d/compare-eax-and 0x2a/imm32/asterisk +3959 { +3960 75/jump-if-!= break/disp8 +3961 ff 0/subop/increment *ecx +3962 ba/copy-to-edx 1/imm32/true +3963 } +3964 (lookup-var-or-literal %ecx *(ebp+0x10)) # => eax +3965 (append-list Heap %eax *(edi+8)) # Stmt1-inouts or Regvardef-inouts => eax +3966 89/<- *(edi+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts +3967 e9/jump loop/disp32 +3968 } +3969 $add-operation-and-inputs-to-stmt:end: +3970 # . reclaim locals +3971 81 0/subop/add %esp 8/imm32 +3972 # . restore registers +3973 5f/pop-to-edi +3974 5a/pop-to-edx +3975 59/pop-to-ecx +3976 58/pop-to-eax +3977 # . epilogue +3978 89/<- %esp 5/r32/ebp +3979 5d/pop-to-ebp +3980 c3/return +3981 +3982 $add-operation-and-inputs-to-stmt:abort: +3983 # error("invalid statement '" line "'\n") +3984 (rewind-stream *(ebp+8)) +3985 (write-buffered Stderr "invalid identifier '") +3986 (flush Stderr) +3987 (write-stream 2 *(ebp+8)) +3988 (write-buffered Stderr "'\n") +3989 (flush Stderr) +3990 # . syscall(exit, 1) +3991 bb/copy-to-ebx 1/imm32 +3992 b8/copy-to-eax 1/imm32/exit +3993 cd/syscall 0x80/imm8 +3994 # never gets here +3995 +3996 stmt-has-outputs?: # line: (addr stream byte) -> result/eax: boolean +3997 # . prologue +3998 55/push-ebp +3999 89/<- %ebp 4/r32/esp +4000 # . save registers +4001 51/push-ecx +4002 # var word-slice/ecx: slice +4003 68/push 0/imm32/end +4004 68/push 0/imm32/start +4005 89/<- %ecx 4/r32/esp +4006 # result = false +4007 b8/copy-to-eax 0/imm32/false +4008 (rewind-stream *(ebp+8)) +4009 { +4010 (next-mu-token *(ebp+8) %ecx) +4011 # if slice-empty?(word-slice) break +4012 (slice-empty? %ecx) +4013 3d/compare-eax-and 0/imm32/false +4014 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) +4015 0f 85/jump-if-!= break/disp32 +4016 # if slice-starts-with?(word-slice, '#') break +4017 # . eax = *word-slice->start +4018 8b/-> *ecx 0/r32/eax +4019 8a/copy-byte *eax 0/r32/AL +4020 81 4/subop/and %eax 0xff/imm32 +4021 # . if (eax == '#') break +4022 3d/compare-eax-and 0x23/imm32/hash +4023 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) +4024 0f 84/jump-if-= break/disp32 +4025 # if slice-equal?(word-slice, '<-') return true +4026 (slice-equal? %ecx "<-") +4027 3d/compare-eax-and 0/imm32/false +4028 74/jump-if-= loop/disp8 +4029 b8/copy-to-eax 1/imm32/true +4030 } +4031 $stmt-has-outputs:end: +4032 (rewind-stream *(ebp+8)) +4033 # . reclaim locals +4034 81 0/subop/add %esp 8/imm32 +4035 # . restore registers +4036 59/pop-to-ecx +4037 # . epilogue +4038 89/<- %esp 5/r32/ebp +4039 5d/pop-to-ebp +4040 c3/return +4041 +4042 # if 'name' starts with a digit, create a new literal var for it +4043 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found +4044 lookup-var-or-literal: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) +4045 # . prologue +4046 55/push-ebp +4047 89/<- %ebp 4/r32/esp +4048 # . save registers +4049 51/push-ecx +4050 56/push-esi +4051 # esi = name +4052 8b/-> *(ebp+8) 6/r32/esi +4053 # if slice-empty?(name) abort +4054 (slice-empty? %esi) # => eax +4055 3d/compare-eax-and 0/imm32/false +4056 0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32 +4057 # var c/ecx: byte = *name->start +4058 8b/-> *esi 1/r32/ecx +4059 8a/copy-byte *ecx 1/r32/CL +4060 81 4/subop/and %ecx 0xff/imm32 +4061 # if is-decimal-digit?(c) return new var(name) +4062 { +4063 (is-decimal-digit? %ecx) # => eax +4064 81 7/subop/compare %eax 0/imm32/false +4065 74/jump-if-= break/disp8 +4066 (new-literal-integer Heap %esi) # => eax +4067 eb/jump $lookup-var-or-literal:end/disp8 +4068 } +4069 # else if (c == '"') return new var(name) 4070 { -4071 # if (curr < min) return 0 -4072 39/compare %ebx 2/r32/edx -4073 b8/copy-to-eax 0/imm32 -4074 0f 82/jump-if-addr< break/disp32 -4075 # var v/eax: (handle var) = *curr -4076 8b/-> *ebx 0/r32/eax -4077 # if (v->name == name) return v -4078 (string-equal? *eax *(ebp+8)) # Var-name -4079 3d/compare-eax-and 0/imm32/false -4080 8b/-> *ebx 0/r32/eax -4081 75/jump-if-!= break/disp8 -4082 # curr -= 4 -4083 81 5/subop/subtract %ebx 4/imm32 -4084 e9/jump loop/disp32 -4085 } -4086 $lookup-var-helper:end: -4087 # . restore registers -4088 5e/pop-to-esi -4089 5b/pop-to-ebx -4090 5a/pop-to-edx -4091 # . epilogue -4092 89/<- %esp 5/r32/ebp -4093 5d/pop-to-ebp -4094 c3/return -4095 -4096 $lookup-var-helper:error1: -4097 (write-buffered Stderr "malformed stack when looking up '") -4098 (write-slice-buffered Stderr *(ebp+8)) -4099 (write-buffered Stderr "'\n") -4100 (flush Stderr) -4101 # . syscall(exit, 1) -4102 bb/copy-to-ebx 1/imm32 -4103 b8/copy-to-eax 1/imm32/exit -4104 cd/syscall 0x80/imm8 -4105 # never gets here -4106 -4107 # return first 'name' from the top (back) of 'vars' and create a new var for a fn output if not found -4108 lookup-or-define-var: # name: (addr slice), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle var) -4109 # . prologue -4110 55/push-ebp -4111 89/<- %ebp 4/r32/esp -4112 # . save registers -4113 51/push-ecx -4114 # var target/ecx: (handle array byte) = slice-to-string(name) -4115 (slice-to-string Heap *(ebp+8)) # => eax -4116 89/<- %ecx 0/r32/eax -4117 # -4118 (lookup-var-helper %ecx *(ebp+0xc)) # => eax -4119 { -4120 # if (result != 0) return -4121 3d/compare-eax-and 0/imm32 -4122 75/jump-if-!= break/disp8 -4123 # if name is one of fn's outputs, return it -4124 { -4125 (find-in-function-outputs *(ebp+0x10) %ecx) # => eax -4126 3d/compare-eax-and 0/imm32 -4127 # otherwise abort -4128 0f 84/jump-if-!= $lookup-var:abort/disp32 -4129 } -4130 } -4131 $lookup-or-define-var:end: -4132 # . restore registers -4133 59/pop-to-ecx -4134 # . epilogue -4135 89/<- %esp 5/r32/ebp -4136 5d/pop-to-ebp -4137 c3/return -4138 -4139 find-in-function-outputs: # fn: (handle function), name: (handle array byte) -> result/eax: (handle var) -4140 # . prologue -4141 55/push-ebp -4142 89/<- %ebp 4/r32/esp -4143 # . save registers -4144 51/push-ecx -4145 # var curr/ecx: (handle list var) = fn->outputs -4146 8b/-> *(ebp+8) 1/r32/ecx -4147 8b/-> *(ecx+0xc) 1/r32/ecx -4148 # while curr != null -4149 { -4150 81 7/subop/compare %ecx 0/imm32 -4151 74/jump-if-= break/disp8 -4152 # var v: (handle var) = *curr -4153 8b/-> *ecx 0/r32/eax # List-value -4154 # if (curr->name == name) return curr -4155 50/push-eax -4156 (string-equal? *eax *(ebp+0xc)) -4157 3d/compare-eax-and 0/imm32/false -4158 58/pop-to-eax -4159 75/jump-if-!= $find-in-function-outputs:end/disp8 -4160 # curr = curr->next -4161 8b/-> *(ecx+4) 1/r32/ecx # List-next -4162 eb/jump loop/disp8 -4163 } -4164 b8/copy-to-eax 0/imm32 -4165 $find-in-function-outputs:end: -4166 # . restore registers -4167 59/pop-to-ecx -4168 # . epilogue -4169 89/<- %esp 5/r32/ebp -4170 5d/pop-to-ebp -4171 c3/return -4172 -4173 test-parse-mu-stmt: -4174 # . prologue -4175 55/push-ebp -4176 89/<- %ebp 4/r32/esp -4177 # setup -4178 (clear-stream _test-input-stream) -4179 (write _test-input-stream "increment n\n") -4180 # var vars/ecx: (stack (addr var) 4) -4181 81 5/subop/subtract %esp 0x10/imm32 -4182 68/push 0x10/imm32/length -4183 68/push 0/imm32/top -4184 89/<- %ecx 4/r32/esp -4185 (clear-stack %ecx) -4186 # var v/edx: var -4187 81 5/subop/subtract %esp 0x14/imm32 # Var-size -4188 89/<- %edx 4/r32/esp -4189 (zero-out %edx 0x14) # Var-size -4190 # v->name = "n" -4191 c7 0/subop/copy *edx "n"/imm32 # Var-name -4192 # -4193 (push %ecx %edx) -4194 # convert -4195 (parse-mu-stmt _test-input-stream %ecx) # => eax -4196 # check result -4197 (check-ints-equal *eax 1 "F - test-parse-mu-stmt/tag") # Stmt-tag is Stmt1 -4198 (check-strings-equal *(eax+4) "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation -4199 # edx: (handle list var) = result->inouts -4200 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts -4201 # ebx: (handle var) = result->inouts->value -4202 8b/-> *edx 3/r32/ebx # List-value -4203 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt/inout:0") # Var-name -4204 # . epilogue -4205 89/<- %esp 5/r32/ebp -4206 5d/pop-to-ebp -4207 c3/return -4208 -4209 test-parse-mu-stmt-with-comma: -4210 # . prologue -4211 55/push-ebp -4212 89/<- %ebp 4/r32/esp -4213 # setup -4214 (clear-stream _test-input-stream) -4215 (write _test-input-stream "copy-to n, 3\n") -4216 # var vars/ecx: (stack (addr var) 4) -4217 81 5/subop/subtract %esp 0x10/imm32 -4218 68/push 0x10/imm32/length -4219 68/push 0/imm32/top -4220 89/<- %ecx 4/r32/esp -4221 (clear-stack %ecx) -4222 # var v/edx: var -4223 81 5/subop/subtract %esp 0x14/imm32 # Var-size -4224 89/<- %edx 4/r32/esp -4225 (zero-out %edx 0x14) # Var-size -4226 # v->name = "n" -4227 c7 0/subop/copy *edx "n"/imm32 # Var-name -4228 # -4229 (push %ecx %edx) -4230 # convert -4231 (parse-mu-stmt _test-input-stream %ecx) # => eax -4232 # check result -4233 (check-ints-equal *eax 1 "F - test-parse-mu-stmt-with-comma/tag") # Stmt-tag is Stmt1 -4234 (check-strings-equal *(eax+4) "copy-to" "F - test-parse-mu-stmt-with-comma/name") # Stmt1-operation -4235 # edx: (handle list var) = result->inouts -4236 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts -4237 # ebx: (handle var) = result->inouts->value -4238 8b/-> *edx 3/r32/ebx # List-value -4239 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt-with-comma/inout:0") # Var-name -4240 # . epilogue -4241 89/<- %esp 5/r32/ebp -4242 5d/pop-to-ebp -4243 c3/return -4244 -4245 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) -4246 # . prologue -4247 55/push-ebp -4248 89/<- %ebp 4/r32/esp -4249 # . save registers -4250 51/push-ecx -4251 # -4252 (allocate *(ebp+8) *Function-size) # => eax -4253 8b/-> *(ebp+0xc) 1/r32/ecx -4254 89/<- *eax 1/r32/ecx # Function-name -4255 8b/-> *(ebp+0x10) 1/r32/ecx -4256 89/<- *(eax+4) 1/r32/ecx # Function-subx-name -4257 8b/-> *(ebp+0x14) 1/r32/ecx -4258 89/<- *(eax+8) 1/r32/ecx # Function-inouts -4259 8b/-> *(ebp+0x18) 1/r32/ecx -4260 89/<- *(eax+0xc) 1/r32/ecx # Function-outputs -4261 8b/-> *(ebp+0x1c) 1/r32/ecx -4262 89/<- *(eax+0x10) 1/r32/ecx # Function-body -4263 8b/-> *(ebp+0x20) 1/r32/ecx -4264 89/<- *(eax+0x14) 1/r32/ecx # Function-next -4265 $new-function:end: -4266 # . restore registers -4267 59/pop-to-ecx -4268 # . epilogue -4269 89/<- %esp 5/r32/ebp -4270 5d/pop-to-ebp -4271 c3/return -4272 -4273 new-var: # ad: (addr allocation-descriptor), name: (addr array byte), type: (addr tree type-id), block: int, stack-offset: int, register: (addr array byte) -> result/eax: (handle var) -4274 # . prologue -4275 55/push-ebp -4276 89/<- %ebp 4/r32/esp -4277 # . save registers -4278 51/push-ecx +4071 81 7/subop/compare %ecx 0x22/imm32/dquote +4072 75/jump-if-!= break/disp8 +4073 (new-literal-string Heap %esi) # => eax +4074 eb/jump $lookup-var-or-literal:end/disp8 +4075 } +4076 # otherwise return lookup-var(name, vars) +4077 { +4078 (lookup-var %esi *(ebp+0xc)) # => eax +4079 } +4080 $lookup-var-or-literal:end: +4081 # . restore registers +4082 5e/pop-to-esi +4083 59/pop-to-ecx +4084 # . epilogue +4085 89/<- %esp 5/r32/ebp +4086 5d/pop-to-ebp +4087 c3/return +4088 +4089 $lookup-var-or-literal:abort: +4090 (write-buffered Stderr "empty variable!") +4091 (flush Stderr) +4092 # . syscall(exit, 1) +4093 bb/copy-to-ebx 1/imm32 +4094 b8/copy-to-eax 1/imm32/exit +4095 cd/syscall 0x80/imm8 +4096 # never gets here +4097 +4098 # return first 'name' from the top (back) of 'vars' and abort if not found +4099 lookup-var: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) +4100 # . prologue +4101 55/push-ebp +4102 89/<- %ebp 4/r32/esp +4103 # var target/eax: (handle array byte) = slice-to-string(name) +4104 (slice-to-string Heap *(ebp+8)) # => eax +4105 # +4106 (lookup-var-helper %eax *(ebp+0xc)) # => eax +4107 # if (result == 0) abort +4108 3d/compare-eax-and 0/imm32 +4109 74/jump-if-= $lookup-var:abort/disp8 +4110 $lookup-var:end: +4111 # . epilogue +4112 89/<- %esp 5/r32/ebp +4113 5d/pop-to-ebp +4114 c3/return +4115 +4116 $lookup-var:abort: +4117 (write-buffered Stderr "unknown variable '") +4118 (write-slice-buffered Stderr *(ebp+8)) +4119 (write-buffered Stderr "'\n") +4120 (flush Stderr) +4121 # . syscall(exit, 1) +4122 bb/copy-to-ebx 1/imm32 +4123 b8/copy-to-eax 1/imm32/exit +4124 cd/syscall 0x80/imm8 +4125 # never gets here +4126 +4127 # return first 'name' from the top (back) of 'vars', and 0/null if not found +4128 lookup-var-helper: # name: (addr array byte), vars: (addr stack (handle var)) -> result/eax: (handle var) +4129 # pseudocode: +4130 # var curr: (addr handle var) = &vars->data[vars->top - 4] +4131 # var min = vars->data +4132 # while curr >= min +4133 # var v: (handle var) = *curr +4134 # if v->name == name +4135 # return v +4136 # return 0 +4137 # +4138 # . prologue +4139 55/push-ebp +4140 89/<- %ebp 4/r32/esp +4141 # . save registers +4142 52/push-edx +4143 53/push-ebx +4144 56/push-esi +4145 # esi = vars +4146 8b/-> *(ebp+0xc) 6/r32/esi +4147 # ebx = vars->top +4148 8b/-> *esi 3/r32/ebx +4149 # if (vars->top > vars->length) abort +4150 3b/compare 0/r32/eax *(esi+4) +4151 0f 8f/jump-if-> $lookup-var-helper:error1/disp32 +4152 # var min/edx: (addr handle var) = vars->data +4153 8d/copy-address *(esi+8) 2/r32/edx +4154 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 4] +4155 81 5/subop/subtract %ebx 4/imm32 +4156 8d/copy-address *(esi+ebx+8) 3/r32/ebx +4157 { +4158 # if (curr < min) return 0 +4159 39/compare %ebx 2/r32/edx +4160 b8/copy-to-eax 0/imm32 +4161 0f 82/jump-if-addr< break/disp32 +4162 # var v/eax: (handle var) = *curr +4163 8b/-> *ebx 0/r32/eax +4164 # if (v->name == name) return v +4165 (string-equal? *eax *(ebp+8)) # Var-name +4166 3d/compare-eax-and 0/imm32/false +4167 8b/-> *ebx 0/r32/eax +4168 75/jump-if-!= break/disp8 +4169 # curr -= 4 +4170 81 5/subop/subtract %ebx 4/imm32 +4171 e9/jump loop/disp32 +4172 } +4173 $lookup-var-helper:end: +4174 # . restore registers +4175 5e/pop-to-esi +4176 5b/pop-to-ebx +4177 5a/pop-to-edx +4178 # . epilogue +4179 89/<- %esp 5/r32/ebp +4180 5d/pop-to-ebp +4181 c3/return +4182 +4183 $lookup-var-helper:error1: +4184 (write-buffered Stderr "malformed stack when looking up '") +4185 (write-slice-buffered Stderr *(ebp+8)) +4186 (write-buffered Stderr "'\n") +4187 (flush Stderr) +4188 # . syscall(exit, 1) +4189 bb/copy-to-ebx 1/imm32 +4190 b8/copy-to-eax 1/imm32/exit +4191 cd/syscall 0x80/imm8 +4192 # never gets here +4193 +4194 # return first 'name' from the top (back) of 'vars' and create a new var for a fn output if not found +4195 lookup-or-define-var: # name: (addr slice), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle var) +4196 # . prologue +4197 55/push-ebp +4198 89/<- %ebp 4/r32/esp +4199 # . save registers +4200 51/push-ecx +4201 # var target/ecx: (handle array byte) = slice-to-string(name) +4202 (slice-to-string Heap *(ebp+8)) # => eax +4203 89/<- %ecx 0/r32/eax +4204 # +4205 (lookup-var-helper %ecx *(ebp+0xc)) # => eax +4206 { +4207 # if (result != 0) return +4208 3d/compare-eax-and 0/imm32 +4209 75/jump-if-!= break/disp8 +4210 # if name is one of fn's outputs, return it +4211 { +4212 (find-in-function-outputs *(ebp+0x10) %ecx) # => eax +4213 3d/compare-eax-and 0/imm32 +4214 # otherwise abort +4215 0f 84/jump-if-!= $lookup-var:abort/disp32 +4216 } +4217 } +4218 $lookup-or-define-var:end: +4219 # . restore registers +4220 59/pop-to-ecx +4221 # . epilogue +4222 89/<- %esp 5/r32/ebp +4223 5d/pop-to-ebp +4224 c3/return +4225 +4226 find-in-function-outputs: # fn: (handle function), name: (handle array byte) -> result/eax: (handle var) +4227 # . prologue +4228 55/push-ebp +4229 89/<- %ebp 4/r32/esp +4230 # . save registers +4231 51/push-ecx +4232 # var curr/ecx: (handle list var) = fn->outputs +4233 8b/-> *(ebp+8) 1/r32/ecx +4234 8b/-> *(ecx+0xc) 1/r32/ecx +4235 # while curr != null +4236 { +4237 81 7/subop/compare %ecx 0/imm32 +4238 74/jump-if-= break/disp8 +4239 # var v: (handle var) = *curr +4240 8b/-> *ecx 0/r32/eax # List-value +4241 # if (curr->name == name) return curr +4242 50/push-eax +4243 (string-equal? *eax *(ebp+0xc)) +4244 3d/compare-eax-and 0/imm32/false +4245 58/pop-to-eax +4246 75/jump-if-!= $find-in-function-outputs:end/disp8 +4247 # curr = curr->next +4248 8b/-> *(ecx+4) 1/r32/ecx # List-next +4249 eb/jump loop/disp8 +4250 } +4251 b8/copy-to-eax 0/imm32 +4252 $find-in-function-outputs:end: +4253 # . restore registers +4254 59/pop-to-ecx +4255 # . epilogue +4256 89/<- %esp 5/r32/ebp +4257 5d/pop-to-ebp +4258 c3/return +4259 +4260 test-parse-mu-stmt: +4261 # . prologue +4262 55/push-ebp +4263 89/<- %ebp 4/r32/esp +4264 # setup +4265 (clear-stream _test-input-stream) +4266 (write _test-input-stream "increment n\n") +4267 # var vars/ecx: (stack (addr var) 4) +4268 81 5/subop/subtract %esp 0x10/imm32 +4269 68/push 0x10/imm32/length +4270 68/push 0/imm32/top +4271 89/<- %ecx 4/r32/esp +4272 (clear-stack %ecx) +4273 # var v/edx: var +4274 81 5/subop/subtract %esp 0x14/imm32 # Var-size +4275 89/<- %edx 4/r32/esp +4276 (zero-out %edx 0x14) # Var-size +4277 # v->name = "n" +4278 c7 0/subop/copy *edx "n"/imm32 # Var-name 4279 # -4280 (allocate *(ebp+8) *Var-size) # => eax -4281 8b/-> *(ebp+0xc) 1/r32/ecx -4282 89/<- *eax 1/r32/ecx # Var-name -4283 8b/-> *(ebp+0x10) 1/r32/ecx -4284 89/<- *(eax+4) 1/r32/ecx # Var-type -4285 8b/-> *(ebp+0x14) 1/r32/ecx -4286 89/<- *(eax+8) 1/r32/ecx # Var-block-depth -4287 8b/-> *(ebp+0x18) 1/r32/ecx -4288 89/<- *(eax+0xc) 1/r32/ecx # Var-stack-offset -4289 8b/-> *(ebp+0x1c) 1/r32/ecx -4290 89/<- *(eax+0x10) 1/r32/ecx # Var-register -4291 $new-var:end: -4292 # . restore registers -4293 59/pop-to-ecx -4294 # . epilogue -4295 89/<- %esp 5/r32/ebp -4296 5d/pop-to-ebp -4297 c3/return -4298 -4299 new-literal-integer: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -4300 # . prologue -4301 55/push-ebp -4302 89/<- %ebp 4/r32/esp -4303 # . save registers -4304 51/push-ecx -4305 # if (!is-hex-int?(name)) abort -4306 (is-hex-int? *(ebp+0xc)) # => eax -4307 3d/compare-eax-and 0/imm32/false -4308 0f 84/jump-if-= $new-literal-integer:abort/disp32 -4309 # var s/ecx: (addr array byte) -4310 (slice-to-string Heap *(ebp+0xc)) # => eax -4311 89/<- %ecx 0/r32/eax -4312 # result/ecx = new var(s) -4313 (allocate *(ebp+8) *Var-size) # => eax -4314 (zero-out %eax *Var-size) -4315 89/<- *eax 1/r32/ecx # Var-name -4316 89/<- %ecx 0/r32/eax -4317 # result->type = new type() -4318 (allocate *(ebp+8) *Tree-size) # => eax -4319 (zero-out %eax *Tree-size) # default type is 'literal' -4320 89/<- *(ecx+4) 0/r32/eax # Var-type -4321 # move result to eax -4322 89/<- %eax 1/r32/ecx -4323 $new-literal-integer:end: -4324 # . restore registers -4325 59/pop-to-ecx -4326 # . epilogue -4327 89/<- %esp 5/r32/ebp -4328 5d/pop-to-ebp -4329 c3/return -4330 -4331 $new-literal-integer:abort: -4332 (write-buffered Stderr "variable cannot begin with a digit '") -4333 (write-slice-buffered Stderr *(ebp+0xc)) -4334 (write-buffered Stderr "'\n") -4335 (flush Stderr) -4336 # . syscall(exit, 1) -4337 bb/copy-to-ebx 1/imm32 -4338 b8/copy-to-eax 1/imm32/exit -4339 cd/syscall 0x80/imm8 -4340 # never gets here -4341 -4342 new-literal-string: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -4343 # . prologue -4344 55/push-ebp -4345 89/<- %ebp 4/r32/esp -4346 # . save registers -4347 51/push-ecx -4348 # var s/ecx: (addr array byte) -4349 (slice-to-string Heap *(ebp+0xc)) # => eax -4350 89/<- %ecx 0/r32/eax -4351 # result/ecx = new var(s) -4352 (allocate *(ebp+8) *Var-size) # => eax -4353 (zero-out %eax *Var-size) -4354 89/<- *eax 1/r32/ecx # Var-name -4355 89/<- %ecx 0/r32/eax -4356 # result->type = new type() -4357 (allocate *(ebp+8) *Tree-size) # => eax -4358 (zero-out %eax *Tree-size) # default type is 'literal' -4359 89/<- *(ecx+4) 0/r32/eax # Var-type -4360 # move result to eax -4361 89/<- %eax 1/r32/ecx -4362 $new-literal-string:end: -4363 # . restore registers -4364 59/pop-to-ecx -4365 # . epilogue -4366 89/<- %esp 5/r32/ebp -4367 5d/pop-to-ebp -4368 c3/return -4369 -4370 new-label: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -4371 # . prologue -4372 55/push-ebp -4373 89/<- %ebp 4/r32/esp -4374 # . save registers -4375 51/push-ecx -4376 # var s/ecx: (addr array byte) -4377 (slice-to-string Heap *(ebp+0xc)) # => eax -4378 89/<- %ecx 0/r32/eax -4379 # -4380 (allocate *(ebp+8) *Var-size) # => eax -4381 89/<- *eax 1/r32/ecx # Var-name -4382 89/<- %ecx 0/r32/eax -4383 (allocate *(ebp+8) *Tree-size) # => eax -4384 (zero-out %eax *Tree-size) # labels are literals -4385 89/<- *(ecx+4) 0/r32/eax # Var-type -4386 89/<- %eax 1/r32/ecx -4387 c7 0/subop/copy *(eax+8) 0/imm32 # Var-block-depth -4388 c7 0/subop/copy *(eax+0xc) 0/imm32 # Var-stack-offset -4389 c7 0/subop/copy *(eax+0x10) 0/imm32 # Var-register -4390 $new-label:end: -4391 # . restore registers -4392 59/pop-to-ecx -4393 # . epilogue -4394 89/<- %esp 5/r32/ebp -4395 5d/pop-to-ebp -4396 c3/return -4397 -4398 new-block: # ad: (addr allocation-descriptor), data: (handle list statement) -> result/eax: (handle statement) -4399 # . prologue -4400 55/push-ebp -4401 89/<- %ebp 4/r32/esp -4402 # . save registers -4403 51/push-ecx -4404 # -4405 (allocate *(ebp+8) *Stmt-size) # => eax -4406 (zero-out %eax *Stmt-size) -4407 c7 0/subop/copy *eax 0/imm32/tag/block # Stmt-tag -4408 8b/-> *(ebp+0xc) 1/r32/ecx -4409 89/<- *(eax+4) 1/r32/ecx # Block-statements -4410 $new-block:end: +4280 (push %ecx %edx) +4281 # convert +4282 (parse-mu-stmt _test-input-stream %ecx) # => eax +4283 # check result +4284 (check-ints-equal *eax 1 "F - test-parse-mu-stmt/tag") # Stmt-tag is Stmt1 +4285 (check-strings-equal *(eax+4) "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation +4286 # edx: (handle list var) = result->inouts +4287 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts +4288 # ebx: (handle var) = result->inouts->value +4289 8b/-> *edx 3/r32/ebx # Stmt-var-value +4290 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt/inout:0") # Var-name +4291 # . epilogue +4292 89/<- %esp 5/r32/ebp +4293 5d/pop-to-ebp +4294 c3/return +4295 +4296 test-parse-mu-stmt-with-comma: +4297 # . prologue +4298 55/push-ebp +4299 89/<- %ebp 4/r32/esp +4300 # setup +4301 (clear-stream _test-input-stream) +4302 (write _test-input-stream "copy-to n, 3\n") +4303 # var vars/ecx: (stack (addr var) 4) +4304 81 5/subop/subtract %esp 0x10/imm32 +4305 68/push 0x10/imm32/length +4306 68/push 0/imm32/top +4307 89/<- %ecx 4/r32/esp +4308 (clear-stack %ecx) +4309 # var v/edx: var +4310 81 5/subop/subtract %esp 0x14/imm32 # Var-size +4311 89/<- %edx 4/r32/esp +4312 (zero-out %edx 0x14) # Var-size +4313 # v->name = "n" +4314 c7 0/subop/copy *edx "n"/imm32 # Var-name +4315 # +4316 (push %ecx %edx) +4317 # convert +4318 (parse-mu-stmt _test-input-stream %ecx) # => eax +4319 # check result +4320 (check-ints-equal *eax 1 "F - test-parse-mu-stmt-with-comma/tag") # Stmt-tag is Stmt1 +4321 (check-strings-equal *(eax+4) "copy-to" "F - test-parse-mu-stmt-with-comma/name") # Stmt1-operation +4322 # edx: (handle list var) = result->inouts +4323 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts +4324 # ebx: (handle var) = result->inouts->value +4325 8b/-> *edx 3/r32/ebx # Stmt-var-value +4326 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt-with-comma/inout:0") # Var-name +4327 # . epilogue +4328 89/<- %esp 5/r32/ebp +4329 5d/pop-to-ebp +4330 c3/return +4331 +4332 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) +4333 # . prologue +4334 55/push-ebp +4335 89/<- %ebp 4/r32/esp +4336 # . save registers +4337 51/push-ecx +4338 # +4339 (allocate *(ebp+8) *Function-size) # => eax +4340 8b/-> *(ebp+0xc) 1/r32/ecx +4341 89/<- *eax 1/r32/ecx # Function-name +4342 8b/-> *(ebp+0x10) 1/r32/ecx +4343 89/<- *(eax+4) 1/r32/ecx # Function-subx-name +4344 8b/-> *(ebp+0x14) 1/r32/ecx +4345 89/<- *(eax+8) 1/r32/ecx # Function-inouts +4346 8b/-> *(ebp+0x18) 1/r32/ecx +4347 89/<- *(eax+0xc) 1/r32/ecx # Function-outputs +4348 8b/-> *(ebp+0x1c) 1/r32/ecx +4349 89/<- *(eax+0x10) 1/r32/ecx # Function-body +4350 8b/-> *(ebp+0x20) 1/r32/ecx +4351 89/<- *(eax+0x14) 1/r32/ecx # Function-next +4352 $new-function:end: +4353 # . restore registers +4354 59/pop-to-ecx +4355 # . epilogue +4356 89/<- %esp 5/r32/ebp +4357 5d/pop-to-ebp +4358 c3/return +4359 +4360 new-var: # ad: (addr allocation-descriptor), name: (addr array byte), type: (addr tree type-id), block: int, stack-offset: int, register: (addr array byte) -> result/eax: (handle var) +4361 # . prologue +4362 55/push-ebp +4363 89/<- %ebp 4/r32/esp +4364 # . save registers +4365 51/push-ecx +4366 # +4367 (allocate *(ebp+8) *Var-size) # => eax +4368 8b/-> *(ebp+0xc) 1/r32/ecx +4369 89/<- *eax 1/r32/ecx # Var-name +4370 8b/-> *(ebp+0x10) 1/r32/ecx +4371 89/<- *(eax+4) 1/r32/ecx # Var-type +4372 8b/-> *(ebp+0x14) 1/r32/ecx +4373 89/<- *(eax+8) 1/r32/ecx # Var-block-depth +4374 8b/-> *(ebp+0x18) 1/r32/ecx +4375 89/<- *(eax+0xc) 1/r32/ecx # Var-stack-offset +4376 8b/-> *(ebp+0x1c) 1/r32/ecx +4377 89/<- *(eax+0x10) 1/r32/ecx # Var-register +4378 $new-var:end: +4379 # . restore registers +4380 59/pop-to-ecx +4381 # . epilogue +4382 89/<- %esp 5/r32/ebp +4383 5d/pop-to-ebp +4384 c3/return +4385 +4386 new-literal-integer: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) +4387 # . prologue +4388 55/push-ebp +4389 89/<- %ebp 4/r32/esp +4390 # . save registers +4391 51/push-ecx +4392 # if (!is-hex-int?(name)) abort +4393 (is-hex-int? *(ebp+0xc)) # => eax +4394 3d/compare-eax-and 0/imm32/false +4395 0f 84/jump-if-= $new-literal-integer:abort/disp32 +4396 # var s/ecx: (addr array byte) +4397 (slice-to-string Heap *(ebp+0xc)) # => eax +4398 89/<- %ecx 0/r32/eax +4399 # result/ecx = new var(s) +4400 (allocate *(ebp+8) *Var-size) # => eax +4401 (zero-out %eax *Var-size) +4402 89/<- *eax 1/r32/ecx # Var-name +4403 89/<- %ecx 0/r32/eax +4404 # result->type = new type() +4405 (allocate *(ebp+8) *Tree-size) # => eax +4406 (zero-out %eax *Tree-size) # default type is 'literal' +4407 89/<- *(ecx+4) 0/r32/eax # Var-type +4408 # move result to eax +4409 89/<- %eax 1/r32/ecx +4410 $new-literal-integer:end: 4411 # . restore registers 4412 59/pop-to-ecx 4413 # . epilogue @@ -4342,4225 +4337,4431 @@ if ('onhashchange' in window) { 4415 5d/pop-to-ebp 4416 c3/return 4417 -4418 new-vardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) -4419 # . prologue -4420 55/push-ebp -4421 89/<- %ebp 4/r32/esp -4422 # . save registers -4423 51/push-ecx -4424 # -4425 (allocate *(ebp+8) *Stmt-size) # => eax -4426 (zero-out %eax *Stmt-size) -4427 c7 0/subop/copy *eax 2/imm32/tag/var-on-stack # Stmt-tag -4428 # result->var = var -4429 8b/-> *(ebp+0xc) 1/r32/ecx -4430 89/<- *(eax+4) 1/r32/ecx # Vardef-var -4431 $new-vardef:end: -4432 # . restore registers -4433 59/pop-to-ecx -4434 # . epilogue -4435 89/<- %esp 5/r32/ebp -4436 5d/pop-to-ebp -4437 c3/return -4438 -4439 new-regvardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) -4440 # . prologue -4441 55/push-ebp -4442 89/<- %ebp 4/r32/esp -4443 # . save registers -4444 51/push-ecx -4445 57/push-edi -4446 # ecx = var -4447 8b/-> *(ebp+0xc) 1/r32/ecx -4448 # edi = result -4449 (allocate *(ebp+8) *Stmt-size) # => eax -4450 89/<- %edi 0/r32/eax -4451 (zero-out %edi *Stmt-size) -4452 # set tag -4453 c7 0/subop/copy *edi 3/imm32/tag/var-in-register # Stmt-tag -4454 # set output -4455 (append-list Heap %ecx *(edi+0xc)) # Regvardef-outputs => eax -4456 89/<- *(edi+0xc) 0/r32/eax # Regvardef-outputs -4457 $new-regvardef:end: -4458 89/<- %eax 7/r32/edi -4459 # . restore registers -4460 5f/pop-to-edi -4461 59/pop-to-ecx -4462 # . epilogue -4463 89/<- %esp 5/r32/ebp -4464 5d/pop-to-ebp -4465 c3/return -4466 -4467 new-list: # ad: (addr allocation-descriptor), value: _type, next: (handle list _type) -> result/eax: (handle list _type) -4468 # . prologue -4469 55/push-ebp -4470 89/<- %ebp 4/r32/esp -4471 # . save registers -4472 51/push-ecx -4473 # -4474 (allocate *(ebp+8) *List-size) # => eax -4475 8b/-> *(ebp+0xc) 1/r32/ecx -4476 89/<- *eax 1/r32/ecx # List-value -4477 8b/-> *(ebp+0x10) 1/r32/ecx -4478 89/<- *(eax+4) 1/r32/ecx # List-next -4479 $new-list:end: -4480 # . restore registers -4481 59/pop-to-ecx -4482 # . epilogue -4483 89/<- %esp 5/r32/ebp -4484 5d/pop-to-ebp -4485 c3/return -4486 -4487 append-list: # ad: (addr allocation-descriptor), value: _type, list: (handle list _type) -> result/eax: (handle list _type) -4488 # . prologue -4489 55/push-ebp -4490 89/<- %ebp 4/r32/esp -4491 # . save registers -4492 51/push-ecx -4493 # -4494 (allocate *(ebp+8) *List-size) # => eax +4418 $new-literal-integer:abort: +4419 (write-buffered Stderr "variable cannot begin with a digit '") +4420 (write-slice-buffered Stderr *(ebp+0xc)) +4421 (write-buffered Stderr "'\n") +4422 (flush Stderr) +4423 # . syscall(exit, 1) +4424 bb/copy-to-ebx 1/imm32 +4425 b8/copy-to-eax 1/imm32/exit +4426 cd/syscall 0x80/imm8 +4427 # never gets here +4428 +4429 new-literal-string: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) +4430 # . prologue +4431 55/push-ebp +4432 89/<- %ebp 4/r32/esp +4433 # . save registers +4434 51/push-ecx +4435 # var s/ecx: (addr array byte) +4436 (slice-to-string Heap *(ebp+0xc)) # => eax +4437 89/<- %ecx 0/r32/eax +4438 # result/ecx = new var(s) +4439 (allocate *(ebp+8) *Var-size) # => eax +4440 (zero-out %eax *Var-size) +4441 89/<- *eax 1/r32/ecx # Var-name +4442 89/<- %ecx 0/r32/eax +4443 # result->type = new type() +4444 (allocate *(ebp+8) *Tree-size) # => eax +4445 (zero-out %eax *Tree-size) # default type is 'literal' +4446 89/<- *(ecx+4) 0/r32/eax # Var-type +4447 # move result to eax +4448 89/<- %eax 1/r32/ecx +4449 $new-literal-string:end: +4450 # . restore registers +4451 59/pop-to-ecx +4452 # . epilogue +4453 89/<- %esp 5/r32/ebp +4454 5d/pop-to-ebp +4455 c3/return +4456 +4457 new-label: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) +4458 # . prologue +4459 55/push-ebp +4460 89/<- %ebp 4/r32/esp +4461 # . save registers +4462 51/push-ecx +4463 # var s/ecx: (addr array byte) +4464 (slice-to-string Heap *(ebp+0xc)) # => eax +4465 89/<- %ecx 0/r32/eax +4466 # +4467 (allocate *(ebp+8) *Var-size) # => eax +4468 89/<- *eax 1/r32/ecx # Var-name +4469 89/<- %ecx 0/r32/eax +4470 (allocate *(ebp+8) *Tree-size) # => eax +4471 (zero-out %eax *Tree-size) # labels are literals +4472 89/<- *(ecx+4) 0/r32/eax # Var-type +4473 89/<- %eax 1/r32/ecx +4474 c7 0/subop/copy *(eax+8) 0/imm32 # Var-block-depth +4475 c7 0/subop/copy *(eax+0xc) 0/imm32 # Var-stack-offset +4476 c7 0/subop/copy *(eax+0x10) 0/imm32 # Var-register +4477 $new-label:end: +4478 # . restore registers +4479 59/pop-to-ecx +4480 # . epilogue +4481 89/<- %esp 5/r32/ebp +4482 5d/pop-to-ebp +4483 c3/return +4484 +4485 new-block: # ad: (addr allocation-descriptor), data: (handle list statement) -> result/eax: (handle statement) +4486 # . prologue +4487 55/push-ebp +4488 89/<- %ebp 4/r32/esp +4489 # . save registers +4490 51/push-ecx +4491 # +4492 (allocate *(ebp+8) *Stmt-size) # => eax +4493 (zero-out %eax *Stmt-size) +4494 c7 0/subop/copy *eax 0/imm32/tag/block # Stmt-tag 4495 8b/-> *(ebp+0xc) 1/r32/ecx -4496 89/<- *eax 1/r32/ecx # List-value -4497 # if (list == null) return result -4498 81 7/subop/compare *(ebp+0x10) 0/imm32 -4499 74/jump-if-= $new-list:end/disp8 -4500 # otherwise append -4501 # var curr/ecx = list -4502 8b/-> *(ebp+0x10) 1/r32/ecx -4503 # while (curr->next != null) curr = curr->next -4504 { -4505 81 7/subop/compare *(ecx+4) 0/imm32 # List-next -4506 74/jump-if-= break/disp8 -4507 # curr = curr->next -4508 8b/-> *(ecx+4) 1/r32/ecx -4509 eb/jump loop/disp8 -4510 } -4511 # curr->next = result -4512 89/<- *(ecx+4) 0/r32/eax -4513 # return list -4514 8b/-> *(ebp+0x10) 0/r32/eax -4515 $append-list:end: -4516 # . restore registers -4517 59/pop-to-ecx -4518 # . epilogue -4519 89/<- %esp 5/r32/ebp -4520 5d/pop-to-ebp -4521 c3/return -4522 -4523 append-to-block: # ad: (addr allocation-descriptor), block: (handle block), x: (handle stmt) -4524 # . prologue -4525 55/push-ebp -4526 89/<- %ebp 4/r32/esp -4527 # . save registers -4528 56/push-esi -4529 # esi = block -4530 8b/-> *(ebp+0xc) 6/r32/esi -4531 (append-list *(ebp+8) *(ebp+0x10) *(esi+4)) # ad, x, Block-statements -4532 89/<- *(esi+4) 0/r32/eax # Block-statements -4533 $append-to-block:end: -4534 # . restore registers -4535 5e/pop-to-esi -4536 # . epilogue -4537 89/<- %esp 5/r32/ebp -4538 5d/pop-to-ebp -4539 c3/return -4540 -4541 ####################################################### -4542 # Type-checking -4543 ####################################################### -4544 -4545 check-mu-types: -4546 # . prologue -4547 55/push-ebp -4548 89/<- %ebp 4/r32/esp -4549 # -4550 $check-mu-types:end: -4551 # . epilogue -4552 89/<- %esp 5/r32/ebp -4553 5d/pop-to-ebp -4554 c3/return -4555 -4556 size-of: # v: (addr var) -> result/eax: int -4557 # . prologue -4558 55/push-ebp -4559 89/<- %ebp 4/r32/esp -4560 # if v is a literal, return 0 -4561 8b/-> *(ebp+8) 0/r32/eax -4562 8b/-> *(eax+4) 0/r32/eax # Var-type -4563 81 7/subop/compare *eax 0/imm32 # Tree-left -4564 b8/copy-to-eax 0/imm32 -4565 74/jump-if-= $size-of:end/disp8 -4566 # hard-coded since we only support 'int' types for now -4567 b8/copy-to-eax 4/imm32 -4568 $size-of:end: -4569 # . epilogue -4570 89/<- %esp 5/r32/ebp -4571 5d/pop-to-ebp -4572 c3/return -4573 -4574 type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean -4575 # . prologue -4576 55/push-ebp -4577 89/<- %ebp 4/r32/esp -4578 # . save registers -4579 51/push-ecx -4580 52/push-edx -4581 # ecx = a -4582 8b/-> *(ebp+8) 1/r32/ecx -4583 # edx = b -4584 8b/-> *(ebp+0xc) 2/r32/edx -4585 # if (a == b) return true -4586 8b/-> %ecx 0/r32/eax # Var-type -4587 39/compare %edx 0/r32/eax # Var-type -4588 b8/copy-to-eax 1/imm32/true -4589 74/jump-if-= $type-equal?:end/disp8 -4590 # if (a < MAX_TYPE_ID) return false -4591 81 7/subop/compare %ecx 0x10000/imm32 -4592 b8/copy-to-eax 0/imm32/false -4593 72/jump-if-addr< $type-equal?:end/disp8 -4594 # if (b < MAX_TYPE_ID) return false -4595 81 7/subop/compare %edx 0x10000/imm32 -4596 b8/copy-to-eax 0/imm32/false -4597 72/jump-if-addr< $type-equal?:end/disp8 -4598 # if (!type-equal?(a->left, b->left)) return false -4599 (type-equal? *ecx *edx) # Tree-left, Tree-left => eax -4600 3d/compare-eax-and 0/imm32/false -4601 74/jump-if-= $type-equal?:end/disp8 -4602 # return type-equal?(a->right, b->right) -4603 (type-equal? *(ecx+4) *(edx+4)) # Tree-right, Tree-right => eax -4604 $type-equal?:end: -4605 # . restore registers -4606 5a/pop-to-edx -4607 59/pop-to-ecx -4608 # . epilogue -4609 89/<- %esp 5/r32/ebp -4610 5d/pop-to-ebp -4611 c3/return -4612 -4613 == data -4614 -4615 # not yet used, but it will be -4616 Type-size: # (stream int) -4617 0x18/imm32/write -4618 0/imm32/read -4619 0x100/imm32/length -4620 # data -4621 4/imm32 # literal -4622 4/imm32 # int -4623 4/imm32 # addr -4624 0/imm32 # array (logic elsewhere) -4625 8/imm32 # handle (fat pointer) -4626 4/imm32 # bool -4627 0/imm32 -4628 0/imm32 -4629 # 0x20 -4630 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4631 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4632 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4633 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4634 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4635 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4636 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4637 -4638 == code -4639 -4640 ####################################################### -4641 # Code-generation -4642 ####################################################### -4643 -4644 emit-subx: # out: (addr buffered-file) -4645 # . prologue -4646 55/push-ebp -4647 89/<- %ebp 4/r32/esp -4648 # . save registers -4649 50/push-eax -4650 51/push-ecx -4651 57/push-edi -4652 # edi = out -4653 8b/-> *(ebp+8) 7/r32/edi -4654 # var curr/ecx: (handle function) = *Program -4655 8b/-> *Program 1/r32/ecx -4656 { -4657 # if (curr == null) break -4658 81 7/subop/compare %ecx 0/imm32 -4659 0f 84/jump-if-= break/disp32 -4660 (emit-subx-function %edi %ecx) -4661 # curr = curr->next -4662 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next -4663 e9/jump loop/disp32 -4664 } -4665 $emit-subx:end: -4666 # . restore registers -4667 5f/pop-to-edi -4668 59/pop-to-ecx -4669 58/pop-to-eax -4670 # . epilogue -4671 89/<- %esp 5/r32/ebp -4672 5d/pop-to-ebp -4673 c3/return -4674 -4675 emit-subx-function: # out: (addr buffered-file), f: (handle function) -4676 # . prologue -4677 55/push-ebp -4678 89/<- %ebp 4/r32/esp -4679 # . save registers -4680 50/push-eax -4681 51/push-ecx -4682 52/push-edx -4683 57/push-edi -4684 # edi = out -4685 8b/-> *(ebp+8) 7/r32/edi -4686 # ecx = f -4687 8b/-> *(ebp+0xc) 1/r32/ecx -4688 # var vars/edx: (stack (addr var) 256) -4689 81 5/subop/subtract %esp 0x400/imm32 -4690 68/push 0x400/imm32/length -4691 68/push 0/imm32/top -4692 89/<- %edx 4/r32/esp -4693 # -4694 (write-buffered %edi *ecx) -4695 (write-buffered %edi ":\n") -4696 # Important: each block's depth during code-generation should be identical -4697 # to what it was during parsing. -4698 c7 0/subop/copy *Curr-block-depth 1/imm32 -4699 (emit-subx-prologue %edi) -4700 (emit-subx-block %edi *(ecx+0x10) %edx) # Function-body -4701 (emit-subx-epilogue %edi) -4702 $emit-subx-function:end: -4703 # . reclaim locals -4704 81 0/subop/add %esp 408/imm32 -4705 # . restore registers -4706 5f/pop-to-edi -4707 5a/pop-to-edx -4708 59/pop-to-ecx -4709 58/pop-to-eax -4710 # . epilogue -4711 89/<- %esp 5/r32/ebp -4712 5d/pop-to-ebp -4713 c3/return -4714 -4715 emit-subx-stmt-list: # out: (addr buffered-file), stmts: (handle list stmt), vars: (addr stack (handle var)) -4716 # . prologue -4717 55/push-ebp -4718 89/<- %ebp 4/r32/esp -4719 # . save registers -4720 50/push-eax -4721 51/push-ecx -4722 52/push-edx -4723 53/push-ebx -4724 56/push-esi -4725 # esi = stmts -4726 8b/-> *(ebp+0xc) 6/r32/esi -4727 # var var-seen?/edx: boolean <- copy false -4728 ba/copy-to-edx 0/imm32/false -4729 # -4730 { -4731 $emit-subx-stmt-list:loop: -4732 81 7/subop/compare %esi 0/imm32 -4733 0f 84/jump-if-= break/disp32 -4734 # var curr-stmt/ecx = stmts->value -4735 8b/-> *esi 1/r32/ecx # List-value -4736 { -4737 $emit-subx-stmt-list:check-for-block: -4738 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag -4739 75/jump-if-!= break/disp8 -4740 $emit-subx-stmt-list:block: -4741 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10)) -4742 } -4743 { -4744 $emit-subx-stmt-list:check-for-stmt: -4745 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag -4746 0f 85/jump-if-!= break/disp32 -4747 $emit-subx-stmt-list:stmt1: -4748 { -4749 (is-mu-branch? %ecx) # => eax -4750 3d/compare-eax-and 0/imm32/false -4751 0f 84/jump-if-= break/disp32 -4752 $emit-subx-stmt-list:branch-stmt: -4753 # if !var-seen? break -4754 81 7/subop/compare %edx 0/imm32/false -4755 0f 84/jump-if-= break/disp32 -4756 $emit-subx-stmt-list:branch-stmt-and-var-seen: -4757 +-- 26 lines: # unconditional loops ----------------------------------------------------------------------------------------------------------------------------------------------------- -4783 +-- 15 lines: # unconditional breaks ---------------------------------------------------------------------------------------------------------------------------------------------------- -4798 +-- 37 lines: # simple conditional branches without a target ---------------------------------------------------------------------------------------------------------------------------- -4835 +-- 19 lines: # conditional branches with an explicit target ---------------------------------------------------------------------------------------------------------------------------- -4854 } -4855 $emit-subx-stmt-list:1-to-1: -4856 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) -4857 } -4858 { -4859 $emit-subx-stmt-list:check-for-vardef: -4860 81 7/subop/compare *ecx 2/imm32/vardef # Stmt-tag -4861 75/jump-if-!= break/disp8 -4862 $emit-subx-stmt-list:vardef: -4863 (emit-subx-var-def *(ebp+8) %ecx) -4864 (push *(ebp+0x10) *(ecx+4)) # Vardef-var -4865 # var-seen? = true -4866 ba/copy-to-edx 1/imm32/true -4867 } -4868 { -4869 $emit-subx-stmt-list:check-for-regvardef: -4870 81 7/subop/compare *ecx 3/imm32/regvardef # Stmt-tag -4871 0f 85/jump-if-!= break/disp32 -4872 $emit-subx-stmt-list:regvardef: -4873 # TODO: ensure that there's exactly one output -4874 # var output/eax: (handle var) = curr-stmt->outputs->value -4875 8b/-> *(ecx+0xc) 0/r32/eax -4876 8b/-> *eax 0/r32/eax -4877 # ensure that output is in a register -4878 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -4879 0f 84/jump-if-= $emit-subx-stmt-list:abort-regvardef-without-register/disp32 -4880 # emit spill -4881 (emit-indent *(ebp+8) *Curr-block-depth) -4882 (write-buffered *(ebp+8) "ff 6/subop/push %") -4883 (write-buffered *(ebp+8) *(eax+0x10)) -4884 (write-buffered *(ebp+8) Newline) -4885 # register variable definition -4886 (push *(ebp+0x10) %eax) -4887 # emit the instruction as usual -4888 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) -4889 # var-seen? = true -4890 ba/copy-to-edx 1/imm32/true -4891 } -4892 $emit-subx-stmt-list:continue: -4893 # TODO: raise an error on unrecognized Stmt-tag -4894 8b/-> *(esi+4) 6/r32/esi # List-next -4895 e9/jump loop/disp32 -4896 } -4897 $emit-subx-stmt-list:emit-cleanup: -4898 (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth) -4899 $emit-subx-stmt-list:cleanup: -4900 (clean-up-blocks *(ebp+0x10) *Curr-block-depth) -4901 $emit-subx-stmt-list:end: -4902 # . restore registers -4903 5e/pop-to-esi -4904 5b/pop-to-ebx -4905 5a/pop-to-edx -4906 59/pop-to-ecx -4907 58/pop-to-eax -4908 # . epilogue -4909 89/<- %esp 5/r32/ebp -4910 5d/pop-to-ebp -4911 c3/return -4912 -4913 $emit-subx-stmt-list:abort-regvardef-without-register: -4914 # error("var '" var->name "' initialized from an instruction must live in a register\n") -4915 (write-buffered Stderr "var '") -4916 (write-buffered Stderr *eax) # Var-name -4917 (write-buffered Stderr "' initialized from an instruction must live in a register\n") -4918 (flush Stderr) -4919 # . syscall(exit, 1) -4920 bb/copy-to-ebx 1/imm32 -4921 b8/copy-to-eax 1/imm32/exit -4922 cd/syscall 0x80/imm8 -4923 # never gets here -4924 -4925 emit-subx-cleanup-and-unconditional-nonlocal-branch: # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack (handle var)) -4926 # . prologue -4927 55/push-ebp -4928 89/<- %ebp 4/r32/esp -4929 # . save registers -4930 50/push-eax -4931 51/push-ecx -4932 52/push-edx -4933 # ecx = stmt -4934 8b/-> *(ebp+0xc) 1/r32/ecx -4935 # var target/edx: (addr array byte) = curr-stmt->inouts->value->name -4936 8b/-> *(ecx+8) 2/r32/edx # Stmt1-inouts -4937 8b/-> *edx 2/r32/edx # List-value -4938 8b/-> *edx 2/r32/edx # Var-name -4939 # clean up until target block -4940 (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %edx) -4941 # emit jump to target block -4942 (emit-indent *(ebp+8) *Curr-block-depth) -4943 (write-buffered *(ebp+8) "e9/jump ") -4944 (write-buffered *(ebp+8) %edx) -4945 (string-starts-with? *(ecx+4) "break") -4946 3d/compare-eax-and 0/imm32/false -4947 { -4948 74/jump-if-= break/disp8 -4949 (write-buffered *(ebp+8) ":break/disp32\n") -4950 } -4951 3d/compare-eax-and 0/imm32/false # just in case the function call modified flags -4952 { -4953 75/jump-if-!= break/disp8 -4954 (write-buffered *(ebp+8) ":loop/disp32\n") -4955 } -4956 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end: -4957 # . restore registers -4958 5a/pop-to-edx -4959 59/pop-to-ecx -4960 58/pop-to-eax -4961 # . epilogue -4962 89/<- %esp 5/r32/ebp -4963 5d/pop-to-ebp -4964 c3/return -4965 -4966 is-mu-branch?: # stmt: (addr stmt1) -> result/eax: boolean -4967 # . prologue -4968 55/push-ebp -4969 89/<- %ebp 4/r32/esp -4970 # . save registers -4971 51/push-ecx -4972 # ecx = stmt -4973 8b/-> *(ebp+8) 1/r32/ecx -4974 # if (stmt->operation starts with "loop") return true -4975 (string-starts-with? *(ecx+4) "loop") # Stmt1-operation => eax -4976 3d/compare-eax-and 0/imm32/false -4977 75/jump-if-not-equal $is-mu-branch?:end/disp8 -4978 # otherwise return (stmt->operation starts with "break") -4979 (string-starts-with? *(ecx+4) "break") # Stmt1-operation => eax -4980 $is-mu-branch?:end: -4981 # . restore registers -4982 59/pop-to-ecx -4983 # . epilogue -4984 89/<- %esp 5/r32/ebp -4985 5d/pop-to-ebp -4986 c3/return -4987 -4988 emit-reverse-break: # out: (addr buffered-file), stmt: (addr stmt1) -4989 # . prologue -4990 55/push-ebp -4991 89/<- %ebp 4/r32/esp -4992 # . save registers -4993 50/push-eax -4994 # eax = stmt -4995 8b/-> *(ebp+0xc) 0/r32/eax -4996 # -4997 (get Reverse-branch *(eax+4) 8 "reverse-branch: ") # Stmt1-operation => eax: (addr addr array byte) -4998 (emit-indent *(ebp+8) *Curr-block-depth) -4999 (write-buffered *(ebp+8) *eax) -5000 (write-buffered *(ebp+8) " break/disp32\n") -5001 $emit-reverse-break:end: -5002 # . restore registers -5003 58/pop-to-eax -5004 # . epilogue -5005 89/<- %esp 5/r32/ebp -5006 5d/pop-to-ebp -5007 c3/return -5008 -5009 == data -5010 -5011 Reverse-branch: # (table string string) -5012 # a table is a stream -5013 0xa0/imm32/write -5014 0/imm32/read -5015 0xa0/imm32/length -5016 # data -5017 "break-if-="/imm32 "0f 85/jump-if-!="/imm32 -5018 "loop-if-="/imm32 "0f 85/jump-if-!="/imm32 -5019 "break-if-!="/imm32 "0f 84/jump-if-="/imm32 -5020 "loop-if-!="/imm32 "0f 84/jump-if-="/imm32 -5021 "break-if-<"/imm32 "0f 8d/jump-if->="/imm32 -5022 "loop-if-<"/imm32 "0f 8d/jump-if->="/imm32 -5023 "break-if->"/imm32 "0f 8e/jump-if-<="/imm32 -5024 "loop-if->"/imm32 "0f 8e/jump-if-<="/imm32 -5025 "break-if-<="/imm32 "0f 87/jump-if->"/imm32 -5026 "loop-if-<="/imm32 "0f 87/jump-if->"/imm32 -5027 "break-if->="/imm32 "0f 8c/jump-if-<"/imm32 -5028 "loop-if->="/imm32 "0f 8c/jump-if-<"/imm32 -5029 "break-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 -5030 "loop-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 -5031 "break-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 -5032 "loop-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 -5033 "break-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 -5034 "loop-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 -5035 "break-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 -5036 "loop-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 -5037 -5038 == code -5039 -5040 emit-unconditional-jump-to-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), depth: int, label-suffix: (addr array byte) -5041 # . prologue -5042 55/push-ebp -5043 89/<- %ebp 4/r32/esp -5044 # . save registers -5045 50/push-eax -5046 51/push-ecx -5047 52/push-edx -5048 53/push-ebx -5049 # ecx = vars -5050 8b/-> *(ebp+0xc) 1/r32/ecx -5051 # var eax: int = vars->top -5052 8b/-> *ecx 0/r32/eax -5053 # var min/ecx: (address (handle var)) = vars->data -5054 81 0/subop/add %ecx 8/imm32 -5055 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] -5056 81 5/subop/subtract %eax 4/imm32 -5057 8d/copy-address *(ecx+eax) 0/r32/eax -5058 # edx = depth -5059 8b/-> *(ebp+0x10) 2/r32/edx -5060 { -5061 $emit-unconditional-jump-to-depth:loop: -5062 # if (curr < min) break -5063 39/compare %eax 1/r32/ecx -5064 0f 82/jump-if-addr< break/disp32 -5065 # var v/ebx: (handle var) = *curr -5066 8b/-> *eax 3/r32/ebx -5067 # if (v->block-depth < until-block-depth) break -5068 39/compare *(ebx+8) 2/r32/edx # Var-block-depth -5069 0f 8c/jump-if-< break/disp32 -5070 { -5071 $emit-unconditional-jump-to-depth:check: -5072 # if v->block-depth != until-block-depth, continue -5073 39/compare *(ebx+8) 2/r32/edx # Var-block-depth -5074 0f 85/jump-if-!= break/disp32 -5075 $emit-unconditional-jump-to-depth:depth-found: -5076 # if v is not a literal, continue -5077 # . var eax: int = size-of(v) -5078 50/push-eax -5079 (size-of %ebx) # => eax -5080 # . if (eax != 0) continue -5081 3d/compare-eax-and 0/imm32 -5082 58/pop-to-eax -5083 # -5084 0f 85/jump-if-!= break/disp32 -5085 $emit-unconditional-jump-to-depth:label-found: -5086 # emit unconditional jump, then return -5087 (emit-indent *(ebp+8) *Curr-block-depth) -5088 (write-buffered *(ebp+8) "e9/jump ") -5089 (write-buffered *(ebp+8) *ebx) # Var-name -5090 (write-buffered *(ebp+8) ":") -5091 (write-buffered *(ebp+8) *(ebp+0x14)) -5092 (write-buffered *(ebp+8) "/disp32\n") -5093 eb/jump $emit-unconditional-jump-to-depth:end/disp8 -5094 } -5095 # curr -= 4 -5096 2d/subtract-from-eax 4/imm32 -5097 e9/jump loop/disp32 -5098 } -5099 # TODO: error if no label at 'depth' was found -5100 $emit-unconditional-jump-to-depth:end: -5101 # . restore registers -5102 5b/pop-to-ebx -5103 5a/pop-to-edx -5104 59/pop-to-ecx -5105 58/pop-to-eax -5106 # . epilogue -5107 89/<- %esp 5/r32/ebp -5108 5d/pop-to-ebp -5109 c3/return -5110 -5111 # emit clean-up code for 'vars' until some block depth -5112 # doesn't actually modify 'vars' so we need traverse manually inside the stack -5113 emit-cleanup-code-until-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-depth: int -5114 # . prologue -5115 55/push-ebp -5116 89/<- %ebp 4/r32/esp -5117 # . save registers -5118 50/push-eax -5119 51/push-ecx -5120 52/push-edx -5121 53/push-ebx -5122 # ecx = vars -5123 8b/-> *(ebp+0xc) 1/r32/ecx -5124 # var eax: int = vars->top -5125 8b/-> *ecx 0/r32/eax -5126 # var min/ecx: (address (handle var)) = vars->data -5127 81 0/subop/add %ecx 8/imm32 -5128 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] -5129 81 5/subop/subtract %eax 4/imm32 -5130 8d/copy-address *(ecx+eax) 0/r32/eax -5131 # edx = until-block-depth -5132 8b/-> *(ebp+0x10) 2/r32/edx -5133 { -5134 $emit-cleanup-code-until-depth:loop: -5135 # if (curr < min) break -5136 39/compare %eax 1/r32/ecx -5137 0f 82/jump-if-addr< break/disp32 -5138 # var v/ebx: (handle var) = *curr -5139 8b/-> *eax 3/r32/ebx -5140 # if (v->block-depth < until-block-depth) break -5141 39/compare *(ebx+8) 2/r32/edx # Var-block-depth -5142 0f 8c/jump-if-< break/disp32 -5143 # if v is in a register -5144 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -5145 { -5146 74/jump-if-= break/disp8 -5147 $emit-cleanup-code-until-depth:reclaim-var-in-register: -5148 (emit-indent *(ebp+8) *Curr-block-depth) -5149 (write-buffered *(ebp+8) "8f 0/subop/pop %") -5150 (write-buffered *(ebp+8) *(ebx+0x10)) -5151 (write-buffered *(ebp+8) Newline) -5152 } -5153 # otherwise v is on the stack -5154 { -5155 75/jump-if-!= break/disp8 -5156 $emit-cleanup-code-until-depth:reclaim-var-on-stack: -5157 50/push-eax -5158 (size-of %ebx) # => eax -5159 # don't emit code for labels -5160 3d/compare-eax-and 0/imm32 -5161 74/jump-if-= break/disp8 -5162 # -5163 (emit-indent *(ebp+8) *Curr-block-depth) -5164 (write-buffered *(ebp+8) "81 0/subop/add %esp ") -5165 (print-int32-buffered *(ebp+8) %eax) -5166 (write-buffered *(ebp+8) "/imm32\n") -5167 58/pop-to-eax -5168 } -5169 # curr -= 4 -5170 2d/subtract-from-eax 4/imm32 -5171 e9/jump loop/disp32 -5172 } -5173 $emit-cleanup-code-until-depth:end: -5174 # . restore registers -5175 5b/pop-to-ebx -5176 5a/pop-to-edx -5177 59/pop-to-ecx -5178 58/pop-to-eax -5179 # . epilogue -5180 89/<- %esp 5/r32/ebp -5181 5d/pop-to-ebp -5182 c3/return -5183 -5184 # emit clean-up code for 'vars' until a given label is encountered -5185 # doesn't actually modify 'vars' so we need traverse manually inside the stack -5186 emit-cleanup-code-until-target: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-label: (addr array byte) -5187 # . prologue -5188 55/push-ebp -5189 89/<- %ebp 4/r32/esp -5190 # . save registers -5191 50/push-eax -5192 51/push-ecx -5193 52/push-edx -5194 53/push-ebx -5195 # ecx = vars -5196 8b/-> *(ebp+0xc) 1/r32/ecx -5197 # var eax: int = vars->top -5198 8b/-> *ecx 0/r32/eax -5199 # var min/ecx: (address (handle var)) = vars->data -5200 81 0/subop/add %ecx 8/imm32 -5201 # var curr/edx: (address (handle var)) = &vars->data[vars->top - 4] -5202 81 5/subop/subtract %eax 4/imm32 -5203 8d/copy-address *(ecx+eax) 2/r32/edx -5204 { -5205 $emit-cleanup-code-until-target:loop: -5206 # if (curr < min) break -5207 39/compare %edx 1/r32/ecx -5208 0f 82/jump-if-addr< break/disp32 -5209 # var v/ebx: (handle var) = *curr -5210 8b/-> *edx 3/r32/ebx -5211 # if (v->name == until-block-label) break -5212 (string-equal? *ebx *(ebp+0x10)) # => eax -5213 3d/compare-eax-and 0/imm32/false -5214 0f 85/jump-if-!= break/disp32 -5215 # if v is in a register -5216 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -5217 { -5218 74/jump-if-= break/disp8 -5219 $emit-cleanup-code-until-target:reclaim-var-in-register: -5220 (emit-indent *(ebp+8) *Curr-block-depth) -5221 (write-buffered *(ebp+8) "8f 0/subop/pop %") -5222 (write-buffered *(ebp+8) *(ebx+0x10)) -5223 (write-buffered *(ebp+8) Newline) -5224 } -5225 # otherwise v is on the stack -5226 { -5227 75/jump-if-!= break/disp8 -5228 $emit-cleanup-code-until-target:reclaim-var-on-stack: -5229 (size-of %ebx) # => eax -5230 # don't emit code for labels -5231 3d/compare-eax-and 0/imm32 -5232 74/jump-if-= break/disp8 -5233 # -5234 (emit-indent *(ebp+8) *Curr-block-depth) -5235 (write-buffered *(ebp+8) "81 0/subop/add %esp ") -5236 (print-int32-buffered *(ebp+8) %eax) -5237 (write-buffered *(ebp+8) "/imm32\n") -5238 } -5239 # curr -= 4 -5240 81 5/subop/subtract %edx 4/imm32 -5241 e9/jump loop/disp32 -5242 } -5243 $emit-cleanup-code-until-target:end: -5244 # . restore registers -5245 5b/pop-to-ebx -5246 5a/pop-to-edx -5247 59/pop-to-ecx -5248 58/pop-to-eax -5249 # . epilogue -5250 89/<- %esp 5/r32/ebp -5251 5d/pop-to-ebp -5252 c3/return -5253 -5254 # clean up global state for 'vars' until some block depth -5255 clean-up-blocks: # vars: (addr stack (handle var)), until-block-depth: int -5256 # . prologue -5257 55/push-ebp -5258 89/<- %ebp 4/r32/esp -5259 # . save registers -5260 50/push-eax -5261 51/push-ecx -5262 56/push-esi -5263 # esi = vars -5264 8b/-> *(ebp+8) 6/r32/esi -5265 # ecx = until-block-depth -5266 8b/-> *(ebp+0xc) 1/r32/ecx -5267 { -5268 $clean-up-blocks:reclaim-loop: -5269 # if (vars->top <= 0) break -5270 81 7/subop/compare *esi 0/imm32 # Stack-top -5271 7e/jump-if-<= break/disp8 -5272 # var v/eax: (handle var) = top(vars) -5273 (top %esi) # => eax -5274 # if (v->block-depth < until-block-depth) break -5275 39/compare *(eax+8) 1/r32/ecx # Var-block-depth -5276 7c/jump-if-< break/disp8 -5277 # if v is on the stack, update Next-local-stack-offset -5278 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -5279 { -5280 75/jump-if-!= break/disp8 -5281 $clean-up-blocks:reclaim-var-on-stack: -5282 (size-of %eax) # => eax -5283 01/add *Next-local-stack-offset 0/r32/eax -5284 } -5285 (pop %esi) -5286 e9/jump loop/disp32 -5287 } -5288 $clean-up-blocks:end: -5289 # . restore registers -5290 5e/pop-to-esi -5291 59/pop-to-ecx -5292 58/pop-to-eax -5293 # . epilogue -5294 89/<- %esp 5/r32/ebp -5295 5d/pop-to-ebp -5296 c3/return -5297 -5298 emit-subx-var-def: # out: (addr buffered-file), stmt: (handle statement) -5299 # . prologue -5300 55/push-ebp -5301 89/<- %ebp 4/r32/esp -5302 # . save registers -5303 50/push-eax -5304 51/push-ecx -5305 # eax = stmt -5306 8b/-> *(ebp+0xc) 0/r32/eax -5307 # var n/eax: int = size-of(stmt->var) -5308 (size-of *(eax+4)) # Vardef-var => eax -5309 # while n > 0 -5310 { -5311 3d/compare-eax-with 0/imm32 -5312 7e/jump-if-<= break/disp8 -5313 (emit-indent *(ebp+8) *Curr-block-depth) -5314 (write-buffered *(ebp+8) "68/push 0/imm32\n") -5315 # n -= 4 -5316 2d/subtract-from-eax 4/imm32 -5317 # -5318 eb/jump loop/disp8 -5319 } -5320 $emit-subx-var-def:end: -5321 # . restore registers -5322 59/pop-to-ecx -5323 58/pop-to-eax -5324 # . epilogue -5325 89/<- %esp 5/r32/ebp -5326 5d/pop-to-ebp -5327 c3/return -5328 -5329 emit-subx-statement: # out: (addr buffered-file), stmt: (handle statement), primitives: (handle primitive), functions: (handle function) -5330 # . prologue -5331 55/push-ebp -5332 89/<- %ebp 4/r32/esp -5333 # . save registers -5334 50/push-eax -5335 51/push-ecx -5336 # handle some special cases -5337 # ecx = stmt -5338 8b/-> *(ebp+0xc) 1/r32/ecx -5339 +-- 24 lines: # array length ------------------------------------------------------------------------------------------------------------------------------------------------------------ -5363 # if stmt matches a primitive, emit it -5364 { -5365 $emit-subx-statement:check-for-primitive: -5366 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => curr/eax -5367 3d/compare-eax-and 0/imm32 -5368 74/jump-if-= break/disp8 -5369 $emit-subx-statement:primitive: -5370 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr -5371 e9/jump $emit-subx-statement:end/disp32 -5372 } -5373 # else if stmt matches a function, emit a call to it +4496 89/<- *(eax+4) 1/r32/ecx # Block-statements +4497 $new-block:end: +4498 # . restore registers +4499 59/pop-to-ecx +4500 # . epilogue +4501 89/<- %esp 5/r32/ebp +4502 5d/pop-to-ebp +4503 c3/return +4504 +4505 new-vardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) +4506 # . prologue +4507 55/push-ebp +4508 89/<- %ebp 4/r32/esp +4509 # . save registers +4510 51/push-ecx +4511 # +4512 (allocate *(ebp+8) *Stmt-size) # => eax +4513 (zero-out %eax *Stmt-size) +4514 c7 0/subop/copy *eax 2/imm32/tag/var-on-stack # Stmt-tag +4515 # result->var = var +4516 8b/-> *(ebp+0xc) 1/r32/ecx +4517 89/<- *(eax+4) 1/r32/ecx # Vardef-var +4518 $new-vardef:end: +4519 # . restore registers +4520 59/pop-to-ecx +4521 # . epilogue +4522 89/<- %esp 5/r32/ebp +4523 5d/pop-to-ebp +4524 c3/return +4525 +4526 new-regvardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) +4527 # . prologue +4528 55/push-ebp +4529 89/<- %ebp 4/r32/esp +4530 # . save registers +4531 51/push-ecx +4532 57/push-edi +4533 # ecx = var +4534 8b/-> *(ebp+0xc) 1/r32/ecx +4535 # edi = result +4536 (allocate *(ebp+8) *Stmt-size) # => eax +4537 89/<- %edi 0/r32/eax +4538 (zero-out %edi *Stmt-size) +4539 # set tag +4540 c7 0/subop/copy *edi 3/imm32/tag/var-in-register # Stmt-tag +4541 # set output +4542 (append-stmt-var Heap %ecx *(edi+0xc) 0) # Regvardef-outputs => eax +4543 89/<- *(edi+0xc) 0/r32/eax # Regvardef-outputs +4544 $new-regvardef:end: +4545 89/<- %eax 7/r32/edi +4546 # . restore registers +4547 5f/pop-to-edi +4548 59/pop-to-ecx +4549 # . epilogue +4550 89/<- %esp 5/r32/ebp +4551 5d/pop-to-ebp +4552 c3/return +4553 +4554 append-list: # ad: (addr allocation-descriptor), value: _type, list: (handle list _type) -> result/eax: (handle list _type) +4555 # . prologue +4556 55/push-ebp +4557 89/<- %ebp 4/r32/esp +4558 # . save registers +4559 51/push-ecx +4560 # +4561 (allocate *(ebp+8) *List-size) # => eax +4562 (zero-out %eax *List-size) +4563 8b/-> *(ebp+0xc) 1/r32/ecx +4564 89/<- *eax 1/r32/ecx # List-value +4565 # if (list == null) return result +4566 81 7/subop/compare *(ebp+0x10) 0/imm32 +4567 74/jump-if-= $append-list:end/disp8 +4568 # otherwise append +4569 # var curr/ecx = list +4570 8b/-> *(ebp+0x10) 1/r32/ecx +4571 # while (curr->next != null) curr = curr->next +4572 { +4573 81 7/subop/compare *(ecx+4) 0/imm32 # List-next +4574 74/jump-if-= break/disp8 +4575 # curr = curr->next +4576 8b/-> *(ecx+4) 1/r32/ecx +4577 eb/jump loop/disp8 +4578 } +4579 # curr->next = result +4580 89/<- *(ecx+4) 0/r32/eax +4581 # return list +4582 8b/-> *(ebp+0x10) 0/r32/eax +4583 $append-list:end: +4584 # . restore registers +4585 59/pop-to-ecx +4586 # . epilogue +4587 89/<- %esp 5/r32/ebp +4588 5d/pop-to-ebp +4589 c3/return +4590 +4591 append-stmt-var: # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean -> result/eax: (handle stmt-var) +4592 # . prologue +4593 55/push-ebp +4594 89/<- %ebp 4/r32/esp +4595 # . save registers +4596 51/push-ecx +4597 # +4598 (allocate *(ebp+8) *Stmt-var-size) # => eax +4599 (zero-out %eax *Stmt-var-size) +4600 8b/-> *(ebp+0xc) 1/r32/ecx +4601 89/<- *eax 1/r32/ecx # Stmt-var-value +4602 8b/-> *(ebp+0x14) 1/r32/ecx +4603 89/<- *(eax+8) 1/r32/ecx # Stmt-var-is-deref +4604 # if (list == null) return result +4605 81 7/subop/compare *(ebp+0x10) 0/imm32 +4606 74/jump-if-= $append-stmt-var:end/disp8 +4607 # otherwise append +4608 # var curr/ecx: (handle stmt-var) = vars +4609 8b/-> *(ebp+0x10) 1/r32/ecx +4610 # while (curr->next != null) curr = curr->next +4611 { +4612 81 7/subop/compare *(ecx+4) 0/imm32 # List-next +4613 74/jump-if-= break/disp8 +4614 # curr = curr->next +4615 8b/-> *(ecx+4) 1/r32/ecx +4616 eb/jump loop/disp8 +4617 } +4618 # curr->next = result +4619 89/<- *(ecx+4) 0/r32/eax +4620 # return vars +4621 8b/-> *(ebp+0x10) 0/r32/eax +4622 $append-stmt-var:end: +4623 # . restore registers +4624 59/pop-to-ecx +4625 # . epilogue +4626 89/<- %esp 5/r32/ebp +4627 5d/pop-to-ebp +4628 c3/return +4629 +4630 append-to-block: # ad: (addr allocation-descriptor), block: (handle block), x: (handle stmt) +4631 # . prologue +4632 55/push-ebp +4633 89/<- %ebp 4/r32/esp +4634 # . save registers +4635 56/push-esi +4636 # esi = block +4637 8b/-> *(ebp+0xc) 6/r32/esi +4638 (append-list *(ebp+8) *(ebp+0x10) *(esi+4)) # ad, x, Block-statements +4639 89/<- *(esi+4) 0/r32/eax # Block-statements +4640 $append-to-block:end: +4641 # . restore registers +4642 5e/pop-to-esi +4643 # . epilogue +4644 89/<- %esp 5/r32/ebp +4645 5d/pop-to-ebp +4646 c3/return +4647 +4648 ####################################################### +4649 # Type-checking +4650 ####################################################### +4651 +4652 check-mu-types: +4653 # . prologue +4654 55/push-ebp +4655 89/<- %ebp 4/r32/esp +4656 # +4657 $check-mu-types:end: +4658 # . epilogue +4659 89/<- %esp 5/r32/ebp +4660 5d/pop-to-ebp +4661 c3/return +4662 +4663 size-of: # v: (addr var) -> result/eax: int +4664 # . prologue +4665 55/push-ebp +4666 89/<- %ebp 4/r32/esp +4667 # if v is a literal, return 0 +4668 8b/-> *(ebp+8) 0/r32/eax +4669 8b/-> *(eax+4) 0/r32/eax # Var-type +4670 81 7/subop/compare *eax 0/imm32 # Tree-left +4671 b8/copy-to-eax 0/imm32 +4672 74/jump-if-= $size-of:end/disp8 +4673 # hard-coded since we only support 'int' types for now +4674 b8/copy-to-eax 4/imm32 +4675 $size-of:end: +4676 # . epilogue +4677 89/<- %esp 5/r32/ebp +4678 5d/pop-to-ebp +4679 c3/return +4680 +4681 type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean +4682 # . prologue +4683 55/push-ebp +4684 89/<- %ebp 4/r32/esp +4685 # . save registers +4686 51/push-ecx +4687 52/push-edx +4688 # ecx = a +4689 8b/-> *(ebp+8) 1/r32/ecx +4690 # edx = b +4691 8b/-> *(ebp+0xc) 2/r32/edx +4692 # if (a == b) return true +4693 8b/-> %ecx 0/r32/eax # Var-type +4694 39/compare %edx 0/r32/eax # Var-type +4695 b8/copy-to-eax 1/imm32/true +4696 74/jump-if-= $type-equal?:end/disp8 +4697 # if (a < MAX_TYPE_ID) return false +4698 81 7/subop/compare %ecx 0x10000/imm32 +4699 b8/copy-to-eax 0/imm32/false +4700 72/jump-if-addr< $type-equal?:end/disp8 +4701 # if (b < MAX_TYPE_ID) return false +4702 81 7/subop/compare %edx 0x10000/imm32 +4703 b8/copy-to-eax 0/imm32/false +4704 72/jump-if-addr< $type-equal?:end/disp8 +4705 # if (!type-equal?(a->left, b->left)) return false +4706 (type-equal? *ecx *edx) # Tree-left, Tree-left => eax +4707 3d/compare-eax-and 0/imm32/false +4708 74/jump-if-= $type-equal?:end/disp8 +4709 # return type-equal?(a->right, b->right) +4710 (type-equal? *(ecx+4) *(edx+4)) # Tree-right, Tree-right => eax +4711 $type-equal?:end: +4712 # . restore registers +4713 5a/pop-to-edx +4714 59/pop-to-ecx +4715 # . epilogue +4716 89/<- %esp 5/r32/ebp +4717 5d/pop-to-ebp +4718 c3/return +4719 +4720 == data +4721 +4722 # not yet used, but it will be +4723 Type-size: # (stream int) +4724 0x18/imm32/write +4725 0/imm32/read +4726 0x100/imm32/length +4727 # data +4728 4/imm32 # literal +4729 4/imm32 # int +4730 4/imm32 # addr +4731 0/imm32 # array (logic elsewhere) +4732 8/imm32 # handle (fat pointer) +4733 4/imm32 # bool +4734 0/imm32 +4735 0/imm32 +4736 # 0x20 +4737 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4738 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4739 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4740 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4741 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4742 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4743 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4744 +4745 == code +4746 +4747 ####################################################### +4748 # Code-generation +4749 ####################################################### +4750 +4751 emit-subx: # out: (addr buffered-file) +4752 # . prologue +4753 55/push-ebp +4754 89/<- %ebp 4/r32/esp +4755 # . save registers +4756 50/push-eax +4757 51/push-ecx +4758 57/push-edi +4759 # edi = out +4760 8b/-> *(ebp+8) 7/r32/edi +4761 # var curr/ecx: (handle function) = *Program +4762 8b/-> *Program 1/r32/ecx +4763 { +4764 # if (curr == null) break +4765 81 7/subop/compare %ecx 0/imm32 +4766 0f 84/jump-if-= break/disp32 +4767 (emit-subx-function %edi %ecx) +4768 # curr = curr->next +4769 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next +4770 e9/jump loop/disp32 +4771 } +4772 $emit-subx:end: +4773 # . restore registers +4774 5f/pop-to-edi +4775 59/pop-to-ecx +4776 58/pop-to-eax +4777 # . epilogue +4778 89/<- %esp 5/r32/ebp +4779 5d/pop-to-ebp +4780 c3/return +4781 +4782 emit-subx-function: # out: (addr buffered-file), f: (handle function) +4783 # . prologue +4784 55/push-ebp +4785 89/<- %ebp 4/r32/esp +4786 # . save registers +4787 50/push-eax +4788 51/push-ecx +4789 52/push-edx +4790 57/push-edi +4791 # edi = out +4792 8b/-> *(ebp+8) 7/r32/edi +4793 # ecx = f +4794 8b/-> *(ebp+0xc) 1/r32/ecx +4795 # var vars/edx: (stack (addr var) 256) +4796 81 5/subop/subtract %esp 0x400/imm32 +4797 68/push 0x400/imm32/length +4798 68/push 0/imm32/top +4799 89/<- %edx 4/r32/esp +4800 # +4801 (write-buffered %edi *ecx) +4802 (write-buffered %edi ":\n") +4803 # Important: each block's depth during code-generation should be identical +4804 # to what it was during parsing. +4805 c7 0/subop/copy *Curr-block-depth 1/imm32 +4806 (emit-subx-prologue %edi) +4807 (emit-subx-block %edi *(ecx+0x10) %edx) # Function-body +4808 (emit-subx-epilogue %edi) +4809 $emit-subx-function:end: +4810 # . reclaim locals +4811 81 0/subop/add %esp 408/imm32 +4812 # . restore registers +4813 5f/pop-to-edi +4814 5a/pop-to-edx +4815 59/pop-to-ecx +4816 58/pop-to-eax +4817 # . epilogue +4818 89/<- %esp 5/r32/ebp +4819 5d/pop-to-ebp +4820 c3/return +4821 +4822 emit-subx-stmt-list: # out: (addr buffered-file), stmts: (handle list stmt), vars: (addr stack (handle var)) +4823 # . prologue +4824 55/push-ebp +4825 89/<- %ebp 4/r32/esp +4826 # . save registers +4827 50/push-eax +4828 51/push-ecx +4829 52/push-edx +4830 53/push-ebx +4831 56/push-esi +4832 # esi = stmts +4833 8b/-> *(ebp+0xc) 6/r32/esi +4834 # var var-seen?/edx: boolean <- copy false +4835 ba/copy-to-edx 0/imm32/false +4836 # +4837 { +4838 $emit-subx-stmt-list:loop: +4839 81 7/subop/compare %esi 0/imm32 +4840 0f 84/jump-if-= break/disp32 +4841 # var curr-stmt/ecx = stmts->value +4842 8b/-> *esi 1/r32/ecx # List-value +4843 { +4844 $emit-subx-stmt-list:check-for-block: +4845 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag +4846 75/jump-if-!= break/disp8 +4847 $emit-subx-stmt-list:block: +4848 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10)) +4849 } +4850 { +4851 $emit-subx-stmt-list:check-for-stmt: +4852 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag +4853 0f 85/jump-if-!= break/disp32 +4854 $emit-subx-stmt-list:stmt1: +4855 { +4856 (is-mu-branch? %ecx) # => eax +4857 3d/compare-eax-and 0/imm32/false +4858 0f 84/jump-if-= break/disp32 +4859 $emit-subx-stmt-list:branch-stmt: +4860 # if !var-seen? break +4861 81 7/subop/compare %edx 0/imm32/false +4862 0f 84/jump-if-= break/disp32 +4863 $emit-subx-stmt-list:branch-stmt-and-var-seen: +4864 +-- 26 lines: # unconditional loops ----------------------------------------------------------------------------------------------------------------------------------------------------- +4890 +-- 15 lines: # unconditional breaks ---------------------------------------------------------------------------------------------------------------------------------------------------- +4905 +-- 37 lines: # simple conditional branches without a target ---------------------------------------------------------------------------------------------------------------------------- +4942 +-- 19 lines: # conditional branches with an explicit target ---------------------------------------------------------------------------------------------------------------------------- +4961 } +4962 $emit-subx-stmt-list:1-to-1: +4963 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) +4964 } +4965 { +4966 $emit-subx-stmt-list:check-for-vardef: +4967 81 7/subop/compare *ecx 2/imm32/vardef # Stmt-tag +4968 75/jump-if-!= break/disp8 +4969 $emit-subx-stmt-list:vardef: +4970 (emit-subx-var-def *(ebp+8) %ecx) +4971 (push *(ebp+0x10) *(ecx+4)) # Vardef-var +4972 # var-seen? = true +4973 ba/copy-to-edx 1/imm32/true +4974 } +4975 { +4976 $emit-subx-stmt-list:check-for-regvardef: +4977 81 7/subop/compare *ecx 3/imm32/regvardef # Stmt-tag +4978 0f 85/jump-if-!= break/disp32 +4979 $emit-subx-stmt-list:regvardef: +4980 # TODO: ensure that there's exactly one output +4981 # var output/eax: (handle var) = curr-stmt->outputs->value +4982 8b/-> *(ecx+0xc) 0/r32/eax +4983 8b/-> *eax 0/r32/eax +4984 # ensure that output is in a register +4985 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register +4986 0f 84/jump-if-= $emit-subx-stmt-list:abort-regvardef-without-register/disp32 +4987 # emit spill +4988 (emit-indent *(ebp+8) *Curr-block-depth) +4989 (write-buffered *(ebp+8) "ff 6/subop/push %") +4990 (write-buffered *(ebp+8) *(eax+0x10)) +4991 (write-buffered *(ebp+8) Newline) +4992 # register variable definition +4993 (push *(ebp+0x10) %eax) +4994 # emit the instruction as usual +4995 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) +4996 # var-seen? = true +4997 ba/copy-to-edx 1/imm32/true +4998 } +4999 $emit-subx-stmt-list:continue: +5000 # TODO: raise an error on unrecognized Stmt-tag +5001 8b/-> *(esi+4) 6/r32/esi # List-next +5002 e9/jump loop/disp32 +5003 } +5004 $emit-subx-stmt-list:emit-cleanup: +5005 (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth) +5006 $emit-subx-stmt-list:cleanup: +5007 (clean-up-blocks *(ebp+0x10) *Curr-block-depth) +5008 $emit-subx-stmt-list:end: +5009 # . restore registers +5010 5e/pop-to-esi +5011 5b/pop-to-ebx +5012 5a/pop-to-edx +5013 59/pop-to-ecx +5014 58/pop-to-eax +5015 # . epilogue +5016 89/<- %esp 5/r32/ebp +5017 5d/pop-to-ebp +5018 c3/return +5019 +5020 $emit-subx-stmt-list:abort-regvardef-without-register: +5021 # error("var '" var->name "' initialized from an instruction must live in a register\n") +5022 (write-buffered Stderr "var '") +5023 (write-buffered Stderr *eax) # Var-name +5024 (write-buffered Stderr "' initialized from an instruction must live in a register\n") +5025 (flush Stderr) +5026 # . syscall(exit, 1) +5027 bb/copy-to-ebx 1/imm32 +5028 b8/copy-to-eax 1/imm32/exit +5029 cd/syscall 0x80/imm8 +5030 # never gets here +5031 +5032 emit-subx-cleanup-and-unconditional-nonlocal-branch: # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack (handle var)) +5033 # . prologue +5034 55/push-ebp +5035 89/<- %ebp 4/r32/esp +5036 # . save registers +5037 50/push-eax +5038 51/push-ecx +5039 52/push-edx +5040 # ecx = stmt +5041 8b/-> *(ebp+0xc) 1/r32/ecx +5042 # var target/edx: (addr array byte) = curr-stmt->inouts->value->name +5043 8b/-> *(ecx+8) 2/r32/edx # Stmt1-inouts +5044 8b/-> *edx 2/r32/edx # Stmt-var-value +5045 8b/-> *edx 2/r32/edx # Var-name +5046 # clean up until target block +5047 (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %edx) +5048 # emit jump to target block +5049 (emit-indent *(ebp+8) *Curr-block-depth) +5050 (write-buffered *(ebp+8) "e9/jump ") +5051 (write-buffered *(ebp+8) %edx) +5052 (string-starts-with? *(ecx+4) "break") +5053 3d/compare-eax-and 0/imm32/false +5054 { +5055 74/jump-if-= break/disp8 +5056 (write-buffered *(ebp+8) ":break/disp32\n") +5057 } +5058 3d/compare-eax-and 0/imm32/false # just in case the function call modified flags +5059 { +5060 75/jump-if-!= break/disp8 +5061 (write-buffered *(ebp+8) ":loop/disp32\n") +5062 } +5063 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end: +5064 # . restore registers +5065 5a/pop-to-edx +5066 59/pop-to-ecx +5067 58/pop-to-eax +5068 # . epilogue +5069 89/<- %esp 5/r32/ebp +5070 5d/pop-to-ebp +5071 c3/return +5072 +5073 is-mu-branch?: # stmt: (addr stmt1) -> result/eax: boolean +5074 # . prologue +5075 55/push-ebp +5076 89/<- %ebp 4/r32/esp +5077 # . save registers +5078 51/push-ecx +5079 # ecx = stmt +5080 8b/-> *(ebp+8) 1/r32/ecx +5081 # if (stmt->operation starts with "loop") return true +5082 (string-starts-with? *(ecx+4) "loop") # Stmt1-operation => eax +5083 3d/compare-eax-and 0/imm32/false +5084 75/jump-if-not-equal $is-mu-branch?:end/disp8 +5085 # otherwise return (stmt->operation starts with "break") +5086 (string-starts-with? *(ecx+4) "break") # Stmt1-operation => eax +5087 $is-mu-branch?:end: +5088 # . restore registers +5089 59/pop-to-ecx +5090 # . epilogue +5091 89/<- %esp 5/r32/ebp +5092 5d/pop-to-ebp +5093 c3/return +5094 +5095 emit-reverse-break: # out: (addr buffered-file), stmt: (addr stmt1) +5096 # . prologue +5097 55/push-ebp +5098 89/<- %ebp 4/r32/esp +5099 # . save registers +5100 50/push-eax +5101 # eax = stmt +5102 8b/-> *(ebp+0xc) 0/r32/eax +5103 # +5104 (get Reverse-branch *(eax+4) 8 "reverse-branch: ") # Stmt1-operation => eax: (addr addr array byte) +5105 (emit-indent *(ebp+8) *Curr-block-depth) +5106 (write-buffered *(ebp+8) *eax) +5107 (write-buffered *(ebp+8) " break/disp32\n") +5108 $emit-reverse-break:end: +5109 # . restore registers +5110 58/pop-to-eax +5111 # . epilogue +5112 89/<- %esp 5/r32/ebp +5113 5d/pop-to-ebp +5114 c3/return +5115 +5116 == data +5117 +5118 Reverse-branch: # (table string string) +5119 # a table is a stream +5120 0xa0/imm32/write +5121 0/imm32/read +5122 0xa0/imm32/length +5123 # data +5124 "break-if-="/imm32 "0f 85/jump-if-!="/imm32 +5125 "loop-if-="/imm32 "0f 85/jump-if-!="/imm32 +5126 "break-if-!="/imm32 "0f 84/jump-if-="/imm32 +5127 "loop-if-!="/imm32 "0f 84/jump-if-="/imm32 +5128 "break-if-<"/imm32 "0f 8d/jump-if->="/imm32 +5129 "loop-if-<"/imm32 "0f 8d/jump-if->="/imm32 +5130 "break-if->"/imm32 "0f 8e/jump-if-<="/imm32 +5131 "loop-if->"/imm32 "0f 8e/jump-if-<="/imm32 +5132 "break-if-<="/imm32 "0f 87/jump-if->"/imm32 +5133 "loop-if-<="/imm32 "0f 87/jump-if->"/imm32 +5134 "break-if->="/imm32 "0f 8c/jump-if-<"/imm32 +5135 "loop-if->="/imm32 "0f 8c/jump-if-<"/imm32 +5136 "break-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 +5137 "loop-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 +5138 "break-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 +5139 "loop-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 +5140 "break-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 +5141 "loop-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 +5142 "break-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 +5143 "loop-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 +5144 +5145 == code +5146 +5147 emit-unconditional-jump-to-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), depth: int, label-suffix: (addr array byte) +5148 # . prologue +5149 55/push-ebp +5150 89/<- %ebp 4/r32/esp +5151 # . save registers +5152 50/push-eax +5153 51/push-ecx +5154 52/push-edx +5155 53/push-ebx +5156 # ecx = vars +5157 8b/-> *(ebp+0xc) 1/r32/ecx +5158 # var eax: int = vars->top +5159 8b/-> *ecx 0/r32/eax +5160 # var min/ecx: (address (handle var)) = vars->data +5161 81 0/subop/add %ecx 8/imm32 +5162 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] +5163 81 5/subop/subtract %eax 4/imm32 +5164 8d/copy-address *(ecx+eax) 0/r32/eax +5165 # edx = depth +5166 8b/-> *(ebp+0x10) 2/r32/edx +5167 { +5168 $emit-unconditional-jump-to-depth:loop: +5169 # if (curr < min) break +5170 39/compare %eax 1/r32/ecx +5171 0f 82/jump-if-addr< break/disp32 +5172 # var v/ebx: (handle var) = *curr +5173 8b/-> *eax 3/r32/ebx +5174 # if (v->block-depth < until-block-depth) break +5175 39/compare *(ebx+8) 2/r32/edx # Var-block-depth +5176 0f 8c/jump-if-< break/disp32 +5177 { +5178 $emit-unconditional-jump-to-depth:check: +5179 # if v->block-depth != until-block-depth, continue +5180 39/compare *(ebx+8) 2/r32/edx # Var-block-depth +5181 0f 85/jump-if-!= break/disp32 +5182 $emit-unconditional-jump-to-depth:depth-found: +5183 # if v is not a literal, continue +5184 # . var eax: int = size-of(v) +5185 50/push-eax +5186 (size-of %ebx) # => eax +5187 # . if (eax != 0) continue +5188 3d/compare-eax-and 0/imm32 +5189 58/pop-to-eax +5190 # +5191 0f 85/jump-if-!= break/disp32 +5192 $emit-unconditional-jump-to-depth:label-found: +5193 # emit unconditional jump, then return +5194 (emit-indent *(ebp+8) *Curr-block-depth) +5195 (write-buffered *(ebp+8) "e9/jump ") +5196 (write-buffered *(ebp+8) *ebx) # Var-name +5197 (write-buffered *(ebp+8) ":") +5198 (write-buffered *(ebp+8) *(ebp+0x14)) +5199 (write-buffered *(ebp+8) "/disp32\n") +5200 eb/jump $emit-unconditional-jump-to-depth:end/disp8 +5201 } +5202 # curr -= 4 +5203 2d/subtract-from-eax 4/imm32 +5204 e9/jump loop/disp32 +5205 } +5206 # TODO: error if no label at 'depth' was found +5207 $emit-unconditional-jump-to-depth:end: +5208 # . restore registers +5209 5b/pop-to-ebx +5210 5a/pop-to-edx +5211 59/pop-to-ecx +5212 58/pop-to-eax +5213 # . epilogue +5214 89/<- %esp 5/r32/ebp +5215 5d/pop-to-ebp +5216 c3/return +5217 +5218 # emit clean-up code for 'vars' until some block depth +5219 # doesn't actually modify 'vars' so we need traverse manually inside the stack +5220 emit-cleanup-code-until-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-depth: int +5221 # . prologue +5222 55/push-ebp +5223 89/<- %ebp 4/r32/esp +5224 # . save registers +5225 50/push-eax +5226 51/push-ecx +5227 52/push-edx +5228 53/push-ebx +5229 # ecx = vars +5230 8b/-> *(ebp+0xc) 1/r32/ecx +5231 # var eax: int = vars->top +5232 8b/-> *ecx 0/r32/eax +5233 # var min/ecx: (address (handle var)) = vars->data +5234 81 0/subop/add %ecx 8/imm32 +5235 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] +5236 81 5/subop/subtract %eax 4/imm32 +5237 8d/copy-address *(ecx+eax) 0/r32/eax +5238 # edx = until-block-depth +5239 8b/-> *(ebp+0x10) 2/r32/edx +5240 { +5241 $emit-cleanup-code-until-depth:loop: +5242 # if (curr < min) break +5243 39/compare %eax 1/r32/ecx +5244 0f 82/jump-if-addr< break/disp32 +5245 # var v/ebx: (handle var) = *curr +5246 8b/-> *eax 3/r32/ebx +5247 # if (v->block-depth < until-block-depth) break +5248 39/compare *(ebx+8) 2/r32/edx # Var-block-depth +5249 0f 8c/jump-if-< break/disp32 +5250 # if v is in a register +5251 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register +5252 { +5253 74/jump-if-= break/disp8 +5254 $emit-cleanup-code-until-depth:reclaim-var-in-register: +5255 (emit-indent *(ebp+8) *Curr-block-depth) +5256 (write-buffered *(ebp+8) "8f 0/subop/pop %") +5257 (write-buffered *(ebp+8) *(ebx+0x10)) +5258 (write-buffered *(ebp+8) Newline) +5259 } +5260 # otherwise v is on the stack +5261 { +5262 75/jump-if-!= break/disp8 +5263 $emit-cleanup-code-until-depth:reclaim-var-on-stack: +5264 50/push-eax +5265 (size-of %ebx) # => eax +5266 # don't emit code for labels +5267 3d/compare-eax-and 0/imm32 +5268 74/jump-if-= break/disp8 +5269 # +5270 (emit-indent *(ebp+8) *Curr-block-depth) +5271 (write-buffered *(ebp+8) "81 0/subop/add %esp ") +5272 (print-int32-buffered *(ebp+8) %eax) +5273 (write-buffered *(ebp+8) "/imm32\n") +5274 58/pop-to-eax +5275 } +5276 # curr -= 4 +5277 2d/subtract-from-eax 4/imm32 +5278 e9/jump loop/disp32 +5279 } +5280 $emit-cleanup-code-until-depth:end: +5281 # . restore registers +5282 5b/pop-to-ebx +5283 5a/pop-to-edx +5284 59/pop-to-ecx +5285 58/pop-to-eax +5286 # . epilogue +5287 89/<- %esp 5/r32/ebp +5288 5d/pop-to-ebp +5289 c3/return +5290 +5291 # emit clean-up code for 'vars' until a given label is encountered +5292 # doesn't actually modify 'vars' so we need traverse manually inside the stack +5293 emit-cleanup-code-until-target: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-label: (addr array byte) +5294 # . prologue +5295 55/push-ebp +5296 89/<- %ebp 4/r32/esp +5297 # . save registers +5298 50/push-eax +5299 51/push-ecx +5300 52/push-edx +5301 53/push-ebx +5302 # ecx = vars +5303 8b/-> *(ebp+0xc) 1/r32/ecx +5304 # var eax: int = vars->top +5305 8b/-> *ecx 0/r32/eax +5306 # var min/ecx: (address (handle var)) = vars->data +5307 81 0/subop/add %ecx 8/imm32 +5308 # var curr/edx: (address (handle var)) = &vars->data[vars->top - 4] +5309 81 5/subop/subtract %eax 4/imm32 +5310 8d/copy-address *(ecx+eax) 2/r32/edx +5311 { +5312 $emit-cleanup-code-until-target:loop: +5313 # if (curr < min) break +5314 39/compare %edx 1/r32/ecx +5315 0f 82/jump-if-addr< break/disp32 +5316 # var v/ebx: (handle var) = *curr +5317 8b/-> *edx 3/r32/ebx +5318 # if (v->name == until-block-label) break +5319 (string-equal? *ebx *(ebp+0x10)) # => eax +5320 3d/compare-eax-and 0/imm32/false +5321 0f 85/jump-if-!= break/disp32 +5322 # if v is in a register +5323 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register +5324 { +5325 74/jump-if-= break/disp8 +5326 $emit-cleanup-code-until-target:reclaim-var-in-register: +5327 (emit-indent *(ebp+8) *Curr-block-depth) +5328 (write-buffered *(ebp+8) "8f 0/subop/pop %") +5329 (write-buffered *(ebp+8) *(ebx+0x10)) +5330 (write-buffered *(ebp+8) Newline) +5331 } +5332 # otherwise v is on the stack +5333 { +5334 75/jump-if-!= break/disp8 +5335 $emit-cleanup-code-until-target:reclaim-var-on-stack: +5336 (size-of %ebx) # => eax +5337 # don't emit code for labels +5338 3d/compare-eax-and 0/imm32 +5339 74/jump-if-= break/disp8 +5340 # +5341 (emit-indent *(ebp+8) *Curr-block-depth) +5342 (write-buffered *(ebp+8) "81 0/subop/add %esp ") +5343 (print-int32-buffered *(ebp+8) %eax) +5344 (write-buffered *(ebp+8) "/imm32\n") +5345 } +5346 # curr -= 4 +5347 81 5/subop/subtract %edx 4/imm32 +5348 e9/jump loop/disp32 +5349 } +5350 $emit-cleanup-code-until-target:end: +5351 # . restore registers +5352 5b/pop-to-ebx +5353 5a/pop-to-edx +5354 59/pop-to-ecx +5355 58/pop-to-eax +5356 # . epilogue +5357 89/<- %esp 5/r32/ebp +5358 5d/pop-to-ebp +5359 c3/return +5360 +5361 # clean up global state for 'vars' until some block depth +5362 clean-up-blocks: # vars: (addr stack (handle var)), until-block-depth: int +5363 # . prologue +5364 55/push-ebp +5365 89/<- %ebp 4/r32/esp +5366 # . save registers +5367 50/push-eax +5368 51/push-ecx +5369 56/push-esi +5370 # esi = vars +5371 8b/-> *(ebp+8) 6/r32/esi +5372 # ecx = until-block-depth +5373 8b/-> *(ebp+0xc) 1/r32/ecx 5374 { -5375 $emit-subx-statement:check-for-call: -5376 (find-matching-function *(ebp+0x14) *(ebp+0xc)) # functions, stmt => curr/eax -5377 3d/compare-eax-and 0/imm32 -5378 74/jump-if-= break/disp8 -5379 $emit-subx-statement:call: -5380 (emit-subx-call *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr -5381 e9/jump $emit-subx-statement:end/disp32 -5382 } -5383 # else assume it's a SubX function (TODO: how to type-check?!) -5384 (emit-hailmary-call *(ebp+8) *(ebp+0xc)) -5385 $emit-subx-statement:end: -5386 # . restore registers -5387 59/pop-to-ecx -5388 58/pop-to-eax -5389 # . epilogue -5390 89/<- %esp 5/r32/ebp -5391 5d/pop-to-ebp -5392 c3/return -5393 -5394 $emit-subx-statement:abort: -5395 # error("couldn't translate '" stmt "'\n") -5396 (write-buffered Stderr "couldn't translate an instruction with operation '") -5397 8b/-> *(ebp+0xc) 0/r32/eax -5398 (write-buffered Stderr *(eax+4)) # Stmt1-operation -5399 (write-buffered Stderr "'\n") -5400 (flush Stderr) -5401 # . syscall(exit, 1) -5402 bb/copy-to-ebx 1/imm32 -5403 b8/copy-to-eax 1/imm32/exit -5404 cd/syscall 0x80/imm8 -5405 # never gets here -5406 -5407 emit-subx-block: # out: (addr buffered-file), block: (handle block), vars: (addr stack (handle var)) -5408 # . prologue -5409 55/push-ebp -5410 89/<- %ebp 4/r32/esp -5411 # . save registers -5412 50/push-eax -5413 51/push-ecx -5414 56/push-esi -5415 # esi = block -5416 8b/-> *(ebp+0xc) 6/r32/esi -5417 # var stmts/eax: (handle list statement) = block->statements -5418 8b/-> *(esi+4) 0/r32/eax # Block-statements -5419 # -5420 { -5421 $emit-subx-block:check-empty: -5422 81 7/subop/compare %eax 0/imm32 -5423 0f 84/jump-if-= break/disp32 -5424 (emit-indent *(ebp+8) *Curr-block-depth) -5425 (write-buffered *(ebp+8) "{\n") -5426 # var v/ecx: (addr array byte) = block->var->name -5427 8b/-> *(esi+8) 1/r32/ecx # Block-var -5428 (write-buffered *(ebp+8) *ecx) # Var-name -5429 (write-buffered *(ebp+8) ":loop:\n") -5430 ff 0/subop/increment *Curr-block-depth -5431 (push *(ebp+0x10) %ecx) -5432 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10)) -5433 (pop *(ebp+0x10)) # => eax -5434 ff 1/subop/decrement *Curr-block-depth -5435 (emit-indent *(ebp+8) *Curr-block-depth) -5436 (write-buffered *(ebp+8) "}\n") -5437 (write-buffered *(ebp+8) *ecx) # Var-name -5438 (write-buffered *(ebp+8) ":break:\n") -5439 } -5440 $emit-subx-block:end: -5441 # . restore registers -5442 5e/pop-to-esi -5443 59/pop-to-ecx -5444 58/pop-to-eax -5445 # . epilogue -5446 89/<- %esp 5/r32/ebp -5447 5d/pop-to-ebp -5448 c3/return -5449 -5450 # Primitives supported -5451 # For each operation, put variants with hard-coded registers before flexible ones. -5452 == data -5453 Primitives: -5454 # - increment/decrement -5455 _Primitive-inc-eax: -5456 # var/eax <- increment => 40/increment-eax -5457 "increment"/imm32/name -5458 0/imm32/no-inouts -5459 Single-int-var-in-eax/imm32/outputs -5460 "40/increment-eax"/imm32/subx-name -5461 0/imm32/no-rm32 -5462 0/imm32/no-r32 -5463 0/imm32/no-imm32 -5464 0/imm32/no-disp32 -5465 0/imm32/output-is-write-only -5466 _Primitive-inc-ecx/imm32/next -5467 _Primitive-inc-ecx: -5468 # var/ecx <- increment => 41/increment-ecx -5469 "increment"/imm32/name -5470 0/imm32/no-inouts -5471 Single-int-var-in-ecx/imm32/outputs -5472 "41/increment-ecx"/imm32/subx-name -5473 0/imm32/no-rm32 -5474 0/imm32/no-r32 -5475 0/imm32/no-imm32 -5476 0/imm32/no-disp32 -5477 0/imm32/output-is-write-only -5478 _Primitive-inc-edx/imm32/next -5479 _Primitive-inc-edx: -5480 # var/edx <- increment => 42/increment-edx -5481 "increment"/imm32/name -5482 0/imm32/no-inouts -5483 Single-int-var-in-edx/imm32/outputs -5484 "42/increment-edx"/imm32/subx-name -5485 0/imm32/no-rm32 -5486 0/imm32/no-r32 -5487 0/imm32/no-imm32 -5488 0/imm32/no-disp32 -5489 0/imm32/output-is-write-only -5490 _Primitive-inc-ebx/imm32/next -5491 _Primitive-inc-ebx: -5492 # var/ebx <- increment => 43/increment-ebx -5493 "increment"/imm32/name -5494 0/imm32/no-inouts -5495 Single-int-var-in-ebx/imm32/outputs -5496 "43/increment-ebx"/imm32/subx-name -5497 0/imm32/no-rm32 -5498 0/imm32/no-r32 -5499 0/imm32/no-imm32 -5500 0/imm32/no-disp32 -5501 0/imm32/output-is-write-only -5502 _Primitive-inc-esi/imm32/next -5503 _Primitive-inc-esi: -5504 # var/esi <- increment => 46/increment-esi -5505 "increment"/imm32/name -5506 0/imm32/no-inouts -5507 Single-int-var-in-esi/imm32/outputs -5508 "46/increment-esi"/imm32/subx-name -5509 0/imm32/no-rm32 -5510 0/imm32/no-r32 -5511 0/imm32/no-imm32 -5512 0/imm32/no-disp32 -5513 0/imm32/output-is-write-only -5514 _Primitive-inc-edi/imm32/next -5515 _Primitive-inc-edi: -5516 # var/edi <- increment => 47/increment-edi -5517 "increment"/imm32/name -5518 0/imm32/no-inouts -5519 Single-int-var-in-edi/imm32/outputs -5520 "47/increment-edi"/imm32/subx-name -5521 0/imm32/no-rm32 -5522 0/imm32/no-r32 -5523 0/imm32/no-imm32 -5524 0/imm32/no-disp32 -5525 0/imm32/output-is-write-only -5526 _Primitive-dec-eax/imm32/next -5527 _Primitive-dec-eax: -5528 # var/eax <- decrement => 48/decrement-eax -5529 "decrement"/imm32/name -5530 0/imm32/no-inouts -5531 Single-int-var-in-eax/imm32/outputs -5532 "48/decrement-eax"/imm32/subx-name -5533 0/imm32/no-rm32 -5534 0/imm32/no-r32 -5535 0/imm32/no-imm32 -5536 0/imm32/no-disp32 -5537 0/imm32/output-is-write-only -5538 _Primitive-dec-ecx/imm32/next -5539 _Primitive-dec-ecx: -5540 # var/ecx <- decrement => 49/decrement-ecx -5541 "decrement"/imm32/name -5542 0/imm32/no-inouts -5543 Single-int-var-in-ecx/imm32/outputs -5544 "49/decrement-ecx"/imm32/subx-name -5545 0/imm32/no-rm32 -5546 0/imm32/no-r32 -5547 0/imm32/no-imm32 -5548 0/imm32/no-disp32 -5549 0/imm32/output-is-write-only -5550 _Primitive-dec-edx/imm32/next -5551 _Primitive-dec-edx: -5552 # var/edx <- decrement => 4a/decrement-edx -5553 "decrement"/imm32/name -5554 0/imm32/no-inouts -5555 Single-int-var-in-edx/imm32/outputs -5556 "4a/decrement-edx"/imm32/subx-name -5557 0/imm32/no-rm32 -5558 0/imm32/no-r32 -5559 0/imm32/no-imm32 -5560 0/imm32/no-disp32 -5561 0/imm32/output-is-write-only -5562 _Primitive-dec-ebx/imm32/next -5563 _Primitive-dec-ebx: -5564 # var/ebx <- decrement => 4b/decrement-ebx -5565 "decrement"/imm32/name -5566 0/imm32/no-inouts -5567 Single-int-var-in-ebx/imm32/outputs -5568 "4b/decrement-ebx"/imm32/subx-name -5569 0/imm32/no-rm32 -5570 0/imm32/no-r32 -5571 0/imm32/no-imm32 -5572 0/imm32/no-disp32 -5573 0/imm32/output-is-write-only -5574 _Primitive-dec-esi/imm32/next -5575 _Primitive-dec-esi: -5576 # var/esi <- decrement => 4e/decrement-esi -5577 "decrement"/imm32/name -5578 0/imm32/no-inouts -5579 Single-int-var-in-esi/imm32/outputs -5580 "4e/decrement-esi"/imm32/subx-name -5581 0/imm32/no-rm32 -5582 0/imm32/no-r32 -5583 0/imm32/no-imm32 -5584 0/imm32/no-disp32 -5585 0/imm32/output-is-write-only -5586 _Primitive-dec-edi/imm32/next -5587 _Primitive-dec-edi: -5588 # var/edi <- decrement => 4f/decrement-edi -5589 "decrement"/imm32/name -5590 0/imm32/no-inouts -5591 Single-int-var-in-edi/imm32/outputs -5592 "4f/decrement-edi"/imm32/subx-name -5593 0/imm32/no-rm32 -5594 0/imm32/no-r32 -5595 0/imm32/no-imm32 -5596 0/imm32/no-disp32 -5597 0/imm32/output-is-write-only -5598 _Primitive-inc-mem/imm32/next -5599 _Primitive-inc-mem: -5600 # increment var => ff 0/subop/increment *(ebp+__) -5601 "increment"/imm32/name -5602 Single-int-var-on-stack/imm32/inouts -5603 0/imm32/no-outputs -5604 "ff 0/subop/increment"/imm32/subx-name -5605 1/imm32/rm32-is-first-inout -5606 0/imm32/no-r32 -5607 0/imm32/no-imm32 -5608 0/imm32/no-disp32 -5609 0/imm32/output-is-write-only -5610 _Primitive-inc-reg/imm32/next -5611 _Primitive-inc-reg: -5612 # var/reg <- increment => ff 0/subop/increment %__ -5613 "increment"/imm32/name -5614 0/imm32/no-inouts -5615 Single-int-var-in-some-register/imm32/outputs -5616 "ff 0/subop/increment"/imm32/subx-name -5617 3/imm32/rm32-is-first-output -5618 0/imm32/no-r32 -5619 0/imm32/no-imm32 -5620 0/imm32/no-disp32 -5621 0/imm32/output-is-write-only -5622 _Primitive-dec-mem/imm32/next -5623 _Primitive-dec-mem: -5624 # decrement var => ff 1/subop/decrement *(ebp+__) -5625 "decrement"/imm32/name -5626 Single-int-var-on-stack/imm32/inouts -5627 0/imm32/no-outputs -5628 "ff 1/subop/decrement"/imm32/subx-name -5629 1/imm32/rm32-is-first-inout -5630 0/imm32/no-r32 -5631 0/imm32/no-imm32 -5632 0/imm32/no-disp32 -5633 0/imm32/output-is-write-only -5634 _Primitive-dec-reg/imm32/next -5635 _Primitive-dec-reg: -5636 # var/reg <- decrement => ff 1/subop/decrement %__ -5637 "decrement"/imm32/name -5638 0/imm32/no-inouts -5639 Single-int-var-in-some-register/imm32/outputs -5640 "ff 1/subop/decrement"/imm32/subx-name -5641 3/imm32/rm32-is-first-output -5642 0/imm32/no-r32 -5643 0/imm32/no-imm32 -5644 0/imm32/no-disp32 -5645 0/imm32/output-is-write-only -5646 _Primitive-add-to-eax/imm32/next -5647 # - add -5648 _Primitive-add-to-eax: -5649 # var/eax <- add lit => 05/add-to-eax lit/imm32 -5650 "add"/imm32/name -5651 Single-lit-var/imm32/inouts -5652 Single-int-var-in-eax/imm32/outputs -5653 "05/add-to-eax"/imm32/subx-name -5654 0/imm32/no-rm32 -5655 0/imm32/no-r32 -5656 1/imm32/imm32-is-first-inout -5657 0/imm32/no-disp32 -5658 0/imm32/output-is-write-only -5659 _Primitive-add-reg-to-reg/imm32/next -5660 _Primitive-add-reg-to-reg: -5661 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 -5662 "add"/imm32/name -5663 Single-int-var-in-some-register/imm32/inouts -5664 Single-int-var-in-some-register/imm32/outputs -5665 "01/add-to"/imm32/subx-name -5666 3/imm32/rm32-is-first-output -5667 1/imm32/r32-is-first-inout -5668 0/imm32/no-imm32 -5669 0/imm32/no-disp32 -5670 0/imm32/output-is-write-only -5671 _Primitive-add-reg-to-mem/imm32/next -5672 _Primitive-add-reg-to-mem: -5673 # add-to var1 var2/reg => 01/add-to var1 var2/r32 -5674 "add-to"/imm32/name -5675 Two-args-int-stack-int-reg/imm32/inouts -5676 0/imm32/outputs -5677 "01/add-to"/imm32/subx-name -5678 1/imm32/rm32-is-first-inout -5679 2/imm32/r32-is-second-inout -5680 0/imm32/no-imm32 -5681 0/imm32/no-disp32 -5682 0/imm32/output-is-write-only -5683 _Primitive-add-mem-to-reg/imm32/next -5684 _Primitive-add-mem-to-reg: -5685 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 -5686 "add"/imm32/name -5687 Single-int-var-on-stack/imm32/inouts -5688 Single-int-var-in-some-register/imm32/outputs -5689 "03/add"/imm32/subx-name -5690 1/imm32/rm32-is-first-inout -5691 3/imm32/r32-is-first-output -5692 0/imm32/no-imm32 -5693 0/imm32/no-disp32 -5694 0/imm32/output-is-write-only -5695 _Primitive-add-lit-to-reg/imm32/next -5696 _Primitive-add-lit-to-reg: -5697 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 -5698 "add"/imm32/name -5699 Single-lit-var/imm32/inouts -5700 Single-int-var-in-some-register/imm32/outputs -5701 "81 0/subop/add"/imm32/subx-name -5702 3/imm32/rm32-is-first-output -5703 0/imm32/no-r32 -5704 1/imm32/imm32-is-first-inout -5705 0/imm32/no-disp32 -5706 0/imm32/output-is-write-only -5707 _Primitive-add-lit-to-mem/imm32/next -5708 _Primitive-add-lit-to-mem: -5709 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 -5710 "add-to"/imm32/name -5711 Int-var-and-literal/imm32/inouts -5712 0/imm32/outputs -5713 "81 0/subop/add"/imm32/subx-name -5714 1/imm32/rm32-is-first-inout -5715 0/imm32/no-r32 -5716 2/imm32/imm32-is-second-inout -5717 0/imm32/no-disp32 -5718 0/imm32/output-is-write-only -5719 _Primitive-subtract-from-eax/imm32/next -5720 # - subtract -5721 _Primitive-subtract-from-eax: -5722 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 -5723 "subtract"/imm32/name -5724 Single-lit-var/imm32/inouts -5725 Single-int-var-in-eax/imm32/outputs -5726 "2d/subtract-from-eax"/imm32/subx-name -5727 0/imm32/no-rm32 -5728 0/imm32/no-r32 -5729 1/imm32/imm32-is-first-inout -5730 0/imm32/no-disp32 -5731 0/imm32/output-is-write-only -5732 _Primitive-subtract-reg-from-reg/imm32/next -5733 _Primitive-subtract-reg-from-reg: -5734 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 -5735 "subtract"/imm32/name -5736 Single-int-var-in-some-register/imm32/inouts -5737 Single-int-var-in-some-register/imm32/outputs -5738 "29/subtract-from"/imm32/subx-name -5739 3/imm32/rm32-is-first-output -5740 1/imm32/r32-is-first-inout -5741 0/imm32/no-imm32 -5742 0/imm32/no-disp32 -5743 0/imm32/output-is-write-only -5744 _Primitive-subtract-reg-from-mem/imm32/next -5745 _Primitive-subtract-reg-from-mem: -5746 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 -5747 "subtract-from"/imm32/name -5748 Two-args-int-stack-int-reg/imm32/inouts -5749 0/imm32/outputs -5750 "29/subtract-from"/imm32/subx-name -5751 1/imm32/rm32-is-first-inout -5752 2/imm32/r32-is-second-inout -5753 0/imm32/no-imm32 -5754 0/imm32/no-disp32 -5755 0/imm32/output-is-write-only -5756 _Primitive-subtract-mem-from-reg/imm32/next -5757 _Primitive-subtract-mem-from-reg: -5758 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 -5759 "subtract"/imm32/name -5760 Single-int-var-on-stack/imm32/inouts -5761 Single-int-var-in-some-register/imm32/outputs -5762 "2b/subtract"/imm32/subx-name -5763 1/imm32/rm32-is-first-inout -5764 3/imm32/r32-is-first-output -5765 0/imm32/no-imm32 -5766 0/imm32/no-disp32 -5767 0/imm32/output-is-write-only -5768 _Primitive-subtract-lit-from-reg/imm32/next -5769 _Primitive-subtract-lit-from-reg: -5770 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 -5771 "subtract"/imm32/name -5772 Single-lit-var/imm32/inouts -5773 Single-int-var-in-some-register/imm32/outputs -5774 "81 5/subop/subtract"/imm32/subx-name -5775 3/imm32/rm32-is-first-output -5776 0/imm32/no-r32 -5777 1/imm32/imm32-is-first-inout -5778 0/imm32/no-disp32 -5779 0/imm32/output-is-write-only -5780 _Primitive-subtract-lit-from-mem/imm32/next -5781 _Primitive-subtract-lit-from-mem: -5782 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 -5783 "subtract-from"/imm32/name -5784 Int-var-and-literal/imm32/inouts -5785 0/imm32/outputs -5786 "81 5/subop/subtract"/imm32/subx-name -5787 1/imm32/rm32-is-first-inout -5788 0/imm32/no-r32 -5789 2/imm32/imm32-is-first-inout -5790 0/imm32/no-disp32 -5791 0/imm32/output-is-write-only -5792 _Primitive-and-with-eax/imm32/next -5793 # - and -5794 _Primitive-and-with-eax: -5795 # var/eax <- and lit => 25/and-with-eax lit/imm32 -5796 "and"/imm32/name -5797 Single-lit-var/imm32/inouts -5798 Single-int-var-in-eax/imm32/outputs -5799 "25/and-with-eax"/imm32/subx-name -5800 0/imm32/no-rm32 -5801 0/imm32/no-r32 -5802 1/imm32/imm32-is-first-inout -5803 0/imm32/no-disp32 -5804 0/imm32/output-is-write-only -5805 _Primitive-and-reg-with-reg/imm32/next -5806 _Primitive-and-reg-with-reg: -5807 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 -5808 "and"/imm32/name -5809 Single-int-var-in-some-register/imm32/inouts -5810 Single-int-var-in-some-register/imm32/outputs -5811 "21/and-with"/imm32/subx-name -5812 3/imm32/rm32-is-first-output -5813 1/imm32/r32-is-first-inout -5814 0/imm32/no-imm32 -5815 0/imm32/no-disp32 -5816 0/imm32/output-is-write-only -5817 _Primitive-and-reg-with-mem/imm32/next -5818 _Primitive-and-reg-with-mem: -5819 # and-with var1 var2/reg => 21/and-with var1 var2/r32 -5820 "and-with"/imm32/name -5821 Two-args-int-stack-int-reg/imm32/inouts -5822 0/imm32/outputs -5823 "21/and-with"/imm32/subx-name -5824 1/imm32/rm32-is-first-inout -5825 2/imm32/r32-is-second-inout -5826 0/imm32/no-imm32 -5827 0/imm32/no-disp32 -5828 0/imm32/output-is-write-only -5829 _Primitive-and-mem-with-reg/imm32/next -5830 _Primitive-and-mem-with-reg: -5831 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 -5832 "and"/imm32/name -5833 Single-int-var-on-stack/imm32/inouts -5834 Single-int-var-in-some-register/imm32/outputs -5835 "23/and"/imm32/subx-name -5836 1/imm32/rm32-is-first-inout -5837 3/imm32/r32-is-first-output -5838 0/imm32/no-imm32 -5839 0/imm32/no-disp32 -5840 0/imm32/output-is-write-only -5841 _Primitive-and-lit-with-reg/imm32/next -5842 _Primitive-and-lit-with-reg: -5843 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 -5844 "and"/imm32/name -5845 Single-lit-var/imm32/inouts -5846 Single-int-var-in-some-register/imm32/outputs -5847 "81 4/subop/and"/imm32/subx-name -5848 3/imm32/rm32-is-first-output -5849 0/imm32/no-r32 -5850 1/imm32/imm32-is-first-inout -5851 0/imm32/no-disp32 -5852 0/imm32/output-is-write-only -5853 _Primitive-and-lit-with-mem/imm32/next -5854 _Primitive-and-lit-with-mem: -5855 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 -5856 "and-with"/imm32/name -5857 Int-var-and-literal/imm32/inouts -5858 0/imm32/outputs -5859 "81 4/subop/and"/imm32/subx-name -5860 1/imm32/rm32-is-first-inout -5861 0/imm32/no-r32 -5862 2/imm32/imm32-is-first-inout -5863 0/imm32/no-disp32 -5864 0/imm32/output-is-write-only -5865 _Primitive-or-with-eax/imm32/next -5866 # - or -5867 _Primitive-or-with-eax: -5868 # var/eax <- or lit => 0d/or-with-eax lit/imm32 -5869 "or"/imm32/name -5870 Single-lit-var/imm32/inouts -5871 Single-int-var-in-eax/imm32/outputs -5872 "0d/or-with-eax"/imm32/subx-name -5873 0/imm32/no-rm32 -5874 0/imm32/no-r32 -5875 1/imm32/imm32-is-first-inout -5876 0/imm32/no-disp32 -5877 0/imm32/output-is-write-only -5878 _Primitive-or-reg-with-reg/imm32/next -5879 _Primitive-or-reg-with-reg: -5880 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 -5881 "or"/imm32/name -5882 Single-int-var-in-some-register/imm32/inouts -5883 Single-int-var-in-some-register/imm32/outputs -5884 "09/or-with"/imm32/subx-name -5885 3/imm32/rm32-is-first-output -5886 1/imm32/r32-is-first-inout -5887 0/imm32/no-imm32 -5888 0/imm32/no-disp32 -5889 0/imm32/output-is-write-only -5890 _Primitive-or-reg-with-mem/imm32/next -5891 _Primitive-or-reg-with-mem: -5892 # or-with var1 var2/reg => 09/or-with var1 var2/r32 -5893 "or-with"/imm32/name -5894 Two-args-int-stack-int-reg/imm32/inouts -5895 0/imm32/outputs -5896 "09/or-with"/imm32/subx-name -5897 1/imm32/rm32-is-first-inout -5898 2/imm32/r32-is-second-inout -5899 0/imm32/no-imm32 -5900 0/imm32/no-disp32 -5901 0/imm32/output-is-write-only -5902 _Primitive-or-mem-with-reg/imm32/next -5903 _Primitive-or-mem-with-reg: -5904 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 -5905 "or"/imm32/name -5906 Single-int-var-on-stack/imm32/inouts -5907 Single-int-var-in-some-register/imm32/outputs -5908 "0b/or"/imm32/subx-name -5909 1/imm32/rm32-is-first-inout -5910 3/imm32/r32-is-first-output -5911 0/imm32/no-imm32 -5912 0/imm32/no-disp32 -5913 0/imm32/output-is-write-only -5914 _Primitive-or-lit-with-reg/imm32/next -5915 _Primitive-or-lit-with-reg: -5916 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 -5917 "or"/imm32/name -5918 Single-lit-var/imm32/inouts -5919 Single-int-var-in-some-register/imm32/outputs -5920 "81 1/subop/or"/imm32/subx-name -5921 3/imm32/rm32-is-first-output -5922 0/imm32/no-r32 -5923 1/imm32/imm32-is-first-inout -5924 0/imm32/no-disp32 -5925 0/imm32/output-is-write-only -5926 _Primitive-or-lit-with-mem/imm32/next -5927 _Primitive-or-lit-with-mem: -5928 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 -5929 "or-with"/imm32/name -5930 Int-var-and-literal/imm32/inouts -5931 0/imm32/outputs -5932 "81 1/subop/or"/imm32/subx-name -5933 1/imm32/rm32-is-first-inout -5934 0/imm32/no-r32 -5935 2/imm32/imm32-is-second-inout -5936 0/imm32/no-disp32 -5937 0/imm32/output-is-write-only -5938 _Primitive-xor-with-eax/imm32/next -5939 # - xor -5940 _Primitive-xor-with-eax: -5941 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 -5942 "xor"/imm32/name -5943 Single-lit-var/imm32/inouts -5944 Single-int-var-in-eax/imm32/outputs -5945 "35/xor-with-eax"/imm32/subx-name -5946 0/imm32/no-rm32 -5947 0/imm32/no-r32 -5948 1/imm32/imm32-is-first-inout -5949 0/imm32/no-disp32 -5950 0/imm32/output-is-write-only -5951 _Primitive-xor-reg-with-reg/imm32/next -5952 _Primitive-xor-reg-with-reg: -5953 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 -5954 "xor"/imm32/name -5955 Single-int-var-in-some-register/imm32/inouts -5956 Single-int-var-in-some-register/imm32/outputs -5957 "31/xor-with"/imm32/subx-name -5958 3/imm32/rm32-is-first-output -5959 1/imm32/r32-is-first-inout -5960 0/imm32/no-imm32 -5961 0/imm32/no-disp32 -5962 0/imm32/output-is-write-only -5963 _Primitive-xor-reg-with-mem/imm32/next -5964 _Primitive-xor-reg-with-mem: -5965 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 -5966 "xor-with"/imm32/name -5967 Two-args-int-stack-int-reg/imm32/inouts -5968 0/imm32/outputs -5969 "31/xor-with"/imm32/subx-name -5970 1/imm32/rm32-is-first-inout -5971 2/imm32/r32-is-second-inout -5972 0/imm32/no-imm32 -5973 0/imm32/no-disp32 -5974 0/imm32/output-is-write-only -5975 _Primitive-xor-mem-with-reg/imm32/next -5976 _Primitive-xor-mem-with-reg: -5977 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 -5978 "xor"/imm32/name -5979 Single-int-var-on-stack/imm32/inouts -5980 Single-int-var-in-some-register/imm32/outputs -5981 "33/xor"/imm32/subx-name -5982 1/imm32/rm32-is-first-inout -5983 3/imm32/r32-is-first-output -5984 0/imm32/no-imm32 -5985 0/imm32/no-disp32 -5986 0/imm32/output-is-write-only -5987 _Primitive-xor-lit-with-reg/imm32/next -5988 _Primitive-xor-lit-with-reg: -5989 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 -5990 "xor"/imm32/name -5991 Single-lit-var/imm32/inouts -5992 Single-int-var-in-some-register/imm32/outputs -5993 "81 6/subop/xor"/imm32/subx-name -5994 3/imm32/rm32-is-first-output -5995 0/imm32/no-r32 -5996 1/imm32/imm32-is-first-inout -5997 0/imm32/no-disp32 -5998 0/imm32/output-is-write-only -5999 _Primitive-xor-lit-with-mem/imm32/next -6000 _Primitive-xor-lit-with-mem: -6001 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 -6002 "xor-with"/imm32/name -6003 Int-var-and-literal/imm32/inouts -6004 0/imm32/outputs -6005 "81 6/subop/xor"/imm32/subx-name -6006 1/imm32/rm32-is-first-inout -6007 0/imm32/no-r32 -6008 2/imm32/imm32-is-first-inout -6009 0/imm32/no-disp32 -6010 0/imm32/output-is-write-only -6011 _Primitive-copy-to-eax/imm32/next -6012 # - copy -6013 _Primitive-copy-to-eax: -6014 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 -6015 "copy"/imm32/name -6016 Single-lit-var/imm32/inouts -6017 Single-int-var-in-eax/imm32/outputs -6018 "b8/copy-to-eax"/imm32/subx-name -6019 0/imm32/no-rm32 -6020 0/imm32/no-r32 -6021 1/imm32/imm32-is-first-inout -6022 0/imm32/no-disp32 -6023 1/imm32/output-is-write-only -6024 _Primitive-copy-to-ecx/imm32/next -6025 _Primitive-copy-to-ecx: -6026 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 -6027 "copy"/imm32/name -6028 Single-lit-var/imm32/inouts -6029 Single-int-var-in-ecx/imm32/outputs -6030 "b9/copy-to-ecx"/imm32/subx-name -6031 0/imm32/no-rm32 -6032 0/imm32/no-r32 -6033 1/imm32/imm32-is-first-inout -6034 0/imm32/no-disp32 -6035 1/imm32/output-is-write-only -6036 _Primitive-copy-to-edx/imm32/next -6037 _Primitive-copy-to-edx: -6038 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 -6039 "copy"/imm32/name -6040 Single-lit-var/imm32/inouts -6041 Single-int-var-in-edx/imm32/outputs -6042 "ba/copy-to-edx"/imm32/subx-name -6043 0/imm32/no-rm32 -6044 0/imm32/no-r32 -6045 1/imm32/imm32-is-first-inout -6046 0/imm32/no-disp32 -6047 1/imm32/output-is-write-only -6048 _Primitive-copy-to-ebx/imm32/next -6049 _Primitive-copy-to-ebx: -6050 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 -6051 "copy"/imm32/name -6052 Single-lit-var/imm32/inouts -6053 Single-int-var-in-ebx/imm32/outputs -6054 "bb/copy-to-ebx"/imm32/subx-name -6055 0/imm32/no-rm32 -6056 0/imm32/no-r32 -6057 1/imm32/imm32-is-first-inout -6058 0/imm32/no-disp32 -6059 1/imm32/output-is-write-only -6060 _Primitive-copy-to-esi/imm32/next -6061 _Primitive-copy-to-esi: -6062 # var/esi <- copy lit => be/copy-to-esi lit/imm32 -6063 "copy"/imm32/name -6064 Single-lit-var/imm32/inouts -6065 Single-int-var-in-esi/imm32/outputs -6066 "be/copy-to-esi"/imm32/subx-name -6067 0/imm32/no-rm32 -6068 0/imm32/no-r32 -6069 1/imm32/imm32-is-first-inout -6070 0/imm32/no-disp32 -6071 1/imm32/output-is-write-only -6072 _Primitive-copy-to-edi/imm32/next -6073 _Primitive-copy-to-edi: -6074 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 -6075 "copy"/imm32/name -6076 Single-lit-var/imm32/inouts -6077 Single-int-var-in-edi/imm32/outputs -6078 "bf/copy-to-edi"/imm32/subx-name -6079 0/imm32/no-rm32 -6080 0/imm32/no-r32 -6081 1/imm32/imm32-is-first-inout -6082 0/imm32/no-disp32 -6083 1/imm32/output-is-write-only -6084 _Primitive-copy-reg-to-reg/imm32/next -6085 _Primitive-copy-reg-to-reg: -6086 # var1/reg <- copy var2/reg => 89/copy-to var1/rm32 var2/r32 -6087 "copy"/imm32/name -6088 Single-int-var-in-some-register/imm32/inouts -6089 Single-int-var-in-some-register/imm32/outputs -6090 "89/copy-to"/imm32/subx-name -6091 3/imm32/rm32-is-first-output -6092 1/imm32/r32-is-first-inout -6093 0/imm32/no-imm32 -6094 0/imm32/no-disp32 -6095 1/imm32/output-is-write-only -6096 _Primitive-copy-reg-to-mem/imm32/next -6097 _Primitive-copy-reg-to-mem: -6098 # copy-to var1 var2/reg => 89/copy-to var1 var2/r32 -6099 "copy-to"/imm32/name -6100 Two-args-int-stack-int-reg/imm32/inouts -6101 0/imm32/outputs -6102 "89/copy-to"/imm32/subx-name -6103 1/imm32/rm32-is-first-inout -6104 2/imm32/r32-is-second-inout -6105 0/imm32/no-imm32 -6106 0/imm32/no-disp32 -6107 1/imm32/output-is-write-only -6108 _Primitive-copy-mem-to-reg/imm32/next -6109 _Primitive-copy-mem-to-reg: -6110 # var1/reg <- copy var2 => 8b/copy-from var2/rm32 var1/r32 -6111 "copy"/imm32/name -6112 Single-int-var-on-stack/imm32/inouts -6113 Single-int-var-in-some-register/imm32/outputs -6114 "8b/copy-from"/imm32/subx-name -6115 1/imm32/rm32-is-first-inout -6116 3/imm32/r32-is-first-output -6117 0/imm32/no-imm32 -6118 0/imm32/no-disp32 -6119 1/imm32/output-is-write-only -6120 _Primitive-copy-lit-to-reg/imm32/next -6121 _Primitive-copy-lit-to-reg: -6122 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 -6123 "copy"/imm32/name -6124 Single-lit-var/imm32/inouts -6125 Single-int-var-in-some-register/imm32/outputs -6126 "c7 0/subop/copy"/imm32/subx-name -6127 3/imm32/rm32-is-first-output -6128 0/imm32/no-r32 -6129 1/imm32/imm32-is-first-inout -6130 0/imm32/no-disp32 -6131 1/imm32/output-is-write-only -6132 _Primitive-copy-lit-to-mem/imm32/next -6133 _Primitive-copy-lit-to-mem: -6134 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 -6135 "copy-to"/imm32/name -6136 Int-var-and-literal/imm32/inouts -6137 0/imm32/outputs -6138 "c7 0/subop/copy"/imm32/subx-name -6139 1/imm32/rm32-is-first-inout -6140 0/imm32/no-r32 -6141 2/imm32/imm32-is-first-inout -6142 0/imm32/no-disp32 -6143 1/imm32/output-is-write-only -6144 _Primitive-compare-mem-with-reg/imm32/next -6145 # - compare -6146 _Primitive-compare-mem-with-reg: -6147 # compare var1 var2/reg => 39/compare-> var1/rm32 var2/r32 -6148 "compare"/imm32/name -6149 Two-args-int-stack-int-reg/imm32/inouts -6150 0/imm32/outputs -6151 "39/compare->"/imm32/subx-name -6152 1/imm32/rm32-is-first-inout -6153 2/imm32/r32-is-second-inout -6154 0/imm32/no-imm32 -6155 0/imm32/no-disp32 -6156 0/imm32/output-is-write-only -6157 _Primitive-compare-reg-with-mem/imm32/next -6158 _Primitive-compare-reg-with-mem: -6159 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 -6160 "compare"/imm32/name -6161 Two-args-int-reg-int-stack/imm32/inouts -6162 0/imm32/outputs -6163 "3b/compare<-"/imm32/subx-name -6164 2/imm32/rm32-is-second-inout -6165 1/imm32/r32-is-first-inout -6166 0/imm32/no-imm32 -6167 0/imm32/no-disp32 -6168 0/imm32/output-is-write-only -6169 _Primitive-compare-eax-with-literal/imm32/next -6170 _Primitive-compare-eax-with-literal: -6171 # compare var1/eax n => 3d/compare-eax-with n/imm32 -6172 "compare"/imm32/name -6173 Two-args-int-eax-int-literal/imm32/inouts -6174 0/imm32/outputs -6175 "3d/compare-eax-with"/imm32/subx-name -6176 0/imm32/no-rm32 -6177 0/imm32/no-r32 -6178 2/imm32/imm32-is-second-inout -6179 0/imm32/no-disp32 -6180 0/imm32/output-is-write-only -6181 _Primitive-compare-regmem-with-literal/imm32/next -6182 _Primitive-compare-regmem-with-literal: -6183 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 -6184 "compare"/imm32/name -6185 Int-var-and-literal/imm32/inouts -6186 0/imm32/outputs -6187 "81 7/subop/compare"/imm32/subx-name -6188 1/imm32/rm32-is-first-inout -6189 0/imm32/no-r32 -6190 2/imm32/imm32-is-second-inout -6191 0/imm32/no-disp32 -6192 0/imm32/output-is-write-only -6193 _Primitive-multiply-reg-by-mem/imm32/next -6194 # - multiply -6195 _Primitive-multiply-reg-by-mem: -6196 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 -6197 "multiply"/imm32/name -6198 Single-int-var-on-stack/imm32/inouts -6199 Single-int-var-in-some-register/imm32/outputs -6200 "0f af/multiply"/imm32/subx-name -6201 1/imm32/rm32-is-first-inout -6202 3/imm32/r32-is-first-output -6203 0/imm32/no-imm32 -6204 0/imm32/no-disp32 -6205 0/imm32/output-is-write-only -6206 _Primitive-break-if-addr</imm32/next -6207 # - branches -6208 _Primitive-break-if-addr<: -6209 "break-if-addr<"/imm32/name -6210 0/imm32/inouts -6211 0/imm32/outputs -6212 "0f 82/jump-if-addr< break/disp32"/imm32/subx-name -6213 0/imm32/no-rm32 -6214 0/imm32/no-r32 -6215 0/imm32/no-imm32 -6216 0/imm32/no-disp32 -6217 0/imm32/no-output -6218 _Primitive-break-if-addr>=/imm32/next -6219 _Primitive-break-if-addr>=: -6220 "break-if-addr>="/imm32/name -6221 0/imm32/inouts -6222 0/imm32/outputs -6223 "0f 83/jump-if-addr>= break/disp32"/imm32/subx-name -6224 0/imm32/no-rm32 -6225 0/imm32/no-r32 -6226 0/imm32/no-imm32 -6227 0/imm32/no-disp32 -6228 0/imm32/no-output -6229 _Primitive-break-if-=/imm32/next -6230 _Primitive-break-if-=: -6231 "break-if-="/imm32/name -6232 0/imm32/inouts -6233 0/imm32/outputs -6234 "0f 84/jump-if-= break/disp32"/imm32/subx-name -6235 0/imm32/no-rm32 -6236 0/imm32/no-r32 -6237 0/imm32/no-imm32 -6238 0/imm32/no-disp32 -6239 0/imm32/no-output -6240 _Primitive-break-if-!=/imm32/next -6241 _Primitive-break-if-!=: -6242 "break-if-!="/imm32/name -6243 0/imm32/inouts +5375 $clean-up-blocks:reclaim-loop: +5376 # if (vars->top <= 0) break +5377 81 7/subop/compare *esi 0/imm32 # Stack-top +5378 7e/jump-if-<= break/disp8 +5379 # var v/eax: (handle var) = top(vars) +5380 (top %esi) # => eax +5381 # if (v->block-depth < until-block-depth) break +5382 39/compare *(eax+8) 1/r32/ecx # Var-block-depth +5383 7c/jump-if-< break/disp8 +5384 # if v is on the stack, update Next-local-stack-offset +5385 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register +5386 { +5387 75/jump-if-!= break/disp8 +5388 $clean-up-blocks:reclaim-var-on-stack: +5389 (size-of %eax) # => eax +5390 01/add *Next-local-stack-offset 0/r32/eax +5391 } +5392 (pop %esi) +5393 e9/jump loop/disp32 +5394 } +5395 $clean-up-blocks:end: +5396 # . restore registers +5397 5e/pop-to-esi +5398 59/pop-to-ecx +5399 58/pop-to-eax +5400 # . epilogue +5401 89/<- %esp 5/r32/ebp +5402 5d/pop-to-ebp +5403 c3/return +5404 +5405 emit-subx-var-def: # out: (addr buffered-file), stmt: (handle statement) +5406 # . prologue +5407 55/push-ebp +5408 89/<- %ebp 4/r32/esp +5409 # . save registers +5410 50/push-eax +5411 51/push-ecx +5412 # eax = stmt +5413 8b/-> *(ebp+0xc) 0/r32/eax +5414 # var n/eax: int = size-of(stmt->var) +5415 (size-of *(eax+4)) # Vardef-var => eax +5416 # while n > 0 +5417 { +5418 3d/compare-eax-with 0/imm32 +5419 7e/jump-if-<= break/disp8 +5420 (emit-indent *(ebp+8) *Curr-block-depth) +5421 (write-buffered *(ebp+8) "68/push 0/imm32\n") +5422 # n -= 4 +5423 2d/subtract-from-eax 4/imm32 +5424 # +5425 eb/jump loop/disp8 +5426 } +5427 $emit-subx-var-def:end: +5428 # . restore registers +5429 59/pop-to-ecx +5430 58/pop-to-eax +5431 # . epilogue +5432 89/<- %esp 5/r32/ebp +5433 5d/pop-to-ebp +5434 c3/return +5435 +5436 emit-subx-statement: # out: (addr buffered-file), stmt: (handle statement), primitives: (handle primitive), functions: (handle function) +5437 # . prologue +5438 55/push-ebp +5439 89/<- %ebp 4/r32/esp +5440 # . save registers +5441 50/push-eax +5442 51/push-ecx +5443 # handle some special cases +5444 # ecx = stmt +5445 8b/-> *(ebp+0xc) 1/r32/ecx +5446 +-- 24 lines: # array length ------------------------------------------------------------------------------------------------------------------------------------------------------------ +5470 # if stmt matches a primitive, emit it +5471 { +5472 $emit-subx-statement:check-for-primitive: +5473 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => curr/eax +5474 3d/compare-eax-and 0/imm32 +5475 74/jump-if-= break/disp8 +5476 $emit-subx-statement:primitive: +5477 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr +5478 e9/jump $emit-subx-statement:end/disp32 +5479 } +5480 # else if stmt matches a function, emit a call to it +5481 { +5482 $emit-subx-statement:check-for-call: +5483 (find-matching-function *(ebp+0x14) *(ebp+0xc)) # functions, stmt => curr/eax +5484 3d/compare-eax-and 0/imm32 +5485 74/jump-if-= break/disp8 +5486 $emit-subx-statement:call: +5487 (emit-subx-call *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr +5488 e9/jump $emit-subx-statement:end/disp32 +5489 } +5490 # else assume it's a SubX function (TODO: how to type-check?!) +5491 (emit-hailmary-call *(ebp+8) *(ebp+0xc)) +5492 $emit-subx-statement:end: +5493 # . restore registers +5494 59/pop-to-ecx +5495 58/pop-to-eax +5496 # . epilogue +5497 89/<- %esp 5/r32/ebp +5498 5d/pop-to-ebp +5499 c3/return +5500 +5501 $emit-subx-statement:abort: +5502 # error("couldn't translate '" stmt "'\n") +5503 (write-buffered Stderr "couldn't translate an instruction with operation '") +5504 8b/-> *(ebp+0xc) 0/r32/eax +5505 (write-buffered Stderr *(eax+4)) # Stmt1-operation +5506 (write-buffered Stderr "'\n") +5507 (flush Stderr) +5508 # . syscall(exit, 1) +5509 bb/copy-to-ebx 1/imm32 +5510 b8/copy-to-eax 1/imm32/exit +5511 cd/syscall 0x80/imm8 +5512 # never gets here +5513 +5514 emit-subx-block: # out: (addr buffered-file), block: (handle block), vars: (addr stack (handle var)) +5515 # . prologue +5516 55/push-ebp +5517 89/<- %ebp 4/r32/esp +5518 # . save registers +5519 50/push-eax +5520 51/push-ecx +5521 56/push-esi +5522 # esi = block +5523 8b/-> *(ebp+0xc) 6/r32/esi +5524 # var stmts/eax: (handle list statement) = block->statements +5525 8b/-> *(esi+4) 0/r32/eax # Block-statements +5526 # +5527 { +5528 $emit-subx-block:check-empty: +5529 81 7/subop/compare %eax 0/imm32 +5530 0f 84/jump-if-= break/disp32 +5531 (emit-indent *(ebp+8) *Curr-block-depth) +5532 (write-buffered *(ebp+8) "{\n") +5533 # var v/ecx: (addr array byte) = block->var->name +5534 8b/-> *(esi+8) 1/r32/ecx # Block-var +5535 (write-buffered *(ebp+8) *ecx) # Var-name +5536 (write-buffered *(ebp+8) ":loop:\n") +5537 ff 0/subop/increment *Curr-block-depth +5538 (push *(ebp+0x10) %ecx) +5539 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10)) +5540 (pop *(ebp+0x10)) # => eax +5541 ff 1/subop/decrement *Curr-block-depth +5542 (emit-indent *(ebp+8) *Curr-block-depth) +5543 (write-buffered *(ebp+8) "}\n") +5544 (write-buffered *(ebp+8) *ecx) # Var-name +5545 (write-buffered *(ebp+8) ":break:\n") +5546 } +5547 $emit-subx-block:end: +5548 # . restore registers +5549 5e/pop-to-esi +5550 59/pop-to-ecx +5551 58/pop-to-eax +5552 # . epilogue +5553 89/<- %esp 5/r32/ebp +5554 5d/pop-to-ebp +5555 c3/return +5556 +5557 # Primitives supported +5558 # For each operation, put variants with hard-coded registers before flexible ones. +5559 == data +5560 Primitives: +5561 # - increment/decrement +5562 _Primitive-inc-eax: +5563 # var/eax <- increment => 40/increment-eax +5564 "increment"/imm32/name +5565 0/imm32/no-inouts +5566 Single-int-var-in-eax/imm32/outputs +5567 "40/increment-eax"/imm32/subx-name +5568 0/imm32/no-rm32 +5569 0/imm32/no-r32 +5570 0/imm32/no-imm32 +5571 0/imm32/no-disp32 +5572 0/imm32/output-is-write-only +5573 _Primitive-inc-ecx/imm32/next +5574 _Primitive-inc-ecx: +5575 # var/ecx <- increment => 41/increment-ecx +5576 "increment"/imm32/name +5577 0/imm32/no-inouts +5578 Single-int-var-in-ecx/imm32/outputs +5579 "41/increment-ecx"/imm32/subx-name +5580 0/imm32/no-rm32 +5581 0/imm32/no-r32 +5582 0/imm32/no-imm32 +5583 0/imm32/no-disp32 +5584 0/imm32/output-is-write-only +5585 _Primitive-inc-edx/imm32/next +5586 _Primitive-inc-edx: +5587 # var/edx <- increment => 42/increment-edx +5588 "increment"/imm32/name +5589 0/imm32/no-inouts +5590 Single-int-var-in-edx/imm32/outputs +5591 "42/increment-edx"/imm32/subx-name +5592 0/imm32/no-rm32 +5593 0/imm32/no-r32 +5594 0/imm32/no-imm32 +5595 0/imm32/no-disp32 +5596 0/imm32/output-is-write-only +5597 _Primitive-inc-ebx/imm32/next +5598 _Primitive-inc-ebx: +5599 # var/ebx <- increment => 43/increment-ebx +5600 "increment"/imm32/name +5601 0/imm32/no-inouts +5602 Single-int-var-in-ebx/imm32/outputs +5603 "43/increment-ebx"/imm32/subx-name +5604 0/imm32/no-rm32 +5605 0/imm32/no-r32 +5606 0/imm32/no-imm32 +5607 0/imm32/no-disp32 +5608 0/imm32/output-is-write-only +5609 _Primitive-inc-esi/imm32/next +5610 _Primitive-inc-esi: +5611 # var/esi <- increment => 46/increment-esi +5612 "increment"/imm32/name +5613 0/imm32/no-inouts +5614 Single-int-var-in-esi/imm32/outputs +5615 "46/increment-esi"/imm32/subx-name +5616 0/imm32/no-rm32 +5617 0/imm32/no-r32 +5618 0/imm32/no-imm32 +5619 0/imm32/no-disp32 +5620 0/imm32/output-is-write-only +5621 _Primitive-inc-edi/imm32/next +5622 _Primitive-inc-edi: +5623 # var/edi <- increment => 47/increment-edi +5624 "increment"/imm32/name +5625 0/imm32/no-inouts +5626 Single-int-var-in-edi/imm32/outputs +5627 "47/increment-edi"/imm32/subx-name +5628 0/imm32/no-rm32 +5629 0/imm32/no-r32 +5630 0/imm32/no-imm32 +5631 0/imm32/no-disp32 +5632 0/imm32/output-is-write-only +5633 _Primitive-dec-eax/imm32/next +5634 _Primitive-dec-eax: +5635 # var/eax <- decrement => 48/decrement-eax +5636 "decrement"/imm32/name +5637 0/imm32/no-inouts +5638 Single-int-var-in-eax/imm32/outputs +5639 "48/decrement-eax"/imm32/subx-name +5640 0/imm32/no-rm32 +5641 0/imm32/no-r32 +5642 0/imm32/no-imm32 +5643 0/imm32/no-disp32 +5644 0/imm32/output-is-write-only +5645 _Primitive-dec-ecx/imm32/next +5646 _Primitive-dec-ecx: +5647 # var/ecx <- decrement => 49/decrement-ecx +5648 "decrement"/imm32/name +5649 0/imm32/no-inouts +5650 Single-int-var-in-ecx/imm32/outputs +5651 "49/decrement-ecx"/imm32/subx-name +5652 0/imm32/no-rm32 +5653 0/imm32/no-r32 +5654 0/imm32/no-imm32 +5655 0/imm32/no-disp32 +5656 0/imm32/output-is-write-only +5657 _Primitive-dec-edx/imm32/next +5658 _Primitive-dec-edx: +5659 # var/edx <- decrement => 4a/decrement-edx +5660 "decrement"/imm32/name +5661 0/imm32/no-inouts +5662 Single-int-var-in-edx/imm32/outputs +5663 "4a/decrement-edx"/imm32/subx-name +5664 0/imm32/no-rm32 +5665 0/imm32/no-r32 +5666 0/imm32/no-imm32 +5667 0/imm32/no-disp32 +5668 0/imm32/output-is-write-only +5669 _Primitive-dec-ebx/imm32/next +5670 _Primitive-dec-ebx: +5671 # var/ebx <- decrement => 4b/decrement-ebx +5672 "decrement"/imm32/name +5673 0/imm32/no-inouts +5674 Single-int-var-in-ebx/imm32/outputs +5675 "4b/decrement-ebx"/imm32/subx-name +5676 0/imm32/no-rm32 +5677 0/imm32/no-r32 +5678 0/imm32/no-imm32 +5679 0/imm32/no-disp32 +5680 0/imm32/output-is-write-only +5681 _Primitive-dec-esi/imm32/next +5682 _Primitive-dec-esi: +5683 # var/esi <- decrement => 4e/decrement-esi +5684 "decrement"/imm32/name +5685 0/imm32/no-inouts +5686 Single-int-var-in-esi/imm32/outputs +5687 "4e/decrement-esi"/imm32/subx-name +5688 0/imm32/no-rm32 +5689 0/imm32/no-r32 +5690 0/imm32/no-imm32 +5691 0/imm32/no-disp32 +5692 0/imm32/output-is-write-only +5693 _Primitive-dec-edi/imm32/next +5694 _Primitive-dec-edi: +5695 # var/edi <- decrement => 4f/decrement-edi +5696 "decrement"/imm32/name +5697 0/imm32/no-inouts +5698 Single-int-var-in-edi/imm32/outputs +5699 "4f/decrement-edi"/imm32/subx-name +5700 0/imm32/no-rm32 +5701 0/imm32/no-r32 +5702 0/imm32/no-imm32 +5703 0/imm32/no-disp32 +5704 0/imm32/output-is-write-only +5705 _Primitive-inc-mem/imm32/next +5706 _Primitive-inc-mem: +5707 # increment var => ff 0/subop/increment *(ebp+__) +5708 "increment"/imm32/name +5709 Single-int-var-in-mem/imm32/inouts +5710 0/imm32/no-outputs +5711 "ff 0/subop/increment"/imm32/subx-name +5712 1/imm32/rm32-is-first-inout +5713 0/imm32/no-r32 +5714 0/imm32/no-imm32 +5715 0/imm32/no-disp32 +5716 0/imm32/output-is-write-only +5717 _Primitive-inc-reg/imm32/next +5718 _Primitive-inc-reg: +5719 # var/reg <- increment => ff 0/subop/increment %__ +5720 "increment"/imm32/name +5721 0/imm32/no-inouts +5722 Single-int-var-in-some-register/imm32/outputs +5723 "ff 0/subop/increment"/imm32/subx-name +5724 3/imm32/rm32-is-first-output +5725 0/imm32/no-r32 +5726 0/imm32/no-imm32 +5727 0/imm32/no-disp32 +5728 0/imm32/output-is-write-only +5729 _Primitive-dec-mem/imm32/next +5730 _Primitive-dec-mem: +5731 # decrement var => ff 1/subop/decrement *(ebp+__) +5732 "decrement"/imm32/name +5733 Single-int-var-in-mem/imm32/inouts +5734 0/imm32/no-outputs +5735 "ff 1/subop/decrement"/imm32/subx-name +5736 1/imm32/rm32-is-first-inout +5737 0/imm32/no-r32 +5738 0/imm32/no-imm32 +5739 0/imm32/no-disp32 +5740 0/imm32/output-is-write-only +5741 _Primitive-dec-reg/imm32/next +5742 _Primitive-dec-reg: +5743 # var/reg <- decrement => ff 1/subop/decrement %__ +5744 "decrement"/imm32/name +5745 0/imm32/no-inouts +5746 Single-int-var-in-some-register/imm32/outputs +5747 "ff 1/subop/decrement"/imm32/subx-name +5748 3/imm32/rm32-is-first-output +5749 0/imm32/no-r32 +5750 0/imm32/no-imm32 +5751 0/imm32/no-disp32 +5752 0/imm32/output-is-write-only +5753 _Primitive-add-to-eax/imm32/next +5754 # - add +5755 _Primitive-add-to-eax: +5756 # var/eax <- add lit => 05/add-to-eax lit/imm32 +5757 "add"/imm32/name +5758 Single-lit-var/imm32/inouts +5759 Single-int-var-in-eax/imm32/outputs +5760 "05/add-to-eax"/imm32/subx-name +5761 0/imm32/no-rm32 +5762 0/imm32/no-r32 +5763 1/imm32/imm32-is-first-inout +5764 0/imm32/no-disp32 +5765 0/imm32/output-is-write-only +5766 _Primitive-add-reg-to-reg/imm32/next +5767 _Primitive-add-reg-to-reg: +5768 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 +5769 "add"/imm32/name +5770 Single-int-var-in-some-register/imm32/inouts +5771 Single-int-var-in-some-register/imm32/outputs +5772 "01/add-to"/imm32/subx-name +5773 3/imm32/rm32-is-first-output +5774 1/imm32/r32-is-first-inout +5775 0/imm32/no-imm32 +5776 0/imm32/no-disp32 +5777 0/imm32/output-is-write-only +5778 _Primitive-add-reg-to-mem/imm32/next +5779 _Primitive-add-reg-to-mem: +5780 # add-to var1 var2/reg => 01/add-to var1 var2/r32 +5781 "add-to"/imm32/name +5782 Two-args-int-stack-int-reg/imm32/inouts +5783 0/imm32/outputs +5784 "01/add-to"/imm32/subx-name +5785 1/imm32/rm32-is-first-inout +5786 2/imm32/r32-is-second-inout +5787 0/imm32/no-imm32 +5788 0/imm32/no-disp32 +5789 0/imm32/output-is-write-only +5790 _Primitive-add-mem-to-reg/imm32/next +5791 _Primitive-add-mem-to-reg: +5792 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 +5793 "add"/imm32/name +5794 Single-int-var-in-mem/imm32/inouts +5795 Single-int-var-in-some-register/imm32/outputs +5796 "03/add"/imm32/subx-name +5797 1/imm32/rm32-is-first-inout +5798 3/imm32/r32-is-first-output +5799 0/imm32/no-imm32 +5800 0/imm32/no-disp32 +5801 0/imm32/output-is-write-only +5802 _Primitive-add-lit-to-reg/imm32/next +5803 _Primitive-add-lit-to-reg: +5804 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 +5805 "add"/imm32/name +5806 Single-lit-var/imm32/inouts +5807 Single-int-var-in-some-register/imm32/outputs +5808 "81 0/subop/add"/imm32/subx-name +5809 3/imm32/rm32-is-first-output +5810 0/imm32/no-r32 +5811 1/imm32/imm32-is-first-inout +5812 0/imm32/no-disp32 +5813 0/imm32/output-is-write-only +5814 _Primitive-add-lit-to-mem/imm32/next +5815 _Primitive-add-lit-to-mem: +5816 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 +5817 "add-to"/imm32/name +5818 Int-var-and-literal/imm32/inouts +5819 0/imm32/outputs +5820 "81 0/subop/add"/imm32/subx-name +5821 1/imm32/rm32-is-first-inout +5822 0/imm32/no-r32 +5823 2/imm32/imm32-is-second-inout +5824 0/imm32/no-disp32 +5825 0/imm32/output-is-write-only +5826 _Primitive-subtract-from-eax/imm32/next +5827 # - subtract +5828 _Primitive-subtract-from-eax: +5829 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 +5830 "subtract"/imm32/name +5831 Single-lit-var/imm32/inouts +5832 Single-int-var-in-eax/imm32/outputs +5833 "2d/subtract-from-eax"/imm32/subx-name +5834 0/imm32/no-rm32 +5835 0/imm32/no-r32 +5836 1/imm32/imm32-is-first-inout +5837 0/imm32/no-disp32 +5838 0/imm32/output-is-write-only +5839 _Primitive-subtract-reg-from-reg/imm32/next +5840 _Primitive-subtract-reg-from-reg: +5841 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 +5842 "subtract"/imm32/name +5843 Single-int-var-in-some-register/imm32/inouts +5844 Single-int-var-in-some-register/imm32/outputs +5845 "29/subtract-from"/imm32/subx-name +5846 3/imm32/rm32-is-first-output +5847 1/imm32/r32-is-first-inout +5848 0/imm32/no-imm32 +5849 0/imm32/no-disp32 +5850 0/imm32/output-is-write-only +5851 _Primitive-subtract-reg-from-mem/imm32/next +5852 _Primitive-subtract-reg-from-mem: +5853 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 +5854 "subtract-from"/imm32/name +5855 Two-args-int-stack-int-reg/imm32/inouts +5856 0/imm32/outputs +5857 "29/subtract-from"/imm32/subx-name +5858 1/imm32/rm32-is-first-inout +5859 2/imm32/r32-is-second-inout +5860 0/imm32/no-imm32 +5861 0/imm32/no-disp32 +5862 0/imm32/output-is-write-only +5863 _Primitive-subtract-mem-from-reg/imm32/next +5864 _Primitive-subtract-mem-from-reg: +5865 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 +5866 "subtract"/imm32/name +5867 Single-int-var-in-mem/imm32/inouts +5868 Single-int-var-in-some-register/imm32/outputs +5869 "2b/subtract"/imm32/subx-name +5870 1/imm32/rm32-is-first-inout +5871 3/imm32/r32-is-first-output +5872 0/imm32/no-imm32 +5873 0/imm32/no-disp32 +5874 0/imm32/output-is-write-only +5875 _Primitive-subtract-lit-from-reg/imm32/next +5876 _Primitive-subtract-lit-from-reg: +5877 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 +5878 "subtract"/imm32/name +5879 Single-lit-var/imm32/inouts +5880 Single-int-var-in-some-register/imm32/outputs +5881 "81 5/subop/subtract"/imm32/subx-name +5882 3/imm32/rm32-is-first-output +5883 0/imm32/no-r32 +5884 1/imm32/imm32-is-first-inout +5885 0/imm32/no-disp32 +5886 0/imm32/output-is-write-only +5887 _Primitive-subtract-lit-from-mem/imm32/next +5888 _Primitive-subtract-lit-from-mem: +5889 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 +5890 "subtract-from"/imm32/name +5891 Int-var-and-literal/imm32/inouts +5892 0/imm32/outputs +5893 "81 5/subop/subtract"/imm32/subx-name +5894 1/imm32/rm32-is-first-inout +5895 0/imm32/no-r32 +5896 2/imm32/imm32-is-first-inout +5897 0/imm32/no-disp32 +5898 0/imm32/output-is-write-only +5899 _Primitive-and-with-eax/imm32/next +5900 # - and +5901 _Primitive-and-with-eax: +5902 # var/eax <- and lit => 25/and-with-eax lit/imm32 +5903 "and"/imm32/name +5904 Single-lit-var/imm32/inouts +5905 Single-int-var-in-eax/imm32/outputs +5906 "25/and-with-eax"/imm32/subx-name +5907 0/imm32/no-rm32 +5908 0/imm32/no-r32 +5909 1/imm32/imm32-is-first-inout +5910 0/imm32/no-disp32 +5911 0/imm32/output-is-write-only +5912 _Primitive-and-reg-with-reg/imm32/next +5913 _Primitive-and-reg-with-reg: +5914 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 +5915 "and"/imm32/name +5916 Single-int-var-in-some-register/imm32/inouts +5917 Single-int-var-in-some-register/imm32/outputs +5918 "21/and-with"/imm32/subx-name +5919 3/imm32/rm32-is-first-output +5920 1/imm32/r32-is-first-inout +5921 0/imm32/no-imm32 +5922 0/imm32/no-disp32 +5923 0/imm32/output-is-write-only +5924 _Primitive-and-reg-with-mem/imm32/next +5925 _Primitive-and-reg-with-mem: +5926 # and-with var1 var2/reg => 21/and-with var1 var2/r32 +5927 "and-with"/imm32/name +5928 Two-args-int-stack-int-reg/imm32/inouts +5929 0/imm32/outputs +5930 "21/and-with"/imm32/subx-name +5931 1/imm32/rm32-is-first-inout +5932 2/imm32/r32-is-second-inout +5933 0/imm32/no-imm32 +5934 0/imm32/no-disp32 +5935 0/imm32/output-is-write-only +5936 _Primitive-and-mem-with-reg/imm32/next +5937 _Primitive-and-mem-with-reg: +5938 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 +5939 "and"/imm32/name +5940 Single-int-var-in-mem/imm32/inouts +5941 Single-int-var-in-some-register/imm32/outputs +5942 "23/and"/imm32/subx-name +5943 1/imm32/rm32-is-first-inout +5944 3/imm32/r32-is-first-output +5945 0/imm32/no-imm32 +5946 0/imm32/no-disp32 +5947 0/imm32/output-is-write-only +5948 _Primitive-and-lit-with-reg/imm32/next +5949 _Primitive-and-lit-with-reg: +5950 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 +5951 "and"/imm32/name +5952 Single-lit-var/imm32/inouts +5953 Single-int-var-in-some-register/imm32/outputs +5954 "81 4/subop/and"/imm32/subx-name +5955 3/imm32/rm32-is-first-output +5956 0/imm32/no-r32 +5957 1/imm32/imm32-is-first-inout +5958 0/imm32/no-disp32 +5959 0/imm32/output-is-write-only +5960 _Primitive-and-lit-with-mem/imm32/next +5961 _Primitive-and-lit-with-mem: +5962 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 +5963 "and-with"/imm32/name +5964 Int-var-and-literal/imm32/inouts +5965 0/imm32/outputs +5966 "81 4/subop/and"/imm32/subx-name +5967 1/imm32/rm32-is-first-inout +5968 0/imm32/no-r32 +5969 2/imm32/imm32-is-first-inout +5970 0/imm32/no-disp32 +5971 0/imm32/output-is-write-only +5972 _Primitive-or-with-eax/imm32/next +5973 # - or +5974 _Primitive-or-with-eax: +5975 # var/eax <- or lit => 0d/or-with-eax lit/imm32 +5976 "or"/imm32/name +5977 Single-lit-var/imm32/inouts +5978 Single-int-var-in-eax/imm32/outputs +5979 "0d/or-with-eax"/imm32/subx-name +5980 0/imm32/no-rm32 +5981 0/imm32/no-r32 +5982 1/imm32/imm32-is-first-inout +5983 0/imm32/no-disp32 +5984 0/imm32/output-is-write-only +5985 _Primitive-or-reg-with-reg/imm32/next +5986 _Primitive-or-reg-with-reg: +5987 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 +5988 "or"/imm32/name +5989 Single-int-var-in-some-register/imm32/inouts +5990 Single-int-var-in-some-register/imm32/outputs +5991 "09/or-with"/imm32/subx-name +5992 3/imm32/rm32-is-first-output +5993 1/imm32/r32-is-first-inout +5994 0/imm32/no-imm32 +5995 0/imm32/no-disp32 +5996 0/imm32/output-is-write-only +5997 _Primitive-or-reg-with-mem/imm32/next +5998 _Primitive-or-reg-with-mem: +5999 # or-with var1 var2/reg => 09/or-with var1 var2/r32 +6000 "or-with"/imm32/name +6001 Two-args-int-stack-int-reg/imm32/inouts +6002 0/imm32/outputs +6003 "09/or-with"/imm32/subx-name +6004 1/imm32/rm32-is-first-inout +6005 2/imm32/r32-is-second-inout +6006 0/imm32/no-imm32 +6007 0/imm32/no-disp32 +6008 0/imm32/output-is-write-only +6009 _Primitive-or-mem-with-reg/imm32/next +6010 _Primitive-or-mem-with-reg: +6011 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 +6012 "or"/imm32/name +6013 Single-int-var-in-mem/imm32/inouts +6014 Single-int-var-in-some-register/imm32/outputs +6015 "0b/or"/imm32/subx-name +6016 1/imm32/rm32-is-first-inout +6017 3/imm32/r32-is-first-output +6018 0/imm32/no-imm32 +6019 0/imm32/no-disp32 +6020 0/imm32/output-is-write-only +6021 _Primitive-or-lit-with-reg/imm32/next +6022 _Primitive-or-lit-with-reg: +6023 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 +6024 "or"/imm32/name +6025 Single-lit-var/imm32/inouts +6026 Single-int-var-in-some-register/imm32/outputs +6027 "81 1/subop/or"/imm32/subx-name +6028 3/imm32/rm32-is-first-output +6029 0/imm32/no-r32 +6030 1/imm32/imm32-is-first-inout +6031 0/imm32/no-disp32 +6032 0/imm32/output-is-write-only +6033 _Primitive-or-lit-with-mem/imm32/next +6034 _Primitive-or-lit-with-mem: +6035 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 +6036 "or-with"/imm32/name +6037 Int-var-and-literal/imm32/inouts +6038 0/imm32/outputs +6039 "81 1/subop/or"/imm32/subx-name +6040 1/imm32/rm32-is-first-inout +6041 0/imm32/no-r32 +6042 2/imm32/imm32-is-second-inout +6043 0/imm32/no-disp32 +6044 0/imm32/output-is-write-only +6045 _Primitive-xor-with-eax/imm32/next +6046 # - xor +6047 _Primitive-xor-with-eax: +6048 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 +6049 "xor"/imm32/name +6050 Single-lit-var/imm32/inouts +6051 Single-int-var-in-eax/imm32/outputs +6052 "35/xor-with-eax"/imm32/subx-name +6053 0/imm32/no-rm32 +6054 0/imm32/no-r32 +6055 1/imm32/imm32-is-first-inout +6056 0/imm32/no-disp32 +6057 0/imm32/output-is-write-only +6058 _Primitive-xor-reg-with-reg/imm32/next +6059 _Primitive-xor-reg-with-reg: +6060 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 +6061 "xor"/imm32/name +6062 Single-int-var-in-some-register/imm32/inouts +6063 Single-int-var-in-some-register/imm32/outputs +6064 "31/xor-with"/imm32/subx-name +6065 3/imm32/rm32-is-first-output +6066 1/imm32/r32-is-first-inout +6067 0/imm32/no-imm32 +6068 0/imm32/no-disp32 +6069 0/imm32/output-is-write-only +6070 _Primitive-xor-reg-with-mem/imm32/next +6071 _Primitive-xor-reg-with-mem: +6072 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 +6073 "xor-with"/imm32/name +6074 Two-args-int-stack-int-reg/imm32/inouts +6075 0/imm32/outputs +6076 "31/xor-with"/imm32/subx-name +6077 1/imm32/rm32-is-first-inout +6078 2/imm32/r32-is-second-inout +6079 0/imm32/no-imm32 +6080 0/imm32/no-disp32 +6081 0/imm32/output-is-write-only +6082 _Primitive-xor-mem-with-reg/imm32/next +6083 _Primitive-xor-mem-with-reg: +6084 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 +6085 "xor"/imm32/name +6086 Single-int-var-in-mem/imm32/inouts +6087 Single-int-var-in-some-register/imm32/outputs +6088 "33/xor"/imm32/subx-name +6089 1/imm32/rm32-is-first-inout +6090 3/imm32/r32-is-first-output +6091 0/imm32/no-imm32 +6092 0/imm32/no-disp32 +6093 0/imm32/output-is-write-only +6094 _Primitive-xor-lit-with-reg/imm32/next +6095 _Primitive-xor-lit-with-reg: +6096 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 +6097 "xor"/imm32/name +6098 Single-lit-var/imm32/inouts +6099 Single-int-var-in-some-register/imm32/outputs +6100 "81 6/subop/xor"/imm32/subx-name +6101 3/imm32/rm32-is-first-output +6102 0/imm32/no-r32 +6103 1/imm32/imm32-is-first-inout +6104 0/imm32/no-disp32 +6105 0/imm32/output-is-write-only +6106 _Primitive-xor-lit-with-mem/imm32/next +6107 _Primitive-xor-lit-with-mem: +6108 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 +6109 "xor-with"/imm32/name +6110 Int-var-and-literal/imm32/inouts +6111 0/imm32/outputs +6112 "81 6/subop/xor"/imm32/subx-name +6113 1/imm32/rm32-is-first-inout +6114 0/imm32/no-r32 +6115 2/imm32/imm32-is-first-inout +6116 0/imm32/no-disp32 +6117 0/imm32/output-is-write-only +6118 _Primitive-copy-to-eax/imm32/next +6119 # - copy +6120 _Primitive-copy-to-eax: +6121 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 +6122 "copy"/imm32/name +6123 Single-lit-var/imm32/inouts +6124 Single-int-var-in-eax/imm32/outputs +6125 "b8/copy-to-eax"/imm32/subx-name +6126 0/imm32/no-rm32 +6127 0/imm32/no-r32 +6128 1/imm32/imm32-is-first-inout +6129 0/imm32/no-disp32 +6130 1/imm32/output-is-write-only +6131 _Primitive-copy-to-ecx/imm32/next +6132 _Primitive-copy-to-ecx: +6133 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 +6134 "copy"/imm32/name +6135 Single-lit-var/imm32/inouts +6136 Single-int-var-in-ecx/imm32/outputs +6137 "b9/copy-to-ecx"/imm32/subx-name +6138 0/imm32/no-rm32 +6139 0/imm32/no-r32 +6140 1/imm32/imm32-is-first-inout +6141 0/imm32/no-disp32 +6142 1/imm32/output-is-write-only +6143 _Primitive-copy-to-edx/imm32/next +6144 _Primitive-copy-to-edx: +6145 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 +6146 "copy"/imm32/name +6147 Single-lit-var/imm32/inouts +6148 Single-int-var-in-edx/imm32/outputs +6149 "ba/copy-to-edx"/imm32/subx-name +6150 0/imm32/no-rm32 +6151 0/imm32/no-r32 +6152 1/imm32/imm32-is-first-inout +6153 0/imm32/no-disp32 +6154 1/imm32/output-is-write-only +6155 _Primitive-copy-to-ebx/imm32/next +6156 _Primitive-copy-to-ebx: +6157 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 +6158 "copy"/imm32/name +6159 Single-lit-var/imm32/inouts +6160 Single-int-var-in-ebx/imm32/outputs +6161 "bb/copy-to-ebx"/imm32/subx-name +6162 0/imm32/no-rm32 +6163 0/imm32/no-r32 +6164 1/imm32/imm32-is-first-inout +6165 0/imm32/no-disp32 +6166 1/imm32/output-is-write-only +6167 _Primitive-copy-to-esi/imm32/next +6168 _Primitive-copy-to-esi: +6169 # var/esi <- copy lit => be/copy-to-esi lit/imm32 +6170 "copy"/imm32/name +6171 Single-lit-var/imm32/inouts +6172 Single-int-var-in-esi/imm32/outputs +6173 "be/copy-to-esi"/imm32/subx-name +6174 0/imm32/no-rm32 +6175 0/imm32/no-r32 +6176 1/imm32/imm32-is-first-inout +6177 0/imm32/no-disp32 +6178 1/imm32/output-is-write-only +6179 _Primitive-copy-to-edi/imm32/next +6180 _Primitive-copy-to-edi: +6181 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 +6182 "copy"/imm32/name +6183 Single-lit-var/imm32/inouts +6184 Single-int-var-in-edi/imm32/outputs +6185 "bf/copy-to-edi"/imm32/subx-name +6186 0/imm32/no-rm32 +6187 0/imm32/no-r32 +6188 1/imm32/imm32-is-first-inout +6189 0/imm32/no-disp32 +6190 1/imm32/output-is-write-only +6191 _Primitive-copy-reg-to-reg/imm32/next +6192 _Primitive-copy-reg-to-reg: +6193 # var1/reg <- copy var2/reg => 89/copy-to var1/rm32 var2/r32 +6194 "copy"/imm32/name +6195 Single-int-var-in-some-register/imm32/inouts +6196 Single-int-var-in-some-register/imm32/outputs +6197 "89/copy-to"/imm32/subx-name +6198 3/imm32/rm32-is-first-output +6199 1/imm32/r32-is-first-inout +6200 0/imm32/no-imm32 +6201 0/imm32/no-disp32 +6202 1/imm32/output-is-write-only +6203 _Primitive-copy-reg-to-mem/imm32/next +6204 _Primitive-copy-reg-to-mem: +6205 # copy-to var1 var2/reg => 89/copy-to var1 var2/r32 +6206 "copy-to"/imm32/name +6207 Two-args-int-stack-int-reg/imm32/inouts +6208 0/imm32/outputs +6209 "89/copy-to"/imm32/subx-name +6210 1/imm32/rm32-is-first-inout +6211 2/imm32/r32-is-second-inout +6212 0/imm32/no-imm32 +6213 0/imm32/no-disp32 +6214 1/imm32/output-is-write-only +6215 _Primitive-copy-mem-to-reg/imm32/next +6216 _Primitive-copy-mem-to-reg: +6217 # var1/reg <- copy var2 => 8b/copy-from var2/rm32 var1/r32 +6218 "copy"/imm32/name +6219 Single-int-var-in-mem/imm32/inouts +6220 Single-int-var-in-some-register/imm32/outputs +6221 "8b/copy-from"/imm32/subx-name +6222 1/imm32/rm32-is-first-inout +6223 3/imm32/r32-is-first-output +6224 0/imm32/no-imm32 +6225 0/imm32/no-disp32 +6226 1/imm32/output-is-write-only +6227 _Primitive-copy-lit-to-reg/imm32/next +6228 _Primitive-copy-lit-to-reg: +6229 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 +6230 "copy"/imm32/name +6231 Single-lit-var/imm32/inouts +6232 Single-int-var-in-some-register/imm32/outputs +6233 "c7 0/subop/copy"/imm32/subx-name +6234 3/imm32/rm32-is-first-output +6235 0/imm32/no-r32 +6236 1/imm32/imm32-is-first-inout +6237 0/imm32/no-disp32 +6238 1/imm32/output-is-write-only +6239 _Primitive-copy-lit-to-mem/imm32/next +6240 _Primitive-copy-lit-to-mem: +6241 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 +6242 "copy-to"/imm32/name +6243 Int-var-and-literal/imm32/inouts 6244 0/imm32/outputs -6245 "0f 85/jump-if-!= break/disp32"/imm32/subx-name -6246 0/imm32/no-rm32 +6245 "c7 0/subop/copy"/imm32/subx-name +6246 1/imm32/rm32-is-first-inout 6247 0/imm32/no-r32 -6248 0/imm32/no-imm32 +6248 2/imm32/imm32-is-first-inout 6249 0/imm32/no-disp32 -6250 0/imm32/no-output -6251 _Primitive-break-if-addr<=/imm32/next -6252 _Primitive-break-if-addr<=: -6253 "break-if-addr<="/imm32/name -6254 0/imm32/inouts -6255 0/imm32/outputs -6256 "0f 86/jump-if-addr<= break/disp32"/imm32/subx-name -6257 0/imm32/no-rm32 -6258 0/imm32/no-r32 -6259 0/imm32/no-imm32 -6260 0/imm32/no-disp32 -6261 0/imm32/no-output -6262 _Primitive-break-if-addr>/imm32/next -6263 _Primitive-break-if-addr>: -6264 "break-if-addr>"/imm32/name -6265 0/imm32/inouts -6266 0/imm32/outputs -6267 "0f 87/jump-if-addr> break/disp32"/imm32/subx-name -6268 0/imm32/no-rm32 -6269 0/imm32/no-r32 -6270 0/imm32/no-imm32 -6271 0/imm32/no-disp32 -6272 0/imm32/no-output -6273 _Primitive-break-if-</imm32/next -6274 _Primitive-break-if-<: -6275 "break-if-<"/imm32/name -6276 0/imm32/inouts -6277 0/imm32/outputs -6278 "0f 8c/jump-if-< break/disp32"/imm32/subx-name -6279 0/imm32/no-rm32 -6280 0/imm32/no-r32 -6281 0/imm32/no-imm32 -6282 0/imm32/no-disp32 -6283 0/imm32/no-output -6284 _Primitive-break-if->=/imm32/next -6285 _Primitive-break-if->=: -6286 "break-if->="/imm32/name -6287 0/imm32/inouts -6288 0/imm32/outputs -6289 "0f 8d/jump-if->= break/disp32"/imm32/subx-name -6290 0/imm32/no-rm32 -6291 0/imm32/no-r32 -6292 0/imm32/no-imm32 -6293 0/imm32/no-disp32 -6294 0/imm32/no-output -6295 _Primitive-break-if-<=/imm32/next -6296 _Primitive-break-if-<=: -6297 "break-if-<="/imm32/name -6298 0/imm32/inouts -6299 0/imm32/outputs -6300 "0f 8e/jump-if-<= break/disp32"/imm32/subx-name -6301 0/imm32/no-rm32 -6302 0/imm32/no-r32 -6303 0/imm32/no-imm32 -6304 0/imm32/no-disp32 -6305 0/imm32/no-output -6306 _Primitive-break-if->/imm32/next -6307 _Primitive-break-if->: -6308 "break-if->"/imm32/name -6309 0/imm32/inouts -6310 0/imm32/outputs -6311 "0f 8f/jump-if-> break/disp32"/imm32/subx-name -6312 0/imm32/no-rm32 -6313 0/imm32/no-r32 -6314 0/imm32/no-imm32 -6315 0/imm32/no-disp32 -6316 0/imm32/no-output -6317 _Primitive-break/imm32/next -6318 _Primitive-break: -6319 "break"/imm32/name -6320 0/imm32/inouts -6321 0/imm32/outputs -6322 "e9/jump break/disp32"/imm32/subx-name -6323 0/imm32/no-rm32 -6324 0/imm32/no-r32 -6325 0/imm32/no-imm32 -6326 0/imm32/no-disp32 -6327 0/imm32/no-output -6328 _Primitive-loop-if-addr</imm32/next -6329 _Primitive-loop-if-addr<: -6330 "loop-if-addr<"/imm32/name -6331 0/imm32/inouts -6332 0/imm32/outputs -6333 "0f 82/jump-if-addr< loop/disp32"/imm32/subx-name -6334 0/imm32/no-rm32 -6335 0/imm32/no-r32 -6336 0/imm32/no-imm32 -6337 0/imm32/no-disp32 -6338 0/imm32/no-output -6339 _Primitive-loop-if-addr>=/imm32/next -6340 _Primitive-loop-if-addr>=: -6341 "loop-if-addr>="/imm32/name -6342 0/imm32/inouts -6343 0/imm32/outputs -6344 "0f 83/jump-if-addr>= loop/disp32"/imm32/subx-name -6345 0/imm32/no-rm32 -6346 0/imm32/no-r32 -6347 0/imm32/no-imm32 -6348 0/imm32/no-disp32 -6349 0/imm32/no-output -6350 _Primitive-loop-if-=/imm32/next -6351 _Primitive-loop-if-=: -6352 "loop-if-="/imm32/name -6353 0/imm32/inouts -6354 0/imm32/outputs -6355 "0f 84/jump-if-= loop/disp32"/imm32/subx-name -6356 0/imm32/no-rm32 -6357 0/imm32/no-r32 -6358 0/imm32/no-imm32 -6359 0/imm32/no-disp32 -6360 0/imm32/no-output -6361 _Primitive-loop-if-!=/imm32/next -6362 _Primitive-loop-if-!=: -6363 "loop-if-!="/imm32/name -6364 0/imm32/inouts -6365 0/imm32/outputs -6366 "0f 85/jump-if-!= loop/disp32"/imm32/subx-name -6367 0/imm32/no-rm32 -6368 0/imm32/no-r32 -6369 0/imm32/no-imm32 -6370 0/imm32/no-disp32 -6371 0/imm32/no-output -6372 _Primitive-loop-if-addr<=/imm32/next -6373 _Primitive-loop-if-addr<=: -6374 "loop-if-addr<="/imm32/name -6375 0/imm32/inouts -6376 0/imm32/outputs -6377 "0f 86/jump-if-addr<= loop/disp32"/imm32/subx-name -6378 0/imm32/no-rm32 -6379 0/imm32/no-r32 -6380 0/imm32/no-imm32 -6381 0/imm32/no-disp32 -6382 0/imm32/no-output -6383 _Primitive-loop-if-addr>/imm32/next -6384 _Primitive-loop-if-addr>: -6385 "loop-if-addr>"/imm32/name -6386 0/imm32/inouts -6387 0/imm32/outputs -6388 "0f 87/jump-if-addr> loop/disp32"/imm32/subx-name -6389 0/imm32/no-rm32 -6390 0/imm32/no-r32 -6391 0/imm32/no-imm32 -6392 0/imm32/no-disp32 -6393 0/imm32/no-output -6394 _Primitive-loop-if-</imm32/next -6395 _Primitive-loop-if-<: -6396 "loop-if-<"/imm32/name -6397 0/imm32/inouts -6398 0/imm32/outputs -6399 "0f 8c/jump-if-< loop/disp32"/imm32/subx-name -6400 0/imm32/no-rm32 -6401 0/imm32/no-r32 -6402 0/imm32/no-imm32 -6403 0/imm32/no-disp32 -6404 0/imm32/no-output -6405 _Primitive-loop-if->=/imm32/next -6406 _Primitive-loop-if->=: -6407 "loop-if->="/imm32/name -6408 0/imm32/inouts -6409 0/imm32/outputs -6410 "0f 8d/jump-if->= loop/disp32"/imm32/subx-name -6411 0/imm32/no-rm32 -6412 0/imm32/no-r32 -6413 0/imm32/no-imm32 -6414 0/imm32/no-disp32 -6415 0/imm32/no-output -6416 _Primitive-loop-if-<=/imm32/next -6417 _Primitive-loop-if-<=: -6418 "loop-if-<="/imm32/name -6419 0/imm32/inouts -6420 0/imm32/outputs -6421 "0f 8e/jump-if-<= loop/disp32"/imm32/subx-name -6422 0/imm32/no-rm32 -6423 0/imm32/no-r32 -6424 0/imm32/no-imm32 -6425 0/imm32/no-disp32 -6426 0/imm32/no-output -6427 _Primitive-loop-if->/imm32/next -6428 _Primitive-loop-if->: -6429 "loop-if->"/imm32/name -6430 0/imm32/inouts -6431 0/imm32/outputs -6432 "0f 8f/jump-if-> loop/disp32"/imm32/subx-name -6433 0/imm32/no-rm32 -6434 0/imm32/no-r32 -6435 0/imm32/no-imm32 -6436 0/imm32/no-disp32 -6437 0/imm32/no-output -6438 _Primitive-loop/imm32/next # we probably don't need an unconditional break -6439 _Primitive-loop: -6440 "loop"/imm32/name -6441 0/imm32/inouts -6442 0/imm32/outputs -6443 "e9/jump loop/disp32"/imm32/subx-name -6444 0/imm32/no-rm32 -6445 0/imm32/no-r32 -6446 0/imm32/no-imm32 -6447 0/imm32/no-disp32 -6448 0/imm32/no-output -6449 _Primitive-break-if-addr<-named/imm32/next -6450 # - branches to named blocks -6451 _Primitive-break-if-addr<-named: -6452 "break-if-addr<"/imm32/name -6453 Single-lit-var/imm32/inouts -6454 0/imm32/outputs -6455 "0f 82/jump-if-addr<"/imm32/subx-name -6456 0/imm32/no-rm32 -6457 0/imm32/no-r32 -6458 0/imm32/no-imm32 -6459 1/imm32/disp32-is-first-inout -6460 0/imm32/no-output -6461 _Primitive-break-if-addr>=-named/imm32/next -6462 _Primitive-break-if-addr>=-named: -6463 "break-if-addr>="/imm32/name -6464 Single-lit-var/imm32/inouts -6465 0/imm32/outputs -6466 "0f 83/jump-if-addr>="/imm32/subx-name -6467 0/imm32/no-rm32 -6468 0/imm32/no-r32 -6469 0/imm32/no-imm32 -6470 1/imm32/disp32-is-first-inout -6471 0/imm32/no-output -6472 _Primitive-break-if-=-named/imm32/next -6473 _Primitive-break-if-=-named: -6474 "break-if-="/imm32/name -6475 Single-lit-var/imm32/inouts -6476 0/imm32/outputs -6477 "0f 84/jump-if-="/imm32/subx-name -6478 0/imm32/no-rm32 -6479 0/imm32/no-r32 -6480 0/imm32/no-imm32 -6481 1/imm32/disp32-is-first-inout -6482 0/imm32/no-output -6483 _Primitive-break-if-!=-named/imm32/next -6484 _Primitive-break-if-!=-named: -6485 "break-if-!="/imm32/name -6486 Single-lit-var/imm32/inouts -6487 0/imm32/outputs -6488 "0f 85/jump-if-!="/imm32/subx-name -6489 0/imm32/no-rm32 -6490 0/imm32/no-r32 -6491 0/imm32/no-imm32 -6492 1/imm32/disp32-is-first-inout -6493 0/imm32/no-output -6494 _Primitive-break-if-addr<=-named/imm32/next -6495 _Primitive-break-if-addr<=-named: -6496 "break-if-addr<="/imm32/name -6497 Single-lit-var/imm32/inouts -6498 0/imm32/outputs -6499 "0f 86/jump-if-addr<="/imm32/subx-name -6500 0/imm32/no-rm32 -6501 0/imm32/no-r32 -6502 0/imm32/no-imm32 -6503 1/imm32/disp32-is-first-inout -6504 0/imm32/no-output -6505 _Primitive-break-if-addr>-named/imm32/next -6506 _Primitive-break-if-addr>-named: -6507 "break-if-addr>"/imm32/name -6508 Single-lit-var/imm32/inouts -6509 0/imm32/outputs -6510 "0f 87/jump-if-addr>"/imm32/subx-name -6511 0/imm32/no-rm32 -6512 0/imm32/no-r32 -6513 0/imm32/no-imm32 -6514 1/imm32/disp32-is-first-inout -6515 0/imm32/no-output -6516 _Primitive-break-if-<-named/imm32/next -6517 _Primitive-break-if-<-named: -6518 "break-if-<"/imm32/name -6519 Single-lit-var/imm32/inouts -6520 0/imm32/outputs -6521 "0f 8c/jump-if-<"/imm32/subx-name -6522 0/imm32/no-rm32 -6523 0/imm32/no-r32 -6524 0/imm32/no-imm32 -6525 1/imm32/disp32-is-first-inout -6526 0/imm32/no-output -6527 _Primitive-break-if->=-named/imm32/next -6528 _Primitive-break-if->=-named: -6529 "break-if->="/imm32/name -6530 Single-lit-var/imm32/inouts -6531 0/imm32/outputs -6532 "0f 8d/jump-if->="/imm32/subx-name -6533 0/imm32/no-rm32 -6534 0/imm32/no-r32 -6535 0/imm32/no-imm32 -6536 1/imm32/disp32-is-first-inout -6537 0/imm32/no-output -6538 _Primitive-break-if-<=-named/imm32/next -6539 _Primitive-break-if-<=-named: -6540 "break-if-<="/imm32/name -6541 Single-lit-var/imm32/inouts -6542 0/imm32/outputs -6543 "0f 8e/jump-if-<="/imm32/subx-name -6544 0/imm32/no-rm32 -6545 0/imm32/no-r32 -6546 0/imm32/no-imm32 -6547 1/imm32/disp32-is-first-inout -6548 0/imm32/no-output -6549 _Primitive-break-if->-named/imm32/next -6550 _Primitive-break-if->-named: -6551 "break-if->"/imm32/name -6552 Single-lit-var/imm32/inouts -6553 0/imm32/outputs -6554 "0f 8f/jump-if->"/imm32/subx-name -6555 0/imm32/no-rm32 -6556 0/imm32/no-r32 -6557 0/imm32/no-imm32 -6558 1/imm32/disp32-is-first-inout -6559 0/imm32/no-output -6560 _Primitive-break-named/imm32/next -6561 _Primitive-break-named: -6562 "break"/imm32/name -6563 Single-lit-var/imm32/inouts -6564 0/imm32/outputs -6565 "e9/jump"/imm32/subx-name -6566 0/imm32/no-rm32 -6567 0/imm32/no-r32 -6568 0/imm32/no-imm32 -6569 1/imm32/disp32-is-first-inout -6570 0/imm32/no-output -6571 _Primitive-loop-if-addr<-named/imm32/next -6572 _Primitive-loop-if-addr<-named: -6573 "loop-if-addr<"/imm32/name -6574 Single-lit-var/imm32/inouts -6575 0/imm32/outputs -6576 "0f 82/jump-if-addr<"/imm32/subx-name -6577 0/imm32/no-rm32 -6578 0/imm32/no-r32 -6579 0/imm32/no-imm32 -6580 1/imm32/disp32-is-first-inout -6581 0/imm32/no-output -6582 _Primitive-loop-if-addr>=-named/imm32/next -6583 _Primitive-loop-if-addr>=-named: -6584 "loop-if-addr>="/imm32/name -6585 Single-lit-var/imm32/inouts -6586 0/imm32/outputs -6587 "0f 83/jump-if-addr>="/imm32/subx-name -6588 0/imm32/no-rm32 -6589 0/imm32/no-r32 -6590 0/imm32/no-imm32 -6591 1/imm32/disp32-is-first-inout -6592 0/imm32/no-output -6593 _Primitive-loop-if-=-named/imm32/next -6594 _Primitive-loop-if-=-named: -6595 "loop-if-="/imm32/name -6596 Single-lit-var/imm32/inouts -6597 0/imm32/outputs -6598 "0f 84/jump-if-="/imm32/subx-name -6599 0/imm32/no-rm32 -6600 0/imm32/no-r32 -6601 0/imm32/no-imm32 -6602 1/imm32/disp32-is-first-inout -6603 0/imm32/no-output -6604 _Primitive-loop-if-!=-named/imm32/next -6605 _Primitive-loop-if-!=-named: -6606 "loop-if-!="/imm32/name -6607 Single-lit-var/imm32/inouts -6608 0/imm32/outputs -6609 "0f 85/jump-if-!="/imm32/subx-name -6610 0/imm32/no-rm32 -6611 0/imm32/no-r32 -6612 0/imm32/no-imm32 -6613 1/imm32/disp32-is-first-inout -6614 0/imm32/no-output -6615 _Primitive-loop-if-addr<=-named/imm32/next -6616 _Primitive-loop-if-addr<=-named: -6617 "loop-if-addr<="/imm32/name -6618 Single-lit-var/imm32/inouts -6619 0/imm32/outputs -6620 "0f 86/jump-if-addr<="/imm32/subx-name -6621 0/imm32/no-rm32 -6622 0/imm32/no-r32 -6623 0/imm32/no-imm32 -6624 1/imm32/disp32-is-first-inout -6625 0/imm32/no-output -6626 _Primitive-loop-if-addr>-named/imm32/next -6627 _Primitive-loop-if-addr>-named: -6628 "loop-if-addr>"/imm32/name -6629 Single-lit-var/imm32/inouts -6630 0/imm32/outputs -6631 "0f 87/jump-if-addr>"/imm32/subx-name -6632 0/imm32/no-rm32 -6633 0/imm32/no-r32 -6634 0/imm32/no-imm32 -6635 1/imm32/disp32-is-first-inout -6636 0/imm32/no-output -6637 _Primitive-loop-if-<-named/imm32/next -6638 _Primitive-loop-if-<-named: -6639 "loop-if-<"/imm32/name -6640 Single-lit-var/imm32/inouts -6641 0/imm32/outputs -6642 "0f 8c/jump-if-<"/imm32/subx-name -6643 0/imm32/no-rm32 -6644 0/imm32/no-r32 -6645 0/imm32/no-imm32 -6646 1/imm32/disp32-is-first-inout -6647 0/imm32/no-output -6648 _Primitive-loop-if->=-named/imm32/next -6649 _Primitive-loop-if->=-named: -6650 "loop-if->="/imm32/name -6651 Single-lit-var/imm32/inouts -6652 0/imm32/outputs -6653 "0f 8d/jump-if->="/imm32/subx-name -6654 0/imm32/no-rm32 -6655 0/imm32/no-r32 -6656 0/imm32/no-imm32 -6657 1/imm32/disp32-is-first-inout -6658 0/imm32/no-output -6659 _Primitive-loop-if-<=-named/imm32/next -6660 _Primitive-loop-if-<=-named: -6661 "loop-if-<="/imm32/name -6662 Single-lit-var/imm32/inouts -6663 0/imm32/outputs -6664 "0f 8e/jump-if-<="/imm32/subx-name -6665 0/imm32/no-rm32 -6666 0/imm32/no-r32 -6667 0/imm32/no-imm32 -6668 1/imm32/disp32-is-first-inout -6669 0/imm32/no-output -6670 _Primitive-loop-if->-named/imm32/next -6671 _Primitive-loop-if->-named: -6672 "loop-if->"/imm32/name -6673 Single-lit-var/imm32/inouts -6674 0/imm32/outputs -6675 "0f 8f/jump-if->"/imm32/subx-name -6676 0/imm32/no-rm32 -6677 0/imm32/no-r32 -6678 0/imm32/no-imm32 -6679 1/imm32/disp32-is-first-inout -6680 0/imm32/no-output -6681 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break -6682 _Primitive-loop-named: -6683 "loop"/imm32/name -6684 Single-lit-var/imm32/inouts -6685 0/imm32/outputs -6686 "e9/jump"/imm32/subx-name -6687 0/imm32/no-rm32 -6688 0/imm32/no-r32 -6689 0/imm32/no-imm32 -6690 1/imm32/disp32-is-first-inout -6691 0/imm32/no-output -6692 0/imm32/next -6693 -6694 Single-int-var-on-stack: -6695 Int-var-on-stack/imm32 -6696 0/imm32/next -6697 -6698 Int-var-on-stack: -6699 "arg1"/imm32/name -6700 Type-int/imm32 -6701 1/imm32/some-block-depth -6702 1/imm32/some-stack-offset -6703 0/imm32/no-register -6704 -6705 Two-args-int-stack-int-reg: -6706 Int-var-on-stack/imm32 -6707 Single-int-var-in-some-register/imm32/next -6708 -6709 Two-args-int-reg-int-stack: -6710 Int-var-in-some-register/imm32 -6711 Single-int-var-on-stack/imm32/next -6712 -6713 Two-args-int-eax-int-literal: -6714 Int-var-in-eax/imm32 -6715 Single-lit-var/imm32/next -6716 -6717 Int-var-and-literal: -6718 Int-var-on-stack/imm32 -6719 Single-lit-var/imm32/next -6720 -6721 Single-int-var-in-some-register: -6722 Int-var-in-some-register/imm32 -6723 0/imm32/next -6724 -6725 Int-var-in-some-register: -6726 "arg1"/imm32/name -6727 Type-int/imm32 -6728 1/imm32/some-block-depth -6729 0/imm32/no-stack-offset -6730 "*"/imm32/register -6731 -6732 Single-int-var-in-eax: -6733 Int-var-in-eax/imm32 -6734 0/imm32/next -6735 -6736 Int-var-in-eax: -6737 "arg1"/imm32/name -6738 Type-int/imm32 -6739 1/imm32/some-block-depth -6740 0/imm32/no-stack-offset -6741 "eax"/imm32/register -6742 -6743 Single-int-var-in-ecx: -6744 Int-var-in-ecx/imm32 -6745 0/imm32/next -6746 -6747 Int-var-in-ecx: -6748 "arg1"/imm32/name -6749 Type-int/imm32 -6750 1/imm32/some-block-depth -6751 0/imm32/no-stack-offset -6752 "ecx"/imm32/register -6753 -6754 Single-int-var-in-edx: -6755 Int-var-in-edx/imm32 -6756 0/imm32/next -6757 -6758 Int-var-in-edx: -6759 "arg1"/imm32/name -6760 Type-int/imm32 -6761 1/imm32/some-block-depth -6762 0/imm32/no-stack-offset -6763 "edx"/imm32/register -6764 -6765 Single-int-var-in-ebx: -6766 Int-var-in-ebx/imm32 -6767 0/imm32/next -6768 -6769 Int-var-in-ebx: -6770 "arg1"/imm32/name -6771 Type-int/imm32 -6772 1/imm32/some-block-depth -6773 0/imm32/no-stack-offset -6774 "ebx"/imm32/register -6775 -6776 Single-int-var-in-esi: -6777 Int-var-in-esi/imm32 -6778 0/imm32/next -6779 -6780 Int-var-in-esi: -6781 "arg1"/imm32/name -6782 Type-int/imm32 -6783 1/imm32/some-block-depth -6784 0/imm32/no-stack-offset -6785 "esi"/imm32/register -6786 -6787 Single-int-var-in-edi: -6788 Int-var-in-edi/imm32 -6789 0/imm32/next -6790 -6791 Int-var-in-edi: -6792 "arg1"/imm32/name -6793 Type-int/imm32 -6794 1/imm32/some-block-depth -6795 0/imm32/no-stack-offset -6796 "edi"/imm32/register -6797 -6798 Single-lit-var: -6799 Lit-var/imm32 -6800 0/imm32/next -6801 -6802 Lit-var: -6803 "literal"/imm32/name -6804 Type-literal/imm32 -6805 1/imm32/some-block-depth -6806 0/imm32/no-stack-offset -6807 0/imm32/no-register -6808 -6809 Type-int: -6810 1/imm32/left/int -6811 0/imm32/right/null +6250 1/imm32/output-is-write-only +6251 _Primitive-compare-mem-with-reg/imm32/next +6252 # - compare +6253 _Primitive-compare-mem-with-reg: +6254 # compare var1 var2/reg => 39/compare-> var1/rm32 var2/r32 +6255 "compare"/imm32/name +6256 Two-args-int-stack-int-reg/imm32/inouts +6257 0/imm32/outputs +6258 "39/compare->"/imm32/subx-name +6259 1/imm32/rm32-is-first-inout +6260 2/imm32/r32-is-second-inout +6261 0/imm32/no-imm32 +6262 0/imm32/no-disp32 +6263 0/imm32/output-is-write-only +6264 _Primitive-compare-reg-with-mem/imm32/next +6265 _Primitive-compare-reg-with-mem: +6266 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 +6267 "compare"/imm32/name +6268 Two-args-int-reg-int-stack/imm32/inouts +6269 0/imm32/outputs +6270 "3b/compare<-"/imm32/subx-name +6271 2/imm32/rm32-is-second-inout +6272 1/imm32/r32-is-first-inout +6273 0/imm32/no-imm32 +6274 0/imm32/no-disp32 +6275 0/imm32/output-is-write-only +6276 _Primitive-compare-eax-with-literal/imm32/next +6277 _Primitive-compare-eax-with-literal: +6278 # compare var1/eax n => 3d/compare-eax-with n/imm32 +6279 "compare"/imm32/name +6280 Two-args-int-eax-int-literal/imm32/inouts +6281 0/imm32/outputs +6282 "3d/compare-eax-with"/imm32/subx-name +6283 0/imm32/no-rm32 +6284 0/imm32/no-r32 +6285 2/imm32/imm32-is-second-inout +6286 0/imm32/no-disp32 +6287 0/imm32/output-is-write-only +6288 _Primitive-compare-reg-with-literal/imm32/next +6289 _Primitive-compare-reg-with-literal: +6290 # compare var1/reg n => 81 7/subop/compare %reg n/imm32 +6291 "compare"/imm32/name +6292 Int-var-in-register-and-literal/imm32/inouts +6293 0/imm32/outputs +6294 "81 7/subop/compare"/imm32/subx-name +6295 1/imm32/rm32-is-first-inout +6296 0/imm32/no-r32 +6297 2/imm32/imm32-is-second-inout +6298 0/imm32/no-disp32 +6299 0/imm32/output-is-write-only +6300 _Primitive-compare-mem-with-literal/imm32/next +6301 _Primitive-compare-mem-with-literal: +6302 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 +6303 "compare"/imm32/name +6304 Int-var-and-literal/imm32/inouts +6305 0/imm32/outputs +6306 "81 7/subop/compare"/imm32/subx-name +6307 1/imm32/rm32-is-first-inout +6308 0/imm32/no-r32 +6309 2/imm32/imm32-is-second-inout +6310 0/imm32/no-disp32 +6311 0/imm32/output-is-write-only +6312 _Primitive-multiply-reg-by-mem/imm32/next +6313 # - multiply +6314 _Primitive-multiply-reg-by-mem: +6315 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 +6316 "multiply"/imm32/name +6317 Single-int-var-in-mem/imm32/inouts +6318 Single-int-var-in-some-register/imm32/outputs +6319 "0f af/multiply"/imm32/subx-name +6320 1/imm32/rm32-is-first-inout +6321 3/imm32/r32-is-first-output +6322 0/imm32/no-imm32 +6323 0/imm32/no-disp32 +6324 0/imm32/output-is-write-only +6325 _Primitive-break-if-addr</imm32/next +6326 # - branches +6327 _Primitive-break-if-addr<: +6328 "break-if-addr<"/imm32/name +6329 0/imm32/inouts +6330 0/imm32/outputs +6331 "0f 82/jump-if-addr< break/disp32"/imm32/subx-name +6332 0/imm32/no-rm32 +6333 0/imm32/no-r32 +6334 0/imm32/no-imm32 +6335 0/imm32/no-disp32 +6336 0/imm32/no-output +6337 _Primitive-break-if-addr>=/imm32/next +6338 _Primitive-break-if-addr>=: +6339 "break-if-addr>="/imm32/name +6340 0/imm32/inouts +6341 0/imm32/outputs +6342 "0f 83/jump-if-addr>= break/disp32"/imm32/subx-name +6343 0/imm32/no-rm32 +6344 0/imm32/no-r32 +6345 0/imm32/no-imm32 +6346 0/imm32/no-disp32 +6347 0/imm32/no-output +6348 _Primitive-break-if-=/imm32/next +6349 _Primitive-break-if-=: +6350 "break-if-="/imm32/name +6351 0/imm32/inouts +6352 0/imm32/outputs +6353 "0f 84/jump-if-= break/disp32"/imm32/subx-name +6354 0/imm32/no-rm32 +6355 0/imm32/no-r32 +6356 0/imm32/no-imm32 +6357 0/imm32/no-disp32 +6358 0/imm32/no-output +6359 _Primitive-break-if-!=/imm32/next +6360 _Primitive-break-if-!=: +6361 "break-if-!="/imm32/name +6362 0/imm32/inouts +6363 0/imm32/outputs +6364 "0f 85/jump-if-!= break/disp32"/imm32/subx-name +6365 0/imm32/no-rm32 +6366 0/imm32/no-r32 +6367 0/imm32/no-imm32 +6368 0/imm32/no-disp32 +6369 0/imm32/no-output +6370 _Primitive-break-if-addr<=/imm32/next +6371 _Primitive-break-if-addr<=: +6372 "break-if-addr<="/imm32/name +6373 0/imm32/inouts +6374 0/imm32/outputs +6375 "0f 86/jump-if-addr<= break/disp32"/imm32/subx-name +6376 0/imm32/no-rm32 +6377 0/imm32/no-r32 +6378 0/imm32/no-imm32 +6379 0/imm32/no-disp32 +6380 0/imm32/no-output +6381 _Primitive-break-if-addr>/imm32/next +6382 _Primitive-break-if-addr>: +6383 "break-if-addr>"/imm32/name +6384 0/imm32/inouts +6385 0/imm32/outputs +6386 "0f 87/jump-if-addr> break/disp32"/imm32/subx-name +6387 0/imm32/no-rm32 +6388 0/imm32/no-r32 +6389 0/imm32/no-imm32 +6390 0/imm32/no-disp32 +6391 0/imm32/no-output +6392 _Primitive-break-if-</imm32/next +6393 _Primitive-break-if-<: +6394 "break-if-<"/imm32/name +6395 0/imm32/inouts +6396 0/imm32/outputs +6397 "0f 8c/jump-if-< break/disp32"/imm32/subx-name +6398 0/imm32/no-rm32 +6399 0/imm32/no-r32 +6400 0/imm32/no-imm32 +6401 0/imm32/no-disp32 +6402 0/imm32/no-output +6403 _Primitive-break-if->=/imm32/next +6404 _Primitive-break-if->=: +6405 "break-if->="/imm32/name +6406 0/imm32/inouts +6407 0/imm32/outputs +6408 "0f 8d/jump-if->= break/disp32"/imm32/subx-name +6409 0/imm32/no-rm32 +6410 0/imm32/no-r32 +6411 0/imm32/no-imm32 +6412 0/imm32/no-disp32 +6413 0/imm32/no-output +6414 _Primitive-break-if-<=/imm32/next +6415 _Primitive-break-if-<=: +6416 "break-if-<="/imm32/name +6417 0/imm32/inouts +6418 0/imm32/outputs +6419 "0f 8e/jump-if-<= break/disp32"/imm32/subx-name +6420 0/imm32/no-rm32 +6421 0/imm32/no-r32 +6422 0/imm32/no-imm32 +6423 0/imm32/no-disp32 +6424 0/imm32/no-output +6425 _Primitive-break-if->/imm32/next +6426 _Primitive-break-if->: +6427 "break-if->"/imm32/name +6428 0/imm32/inouts +6429 0/imm32/outputs +6430 "0f 8f/jump-if-> break/disp32"/imm32/subx-name +6431 0/imm32/no-rm32 +6432 0/imm32/no-r32 +6433 0/imm32/no-imm32 +6434 0/imm32/no-disp32 +6435 0/imm32/no-output +6436 _Primitive-break/imm32/next +6437 _Primitive-break: +6438 "break"/imm32/name +6439 0/imm32/inouts +6440 0/imm32/outputs +6441 "e9/jump break/disp32"/imm32/subx-name +6442 0/imm32/no-rm32 +6443 0/imm32/no-r32 +6444 0/imm32/no-imm32 +6445 0/imm32/no-disp32 +6446 0/imm32/no-output +6447 _Primitive-loop-if-addr</imm32/next +6448 _Primitive-loop-if-addr<: +6449 "loop-if-addr<"/imm32/name +6450 0/imm32/inouts +6451 0/imm32/outputs +6452 "0f 82/jump-if-addr< loop/disp32"/imm32/subx-name +6453 0/imm32/no-rm32 +6454 0/imm32/no-r32 +6455 0/imm32/no-imm32 +6456 0/imm32/no-disp32 +6457 0/imm32/no-output +6458 _Primitive-loop-if-addr>=/imm32/next +6459 _Primitive-loop-if-addr>=: +6460 "loop-if-addr>="/imm32/name +6461 0/imm32/inouts +6462 0/imm32/outputs +6463 "0f 83/jump-if-addr>= loop/disp32"/imm32/subx-name +6464 0/imm32/no-rm32 +6465 0/imm32/no-r32 +6466 0/imm32/no-imm32 +6467 0/imm32/no-disp32 +6468 0/imm32/no-output +6469 _Primitive-loop-if-=/imm32/next +6470 _Primitive-loop-if-=: +6471 "loop-if-="/imm32/name +6472 0/imm32/inouts +6473 0/imm32/outputs +6474 "0f 84/jump-if-= loop/disp32"/imm32/subx-name +6475 0/imm32/no-rm32 +6476 0/imm32/no-r32 +6477 0/imm32/no-imm32 +6478 0/imm32/no-disp32 +6479 0/imm32/no-output +6480 _Primitive-loop-if-!=/imm32/next +6481 _Primitive-loop-if-!=: +6482 "loop-if-!="/imm32/name +6483 0/imm32/inouts +6484 0/imm32/outputs +6485 "0f 85/jump-if-!= loop/disp32"/imm32/subx-name +6486 0/imm32/no-rm32 +6487 0/imm32/no-r32 +6488 0/imm32/no-imm32 +6489 0/imm32/no-disp32 +6490 0/imm32/no-output +6491 _Primitive-loop-if-addr<=/imm32/next +6492 _Primitive-loop-if-addr<=: +6493 "loop-if-addr<="/imm32/name +6494 0/imm32/inouts +6495 0/imm32/outputs +6496 "0f 86/jump-if-addr<= loop/disp32"/imm32/subx-name +6497 0/imm32/no-rm32 +6498 0/imm32/no-r32 +6499 0/imm32/no-imm32 +6500 0/imm32/no-disp32 +6501 0/imm32/no-output +6502 _Primitive-loop-if-addr>/imm32/next +6503 _Primitive-loop-if-addr>: +6504 "loop-if-addr>"/imm32/name +6505 0/imm32/inouts +6506 0/imm32/outputs +6507 "0f 87/jump-if-addr> loop/disp32"/imm32/subx-name +6508 0/imm32/no-rm32 +6509 0/imm32/no-r32 +6510 0/imm32/no-imm32 +6511 0/imm32/no-disp32 +6512 0/imm32/no-output +6513 _Primitive-loop-if-</imm32/next +6514 _Primitive-loop-if-<: +6515 "loop-if-<"/imm32/name +6516 0/imm32/inouts +6517 0/imm32/outputs +6518 "0f 8c/jump-if-< loop/disp32"/imm32/subx-name +6519 0/imm32/no-rm32 +6520 0/imm32/no-r32 +6521 0/imm32/no-imm32 +6522 0/imm32/no-disp32 +6523 0/imm32/no-output +6524 _Primitive-loop-if->=/imm32/next +6525 _Primitive-loop-if->=: +6526 "loop-if->="/imm32/name +6527 0/imm32/inouts +6528 0/imm32/outputs +6529 "0f 8d/jump-if->= loop/disp32"/imm32/subx-name +6530 0/imm32/no-rm32 +6531 0/imm32/no-r32 +6532 0/imm32/no-imm32 +6533 0/imm32/no-disp32 +6534 0/imm32/no-output +6535 _Primitive-loop-if-<=/imm32/next +6536 _Primitive-loop-if-<=: +6537 "loop-if-<="/imm32/name +6538 0/imm32/inouts +6539 0/imm32/outputs +6540 "0f 8e/jump-if-<= loop/disp32"/imm32/subx-name +6541 0/imm32/no-rm32 +6542 0/imm32/no-r32 +6543 0/imm32/no-imm32 +6544 0/imm32/no-disp32 +6545 0/imm32/no-output +6546 _Primitive-loop-if->/imm32/next +6547 _Primitive-loop-if->: +6548 "loop-if->"/imm32/name +6549 0/imm32/inouts +6550 0/imm32/outputs +6551 "0f 8f/jump-if-> loop/disp32"/imm32/subx-name +6552 0/imm32/no-rm32 +6553 0/imm32/no-r32 +6554 0/imm32/no-imm32 +6555 0/imm32/no-disp32 +6556 0/imm32/no-output +6557 _Primitive-loop/imm32/next # we probably don't need an unconditional break +6558 _Primitive-loop: +6559 "loop"/imm32/name +6560 0/imm32/inouts +6561 0/imm32/outputs +6562 "e9/jump loop/disp32"/imm32/subx-name +6563 0/imm32/no-rm32 +6564 0/imm32/no-r32 +6565 0/imm32/no-imm32 +6566 0/imm32/no-disp32 +6567 0/imm32/no-output +6568 _Primitive-break-if-addr<-named/imm32/next +6569 # - branches to named blocks +6570 _Primitive-break-if-addr<-named: +6571 "break-if-addr<"/imm32/name +6572 Single-lit-var/imm32/inouts +6573 0/imm32/outputs +6574 "0f 82/jump-if-addr<"/imm32/subx-name +6575 0/imm32/no-rm32 +6576 0/imm32/no-r32 +6577 0/imm32/no-imm32 +6578 1/imm32/disp32-is-first-inout +6579 0/imm32/no-output +6580 _Primitive-break-if-addr>=-named/imm32/next +6581 _Primitive-break-if-addr>=-named: +6582 "break-if-addr>="/imm32/name +6583 Single-lit-var/imm32/inouts +6584 0/imm32/outputs +6585 "0f 83/jump-if-addr>="/imm32/subx-name +6586 0/imm32/no-rm32 +6587 0/imm32/no-r32 +6588 0/imm32/no-imm32 +6589 1/imm32/disp32-is-first-inout +6590 0/imm32/no-output +6591 _Primitive-break-if-=-named/imm32/next +6592 _Primitive-break-if-=-named: +6593 "break-if-="/imm32/name +6594 Single-lit-var/imm32/inouts +6595 0/imm32/outputs +6596 "0f 84/jump-if-="/imm32/subx-name +6597 0/imm32/no-rm32 +6598 0/imm32/no-r32 +6599 0/imm32/no-imm32 +6600 1/imm32/disp32-is-first-inout +6601 0/imm32/no-output +6602 _Primitive-break-if-!=-named/imm32/next +6603 _Primitive-break-if-!=-named: +6604 "break-if-!="/imm32/name +6605 Single-lit-var/imm32/inouts +6606 0/imm32/outputs +6607 "0f 85/jump-if-!="/imm32/subx-name +6608 0/imm32/no-rm32 +6609 0/imm32/no-r32 +6610 0/imm32/no-imm32 +6611 1/imm32/disp32-is-first-inout +6612 0/imm32/no-output +6613 _Primitive-break-if-addr<=-named/imm32/next +6614 _Primitive-break-if-addr<=-named: +6615 "break-if-addr<="/imm32/name +6616 Single-lit-var/imm32/inouts +6617 0/imm32/outputs +6618 "0f 86/jump-if-addr<="/imm32/subx-name +6619 0/imm32/no-rm32 +6620 0/imm32/no-r32 +6621 0/imm32/no-imm32 +6622 1/imm32/disp32-is-first-inout +6623 0/imm32/no-output +6624 _Primitive-break-if-addr>-named/imm32/next +6625 _Primitive-break-if-addr>-named: +6626 "break-if-addr>"/imm32/name +6627 Single-lit-var/imm32/inouts +6628 0/imm32/outputs +6629 "0f 87/jump-if-addr>"/imm32/subx-name +6630 0/imm32/no-rm32 +6631 0/imm32/no-r32 +6632 0/imm32/no-imm32 +6633 1/imm32/disp32-is-first-inout +6634 0/imm32/no-output +6635 _Primitive-break-if-<-named/imm32/next +6636 _Primitive-break-if-<-named: +6637 "break-if-<"/imm32/name +6638 Single-lit-var/imm32/inouts +6639 0/imm32/outputs +6640 "0f 8c/jump-if-<"/imm32/subx-name +6641 0/imm32/no-rm32 +6642 0/imm32/no-r32 +6643 0/imm32/no-imm32 +6644 1/imm32/disp32-is-first-inout +6645 0/imm32/no-output +6646 _Primitive-break-if->=-named/imm32/next +6647 _Primitive-break-if->=-named: +6648 "break-if->="/imm32/name +6649 Single-lit-var/imm32/inouts +6650 0/imm32/outputs +6651 "0f 8d/jump-if->="/imm32/subx-name +6652 0/imm32/no-rm32 +6653 0/imm32/no-r32 +6654 0/imm32/no-imm32 +6655 1/imm32/disp32-is-first-inout +6656 0/imm32/no-output +6657 _Primitive-break-if-<=-named/imm32/next +6658 _Primitive-break-if-<=-named: +6659 "break-if-<="/imm32/name +6660 Single-lit-var/imm32/inouts +6661 0/imm32/outputs +6662 "0f 8e/jump-if-<="/imm32/subx-name +6663 0/imm32/no-rm32 +6664 0/imm32/no-r32 +6665 0/imm32/no-imm32 +6666 1/imm32/disp32-is-first-inout +6667 0/imm32/no-output +6668 _Primitive-break-if->-named/imm32/next +6669 _Primitive-break-if->-named: +6670 "break-if->"/imm32/name +6671 Single-lit-var/imm32/inouts +6672 0/imm32/outputs +6673 "0f 8f/jump-if->"/imm32/subx-name +6674 0/imm32/no-rm32 +6675 0/imm32/no-r32 +6676 0/imm32/no-imm32 +6677 1/imm32/disp32-is-first-inout +6678 0/imm32/no-output +6679 _Primitive-break-named/imm32/next +6680 _Primitive-break-named: +6681 "break"/imm32/name +6682 Single-lit-var/imm32/inouts +6683 0/imm32/outputs +6684 "e9/jump"/imm32/subx-name +6685 0/imm32/no-rm32 +6686 0/imm32/no-r32 +6687 0/imm32/no-imm32 +6688 1/imm32/disp32-is-first-inout +6689 0/imm32/no-output +6690 _Primitive-loop-if-addr<-named/imm32/next +6691 _Primitive-loop-if-addr<-named: +6692 "loop-if-addr<"/imm32/name +6693 Single-lit-var/imm32/inouts +6694 0/imm32/outputs +6695 "0f 82/jump-if-addr<"/imm32/subx-name +6696 0/imm32/no-rm32 +6697 0/imm32/no-r32 +6698 0/imm32/no-imm32 +6699 1/imm32/disp32-is-first-inout +6700 0/imm32/no-output +6701 _Primitive-loop-if-addr>=-named/imm32/next +6702 _Primitive-loop-if-addr>=-named: +6703 "loop-if-addr>="/imm32/name +6704 Single-lit-var/imm32/inouts +6705 0/imm32/outputs +6706 "0f 83/jump-if-addr>="/imm32/subx-name +6707 0/imm32/no-rm32 +6708 0/imm32/no-r32 +6709 0/imm32/no-imm32 +6710 1/imm32/disp32-is-first-inout +6711 0/imm32/no-output +6712 _Primitive-loop-if-=-named/imm32/next +6713 _Primitive-loop-if-=-named: +6714 "loop-if-="/imm32/name +6715 Single-lit-var/imm32/inouts +6716 0/imm32/outputs +6717 "0f 84/jump-if-="/imm32/subx-name +6718 0/imm32/no-rm32 +6719 0/imm32/no-r32 +6720 0/imm32/no-imm32 +6721 1/imm32/disp32-is-first-inout +6722 0/imm32/no-output +6723 _Primitive-loop-if-!=-named/imm32/next +6724 _Primitive-loop-if-!=-named: +6725 "loop-if-!="/imm32/name +6726 Single-lit-var/imm32/inouts +6727 0/imm32/outputs +6728 "0f 85/jump-if-!="/imm32/subx-name +6729 0/imm32/no-rm32 +6730 0/imm32/no-r32 +6731 0/imm32/no-imm32 +6732 1/imm32/disp32-is-first-inout +6733 0/imm32/no-output +6734 _Primitive-loop-if-addr<=-named/imm32/next +6735 _Primitive-loop-if-addr<=-named: +6736 "loop-if-addr<="/imm32/name +6737 Single-lit-var/imm32/inouts +6738 0/imm32/outputs +6739 "0f 86/jump-if-addr<="/imm32/subx-name +6740 0/imm32/no-rm32 +6741 0/imm32/no-r32 +6742 0/imm32/no-imm32 +6743 1/imm32/disp32-is-first-inout +6744 0/imm32/no-output +6745 _Primitive-loop-if-addr>-named/imm32/next +6746 _Primitive-loop-if-addr>-named: +6747 "loop-if-addr>"/imm32/name +6748 Single-lit-var/imm32/inouts +6749 0/imm32/outputs +6750 "0f 87/jump-if-addr>"/imm32/subx-name +6751 0/imm32/no-rm32 +6752 0/imm32/no-r32 +6753 0/imm32/no-imm32 +6754 1/imm32/disp32-is-first-inout +6755 0/imm32/no-output +6756 _Primitive-loop-if-<-named/imm32/next +6757 _Primitive-loop-if-<-named: +6758 "loop-if-<"/imm32/name +6759 Single-lit-var/imm32/inouts +6760 0/imm32/outputs +6761 "0f 8c/jump-if-<"/imm32/subx-name +6762 0/imm32/no-rm32 +6763 0/imm32/no-r32 +6764 0/imm32/no-imm32 +6765 1/imm32/disp32-is-first-inout +6766 0/imm32/no-output +6767 _Primitive-loop-if->=-named/imm32/next +6768 _Primitive-loop-if->=-named: +6769 "loop-if->="/imm32/name +6770 Single-lit-var/imm32/inouts +6771 0/imm32/outputs +6772 "0f 8d/jump-if->="/imm32/subx-name +6773 0/imm32/no-rm32 +6774 0/imm32/no-r32 +6775 0/imm32/no-imm32 +6776 1/imm32/disp32-is-first-inout +6777 0/imm32/no-output +6778 _Primitive-loop-if-<=-named/imm32/next +6779 _Primitive-loop-if-<=-named: +6780 "loop-if-<="/imm32/name +6781 Single-lit-var/imm32/inouts +6782 0/imm32/outputs +6783 "0f 8e/jump-if-<="/imm32/subx-name +6784 0/imm32/no-rm32 +6785 0/imm32/no-r32 +6786 0/imm32/no-imm32 +6787 1/imm32/disp32-is-first-inout +6788 0/imm32/no-output +6789 _Primitive-loop-if->-named/imm32/next +6790 _Primitive-loop-if->-named: +6791 "loop-if->"/imm32/name +6792 Single-lit-var/imm32/inouts +6793 0/imm32/outputs +6794 "0f 8f/jump-if->"/imm32/subx-name +6795 0/imm32/no-rm32 +6796 0/imm32/no-r32 +6797 0/imm32/no-imm32 +6798 1/imm32/disp32-is-first-inout +6799 0/imm32/no-output +6800 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break +6801 _Primitive-loop-named: +6802 "loop"/imm32/name +6803 Single-lit-var/imm32/inouts +6804 0/imm32/outputs +6805 "e9/jump"/imm32/subx-name +6806 0/imm32/no-rm32 +6807 0/imm32/no-r32 +6808 0/imm32/no-imm32 +6809 1/imm32/disp32-is-first-inout +6810 0/imm32/no-output +6811 0/imm32/next 6812 -6813 Type-literal: -6814 0/imm32/left/literal -6815 0/imm32/right/null +6813 Single-int-var-in-mem: +6814 Int-var-in-mem/imm32 +6815 0/imm32/next 6816 -6817 == code -6818 emit-subx-primitive: # out: (addr buffered-file), stmt: (handle statement), primitive: (handle function) -6819 # . prologue -6820 55/push-ebp -6821 89/<- %ebp 4/r32/esp -6822 # . save registers -6823 50/push-eax -6824 51/push-ecx -6825 # ecx = primitive -6826 8b/-> *(ebp+0x10) 1/r32/ecx -6827 # emit primitive name -6828 (emit-indent *(ebp+8) *Curr-block-depth) -6829 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name -6830 # emit rm32 if necessary -6831 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt -6832 # emit r32 if necessary -6833 (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt -6834 # emit imm32 if necessary -6835 (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt -6836 # emit disp32 if necessary -6837 (emit-subx-disp32 *(ebp+8) *(ecx+0x1c) *(ebp+0xc)) # out, Primitive-subx-disp32, stmt -6838 (write-buffered *(ebp+8) Newline) -6839 $emit-subx-primitive:end: -6840 # . restore registers -6841 59/pop-to-ecx -6842 58/pop-to-eax -6843 # . epilogue -6844 89/<- %esp 5/r32/ebp -6845 5d/pop-to-ebp -6846 c3/return +6817 Int-var-in-mem: +6818 "arg1"/imm32/name +6819 Type-int/imm32 +6820 1/imm32/some-block-depth +6821 1/imm32/some-stack-offset +6822 0/imm32/no-register +6823 +6824 Two-args-int-stack-int-reg: +6825 Int-var-in-mem/imm32 +6826 Single-int-var-in-some-register/imm32/next +6827 +6828 Two-args-int-reg-int-stack: +6829 Int-var-in-some-register/imm32 +6830 Single-int-var-in-mem/imm32/next +6831 +6832 Two-args-int-eax-int-literal: +6833 Int-var-in-eax/imm32 +6834 Single-lit-var/imm32/next +6835 +6836 Int-var-and-literal: +6837 Int-var-in-mem/imm32 +6838 Single-lit-var/imm32/next +6839 +6840 Int-var-in-register-and-literal: +6841 Int-var-in-some-register/imm32 +6842 Single-lit-var/imm32/next +6843 +6844 Single-int-var-in-some-register: +6845 Int-var-in-some-register/imm32 +6846 0/imm32/next 6847 -6848 emit-subx-rm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6849 # . prologue -6850 55/push-ebp -6851 89/<- %ebp 4/r32/esp -6852 # . save registers -6853 50/push-eax -6854 # if (l == 0) return -6855 81 7/subop/compare *(ebp+0xc) 0/imm32 -6856 74/jump-if-= $emit-subx-rm32:end/disp8 -6857 # -6858 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -6859 (emit-subx-var-as-rm32 *(ebp+8) %eax) # out, var -6860 $emit-subx-rm32:end: -6861 # . restore registers -6862 58/pop-to-eax -6863 # . epilogue -6864 89/<- %esp 5/r32/ebp -6865 5d/pop-to-ebp -6866 c3/return -6867 -6868 get-stmt-operand-from-arg-location: # stmt: (handle statement), l: arg-location -> var/eax: (handle variable) -6869 # . prologue -6870 55/push-ebp -6871 89/<- %ebp 4/r32/esp -6872 # . save registers -6873 51/push-ecx -6874 # eax = l -6875 8b/-> *(ebp+0xc) 0/r32/eax -6876 # ecx = stmt -6877 8b/-> *(ebp+8) 1/r32/ecx -6878 # if (l == 1) return stmt->inouts->var -6879 { -6880 3d/compare-eax-and 1/imm32 -6881 75/jump-if-!= break/disp8 -6882 $get-stmt-operand-from-arg-location:1: -6883 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts -6884 8b/-> *eax 0/r32/eax # Operand-var -6885 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -6886 } -6887 # if (l == 2) return stmt->inouts->next->var -6888 { -6889 3d/compare-eax-and 2/imm32 -6890 75/jump-if-!= break/disp8 -6891 $get-stmt-operand-from-arg-location:2: -6892 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts -6893 8b/-> *(eax+4) 0/r32/eax # Operand-next -6894 8b/-> *eax 0/r32/eax # Operand-var -6895 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -6896 } -6897 # if (l == 3) return stmt->outputs -6898 { -6899 3d/compare-eax-and 3/imm32 -6900 75/jump-if-!= break/disp8 -6901 $get-stmt-operand-from-arg-location:3: -6902 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs -6903 8b/-> *eax 0/r32/eax # Operand-var -6904 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -6905 } -6906 # abort -6907 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 -6908 $get-stmt-operand-from-arg-location:end: -6909 # . restore registers -6910 59/pop-to-ecx -6911 # . epilogue -6912 89/<- %esp 5/r32/ebp -6913 5d/pop-to-ebp -6914 c3/return -6915 -6916 $get-stmt-operand-from-arg-location:abort: -6917 # error("invalid arg-location " eax) -6918 (write-buffered Stderr "invalid arg-location ") -6919 (print-int32-buffered Stderr %eax) -6920 (write-buffered Stderr Newline) -6921 (flush Stderr) -6922 # . syscall(exit, 1) -6923 bb/copy-to-ebx 1/imm32 -6924 b8/copy-to-eax 1/imm32/exit -6925 cd/syscall 0x80/imm8 -6926 # never gets here -6927 -6928 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6929 # . prologue -6930 55/push-ebp -6931 89/<- %ebp 4/r32/esp -6932 # . save registers -6933 50/push-eax -6934 51/push-ecx -6935 # if (location == 0) return -6936 81 7/subop/compare *(ebp+0xc) 0/imm32 -6937 0f 84/jump-if-= $emit-subx-r32:end/disp32 -6938 # -6939 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -6940 (maybe-get Registers *(eax+0x10) 8) # Var-register => eax: (addr register-index) -6941 (write-buffered *(ebp+8) Space) -6942 (print-int32-buffered *(ebp+8) *eax) -6943 (write-buffered *(ebp+8) "/r32") -6944 $emit-subx-r32:end: -6945 # . restore registers -6946 59/pop-to-ecx -6947 58/pop-to-eax -6948 # . epilogue -6949 89/<- %esp 5/r32/ebp -6950 5d/pop-to-ebp -6951 c3/return -6952 -6953 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6954 # . prologue -6955 55/push-ebp -6956 89/<- %ebp 4/r32/esp -6957 # . save registers -6958 50/push-eax -6959 51/push-ecx -6960 # if (location == 0) return -6961 81 7/subop/compare *(ebp+0xc) 0/imm32 -6962 74/jump-if-= $emit-subx-imm32:end/disp8 -6963 # -6964 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -6965 (write-buffered *(ebp+8) Space) -6966 (write-buffered *(ebp+8) *eax) # Var-name -6967 (write-buffered *(ebp+8) "/imm32") -6968 $emit-subx-imm32:end: -6969 # . restore registers -6970 59/pop-to-ecx -6971 58/pop-to-eax -6972 # . epilogue -6973 89/<- %esp 5/r32/ebp -6974 5d/pop-to-ebp -6975 c3/return -6976 -6977 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6978 # . prologue -6979 55/push-ebp -6980 89/<- %ebp 4/r32/esp -6981 # . save registers -6982 50/push-eax -6983 51/push-ecx -6984 # if (location == 0) return -6985 81 7/subop/compare *(ebp+0xc) 0/imm32 -6986 0f 84/jump-if-= $emit-subx-disp32:end/disp32 -6987 # -6988 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax -6989 (write-buffered *(ebp+8) Space) -6990 (write-buffered *(ebp+8) *eax) # Var-name -6991 # hack: if instruction operation starts with "break", emit ":break" -6992 # var name/ecx: (addr array byte) = stmt->operation -6993 8b/-> *(ebp+0x10) 0/r32/eax -6994 8b/-> *(eax+4) 1/r32/ecx -6995 { -6996 (string-starts-with? %ecx "break") # => eax -6997 3d/compare-eax-and 0/imm32/false -6998 74/jump-if-= break/disp8 -6999 (write-buffered *(ebp+8) ":break") -7000 } -7001 # hack: if instruction operation starts with "loop", emit ":loop" +6848 Int-var-in-some-register: +6849 "arg1"/imm32/name +6850 Type-int/imm32 +6851 1/imm32/some-block-depth +6852 0/imm32/no-stack-offset +6853 Any-register/imm32 +6854 +6855 Single-int-var-in-eax: +6856 Int-var-in-eax/imm32 +6857 0/imm32/next +6858 +6859 Int-var-in-eax: +6860 "arg1"/imm32/name +6861 Type-int/imm32 +6862 1/imm32/some-block-depth +6863 0/imm32/no-stack-offset +6864 "eax"/imm32/register +6865 +6866 Single-int-var-in-ecx: +6867 Int-var-in-ecx/imm32 +6868 0/imm32/next +6869 +6870 Int-var-in-ecx: +6871 "arg1"/imm32/name +6872 Type-int/imm32 +6873 1/imm32/some-block-depth +6874 0/imm32/no-stack-offset +6875 "ecx"/imm32/register +6876 +6877 Single-int-var-in-edx: +6878 Int-var-in-edx/imm32 +6879 0/imm32/next +6880 +6881 Int-var-in-edx: +6882 "arg1"/imm32/name +6883 Type-int/imm32 +6884 1/imm32/some-block-depth +6885 0/imm32/no-stack-offset +6886 "edx"/imm32/register +6887 +6888 Single-int-var-in-ebx: +6889 Int-var-in-ebx/imm32 +6890 0/imm32/next +6891 +6892 Int-var-in-ebx: +6893 "arg1"/imm32/name +6894 Type-int/imm32 +6895 1/imm32/some-block-depth +6896 0/imm32/no-stack-offset +6897 "ebx"/imm32/register +6898 +6899 Single-int-var-in-esi: +6900 Int-var-in-esi/imm32 +6901 0/imm32/next +6902 +6903 Int-var-in-esi: +6904 "arg1"/imm32/name +6905 Type-int/imm32 +6906 1/imm32/some-block-depth +6907 0/imm32/no-stack-offset +6908 "esi"/imm32/register +6909 +6910 Single-int-var-in-edi: +6911 Int-var-in-edi/imm32 +6912 0/imm32/next +6913 +6914 Int-var-in-edi: +6915 "arg1"/imm32/name +6916 Type-int/imm32 +6917 1/imm32/some-block-depth +6918 0/imm32/no-stack-offset +6919 "edi"/imm32/register +6920 +6921 Single-lit-var: +6922 Lit-var/imm32 +6923 0/imm32/next +6924 +6925 Lit-var: +6926 "literal"/imm32/name +6927 Type-literal/imm32 +6928 1/imm32/some-block-depth +6929 0/imm32/no-stack-offset +6930 0/imm32/no-register +6931 +6932 Type-int: +6933 1/imm32/left/int +6934 0/imm32/right/null +6935 +6936 Type-literal: +6937 0/imm32/left/literal +6938 0/imm32/right/null +6939 +6940 == code +6941 emit-subx-primitive: # out: (addr buffered-file), stmt: (handle statement), primitive: (handle function) +6942 # . prologue +6943 55/push-ebp +6944 89/<- %ebp 4/r32/esp +6945 # . save registers +6946 50/push-eax +6947 51/push-ecx +6948 # ecx = primitive +6949 8b/-> *(ebp+0x10) 1/r32/ecx +6950 # emit primitive name +6951 (emit-indent *(ebp+8) *Curr-block-depth) +6952 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name +6953 # emit rm32 if necessary +6954 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt +6955 # emit r32 if necessary +6956 (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt +6957 # emit imm32 if necessary +6958 (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt +6959 # emit disp32 if necessary +6960 (emit-subx-disp32 *(ebp+8) *(ecx+0x1c) *(ebp+0xc)) # out, Primitive-subx-disp32, stmt +6961 (write-buffered *(ebp+8) Newline) +6962 $emit-subx-primitive:end: +6963 # . restore registers +6964 59/pop-to-ecx +6965 58/pop-to-eax +6966 # . epilogue +6967 89/<- %esp 5/r32/ebp +6968 5d/pop-to-ebp +6969 c3/return +6970 +6971 emit-subx-rm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) +6972 # . prologue +6973 55/push-ebp +6974 89/<- %ebp 4/r32/esp +6975 # . save registers +6976 50/push-eax +6977 # if (l == 0) return +6978 81 7/subop/compare *(ebp+0xc) 0/imm32 +6979 74/jump-if-= $emit-subx-rm32:end/disp8 +6980 # var v/eax: (handle var) +6981 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax +6982 (emit-subx-var-as-rm32 *(ebp+8) %eax) +6983 $emit-subx-rm32:end: +6984 # . restore registers +6985 58/pop-to-eax +6986 # . epilogue +6987 89/<- %esp 5/r32/ebp +6988 5d/pop-to-ebp +6989 c3/return +6990 +6991 get-stmt-operand-from-arg-location: # stmt: (handle statement), l: arg-location -> var/eax: (handle stmt-var) +6992 # . prologue +6993 55/push-ebp +6994 89/<- %ebp 4/r32/esp +6995 # . save registers +6996 51/push-ecx +6997 # eax = l +6998 8b/-> *(ebp+0xc) 0/r32/eax +6999 # ecx = stmt +7000 8b/-> *(ebp+8) 1/r32/ecx +7001 # if (l == 1) return stmt->inouts 7002 { -7003 (string-starts-with? %ecx "loop") # => eax -7004 3d/compare-eax-and 0/imm32/false -7005 74/jump-if-= break/disp8 -7006 (write-buffered *(ebp+8) ":loop") -7007 } -7008 (write-buffered *(ebp+8) "/disp32") -7009 $emit-subx-disp32:end: -7010 # . restore registers -7011 59/pop-to-ecx -7012 58/pop-to-eax -7013 # . epilogue -7014 89/<- %esp 5/r32/ebp -7015 5d/pop-to-ebp -7016 c3/return -7017 -7018 emit-subx-call: # out: (addr buffered-file), stmt: (handle statement), callee: (handle function) -7019 # . prologue -7020 55/push-ebp -7021 89/<- %ebp 4/r32/esp -7022 # . save registers -7023 51/push-ecx -7024 # -7025 (emit-indent *(ebp+8) *Curr-block-depth) -7026 (write-buffered *(ebp+8) "(") -7027 # - emit function name -7028 8b/-> *(ebp+0x10) 1/r32/ecx -7029 (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name -7030 # - emit arguments -7031 # var curr/ecx: (handle list var) = stmt->inouts -7032 8b/-> *(ebp+0xc) 1/r32/ecx -7033 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts -7034 { -7035 # if (curr == null) break -7036 81 7/subop/compare %ecx 0/imm32 -7037 74/jump-if-= break/disp8 -7038 # -7039 (emit-subx-call-operand *(ebp+8) *ecx) -7040 # curr = curr->next -7041 8b/-> *(ecx+4) 1/r32/ecx -7042 eb/jump loop/disp8 -7043 } -7044 # -7045 (write-buffered *(ebp+8) ")\n") -7046 $emit-subx-call:end: -7047 # . restore registers -7048 59/pop-to-ecx -7049 # . epilogue -7050 89/<- %esp 5/r32/ebp -7051 5d/pop-to-ebp -7052 c3/return -7053 -7054 # like a function call, except we have no idea what function it is -7055 # we hope it's defined in SubX and that the types are ok -7056 emit-hailmary-call: # out: (addr buffered-file), stmt: (handle statement) -7057 # . prologue -7058 55/push-ebp -7059 89/<- %ebp 4/r32/esp -7060 # . save registers -7061 51/push-ecx -7062 # -7063 (emit-indent *(ebp+8) *Curr-block-depth) -7064 (write-buffered *(ebp+8) "(") -7065 # ecx = stmt -7066 8b/-> *(ebp+0xc) 1/r32/ecx -7067 # - emit function name -7068 (write-buffered *(ebp+8) *(ecx+4)) # Stmt1-operation -7069 # - emit arguments -7070 # var curr/ecx: (handle list var) = stmt->inouts -7071 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts -7072 { -7073 # if (curr == null) break -7074 81 7/subop/compare %ecx 0/imm32 -7075 74/jump-if-= break/disp8 -7076 # -7077 (emit-subx-call-operand *(ebp+8) *ecx) -7078 # curr = curr->next -7079 8b/-> *(ecx+4) 1/r32/ecx -7080 eb/jump loop/disp8 -7081 } -7082 # -7083 (write-buffered *(ebp+8) ")\n") -7084 $emit-hailmary-call:end: -7085 # . restore registers -7086 59/pop-to-ecx -7087 # . epilogue -7088 89/<- %esp 5/r32/ebp -7089 5d/pop-to-ebp -7090 c3/return -7091 -7092 emit-subx-call-operand: # out: (addr buffered-file), operand: (handle variable) -7093 # shares code with emit-subx-var-as-rm32 -7094 # . prologue -7095 55/push-ebp -7096 89/<- %ebp 4/r32/esp -7097 # . save registers -7098 50/push-eax -7099 # eax = operand -7100 8b/-> *(ebp+0xc) 0/r32/eax -7101 # if (operand->register) emit "%__" -7102 { -7103 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -7104 74/jump-if-= break/disp8 -7105 $emit-subx-call-operand:register: -7106 (write-buffered *(ebp+8) " %") -7107 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register -7108 e9/jump $emit-subx-call-operand:end/disp32 -7109 } -7110 # else if (operand->stack-offset) emit "*(ebp+__)" -7111 { -7112 81 7/subop/compare *(eax+0xc) 0/imm32 # Var-stack-offset -7113 74/jump-if-= break/disp8 -7114 $emit-subx-call-operand:stack: -7115 (write-buffered *(ebp+8) Space) -7116 (write-buffered *(ebp+8) "*(ebp+") -7117 8b/-> *(ebp+0xc) 0/r32/eax -7118 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-stack-offset -7119 (write-buffered *(ebp+8) ")") -7120 e9/jump $emit-subx-call-operand:end/disp32 -7121 } -7122 # else if (operand->type == literal) emit "__" -7123 { -7124 50/push-eax -7125 8b/-> *(eax+4) 0/r32/eax # Var-type -7126 81 7/subop/compare *eax 0/imm32 # Tree-left -7127 58/pop-to-eax -7128 75/jump-if-!= break/disp8 -7129 $emit-subx-call-operand:literal: -7130 (write-buffered *(ebp+8) Space) -7131 (write-buffered *(ebp+8) *eax) -7132 } -7133 $emit-subx-call-operand:end: -7134 # . restore registers +7003 3d/compare-eax-and 1/imm32 +7004 75/jump-if-!= break/disp8 +7005 $get-stmt-operand-from-arg-location:1: +7006 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts +7007 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +7008 } +7009 # if (l == 2) return stmt->inouts->next +7010 { +7011 3d/compare-eax-and 2/imm32 +7012 75/jump-if-!= break/disp8 +7013 $get-stmt-operand-from-arg-location:2: +7014 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts +7015 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next +7016 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +7017 } +7018 # if (l == 3) return stmt->outputs +7019 { +7020 3d/compare-eax-and 3/imm32 +7021 75/jump-if-!= break/disp8 +7022 $get-stmt-operand-from-arg-location:3: +7023 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs +7024 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +7025 } +7026 # abort +7027 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 +7028 $get-stmt-operand-from-arg-location:end: +7029 # . restore registers +7030 59/pop-to-ecx +7031 # . epilogue +7032 89/<- %esp 5/r32/ebp +7033 5d/pop-to-ebp +7034 c3/return +7035 +7036 $get-stmt-operand-from-arg-location:abort: +7037 # error("invalid arg-location " eax) +7038 (write-buffered Stderr "invalid arg-location ") +7039 (print-int32-buffered Stderr %eax) +7040 (write-buffered Stderr Newline) +7041 (flush Stderr) +7042 # . syscall(exit, 1) +7043 bb/copy-to-ebx 1/imm32 +7044 b8/copy-to-eax 1/imm32/exit +7045 cd/syscall 0x80/imm8 +7046 # never gets here +7047 +7048 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) +7049 # . prologue +7050 55/push-ebp +7051 89/<- %ebp 4/r32/esp +7052 # . save registers +7053 50/push-eax +7054 51/push-ecx +7055 # if (location == 0) return +7056 81 7/subop/compare *(ebp+0xc) 0/imm32 +7057 0f 84/jump-if-= $emit-subx-r32:end/disp32 +7058 # var v/eax: (handle var) +7059 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax +7060 8b/-> *eax 0/r32/eax # Stmt-var-value +7061 (maybe-get Registers *(eax+0x10) 8) # Var-register => eax: (addr register-index) +7062 (write-buffered *(ebp+8) Space) +7063 (print-int32-buffered *(ebp+8) *eax) +7064 (write-buffered *(ebp+8) "/r32") +7065 $emit-subx-r32:end: +7066 # . restore registers +7067 59/pop-to-ecx +7068 58/pop-to-eax +7069 # . epilogue +7070 89/<- %esp 5/r32/ebp +7071 5d/pop-to-ebp +7072 c3/return +7073 +7074 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) +7075 # . prologue +7076 55/push-ebp +7077 89/<- %ebp 4/r32/esp +7078 # . save registers +7079 50/push-eax +7080 51/push-ecx +7081 # if (location == 0) return +7082 81 7/subop/compare *(ebp+0xc) 0/imm32 +7083 74/jump-if-= $emit-subx-imm32:end/disp8 +7084 # var v/eax: (handle var) +7085 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax +7086 8b/-> *eax 0/r32/eax # Stmt-var-value +7087 (write-buffered *(ebp+8) Space) +7088 (write-buffered *(ebp+8) *eax) # Var-name +7089 (write-buffered *(ebp+8) "/imm32") +7090 $emit-subx-imm32:end: +7091 # . restore registers +7092 59/pop-to-ecx +7093 58/pop-to-eax +7094 # . epilogue +7095 89/<- %esp 5/r32/ebp +7096 5d/pop-to-ebp +7097 c3/return +7098 +7099 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) +7100 # . prologue +7101 55/push-ebp +7102 89/<- %ebp 4/r32/esp +7103 # . save registers +7104 50/push-eax +7105 51/push-ecx +7106 # if (location == 0) return +7107 81 7/subop/compare *(ebp+0xc) 0/imm32 +7108 0f 84/jump-if-= $emit-subx-disp32:end/disp32 +7109 # var v/eax: (handle var) +7110 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax +7111 8b/-> *eax 0/r32/eax # Stmt-var-value +7112 (write-buffered *(ebp+8) Space) +7113 (write-buffered *(ebp+8) *eax) # Var-name +7114 # hack: if instruction operation starts with "break", emit ":break" +7115 # var name/ecx: (addr array byte) = stmt->operation +7116 8b/-> *(ebp+0x10) 0/r32/eax +7117 8b/-> *(eax+4) 1/r32/ecx +7118 { +7119 (string-starts-with? %ecx "break") # => eax +7120 3d/compare-eax-and 0/imm32/false +7121 74/jump-if-= break/disp8 +7122 (write-buffered *(ebp+8) ":break") +7123 } +7124 # hack: if instruction operation starts with "loop", emit ":loop" +7125 { +7126 (string-starts-with? %ecx "loop") # => eax +7127 3d/compare-eax-and 0/imm32/false +7128 74/jump-if-= break/disp8 +7129 (write-buffered *(ebp+8) ":loop") +7130 } +7131 (write-buffered *(ebp+8) "/disp32") +7132 $emit-subx-disp32:end: +7133 # . restore registers +7134 59/pop-to-ecx 7135 58/pop-to-eax 7136 # . epilogue 7137 89/<- %esp 5/r32/ebp 7138 5d/pop-to-ebp 7139 c3/return 7140 -7141 emit-subx-var-as-rm32: # out: (addr buffered-file), operand: (handle variable) +7141 emit-subx-call: # out: (addr buffered-file), stmt: (handle statement), callee: (handle function) 7142 # . prologue 7143 55/push-ebp 7144 89/<- %ebp 4/r32/esp 7145 # . save registers -7146 50/push-eax -7147 # eax = operand -7148 8b/-> *(ebp+0xc) 0/r32/eax -7149 # if (operand->register) emit "%__" -7150 { -7151 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -7152 74/jump-if-= break/disp8 -7153 $emit-subx-var-as-rm32:register: -7154 (write-buffered *(ebp+8) " %") -7155 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register -7156 } -7157 # else if (operand->stack-offset) emit "*(ebp+__)" -7158 { -7159 81 7/subop/compare *(eax+0xc) 0/imm32 # Var-stack-offset +7146 51/push-ecx +7147 # +7148 (emit-indent *(ebp+8) *Curr-block-depth) +7149 (write-buffered *(ebp+8) "(") +7150 # - emit function name +7151 8b/-> *(ebp+0x10) 1/r32/ecx +7152 (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name +7153 # - emit arguments +7154 # var curr/ecx: (handle stmt-var) = stmt->inouts +7155 8b/-> *(ebp+0xc) 1/r32/ecx +7156 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts +7157 { +7158 # if (curr == null) break +7159 81 7/subop/compare %ecx 0/imm32 7160 74/jump-if-= break/disp8 -7161 $emit-subx-var-as-rm32:stack: -7162 (write-buffered *(ebp+8) Space) -7163 (write-buffered *(ebp+8) "*(ebp+") -7164 8b/-> *(ebp+0xc) 0/r32/eax -7165 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-stack-offset -7166 (write-buffered *(ebp+8) ")") -7167 } -7168 $emit-subx-var-as-rm32:end: -7169 # . restore registers -7170 58/pop-to-eax -7171 # . epilogue -7172 89/<- %esp 5/r32/ebp -7173 5d/pop-to-ebp -7174 c3/return -7175 -7176 find-matching-function: # functions: (addr function), stmt: (handle statement) -> result/eax: (handle function) -7177 # . prologue -7178 55/push-ebp -7179 89/<- %ebp 4/r32/esp -7180 # . save registers -7181 51/push-ecx -7182 # var curr/ecx: (handle function) = functions -7183 8b/-> *(ebp+8) 1/r32/ecx -7184 { -7185 # if (curr == null) break -7186 81 7/subop/compare %ecx 0/imm32 -7187 74/jump-if-= break/disp8 -7188 # if match(stmt, curr) return curr -7189 { -7190 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax -7191 3d/compare-eax-and 0/imm32/false -7192 74/jump-if-= break/disp8 -7193 89/<- %eax 1/r32/ecx -7194 eb/jump $find-matching-function:end/disp8 -7195 } -7196 # curr = curr->next -7197 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next -7198 eb/jump loop/disp8 -7199 } -7200 # return null -7201 b8/copy-to-eax 0/imm32 -7202 $find-matching-function:end: -7203 # . restore registers -7204 59/pop-to-ecx -7205 # . epilogue -7206 89/<- %esp 5/r32/ebp -7207 5d/pop-to-ebp -7208 c3/return -7209 -7210 find-matching-primitive: # primitives: (handle primitive), stmt: (handle statement) -> result/eax: (handle primitive) -7211 # . prologue -7212 55/push-ebp -7213 89/<- %ebp 4/r32/esp -7214 # . save registers -7215 51/push-ecx -7216 # var curr/ecx: (handle primitive) = primitives -7217 8b/-> *(ebp+8) 1/r32/ecx -7218 { -7219 $find-matching-primitive:loop: -7220 # if (curr == null) break -7221 81 7/subop/compare %ecx 0/imm32 -7222 0f 84/jump-if-= break/disp32 -7223 #? (write-buffered Stderr "prim: ") -7224 #? (write-buffered Stderr *ecx) # Primitive-name -7225 #? (write-buffered Stderr " => ") -7226 #? (write-buffered Stderr *(ecx+0xc)) # Primitive-subx-name -7227 #? (write-buffered Stderr Newline) -7228 #? (flush Stderr) -7229 # if match(curr, stmt) return curr -7230 { -7231 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax -7232 3d/compare-eax-and 0/imm32/false -7233 74/jump-if-= break/disp8 -7234 89/<- %eax 1/r32/ecx -7235 eb/jump $find-matching-primitive:end/disp8 -7236 } -7237 $find-matching-primitive:next-primitive: -7238 # curr = curr->next -7239 8b/-> *(ecx+0x24) 1/r32/ecx # Primitive-next -7240 e9/jump loop/disp32 -7241 } -7242 # return null -7243 b8/copy-to-eax 0/imm32 -7244 $find-matching-primitive:end: -7245 # . restore registers -7246 59/pop-to-ecx -7247 # . epilogue -7248 89/<- %esp 5/r32/ebp -7249 5d/pop-to-ebp -7250 c3/return -7251 -7252 mu-stmt-matches-function?: # stmt: (handle statement), function: (handle function) -> result/eax: boolean -7253 # . prologue -7254 55/push-ebp -7255 89/<- %ebp 4/r32/esp -7256 # . save registers -7257 51/push-ecx -7258 # return function->name == stmt->operation -7259 8b/-> *(ebp+8) 1/r32/ecx -7260 8b/-> *(ebp+0xc) 0/r32/eax -7261 (string-equal? *(ecx+4) *eax) # Stmt1-operation, Function-name => eax -7262 $mu-stmt-matches-function?:end: -7263 # . restore registers -7264 59/pop-to-ecx -7265 # . epilogue -7266 89/<- %esp 5/r32/ebp -7267 5d/pop-to-ebp -7268 c3/return -7269 -7270 mu-stmt-matches-primitive?: # stmt: (handle statement), primitive: (handle primitive) -> result/eax: boolean -7271 # A mu stmt matches a primitive if the name matches, all the inout vars -7272 # match, and all the output vars match. -7273 # Vars match if types match and registers match. -7274 # In addition, a stmt output matches a primitive's output if types match -7275 # and the primitive has a wildcard register. -7276 # . prologue -7277 55/push-ebp -7278 89/<- %ebp 4/r32/esp -7279 # . save registers -7280 51/push-ecx -7281 52/push-edx -7282 53/push-ebx -7283 56/push-esi -7284 57/push-edi -7285 # ecx = stmt -7286 8b/-> *(ebp+8) 1/r32/ecx -7287 # edx = primitive -7288 8b/-> *(ebp+0xc) 2/r32/edx -7289 { -7290 $mu-stmt-matches-primitive?:check-name: -7291 # if (primitive->name != stmt->operation) return false -7292 (string-equal? *(ecx+4) *edx) # Stmt1-operation, Primitive-name => eax -7293 3d/compare-eax-and 0/imm32/false +7161 # +7162 (emit-subx-call-operand *(ebp+8) %ecx) +7163 # curr = curr->next +7164 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next +7165 eb/jump loop/disp8 +7166 } +7167 # +7168 (write-buffered *(ebp+8) ")\n") +7169 $emit-subx-call:end: +7170 # . restore registers +7171 59/pop-to-ecx +7172 # . epilogue +7173 89/<- %esp 5/r32/ebp +7174 5d/pop-to-ebp +7175 c3/return +7176 +7177 # like a function call, except we have no idea what function it is +7178 # we hope it's defined in SubX and that the types are ok +7179 emit-hailmary-call: # out: (addr buffered-file), stmt: (handle statement) +7180 # . prologue +7181 55/push-ebp +7182 89/<- %ebp 4/r32/esp +7183 # . save registers +7184 51/push-ecx +7185 # +7186 (emit-indent *(ebp+8) *Curr-block-depth) +7187 (write-buffered *(ebp+8) "(") +7188 # ecx = stmt +7189 8b/-> *(ebp+0xc) 1/r32/ecx +7190 # - emit function name +7191 (write-buffered *(ebp+8) *(ecx+4)) # Stmt1-operation +7192 # - emit arguments +7193 # var curr/ecx: (handle stmt-var) = stmt->inouts +7194 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts +7195 { +7196 # if (curr == null) break +7197 81 7/subop/compare %ecx 0/imm32 +7198 74/jump-if-= break/disp8 +7199 # +7200 (emit-subx-call-operand *(ebp+8) %ecx) +7201 # curr = curr->next +7202 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next +7203 eb/jump loop/disp8 +7204 } +7205 # +7206 (write-buffered *(ebp+8) ")\n") +7207 $emit-hailmary-call:end: +7208 # . restore registers +7209 59/pop-to-ecx +7210 # . epilogue +7211 89/<- %esp 5/r32/ebp +7212 5d/pop-to-ebp +7213 c3/return +7214 +7215 emit-subx-call-operand: # out: (addr buffered-file), s: (handle stmt-var) +7216 # shares code with emit-subx-var-as-rm32 +7217 # . prologue +7218 55/push-ebp +7219 89/<- %ebp 4/r32/esp +7220 # . save registers +7221 50/push-eax +7222 51/push-ecx +7223 56/push-esi +7224 # ecx = s +7225 8b/-> *(ebp+0xc) 1/r32/ecx +7226 # var operand/esi: (handle var) = s->value +7227 8b/-> *ecx 6/r32/esi # Stmt-var-value +7228 # if (operand->register) emit "%__" +7229 { +7230 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +7231 74/jump-if-= break/disp8 +7232 $emit-subx-call-operand:register: +7233 (write-buffered *(ebp+8) " %") +7234 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register +7235 e9/jump $emit-subx-call-operand:end/disp32 +7236 } +7237 # else if (operand->stack-offset) emit "*(ebp+__)" +7238 { +7239 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-stack-offset +7240 74/jump-if-= break/disp8 +7241 $emit-subx-call-operand:stack: +7242 (write-buffered *(ebp+8) Space) +7243 (write-buffered *(ebp+8) "*(ebp+") +7244 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-stack-offset +7245 (write-buffered *(ebp+8) ")") +7246 e9/jump $emit-subx-call-operand:end/disp32 +7247 } +7248 # else if (operand->type == literal) emit "__" +7249 { +7250 8b/-> *(esi+4) 0/r32/eax # Var-type +7251 81 7/subop/compare *eax 0/imm32 # Tree-left +7252 75/jump-if-!= break/disp8 +7253 $emit-subx-call-operand:literal: +7254 (write-buffered *(ebp+8) Space) +7255 (write-buffered *(ebp+8) *esi) +7256 } +7257 $emit-subx-call-operand:end: +7258 # . restore registers +7259 5e/pop-to-esi +7260 59/pop-to-ecx +7261 58/pop-to-eax +7262 # . epilogue +7263 89/<- %esp 5/r32/ebp +7264 5d/pop-to-ebp +7265 c3/return +7266 +7267 emit-subx-var-as-rm32: # out: (addr buffered-file), s: (handle stmt-var) +7268 # . prologue +7269 55/push-ebp +7270 89/<- %ebp 4/r32/esp +7271 # . save registers +7272 50/push-eax +7273 51/push-ecx +7274 56/push-esi +7275 # ecx = s +7276 8b/-> *(ebp+0xc) 1/r32/ecx +7277 # var operand/esi: (handle var) = s->value +7278 8b/-> *ecx 6/r32/esi # Stmt-var-value +7279 # if (operand->register && s->is-deref?) emit "*__" +7280 { +7281 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +7282 74/jump-if-= break/disp8 +7283 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +7284 74/jump-if-= break/disp8 +7285 $emit-subx-var-as-rm32:register-indirect: +7286 (write-buffered *(ebp+8) " *") +7287 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register +7288 } +7289 # if (operand->register && !s->is-deref?) emit "%__" +7290 { +7291 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +7292 74/jump-if-= break/disp8 +7293 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref 7294 75/jump-if-!= break/disp8 -7295 b8/copy-to-eax 0/imm32 -7296 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7297 } -7298 $mu-stmt-matches-primitive?:check-inouts: -7299 # for (curr/esi in stmt->inouts, curr2/edi in primitive->inouts) -7300 8b/-> *(ecx+8) 6/r32/esi # Stmt1-inouts -7301 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts -7302 { -7303 # if (curr == 0 && curr2 == 0) move on to check outputs -7304 { -7305 81 7/subop/compare %esi 0/imm32 -7306 75/jump-if-!= break/disp8 -7307 $mu-stmt-matches-primitive?:stmt-inout-is-null: -7308 { -7309 81 7/subop/compare %edi 0/imm32 -7310 75/jump-if-!= break/disp8 -7311 # -7312 e9/jump $mu-stmt-matches-primitive?:check-outputs/disp32 -7313 } -7314 # return false -7315 b8/copy-to-eax 0/imm32/false -7316 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7317 } -7318 # if (curr2 == 0) return false -7319 { -7320 81 7/subop/compare %edi 0/imm32 -7321 75/jump-if-!= break/disp8 -7322 $mu-stmt-matches-primitive?:prim-inout-is-null: -7323 b8/copy-to-eax 0/imm32/false -7324 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7325 } -7326 # if (curr != curr2) return false -7327 { -7328 (operand-matches-primitive? *esi *edi) # => eax -7329 3d/compare-eax-and 0/imm32/false -7330 75/jump-if-!= break/disp8 -7331 b8/copy-to-eax 0/imm32/false -7332 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7333 } -7334 # curr=curr->next -7335 8b/-> *(esi+4) 6/r32/esi # Operand-next -7336 # curr2=curr2->next -7337 8b/-> *(edi+4) 7/r32/edi # Operand-next -7338 eb/jump loop/disp8 -7339 } -7340 $mu-stmt-matches-primitive?:check-outputs: -7341 # for (curr/esi in stmt->outputs, curr2/edi in primitive->outputs) -7342 8b/-> *(ecx+0xc) 6/r32/esi # Stmt1-outputs -7343 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs -7344 { -7345 # if (curr == 0) return (curr2 == 0) -7346 { -7347 $mu-stmt-matches-primitive?:check-output: -7348 81 7/subop/compare %esi 0/imm32 -7349 75/jump-if-!= break/disp8 -7350 { -7351 81 7/subop/compare %edi 0/imm32 -7352 75/jump-if-!= break/disp8 -7353 # return true -7354 b8/copy-to-eax 1/imm32 -7355 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7356 } -7357 # return false -7358 b8/copy-to-eax 0/imm32 -7359 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7360 } -7361 # if (curr2 == 0) return false -7362 { -7363 81 7/subop/compare %edi 0/imm32 -7364 75/jump-if-!= break/disp8 -7365 b8/copy-to-eax 0/imm32 -7366 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7367 } -7368 # if (curr != curr2) return false -7369 { -7370 (operand-matches-primitive? *esi *edi) # List-value List-value => eax -7371 3d/compare-eax-and 0/imm32/false -7372 75/jump-if-!= break/disp8 -7373 b8/copy-to-eax 0/imm32 -7374 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7375 } -7376 # curr=curr->next -7377 8b/-> *(esi+4) 6/r32/esi # Operand-next -7378 # curr2=curr2->next -7379 8b/-> *(edi+4) 7/r32/edi # Operand-next -7380 eb/jump loop/disp8 -7381 } -7382 $mu-stmt-matches-primitive?:return-true: -7383 b8/copy-to-eax 1/imm32 -7384 $mu-stmt-matches-primitive?:end: -7385 # . restore registers -7386 5f/pop-to-edi -7387 5e/pop-to-esi -7388 5b/pop-to-ebx -7389 5a/pop-to-edx -7390 59/pop-to-ecx -7391 # . epilogue -7392 89/<- %esp 5/r32/ebp -7393 5d/pop-to-ebp -7394 c3/return -7395 -7396 operand-matches-primitive?: # var: (handle var), prim-var: (handle var) -> result/eax: boolean -7397 # . prologue -7398 55/push-ebp -7399 89/<- %ebp 4/r32/esp -7400 # . save registers -7401 56/push-esi -7402 57/push-edi -7403 # esi = var -7404 8b/-> *(ebp+8) 6/r32/esi -7405 # edi = prim-var -7406 8b/-> *(ebp+0xc) 7/r32/edi -7407 # if (var->type != prim-var->type) return false -7408 (subx-type-equal? *(esi+4) *(edi+4)) # Var-type, Var-type => eax -7409 3d/compare-eax-and 0/imm32/false -7410 b8/copy-to-eax 0/imm32/false -7411 74/jump-if-= $operand-matches-primitive?:end/disp8 -7412 # return false if var->register doesn't match prim-var->register -7413 { -7414 # if addresses are equal, don't return here -7415 8b/-> *(esi+0x10) 0/r32/eax -7416 39/compare *(edi+0x10) 0/r32/eax -7417 74/jump-if-= break/disp8 -7418 # if either address is 0, return false -7419 3d/compare-eax-and 0/imm32 -7420 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result -7421 81 7/subop/compare *(edi+0x10) 0/imm32 -7422 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result -7423 # if prim-var->register is "*", return true -7424 (string-equal? *(edi+0x10) "*") # Var-register -7425 3d/compare-eax-and 0/imm32/false -7426 b8/copy-to-eax 1/imm32/true -7427 75/jump-if-!= $operand-matches-primitive?:end/disp8 -7428 # if string contents don't match, return false -7429 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register -7430 3d/compare-eax-and 0/imm32/false -7431 b8/copy-to-eax 0/imm32/false -7432 74/jump-if-= $operand-matches-primitive?:end/disp8 -7433 } -7434 # return true -7435 b8/copy-to-eax 1/imm32/true -7436 $operand-matches-primitive?:end: -7437 # . restore registers -7438 5f/pop-to-edi -7439 5e/pop-to-esi -7440 # . epilogue -7441 89/<- %esp 5/r32/ebp -7442 5d/pop-to-ebp -7443 c3/return -7444 -7445 subx-type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean -7446 # . prologue -7447 55/push-ebp -7448 89/<- %ebp 4/r32/esp -7449 # . save registers -7450 51/push-ecx -7451 # var alit/ecx: boolean = is-literal-type?(a) -7452 (is-literal-type? *(ebp+8)) # => eax -7453 89/<- %ecx 0/r32/eax -7454 # var blit/eax: boolean = is-literal-type?(b) -7455 (is-literal-type? *(ebp+0xc)) # => eax -7456 # return alit == blit -7457 39/compare %eax 1/r32/ecx -7458 74/jump-if-= $subx-type-equal?:true/disp8 -7459 $subx-type-equal?:false: -7460 b8/copy-to-eax 0/imm32/false -7461 eb/jump $subx-type-equal?:end/disp8 -7462 $subx-type-equal?:true: -7463 b8/copy-to-eax 1/imm32/true -7464 $subx-type-equal?:end: -7465 # . restore registers -7466 59/pop-to-ecx -7467 # . epilogue -7468 89/<- %esp 5/r32/ebp -7469 5d/pop-to-ebp -7470 c3/return -7471 -7472 is-literal-type?: # a: (handle tree type-id) -> result/eax: boolean -7473 # . prologue -7474 55/push-ebp -7475 89/<- %ebp 4/r32/esp -7476 # -7477 8b/-> *(ebp+8) 0/r32/eax -7478 8b/-> *eax 0/r32/eax # Atom-value -7479 3d/compare-eax-and 0/imm32/false -7480 74/jump-if-equal $is-literal-type?:end/disp8 -7481 b8/copy-to-eax 1/imm32/true -7482 $is-literal-type?:end: -7483 # . epilogue -7484 89/<- %esp 5/r32/ebp -7485 5d/pop-to-ebp -7486 c3/return -7487 -7488 test-emit-subx-statement-primitive: -7489 # Primitive operation on a variable on the stack. -7490 # increment foo -7491 # => -7492 # ff 0/subop/increment *(ebp-8) -7493 # -7494 # There's a variable on the var stack as follows: -7495 # name: 'foo' -7496 # type: int -7497 # stack-offset: -8 -7498 # -7499 # There's a primitive with this info: -7500 # name: 'increment' -7501 # inouts: int/mem -7502 # value: 'ff 0/subop/increment' -7503 # -7504 # There's nothing in functions. -7505 # -7506 # . prologue -7507 55/push-ebp -7508 89/<- %ebp 4/r32/esp -7509 # setup -7510 (clear-stream _test-output-stream) -7511 (clear-stream $_test-output-buffered-file->buffer) -7512 # var type/ecx: (handle tree type-id) = int -7513 68/push 0/imm32/right/null -7514 68/push 1/imm32/left/int -7515 89/<- %ecx 4/r32/esp -7516 # var var-foo/ecx: var -7517 68/push 0/imm32/no-register -7518 68/push -8/imm32/stack-offset -7519 68/push 1/imm32/block-depth -7520 51/push-ecx -7521 68/push "foo"/imm32 -7522 89/<- %ecx 4/r32/esp -7523 # var operand/ebx: (list var) -7524 68/push 0/imm32/next -7525 51/push-ecx/var-foo -7526 89/<- %ebx 4/r32/esp -7527 # var stmt/esi: statement -7528 68/push 0/imm32/next -7529 68/push 0/imm32/outputs -7530 53/push-ebx/operands -7531 68/push "increment"/imm32/operation -7532 68/push 1/imm32 -7533 89/<- %esi 4/r32/esp -7534 # var primitives/ebx: primitive -7535 68/push 0/imm32/next -7536 68/push 0/imm32/output-is-write-only -7537 68/push 0/imm32/no-disp32 -7538 68/push 0/imm32/no-imm32 -7539 68/push 0/imm32/no-r32 -7540 68/push 1/imm32/rm32-is-first-inout -7541 68/push "ff 0/subop/increment"/imm32/subx-name -7542 68/push 0/imm32/outputs -7543 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call -7544 68/push "increment"/imm32/name -7545 89/<- %ebx 4/r32/esp -7546 # convert -7547 c7 0/subop/copy *Curr-block-depth 0/imm32 -7548 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -7549 (flush _test-output-buffered-file) -7550 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -7556 # check output -7557 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-statement-primitive") -7558 # . epilogue -7559 89/<- %esp 5/r32/ebp -7560 5d/pop-to-ebp -7561 c3/return -7562 -7563 test-emit-subx-statement-primitive-register: -7564 # Primitive operation on a variable in a register. -7565 # foo <- increment -7566 # => -7567 # ff 0/subop/increment %eax # sub-optimal, but should suffice -7568 # -7569 # There's a variable on the var stack as follows: -7570 # name: 'foo' -7571 # type: int -7572 # register: 'eax' -7573 # -7574 # There's a primitive with this info: -7575 # name: 'increment' -7576 # out: int/reg -7577 # value: 'ff 0/subop/increment' -7578 # -7579 # There's nothing in functions. -7580 # -7581 # . prologue -7582 55/push-ebp -7583 89/<- %ebp 4/r32/esp -7584 # setup -7585 (clear-stream _test-output-stream) -7586 (clear-stream $_test-output-buffered-file->buffer) -7587 # var type/ecx: (handle tree type-id) = int -7588 68/push 0/imm32/right/null -7589 68/push 1/imm32/left/int -7590 89/<- %ecx 4/r32/esp -7591 # var var-foo/ecx: var in eax -7592 68/push "eax"/imm32/register -7593 68/push 0/imm32/no-stack-offset -7594 68/push 1/imm32/block-depth -7595 51/push-ecx -7596 68/push "foo"/imm32 -7597 89/<- %ecx 4/r32/esp -7598 # var operand/ebx: (list var) -7599 68/push 0/imm32/next -7600 51/push-ecx/var-foo -7601 89/<- %ebx 4/r32/esp -7602 # var stmt/esi: statement -7603 68/push 0/imm32/next -7604 53/push-ebx/outputs -7605 68/push 0/imm32/inouts -7606 68/push "increment"/imm32/operation -7607 68/push 1/imm32 -7608 89/<- %esi 4/r32/esp -7609 # var formal-var/ebx: var in any register -7610 68/push Any-register/imm32 -7611 68/push 0/imm32/no-stack-offset -7612 68/push 1/imm32/block-depth -7613 ff 6/subop/push *(ecx+4) # Var-type -7614 68/push "dummy"/imm32 -7615 89/<- %ebx 4/r32/esp -7616 # var operand/ebx: (list var) -7617 68/push 0/imm32/next -7618 53/push-ebx/formal-var -7619 89/<- %ebx 4/r32/esp -7620 # var primitives/ebx: primitive -7621 68/push 0/imm32/next -7622 68/push 0/imm32/output-is-write-only -7623 68/push 0/imm32/no-disp32 -7624 68/push 0/imm32/no-imm32 -7625 68/push 0/imm32/no-r32 -7626 68/push 3/imm32/rm32-in-first-output -7627 68/push "ff 0/subop/increment"/imm32/subx-name -7628 53/push-ebx/outputs -7629 68/push 0/imm32/inouts -7630 68/push "increment"/imm32/name -7631 89/<- %ebx 4/r32/esp -7632 # convert -7633 c7 0/subop/copy *Curr-block-depth 0/imm32 -7634 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -7635 (flush _test-output-buffered-file) -7636 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -7642 # check output -7643 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-primitive-register") -7644 # . epilogue -7645 89/<- %esp 5/r32/ebp -7646 5d/pop-to-ebp -7647 c3/return -7648 -7649 test-emit-subx-statement-select-primitive: -7650 # Select the right primitive between overloads. -7651 # foo <- increment -7652 # => -7653 # ff 0/subop/increment %eax # sub-optimal, but should suffice -7654 # -7655 # There's a variable on the var stack as follows: -7656 # name: 'foo' -7657 # type: int -7658 # register: 'eax' -7659 # -7660 # There's two primitives, as follows: -7661 # - name: 'increment' -7662 # out: int/reg -7663 # value: 'ff 0/subop/increment' -7664 # - name: 'increment' -7665 # inout: int/mem -7666 # value: 'ff 0/subop/increment' -7667 # -7668 # There's nothing in functions. -7669 # -7670 # . prologue -7671 55/push-ebp -7672 89/<- %ebp 4/r32/esp -7673 # setup -7674 (clear-stream _test-output-stream) -7675 (clear-stream $_test-output-buffered-file->buffer) -7676 # var type/ecx: (handle tree type-id) = int -7677 68/push 0/imm32/right/null -7678 68/push 1/imm32/left/int -7679 89/<- %ecx 4/r32/esp -7680 # var var-foo/ecx: var in eax -7681 68/push "eax"/imm32/register -7682 68/push 0/imm32/no-stack-offset -7683 68/push 1/imm32/block-depth -7684 51/push-ecx -7685 68/push "foo"/imm32 -7686 89/<- %ecx 4/r32/esp -7687 # var real-outputs/edi: (list var) -7688 68/push 0/imm32/next -7689 51/push-ecx/var-foo -7690 89/<- %edi 4/r32/esp -7691 # var stmt/esi: statement -7692 68/push 0/imm32/next -7693 57/push-edi/outputs -7694 68/push 0/imm32/inouts -7695 68/push "increment"/imm32/operation -7696 68/push 1/imm32 -7697 89/<- %esi 4/r32/esp -7698 # var formal-var/ebx: var in any register -7699 68/push Any-register/imm32 -7700 68/push 0/imm32/no-stack-offset -7701 68/push 1/imm32/block-depth -7702 ff 6/subop/push *(ecx+4) # Var-type -7703 68/push "dummy"/imm32 -7704 89/<- %ebx 4/r32/esp -7705 # var formal-outputs/ebx: (list var) = {formal-var, 0} -7706 68/push 0/imm32/next -7707 53/push-ebx/formal-var -7708 89/<- %ebx 4/r32/esp -7709 # var primitive1/ebx: primitive -7710 68/push 0/imm32/next -7711 68/push 0/imm32/output-is-write-only -7712 68/push 0/imm32/no-disp32 -7713 68/push 0/imm32/no-imm32 -7714 68/push 0/imm32/no-r32 -7715 68/push 3/imm32/rm32-in-first-output -7716 68/push "ff 0/subop/increment"/imm32/subx-name -7717 53/push-ebx/outputs/formal-outputs -7718 68/push 0/imm32/inouts -7719 68/push "increment"/imm32/name -7720 89/<- %ebx 4/r32/esp -7721 # var primitives/ebx: primitive -7722 53/push-ebx/next -7723 68/push 0/imm32/output-is-write-only -7724 68/push 0/imm32/no-disp32 -7725 68/push 0/imm32/no-imm32 -7726 68/push 0/imm32/no-r32 -7727 68/push 1/imm32/rm32-is-first-inout -7728 68/push "ff 0/subop/increment"/imm32/subx-name -7729 68/push 0/imm32/outputs -7730 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -7731 68/push "increment"/imm32/name -7732 89/<- %ebx 4/r32/esp -7733 # convert -7734 c7 0/subop/copy *Curr-block-depth 0/imm32 -7735 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -7736 (flush _test-output-buffered-file) -7737 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -7743 # check output -7744 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive") -7745 # . epilogue -7746 89/<- %esp 5/r32/ebp -7747 5d/pop-to-ebp -7748 c3/return -7749 -7750 test-emit-subx-statement-select-primitive-2: -7751 # Select the right primitive between overloads. -7752 # foo <- increment -7753 # => -7754 # ff 0/subop/increment %eax # sub-optimal, but should suffice -7755 # -7756 # There's a variable on the var stack as follows: -7757 # name: 'foo' -7758 # type: int -7759 # register: 'eax' -7760 # -7761 # There's two primitives, as follows: -7762 # - name: 'increment' -7763 # out: int/reg -7764 # value: 'ff 0/subop/increment' -7765 # - name: 'increment' -7766 # inout: int/mem -7767 # value: 'ff 0/subop/increment' -7768 # -7769 # There's nothing in functions. -7770 # -7771 # . prologue -7772 55/push-ebp -7773 89/<- %ebp 4/r32/esp -7774 # setup -7775 (clear-stream _test-output-stream) -7776 (clear-stream $_test-output-buffered-file->buffer) -7777 # var type/ecx: (handle tree type-id) = int -7778 68/push 0/imm32/right/null -7779 68/push 1/imm32/left/int -7780 89/<- %ecx 4/r32/esp -7781 # var var-foo/ecx: var in eax -7782 68/push "eax"/imm32/register -7783 68/push 0/imm32/no-stack-offset -7784 68/push 1/imm32/block-depth -7785 51/push-ecx -7786 68/push "foo"/imm32 -7787 89/<- %ecx 4/r32/esp -7788 # var inouts/edi: (list var) -7789 68/push 0/imm32/next -7790 51/push-ecx/var-foo -7791 89/<- %edi 4/r32/esp -7792 # var stmt/esi: statement -7793 68/push 0/imm32/next -7794 68/push 0/imm32/outputs -7795 57/push-edi/inouts -7796 68/push "increment"/imm32/operation -7797 68/push 1/imm32 -7798 89/<- %esi 4/r32/esp -7799 # var formal-var/ebx: var in any register -7800 68/push Any-register/imm32 -7801 68/push 0/imm32/no-stack-offset -7802 68/push 1/imm32/block-depth -7803 ff 6/subop/push *(ecx+4) # Var-type -7804 68/push "dummy"/imm32 -7805 89/<- %ebx 4/r32/esp -7806 # var operand/ebx: (list var) -7807 68/push 0/imm32/next -7808 53/push-ebx/formal-var -7809 89/<- %ebx 4/r32/esp -7810 # var primitive1/ebx: primitive -7811 68/push 0/imm32/next -7812 68/push 0/imm32/output-is-write-only -7813 68/push 0/imm32/no-disp32 -7814 68/push 0/imm32/no-imm32 -7815 68/push 0/imm32/no-r32 -7816 68/push 3/imm32/rm32-in-first-output -7817 68/push "ff 0/subop/increment"/imm32/subx-name -7818 53/push-ebx/outputs/formal-outputs -7819 68/push 0/imm32/inouts -7820 68/push "increment"/imm32/name -7821 89/<- %ebx 4/r32/esp -7822 # var primitives/ebx: primitive -7823 53/push-ebx/next -7824 68/push 0/imm32/output-is-write-only -7825 68/push 0/imm32/no-disp32 -7826 68/push 0/imm32/no-imm32 -7827 68/push 0/imm32/no-r32 -7828 68/push 1/imm32/rm32-is-first-inout -7829 68/push "ff 0/subop/increment"/imm32/subx-name -7830 68/push 0/imm32/outputs -7831 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -7832 68/push "increment"/imm32/name -7833 89/<- %ebx 4/r32/esp -7834 # convert -7835 c7 0/subop/copy *Curr-block-depth 0/imm32 -7836 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -7837 (flush _test-output-buffered-file) -7838 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -7844 # check output -7845 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2") -7846 # . epilogue -7847 89/<- %esp 5/r32/ebp -7848 5d/pop-to-ebp -7849 c3/return -7850 -7851 test-increment-register: -7852 # Select the right register between overloads. -7853 # foo <- increment -7854 # => -7855 # 50/increment-eax -7856 # -7857 # There's a variable on the var stack as follows: -7858 # name: 'foo' -7859 # type: int -7860 # register: 'eax' -7861 # -7862 # Primitives are the global definitions. -7863 # -7864 # There are no functions defined. -7865 # -7866 # . prologue -7867 55/push-ebp -7868 89/<- %ebp 4/r32/esp -7869 # setup -7870 (clear-stream _test-output-stream) -7871 (clear-stream $_test-output-buffered-file->buffer) -7872 # var type/ecx: (handle tree type-id) = int -7873 68/push 0/imm32/right/null -7874 68/push 1/imm32/left/int -7875 89/<- %ecx 4/r32/esp -7876 # var var-foo/ecx: var in eax -7877 68/push "eax"/imm32/register -7878 68/push 0/imm32/no-stack-offset -7879 68/push 1/imm32/block-depth -7880 51/push-ecx -7881 68/push "foo"/imm32 -7882 89/<- %ecx 4/r32/esp -7883 # var real-outputs/edi: (list var) -7884 68/push 0/imm32/next -7885 51/push-ecx/var-foo -7886 89/<- %edi 4/r32/esp -7887 # var stmt/esi: statement -7888 68/push 0/imm32/next -7889 57/push-edi/outputs -7890 68/push 0/imm32/inouts -7891 68/push "increment"/imm32/operation -7892 68/push 1/imm32/regular-statement -7893 89/<- %esi 4/r32/esp -7894 # convert -7895 c7 0/subop/copy *Curr-block-depth 0/imm32 -7896 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7897 (flush _test-output-buffered-file) -7898 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -7904 # check output -7905 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") -7906 # . epilogue -7907 89/<- %esp 5/r32/ebp -7908 5d/pop-to-ebp -7909 c3/return -7910 -7911 test-increment-var: -7912 # Select the right primitive between overloads. -7913 # foo <- increment -7914 # => -7915 # ff 0/subop/increment %eax # sub-optimal, but should suffice -7916 # -7917 # There's a variable on the var stack as follows: -7918 # name: 'foo' -7919 # type: int -7920 # register: 'eax' -7921 # -7922 # Primitives are the global definitions. -7923 # -7924 # There are no functions defined. -7925 # -7926 # . prologue -7927 55/push-ebp -7928 89/<- %ebp 4/r32/esp -7929 # setup -7930 (clear-stream _test-output-stream) -7931 (clear-stream $_test-output-buffered-file->buffer) -7932 # var type/ecx: (handle tree type-id) = int -7933 68/push 0/imm32/right/null -7934 68/push 1/imm32/left/int -7935 89/<- %ecx 4/r32/esp -7936 # var var-foo/ecx: var in eax -7937 68/push "eax"/imm32/register -7938 68/push 0/imm32/no-stack-offset -7939 68/push 1/imm32/block-depth -7940 51/push-ecx -7941 68/push "foo"/imm32 -7942 89/<- %ecx 4/r32/esp -7943 # var inouts/edi: (list var) -7944 68/push 0/imm32/next -7945 51/push-ecx/var-foo -7946 89/<- %edi 4/r32/esp -7947 # var stmt/esi: statement -7948 68/push 0/imm32/next -7949 68/push 0/imm32/outputs -7950 57/push-edi/inouts -7951 68/push "increment"/imm32/operation -7952 68/push 1/imm32 -7953 89/<- %esi 4/r32/esp -7954 # convert -7955 c7 0/subop/copy *Curr-block-depth 0/imm32 -7956 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -7957 (flush _test-output-buffered-file) -7958 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -7964 # check output -7965 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-increment-var") -7966 # . epilogue -7967 89/<- %esp 5/r32/ebp -7968 5d/pop-to-ebp -7969 c3/return -7970 -7971 test-add-reg-to-reg: -7972 # var1/reg <- add var2/reg -7973 # => -7974 # 01/add %var1 var2 -7975 # -7976 # . prologue -7977 55/push-ebp -7978 89/<- %ebp 4/r32/esp -7979 # setup -7980 (clear-stream _test-output-stream) -7981 (clear-stream $_test-output-buffered-file->buffer) -7982 # var type/ecx: (handle tree type-id) = int -7983 68/push 0/imm32/right/null -7984 68/push 1/imm32/left/int -7985 89/<- %ecx 4/r32/esp -7986 # var var-var1/ecx: var in eax -7987 68/push "eax"/imm32/register -7988 68/push 0/imm32/no-stack-offset -7989 68/push 1/imm32/block-depth -7990 51/push-ecx -7991 68/push "var1"/imm32 -7992 89/<- %ecx 4/r32/esp -7993 # var var-var2/edx: var in ecx -7994 68/push "ecx"/imm32/register -7995 68/push 0/imm32/no-stack-offset -7996 68/push 1/imm32/block-depth -7997 ff 6/subop/push *(ecx+4) # Var-type -7998 68/push "var2"/imm32 -7999 89/<- %edx 4/r32/esp -8000 # var inouts/esi: (list var2) -8001 68/push 0/imm32/next -8002 52/push-edx/var-var2 -8003 89/<- %esi 4/r32/esp -8004 # var outputs/edi: (list var1) -8005 68/push 0/imm32/next -8006 51/push-ecx/var-var1 -8007 89/<- %edi 4/r32/esp -8008 # var stmt/esi: statement -8009 68/push 0/imm32/next -8010 57/push-edi/outputs -8011 56/push-esi/inouts -8012 68/push "add"/imm32/operation -8013 68/push 1/imm32 -8014 89/<- %esi 4/r32/esp -8015 # convert -8016 c7 0/subop/copy *Curr-block-depth 0/imm32 -8017 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8018 (flush _test-output-buffered-file) -8019 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8025 # check output -8026 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") -8027 # . epilogue -8028 89/<- %esp 5/r32/ebp -8029 5d/pop-to-ebp -8030 c3/return -8031 -8032 test-add-reg-to-mem: -8033 # add-to var1 var2/reg -8034 # => -8035 # 01/add *(ebp+__) var2 -8036 # -8037 # . prologue -8038 55/push-ebp -8039 89/<- %ebp 4/r32/esp -8040 # setup -8041 (clear-stream _test-output-stream) -8042 (clear-stream $_test-output-buffered-file->buffer) -8043 # var type/ecx: (handle tree type-id) = int -8044 68/push 0/imm32/right/null -8045 68/push 1/imm32/left/int -8046 89/<- %ecx 4/r32/esp -8047 # var var-var1/ecx: var -8048 68/push 0/imm32/no-register -8049 68/push 8/imm32/stack-offset -8050 68/push 1/imm32/block-depth -8051 51/push-ecx -8052 68/push "var1"/imm32 -8053 89/<- %ecx 4/r32/esp -8054 # var var-var2/edx: var in ecx -8055 68/push "ecx"/imm32/register -8056 68/push 0/imm32/no-stack-offset -8057 68/push 1/imm32/block-depth -8058 ff 6/subop/push *(ecx+4) # Var-type -8059 68/push "var2"/imm32 -8060 89/<- %edx 4/r32/esp -8061 # var inouts/esi: (list var2) -8062 68/push 0/imm32/next -8063 52/push-edx/var-var2 -8064 89/<- %esi 4/r32/esp -8065 # var inouts = (list var1 var2) -8066 56/push-esi/next -8067 51/push-ecx/var-var1 -8068 89/<- %esi 4/r32/esp -8069 # var stmt/esi: statement -8070 68/push 0/imm32/next -8071 68/push 0/imm32/outputs -8072 56/push-esi/inouts -8073 68/push "add-to"/imm32/operation -8074 68/push 1/imm32 -8075 89/<- %esi 4/r32/esp -8076 # convert -8077 c7 0/subop/copy *Curr-block-depth 0/imm32 -8078 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8079 (flush _test-output-buffered-file) -8080 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8086 # check output -8087 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") -8088 # . epilogue -8089 89/<- %esp 5/r32/ebp -8090 5d/pop-to-ebp -8091 c3/return -8092 -8093 test-add-mem-to-reg: -8094 # var1/reg <- add var2 -8095 # => -8096 # 03/add *(ebp+__) var1 -8097 # -8098 # . prologue -8099 55/push-ebp -8100 89/<- %ebp 4/r32/esp -8101 # setup -8102 (clear-stream _test-output-stream) -8103 (clear-stream $_test-output-buffered-file->buffer) -8104 # var type/ecx: (handle tree type-id) = int -8105 68/push 0/imm32/right/null -8106 68/push 1/imm32/left/int -8107 89/<- %ecx 4/r32/esp -8108 # var var-var1/ecx: var in eax -8109 68/push "eax"/imm32/register -8110 68/push 0/imm32/no-stack-offset -8111 68/push 1/imm32/block-depth -8112 51/push-ecx -8113 68/push "var1"/imm32 -8114 89/<- %ecx 4/r32/esp -8115 # var var-var2/edx: var -8116 68/push 0/imm32/no-register -8117 68/push 8/imm32/stack-offset -8118 68/push 1/imm32/block-depth -8119 ff 6/subop/push *(ecx+4) # Var-type -8120 68/push "var2"/imm32 -8121 89/<- %edx 4/r32/esp -8122 # var inouts/esi: (list var2) -8123 68/push 0/imm32/next -8124 52/push-edx/var-var2 -8125 89/<- %esi 4/r32/esp -8126 # var outputs/edi: (list var1) -8127 68/push 0/imm32/next -8128 51/push-ecx/var-var1 -8129 89/<- %edi 4/r32/esp -8130 # var stmt/esi: statement -8131 68/push 0/imm32/next -8132 57/push-edi/outputs -8133 56/push-esi/inouts -8134 68/push "add"/imm32/operation -8135 68/push 1/imm32 -8136 89/<- %esi 4/r32/esp -8137 # convert -8138 c7 0/subop/copy *Curr-block-depth 0/imm32 -8139 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8140 (flush _test-output-buffered-file) -8141 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8147 # check output -8148 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") -8149 # . epilogue -8150 89/<- %esp 5/r32/ebp -8151 5d/pop-to-ebp -8152 c3/return -8153 -8154 test-add-literal-to-eax: -8155 # var1/eax <- add 0x34 -8156 # => -8157 # 05/add-to-eax 0x34/imm32 -8158 # -8159 # . prologue -8160 55/push-ebp -8161 89/<- %ebp 4/r32/esp -8162 # setup -8163 (clear-stream _test-output-stream) -8164 (clear-stream $_test-output-buffered-file->buffer) -8165 # var type/ecx: (handle tree type-id) = int -8166 68/push 0/imm32/right/null -8167 68/push 1/imm32/left/int -8168 89/<- %ecx 4/r32/esp -8169 # var var-var1/ecx: var in eax -8170 68/push "eax"/imm32/register -8171 68/push 0/imm32/no-stack-offset -8172 68/push 1/imm32/block-depth -8173 51/push-ecx -8174 68/push "var1"/imm32 -8175 89/<- %ecx 4/r32/esp -8176 # var type/edx: (handle tree type-id) = literal -8177 68/push 0/imm32/right/null -8178 68/push 0/imm32/left/literal -8179 89/<- %edx 4/r32/esp -8180 # var var-var2/edx: var literal -8181 68/push 0/imm32/no-register -8182 68/push 0/imm32/no-stack-offset -8183 68/push 1/imm32/block-depth -8184 52/push-edx -8185 68/push "0x34"/imm32 -8186 89/<- %edx 4/r32/esp -8187 # var inouts/esi: (list var2) +7295 $emit-subx-var-as-rm32:register-direct: +7296 (write-buffered *(ebp+8) " %") +7297 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register +7298 } +7299 # else if (operand->stack-offset) emit "*(ebp+__)" +7300 { +7301 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-stack-offset +7302 74/jump-if-= break/disp8 +7303 $emit-subx-var-as-rm32:stack: +7304 (write-buffered *(ebp+8) Space) +7305 (write-buffered *(ebp+8) "*(ebp+") +7306 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-stack-offset +7307 (write-buffered *(ebp+8) ")") +7308 } +7309 $emit-subx-var-as-rm32:end: +7310 # . restore registers +7311 5e/pop-to-esi +7312 59/pop-to-ecx +7313 58/pop-to-eax +7314 # . epilogue +7315 89/<- %esp 5/r32/ebp +7316 5d/pop-to-ebp +7317 c3/return +7318 +7319 find-matching-function: # functions: (addr function), stmt: (handle statement) -> result/eax: (handle function) +7320 # . prologue +7321 55/push-ebp +7322 89/<- %ebp 4/r32/esp +7323 # . save registers +7324 51/push-ecx +7325 # var curr/ecx: (handle function) = functions +7326 8b/-> *(ebp+8) 1/r32/ecx +7327 { +7328 # if (curr == null) break +7329 81 7/subop/compare %ecx 0/imm32 +7330 74/jump-if-= break/disp8 +7331 # if match(stmt, curr) return curr +7332 { +7333 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax +7334 3d/compare-eax-and 0/imm32/false +7335 74/jump-if-= break/disp8 +7336 89/<- %eax 1/r32/ecx +7337 eb/jump $find-matching-function:end/disp8 +7338 } +7339 # curr = curr->next +7340 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next +7341 eb/jump loop/disp8 +7342 } +7343 # return null +7344 b8/copy-to-eax 0/imm32 +7345 $find-matching-function:end: +7346 # . restore registers +7347 59/pop-to-ecx +7348 # . epilogue +7349 89/<- %esp 5/r32/ebp +7350 5d/pop-to-ebp +7351 c3/return +7352 +7353 find-matching-primitive: # primitives: (handle primitive), stmt: (handle statement) -> result/eax: (handle primitive) +7354 # . prologue +7355 55/push-ebp +7356 89/<- %ebp 4/r32/esp +7357 # . save registers +7358 51/push-ecx +7359 # var curr/ecx: (handle primitive) = primitives +7360 8b/-> *(ebp+8) 1/r32/ecx +7361 { +7362 $find-matching-primitive:loop: +7363 # if (curr == null) break +7364 81 7/subop/compare %ecx 0/imm32 +7365 0f 84/jump-if-= break/disp32 +7366 #? (write-buffered Stderr "prim: ") +7367 #? (write-buffered Stderr *ecx) # Primitive-name +7368 #? (write-buffered Stderr " => ") +7369 #? (write-buffered Stderr *(ecx+0xc)) # Primitive-subx-name +7370 #? (write-buffered Stderr Newline) +7371 #? (flush Stderr) +7372 # if match(curr, stmt) return curr +7373 { +7374 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax +7375 3d/compare-eax-and 0/imm32/false +7376 74/jump-if-= break/disp8 +7377 89/<- %eax 1/r32/ecx +7378 eb/jump $find-matching-primitive:end/disp8 +7379 } +7380 $find-matching-primitive:next-primitive: +7381 # curr = curr->next +7382 8b/-> *(ecx+0x24) 1/r32/ecx # Primitive-next +7383 e9/jump loop/disp32 +7384 } +7385 # return null +7386 b8/copy-to-eax 0/imm32 +7387 $find-matching-primitive:end: +7388 # . restore registers +7389 59/pop-to-ecx +7390 # . epilogue +7391 89/<- %esp 5/r32/ebp +7392 5d/pop-to-ebp +7393 c3/return +7394 +7395 mu-stmt-matches-function?: # stmt: (handle statement), function: (handle function) -> result/eax: boolean +7396 # . prologue +7397 55/push-ebp +7398 89/<- %ebp 4/r32/esp +7399 # . save registers +7400 51/push-ecx +7401 # return function->name == stmt->operation +7402 8b/-> *(ebp+8) 1/r32/ecx +7403 8b/-> *(ebp+0xc) 0/r32/eax +7404 (string-equal? *(ecx+4) *eax) # Stmt1-operation, Function-name => eax +7405 $mu-stmt-matches-function?:end: +7406 # . restore registers +7407 59/pop-to-ecx +7408 # . epilogue +7409 89/<- %esp 5/r32/ebp +7410 5d/pop-to-ebp +7411 c3/return +7412 +7413 mu-stmt-matches-primitive?: # stmt: (handle statement), primitive: (handle primitive) -> result/eax: boolean +7414 # A mu stmt matches a primitive if the name matches, all the inout vars +7415 # match, and all the output vars match. +7416 # Vars match if types match and registers match. +7417 # In addition, a stmt output matches a primitive's output if types match +7418 # and the primitive has a wildcard register. +7419 # . prologue +7420 55/push-ebp +7421 89/<- %ebp 4/r32/esp +7422 # . save registers +7423 51/push-ecx +7424 52/push-edx +7425 53/push-ebx +7426 56/push-esi +7427 57/push-edi +7428 # ecx = stmt +7429 8b/-> *(ebp+8) 1/r32/ecx +7430 # edx = primitive +7431 8b/-> *(ebp+0xc) 2/r32/edx +7432 { +7433 $mu-stmt-matches-primitive?:check-name: +7434 # if (primitive->name != stmt->operation) return false +7435 (string-equal? *(ecx+4) *edx) # Stmt1-operation, Primitive-name => eax +7436 3d/compare-eax-and 0/imm32/false +7437 75/jump-if-!= break/disp8 +7438 b8/copy-to-eax 0/imm32 +7439 e9/jump $mu-stmt-matches-primitive?:end/disp32 +7440 } +7441 $mu-stmt-matches-primitive?:check-inouts: +7442 # for (curr/esi in stmt->inouts, curr2/edi in primitive->inouts) +7443 8b/-> *(ecx+8) 6/r32/esi # Stmt1-inouts or Regvardef-inouts +7444 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts +7445 { +7446 # if (curr == 0 && curr2 == 0) move on to check outputs +7447 { +7448 81 7/subop/compare %esi 0/imm32 +7449 75/jump-if-!= break/disp8 +7450 $mu-stmt-matches-primitive?:stmt-inout-is-null: +7451 { +7452 81 7/subop/compare %edi 0/imm32 +7453 75/jump-if-!= break/disp8 +7454 # +7455 e9/jump $mu-stmt-matches-primitive?:check-outputs/disp32 +7456 } +7457 # return false +7458 b8/copy-to-eax 0/imm32/false +7459 e9/jump $mu-stmt-matches-primitive?:end/disp32 +7460 } +7461 # if (curr2 == 0) return false +7462 { +7463 81 7/subop/compare %edi 0/imm32 +7464 75/jump-if-!= break/disp8 +7465 $mu-stmt-matches-primitive?:prim-inout-is-null: +7466 b8/copy-to-eax 0/imm32/false +7467 e9/jump $mu-stmt-matches-primitive?:end/disp32 +7468 } +7469 # if (curr != curr2) return false +7470 { +7471 (operand-matches-primitive? %esi *edi) # List-value => eax +7472 3d/compare-eax-and 0/imm32/false +7473 75/jump-if-!= break/disp8 +7474 b8/copy-to-eax 0/imm32/false +7475 e9/jump $mu-stmt-matches-primitive?:end/disp32 +7476 } +7477 # curr=curr->next +7478 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next +7479 # curr2=curr2->next +7480 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next +7481 eb/jump loop/disp8 +7482 } +7483 $mu-stmt-matches-primitive?:check-outputs: +7484 # for (curr/esi in stmt->outputs, curr2/edi in primitive->outputs) +7485 8b/-> *(ecx+0xc) 6/r32/esi # Stmt1-outputs +7486 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs +7487 { +7488 # if (curr == 0) return (curr2 == 0) +7489 { +7490 $mu-stmt-matches-primitive?:check-output: +7491 81 7/subop/compare %esi 0/imm32 +7492 75/jump-if-!= break/disp8 +7493 { +7494 81 7/subop/compare %edi 0/imm32 +7495 75/jump-if-!= break/disp8 +7496 # return true +7497 b8/copy-to-eax 1/imm32 +7498 e9/jump $mu-stmt-matches-primitive?:end/disp32 +7499 } +7500 # return false +7501 b8/copy-to-eax 0/imm32 +7502 e9/jump $mu-stmt-matches-primitive?:end/disp32 +7503 } +7504 # if (curr2 == 0) return false +7505 { +7506 81 7/subop/compare %edi 0/imm32 +7507 75/jump-if-!= break/disp8 +7508 b8/copy-to-eax 0/imm32 +7509 e9/jump $mu-stmt-matches-primitive?:end/disp32 +7510 } +7511 # if (curr != curr2) return false +7512 { +7513 (operand-matches-primitive? %esi *edi) # List-value => eax +7514 3d/compare-eax-and 0/imm32/false +7515 75/jump-if-!= break/disp8 +7516 b8/copy-to-eax 0/imm32 +7517 e9/jump $mu-stmt-matches-primitive?:end/disp32 +7518 } +7519 # curr=curr->next +7520 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next +7521 # curr2=curr2->next +7522 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next +7523 eb/jump loop/disp8 +7524 } +7525 $mu-stmt-matches-primitive?:return-true: +7526 b8/copy-to-eax 1/imm32 +7527 $mu-stmt-matches-primitive?:end: +7528 # . restore registers +7529 5f/pop-to-edi +7530 5e/pop-to-esi +7531 5b/pop-to-ebx +7532 5a/pop-to-edx +7533 59/pop-to-ecx +7534 # . epilogue +7535 89/<- %esp 5/r32/ebp +7536 5d/pop-to-ebp +7537 c3/return +7538 +7539 operand-matches-primitive?: # s: (handle stmt-var), prim-var: (handle var) -> result/eax: boolean +7540 # . prologue +7541 55/push-ebp +7542 89/<- %ebp 4/r32/esp +7543 # . save registers +7544 51/push-ecx +7545 56/push-esi +7546 57/push-edi +7547 # ecx = s +7548 8b/-> *(ebp+8) 1/r32/ecx +7549 # var var/esi : (handle var) = s->value +7550 8b/-> *ecx 6/r32/esi # Stmt-var-value +7551 # edi = prim-var +7552 8b/-> *(ebp+0xc) 7/r32/edi +7553 $operand-matches-primitive?:check-type: +7554 # if (var->type != prim-var->type) return false +7555 (subx-type-equal? *(esi+4) *(edi+4)) # Var-type, Var-type => eax +7556 3d/compare-eax-and 0/imm32/false +7557 b8/copy-to-eax 0/imm32/false +7558 0f 84/jump-if-= $operand-matches-primitive?:end/disp32 +7559 { +7560 $operand-matches-primitive?:check-register: +7561 # if prim-var is in memory and var is in register but dereference, match +7562 { +7563 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register +7564 0f 85/jump-if-!= break/disp32 +7565 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +7566 74/jump-if-= break/disp8 +7567 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +7568 74/jump-if-= break/disp8 +7569 e9/jump $operand-matches-primitive?:return-true/disp32 +7570 } +7571 # if prim-var is in register and var is in register but dereference, no match +7572 { +7573 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register +7574 0f 84/jump-if-= break/disp32 +7575 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +7576 0f 84/jump-if-= break/disp32 +7577 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +7578 74/jump-if-= break/disp8 +7579 e9/jump $operand-matches-primitive?:return-false/disp32 +7580 } +7581 # return false if var->register doesn't match prim-var->register +7582 { +7583 # if register addresses are equal, it's a match +7584 8b/-> *(esi+0x10) 0/r32/eax # Var-register +7585 39/compare *(edi+0x10) 0/r32/eax # Var-register +7586 74/jump-if-= break/disp8 +7587 # if either address is 0, return false +7588 3d/compare-eax-and 0/imm32 +7589 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result +7590 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register +7591 74/jump-if-= $operand-matches-primitive?:return-false/disp8 +7592 # if prim-var->register is wildcard, it's a match +7593 (string-equal? *(edi+0x10) Any-register) # Var-register => eax +7594 3d/compare-eax-and 0/imm32/false +7595 75/jump-if-!= break/disp8 +7596 # if string contents aren't equal, return false +7597 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register => eax +7598 3d/compare-eax-and 0/imm32/false +7599 74/jump-if-= $operand-matches-primitive?:return-false/disp8 +7600 } +7601 } +7602 $operand-matches-primitive?:return-true: +7603 b8/copy-to-eax 1/imm32/true +7604 eb/jump $operand-matches-primitive?:end/disp8 +7605 $operand-matches-primitive?:return-false: +7606 b8/copy-to-eax 0/imm32/false +7607 $operand-matches-primitive?:end: +7608 # . restore registers +7609 5f/pop-to-edi +7610 5e/pop-to-esi +7611 59/pop-to-ecx +7612 # . epilogue +7613 89/<- %esp 5/r32/ebp +7614 5d/pop-to-ebp +7615 c3/return +7616 +7617 subx-type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean +7618 # . prologue +7619 55/push-ebp +7620 89/<- %ebp 4/r32/esp +7621 # . save registers +7622 51/push-ecx +7623 # var alit/ecx: boolean = is-literal-type?(a) +7624 (is-literal-type? *(ebp+8)) # => eax +7625 89/<- %ecx 0/r32/eax +7626 # var blit/eax: boolean = is-literal-type?(b) +7627 (is-literal-type? *(ebp+0xc)) # => eax +7628 # return alit == blit +7629 39/compare %eax 1/r32/ecx +7630 74/jump-if-= $subx-type-equal?:true/disp8 +7631 $subx-type-equal?:false: +7632 b8/copy-to-eax 0/imm32/false +7633 eb/jump $subx-type-equal?:end/disp8 +7634 $subx-type-equal?:true: +7635 b8/copy-to-eax 1/imm32/true +7636 $subx-type-equal?:end: +7637 # . restore registers +7638 59/pop-to-ecx +7639 # . epilogue +7640 89/<- %esp 5/r32/ebp +7641 5d/pop-to-ebp +7642 c3/return +7643 +7644 is-literal-type?: # a: (handle tree type-id) -> result/eax: boolean +7645 # . prologue +7646 55/push-ebp +7647 89/<- %ebp 4/r32/esp +7648 # +7649 8b/-> *(ebp+8) 0/r32/eax +7650 8b/-> *eax 0/r32/eax # Atom-value +7651 3d/compare-eax-and 0/imm32/false +7652 74/jump-if-equal $is-literal-type?:end/disp8 +7653 b8/copy-to-eax 1/imm32/true +7654 $is-literal-type?:end: +7655 # . epilogue +7656 89/<- %esp 5/r32/ebp +7657 5d/pop-to-ebp +7658 c3/return +7659 +7660 test-emit-subx-statement-primitive: +7661 # Primitive operation on a variable on the stack. +7662 # increment foo +7663 # => +7664 # ff 0/subop/increment *(ebp-8) +7665 # +7666 # There's a variable on the var stack as follows: +7667 # name: 'foo' +7668 # type: int +7669 # stack-offset: -8 +7670 # +7671 # There's a primitive with this info: +7672 # name: 'increment' +7673 # inouts: int/mem +7674 # value: 'ff 0/subop/increment' +7675 # +7676 # There's nothing in functions. +7677 # +7678 # . prologue +7679 55/push-ebp +7680 89/<- %ebp 4/r32/esp +7681 # setup +7682 (clear-stream _test-output-stream) +7683 (clear-stream $_test-output-buffered-file->buffer) +7684 # var type/ecx: (handle tree type-id) = int +7685 68/push 0/imm32/right/null +7686 68/push 1/imm32/left/int +7687 89/<- %ecx 4/r32/esp +7688 # var var-foo/ecx: var +7689 68/push 0/imm32/no-register +7690 68/push -8/imm32/stack-offset +7691 68/push 1/imm32/block-depth +7692 51/push-ecx +7693 68/push "foo"/imm32 +7694 89/<- %ecx 4/r32/esp +7695 # var operand/ebx: (handle stmt-var) +7696 68/push 0/imm32/is-deref:false +7697 68/push 0/imm32/next +7698 51/push-ecx/var-foo +7699 89/<- %ebx 4/r32/esp +7700 # var stmt/esi: statement +7701 68/push 0/imm32/next +7702 68/push 0/imm32/outputs +7703 53/push-ebx/operands +7704 68/push "increment"/imm32/operation +7705 68/push 1/imm32 +7706 89/<- %esi 4/r32/esp +7707 # var primitives/ebx: primitive +7708 68/push 0/imm32/next +7709 68/push 0/imm32/output-is-write-only +7710 68/push 0/imm32/no-disp32 +7711 68/push 0/imm32/no-imm32 +7712 68/push 0/imm32/no-r32 +7713 68/push 1/imm32/rm32-is-first-inout +7714 68/push "ff 0/subop/increment"/imm32/subx-name +7715 68/push 0/imm32/outputs +7716 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call +7717 68/push "increment"/imm32/name +7718 89/<- %ebx 4/r32/esp +7719 # convert +7720 c7 0/subop/copy *Curr-block-depth 0/imm32 +7721 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) +7722 (flush _test-output-buffered-file) +7723 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +7729 # check output +7730 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-statement-primitive") +7731 # . epilogue +7732 89/<- %esp 5/r32/ebp +7733 5d/pop-to-ebp +7734 c3/return +7735 +7736 test-emit-subx-statement-primitive-register: +7737 # Primitive operation on a variable in a register. +7738 # foo <- increment +7739 # => +7740 # ff 0/subop/increment %eax # sub-optimal, but should suffice +7741 # +7742 # There's a variable on the var stack as follows: +7743 # name: 'foo' +7744 # type: int +7745 # register: 'eax' +7746 # +7747 # There's a primitive with this info: +7748 # name: 'increment' +7749 # out: int/reg +7750 # value: 'ff 0/subop/increment' +7751 # +7752 # There's nothing in functions. +7753 # +7754 # . prologue +7755 55/push-ebp +7756 89/<- %ebp 4/r32/esp +7757 # setup +7758 (clear-stream _test-output-stream) +7759 (clear-stream $_test-output-buffered-file->buffer) +7760 # var type/ecx: (handle tree type-id) = int +7761 68/push 0/imm32/right/null +7762 68/push 1/imm32/left/int +7763 89/<- %ecx 4/r32/esp +7764 # var var-foo/ecx: var in eax +7765 68/push "eax"/imm32/register +7766 68/push 0/imm32/no-stack-offset +7767 68/push 1/imm32/block-depth +7768 51/push-ecx +7769 68/push "foo"/imm32 +7770 89/<- %ecx 4/r32/esp +7771 # var operand/ebx: (handle stmt-var) +7772 68/push 0/imm32/is-deref:false +7773 68/push 0/imm32/next +7774 51/push-ecx/var-foo +7775 89/<- %ebx 4/r32/esp +7776 # var stmt/esi: statement +7777 68/push 0/imm32/next +7778 53/push-ebx/outputs +7779 68/push 0/imm32/inouts +7780 68/push "increment"/imm32/operation +7781 68/push 1/imm32 +7782 89/<- %esi 4/r32/esp +7783 # var formal-var/ebx: var in any register +7784 68/push Any-register/imm32 +7785 68/push 0/imm32/no-stack-offset +7786 68/push 1/imm32/block-depth +7787 ff 6/subop/push *(ecx+4) # Var-type +7788 68/push "dummy"/imm32 +7789 89/<- %ebx 4/r32/esp +7790 # var operand/ebx: (handle stmt-var) +7791 68/push 0/imm32/is-deref:false +7792 68/push 0/imm32/next +7793 53/push-ebx/formal-var +7794 89/<- %ebx 4/r32/esp +7795 # var primitives/ebx: primitive +7796 68/push 0/imm32/next +7797 68/push 0/imm32/output-is-write-only +7798 68/push 0/imm32/no-disp32 +7799 68/push 0/imm32/no-imm32 +7800 68/push 0/imm32/no-r32 +7801 68/push 3/imm32/rm32-in-first-output +7802 68/push "ff 0/subop/increment"/imm32/subx-name +7803 53/push-ebx/outputs +7804 68/push 0/imm32/inouts +7805 68/push "increment"/imm32/name +7806 89/<- %ebx 4/r32/esp +7807 # convert +7808 c7 0/subop/copy *Curr-block-depth 0/imm32 +7809 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) +7810 (flush _test-output-buffered-file) +7811 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +7817 # check output +7818 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-primitive-register") +7819 # . epilogue +7820 89/<- %esp 5/r32/ebp +7821 5d/pop-to-ebp +7822 c3/return +7823 +7824 test-emit-subx-statement-select-primitive: +7825 # Select the right primitive between overloads. +7826 # foo <- increment +7827 # => +7828 # ff 0/subop/increment %eax # sub-optimal, but should suffice +7829 # +7830 # There's a variable on the var stack as follows: +7831 # name: 'foo' +7832 # type: int +7833 # register: 'eax' +7834 # +7835 # There's two primitives, as follows: +7836 # - name: 'increment' +7837 # out: int/reg +7838 # value: 'ff 0/subop/increment' +7839 # - name: 'increment' +7840 # inout: int/mem +7841 # value: 'ff 0/subop/increment' +7842 # +7843 # There's nothing in functions. +7844 # +7845 # . prologue +7846 55/push-ebp +7847 89/<- %ebp 4/r32/esp +7848 # setup +7849 (clear-stream _test-output-stream) +7850 (clear-stream $_test-output-buffered-file->buffer) +7851 # var type/ecx: (handle tree type-id) = int +7852 68/push 0/imm32/right/null +7853 68/push 1/imm32/left/int +7854 89/<- %ecx 4/r32/esp +7855 # var var-foo/ecx: var in eax +7856 68/push "eax"/imm32/register +7857 68/push 0/imm32/no-stack-offset +7858 68/push 1/imm32/block-depth +7859 51/push-ecx +7860 68/push "foo"/imm32 +7861 89/<- %ecx 4/r32/esp +7862 # var real-outputs/edi: (handle stmt-var) +7863 68/push 0/imm32/is-deref:false +7864 68/push 0/imm32/next +7865 51/push-ecx/var-foo +7866 89/<- %edi 4/r32/esp +7867 # var stmt/esi: statement +7868 68/push 0/imm32/next +7869 57/push-edi/outputs +7870 68/push 0/imm32/inouts +7871 68/push "increment"/imm32/operation +7872 68/push 1/imm32 +7873 89/<- %esi 4/r32/esp +7874 # var formal-var/ebx: var in any register +7875 68/push Any-register/imm32 +7876 68/push 0/imm32/no-stack-offset +7877 68/push 1/imm32/block-depth +7878 ff 6/subop/push *(ecx+4) # Var-type +7879 68/push "dummy"/imm32 +7880 89/<- %ebx 4/r32/esp +7881 # var formal-outputs/ebx: (handle stmt-var) +7882 68/push 0/imm32/is-deref:false +7883 68/push 0/imm32/next +7884 53/push-ebx/formal-var +7885 89/<- %ebx 4/r32/esp +7886 # var primitive1/ebx: primitive +7887 68/push 0/imm32/next +7888 68/push 0/imm32/output-is-write-only +7889 68/push 0/imm32/no-disp32 +7890 68/push 0/imm32/no-imm32 +7891 68/push 0/imm32/no-r32 +7892 68/push 3/imm32/rm32-in-first-output +7893 68/push "ff 0/subop/increment"/imm32/subx-name +7894 53/push-ebx/outputs/formal-outputs +7895 68/push 0/imm32/inouts +7896 68/push "increment"/imm32/name +7897 89/<- %ebx 4/r32/esp +7898 # var primitives/ebx: primitive +7899 53/push-ebx/next +7900 68/push 0/imm32/output-is-write-only +7901 68/push 0/imm32/no-disp32 +7902 68/push 0/imm32/no-imm32 +7903 68/push 0/imm32/no-r32 +7904 68/push 1/imm32/rm32-is-first-inout +7905 68/push "ff 0/subop/increment"/imm32/subx-name +7906 68/push 0/imm32/outputs +7907 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call +7908 68/push "increment"/imm32/name +7909 89/<- %ebx 4/r32/esp +7910 # convert +7911 c7 0/subop/copy *Curr-block-depth 0/imm32 +7912 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) +7913 (flush _test-output-buffered-file) +7914 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +7920 # check output +7921 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive") +7922 # . epilogue +7923 89/<- %esp 5/r32/ebp +7924 5d/pop-to-ebp +7925 c3/return +7926 +7927 test-emit-subx-statement-select-primitive-2: +7928 # Select the right primitive between overloads. +7929 # foo <- increment +7930 # => +7931 # ff 0/subop/increment %eax # sub-optimal, but should suffice +7932 # +7933 # There's a variable on the var stack as follows: +7934 # name: 'foo' +7935 # type: int +7936 # register: 'eax' +7937 # +7938 # There's two primitives, as follows: +7939 # - name: 'increment' +7940 # out: int/reg +7941 # value: 'ff 0/subop/increment' +7942 # - name: 'increment' +7943 # inout: int/mem +7944 # value: 'ff 0/subop/increment' +7945 # +7946 # There's nothing in functions. +7947 # +7948 # . prologue +7949 55/push-ebp +7950 89/<- %ebp 4/r32/esp +7951 # setup +7952 (clear-stream _test-output-stream) +7953 (clear-stream $_test-output-buffered-file->buffer) +7954 # var type/ecx: (handle tree type-id) = int +7955 68/push 0/imm32/right/null +7956 68/push 1/imm32/left/int +7957 89/<- %ecx 4/r32/esp +7958 # var var-foo/ecx: var in eax +7959 68/push "eax"/imm32/register +7960 68/push 0/imm32/no-stack-offset +7961 68/push 1/imm32/block-depth +7962 51/push-ecx +7963 68/push "foo"/imm32 +7964 89/<- %ecx 4/r32/esp +7965 # var inouts/edi: (handle stmt-var) +7966 68/push 0/imm32/is-deref:false +7967 68/push 0/imm32/next +7968 51/push-ecx/var-foo +7969 89/<- %edi 4/r32/esp +7970 # var stmt/esi: statement +7971 68/push 0/imm32/next +7972 68/push 0/imm32/outputs +7973 57/push-edi/inouts +7974 68/push "increment"/imm32/operation +7975 68/push 1/imm32 +7976 89/<- %esi 4/r32/esp +7977 # var formal-var/ebx: var in any register +7978 68/push Any-register/imm32 +7979 68/push 0/imm32/no-stack-offset +7980 68/push 1/imm32/block-depth +7981 ff 6/subop/push *(ecx+4) # Var-type +7982 68/push "dummy"/imm32 +7983 89/<- %ebx 4/r32/esp +7984 # var operand/ebx: (handle stmt-var) +7985 68/push 0/imm32/is-deref:false +7986 68/push 0/imm32/next +7987 53/push-ebx/formal-var +7988 89/<- %ebx 4/r32/esp +7989 # var primitive1/ebx: primitive +7990 68/push 0/imm32/next +7991 68/push 0/imm32/output-is-write-only +7992 68/push 0/imm32/no-disp32 +7993 68/push 0/imm32/no-imm32 +7994 68/push 0/imm32/no-r32 +7995 68/push 3/imm32/rm32-in-first-output +7996 68/push "ff 0/subop/increment"/imm32/subx-name +7997 53/push-ebx/outputs/formal-outputs +7998 68/push 0/imm32/inouts +7999 68/push "increment"/imm32/name +8000 89/<- %ebx 4/r32/esp +8001 # var primitives/ebx: primitive +8002 53/push-ebx/next +8003 68/push 0/imm32/output-is-write-only +8004 68/push 0/imm32/no-disp32 +8005 68/push 0/imm32/no-imm32 +8006 68/push 0/imm32/no-r32 +8007 68/push 1/imm32/rm32-is-first-inout +8008 68/push "ff 0/subop/increment"/imm32/subx-name +8009 68/push 0/imm32/outputs +8010 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call +8011 68/push "increment"/imm32/name +8012 89/<- %ebx 4/r32/esp +8013 # convert +8014 c7 0/subop/copy *Curr-block-depth 0/imm32 +8015 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) +8016 (flush _test-output-buffered-file) +8017 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8023 # check output +8024 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2") +8025 # . epilogue +8026 89/<- %esp 5/r32/ebp +8027 5d/pop-to-ebp +8028 c3/return +8029 +8030 test-increment-register: +8031 # Select the right register between overloads. +8032 # foo <- increment +8033 # => +8034 # 50/increment-eax +8035 # +8036 # There's a variable on the var stack as follows: +8037 # name: 'foo' +8038 # type: int +8039 # register: 'eax' +8040 # +8041 # Primitives are the global definitions. +8042 # +8043 # There are no functions defined. +8044 # +8045 # . prologue +8046 55/push-ebp +8047 89/<- %ebp 4/r32/esp +8048 # setup +8049 (clear-stream _test-output-stream) +8050 (clear-stream $_test-output-buffered-file->buffer) +8051 # var type/ecx: (handle tree type-id) = int +8052 68/push 0/imm32/right/null +8053 68/push 1/imm32/left/int +8054 89/<- %ecx 4/r32/esp +8055 # var var-foo/ecx: var in eax +8056 68/push "eax"/imm32/register +8057 68/push 0/imm32/no-stack-offset +8058 68/push 1/imm32/block-depth +8059 51/push-ecx +8060 68/push "foo"/imm32 +8061 89/<- %ecx 4/r32/esp +8062 # var real-outputs/edi: (handle stmt-var) +8063 68/push 0/imm32/is-deref:false +8064 68/push 0/imm32/next +8065 51/push-ecx/var-foo +8066 89/<- %edi 4/r32/esp +8067 # var stmt/esi: statement +8068 68/push 0/imm32/next +8069 57/push-edi/outputs +8070 68/push 0/imm32/inouts +8071 68/push "increment"/imm32/operation +8072 68/push 1/imm32/regular-statement +8073 89/<- %esi 4/r32/esp +8074 # convert +8075 c7 0/subop/copy *Curr-block-depth 0/imm32 +8076 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8077 (flush _test-output-buffered-file) +8078 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8084 # check output +8085 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") +8086 # . epilogue +8087 89/<- %esp 5/r32/ebp +8088 5d/pop-to-ebp +8089 c3/return +8090 +8091 test-increment-var: +8092 # Select the right primitive between overloads. +8093 # foo <- increment +8094 # => +8095 # ff 0/subop/increment %eax # sub-optimal, but should suffice +8096 # +8097 # There's a variable on the var stack as follows: +8098 # name: 'foo' +8099 # type: int +8100 # register: 'eax' +8101 # +8102 # Primitives are the global definitions. +8103 # +8104 # There are no functions defined. +8105 # +8106 # . prologue +8107 55/push-ebp +8108 89/<- %ebp 4/r32/esp +8109 # setup +8110 (clear-stream _test-output-stream) +8111 (clear-stream $_test-output-buffered-file->buffer) +8112 # var type/ecx: (handle tree type-id) = int +8113 68/push 0/imm32/right/null +8114 68/push 1/imm32/left/int +8115 89/<- %ecx 4/r32/esp +8116 # var var-foo/ecx: var in eax +8117 68/push "eax"/imm32/register +8118 68/push 0/imm32/no-stack-offset +8119 68/push 1/imm32/block-depth +8120 51/push-ecx +8121 68/push "foo"/imm32 +8122 89/<- %ecx 4/r32/esp +8123 # var inouts/edi: (handle stmt-var) +8124 68/push 0/imm32/is-deref:false +8125 68/push 0/imm32/next +8126 51/push-ecx/var-foo +8127 89/<- %edi 4/r32/esp +8128 # var stmt/esi: statement +8129 68/push 0/imm32/next +8130 57/push-edi/outputs +8131 68/push 0/imm32/inouts +8132 68/push "increment"/imm32/operation +8133 68/push 1/imm32 +8134 89/<- %esi 4/r32/esp +8135 # convert +8136 c7 0/subop/copy *Curr-block-depth 0/imm32 +8137 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8138 (flush _test-output-buffered-file) +8139 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8145 # check output +8146 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-var") +8147 # . epilogue +8148 89/<- %esp 5/r32/ebp +8149 5d/pop-to-ebp +8150 c3/return +8151 +8152 test-add-reg-to-reg: +8153 # var1/reg <- add var2/reg +8154 # => +8155 # 01/add %var1 var2 +8156 # +8157 # . prologue +8158 55/push-ebp +8159 89/<- %ebp 4/r32/esp +8160 # setup +8161 (clear-stream _test-output-stream) +8162 (clear-stream $_test-output-buffered-file->buffer) +8163 # var type/ecx: (handle tree type-id) = int +8164 68/push 0/imm32/right/null +8165 68/push 1/imm32/left/int +8166 89/<- %ecx 4/r32/esp +8167 # var var-var1/ecx: var in eax +8168 68/push "eax"/imm32/register +8169 68/push 0/imm32/no-stack-offset +8170 68/push 1/imm32/block-depth +8171 51/push-ecx +8172 68/push "var1"/imm32 +8173 89/<- %ecx 4/r32/esp +8174 # var var-var2/edx: var in ecx +8175 68/push "ecx"/imm32/register +8176 68/push 0/imm32/no-stack-offset +8177 68/push 1/imm32/block-depth +8178 ff 6/subop/push *(ecx+4) # Var-type +8179 68/push "var2"/imm32 +8180 89/<- %edx 4/r32/esp +8181 # var inouts/esi: (handle stmt-var) = [var2] +8182 68/push 0/imm32/is-deref:false +8183 68/push 0/imm32/next +8184 52/push-edx/var-var2 +8185 89/<- %esi 4/r32/esp +8186 # var outputs/edi: (handle stmt-var) = [var1, var2] +8187 68/push 0/imm32/is-deref:false 8188 68/push 0/imm32/next -8189 52/push-edx/var-var2 -8190 89/<- %esi 4/r32/esp -8191 # var outputs/edi: (list var1) +8189 51/push-ecx/var-var1 +8190 89/<- %edi 4/r32/esp +8191 # var stmt/esi: statement 8192 68/push 0/imm32/next -8193 51/push-ecx/var-var1 -8194 89/<- %edi 4/r32/esp -8195 # var stmt/esi: statement -8196 68/push 0/imm32/next -8197 57/push-edi/outputs -8198 56/push-esi/inouts -8199 68/push "add"/imm32/operation -8200 68/push 1/imm32 -8201 89/<- %esi 4/r32/esp -8202 # convert -8203 c7 0/subop/copy *Curr-block-depth 0/imm32 -8204 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8205 (flush _test-output-buffered-file) -8206 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8212 # check output -8213 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") -8214 # . epilogue -8215 89/<- %esp 5/r32/ebp -8216 5d/pop-to-ebp -8217 c3/return -8218 -8219 test-add-literal-to-reg: -8220 # var1/ecx <- add 0x34 -8221 # => -8222 # 81 0/subop/add %ecx 0x34/imm32 -8223 # -8224 # . prologue -8225 55/push-ebp -8226 89/<- %ebp 4/r32/esp -8227 # setup -8228 (clear-stream _test-output-stream) -8229 (clear-stream $_test-output-buffered-file->buffer) -8230 # var type/ecx: (handle tree type-id) = int -8231 68/push 0/imm32/right/null -8232 68/push 1/imm32/left/int -8233 89/<- %ecx 4/r32/esp -8234 # var var-var1/ecx: var in ecx -8235 68/push "ecx"/imm32/register -8236 68/push 0/imm32/no-stack-offset -8237 68/push 1/imm32/block-depth -8238 51/push-ecx -8239 68/push "var1"/imm32 -8240 89/<- %ecx 4/r32/esp -8241 # var type/edx: (handle tree type-id) = literal -8242 68/push 0/imm32/right/null -8243 68/push 0/imm32/left/literal -8244 89/<- %edx 4/r32/esp -8245 # var var-var2/edx: var literal -8246 68/push 0/imm32/no-register -8247 68/push 0/imm32/no-stack-offset -8248 68/push 1/imm32/block-depth -8249 52/push-edx -8250 68/push "0x34"/imm32 -8251 89/<- %edx 4/r32/esp -8252 # var inouts/esi: (list var2) -8253 68/push 0/imm32/next -8254 52/push-edx/var-var2 -8255 89/<- %esi 4/r32/esp -8256 # var outputs/edi: (list var1) -8257 68/push 0/imm32/next -8258 51/push-ecx/var-var1 -8259 89/<- %edi 4/r32/esp -8260 # var stmt/esi: statement -8261 68/push 0/imm32/next -8262 57/push-edi/outputs -8263 56/push-esi/inouts -8264 68/push "add"/imm32/operation -8265 68/push 1/imm32 -8266 89/<- %esi 4/r32/esp -8267 # convert -8268 c7 0/subop/copy *Curr-block-depth 0/imm32 -8269 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8270 (flush _test-output-buffered-file) -8271 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8277 # check output -8278 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") -8279 # . epilogue -8280 89/<- %esp 5/r32/ebp -8281 5d/pop-to-ebp -8282 c3/return -8283 -8284 test-add-literal-to-mem: -8285 # add-to var1, 0x34 -8286 # => -8287 # 81 0/subop/add %eax 0x34/imm32 -8288 # -8289 # . prologue -8290 55/push-ebp -8291 89/<- %ebp 4/r32/esp -8292 # setup -8293 (clear-stream _test-output-stream) -8294 (clear-stream $_test-output-buffered-file->buffer) -8295 # var type/ecx: (handle tree type-id) = int -8296 68/push 0/imm32/right/null -8297 68/push 1/imm32/left/int +8193 57/push-edi/outputs +8194 56/push-esi/inouts +8195 68/push "add"/imm32/operation +8196 68/push 1/imm32 +8197 89/<- %esi 4/r32/esp +8198 # convert +8199 c7 0/subop/copy *Curr-block-depth 0/imm32 +8200 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8201 (flush _test-output-buffered-file) +8202 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8208 # check output +8209 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") +8210 # . epilogue +8211 89/<- %esp 5/r32/ebp +8212 5d/pop-to-ebp +8213 c3/return +8214 +8215 test-add-reg-to-mem: +8216 # add-to var1 var2/reg +8217 # => +8218 # 01/add *(ebp+__) var2 +8219 # +8220 # . prologue +8221 55/push-ebp +8222 89/<- %ebp 4/r32/esp +8223 # setup +8224 (clear-stream _test-output-stream) +8225 (clear-stream $_test-output-buffered-file->buffer) +8226 # var type/ecx: (handle tree type-id) = int +8227 68/push 0/imm32/right/null +8228 68/push 1/imm32/left/int +8229 89/<- %ecx 4/r32/esp +8230 # var var-var1/ecx: var +8231 68/push 0/imm32/no-register +8232 68/push 8/imm32/stack-offset +8233 68/push 1/imm32/block-depth +8234 51/push-ecx +8235 68/push "var1"/imm32 +8236 89/<- %ecx 4/r32/esp +8237 # var var-var2/edx: var in ecx +8238 68/push "ecx"/imm32/register +8239 68/push 0/imm32/no-stack-offset +8240 68/push 1/imm32/block-depth +8241 ff 6/subop/push *(ecx+4) # Var-type +8242 68/push "var2"/imm32 +8243 89/<- %edx 4/r32/esp +8244 # var inouts/esi: (handle stmt-var) = [var2] +8245 68/push 0/imm32/is-deref:false +8246 68/push 0/imm32/next +8247 52/push-edx/var-var2 +8248 89/<- %esi 4/r32/esp +8249 # var inouts = (handle stmt-var) = [var1, var2] +8250 56/push-esi/next +8251 51/push-ecx/var-var1 +8252 89/<- %esi 4/r32/esp +8253 # var stmt/esi: statement +8254 68/push 0/imm32/next +8255 68/push 0/imm32/outputs +8256 56/push-esi/inouts +8257 68/push "add-to"/imm32/operation +8258 68/push 1/imm32 +8259 89/<- %esi 4/r32/esp +8260 # convert +8261 c7 0/subop/copy *Curr-block-depth 0/imm32 +8262 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8263 (flush _test-output-buffered-file) +8264 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8270 # check output +8271 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") +8272 # . epilogue +8273 89/<- %esp 5/r32/ebp +8274 5d/pop-to-ebp +8275 c3/return +8276 +8277 test-add-mem-to-reg: +8278 # var1/reg <- add var2 +8279 # => +8280 # 03/add *(ebp+__) var1 +8281 # +8282 # . prologue +8283 55/push-ebp +8284 89/<- %ebp 4/r32/esp +8285 # setup +8286 (clear-stream _test-output-stream) +8287 (clear-stream $_test-output-buffered-file->buffer) +8288 # var type/ecx: (handle tree type-id) = int +8289 68/push 0/imm32/right/null +8290 68/push 1/imm32/left/int +8291 89/<- %ecx 4/r32/esp +8292 # var var-var1/ecx: var in eax +8293 68/push "eax"/imm32/register +8294 68/push 0/imm32/no-stack-offset +8295 68/push 1/imm32/block-depth +8296 51/push-ecx +8297 68/push "var1"/imm32 8298 89/<- %ecx 4/r32/esp -8299 # var var-var1/ecx: var +8299 # var var-var2/edx: var 8300 68/push 0/imm32/no-register 8301 68/push 8/imm32/stack-offset 8302 68/push 1/imm32/block-depth -8303 51/push-ecx -8304 68/push "var1"/imm32 -8305 89/<- %ecx 4/r32/esp -8306 # var type/edx: (handle tree type-id) = literal -8307 68/push 0/imm32/right/null -8308 68/push 0/imm32/left/literal -8309 89/<- %edx 4/r32/esp -8310 # var var-var2/edx: var literal -8311 68/push 0/imm32/no-register -8312 68/push 0/imm32/no-stack-offset -8313 68/push 1/imm32/block-depth -8314 52/push-edx -8315 68/push "0x34"/imm32 -8316 89/<- %edx 4/r32/esp -8317 # var inouts/esi: (list var2) -8318 68/push 0/imm32/next -8319 52/push-edx/var-var2 -8320 89/<- %esi 4/r32/esp -8321 # var inouts = (list var1 inouts) -8322 56/push-esi/next -8323 51/push-ecx/var-var1 -8324 89/<- %esi 4/r32/esp -8325 # var stmt/esi: statement -8326 68/push 0/imm32/next -8327 68/push 0/imm32/outputs -8328 56/push-esi/inouts -8329 68/push "add-to"/imm32/operation -8330 68/push 1/imm32 -8331 89/<- %esi 4/r32/esp -8332 # convert -8333 c7 0/subop/copy *Curr-block-depth 0/imm32 -8334 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8335 (flush _test-output-buffered-file) -8336 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8342 # check output -8343 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") -8344 # . epilogue -8345 89/<- %esp 5/r32/ebp -8346 5d/pop-to-ebp -8347 c3/return -8348 -8349 test-compare-mem-with-reg: -8350 # compare var1, var2/eax -8351 # => -8352 # 39/compare *(ebp+___) 0/r32/eax -8353 # -8354 # . prologue -8355 55/push-ebp -8356 89/<- %ebp 4/r32/esp -8357 # setup -8358 (clear-stream _test-output-stream) -8359 (clear-stream $_test-output-buffered-file->buffer) -8360 # var type/ecx: (handle tree type-id) = int -8361 68/push 0/imm32/right/null -8362 68/push 1/imm32/left/int -8363 89/<- %ecx 4/r32/esp -8364 # var var-var2/ecx: var in eax -8365 68/push "eax"/imm32/register -8366 68/push 0/imm32/no-stack-offset -8367 68/push 1/imm32/block-depth -8368 51/push-ecx -8369 68/push "var2"/imm32 -8370 89/<- %ecx 4/r32/esp -8371 # var var-var1/edx: var -8372 68/push 0/imm32/no-register -8373 68/push 8/imm32/stack-offset -8374 68/push 1/imm32/block-depth -8375 ff 6/subop/push *(ecx+4) # Var-type -8376 68/push "var1"/imm32 -8377 89/<- %edx 4/r32/esp -8378 # var inouts/esi: (list var1 var2) -8379 68/push 0/imm32/next -8380 51/push-ecx/var-var2 -8381 89/<- %esi 4/r32/esp -8382 56/push-esi -8383 52/push-edx/var-var1 -8384 89/<- %esi 4/r32/esp -8385 # var stmt/esi: statement -8386 68/push 0/imm32/next -8387 68/push 0/imm32/outputs -8388 56/push-esi/inouts -8389 68/push "compare"/imm32/operation -8390 68/push 1/imm32 -8391 89/<- %esi 4/r32/esp -8392 # convert -8393 c7 0/subop/copy *Curr-block-depth 0/imm32 -8394 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8395 (flush _test-output-buffered-file) -8396 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8402 # check output -8403 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") -8404 # . epilogue -8405 89/<- %esp 5/r32/ebp -8406 5d/pop-to-ebp -8407 c3/return -8408 -8409 test-compare-reg-with-mem: -8410 # compare var1/eax, var2 -8411 # => -8412 # 3b/compare *(ebp+___) 0/r32/eax -8413 # -8414 # . prologue -8415 55/push-ebp -8416 89/<- %ebp 4/r32/esp -8417 # setup -8418 (clear-stream _test-output-stream) -8419 (clear-stream $_test-output-buffered-file->buffer) -8420 # var type/ecx: (handle tree type-id) = int -8421 68/push 0/imm32/right/null -8422 68/push 1/imm32/left/int -8423 89/<- %ecx 4/r32/esp -8424 # var var-var1/ecx: var in eax -8425 68/push "eax"/imm32/register -8426 68/push 0/imm32/no-stack-offset -8427 68/push 1/imm32/block-depth -8428 51/push-ecx -8429 68/push "var1"/imm32 -8430 89/<- %ecx 4/r32/esp -8431 # var var-var2/edx: var -8432 68/push 0/imm32/no-register -8433 68/push 8/imm32/stack-offset -8434 68/push 1/imm32/block-depth -8435 ff 6/subop/push *(ecx+4) # Var-type -8436 68/push "var2"/imm32 -8437 89/<- %edx 4/r32/esp -8438 # var inouts/esi: (list var1 var2) -8439 68/push 0/imm32/next -8440 52/push-edx/var-var2 -8441 89/<- %esi 4/r32/esp -8442 56/push-esi -8443 51/push-ecx/var-var1 +8303 ff 6/subop/push *(ecx+4) # Var-type +8304 68/push "var2"/imm32 +8305 89/<- %edx 4/r32/esp +8306 # var inouts/esi: (handle stmt-var) = [var2] +8307 68/push 0/imm32/is-deref:false +8308 68/push 0/imm32/next +8309 52/push-edx/var-var2 +8310 89/<- %esi 4/r32/esp +8311 # var outputs/edi = (handle stmt-var) = [var1] +8312 68/push 0/imm32/is-deref:false +8313 68/push 0/imm32/next +8314 51/push-ecx/var-var1 +8315 89/<- %edi 4/r32/esp +8316 # var stmt/esi: statement +8317 68/push 0/imm32/next +8318 57/push-edi/outputs +8319 56/push-esi/inouts +8320 68/push "add"/imm32/operation +8321 68/push 1/imm32 +8322 89/<- %esi 4/r32/esp +8323 # convert +8324 c7 0/subop/copy *Curr-block-depth 0/imm32 +8325 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8326 (flush _test-output-buffered-file) +8327 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8333 # check output +8334 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") +8335 # . epilogue +8336 89/<- %esp 5/r32/ebp +8337 5d/pop-to-ebp +8338 c3/return +8339 +8340 test-add-literal-to-eax: +8341 # var1/eax <- add 0x34 +8342 # => +8343 # 05/add-to-eax 0x34/imm32 +8344 # +8345 # . prologue +8346 55/push-ebp +8347 89/<- %ebp 4/r32/esp +8348 # setup +8349 (clear-stream _test-output-stream) +8350 (clear-stream $_test-output-buffered-file->buffer) +8351 # var type/ecx: (handle tree type-id) = int +8352 68/push 0/imm32/right/null +8353 68/push 1/imm32/left/int +8354 89/<- %ecx 4/r32/esp +8355 # var var-var1/ecx: var in eax +8356 68/push "eax"/imm32/register +8357 68/push 0/imm32/no-stack-offset +8358 68/push 1/imm32/block-depth +8359 51/push-ecx +8360 68/push "var1"/imm32 +8361 89/<- %ecx 4/r32/esp +8362 # var type/edx: (handle tree type-id) = literal +8363 68/push 0/imm32/right/null +8364 68/push 0/imm32/left/literal +8365 89/<- %edx 4/r32/esp +8366 # var var-var2/edx: var literal +8367 68/push 0/imm32/no-register +8368 68/push 0/imm32/no-stack-offset +8369 68/push 1/imm32/block-depth +8370 52/push-edx +8371 68/push "0x34"/imm32 +8372 89/<- %edx 4/r32/esp +8373 # var inouts/esi: (handle stmt-var) = [var2] +8374 68/push 0/imm32/is-deref:false +8375 68/push 0/imm32/next +8376 52/push-edx/var-var2 +8377 89/<- %esi 4/r32/esp +8378 # var outputs/edi: (handle stmt-var) = [var1] +8379 68/push 0/imm32/is-deref:false +8380 68/push 0/imm32/next +8381 51/push-ecx/var-var1 +8382 89/<- %edi 4/r32/esp +8383 # var stmt/esi: statement +8384 68/push 0/imm32/next +8385 57/push-edi/outputs +8386 56/push-esi/inouts +8387 68/push "add"/imm32/operation +8388 68/push 1/imm32 +8389 89/<- %esi 4/r32/esp +8390 # convert +8391 c7 0/subop/copy *Curr-block-depth 0/imm32 +8392 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8393 (flush _test-output-buffered-file) +8394 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8400 # check output +8401 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") +8402 # . epilogue +8403 89/<- %esp 5/r32/ebp +8404 5d/pop-to-ebp +8405 c3/return +8406 +8407 test-add-literal-to-reg: +8408 # var1/ecx <- add 0x34 +8409 # => +8410 # 81 0/subop/add %ecx 0x34/imm32 +8411 # +8412 # . prologue +8413 55/push-ebp +8414 89/<- %ebp 4/r32/esp +8415 # setup +8416 (clear-stream _test-output-stream) +8417 (clear-stream $_test-output-buffered-file->buffer) +8418 # var type/ecx: (handle tree type-id) = int +8419 68/push 0/imm32/right/null +8420 68/push 1/imm32/left/int +8421 89/<- %ecx 4/r32/esp +8422 # var var-var1/ecx: var in ecx +8423 68/push "ecx"/imm32/register +8424 68/push 0/imm32/no-stack-offset +8425 68/push 1/imm32/block-depth +8426 51/push-ecx +8427 68/push "var1"/imm32 +8428 89/<- %ecx 4/r32/esp +8429 # var type/edx: (handle tree type-id) = literal +8430 68/push 0/imm32/right/null +8431 68/push 0/imm32/left/literal +8432 89/<- %edx 4/r32/esp +8433 # var var-var2/edx: var literal +8434 68/push 0/imm32/no-register +8435 68/push 0/imm32/no-stack-offset +8436 68/push 1/imm32/block-depth +8437 52/push-edx +8438 68/push "0x34"/imm32 +8439 89/<- %edx 4/r32/esp +8440 # var inouts/esi: (handle stmt-var) = [var2] +8441 68/push 0/imm32/is-deref:false +8442 68/push 0/imm32/next +8443 52/push-edx/var-var2 8444 89/<- %esi 4/r32/esp -8445 # var stmt/esi: statement -8446 68/push 0/imm32/next -8447 68/push 0/imm32/outputs -8448 56/push-esi/inouts -8449 68/push "compare"/imm32/operation -8450 68/push 1/imm32 -8451 89/<- %esi 4/r32/esp -8452 # convert -8453 c7 0/subop/copy *Curr-block-depth 0/imm32 -8454 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8455 (flush _test-output-buffered-file) -8456 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8462 # check output -8463 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") -8464 # . epilogue -8465 89/<- %esp 5/r32/ebp -8466 5d/pop-to-ebp -8467 c3/return -8468 -8469 test-compare-mem-with-literal: -8470 # compare var1, 0x34 -8471 # => -8472 # 81 7/subop/compare *(ebp+___) 0x34/imm32 -8473 # -8474 # . prologue -8475 55/push-ebp -8476 89/<- %ebp 4/r32/esp -8477 # setup -8478 (clear-stream _test-output-stream) -8479 (clear-stream $_test-output-buffered-file->buffer) -8480 # var type/ecx: (handle tree type-id) = int -8481 68/push 0/imm32/right/null -8482 68/push 1/imm32/left/int -8483 89/<- %ecx 4/r32/esp -8484 # var var-var1/ecx: var -8485 68/push 0/imm32/no-register -8486 68/push 8/imm32/stack-offset -8487 68/push 1/imm32/block-depth -8488 51/push-ecx -8489 68/push "var1"/imm32 -8490 89/<- %ecx 4/r32/esp -8491 # var type/edx: (handle tree type-id) = literal -8492 68/push 0/imm32/right/null -8493 68/push 0/imm32/left/literal -8494 89/<- %edx 4/r32/esp -8495 # var var-var2/edx: var literal -8496 68/push 0/imm32/no-register -8497 68/push 0/imm32/no-stack-offset -8498 68/push 1/imm32/block-depth -8499 52/push-edx -8500 68/push "0x34"/imm32 -8501 89/<- %edx 4/r32/esp -8502 # var inouts/esi: (list var2) -8503 68/push 0/imm32/next -8504 52/push-edx/var-var2 -8505 89/<- %esi 4/r32/esp -8506 # var inouts = (list var1 inouts) -8507 56/push-esi/next -8508 51/push-ecx/var-var1 -8509 89/<- %esi 4/r32/esp -8510 # var stmt/esi: statement -8511 68/push 0/imm32/next -8512 68/push 0/imm32/outputs -8513 56/push-esi/inouts -8514 68/push "compare"/imm32/operation -8515 68/push 1/imm32 +8445 # var outputs/edi: (handle stmt-var) = [var1] +8446 68/push 0/imm32/is-deref:false +8447 68/push 0/imm32/next +8448 51/push-ecx/var-var1 +8449 89/<- %edi 4/r32/esp +8450 # var stmt/esi: statement +8451 68/push 0/imm32/next +8452 57/push-edi/outputs +8453 56/push-esi/inouts +8454 68/push "add"/imm32/operation +8455 68/push 1/imm32 +8456 89/<- %esi 4/r32/esp +8457 # convert +8458 c7 0/subop/copy *Curr-block-depth 0/imm32 +8459 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8460 (flush _test-output-buffered-file) +8461 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8467 # check output +8468 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") +8469 # . epilogue +8470 89/<- %esp 5/r32/ebp +8471 5d/pop-to-ebp +8472 c3/return +8473 +8474 test-add-literal-to-mem: +8475 # add-to var1, 0x34 +8476 # => +8477 # 81 0/subop/add %eax 0x34/imm32 +8478 # +8479 # . prologue +8480 55/push-ebp +8481 89/<- %ebp 4/r32/esp +8482 # setup +8483 (clear-stream _test-output-stream) +8484 (clear-stream $_test-output-buffered-file->buffer) +8485 # var type/ecx: (handle tree type-id) = int +8486 68/push 0/imm32/right/null +8487 68/push 1/imm32/left/int +8488 89/<- %ecx 4/r32/esp +8489 # var var-var1/ecx: var +8490 68/push 0/imm32/no-register +8491 68/push 8/imm32/stack-offset +8492 68/push 1/imm32/block-depth +8493 51/push-ecx +8494 68/push "var1"/imm32 +8495 89/<- %ecx 4/r32/esp +8496 # var type/edx: (handle tree type-id) = literal +8497 68/push 0/imm32/right/null +8498 68/push 0/imm32/left/literal +8499 89/<- %edx 4/r32/esp +8500 # var var-var2/edx: var literal +8501 68/push 0/imm32/no-register +8502 68/push 0/imm32/no-stack-offset +8503 68/push 1/imm32/block-depth +8504 52/push-edx +8505 68/push "0x34"/imm32 +8506 89/<- %edx 4/r32/esp +8507 # var inouts/esi: (handle stmt-var) = [var2] +8508 68/push 0/imm32/is-deref:false +8509 68/push 0/imm32/next +8510 52/push-edx/var-var2 +8511 89/<- %esi 4/r32/esp +8512 # var inouts = (handle stmt-var) = [var1, var2] +8513 68/push 0/imm32/is-deref:false +8514 56/push-esi/next +8515 51/push-ecx/var-var1 8516 89/<- %esi 4/r32/esp -8517 # convert -8518 c7 0/subop/copy *Curr-block-depth 0/imm32 -8519 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8520 (flush _test-output-buffered-file) -8521 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8527 # check output -8528 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") -8529 # . epilogue -8530 89/<- %esp 5/r32/ebp -8531 5d/pop-to-ebp -8532 c3/return -8533 -8534 test-compare-eax-with-literal: -8535 # compare var1/eax 0x34 -8536 # => -8537 # 3d/compare-eax-with 0x34/imm32 -8538 # -8539 # . prologue -8540 55/push-ebp -8541 89/<- %ebp 4/r32/esp -8542 # setup -8543 (clear-stream _test-output-stream) -8544 (clear-stream $_test-output-buffered-file->buffer) -8545 # var type/ecx: (handle tree type-id) = int -8546 68/push 0/imm32/right/null -8547 68/push 1/imm32/left/int -8548 89/<- %ecx 4/r32/esp -8549 # var var-var1/ecx: var in eax -8550 68/push "eax"/imm32/register -8551 68/push 0/imm32/no-stack-offset -8552 68/push 1/imm32/block-depth -8553 51/push-ecx -8554 68/push "var1"/imm32 +8517 # var stmt/esi: statement +8518 68/push 0/imm32/next +8519 68/push 0/imm32/outputs +8520 56/push-esi/inouts +8521 68/push "add-to"/imm32/operation +8522 68/push 1/imm32 +8523 89/<- %esi 4/r32/esp +8524 # convert +8525 c7 0/subop/copy *Curr-block-depth 0/imm32 +8526 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8527 (flush _test-output-buffered-file) +8528 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8534 # check output +8535 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") +8536 # . epilogue +8537 89/<- %esp 5/r32/ebp +8538 5d/pop-to-ebp +8539 c3/return +8540 +8541 test-compare-mem-with-reg: +8542 # compare var1, var2/eax +8543 # => +8544 # 39/compare *(ebp+___) 0/r32/eax +8545 # +8546 # . prologue +8547 55/push-ebp +8548 89/<- %ebp 4/r32/esp +8549 # setup +8550 (clear-stream _test-output-stream) +8551 (clear-stream $_test-output-buffered-file->buffer) +8552 # var type/ecx: (handle tree type-id) = int +8553 68/push 0/imm32/right/null +8554 68/push 1/imm32/left/int 8555 89/<- %ecx 4/r32/esp -8556 # var type/edx: (handle tree type-id) = literal -8557 68/push 0/imm32/right/null -8558 68/push 0/imm32/left/literal -8559 89/<- %edx 4/r32/esp -8560 # var var-var2/edx: var literal -8561 68/push 0/imm32/no-register -8562 68/push 0/imm32/no-stack-offset -8563 68/push 1/imm32/block-depth -8564 52/push-edx -8565 68/push "0x34"/imm32 -8566 89/<- %edx 4/r32/esp -8567 # var inouts/esi: (list var2) -8568 68/push 0/imm32/next -8569 52/push-edx/var-var2 -8570 89/<- %esi 4/r32/esp -8571 # var inouts = (list var1 inouts) -8572 56/push-esi/next -8573 51/push-ecx/var-var1 +8556 # var var-var2/ecx: var in eax +8557 68/push "eax"/imm32/register +8558 68/push 0/imm32/no-stack-offset +8559 68/push 1/imm32/block-depth +8560 51/push-ecx +8561 68/push "var2"/imm32 +8562 89/<- %ecx 4/r32/esp +8563 # var var-var1/edx: var +8564 68/push 0/imm32/no-register +8565 68/push 8/imm32/stack-offset +8566 68/push 1/imm32/block-depth +8567 ff 6/subop/push *(ecx+4) # Var-type +8568 68/push "var1"/imm32 +8569 89/<- %edx 4/r32/esp +8570 # var inouts/esi: (handle stmt-var) = [var2] +8571 68/push 0/imm32/is-deref:false +8572 68/push 0/imm32/next +8573 51/push-ecx/var-var2 8574 89/<- %esi 4/r32/esp -8575 # var stmt/esi: statement -8576 68/push 0/imm32/next -8577 68/push 0/imm32/outputs -8578 56/push-esi/inouts -8579 68/push "compare"/imm32/operation -8580 68/push 1/imm32/regular-stmt -8581 89/<- %esi 4/r32/esp -8582 # convert -8583 c7 0/subop/copy *Curr-block-depth 0/imm32 -8584 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8585 (flush _test-output-buffered-file) -8586 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8592 # check output -8593 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") -8594 # . epilogue -8595 89/<- %esp 5/r32/ebp -8596 5d/pop-to-ebp -8597 c3/return -8598 -8599 test-compare-reg-with-literal: -8600 # compare var1/ecx 0x34 -8601 # => -8602 # 81 7/subop/compare %ecx 0x34/imm32 -8603 # -8604 # . prologue -8605 55/push-ebp -8606 89/<- %ebp 4/r32/esp -8607 # setup -8608 (clear-stream _test-output-stream) -8609 (clear-stream $_test-output-buffered-file->buffer) -8610 # var type/ecx: (handle tree type-id) = int -8611 68/push 0/imm32/right/null -8612 68/push 1/imm32/left/int -8613 89/<- %ecx 4/r32/esp -8614 # var var-var1/ecx: var in ecx -8615 68/push "ecx"/imm32/register -8616 68/push 0/imm32/no-stack-offset -8617 68/push 1/imm32/block-depth -8618 51/push-ecx -8619 68/push "var1"/imm32 -8620 89/<- %ecx 4/r32/esp -8621 # var type/edx: (handle tree type-id) = literal -8622 68/push 0/imm32/right/null -8623 68/push 0/imm32/left/literal -8624 89/<- %edx 4/r32/esp -8625 # var var-var2/edx: var literal -8626 68/push 0/imm32/no-register -8627 68/push 0/imm32/no-stack-offset -8628 68/push 1/imm32/block-depth -8629 52/push-edx -8630 68/push "0x34"/imm32 -8631 89/<- %edx 4/r32/esp -8632 # var inouts/esi: (list var2) -8633 68/push 0/imm32/next -8634 52/push-edx/var-var2 -8635 89/<- %esi 4/r32/esp -8636 # var inouts = (list var1 inouts) -8637 56/push-esi/next -8638 51/push-ecx/var-var1 -8639 89/<- %esi 4/r32/esp -8640 # var stmt/esi: statement -8641 68/push 0/imm32/next -8642 68/push 0/imm32/outputs -8643 56/push-esi/inouts -8644 68/push "compare"/imm32/operation -8645 68/push 1/imm32/regular-stmt -8646 89/<- %esi 4/r32/esp -8647 # convert -8648 c7 0/subop/copy *Curr-block-depth 0/imm32 -8649 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8650 (flush _test-output-buffered-file) -8651 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8657 # check output -8658 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") -8659 # . epilogue -8660 89/<- %esp 5/r32/ebp -8661 5d/pop-to-ebp -8662 c3/return -8663 -8664 test-emit-subx-statement-function-call: -8665 # Call a function on a variable on the stack. -8666 # f foo -8667 # => -8668 # (f2 *(ebp-8)) -8669 # (Changing the function name supports overloading in general, but here it -8670 # just serves to help disambiguate things.) +8575 # inouts = [var1, var2] +8576 68/push 0/imm32/is-deref:false +8577 56/push-esi +8578 52/push-edx/var-var1 +8579 89/<- %esi 4/r32/esp +8580 # var stmt/esi: statement +8581 68/push 0/imm32/next +8582 68/push 0/imm32/outputs +8583 56/push-esi/inouts +8584 68/push "compare"/imm32/operation +8585 68/push 1/imm32 +8586 89/<- %esi 4/r32/esp +8587 # convert +8588 c7 0/subop/copy *Curr-block-depth 0/imm32 +8589 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8590 (flush _test-output-buffered-file) +8591 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8597 # check output +8598 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") +8599 # . epilogue +8600 89/<- %esp 5/r32/ebp +8601 5d/pop-to-ebp +8602 c3/return +8603 +8604 test-compare-reg-with-mem: +8605 # compare var1/eax, var2 +8606 # => +8607 # 3b/compare *(ebp+___) 0/r32/eax +8608 # +8609 # . prologue +8610 55/push-ebp +8611 89/<- %ebp 4/r32/esp +8612 # setup +8613 (clear-stream _test-output-stream) +8614 (clear-stream $_test-output-buffered-file->buffer) +8615 # var type/ecx: (handle tree type-id) = int +8616 68/push 0/imm32/right/null +8617 68/push 1/imm32/left/int +8618 89/<- %ecx 4/r32/esp +8619 # var var-var1/ecx: var in eax +8620 68/push "eax"/imm32/register +8621 68/push 0/imm32/no-stack-offset +8622 68/push 1/imm32/block-depth +8623 51/push-ecx +8624 68/push "var1"/imm32 +8625 89/<- %ecx 4/r32/esp +8626 # var var-var2/edx: var +8627 68/push 0/imm32/no-register +8628 68/push 8/imm32/stack-offset +8629 68/push 1/imm32/block-depth +8630 ff 6/subop/push *(ecx+4) # Var-type +8631 68/push "var2"/imm32 +8632 89/<- %edx 4/r32/esp +8633 # var inouts/esi: (handle stmt-var) = [var2] +8634 68/push 0/imm32/is-deref:false +8635 68/push 0/imm32/next +8636 52/push-edx/var-var2 +8637 89/<- %esi 4/r32/esp +8638 # inouts = [var1, var2] +8639 68/push 0/imm32/is-deref:false +8640 56/push-esi +8641 51/push-ecx/var-var1 +8642 89/<- %esi 4/r32/esp +8643 # var stmt/esi: statement +8644 68/push 0/imm32/next +8645 68/push 0/imm32/outputs +8646 56/push-esi/inouts +8647 68/push "compare"/imm32/operation +8648 68/push 1/imm32 +8649 89/<- %esi 4/r32/esp +8650 # convert +8651 c7 0/subop/copy *Curr-block-depth 0/imm32 +8652 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8653 (flush _test-output-buffered-file) +8654 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8660 # check output +8661 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") +8662 # . epilogue +8663 89/<- %esp 5/r32/ebp +8664 5d/pop-to-ebp +8665 c3/return +8666 +8667 test-compare-mem-with-literal: +8668 # compare var1, 0x34 +8669 # => +8670 # 81 7/subop/compare *(ebp+___) 0x34/imm32 8671 # -8672 # There's a variable on the var stack as follows: -8673 # name: 'foo' -8674 # type: int -8675 # stack-offset: -8 -8676 # -8677 # There's nothing in primitives. -8678 # -8679 # There's a function with this info: -8680 # name: 'f' -8681 # inout: int/mem -8682 # value: 'f2' -8683 # -8684 # . prologue -8685 55/push-ebp -8686 89/<- %ebp 4/r32/esp -8687 # setup -8688 (clear-stream _test-output-stream) -8689 (clear-stream $_test-output-buffered-file->buffer) -8690 # var type/ecx: (handle tree type-id) = int -8691 68/push 0/imm32/right/null -8692 68/push 1/imm32/left/int -8693 89/<- %ecx 4/r32/esp -8694 # var var-foo/ecx: var -8695 68/push 0/imm32/no-register -8696 68/push -8/imm32/stack-offset -8697 68/push 0/imm32/block-depth -8698 51/push-ecx -8699 68/push "foo"/imm32 -8700 89/<- %ecx 4/r32/esp -8701 # var operands/esi: (list var) +8672 # . prologue +8673 55/push-ebp +8674 89/<- %ebp 4/r32/esp +8675 # setup +8676 (clear-stream _test-output-stream) +8677 (clear-stream $_test-output-buffered-file->buffer) +8678 # var type/ecx: (handle tree type-id) = int +8679 68/push 0/imm32/right/null +8680 68/push 1/imm32/left/int +8681 89/<- %ecx 4/r32/esp +8682 # var var-var1/ecx: var +8683 68/push 0/imm32/no-register +8684 68/push 8/imm32/stack-offset +8685 68/push 1/imm32/block-depth +8686 51/push-ecx +8687 68/push "var1"/imm32 +8688 89/<- %ecx 4/r32/esp +8689 # var type/edx: (handle tree type-id) = literal +8690 68/push 0/imm32/right/null +8691 68/push 0/imm32/left/literal +8692 89/<- %edx 4/r32/esp +8693 # var var-var2/edx: var literal +8694 68/push 0/imm32/no-register +8695 68/push 0/imm32/no-stack-offset +8696 68/push 1/imm32/block-depth +8697 52/push-edx +8698 68/push "0x34"/imm32 +8699 89/<- %edx 4/r32/esp +8700 # var inouts/esi: (handle stmt-var) = [var2] +8701 68/push 0/imm32/is-deref:false 8702 68/push 0/imm32/next -8703 51/push-ecx/var-foo +8703 52/push-edx/var-var2 8704 89/<- %esi 4/r32/esp -8705 # var stmt/esi: statement -8706 68/push 0/imm32/next -8707 68/push 0/imm32/outputs -8708 56/push-esi/inouts -8709 68/push "f"/imm32/operation -8710 68/push 1/imm32 -8711 89/<- %esi 4/r32/esp -8712 # var functions/ebx: function -8713 68/push 0/imm32/next -8714 68/push 0/imm32/body -8715 68/push 0/imm32/outputs -8716 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -8717 68/push "f2"/imm32/subx-name -8718 68/push "f"/imm32/name -8719 89/<- %ebx 4/r32/esp -8720 # convert -8721 c7 0/subop/copy *Curr-block-depth 0/imm32 -8722 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) -8723 (flush _test-output-buffered-file) -8724 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8730 # check output -8731 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-statement-function-call") -8732 # . epilogue -8733 89/<- %esp 5/r32/ebp -8734 5d/pop-to-ebp -8735 c3/return -8736 -8737 test-emit-subx-statement-function-call-with-literal-arg: -8738 # Call a function on a literal. -8739 # f 34 -8740 # => -8741 # (f2 34) -8742 # -8743 # . prologue -8744 55/push-ebp -8745 89/<- %ebp 4/r32/esp -8746 # setup -8747 (clear-stream _test-output-stream) -8748 (clear-stream $_test-output-buffered-file->buffer) -8749 # var type/ecx: (handle tree type-id) = literal -8750 68/push 0/imm32/right/null -8751 68/push 0/imm32/left/literal -8752 89/<- %ecx 4/r32/esp -8753 # var var-foo/ecx: var literal -8754 68/push 0/imm32/no-register -8755 68/push 0/imm32/no-stack-offset -8756 68/push 0/imm32/block-depth -8757 51/push-ecx -8758 68/push "34"/imm32 -8759 89/<- %ecx 4/r32/esp -8760 # var operands/esi: (list var) -8761 68/push 0/imm32/next -8762 51/push-ecx/var-foo -8763 89/<- %esi 4/r32/esp -8764 # var stmt/esi: statement -8765 68/push 0/imm32/next -8766 68/push 0/imm32/outputs -8767 56/push-esi/inouts -8768 68/push "f"/imm32/operation -8769 68/push 1/imm32 -8770 89/<- %esi 4/r32/esp -8771 # var functions/ebx: function -8772 68/push 0/imm32/next -8773 68/push 0/imm32/body -8774 68/push 0/imm32/outputs -8775 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -8776 68/push "f2"/imm32/subx-name -8777 68/push "f"/imm32/name -8778 89/<- %ebx 4/r32/esp -8779 # convert -8780 c7 0/subop/copy *Curr-block-depth 0/imm32 -8781 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) -8782 (flush _test-output-buffered-file) -8783 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8789 # check output -8790 (check-next-stream-line-equal _test-output-stream "(f2 34)" "F - test-emit-subx-statement-function-call-with-literal-arg") -8791 # . epilogue -8792 89/<- %esp 5/r32/ebp -8793 5d/pop-to-ebp -8794 c3/return -8795 -8796 emit-indent: # out: (addr buffered-file), n: int -8797 # . prologue -8798 55/push-ebp -8799 89/<- %ebp 4/r32/esp -8800 # . save registers -8801 50/push-eax -8802 # var i/eax: int = n -8803 8b/-> *(ebp+0xc) 0/r32/eax -8804 { -8805 # if (i <= 0) break -8806 3d/compare-eax-with 0/imm32 -8807 7e/jump-if-<= break/disp8 -8808 (write-buffered *(ebp+8) " ") -8809 48/decrement-eax -8810 eb/jump loop/disp8 -8811 } -8812 $emit-indent:end: -8813 # . restore registers -8814 58/pop-to-eax -8815 # . epilogue -8816 89/<- %esp 5/r32/ebp -8817 5d/pop-to-ebp -8818 c3/return -8819 -8820 emit-subx-prologue: # out: (addr buffered-file) -8821 # . prologue -8822 55/push-ebp -8823 89/<- %ebp 4/r32/esp -8824 # -8825 (write-buffered *(ebp+8) " # . prologue\n") -8826 (write-buffered *(ebp+8) " 55/push-ebp\n") -8827 (write-buffered *(ebp+8) " 89/<- %ebp 4/r32/esp\n") -8828 $emit-subx-prologue:end: -8829 # . epilogue -8830 89/<- %esp 5/r32/ebp -8831 5d/pop-to-ebp -8832 c3/return -8833 -8834 emit-subx-epilogue: # out: (addr buffered-file) -8835 # . prologue -8836 55/push-ebp -8837 89/<- %ebp 4/r32/esp -8838 # -8839 (write-buffered *(ebp+8) " # . epilogue\n") -8840 (write-buffered *(ebp+8) " 89/<- %esp 5/r32/ebp\n") -8841 (write-buffered *(ebp+8) " 5d/pop-to-ebp\n") -8842 (write-buffered *(ebp+8) " c3/return\n") -8843 $emit-subx-epilogue:end: -8844 # . epilogue -8845 89/<- %esp 5/r32/ebp -8846 5d/pop-to-ebp -8847 c3/return +8705 # inouts = [var1, var2] +8706 68/push 0/imm32/is-deref:false +8707 56/push-esi/next +8708 51/push-ecx/var-var1 +8709 89/<- %esi 4/r32/esp +8710 # var stmt/esi: statement +8711 68/push 0/imm32/next +8712 68/push 0/imm32/outputs +8713 56/push-esi/inouts +8714 68/push "compare"/imm32/operation +8715 68/push 1/imm32 +8716 89/<- %esi 4/r32/esp +8717 # convert +8718 c7 0/subop/copy *Curr-block-depth 0/imm32 +8719 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8720 (flush _test-output-buffered-file) +8721 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8727 # check output +8728 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") +8729 # . epilogue +8730 89/<- %esp 5/r32/ebp +8731 5d/pop-to-ebp +8732 c3/return +8733 +8734 test-compare-eax-with-literal: +8735 # compare var1/eax 0x34 +8736 # => +8737 # 3d/compare-eax-with 0x34/imm32 +8738 # +8739 # . prologue +8740 55/push-ebp +8741 89/<- %ebp 4/r32/esp +8742 # setup +8743 (clear-stream _test-output-stream) +8744 (clear-stream $_test-output-buffered-file->buffer) +8745 # var type/ecx: (handle tree type-id) = int +8746 68/push 0/imm32/right/null +8747 68/push 1/imm32/left/int +8748 89/<- %ecx 4/r32/esp +8749 # var var-var1/ecx: var in eax +8750 68/push "eax"/imm32/register +8751 68/push 0/imm32/no-stack-offset +8752 68/push 1/imm32/block-depth +8753 51/push-ecx +8754 68/push "var1"/imm32 +8755 89/<- %ecx 4/r32/esp +8756 # var type/edx: (handle tree type-id) = literal +8757 68/push 0/imm32/right/null +8758 68/push 0/imm32/left/literal +8759 89/<- %edx 4/r32/esp +8760 # var var-var2/edx: var literal +8761 68/push 0/imm32/no-register +8762 68/push 0/imm32/no-stack-offset +8763 68/push 1/imm32/block-depth +8764 52/push-edx +8765 68/push "0x34"/imm32 +8766 89/<- %edx 4/r32/esp +8767 # var inouts/esi: (handle stmt-var) = [var2] +8768 68/push 0/imm32/is-deref:false +8769 68/push 0/imm32/next +8770 52/push-edx/var-var2 +8771 89/<- %esi 4/r32/esp +8772 # inouts = [var1, var2] +8773 68/push 0/imm32/is-deref:false +8774 56/push-esi/next +8775 51/push-ecx/var-var1 +8776 89/<- %esi 4/r32/esp +8777 # var stmt/esi: statement +8778 68/push 0/imm32/next +8779 68/push 0/imm32/outputs +8780 56/push-esi/inouts +8781 68/push "compare"/imm32/operation +8782 68/push 1/imm32/regular-stmt +8783 89/<- %esi 4/r32/esp +8784 # convert +8785 c7 0/subop/copy *Curr-block-depth 0/imm32 +8786 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8787 (flush _test-output-buffered-file) +8788 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8794 # check output +8795 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") +8796 # . epilogue +8797 89/<- %esp 5/r32/ebp +8798 5d/pop-to-ebp +8799 c3/return +8800 +8801 test-compare-reg-with-literal: +8802 # compare var1/ecx 0x34 +8803 # => +8804 # 81 7/subop/compare %ecx 0x34/imm32 +8805 # +8806 # . prologue +8807 55/push-ebp +8808 89/<- %ebp 4/r32/esp +8809 # setup +8810 (clear-stream _test-output-stream) +8811 (clear-stream $_test-output-buffered-file->buffer) +8812 # var type/ecx: (handle tree type-id) = int +8813 68/push 0/imm32/right/null +8814 68/push 1/imm32/left/int +8815 89/<- %ecx 4/r32/esp +8816 # var var-var1/ecx: var in ecx +8817 68/push "ecx"/imm32/register +8818 68/push 0/imm32/no-stack-offset +8819 68/push 1/imm32/block-depth +8820 51/push-ecx +8821 68/push "var1"/imm32 +8822 89/<- %ecx 4/r32/esp +8823 # var type/edx: (handle tree type-id) = literal +8824 68/push 0/imm32/right/null +8825 68/push 0/imm32/left/literal +8826 89/<- %edx 4/r32/esp +8827 # var var-var2/edx: var literal +8828 68/push 0/imm32/no-register +8829 68/push 0/imm32/no-stack-offset +8830 68/push 1/imm32/block-depth +8831 52/push-edx +8832 68/push "0x34"/imm32 +8833 89/<- %edx 4/r32/esp +8834 # var inouts/esi: (handle stmt-var) = [var2] +8835 68/push 0/imm32/is-deref:false +8836 68/push 0/imm32/next +8837 52/push-edx/var-var2 +8838 89/<- %esi 4/r32/esp +8839 # inouts = [var1, var2] +8840 68/push 0/imm32/is-deref:false +8841 56/push-esi/next +8842 51/push-ecx/var-var1 +8843 89/<- %esi 4/r32/esp +8844 # var stmt/esi: statement +8845 68/push 0/imm32/next +8846 68/push 0/imm32/outputs +8847 56/push-esi/inouts +8848 68/push "compare"/imm32/operation +8849 68/push 1/imm32/regular-stmt +8850 89/<- %esi 4/r32/esp +8851 # convert +8852 c7 0/subop/copy *Curr-block-depth 0/imm32 +8853 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8854 (flush _test-output-buffered-file) +8855 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8861 # check output +8862 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") +8863 # . epilogue +8864 89/<- %esp 5/r32/ebp +8865 5d/pop-to-ebp +8866 c3/return +8867 +8868 test-emit-subx-statement-function-call: +8869 # Call a function on a variable on the stack. +8870 # f foo +8871 # => +8872 # (f2 *(ebp-8)) +8873 # (Changing the function name supports overloading in general, but here it +8874 # just serves to help disambiguate things.) +8875 # +8876 # There's a variable on the var stack as follows: +8877 # name: 'foo' +8878 # type: int +8879 # stack-offset: -8 +8880 # +8881 # There's nothing in primitives. +8882 # +8883 # There's a function with this info: +8884 # name: 'f' +8885 # inout: int/mem +8886 # value: 'f2' +8887 # +8888 # . prologue +8889 55/push-ebp +8890 89/<- %ebp 4/r32/esp +8891 # setup +8892 (clear-stream _test-output-stream) +8893 (clear-stream $_test-output-buffered-file->buffer) +8894 # var type/ecx: (handle tree type-id) = int +8895 68/push 0/imm32/right/null +8896 68/push 1/imm32/left/int +8897 89/<- %ecx 4/r32/esp +8898 # var var-foo/ecx: var +8899 68/push 0/imm32/no-register +8900 68/push -8/imm32/stack-offset +8901 68/push 0/imm32/block-depth +8902 51/push-ecx +8903 68/push "foo"/imm32 +8904 89/<- %ecx 4/r32/esp +8905 # var inouts/esi: (handle stmt-var) +8906 68/push 0/imm32/is-deref:false +8907 68/push 0/imm32/next +8908 51/push-ecx/var-foo +8909 89/<- %esi 4/r32/esp +8910 # var stmt/esi: statement +8911 68/push 0/imm32/next +8912 68/push 0/imm32/outputs +8913 56/push-esi/inouts +8914 68/push "f"/imm32/operation +8915 68/push 1/imm32 +8916 89/<- %esi 4/r32/esp +8917 # var functions/ebx: function +8918 68/push 0/imm32/next +8919 68/push 0/imm32/body +8920 68/push 0/imm32/outputs +8921 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call +8922 68/push "f2"/imm32/subx-name +8923 68/push "f"/imm32/name +8924 89/<- %ebx 4/r32/esp +8925 # convert +8926 c7 0/subop/copy *Curr-block-depth 0/imm32 +8927 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) +8928 (flush _test-output-buffered-file) +8929 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8935 # check output +8936 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-statement-function-call") +8937 # . epilogue +8938 89/<- %esp 5/r32/ebp +8939 5d/pop-to-ebp +8940 c3/return +8941 +8942 test-emit-subx-statement-function-call-with-literal-arg: +8943 # Call a function on a literal. +8944 # f 34 +8945 # => +8946 # (f2 34) +8947 # +8948 # . prologue +8949 55/push-ebp +8950 89/<- %ebp 4/r32/esp +8951 # setup +8952 (clear-stream _test-output-stream) +8953 (clear-stream $_test-output-buffered-file->buffer) +8954 # var type/ecx: (handle tree type-id) = literal +8955 68/push 0/imm32/right/null +8956 68/push 0/imm32/left/literal +8957 89/<- %ecx 4/r32/esp +8958 # var var-foo/ecx: var literal +8959 68/push 0/imm32/no-register +8960 68/push 0/imm32/no-stack-offset +8961 68/push 0/imm32/block-depth +8962 51/push-ecx +8963 68/push "34"/imm32 +8964 89/<- %ecx 4/r32/esp +8965 # var inouts/esi: (handle stmt-var) +8966 68/push 0/imm32/is-deref:false +8967 68/push 0/imm32/next +8968 51/push-ecx/var-foo +8969 89/<- %esi 4/r32/esp +8970 # var stmt/esi: statement +8971 68/push 0/imm32/next +8972 68/push 0/imm32/outputs +8973 56/push-esi/inouts +8974 68/push "f"/imm32/operation +8975 68/push 1/imm32 +8976 89/<- %esi 4/r32/esp +8977 # var functions/ebx: function +8978 68/push 0/imm32/next +8979 68/push 0/imm32/body +8980 68/push 0/imm32/outputs +8981 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call +8982 68/push "f2"/imm32/subx-name +8983 68/push "f"/imm32/name +8984 89/<- %ebx 4/r32/esp +8985 # convert +8986 c7 0/subop/copy *Curr-block-depth 0/imm32 +8987 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) +8988 (flush _test-output-buffered-file) +8989 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8995 # check output +8996 (check-next-stream-line-equal _test-output-stream "(f2 34)" "F - test-emit-subx-statement-function-call-with-literal-arg") +8997 # . epilogue +8998 89/<- %esp 5/r32/ebp +8999 5d/pop-to-ebp +9000 c3/return +9001 +9002 emit-indent: # out: (addr buffered-file), n: int +9003 # . prologue +9004 55/push-ebp +9005 89/<- %ebp 4/r32/esp +9006 # . save registers +9007 50/push-eax +9008 # var i/eax: int = n +9009 8b/-> *(ebp+0xc) 0/r32/eax +9010 { +9011 # if (i <= 0) break +9012 3d/compare-eax-with 0/imm32 +9013 7e/jump-if-<= break/disp8 +9014 (write-buffered *(ebp+8) " ") +9015 48/decrement-eax +9016 eb/jump loop/disp8 +9017 } +9018 $emit-indent:end: +9019 # . restore registers +9020 58/pop-to-eax +9021 # . epilogue +9022 89/<- %esp 5/r32/ebp +9023 5d/pop-to-ebp +9024 c3/return +9025 +9026 emit-subx-prologue: # out: (addr buffered-file) +9027 # . prologue +9028 55/push-ebp +9029 89/<- %ebp 4/r32/esp +9030 # +9031 (write-buffered *(ebp+8) " # . prologue\n") +9032 (write-buffered *(ebp+8) " 55/push-ebp\n") +9033 (write-buffered *(ebp+8) " 89/<- %ebp 4/r32/esp\n") +9034 $emit-subx-prologue:end: +9035 # . epilogue +9036 89/<- %esp 5/r32/ebp +9037 5d/pop-to-ebp +9038 c3/return +9039 +9040 emit-subx-epilogue: # out: (addr buffered-file) +9041 # . prologue +9042 55/push-ebp +9043 89/<- %ebp 4/r32/esp +9044 # +9045 (write-buffered *(ebp+8) " # . epilogue\n") +9046 (write-buffered *(ebp+8) " 89/<- %esp 5/r32/ebp\n") +9047 (write-buffered *(ebp+8) " 5d/pop-to-ebp\n") +9048 (write-buffered *(ebp+8) " c3/return\n") +9049 $emit-subx-epilogue:end: +9050 # . epilogue +9051 89/<- %esp 5/r32/ebp +9052 5d/pop-to-ebp +9053 c3/return -- cgit 1.4.1-2-gfad0