From 510a5429ca20b14b499ab9551ddbead660b23aeb Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Thu, 27 Feb 2020 16:47:40 -0800 Subject: 6056 --- html/apps/mu.subx.html | 17532 +++++++++++++++++++++++--------------------- html/apps/tests.subx.html | 2 +- 2 files changed, 9028 insertions(+), 8506 deletions(-) (limited to 'html/apps') diff --git a/html/apps/mu.subx.html b/html/apps/mu.subx.html index 36707012..2d4f8c3d 100644 --- a/html/apps/mu.subx.html +++ b/html/apps/mu.subx.html @@ -16,13 +16,13 @@ a { color:inherit; } * { font-size:12pt; font-size: 1em; } .subxComment { color: #005faf; } .subxFunction { color: #af5f00; text-decoration: underline; } -.subxMinorFunction { color: #875f5f; } +.Folded { color: #080808; background-color: #949494; } .LineNr { } .subxS1Comment { color: #0000af; } .CommentedCode { color: #8a8a8a; } .SpecialChar { color: #d70000; } .Constant { color: #008787; } -.Folded { color: #080808; background-color: #949494; } +.subxMinorFunction { color: #875f5f; } .subxTest { color: #5f8700; } .subxH1Comment { color: #005faf; text-decoration: underline; } --> @@ -170,7 +170,7 @@ if ('onhashchange' in window) { 108 # 109 # A block contains: 110 # tag: 0 - 111 # statements: (handle list statement) + 111 # statements: (handle list stmt) 112 # name: (handle array byte) -- starting with '$' 113 # 114 # A regular statement contains: @@ -302,8524 +302,9046 @@ if ('onhashchange' in window) { 240 241 == data 242 - 243 Program: # (handle function) - 244 0/imm32 - 245 - 246 Function-name: + 243 Program: + 244 _Program-functions: # (handle function) + 245 0/imm32 + 246 _Program-types: # (handle typeinfo) 247 0/imm32 - 248 Function-subx-name: - 249 4/imm32 - 250 Function-inouts: # (handle list var) - 251 8/imm32 - 252 Function-outputs: # (handle list var) - 253 0xc/imm32 - 254 Function-body: # (handle block) - 255 0x10/imm32 - 256 Function-next: # (handle function) - 257 0x14/imm32 - 258 Function-size: # (addr int) - 259 0x18/imm32/24 - 260 - 261 Primitive-name: - 262 0/imm32 - 263 Primitive-inouts: # (handle list var) - 264 4/imm32 - 265 Primitive-outputs: # (handle list var) - 266 8/imm32 - 267 Primitive-subx-name: # (handle array byte) - 268 0xc/imm32 - 269 Primitive-subx-rm32: # enum arg-location - 270 0x10/imm32 - 271 Primitive-subx-r32: # enum arg-location - 272 0x14/imm32 - 273 Primitive-subx-imm32: # enum arg-location - 274 0x18/imm32 - 275 Primitive-subx-disp32: # enum arg-location -- only for branches - 276 0x1c/imm32 - 277 Primitive-output-is-write-only: # boolean - 278 0x20/imm32 - 279 Primitive-next: # (handle function) - 280 0x24/imm32 - 281 Primitive-size: # (addr int) - 282 0x28/imm32/36 - 283 - 284 Stmt-tag: - 285 0/imm32 - 286 - 287 Block-statements: # (handle list statement) - 288 4/imm32 - 289 Block-var: # (handle var) - 290 8/imm32 - 291 - 292 Stmt1-operation: # (handle array byte) - 293 4/imm32 - 294 Stmt1-inouts: # (handle stmt-var) - 295 8/imm32 - 296 Stmt1-outputs: # (handle stmt-var) - 297 0xc/imm32 - 298 - 299 Vardef-var: # (handle var) - 300 4/imm32 - 301 - 302 Regvardef-operation: # (handle array byte) - 303 4/imm32 - 304 Regvardef-inouts: # (handle stmt-var) - 305 8/imm32 - 306 Regvardef-outputs: # (handle stmt-var) # will have exactly one element - 307 0xc/imm32 - 308 - 309 Stmt-size: # (addr int) - 310 0x10/imm32 - 311 - 312 Var-name: - 313 0/imm32 - 314 Var-type: - 315 4/imm32 - 316 Var-block-depth: - 317 8/imm32 - 318 Var-stack-offset: - 319 0xc/imm32 - 320 Var-register: - 321 0x10/imm32 - 322 Var-size: # (addr int) - 323 0x14/imm32 - 324 - 325 Any-register: # wildcard - 326 # size - 327 1/imm32 - 328 # data - 329 2a/asterisk - 330 - 331 List-value: - 332 0/imm32 - 333 List-next: - 334 4/imm32 - 335 List-size: # (addr int) - 336 8/imm32 - 337 - 338 # A stmt-var is like a list of vars with call-site specific metadata - 339 Stmt-var-value: # (handle var) - 340 0/imm32 - 341 Stmt-var-next: # (handle stmt-var) - 342 4/imm32 - 343 Stmt-var-is-deref: # boolean - 344 8/imm32 - 345 Stmt-var-size: # (addr int) - 346 0xc/imm32 - 347 - 348 # Types are expressed as trees (s-expressions) of type-ids (ints). - 349 # However, there's no need for singletons, so we can assume (int) == int - 350 # - if x->right == nil, x is an atom - 351 # - x->left contains either a pointer to a pair, or an atomic type-id directly. - 352 # type ids will be less than 0x10000 (MAX_TYPE_ID). - 353 - 354 Tree-left: # either type-id or (addr tree type-id) - 355 0/imm32 - 356 Tree-right: # (addr tree type-id) - 357 4/imm32 - 358 Tree-size: # (addr int) - 359 8/imm32 - 360 - 361 Max-type-id: - 362 0x10000/imm32 - 363 - 364 == code - 365 - 366 Entry: - 367 # . prologue - 368 89/<- %ebp 4/r32/esp - 369 (new-segment *Heap-size Heap) - 370 # if (argv[1] == "test') run-tests() - 371 { - 372 # if (argc <= 1) break - 373 81 7/subop/compare *ebp 1/imm32 - 374 7e/jump-if-<= break/disp8 - 375 # if (argv[1] != "test") break - 376 (kernel-string-equal? *(ebp+8) "test") # => eax - 377 3d/compare-eax-and 0/imm32/false - 378 74/jump-if-= break/disp8 - 379 # - 380 (run-tests) - 381 # syscall(exit, *Num-test-failures) - 382 8b/-> *Num-test-failures 3/r32/ebx - 383 eb/jump $mu-main:end/disp8 - 384 } - 385 # otherwise convert Stdin - 386 (convert-mu Stdin Stdout) - 387 (flush Stdout) - 388 # syscall(exit, 0) - 389 bb/copy-to-ebx 0/imm32 - 390 $mu-main:end: - 391 b8/copy-to-eax 1/imm32/exit - 392 cd/syscall 0x80/imm8 - 393 - 394 convert-mu: # in: (addr buffered-file), out: (addr buffered-file) - 395 # . prologue - 396 55/push-ebp - 397 89/<- %ebp 4/r32/esp - 398 # - 399 (parse-mu *(ebp+8)) - 400 (check-mu-types) - 401 (emit-subx *(ebp+0xc)) - 402 $convert-mu:end: - 403 # . epilogue - 404 89/<- %esp 5/r32/ebp - 405 5d/pop-to-ebp - 406 c3/return - 407 - 408 test-convert-empty-input: - 409 # empty input => empty output - 410 # . prologue - 411 55/push-ebp - 412 89/<- %ebp 4/r32/esp - 413 # setup - 414 (clear-stream _test-input-stream) - 415 (clear-stream $_test-input-buffered-file->buffer) - 416 (clear-stream _test-output-stream) - 417 (clear-stream $_test-output-buffered-file->buffer) - 418 # - 419 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 420 (flush _test-output-buffered-file) - 421 (check-stream-equal _test-output-stream "" "F - test-convert-empty-input") - 422 # . epilogue - 423 89/<- %esp 5/r32/ebp - 424 5d/pop-to-ebp - 425 c3/return - 426 - 427 test-convert-function-skeleton: - 428 # . prologue - 429 55/push-ebp - 430 89/<- %ebp 4/r32/esp - 431 # setup - 432 (clear-stream _test-input-stream) - 433 (clear-stream $_test-input-buffered-file->buffer) - 434 (clear-stream _test-output-stream) - 435 (clear-stream $_test-output-buffered-file->buffer) - 436 # - 437 (write _test-input-stream "fn foo {\n") - 438 (write _test-input-stream "}\n") - 439 # convert - 440 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 441 (flush _test-output-buffered-file) - 442 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 448 # check output - 449 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-skeleton/0") - 450 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-skeleton/1") - 451 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-skeleton/2") - 452 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-skeleton/3") - 453 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-skeleton/4") - 454 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-skeleton/5") - 455 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-skeleton/6") - 456 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-skeleton/7") - 457 # . epilogue - 458 89/<- %esp 5/r32/ebp - 459 5d/pop-to-ebp - 460 c3/return - 461 - 462 test-convert-multiple-function-skeletons: - 463 # . prologue - 464 55/push-ebp - 465 89/<- %ebp 4/r32/esp - 466 # setup - 467 (clear-stream _test-input-stream) - 468 (clear-stream $_test-input-buffered-file->buffer) - 469 (clear-stream _test-output-stream) - 470 (clear-stream $_test-output-buffered-file->buffer) - 471 # - 472 (write _test-input-stream "fn foo {\n") - 473 (write _test-input-stream "}\n") - 474 (write _test-input-stream "fn bar {\n") - 475 (write _test-input-stream "}\n") - 476 # convert - 477 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 478 (flush _test-output-buffered-file) - 479 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 485 # check first function - 486 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-multiple-function-skeletons/0") - 487 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/1") - 488 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/2") - 489 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/3") - 490 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/4") - 491 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/5") - 492 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/6") - 493 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/7") - 494 # check second function - 495 (check-next-stream-line-equal _test-output-stream "bar:" "F - test-convert-multiple-function-skeletons/10") - 496 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/11") - 497 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/12") - 498 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/13") - 499 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/14") - 500 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/15") - 501 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/16") - 502 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/17") - 503 # . epilogue - 504 89/<- %esp 5/r32/ebp - 505 5d/pop-to-ebp - 506 c3/return - 507 - 508 test-convert-function-with-arg: - 509 # . prologue - 510 55/push-ebp - 511 89/<- %ebp 4/r32/esp - 512 # setup - 513 (clear-stream _test-input-stream) - 514 (clear-stream $_test-input-buffered-file->buffer) - 515 (clear-stream _test-output-stream) - 516 (clear-stream $_test-output-buffered-file->buffer) - 517 # - 518 (write _test-input-stream "fn foo n: int {\n") - 519 (write _test-input-stream "}\n") - 520 # convert - 521 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 522 (flush _test-output-buffered-file) - 523 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 529 # check output - 530 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg/0") - 531 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg/1") - 532 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg/2") - 533 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg/3") - 534 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg/4") - 535 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg/5") - 536 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg/6") - 537 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg/7") - 538 # . epilogue - 539 89/<- %esp 5/r32/ebp - 540 5d/pop-to-ebp - 541 c3/return - 542 - 543 test-convert-function-with-arg-and-body: - 544 # . prologue - 545 55/push-ebp - 546 89/<- %ebp 4/r32/esp - 547 # setup - 548 (clear-stream _test-input-stream) - 549 (clear-stream $_test-input-buffered-file->buffer) - 550 (clear-stream _test-output-stream) - 551 (clear-stream $_test-output-buffered-file->buffer) - 552 c7 0/subop/copy *Next-block-index 1/imm32 - 553 # - 554 (write _test-input-stream "fn foo n: int {\n") - 555 (write _test-input-stream " increment n\n") - 556 (write _test-input-stream "}\n") - 557 # convert - 558 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 559 (flush _test-output-buffered-file) - 560 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 566 # check output - 567 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg-and-body/0") - 568 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg-and-body/1") - 569 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg-and-body/2") - 570 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg-and-body/3") - 571 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-arg-and-body/4") - 572 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-arg-and-body/5") - 573 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-arg-and-body/6") - 574 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-arg-and-body/7") - 575 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-arg-and-body/8") - 576 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg-and-body/9") - 577 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg-and-body/10") - 578 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg-and-body/11") - 579 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg-and-body/12") - 580 # . epilogue - 581 89/<- %esp 5/r32/ebp - 582 5d/pop-to-ebp - 583 c3/return - 584 - 585 test-convert-function-distinguishes-args: - 586 # . prologue - 587 55/push-ebp - 588 89/<- %ebp 4/r32/esp - 589 # setup - 590 (clear-stream _test-input-stream) - 591 (clear-stream $_test-input-buffered-file->buffer) - 592 (clear-stream _test-output-stream) - 593 (clear-stream $_test-output-buffered-file->buffer) - 594 c7 0/subop/copy *Next-block-index 1/imm32 - 595 # - 596 (write _test-input-stream "fn foo a: int, b: int {\n") - 597 (write _test-input-stream " increment b\n") - 598 (write _test-input-stream "}\n") - 599 # convert - 600 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 601 (flush _test-output-buffered-file) - 602 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 608 # check output - 609 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-distinguishes-args/0") - 610 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-distinguishes-args/1") - 611 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-distinguishes-args/2") - 612 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-distinguishes-args/3") - 613 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-distinguishes-args/4") - 614 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-distinguishes-args/5") - 615 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x0000000c)" "F - test-convert-function-distinguishes-args/6") - 616 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-distinguishes-args/7") - 617 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-distinguishes-args/8") - 618 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-distinguishes-args/9") - 619 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-distinguishes-args/10") - 620 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-distinguishes-args/11") - 621 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-distinguishes-args/12") - 622 # . epilogue - 623 89/<- %esp 5/r32/ebp - 624 5d/pop-to-ebp - 625 c3/return - 626 - 627 test-convert-function-returns-result: - 628 # . prologue - 629 55/push-ebp - 630 89/<- %ebp 4/r32/esp - 631 # setup - 632 (clear-stream _test-input-stream) - 633 (clear-stream $_test-input-buffered-file->buffer) - 634 (clear-stream _test-output-stream) - 635 (clear-stream $_test-output-buffered-file->buffer) - 636 c7 0/subop/copy *Next-block-index 1/imm32 - 637 # - 638 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") - 639 (write _test-input-stream " result <- copy a\n") - 640 (write _test-input-stream " result <- increment\n") - 641 (write _test-input-stream "}\n") - 642 # convert - 643 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 644 (flush _test-output-buffered-file) - 645 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 651 # check output - 652 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-returns-result/0") - 653 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-returns-result/1") - 654 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-returns-result/2") - 655 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-returns-result/3") - 656 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-returns-result/4") - 657 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-returns-result/5") - 658 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-returns-result/6") - 659 (check-next-stream-line-equal _test-output-stream " 40/increment-eax" "F - test-convert-function-returns-result/7") - 660 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-returns-result/8") - 661 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-returns-result/9") - 662 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-returns-result/10") - 663 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-returns-result/11") - 664 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-returns-result/12") - 665 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-returns-result/13") - 666 # . epilogue - 667 89/<- %esp 5/r32/ebp - 668 5d/pop-to-ebp - 669 c3/return - 670 - 671 test-convert-function-literal-arg: - 672 # . prologue - 673 55/push-ebp - 674 89/<- %ebp 4/r32/esp - 675 # setup - 676 (clear-stream _test-input-stream) - 677 (clear-stream $_test-input-buffered-file->buffer) - 678 (clear-stream _test-output-stream) - 679 (clear-stream $_test-output-buffered-file->buffer) - 680 c7 0/subop/copy *Next-block-index 1/imm32 - 681 # - 682 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") - 683 (write _test-input-stream " result <- copy a\n") - 684 (write _test-input-stream " result <- add 1\n") - 685 (write _test-input-stream "}\n") - 686 # convert - 687 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 688 (flush _test-output-buffered-file) - 689 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 695 # check output - 696 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-literal-arg/0") - 697 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-literal-arg/1") - 698 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-literal-arg/2") - 699 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-literal-arg/3") - 700 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-literal-arg/4") - 701 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-literal-arg/5") - 702 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-literal-arg/6") - 703 (check-next-stream-line-equal _test-output-stream " 05/add-to-eax 1/imm32" "F - test-convert-function-literal-arg/7") - 704 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-literal-arg/8") - 705 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-literal-arg/9") - 706 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-literal-arg/10") - 707 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-literal-arg/11") - 708 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-literal-arg/12") - 709 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-literal-arg/13") - 710 # . epilogue - 711 89/<- %esp 5/r32/ebp - 712 5d/pop-to-ebp - 713 c3/return - 714 - 715 test-convert-function-literal-arg-2: - 716 # . prologue - 717 55/push-ebp - 718 89/<- %ebp 4/r32/esp - 719 # setup - 720 (clear-stream _test-input-stream) - 721 (clear-stream $_test-input-buffered-file->buffer) - 722 (clear-stream _test-output-stream) - 723 (clear-stream $_test-output-buffered-file->buffer) - 724 c7 0/subop/copy *Next-block-index 1/imm32 - 725 # - 726 (write _test-input-stream "fn foo a: int, b: int -> result/ebx: int {\n") - 727 (write _test-input-stream " result <- copy a\n") - 728 (write _test-input-stream " result <- add 1\n") - 729 (write _test-input-stream "}\n") - 730 # convert - 731 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 732 (flush _test-output-buffered-file) - 733 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 739 # check output - 740 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-literal-arg-2/0") - 741 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-literal-arg-2/1") - 742 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-literal-arg-2/2") - 743 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-literal-arg-2/3") - 744 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-literal-arg-2/4") - 745 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-literal-arg-2/5") - 746 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-literal-arg-2/6") - 747 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %ebx 1/imm32" "F - test-convert-function-literal-arg-2/7") - 748 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-literal-arg-2/8") - 749 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-literal-arg-2/9") - 750 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-literal-arg-2/10") - 751 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-literal-arg-2/11") - 752 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-literal-arg-2/12") - 753 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-literal-arg-2/13") - 754 # . epilogue - 755 89/<- %esp 5/r32/ebp - 756 5d/pop-to-ebp - 757 c3/return - 758 - 759 test-convert-function-call-with-literal-arg: - 760 # . prologue - 761 55/push-ebp - 762 89/<- %ebp 4/r32/esp - 763 # setup - 764 (clear-stream _test-input-stream) - 765 (clear-stream $_test-input-buffered-file->buffer) - 766 (clear-stream _test-output-stream) - 767 (clear-stream $_test-output-buffered-file->buffer) - 768 c7 0/subop/copy *Next-block-index 1/imm32 - 769 # - 770 (write _test-input-stream "fn main -> result/ebx: int {\n") - 771 (write _test-input-stream " result <- do-add 3 4\n") - 772 (write _test-input-stream "}\n") - 773 (write _test-input-stream "fn do-add a: int, b: int -> result/ebx: int {\n") - 774 (write _test-input-stream " result <- copy a\n") - 775 (write _test-input-stream " result <- add b\n") - 776 (write _test-input-stream "}\n") - 777 # convert - 778 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 779 (flush _test-output-buffered-file) - 780 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 786 # check output - 787 (check-next-stream-line-equal _test-output-stream "main:" "F - test-convert-function-call-with-literal-arg/0") - 788 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/1") - 789 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/2") - 790 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/3") - 791 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/4") - 792 (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:" "F - test-convert-function-call-with-literal-arg/5") - 793 (check-next-stream-line-equal _test-output-stream " (do-add 3 4)" "F - test-convert-function-call-with-literal-arg/6") - 794 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/7") - 795 (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/8") - 796 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/9") - 797 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/10") - 798 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/11") - 799 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/12") - 800 (check-next-stream-line-equal _test-output-stream "do-add:" "F - test-convert-function-call-with-literal-arg/13") - 801 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/14") - 802 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/15") - 803 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/16") - 804 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/17") - 805 (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:" "F - test-convert-function-call-with-literal-arg/18") - 806 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/19") - 807 (check-next-stream-line-equal _test-output-stream " 03/add *(ebp+0x0000000c) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/20") - 808 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/21") - 809 (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:" "F - test-convert-function-call-with-literal-arg/22") - 810 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/23") - 811 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/24") - 812 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/25") - 813 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/26") - 814 # . epilogue - 815 89/<- %esp 5/r32/ebp - 816 5d/pop-to-ebp - 817 c3/return - 818 - 819 test-convert-function-with-local-var-in-mem: - 820 # . prologue - 821 55/push-ebp - 822 89/<- %ebp 4/r32/esp - 823 # setup - 824 (clear-stream _test-input-stream) - 825 (clear-stream $_test-input-buffered-file->buffer) - 826 (clear-stream _test-output-stream) - 827 (clear-stream $_test-output-buffered-file->buffer) - 828 c7 0/subop/copy *Next-block-index 1/imm32 - 829 # - 830 (write _test-input-stream "fn foo {\n") - 831 (write _test-input-stream " var x: int\n") - 832 (write _test-input-stream " increment x\n") - 833 (write _test-input-stream "}\n") - 834 # convert - 835 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 836 (flush _test-output-buffered-file) - 837 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 843 # check output - 844 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-mem/0") - 845 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-mem/1") - 846 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-mem/2") - 847 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-mem/3") - 848 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-mem/4") - 849 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-mem/5") - 850 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-mem/6") - 851 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-mem/7") - 852 (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") - 853 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-mem/9") - 854 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-mem/10") - 855 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-mem/11") - 856 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-mem/12") - 857 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-mem/13") - 858 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-mem/14") - 859 # . epilogue - 860 89/<- %esp 5/r32/ebp - 861 5d/pop-to-ebp - 862 c3/return - 863 - 864 test-convert-function-with-local-var-in-reg: - 865 # . prologue - 866 55/push-ebp - 867 89/<- %ebp 4/r32/esp - 868 # setup - 869 (clear-stream _test-input-stream) - 870 (clear-stream $_test-input-buffered-file->buffer) - 871 (clear-stream _test-output-stream) - 872 (clear-stream $_test-output-buffered-file->buffer) - 873 c7 0/subop/copy *Next-block-index 1/imm32 - 874 # - 875 (write _test-input-stream "fn foo {\n") - 876 (write _test-input-stream " var x/ecx: int <- copy 3\n") - 877 (write _test-input-stream " x <- increment\n") - 878 (write _test-input-stream "}\n") - 879 # convert - 880 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 881 (flush _test-output-buffered-file) - 882 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 888 # check output - 889 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-reg/0") - 890 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-reg/1") - 891 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-reg/2") - 892 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-reg/3") - 893 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-reg/4") - 894 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-reg/5") - 895 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-local-var-in-reg/6") - 896 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-function-with-local-var-in-reg/7") - 897 (check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-convert-function-with-local-var-in-reg/8") - 898 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9") - 899 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-reg/10") - 900 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-reg/11") - 901 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-reg/12") - 902 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-reg/13") - 903 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-reg/14") - 904 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-reg/15") - 905 # . epilogue - 906 89/<- %esp 5/r32/ebp - 907 5d/pop-to-ebp - 908 c3/return - 909 - 910 test-convert-function-with-local-var-dereferenced: - 911 # . prologue - 912 55/push-ebp - 913 89/<- %ebp 4/r32/esp - 914 # setup - 915 (clear-stream _test-input-stream) - 916 (clear-stream $_test-input-buffered-file->buffer) - 917 (clear-stream _test-output-stream) - 918 (clear-stream $_test-output-buffered-file->buffer) - 919 c7 0/subop/copy *Next-block-index 1/imm32 - 920 # - 921 (write _test-input-stream "fn foo {\n") - 922 (write _test-input-stream " var x/ecx: (addr int) <- copy 0\n") - 923 (write _test-input-stream " increment *x\n") - 924 (write _test-input-stream "}\n") - 925 # convert - 926 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 927 (flush _test-output-buffered-file) - 928 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 934 # check output - 935 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-dereferenced/0") - 936 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-dereferenced/1") - 937 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-dereferenced/2") - 938 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-dereferenced/3") - 939 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-dereferenced/4") - 940 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-dereferenced/5") - 941 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-local-var-dereferenced/6") - 942 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-function-with-local-var-dereferenced/7") - 943 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *ecx" "F - test-convert-function-with-local-var-dereferenced/8") - 944 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9") - 945 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-dereferenced/10") - 946 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-dereferenced/11") - 947 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-dereferenced/12") - 948 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-dereferenced/13") - 949 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-dereferenced/14") - 950 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-dereferenced/15") - 951 # . epilogue - 952 89/<- %esp 5/r32/ebp - 953 5d/pop-to-ebp - 954 c3/return - 955 - 956 test-convert-compare-register-with-literal: - 957 # . prologue - 958 55/push-ebp - 959 89/<- %ebp 4/r32/esp - 960 # setup - 961 (clear-stream _test-input-stream) - 962 (clear-stream $_test-input-buffered-file->buffer) - 963 (clear-stream _test-output-stream) - 964 (clear-stream $_test-output-buffered-file->buffer) - 965 c7 0/subop/copy *Next-block-index 1/imm32 - 966 # - 967 (write _test-input-stream "fn foo {\n") - 968 (write _test-input-stream " var x/ecx: int <- copy 0\n") - 969 (write _test-input-stream " compare x, 0\n") - 970 (write _test-input-stream "}\n") - 971 # convert - 972 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 973 (flush _test-output-buffered-file) - 974 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 980 # check output - 981 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-compare-register-with-literal/0") - 982 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-compare-register-with-literal/1") - 983 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-compare-register-with-literal/2") - 984 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-compare-register-with-literal/3") - 985 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-compare-register-with-literal/4") - 986 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-compare-register-with-literal/5") - 987 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-compare-register-with-literal/6") - 988 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-compare-register-with-literal/7") - 989 (check-next-stream-line-equal _test-output-stream " 81 7/subop/compare %ecx 0/imm32" "F - test-convert-compare-register-with-literal/8") - 990 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9") - 991 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-compare-register-with-literal/10") - 992 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-compare-register-with-literal/11") - 993 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-compare-register-with-literal/12") - 994 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-compare-register-with-literal/13") - 995 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-compare-register-with-literal/14") - 996 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-compare-register-with-literal/15") - 997 # . epilogue - 998 89/<- %esp 5/r32/ebp - 999 5d/pop-to-ebp -1000 c3/return -1001 -1002 test-convert-function-with-local-var-in-block: -1003 # . prologue -1004 55/push-ebp -1005 89/<- %ebp 4/r32/esp -1006 # setup -1007 (clear-stream _test-input-stream) -1008 (clear-stream $_test-input-buffered-file->buffer) -1009 (clear-stream _test-output-stream) -1010 (clear-stream $_test-output-buffered-file->buffer) -1011 c7 0/subop/copy *Next-block-index 1/imm32 -1012 # -1013 (write _test-input-stream "fn foo {\n") -1014 (write _test-input-stream " {\n") -1015 (write _test-input-stream " var x: int\n") -1016 (write _test-input-stream " increment x\n") -1017 (write _test-input-stream " }\n") -1018 (write _test-input-stream "}\n") -1019 # convert -1020 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1021 (flush _test-output-buffered-file) -1022 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1028 # check output -1029 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-block/0") -1030 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-block/1") -1031 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-block/2") -1032 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-block/3") -1033 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/4") -1034 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-block/5") -1035 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/6") -1036 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-local-var-in-block/7") -1037 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-block/8") -1038 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-block/9") -1039 (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") -1040 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/11") -1041 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-local-var-in-block/12") -1042 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/13") -1043 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-block/14") -1044 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-block/15") -1045 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-block/16") -1046 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-block/17") -1047 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-block/18") -1048 # . epilogue -1049 89/<- %esp 5/r32/ebp -1050 5d/pop-to-ebp -1051 c3/return -1052 -1053 test-convert-function-with-local-var-in-named-block: -1054 # . prologue -1055 55/push-ebp -1056 89/<- %ebp 4/r32/esp -1057 # setup -1058 (clear-stream _test-input-stream) -1059 (clear-stream $_test-input-buffered-file->buffer) -1060 (clear-stream _test-output-stream) -1061 (clear-stream $_test-output-buffered-file->buffer) -1062 c7 0/subop/copy *Next-block-index 1/imm32 -1063 # -1064 (write _test-input-stream "fn foo {\n") -1065 (write _test-input-stream " $bar: {\n") -1066 (write _test-input-stream " var x: int\n") -1067 (write _test-input-stream " increment x\n") -1068 (write _test-input-stream " }\n") -1069 (write _test-input-stream "}\n") -1070 # convert -1071 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1072 (flush _test-output-buffered-file) -1073 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1079 # check output -1080 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-named-block/0") -1081 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-named-block/1") -1082 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-named-block/2") -1083 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-named-block/3") -1084 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/4") -1085 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-named-block/5") -1086 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/6") -1087 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-local-var-in-named-block/7") -1088 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-named-block/8") -1089 (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") -1090 (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") -1091 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/11") -1092 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-local-var-in-named-block/12") -1093 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/13") -1094 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-named-block/14") -1095 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-named-block/15") -1096 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-named-block/16") -1097 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-named-block/17") -1098 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-named-block/18") -1099 # . epilogue -1100 89/<- %esp 5/r32/ebp -1101 5d/pop-to-ebp -1102 c3/return -1103 -1104 test-convert-function-with-branches-in-block: -1105 # . prologue -1106 55/push-ebp -1107 89/<- %ebp 4/r32/esp -1108 # setup -1109 (clear-stream _test-input-stream) -1110 (clear-stream $_test-input-buffered-file->buffer) -1111 (clear-stream _test-output-stream) -1112 (clear-stream $_test-output-buffered-file->buffer) -1113 c7 0/subop/copy *Next-block-index 1/imm32 -1114 # -1115 (write _test-input-stream "fn foo x: int {\n") -1116 (write _test-input-stream " {\n") -1117 (write _test-input-stream " break-if->=\n") -1118 (write _test-input-stream " loop-if-addr<\n") + 248 + 249 # Some constants for simulating the data structures described above. + 250 # Many constants here come with a type in a comment. + 251 # + 252 # Sometimes the type is of the value at that offset for the given type. For + 253 # example, if you start at a function record and move forward Function-inouts + 254 # bytes, you'll find a (handle list var). + 255 # + 256 # At other times, the type is of the constant itself. For example, the type of + 257 # the constant Function-size is (addr int). To get the size of a function, + 258 # look in *Function-size. + 259 + 260 Function-name: # (handle array byte) + 261 0/imm32 + 262 Function-subx-name: # (handle array byte) + 263 4/imm32 + 264 Function-inouts: # (handle list var) + 265 8/imm32 + 266 Function-outputs: # (handle list var) + 267 0xc/imm32 + 268 Function-body: # (handle block) + 269 0x10/imm32 + 270 Function-next: # (handle function) + 271 0x14/imm32 + 272 Function-size: # (addr int) + 273 0x18/imm32/24 + 274 + 275 Primitive-name: # (handle array byte) + 276 0/imm32 + 277 Primitive-inouts: # (handle list var) + 278 4/imm32 + 279 Primitive-outputs: # (handle list var) + 280 8/imm32 + 281 Primitive-subx-name: # (handle array byte) + 282 0xc/imm32 + 283 Primitive-subx-rm32: # enum arg-location + 284 0x10/imm32 + 285 Primitive-subx-r32: # enum arg-location + 286 0x14/imm32 + 287 Primitive-subx-imm32: # enum arg-location + 288 0x18/imm32 + 289 Primitive-subx-disp32: # enum arg-location -- only for branches + 290 0x1c/imm32 + 291 Primitive-output-is-write-only: # boolean + 292 0x20/imm32 + 293 Primitive-next: # (handle function) + 294 0x24/imm32 + 295 Primitive-size: # (addr int) + 296 0x28/imm32/36 + 297 + 298 Stmt-tag: # int + 299 0/imm32 + 300 + 301 Block-stmts: # (handle list stmt) + 302 4/imm32 + 303 Block-var: # (handle var) + 304 8/imm32 + 305 + 306 Stmt1-operation: # (handle array byte) + 307 4/imm32 + 308 Stmt1-inouts: # (handle stmt-var) + 309 8/imm32 + 310 Stmt1-outputs: # (handle stmt-var) + 311 0xc/imm32 + 312 + 313 Vardef-var: # (handle var) + 314 4/imm32 + 315 + 316 Regvardef-operation: # (handle array byte) + 317 4/imm32 + 318 Regvardef-inouts: # (handle stmt-var) + 319 8/imm32 + 320 Regvardef-outputs: # (handle stmt-var) # will have exactly one element + 321 0xc/imm32 + 322 + 323 Stmt-size: # (addr int) + 324 0x10/imm32 + 325 + 326 Var-name: # (handle array byte) + 327 0/imm32 + 328 Var-type: # (handle tree type-id) + 329 4/imm32 + 330 Var-block-depth: # int + 331 8/imm32 + 332 Var-offset: # int + 333 0xc/imm32 + 334 Var-register: # (handle array byte) -- name of a register + 335 0x10/imm32 + 336 Var-size: # (addr int) + 337 0x14/imm32 + 338 + 339 Any-register: # wildcard + 340 # size + 341 1/imm32 + 342 # data + 343 2a/asterisk + 344 + 345 List-value: + 346 0/imm32 + 347 List-next: # (handle list _) + 348 4/imm32 + 349 List-size: # (addr int) + 350 8/imm32 + 351 + 352 # A stmt-var is like a list of vars with call-site specific metadata + 353 Stmt-var-value: # (handle var) + 354 0/imm32 + 355 Stmt-var-next: # (handle stmt-var) + 356 4/imm32 + 357 Stmt-var-is-deref: # boolean + 358 8/imm32 + 359 Stmt-var-size: # (addr int) + 360 0xc/imm32 + 361 + 362 # Types are expressed as trees (s-expressions) of type-ids (ints). + 363 # However, there's no need for singletons, so we can assume (int) == int + 364 # - if x->right == nil, x is an atom + 365 # - x->left contains either a pointer to a pair, or an atomic type-id directly. + 366 # type ids will be less than 0x10000 (MAX_TYPE_ID). + 367 + 368 Tree-left: # either type-id or (addr tree type-id) + 369 0/imm32 + 370 Tree-right: # (addr tree type-id) + 371 4/imm32 + 372 Tree-size: # (addr int) + 373 8/imm32 + 374 + 375 # Types + 376 + 377 Max-type-id: + 378 0x10000/imm32 + 379 + 380 Type-id: # (stream (address array byte)) + 381 0x1c/imm32/write + 382 0/imm32/read + 383 0x100/imm32/length + 384 # data + 385 "literal"/imm32 # 0 + 386 "int"/imm32 # 1 + 387 "addr"/imm32 # 2 + 388 "array"/imm32 # 3 + 389 "handle"/imm32 # 4 + 390 "boolean"/imm32 # 5 + 391 "constant"/imm32 # 6: like a literal, but replaced with its value in Var-offset + 392 0/imm32 + 393 # 0x20 + 394 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 + 395 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 + 396 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 + 397 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 + 398 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 + 399 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 + 400 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 + 401 + 402 # Program->types contains some typeinfo for each type definition. + 403 # Types contain vars with types, but can't specify registers. + 404 Typeinfo-id: # type-id + 405 0/imm32 + 406 # each field of a type is represented using two var's: + 407 # 1. the input var: expected type of the field; convenient for creating using parse-var-with-type + 408 # 2. the output var: a constant containing the byte offset; convenient for code-generation + 409 Typeinfo-fields: # (handle table string {(handle var), (handle var)}) + 410 4/imm32 + 411 Typeinfo-next: # (handle typeinfo) + 412 8/imm32 + 413 Typeinfo-size: # (addr int) + 414 0xc/imm32 + 415 + 416 == code + 417 + 418 Entry: + 419 # . prologue + 420 89/<- %ebp 4/r32/esp + 421 (new-segment *Heap-size Heap) + 422 # if (argv[1] == "test') run-tests() + 423 { + 424 # if (argc <= 1) break + 425 81 7/subop/compare *ebp 1/imm32 + 426 7e/jump-if-<= break/disp8 + 427 # if (argv[1] != "test") break + 428 (kernel-string-equal? *(ebp+8) "test") # => eax + 429 3d/compare-eax-and 0/imm32/false + 430 74/jump-if-= break/disp8 + 431 # + 432 (run-tests) + 433 # syscall(exit, *Num-test-failures) + 434 8b/-> *Num-test-failures 3/r32/ebx + 435 eb/jump $mu-main:end/disp8 + 436 } + 437 # otherwise convert Stdin + 438 (convert-mu Stdin Stdout) + 439 (flush Stdout) + 440 # syscall(exit, 0) + 441 bb/copy-to-ebx 0/imm32 + 442 $mu-main:end: + 443 b8/copy-to-eax 1/imm32/exit + 444 cd/syscall 0x80/imm8 + 445 + 446 convert-mu: # in: (addr buffered-file), out: (addr buffered-file) + 447 # . prologue + 448 55/push-ebp + 449 89/<- %ebp 4/r32/esp + 450 # + 451 (parse-mu *(ebp+8)) + 452 (check-mu-types) + 453 (emit-subx *(ebp+0xc)) + 454 $convert-mu:end: + 455 # . epilogue + 456 89/<- %esp 5/r32/ebp + 457 5d/pop-to-ebp + 458 c3/return + 459 + 460 test-convert-empty-input: + 461 # empty input => empty output + 462 # . prologue + 463 55/push-ebp + 464 89/<- %ebp 4/r32/esp + 465 # setup + 466 (clear-stream _test-input-stream) + 467 (clear-stream $_test-input-buffered-file->buffer) + 468 (clear-stream _test-output-stream) + 469 (clear-stream $_test-output-buffered-file->buffer) + 470 # + 471 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 472 (flush _test-output-buffered-file) + 473 (check-stream-equal _test-output-stream "" "F - test-convert-empty-input") + 474 # . epilogue + 475 89/<- %esp 5/r32/ebp + 476 5d/pop-to-ebp + 477 c3/return + 478 + 479 test-convert-function-skeleton: + 480 # . prologue + 481 55/push-ebp + 482 89/<- %ebp 4/r32/esp + 483 # setup + 484 (clear-stream _test-input-stream) + 485 (clear-stream $_test-input-buffered-file->buffer) + 486 (clear-stream _test-output-stream) + 487 (clear-stream $_test-output-buffered-file->buffer) + 488 # + 489 (write _test-input-stream "fn foo {\n") + 490 (write _test-input-stream "}\n") + 491 # convert + 492 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 493 (flush _test-output-buffered-file) + 494 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 500 # check output + 501 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-skeleton/0") + 502 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-skeleton/1") + 503 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-skeleton/2") + 504 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-skeleton/3") + 505 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-skeleton/4") + 506 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-skeleton/5") + 507 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-skeleton/6") + 508 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-skeleton/7") + 509 # . epilogue + 510 89/<- %esp 5/r32/ebp + 511 5d/pop-to-ebp + 512 c3/return + 513 + 514 test-convert-multiple-function-skeletons: + 515 # . prologue + 516 55/push-ebp + 517 89/<- %ebp 4/r32/esp + 518 # setup + 519 (clear-stream _test-input-stream) + 520 (clear-stream $_test-input-buffered-file->buffer) + 521 (clear-stream _test-output-stream) + 522 (clear-stream $_test-output-buffered-file->buffer) + 523 # + 524 (write _test-input-stream "fn foo {\n") + 525 (write _test-input-stream "}\n") + 526 (write _test-input-stream "fn bar {\n") + 527 (write _test-input-stream "}\n") + 528 # convert + 529 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 530 (flush _test-output-buffered-file) + 531 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 537 # check first function + 538 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-multiple-function-skeletons/0") + 539 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/1") + 540 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/2") + 541 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/3") + 542 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/4") + 543 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/5") + 544 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/6") + 545 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/7") + 546 # check second function + 547 (check-next-stream-line-equal _test-output-stream "bar:" "F - test-convert-multiple-function-skeletons/10") + 548 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/11") + 549 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/12") + 550 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/13") + 551 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/14") + 552 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/15") + 553 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/16") + 554 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/17") + 555 # . epilogue + 556 89/<- %esp 5/r32/ebp + 557 5d/pop-to-ebp + 558 c3/return + 559 + 560 test-convert-function-with-arg: + 561 # . prologue + 562 55/push-ebp + 563 89/<- %ebp 4/r32/esp + 564 # setup + 565 (clear-stream _test-input-stream) + 566 (clear-stream $_test-input-buffered-file->buffer) + 567 (clear-stream _test-output-stream) + 568 (clear-stream $_test-output-buffered-file->buffer) + 569 # + 570 (write _test-input-stream "fn foo n: int {\n") + 571 (write _test-input-stream "}\n") + 572 # convert + 573 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 574 (flush _test-output-buffered-file) + 575 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 581 # check output + 582 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg/0") + 583 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg/1") + 584 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg/2") + 585 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg/3") + 586 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg/4") + 587 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg/5") + 588 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg/6") + 589 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg/7") + 590 # . epilogue + 591 89/<- %esp 5/r32/ebp + 592 5d/pop-to-ebp + 593 c3/return + 594 + 595 test-convert-function-with-arg-and-body: + 596 # . prologue + 597 55/push-ebp + 598 89/<- %ebp 4/r32/esp + 599 # setup + 600 (clear-stream _test-input-stream) + 601 (clear-stream $_test-input-buffered-file->buffer) + 602 (clear-stream _test-output-stream) + 603 (clear-stream $_test-output-buffered-file->buffer) + 604 c7 0/subop/copy *Next-block-index 1/imm32 + 605 # + 606 (write _test-input-stream "fn foo n: int {\n") + 607 (write _test-input-stream " increment n\n") + 608 (write _test-input-stream "}\n") + 609 # convert + 610 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 611 (flush _test-output-buffered-file) + 612 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 618 # check output + 619 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg-and-body/0") + 620 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg-and-body/1") + 621 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg-and-body/2") + 622 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg-and-body/3") + 623 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-arg-and-body/4") + 624 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-arg-and-body/5") + 625 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-arg-and-body/6") + 626 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-arg-and-body/7") + 627 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-arg-and-body/8") + 628 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg-and-body/9") + 629 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg-and-body/10") + 630 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg-and-body/11") + 631 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg-and-body/12") + 632 # . epilogue + 633 89/<- %esp 5/r32/ebp + 634 5d/pop-to-ebp + 635 c3/return + 636 + 637 test-convert-function-distinguishes-args: + 638 # . prologue + 639 55/push-ebp + 640 89/<- %ebp 4/r32/esp + 641 # setup + 642 (clear-stream _test-input-stream) + 643 (clear-stream $_test-input-buffered-file->buffer) + 644 (clear-stream _test-output-stream) + 645 (clear-stream $_test-output-buffered-file->buffer) + 646 c7 0/subop/copy *Next-block-index 1/imm32 + 647 # + 648 (write _test-input-stream "fn foo a: int, b: int {\n") + 649 (write _test-input-stream " increment b\n") + 650 (write _test-input-stream "}\n") + 651 # convert + 652 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 653 (flush _test-output-buffered-file) + 654 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 660 # check output + 661 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-distinguishes-args/0") + 662 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-distinguishes-args/1") + 663 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-distinguishes-args/2") + 664 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-distinguishes-args/3") + 665 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-distinguishes-args/4") + 666 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-distinguishes-args/5") + 667 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x0000000c)" "F - test-convert-function-distinguishes-args/6") + 668 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-distinguishes-args/7") + 669 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-distinguishes-args/8") + 670 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-distinguishes-args/9") + 671 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-distinguishes-args/10") + 672 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-distinguishes-args/11") + 673 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-distinguishes-args/12") + 674 # . epilogue + 675 89/<- %esp 5/r32/ebp + 676 5d/pop-to-ebp + 677 c3/return + 678 + 679 test-convert-function-returns-result: + 680 # . prologue + 681 55/push-ebp + 682 89/<- %ebp 4/r32/esp + 683 # setup + 684 (clear-stream _test-input-stream) + 685 (clear-stream $_test-input-buffered-file->buffer) + 686 (clear-stream _test-output-stream) + 687 (clear-stream $_test-output-buffered-file->buffer) + 688 c7 0/subop/copy *Next-block-index 1/imm32 + 689 # + 690 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") + 691 (write _test-input-stream " result <- copy a\n") + 692 (write _test-input-stream " result <- increment\n") + 693 (write _test-input-stream "}\n") + 694 # convert + 695 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 696 (flush _test-output-buffered-file) + 697 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 703 # check output + 704 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-returns-result/0") + 705 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-returns-result/1") + 706 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-returns-result/2") + 707 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-returns-result/3") + 708 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-returns-result/4") + 709 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-returns-result/5") + 710 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-returns-result/6") + 711 (check-next-stream-line-equal _test-output-stream " 40/increment-eax" "F - test-convert-function-returns-result/7") + 712 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-returns-result/8") + 713 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-returns-result/9") + 714 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-returns-result/10") + 715 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-returns-result/11") + 716 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-returns-result/12") + 717 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-returns-result/13") + 718 # . epilogue + 719 89/<- %esp 5/r32/ebp + 720 5d/pop-to-ebp + 721 c3/return + 722 + 723 test-convert-function-literal-arg: + 724 # . prologue + 725 55/push-ebp + 726 89/<- %ebp 4/r32/esp + 727 # setup + 728 (clear-stream _test-input-stream) + 729 (clear-stream $_test-input-buffered-file->buffer) + 730 (clear-stream _test-output-stream) + 731 (clear-stream $_test-output-buffered-file->buffer) + 732 c7 0/subop/copy *Next-block-index 1/imm32 + 733 # + 734 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") + 735 (write _test-input-stream " result <- copy a\n") + 736 (write _test-input-stream " result <- add 1\n") + 737 (write _test-input-stream "}\n") + 738 # convert + 739 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 740 (flush _test-output-buffered-file) + 741 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 747 # check output + 748 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-literal-arg/0") + 749 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-literal-arg/1") + 750 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-literal-arg/2") + 751 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-literal-arg/3") + 752 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-literal-arg/4") + 753 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-literal-arg/5") + 754 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-literal-arg/6") + 755 (check-next-stream-line-equal _test-output-stream " 05/add-to-eax 1/imm32" "F - test-convert-function-literal-arg/7") + 756 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-literal-arg/8") + 757 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-literal-arg/9") + 758 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-literal-arg/10") + 759 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-literal-arg/11") + 760 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-literal-arg/12") + 761 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-literal-arg/13") + 762 # . epilogue + 763 89/<- %esp 5/r32/ebp + 764 5d/pop-to-ebp + 765 c3/return + 766 + 767 test-convert-function-literal-arg-2: + 768 # . prologue + 769 55/push-ebp + 770 89/<- %ebp 4/r32/esp + 771 # setup + 772 (clear-stream _test-input-stream) + 773 (clear-stream $_test-input-buffered-file->buffer) + 774 (clear-stream _test-output-stream) + 775 (clear-stream $_test-output-buffered-file->buffer) + 776 c7 0/subop/copy *Next-block-index 1/imm32 + 777 # + 778 (write _test-input-stream "fn foo a: int, b: int -> result/ebx: int {\n") + 779 (write _test-input-stream " result <- copy a\n") + 780 (write _test-input-stream " result <- add 1\n") + 781 (write _test-input-stream "}\n") + 782 # convert + 783 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 784 (flush _test-output-buffered-file) + 785 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 791 # check output + 792 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-literal-arg-2/0") + 793 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-literal-arg-2/1") + 794 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-literal-arg-2/2") + 795 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-literal-arg-2/3") + 796 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-literal-arg-2/4") + 797 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-literal-arg-2/5") + 798 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-literal-arg-2/6") + 799 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %ebx 1/imm32" "F - test-convert-function-literal-arg-2/7") + 800 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-literal-arg-2/8") + 801 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-literal-arg-2/9") + 802 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-literal-arg-2/10") + 803 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-literal-arg-2/11") + 804 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-literal-arg-2/12") + 805 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-literal-arg-2/13") + 806 # . epilogue + 807 89/<- %esp 5/r32/ebp + 808 5d/pop-to-ebp + 809 c3/return + 810 + 811 test-convert-function-call-with-literal-arg: + 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 main -> result/ebx: int {\n") + 823 (write _test-input-stream " result <- do-add 3 4\n") + 824 (write _test-input-stream "}\n") + 825 (write _test-input-stream "fn do-add a: int, b: int -> result/ebx: int {\n") + 826 (write _test-input-stream " result <- copy a\n") + 827 (write _test-input-stream " result <- add b\n") + 828 (write _test-input-stream "}\n") + 829 # convert + 830 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 831 (flush _test-output-buffered-file) + 832 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 838 # check output + 839 (check-next-stream-line-equal _test-output-stream "main:" "F - test-convert-function-call-with-literal-arg/0") + 840 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/1") + 841 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/2") + 842 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/3") + 843 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/4") + 844 (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:" "F - test-convert-function-call-with-literal-arg/5") + 845 (check-next-stream-line-equal _test-output-stream " (do-add 3 4)" "F - test-convert-function-call-with-literal-arg/6") + 846 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/7") + 847 (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/8") + 848 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/9") + 849 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/10") + 850 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/11") + 851 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/12") + 852 (check-next-stream-line-equal _test-output-stream "do-add:" "F - test-convert-function-call-with-literal-arg/13") + 853 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/14") + 854 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/15") + 855 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/16") + 856 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/17") + 857 (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:" "F - test-convert-function-call-with-literal-arg/18") + 858 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/19") + 859 (check-next-stream-line-equal _test-output-stream " 03/add *(ebp+0x0000000c) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/20") + 860 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/21") + 861 (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:" "F - test-convert-function-call-with-literal-arg/22") + 862 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/23") + 863 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/24") + 864 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/25") + 865 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/26") + 866 # . epilogue + 867 89/<- %esp 5/r32/ebp + 868 5d/pop-to-ebp + 869 c3/return + 870 + 871 test-convert-function-with-local-var-in-mem: + 872 # . prologue + 873 55/push-ebp + 874 89/<- %ebp 4/r32/esp + 875 # setup + 876 (clear-stream _test-input-stream) + 877 (clear-stream $_test-input-buffered-file->buffer) + 878 (clear-stream _test-output-stream) + 879 (clear-stream $_test-output-buffered-file->buffer) + 880 c7 0/subop/copy *Next-block-index 1/imm32 + 881 # + 882 (write _test-input-stream "fn foo {\n") + 883 (write _test-input-stream " var x: int\n") + 884 (write _test-input-stream " increment x\n") + 885 (write _test-input-stream "}\n") + 886 # convert + 887 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 888 (flush _test-output-buffered-file) + 889 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 895 # check output + 896 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-mem/0") + 897 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-mem/1") + 898 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-mem/2") + 899 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-mem/3") + 900 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-mem/4") + 901 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-mem/5") + 902 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-mem/6") + 903 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-mem/7") + 904 (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") + 905 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-mem/9") + 906 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-mem/10") + 907 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-mem/11") + 908 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-mem/12") + 909 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-mem/13") + 910 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-mem/14") + 911 # . epilogue + 912 89/<- %esp 5/r32/ebp + 913 5d/pop-to-ebp + 914 c3/return + 915 + 916 test-convert-function-with-local-var-in-reg: + 917 # . prologue + 918 55/push-ebp + 919 89/<- %ebp 4/r32/esp + 920 # setup + 921 (clear-stream _test-input-stream) + 922 (clear-stream $_test-input-buffered-file->buffer) + 923 (clear-stream _test-output-stream) + 924 (clear-stream $_test-output-buffered-file->buffer) + 925 c7 0/subop/copy *Next-block-index 1/imm32 + 926 # + 927 (write _test-input-stream "fn foo {\n") + 928 (write _test-input-stream " var x/ecx: int <- copy 3\n") + 929 (write _test-input-stream " x <- increment\n") + 930 (write _test-input-stream "}\n") + 931 # convert + 932 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 933 (flush _test-output-buffered-file) + 934 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 940 # check output + 941 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-reg/0") + 942 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-reg/1") + 943 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-reg/2") + 944 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-reg/3") + 945 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-reg/4") + 946 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-reg/5") + 947 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-local-var-in-reg/6") + 948 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-function-with-local-var-in-reg/7") + 949 (check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-convert-function-with-local-var-in-reg/8") + 950 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9") + 951 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-reg/10") + 952 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-reg/11") + 953 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-reg/12") + 954 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-reg/13") + 955 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-reg/14") + 956 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-reg/15") + 957 # . epilogue + 958 89/<- %esp 5/r32/ebp + 959 5d/pop-to-ebp + 960 c3/return + 961 + 962 test-convert-function-with-local-var-dereferenced: + 963 # . prologue + 964 55/push-ebp + 965 89/<- %ebp 4/r32/esp + 966 # setup + 967 (clear-stream _test-input-stream) + 968 (clear-stream $_test-input-buffered-file->buffer) + 969 (clear-stream _test-output-stream) + 970 (clear-stream $_test-output-buffered-file->buffer) + 971 c7 0/subop/copy *Next-block-index 1/imm32 + 972 # + 973 (write _test-input-stream "fn foo {\n") + 974 (write _test-input-stream " var x/ecx: (addr int) <- copy 0\n") + 975 (write _test-input-stream " increment *x\n") + 976 (write _test-input-stream "}\n") + 977 # convert + 978 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 979 (flush _test-output-buffered-file) + 980 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 986 # check output + 987 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-dereferenced/0") + 988 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-dereferenced/1") + 989 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-dereferenced/2") + 990 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-dereferenced/3") + 991 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-dereferenced/4") + 992 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-dereferenced/5") + 993 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-local-var-dereferenced/6") + 994 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-function-with-local-var-dereferenced/7") + 995 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *ecx" "F - test-convert-function-with-local-var-dereferenced/8") + 996 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9") + 997 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-dereferenced/10") + 998 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-dereferenced/11") + 999 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-dereferenced/12") +1000 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-dereferenced/13") +1001 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-dereferenced/14") +1002 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-dereferenced/15") +1003 # . epilogue +1004 89/<- %esp 5/r32/ebp +1005 5d/pop-to-ebp +1006 c3/return +1007 +1008 test-convert-compare-register-with-literal: +1009 # . prologue +1010 55/push-ebp +1011 89/<- %ebp 4/r32/esp +1012 # setup +1013 (clear-stream _test-input-stream) +1014 (clear-stream $_test-input-buffered-file->buffer) +1015 (clear-stream _test-output-stream) +1016 (clear-stream $_test-output-buffered-file->buffer) +1017 c7 0/subop/copy *Next-block-index 1/imm32 +1018 # +1019 (write _test-input-stream "fn foo {\n") +1020 (write _test-input-stream " var x/ecx: int <- copy 0\n") +1021 (write _test-input-stream " compare x, 0\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-compare-register-with-literal/0") +1034 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-compare-register-with-literal/1") +1035 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-compare-register-with-literal/2") +1036 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-compare-register-with-literal/3") +1037 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-compare-register-with-literal/4") +1038 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-compare-register-with-literal/5") +1039 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-compare-register-with-literal/6") +1040 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-compare-register-with-literal/7") +1041 (check-next-stream-line-equal _test-output-stream " 81 7/subop/compare %ecx 0/imm32" "F - test-convert-compare-register-with-literal/8") +1042 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9") +1043 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-compare-register-with-literal/10") +1044 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-compare-register-with-literal/11") +1045 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-compare-register-with-literal/12") +1046 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-compare-register-with-literal/13") +1047 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-compare-register-with-literal/14") +1048 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-compare-register-with-literal/15") +1049 # . epilogue +1050 89/<- %esp 5/r32/ebp +1051 5d/pop-to-ebp +1052 c3/return +1053 +1054 test-convert-function-with-local-var-in-block: +1055 # . prologue +1056 55/push-ebp +1057 89/<- %ebp 4/r32/esp +1058 # setup +1059 (clear-stream _test-input-stream) +1060 (clear-stream $_test-input-buffered-file->buffer) +1061 (clear-stream _test-output-stream) +1062 (clear-stream $_test-output-buffered-file->buffer) +1063 c7 0/subop/copy *Next-block-index 1/imm32 +1064 # +1065 (write _test-input-stream "fn foo {\n") +1066 (write _test-input-stream " {\n") +1067 (write _test-input-stream " var x: int\n") +1068 (write _test-input-stream " increment x\n") +1069 (write _test-input-stream " }\n") +1070 (write _test-input-stream "}\n") +1071 # convert +1072 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1073 (flush _test-output-buffered-file) +1074 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1080 # check output +1081 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-block/0") +1082 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-block/1") +1083 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-block/2") +1084 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-block/3") +1085 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/4") +1086 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-block/5") +1087 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/6") +1088 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-local-var-in-block/7") +1089 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-block/8") +1090 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-block/9") +1091 (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") +1092 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/11") +1093 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-local-var-in-block/12") +1094 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/13") +1095 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-block/14") +1096 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-block/15") +1097 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-block/16") +1098 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-block/17") +1099 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-block/18") +1100 # . epilogue +1101 89/<- %esp 5/r32/ebp +1102 5d/pop-to-ebp +1103 c3/return +1104 +1105 test-convert-function-with-local-var-in-named-block: +1106 # . prologue +1107 55/push-ebp +1108 89/<- %ebp 4/r32/esp +1109 # setup +1110 (clear-stream _test-input-stream) +1111 (clear-stream $_test-input-buffered-file->buffer) +1112 (clear-stream _test-output-stream) +1113 (clear-stream $_test-output-buffered-file->buffer) +1114 c7 0/subop/copy *Next-block-index 1/imm32 +1115 # +1116 (write _test-input-stream "fn foo {\n") +1117 (write _test-input-stream " $bar: {\n") +1118 (write _test-input-stream " var x: int\n") 1119 (write _test-input-stream " increment x\n") -1120 (write _test-input-stream " loop\n") -1121 (write _test-input-stream " }\n") -1122 (write _test-input-stream "}\n") -1123 # convert -1124 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1125 (flush _test-output-buffered-file) -1126 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1132 # check output -1133 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-block/0") -1134 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-block/1") -1135 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-block/2") -1136 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-block/3") -1137 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/4") -1138 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-in-block/5") -1139 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/6") -1140 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-in-block/7") -1141 (check-next-stream-line-equal _test-output-stream " 0f 8d/jump-if->= break/disp32" "F - test-convert-function-with-branches-in-block/8") -1142 (check-next-stream-line-equal _test-output-stream " 0f 82/jump-if-addr< loop/disp32" "F - test-convert-function-with-branches-in-block/9") -1143 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-block/10") -1144 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-block/11") -1145 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/12") -1146 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-in-block/13") -1147 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/14") -1148 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-in-block/15") -1149 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-block/16") -1150 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-block/17") -1151 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-block/18") -1152 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-block/19") -1153 # . epilogue -1154 89/<- %esp 5/r32/ebp -1155 5d/pop-to-ebp -1156 c3/return -1157 -1158 test-convert-function-with-branches-in-named-block: -1159 # . prologue -1160 55/push-ebp -1161 89/<- %ebp 4/r32/esp -1162 # setup -1163 (clear-stream _test-input-stream) -1164 (clear-stream $_test-input-buffered-file->buffer) -1165 (clear-stream _test-output-stream) -1166 (clear-stream $_test-output-buffered-file->buffer) -1167 c7 0/subop/copy *Next-block-index 1/imm32 -1168 # -1169 (write _test-input-stream "fn foo x: int {\n") -1170 (write _test-input-stream " $bar: {\n") -1171 (write _test-input-stream " break-if->= $bar\n") -1172 (write _test-input-stream " loop-if-addr< $bar\n") -1173 (write _test-input-stream " increment x\n") -1174 (write _test-input-stream " loop\n") -1175 (write _test-input-stream " }\n") -1176 (write _test-input-stream "}\n") -1177 # convert -1178 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1179 (flush _test-output-buffered-file) -1180 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1186 # check output -1187 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-named-block/0") -1188 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-named-block/1") -1189 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-named-block/2") -1190 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-named-block/3") -1191 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/4") -1192 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-in-named-block/5") -1193 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/6") -1194 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-branches-in-named-block/7") -1195 (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") -1196 (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") -1197 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-named-block/10") -1198 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-named-block/11") -1199 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/12") -1200 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-branches-in-named-block/13") -1201 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/14") -1202 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-in-named-block/15") -1203 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-named-block/16") -1204 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-named-block/17") -1205 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-named-block/18") -1206 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-named-block/19") -1207 # . epilogue -1208 89/<- %esp 5/r32/ebp -1209 5d/pop-to-ebp -1210 c3/return -1211 -1212 test-convert-function-with-var-in-nested-block: -1213 # . prologue -1214 55/push-ebp -1215 89/<- %ebp 4/r32/esp -1216 # setup -1217 (clear-stream _test-input-stream) -1218 (clear-stream $_test-input-buffered-file->buffer) -1219 (clear-stream _test-output-stream) -1220 (clear-stream $_test-output-buffered-file->buffer) -1221 c7 0/subop/copy *Next-block-index 1/imm32 -1222 # -1223 (write _test-input-stream "fn foo x: int {\n") -1224 (write _test-input-stream " {\n") -1225 (write _test-input-stream " {\n") -1226 (write _test-input-stream " var x: int\n") -1227 (write _test-input-stream " increment x\n") -1228 (write _test-input-stream " }\n") -1229 (write _test-input-stream " }\n") -1230 (write _test-input-stream "}\n") -1231 # convert -1232 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1233 (flush _test-output-buffered-file) -1234 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1240 # check output -1241 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-var-in-nested-block/0") -1242 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-var-in-nested-block/1") -1243 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-var-in-nested-block/2") -1244 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-var-in-nested-block/3") -1245 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/4") -1246 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-var-in-nested-block/5") -1247 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/6") -1248 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-var-in-nested-block/7") -1249 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/8") -1250 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-var-in-nested-block/9") -1251 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10") -1252 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-var-in-nested-block/11") -1253 (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") -1254 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/13") -1255 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-var-in-nested-block/14") -1256 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/15") -1257 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-var-in-nested-block/16") -1258 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/17") -1259 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-var-in-nested-block/18") -1260 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-var-in-nested-block/19") -1261 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-var-in-nested-block/20") -1262 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-var-in-nested-block/21") -1263 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-var-in-nested-block/22") -1264 # . epilogue -1265 89/<- %esp 5/r32/ebp -1266 5d/pop-to-ebp -1267 c3/return -1268 -1269 test-convert-function-with-multiple-vars-in-nested-blocks: -1270 # . prologue -1271 55/push-ebp -1272 89/<- %ebp 4/r32/esp -1273 # setup -1274 (clear-stream _test-input-stream) -1275 (clear-stream $_test-input-buffered-file->buffer) -1276 (clear-stream _test-output-stream) -1277 (clear-stream $_test-output-buffered-file->buffer) -1278 c7 0/subop/copy *Next-block-index 1/imm32 -1279 # -1280 (write _test-input-stream "fn foo x: int {\n") -1281 (write _test-input-stream " {\n") -1282 (write _test-input-stream " var x/eax: int <- copy 0\n") -1283 (write _test-input-stream " {\n") -1284 (write _test-input-stream " var y: int\n") -1285 (write _test-input-stream " x <- add y\n") -1286 (write _test-input-stream " }\n") -1287 (write _test-input-stream " }\n") -1288 (write _test-input-stream "}\n") -1289 # convert -1290 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1291 (flush _test-output-buffered-file) -1292 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1298 # check output -1299 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/0") -1300 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-multiple-vars-in-nested-blocks/1") -1301 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/2") -1302 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/3") -1303 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/4") -1304 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/5") -1305 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/6") -1306 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/7") -1307 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-with-multiple-vars-in-nested-blocks/8") -1308 (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") -1309 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/10") -1310 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/11") -1311 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12") -1312 (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") -1313 (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") -1314 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/15") -1315 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/16") -1316 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-with-multiple-vars-in-nested-blocks/17") -1317 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/18") -1318 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/19") -1319 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/20") -1320 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/21") -1321 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-multiple-vars-in-nested-blocks/22") -1322 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/23") -1323 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/24") -1324 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-multiple-vars-in-nested-blocks/25") -1325 # . epilogue -1326 89/<- %esp 5/r32/ebp -1327 5d/pop-to-ebp -1328 c3/return -1329 -1330 test-convert-function-with-branches-and-local-vars: -1331 # A conditional 'break' after a 'var' in a block is converted into a -1332 # nested block that performs all necessary cleanup before jumping. This -1333 # results in some ugly code duplication. -1334 # . prologue -1335 55/push-ebp -1336 89/<- %ebp 4/r32/esp -1337 # setup -1338 (clear-stream _test-input-stream) -1339 (clear-stream $_test-input-buffered-file->buffer) -1340 (clear-stream _test-output-stream) -1341 (clear-stream $_test-output-buffered-file->buffer) -1342 c7 0/subop/copy *Next-block-index 1/imm32 -1343 # -1344 (write _test-input-stream "fn foo {\n") -1345 (write _test-input-stream " {\n") -1346 (write _test-input-stream " var x: int\n") -1347 (write _test-input-stream " break-if->=\n") -1348 (write _test-input-stream " increment x\n") -1349 (write _test-input-stream " }\n") -1350 (write _test-input-stream "}\n") -1351 # convert -1352 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1353 (flush _test-output-buffered-file) -1354 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1360 # check output -1361 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-local-vars/0") -1362 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-local-vars/1") -1363 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-local-vars/2") -1364 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-and-local-vars/3") -1365 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/4") -1366 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-and-local-vars/5") -1367 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/6") -1368 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-and-local-vars/7") -1369 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-local-vars/8") -1370 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/9") -1371 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-branches-and-local-vars/10") -1372 (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") -1373 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:break/disp32" "F - test-convert-function-with-branches-and-local-vars/12") -1374 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/13") -1375 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-branches-and-local-vars/14") -1376 (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") -1377 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/16") -1378 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-and-local-vars/17") -1379 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/18") -1380 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-and-local-vars/19") -1381 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-local-vars/20") -1382 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-and-local-vars/21") -1383 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-local-vars/22") -1384 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-local-vars/23") -1385 # . epilogue -1386 89/<- %esp 5/r32/ebp -1387 5d/pop-to-ebp -1388 c3/return -1389 -1390 test-convert-function-with-conditional-loops-and-local-vars: -1391 # A conditional 'loop' after a 'var' in a block is converted into a nested -1392 # block that performs all necessary cleanup before jumping. This results -1393 # in some ugly code duplication. -1394 # . prologue -1395 55/push-ebp -1396 89/<- %ebp 4/r32/esp -1397 # setup -1398 (clear-stream _test-input-stream) -1399 (clear-stream $_test-input-buffered-file->buffer) -1400 (clear-stream _test-output-stream) -1401 (clear-stream $_test-output-buffered-file->buffer) -1402 c7 0/subop/copy *Next-block-index 1/imm32 -1403 # -1404 (write _test-input-stream "fn foo {\n") -1405 (write _test-input-stream " {\n") -1406 (write _test-input-stream " var x: int\n") -1407 (write _test-input-stream " loop-if->=\n") -1408 (write _test-input-stream " increment x\n") -1409 (write _test-input-stream " }\n") -1410 (write _test-input-stream "}\n") -1411 # convert -1412 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1413 (flush _test-output-buffered-file) -1414 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1420 # check output -1421 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-conditional-loops-and-local-vars/0") -1422 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-conditional-loops-and-local-vars/1") -1423 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/2") -1424 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-conditional-loops-and-local-vars/3") -1425 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/4") -1426 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-conditional-loops-and-local-vars/5") -1427 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/6") -1428 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-conditional-loops-and-local-vars/7") -1429 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-conditional-loops-and-local-vars/8") -1430 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/9") -1431 (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") -1432 (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") -1433 (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") -1434 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/13") -1435 (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") -1436 (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") -1437 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/16") -1438 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-conditional-loops-and-local-vars/17") -1439 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/18") -1440 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-conditional-loops-and-local-vars/19") -1441 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-conditional-loops-and-local-vars/20") -1442 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/21") -1443 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/22") -1444 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-conditional-loops-and-local-vars/23") -1445 # . epilogue -1446 89/<- %esp 5/r32/ebp -1447 5d/pop-to-ebp -1448 c3/return -1449 -1450 test-convert-function-with-unconditional-loops-and-local-vars: -1451 # An unconditional 'loop' after a 'var' in a block is emitted _after_ the -1452 # regular block cleanup. Any instructions after 'loop' are dead and -1453 # therefore skipped. -1454 # . prologue -1455 55/push-ebp -1456 89/<- %ebp 4/r32/esp -1457 # setup -1458 (clear-stream _test-input-stream) -1459 (clear-stream $_test-input-buffered-file->buffer) -1460 (clear-stream _test-output-stream) -1461 (clear-stream $_test-output-buffered-file->buffer) -1462 c7 0/subop/copy *Next-block-index 1/imm32 -1463 # -1464 (write _test-input-stream "fn foo {\n") -1465 (write _test-input-stream " {\n") -1466 (write _test-input-stream " var x: int\n") -1467 (write _test-input-stream " loop\n") -1468 (write _test-input-stream " increment x\n") -1469 (write _test-input-stream " }\n") -1470 (write _test-input-stream "}\n") -1471 # convert -1472 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1473 (flush _test-output-buffered-file) -1474 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1480 # check output -1481 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-unconditional-loops-and-local-vars/0") -1482 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-unconditional-loops-and-local-vars/1") -1483 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/2") -1484 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-unconditional-loops-and-local-vars/3") -1485 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-loops-and-local-vars/4") -1486 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-unconditional-loops-and-local-vars/5") -1487 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-loops-and-local-vars/6") -1488 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-unconditional-loops-and-local-vars/7") -1489 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-loops-and-local-vars/8") -1490 (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") -1491 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-unconditional-loops-and-local-vars/10") -1492 # not emitted: ff 0/subop/increment *(ebp+0xfffffffc) -1493 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-loops-and-local-vars/11") -1494 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-unconditional-loops-and-local-vars/12") -1495 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-loops-and-local-vars/13") -1496 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-unconditional-loops-and-local-vars/14") -1497 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-unconditional-loops-and-local-vars/15") -1498 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/16") -1499 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/17") -1500 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-unconditional-loops-and-local-vars/18") -1501 # . epilogue -1502 89/<- %esp 5/r32/ebp -1503 5d/pop-to-ebp -1504 c3/return -1505 -1506 test-convert-function-with-branches-and-loops-and-local-vars: -1507 # . prologue -1508 55/push-ebp -1509 89/<- %ebp 4/r32/esp -1510 # setup -1511 (clear-stream _test-input-stream) -1512 (clear-stream $_test-input-buffered-file->buffer) -1513 (clear-stream _test-output-stream) -1514 (clear-stream $_test-output-buffered-file->buffer) -1515 c7 0/subop/copy *Next-block-index 1/imm32 -1516 # -1517 (write _test-input-stream "fn foo {\n") -1518 (write _test-input-stream " {\n") -1519 (write _test-input-stream " var x: int\n") -1520 (write _test-input-stream " break-if->=\n") -1521 (write _test-input-stream " increment x\n") -1522 (write _test-input-stream " loop\n") -1523 (write _test-input-stream " }\n") -1524 (write _test-input-stream "}\n") -1525 # convert -1526 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1527 (flush _test-output-buffered-file) -1528 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1534 # check output -1535 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-loops-and-local-vars/0") -1536 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-loops-and-local-vars/1") -1537 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/2") -1538 (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") -1539 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/4") -1540 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-and-loops-and-local-vars/5") -1541 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/6") -1542 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-and-loops-and-local-vars/7") -1543 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-loops-and-local-vars/8") -1544 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/9") -1545 (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") -1546 (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") -1547 (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") -1548 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/13") -1549 (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") -1550 (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") -1551 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-and-loops-and-local-vars/16") -1552 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/17") -1553 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-and-loops-and-local-vars/18") -1554 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/19") -1555 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-and-loops-and-local-vars/20") -1556 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-loops-and-local-vars/21") -1557 (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") -1558 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/23") -1559 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-loops-and-local-vars/24") -1560 # . epilogue -1561 89/<- %esp 5/r32/ebp -1562 5d/pop-to-ebp -1563 c3/return -1564 -1565 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars: -1566 # . prologue -1567 55/push-ebp -1568 89/<- %ebp 4/r32/esp -1569 # setup -1570 (clear-stream _test-input-stream) -1571 (clear-stream $_test-input-buffered-file->buffer) -1572 (clear-stream _test-output-stream) -1573 (clear-stream $_test-output-buffered-file->buffer) -1574 c7 0/subop/copy *Next-block-index 1/imm32 -1575 # -1576 (write _test-input-stream "fn foo {\n") -1577 (write _test-input-stream " a: {\n") -1578 (write _test-input-stream " var x: int\n") -1579 (write _test-input-stream " {\n") -1580 (write _test-input-stream " var y: int\n") -1581 (write _test-input-stream " break-if->= a\n") -1582 (write _test-input-stream " increment x\n") -1583 (write _test-input-stream " loop\n") -1584 (write _test-input-stream " }\n") -1585 (write _test-input-stream " }\n") -1586 (write _test-input-stream "}\n") -1587 # convert -1588 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1589 (flush _test-output-buffered-file) -1590 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1596 # check output -1597 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0") -1598 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1") -1599 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2") -1600 (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") -1601 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4") -1602 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5") -1603 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6") -1604 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7") -1605 (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") -1606 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9") -1607 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10") -1608 (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") -1609 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12") -1610 (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") -1611 (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") -1612 (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") -1613 (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") -1614 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17") -1615 (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") -1616 (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") -1617 (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") -1618 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21") -1619 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22") -1620 (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") -1621 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24") -1622 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25") -1623 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26") -1624 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27") -1625 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28") -1626 (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") -1627 (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") -1628 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31") -1629 # . epilogue -1630 89/<- %esp 5/r32/ebp -1631 5d/pop-to-ebp -1632 c3/return -1633 -1634 test-convert-function-with-nonlocal-unconditional-break-and-local-vars: -1635 # . prologue -1636 55/push-ebp -1637 89/<- %ebp 4/r32/esp -1638 # setup -1639 (clear-stream _test-input-stream) -1640 (clear-stream $_test-input-buffered-file->buffer) -1641 (clear-stream _test-output-stream) -1642 (clear-stream $_test-output-buffered-file->buffer) -1643 c7 0/subop/copy *Next-block-index 1/imm32 -1644 # -1645 (write _test-input-stream "fn foo {\n") -1646 (write _test-input-stream " a: {\n") -1647 (write _test-input-stream " var x: int\n") -1648 (write _test-input-stream " {\n") -1649 (write _test-input-stream " var y: int\n") -1650 (write _test-input-stream " break a\n") -1651 (write _test-input-stream " increment x\n") -1652 (write _test-input-stream " }\n") -1653 (write _test-input-stream " }\n") -1654 (write _test-input-stream "}\n") -1655 # convert -1656 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1657 (flush _test-output-buffered-file) -1658 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1664 # check output -1665 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0") -1666 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1") -1667 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2") -1668 (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") -1669 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4") -1670 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5") -1671 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6") -1672 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7") -1673 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8") -1674 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9") -1675 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10") -1676 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11") -1677 (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") -1678 (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") -1679 (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") -1680 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15") -1681 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16") -1682 (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") -1683 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18") -1684 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19") -1685 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20") -1686 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21") -1687 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22") -1688 (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") -1689 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24") -1690 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25") -1691 # . epilogue -1692 89/<- %esp 5/r32/ebp -1693 5d/pop-to-ebp -1694 c3/return -1695 -1696 test-convert-function-with-unconditional-break-and-local-vars: -1697 # . prologue -1698 55/push-ebp -1699 89/<- %ebp 4/r32/esp -1700 # setup -1701 (clear-stream _test-input-stream) -1702 (clear-stream $_test-input-buffered-file->buffer) -1703 (clear-stream _test-output-stream) -1704 (clear-stream $_test-output-buffered-file->buffer) -1705 c7 0/subop/copy *Next-block-index 1/imm32 -1706 # -1707 (write _test-input-stream "fn foo {\n") -1708 (write _test-input-stream " {\n") -1709 (write _test-input-stream " var x: int\n") -1710 (write _test-input-stream " {\n") -1711 (write _test-input-stream " var y: int\n") -1712 (write _test-input-stream " break\n") -1713 (write _test-input-stream " increment x\n") -1714 (write _test-input-stream " }\n") -1715 (write _test-input-stream " }\n") -1716 (write _test-input-stream "}\n") -1717 # convert -1718 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1719 (flush _test-output-buffered-file) -1720 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1726 # check output -1727 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-unconditional-break-and-local-vars/0") -1728 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-unconditional-break-and-local-vars/1") -1729 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/2") -1730 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-unconditional-break-and-local-vars/3") -1731 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/4") -1732 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/5") -1733 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/6") -1734 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/7") -1735 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/8") -1736 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/9") -1737 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/10") -1738 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11") -1739 (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") -1740 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/13") -1741 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/14") -1742 (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") -1743 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/16") -1744 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/17") -1745 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/18") -1746 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/19") -1747 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-unconditional-break-and-local-vars/20") -1748 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/21") -1749 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/22") -1750 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-unconditional-break-and-local-vars/23") -1751 # . epilogue -1752 89/<- %esp 5/r32/ebp -1753 5d/pop-to-ebp -1754 c3/return -1755 -1756 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars: -1757 # . prologue -1758 55/push-ebp -1759 89/<- %ebp 4/r32/esp -1760 # setup -1761 (clear-stream _test-input-stream) -1762 (clear-stream $_test-input-buffered-file->buffer) -1763 (clear-stream _test-output-stream) -1764 (clear-stream $_test-output-buffered-file->buffer) -1765 c7 0/subop/copy *Next-block-index 1/imm32 -1766 # -1767 (write _test-input-stream "fn foo {\n") -1768 (write _test-input-stream " a: {\n") -1769 (write _test-input-stream " var x: int\n") -1770 (write _test-input-stream " {\n") -1771 (write _test-input-stream " var y: int\n") -1772 (write _test-input-stream " loop a\n") -1773 (write _test-input-stream " increment x\n") -1774 (write _test-input-stream " }\n") -1775 (write _test-input-stream " }\n") -1776 (write _test-input-stream "}\n") -1777 # convert -1778 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1779 (flush _test-output-buffered-file) -1780 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1786 # check output -1787 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0") -1788 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1") -1789 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2") -1790 (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") -1791 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4") -1792 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5") -1793 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6") -1794 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7") -1795 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8") -1796 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9") -1797 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10") -1798 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11") -1799 (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") -1800 (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") -1801 (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") -1802 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15") -1803 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16") -1804 (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") -1805 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18") -1806 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19") -1807 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20") -1808 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21") -1809 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22") -1810 (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") -1811 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24") -1812 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25") -1813 # . epilogue -1814 89/<- %esp 5/r32/ebp -1815 5d/pop-to-ebp -1816 c3/return -1817 -1818 test-convert-length-of-array: -1819 # . prologue -1820 55/push-ebp -1821 89/<- %ebp 4/r32/esp -1822 # setup -1823 (clear-stream _test-input-stream) -1824 (clear-stream $_test-input-buffered-file->buffer) -1825 (clear-stream _test-output-stream) -1826 (clear-stream $_test-output-buffered-file->buffer) -1827 c7 0/subop/copy *Next-block-index 1/imm32 -1828 # -1829 (write _test-input-stream "fn foo a: (addr array int) {\n") -1830 (write _test-input-stream " var b/eax: (addr array int) <- copy a\n") -1831 (write _test-input-stream " var c/eax: int <- length b\n") -1832 (write _test-input-stream "}\n") -1833 # convert -1834 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1835 (flush _test-output-buffered-file) -1836 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1842 # check output -1843 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array/0") -1844 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array/1") -1845 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array/2") -1846 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array/3") -1847 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array/4") -1848 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array/5") -1849 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/6") -1850 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-length-of-array/7") -1851 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/8") -1852 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *eax 0x00000000/r32" "F - test-convert-length-of-array/9") -1853 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/10") -1854 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/11") -1855 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array/12") -1856 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array/13") -1857 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array/14") -1858 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array/15") -1859 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array/16") -1860 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array/17") -1861 # . epilogue -1862 89/<- %esp 5/r32/ebp -1863 5d/pop-to-ebp -1864 c3/return -1865 -1866 ####################################################### -1867 # Parsing -1868 ####################################################### +1120 (write _test-input-stream " }\n") +1121 (write _test-input-stream "}\n") +1122 # convert +1123 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1124 (flush _test-output-buffered-file) +1125 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1131 # check output +1132 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-named-block/0") +1133 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-named-block/1") +1134 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-named-block/2") +1135 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-named-block/3") +1136 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/4") +1137 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-named-block/5") +1138 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/6") +1139 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-local-var-in-named-block/7") +1140 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-named-block/8") +1141 (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") +1142 (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") +1143 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/11") +1144 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-local-var-in-named-block/12") +1145 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/13") +1146 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-named-block/14") +1147 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-named-block/15") +1148 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-named-block/16") +1149 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-named-block/17") +1150 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-named-block/18") +1151 # . epilogue +1152 89/<- %esp 5/r32/ebp +1153 5d/pop-to-ebp +1154 c3/return +1155 +1156 test-convert-function-with-branches-in-block: +1157 # . prologue +1158 55/push-ebp +1159 89/<- %ebp 4/r32/esp +1160 # setup +1161 (clear-stream _test-input-stream) +1162 (clear-stream $_test-input-buffered-file->buffer) +1163 (clear-stream _test-output-stream) +1164 (clear-stream $_test-output-buffered-file->buffer) +1165 c7 0/subop/copy *Next-block-index 1/imm32 +1166 # +1167 (write _test-input-stream "fn foo x: int {\n") +1168 (write _test-input-stream " {\n") +1169 (write _test-input-stream " break-if->=\n") +1170 (write _test-input-stream " loop-if-addr<\n") +1171 (write _test-input-stream " increment x\n") +1172 (write _test-input-stream " loop\n") +1173 (write _test-input-stream " }\n") +1174 (write _test-input-stream "}\n") +1175 # convert +1176 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1177 (flush _test-output-buffered-file) +1178 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1184 # check output +1185 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-block/0") +1186 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-block/1") +1187 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-block/2") +1188 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-block/3") +1189 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/4") +1190 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-in-block/5") +1191 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/6") +1192 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-in-block/7") +1193 (check-next-stream-line-equal _test-output-stream " 0f 8d/jump-if->= break/disp32" "F - test-convert-function-with-branches-in-block/8") +1194 (check-next-stream-line-equal _test-output-stream " 0f 82/jump-if-addr< loop/disp32" "F - test-convert-function-with-branches-in-block/9") +1195 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-block/10") +1196 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-block/11") +1197 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/12") +1198 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-in-block/13") +1199 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/14") +1200 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-in-block/15") +1201 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-block/16") +1202 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-block/17") +1203 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-block/18") +1204 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-block/19") +1205 # . epilogue +1206 89/<- %esp 5/r32/ebp +1207 5d/pop-to-ebp +1208 c3/return +1209 +1210 test-convert-function-with-branches-in-named-block: +1211 # . prologue +1212 55/push-ebp +1213 89/<- %ebp 4/r32/esp +1214 # setup +1215 (clear-stream _test-input-stream) +1216 (clear-stream $_test-input-buffered-file->buffer) +1217 (clear-stream _test-output-stream) +1218 (clear-stream $_test-output-buffered-file->buffer) +1219 c7 0/subop/copy *Next-block-index 1/imm32 +1220 # +1221 (write _test-input-stream "fn foo x: int {\n") +1222 (write _test-input-stream " $bar: {\n") +1223 (write _test-input-stream " break-if->= $bar\n") +1224 (write _test-input-stream " loop-if-addr< $bar\n") +1225 (write _test-input-stream " increment x\n") +1226 (write _test-input-stream " loop\n") +1227 (write _test-input-stream " }\n") +1228 (write _test-input-stream "}\n") +1229 # convert +1230 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1231 (flush _test-output-buffered-file) +1232 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1238 # check output +1239 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-named-block/0") +1240 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-named-block/1") +1241 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-named-block/2") +1242 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-named-block/3") +1243 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/4") +1244 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-in-named-block/5") +1245 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/6") +1246 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-branches-in-named-block/7") +1247 (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") +1248 (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") +1249 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-named-block/10") +1250 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-named-block/11") +1251 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/12") +1252 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-branches-in-named-block/13") +1253 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/14") +1254 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-in-named-block/15") +1255 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-named-block/16") +1256 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-named-block/17") +1257 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-named-block/18") +1258 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-named-block/19") +1259 # . epilogue +1260 89/<- %esp 5/r32/ebp +1261 5d/pop-to-ebp +1262 c3/return +1263 +1264 test-convert-function-with-var-in-nested-block: +1265 # . prologue +1266 55/push-ebp +1267 89/<- %ebp 4/r32/esp +1268 # setup +1269 (clear-stream _test-input-stream) +1270 (clear-stream $_test-input-buffered-file->buffer) +1271 (clear-stream _test-output-stream) +1272 (clear-stream $_test-output-buffered-file->buffer) +1273 c7 0/subop/copy *Next-block-index 1/imm32 +1274 # +1275 (write _test-input-stream "fn foo x: int {\n") +1276 (write _test-input-stream " {\n") +1277 (write _test-input-stream " {\n") +1278 (write _test-input-stream " var x: int\n") +1279 (write _test-input-stream " increment x\n") +1280 (write _test-input-stream " }\n") +1281 (write _test-input-stream " }\n") +1282 (write _test-input-stream "}\n") +1283 # convert +1284 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1285 (flush _test-output-buffered-file) +1286 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1292 # check output +1293 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-var-in-nested-block/0") +1294 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-var-in-nested-block/1") +1295 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-var-in-nested-block/2") +1296 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-var-in-nested-block/3") +1297 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/4") +1298 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-var-in-nested-block/5") +1299 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/6") +1300 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-var-in-nested-block/7") +1301 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/8") +1302 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-var-in-nested-block/9") +1303 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10") +1304 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-var-in-nested-block/11") +1305 (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") +1306 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/13") +1307 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-var-in-nested-block/14") +1308 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/15") +1309 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-var-in-nested-block/16") +1310 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/17") +1311 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-var-in-nested-block/18") +1312 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-var-in-nested-block/19") +1313 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-var-in-nested-block/20") +1314 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-var-in-nested-block/21") +1315 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-var-in-nested-block/22") +1316 # . epilogue +1317 89/<- %esp 5/r32/ebp +1318 5d/pop-to-ebp +1319 c3/return +1320 +1321 test-convert-function-with-multiple-vars-in-nested-blocks: +1322 # . prologue +1323 55/push-ebp +1324 89/<- %ebp 4/r32/esp +1325 # setup +1326 (clear-stream _test-input-stream) +1327 (clear-stream $_test-input-buffered-file->buffer) +1328 (clear-stream _test-output-stream) +1329 (clear-stream $_test-output-buffered-file->buffer) +1330 c7 0/subop/copy *Next-block-index 1/imm32 +1331 # +1332 (write _test-input-stream "fn foo x: int {\n") +1333 (write _test-input-stream " {\n") +1334 (write _test-input-stream " var x/eax: int <- copy 0\n") +1335 (write _test-input-stream " {\n") +1336 (write _test-input-stream " var y: int\n") +1337 (write _test-input-stream " x <- add y\n") +1338 (write _test-input-stream " }\n") +1339 (write _test-input-stream " }\n") +1340 (write _test-input-stream "}\n") +1341 # convert +1342 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1343 (flush _test-output-buffered-file) +1344 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1350 # check output +1351 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/0") +1352 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-multiple-vars-in-nested-blocks/1") +1353 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/2") +1354 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/3") +1355 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/4") +1356 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/5") +1357 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/6") +1358 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/7") +1359 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-with-multiple-vars-in-nested-blocks/8") +1360 (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") +1361 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/10") +1362 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/11") +1363 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12") +1364 (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") +1365 (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") +1366 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/15") +1367 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/16") +1368 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-with-multiple-vars-in-nested-blocks/17") +1369 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/18") +1370 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/19") +1371 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/20") +1372 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/21") +1373 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-multiple-vars-in-nested-blocks/22") +1374 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/23") +1375 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/24") +1376 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-multiple-vars-in-nested-blocks/25") +1377 # . epilogue +1378 89/<- %esp 5/r32/ebp +1379 5d/pop-to-ebp +1380 c3/return +1381 +1382 test-convert-function-with-branches-and-local-vars: +1383 # A conditional 'break' after a 'var' in a block is converted into a +1384 # nested block that performs all necessary cleanup before jumping. This +1385 # results in some ugly code duplication. +1386 # . prologue +1387 55/push-ebp +1388 89/<- %ebp 4/r32/esp +1389 # setup +1390 (clear-stream _test-input-stream) +1391 (clear-stream $_test-input-buffered-file->buffer) +1392 (clear-stream _test-output-stream) +1393 (clear-stream $_test-output-buffered-file->buffer) +1394 c7 0/subop/copy *Next-block-index 1/imm32 +1395 # +1396 (write _test-input-stream "fn foo {\n") +1397 (write _test-input-stream " {\n") +1398 (write _test-input-stream " var x: int\n") +1399 (write _test-input-stream " break-if->=\n") +1400 (write _test-input-stream " increment x\n") +1401 (write _test-input-stream " }\n") +1402 (write _test-input-stream "}\n") +1403 # convert +1404 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1405 (flush _test-output-buffered-file) +1406 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1412 # check output +1413 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-local-vars/0") +1414 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-local-vars/1") +1415 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-local-vars/2") +1416 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-and-local-vars/3") +1417 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/4") +1418 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-and-local-vars/5") +1419 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/6") +1420 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-and-local-vars/7") +1421 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-local-vars/8") +1422 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/9") +1423 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-branches-and-local-vars/10") +1424 (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") +1425 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:break/disp32" "F - test-convert-function-with-branches-and-local-vars/12") +1426 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/13") +1427 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-branches-and-local-vars/14") +1428 (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") +1429 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/16") +1430 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-and-local-vars/17") +1431 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/18") +1432 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-and-local-vars/19") +1433 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-local-vars/20") +1434 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-and-local-vars/21") +1435 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-local-vars/22") +1436 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-local-vars/23") +1437 # . epilogue +1438 89/<- %esp 5/r32/ebp +1439 5d/pop-to-ebp +1440 c3/return +1441 +1442 test-convert-function-with-conditional-loops-and-local-vars: +1443 # A conditional 'loop' after a 'var' in a block is converted into a nested +1444 # block that performs all necessary cleanup before jumping. This results +1445 # in some ugly code duplication. +1446 # . prologue +1447 55/push-ebp +1448 89/<- %ebp 4/r32/esp +1449 # setup +1450 (clear-stream _test-input-stream) +1451 (clear-stream $_test-input-buffered-file->buffer) +1452 (clear-stream _test-output-stream) +1453 (clear-stream $_test-output-buffered-file->buffer) +1454 c7 0/subop/copy *Next-block-index 1/imm32 +1455 # +1456 (write _test-input-stream "fn foo {\n") +1457 (write _test-input-stream " {\n") +1458 (write _test-input-stream " var x: int\n") +1459 (write _test-input-stream " loop-if->=\n") +1460 (write _test-input-stream " increment x\n") +1461 (write _test-input-stream " }\n") +1462 (write _test-input-stream "}\n") +1463 # convert +1464 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1465 (flush _test-output-buffered-file) +1466 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1472 # check output +1473 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-conditional-loops-and-local-vars/0") +1474 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-conditional-loops-and-local-vars/1") +1475 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/2") +1476 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-conditional-loops-and-local-vars/3") +1477 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/4") +1478 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-conditional-loops-and-local-vars/5") +1479 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/6") +1480 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-conditional-loops-and-local-vars/7") +1481 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-conditional-loops-and-local-vars/8") +1482 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/9") +1483 (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") +1484 (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") +1485 (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") +1486 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/13") +1487 (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") +1488 (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") +1489 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/16") +1490 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-conditional-loops-and-local-vars/17") +1491 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/18") +1492 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-conditional-loops-and-local-vars/19") +1493 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-conditional-loops-and-local-vars/20") +1494 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/21") +1495 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/22") +1496 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-conditional-loops-and-local-vars/23") +1497 # . epilogue +1498 89/<- %esp 5/r32/ebp +1499 5d/pop-to-ebp +1500 c3/return +1501 +1502 test-convert-function-with-unconditional-loops-and-local-vars: +1503 # An unconditional 'loop' after a 'var' in a block is emitted _after_ the +1504 # regular block cleanup. Any instructions after 'loop' are dead and +1505 # therefore skipped. +1506 # . prologue +1507 55/push-ebp +1508 89/<- %ebp 4/r32/esp +1509 # setup +1510 (clear-stream _test-input-stream) +1511 (clear-stream $_test-input-buffered-file->buffer) +1512 (clear-stream _test-output-stream) +1513 (clear-stream $_test-output-buffered-file->buffer) +1514 c7 0/subop/copy *Next-block-index 1/imm32 +1515 # +1516 (write _test-input-stream "fn foo {\n") +1517 (write _test-input-stream " {\n") +1518 (write _test-input-stream " var x: int\n") +1519 (write _test-input-stream " loop\n") +1520 (write _test-input-stream " increment x\n") +1521 (write _test-input-stream " }\n") +1522 (write _test-input-stream "}\n") +1523 # convert +1524 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1525 (flush _test-output-buffered-file) +1526 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1532 # check output +1533 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-unconditional-loops-and-local-vars/0") +1534 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-unconditional-loops-and-local-vars/1") +1535 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/2") +1536 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-unconditional-loops-and-local-vars/3") +1537 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-loops-and-local-vars/4") +1538 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-unconditional-loops-and-local-vars/5") +1539 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-loops-and-local-vars/6") +1540 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-unconditional-loops-and-local-vars/7") +1541 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-loops-and-local-vars/8") +1542 (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") +1543 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-unconditional-loops-and-local-vars/10") +1544 # not emitted: ff 0/subop/increment *(ebp+0xfffffffc) +1545 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-loops-and-local-vars/11") +1546 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-unconditional-loops-and-local-vars/12") +1547 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-loops-and-local-vars/13") +1548 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-unconditional-loops-and-local-vars/14") +1549 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-unconditional-loops-and-local-vars/15") +1550 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/16") +1551 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/17") +1552 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-unconditional-loops-and-local-vars/18") +1553 # . epilogue +1554 89/<- %esp 5/r32/ebp +1555 5d/pop-to-ebp +1556 c3/return +1557 +1558 test-convert-function-with-branches-and-loops-and-local-vars: +1559 # . prologue +1560 55/push-ebp +1561 89/<- %ebp 4/r32/esp +1562 # setup +1563 (clear-stream _test-input-stream) +1564 (clear-stream $_test-input-buffered-file->buffer) +1565 (clear-stream _test-output-stream) +1566 (clear-stream $_test-output-buffered-file->buffer) +1567 c7 0/subop/copy *Next-block-index 1/imm32 +1568 # +1569 (write _test-input-stream "fn foo {\n") +1570 (write _test-input-stream " {\n") +1571 (write _test-input-stream " var x: int\n") +1572 (write _test-input-stream " break-if->=\n") +1573 (write _test-input-stream " increment x\n") +1574 (write _test-input-stream " loop\n") +1575 (write _test-input-stream " }\n") +1576 (write _test-input-stream "}\n") +1577 # convert +1578 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1579 (flush _test-output-buffered-file) +1580 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1586 # check output +1587 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-loops-and-local-vars/0") +1588 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-loops-and-local-vars/1") +1589 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/2") +1590 (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") +1591 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/4") +1592 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-and-loops-and-local-vars/5") +1593 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/6") +1594 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-and-loops-and-local-vars/7") +1595 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-loops-and-local-vars/8") +1596 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/9") +1597 (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") +1598 (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") +1599 (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") +1600 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/13") +1601 (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") +1602 (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") +1603 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-and-loops-and-local-vars/16") +1604 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/17") +1605 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-and-loops-and-local-vars/18") +1606 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/19") +1607 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-and-loops-and-local-vars/20") +1608 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-loops-and-local-vars/21") +1609 (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") +1610 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/23") +1611 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-loops-and-local-vars/24") +1612 # . epilogue +1613 89/<- %esp 5/r32/ebp +1614 5d/pop-to-ebp +1615 c3/return +1616 +1617 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars: +1618 # . prologue +1619 55/push-ebp +1620 89/<- %ebp 4/r32/esp +1621 # setup +1622 (clear-stream _test-input-stream) +1623 (clear-stream $_test-input-buffered-file->buffer) +1624 (clear-stream _test-output-stream) +1625 (clear-stream $_test-output-buffered-file->buffer) +1626 c7 0/subop/copy *Next-block-index 1/imm32 +1627 # +1628 (write _test-input-stream "fn foo {\n") +1629 (write _test-input-stream " a: {\n") +1630 (write _test-input-stream " var x: int\n") +1631 (write _test-input-stream " {\n") +1632 (write _test-input-stream " var y: int\n") +1633 (write _test-input-stream " break-if->= a\n") +1634 (write _test-input-stream " increment x\n") +1635 (write _test-input-stream " loop\n") +1636 (write _test-input-stream " }\n") +1637 (write _test-input-stream " }\n") +1638 (write _test-input-stream "}\n") +1639 # convert +1640 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1641 (flush _test-output-buffered-file) +1642 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1648 # check output +1649 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0") +1650 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1") +1651 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2") +1652 (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") +1653 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4") +1654 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5") +1655 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6") +1656 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7") +1657 (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") +1658 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9") +1659 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10") +1660 (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") +1661 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12") +1662 (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") +1663 (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") +1664 (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") +1665 (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") +1666 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17") +1667 (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") +1668 (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") +1669 (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") +1670 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21") +1671 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22") +1672 (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") +1673 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24") +1674 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25") +1675 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26") +1676 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27") +1677 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28") +1678 (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") +1679 (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") +1680 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31") +1681 # . epilogue +1682 89/<- %esp 5/r32/ebp +1683 5d/pop-to-ebp +1684 c3/return +1685 +1686 test-convert-function-with-nonlocal-unconditional-break-and-local-vars: +1687 # . prologue +1688 55/push-ebp +1689 89/<- %ebp 4/r32/esp +1690 # setup +1691 (clear-stream _test-input-stream) +1692 (clear-stream $_test-input-buffered-file->buffer) +1693 (clear-stream _test-output-stream) +1694 (clear-stream $_test-output-buffered-file->buffer) +1695 c7 0/subop/copy *Next-block-index 1/imm32 +1696 # +1697 (write _test-input-stream "fn foo {\n") +1698 (write _test-input-stream " a: {\n") +1699 (write _test-input-stream " var x: int\n") +1700 (write _test-input-stream " {\n") +1701 (write _test-input-stream " var y: int\n") +1702 (write _test-input-stream " break a\n") +1703 (write _test-input-stream " increment x\n") +1704 (write _test-input-stream " }\n") +1705 (write _test-input-stream " }\n") +1706 (write _test-input-stream "}\n") +1707 # convert +1708 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1709 (flush _test-output-buffered-file) +1710 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1716 # check output +1717 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0") +1718 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1") +1719 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2") +1720 (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") +1721 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4") +1722 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5") +1723 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6") +1724 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7") +1725 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8") +1726 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9") +1727 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10") +1728 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11") +1729 (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") +1730 (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") +1731 (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") +1732 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15") +1733 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16") +1734 (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") +1735 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18") +1736 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19") +1737 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20") +1738 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21") +1739 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22") +1740 (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") +1741 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24") +1742 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25") +1743 # . epilogue +1744 89/<- %esp 5/r32/ebp +1745 5d/pop-to-ebp +1746 c3/return +1747 +1748 test-convert-function-with-unconditional-break-and-local-vars: +1749 # . prologue +1750 55/push-ebp +1751 89/<- %ebp 4/r32/esp +1752 # setup +1753 (clear-stream _test-input-stream) +1754 (clear-stream $_test-input-buffered-file->buffer) +1755 (clear-stream _test-output-stream) +1756 (clear-stream $_test-output-buffered-file->buffer) +1757 c7 0/subop/copy *Next-block-index 1/imm32 +1758 # +1759 (write _test-input-stream "fn foo {\n") +1760 (write _test-input-stream " {\n") +1761 (write _test-input-stream " var x: int\n") +1762 (write _test-input-stream " {\n") +1763 (write _test-input-stream " var y: int\n") +1764 (write _test-input-stream " break\n") +1765 (write _test-input-stream " increment x\n") +1766 (write _test-input-stream " }\n") +1767 (write _test-input-stream " }\n") +1768 (write _test-input-stream "}\n") +1769 # convert +1770 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1771 (flush _test-output-buffered-file) +1772 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1778 # check output +1779 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-unconditional-break-and-local-vars/0") +1780 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-unconditional-break-and-local-vars/1") +1781 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/2") +1782 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-unconditional-break-and-local-vars/3") +1783 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/4") +1784 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/5") +1785 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/6") +1786 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/7") +1787 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/8") +1788 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/9") +1789 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/10") +1790 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11") +1791 (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") +1792 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/13") +1793 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/14") +1794 (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") +1795 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/16") +1796 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/17") +1797 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/18") +1798 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/19") +1799 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-unconditional-break-and-local-vars/20") +1800 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/21") +1801 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/22") +1802 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-unconditional-break-and-local-vars/23") +1803 # . epilogue +1804 89/<- %esp 5/r32/ebp +1805 5d/pop-to-ebp +1806 c3/return +1807 +1808 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars: +1809 # . prologue +1810 55/push-ebp +1811 89/<- %ebp 4/r32/esp +1812 # setup +1813 (clear-stream _test-input-stream) +1814 (clear-stream $_test-input-buffered-file->buffer) +1815 (clear-stream _test-output-stream) +1816 (clear-stream $_test-output-buffered-file->buffer) +1817 c7 0/subop/copy *Next-block-index 1/imm32 +1818 # +1819 (write _test-input-stream "fn foo {\n") +1820 (write _test-input-stream " a: {\n") +1821 (write _test-input-stream " var x: int\n") +1822 (write _test-input-stream " {\n") +1823 (write _test-input-stream " var y: int\n") +1824 (write _test-input-stream " loop a\n") +1825 (write _test-input-stream " increment x\n") +1826 (write _test-input-stream " }\n") +1827 (write _test-input-stream " }\n") +1828 (write _test-input-stream "}\n") +1829 # convert +1830 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1831 (flush _test-output-buffered-file) +1832 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1838 # check output +1839 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0") +1840 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1") +1841 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2") +1842 (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") +1843 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4") +1844 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5") +1845 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6") +1846 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7") +1847 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8") +1848 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9") +1849 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10") +1850 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11") +1851 (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") +1852 (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") +1853 (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") +1854 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15") +1855 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16") +1856 (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") +1857 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18") +1858 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19") +1859 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20") +1860 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21") +1861 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22") +1862 (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") +1863 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24") +1864 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25") +1865 # . epilogue +1866 89/<- %esp 5/r32/ebp +1867 5d/pop-to-ebp +1868 c3/return 1869 -1870 parse-mu: # in: (addr buffered-file) -1871 # pseudocode -1872 # var curr-function: (addr (handle function)) = Program -1873 # var line: (stream byte 512) -1874 # var word-slice: slice -1875 # while true # line loop -1876 # clear-stream(line) -1877 # read-line-buffered(in, line) -1878 # if (line->write == 0) break # end of file -1879 # word-slice = next-mu-token(line) -1880 # if slice-empty?(word-slice) # end of line -1881 # continue -1882 # else if slice-starts-with?(word-slice, "#") # comment -1883 # continue # end of line -1884 # else if slice-equal(word-slice, "fn") -1885 # var new-function: (handle function) = allocate(function) -1886 # var vars: (stack (addr var) 256) -1887 # populate-mu-function-header(in, new-function, vars) -1888 # populate-mu-function-body(in, new-function, vars) -1889 # assert(vars->top == 0) -1890 # *curr-function = new-function -1891 # curr-function = &new-function->next -1892 # else -1893 # abort() -1894 # -1895 # . prologue -1896 55/push-ebp -1897 89/<- %ebp 4/r32/esp -1898 # . save registers -1899 50/push-eax -1900 51/push-ecx -1901 52/push-edx -1902 53/push-ebx -1903 57/push-edi -1904 # var line/ecx: (stream byte 512) -1905 81 5/subop/subtract %esp 0x200/imm32 -1906 68/push 0x200/imm32/length -1907 68/push 0/imm32/read -1908 68/push 0/imm32/write -1909 89/<- %ecx 4/r32/esp -1910 # var word-slice/edx: slice -1911 68/push 0/imm32/end -1912 68/push 0/imm32/start -1913 89/<- %edx 4/r32/esp -1914 # var curr-function/edi: (addr (handle function)) = Program -1915 bf/copy-to-edi Program/imm32 -1916 # var vars/ebx: (stack (addr var) 256) -1917 81 5/subop/subtract %esp 0x400/imm32 -1918 68/push 0x400/imm32/length -1919 68/push 0/imm32/top -1920 89/<- %ebx 4/r32/esp -1921 { -1922 $parse-mu:line-loop: -1923 (clear-stream %ecx) -1924 (read-line-buffered *(ebp+8) %ecx) -1925 # if (line->write == 0) break -1926 81 7/subop/compare *ecx 0/imm32 -1927 0f 84/jump-if-= break/disp32 -1928 +-- 6 lines: #? # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------ -1934 (next-mu-token %ecx %edx) -1935 # if slice-empty?(word-slice) continue -1936 (slice-empty? %edx) -1937 3d/compare-eax-and 0/imm32/false -1938 0f 85/jump-if-!= loop/disp32 -1939 # if (*word-slice->start == "#") continue -1940 # . eax = *word-slice->start -1941 8b/-> *edx 0/r32/eax -1942 8a/copy-byte *eax 0/r32/AL -1943 81 4/subop/and %eax 0xff/imm32 -1944 # . if (eax == '#') continue -1945 3d/compare-eax-and 0x23/imm32/hash -1946 0f 84/jump-if-= loop/disp32 -1947 # if (slice-equal?(word-slice, "fn")) parse a function -1948 { -1949 $parse-mu:fn: -1950 (slice-equal? %edx "fn") -1951 3d/compare-eax-and 0/imm32/false -1952 0f 84/jump-if-= break/disp32 -1953 # var new-function/eax: (handle function) = populate-mu-function(in, new-function, vars) -1954 (allocate Heap *Function-size) # => eax -1955 (zero-out %eax *Function-size) -1956 (clear-stack %ebx) -1957 (populate-mu-function-header %ecx %eax %ebx) -1958 (populate-mu-function-body *(ebp+8) %eax %ebx) -1959 # *curr-function = new-function -1960 89/<- *edi 0/r32/eax -1961 # curr-function = &new-function->next -1962 8d/address-> *(eax+0x14) 7/r32/edi # Function-next -1963 e9/jump $parse-mu:line-loop/disp32 -1964 } -1965 # otherwise abort -1966 e9/jump $parse-mu:error1/disp32 -1967 } # end line loop -1968 $parse-mu:end: -1969 # . reclaim locals -1970 81 0/subop/add %esp 0x630/imm32 -1971 # . restore registers -1972 5f/pop-to-edi -1973 5b/pop-to-ebx -1974 5a/pop-to-edx -1975 59/pop-to-ecx -1976 58/pop-to-eax -1977 # . epilogue -1978 89/<- %esp 5/r32/ebp -1979 5d/pop-to-ebp -1980 c3/return -1981 -1982 $parse-mu:error1: -1983 # error("unexpected top-level command: " word-slice "\n") -1984 (write-buffered Stderr "unexpected top-level command: ") -1985 (write-slice-buffered Stderr %edx) -1986 (write-buffered Stderr "\n") -1987 (flush Stderr) -1988 # . syscall(exit, 1) -1989 bb/copy-to-ebx 1/imm32 -1990 b8/copy-to-eax 1/imm32/exit -1991 cd/syscall 0x80/imm8 -1992 # never gets here -1993 -1994 $parse-mu:error2: -1995 # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n") -1996 (print-int32-buffered Stderr *ebx) -1997 (write-buffered Stderr " vars not reclaimed after fn '") -1998 (write-slice-buffered Stderr *eax) # Function-name -1999 (write-buffered Stderr "'\n") -2000 (flush Stderr) -2001 # . syscall(exit, 1) -2002 bb/copy-to-ebx 1/imm32 -2003 b8/copy-to-eax 1/imm32/exit -2004 cd/syscall 0x80/imm8 -2005 # never gets here -2006 -2007 # scenarios considered: -2008 # ✗ fn foo # no block -2009 # ✓ fn foo { -2010 # ✗ fn foo { { -2011 # ✗ fn foo { } -2012 # ✗ fn foo { } { -2013 # ✗ fn foo x { -2014 # ✗ fn foo x: { -2015 # ✓ fn foo x: int { -2016 # ✓ fn foo x: int { -2017 # ✓ fn foo x: int -> y/eax: int { -2018 populate-mu-function-header: # first-line: (addr stream byte), out: (handle function), vars: (addr stack (handle var)) -2019 # pseudocode: -2020 # var name: slice -2021 # next-mu-token(first-line, name) -2022 # assert(name not in '{' '}' '->') -2023 # out->name = slice-to-string(name) -2024 # var next-offset: int = 8 -2025 # ## inouts -2026 # while true -2027 # ## name -2028 # name = next-mu-token(first-line) -2029 # if (name == '{') goto done -2030 # if (name == '->') break -2031 # assert(name != '}') -2032 # var v: (handle var) = parse-var-with-type(name, first-line) -2033 # assert(v->register == null) -2034 # v->stack-offset = next-offset -2035 # next-offset += size-of(v) -2036 # # v->block-depth is implicitly 0 -2037 # out->inouts = append(out->inouts, v) -2038 # push(vars, v) -2039 # ## outputs -2040 # while true -2041 # ## name -2042 # name = next-mu-token(first-line) -2043 # assert(name not in '{' '}' '->') -2044 # var v: (handle var) = parse-var-with-type(name, first-line) -2045 # assert(v->register != null) -2046 # out->outputs = append(out->outputs, v) -2047 # done: -2048 # -2049 # . prologue -2050 55/push-ebp -2051 89/<- %ebp 4/r32/esp -2052 # . save registers -2053 50/push-eax -2054 51/push-ecx -2055 52/push-edx -2056 53/push-ebx -2057 57/push-edi -2058 # edi = out -2059 8b/-> *(ebp+0xc) 7/r32/edi -2060 # var word-slice/ecx: slice -2061 68/push 0/imm32/end -2062 68/push 0/imm32/start -2063 89/<- %ecx 4/r32/esp -2064 # var next-offset/edx = 8 -2065 ba/copy-to-edx 8/imm32 -2066 # read function name -2067 (next-mu-token *(ebp+8) %ecx) -2068 # error checking -2069 # TODO: error if name starts with 'break' or 'loop' -2070 # if (word-slice == '{') abort -2071 (slice-equal? %ecx "{") # => eax -2072 3d/compare-eax-and 0/imm32/false -2073 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -2074 # if (word-slice == '->') abort -2075 (slice-equal? %ecx "->") # => eax -2076 3d/compare-eax-and 0/imm32/false -2077 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -2078 # if (word-slice == '}') abort -2079 (slice-equal? %ecx "}") # => eax -2080 3d/compare-eax-and 0/imm32/false -2081 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -2082 # save function name -2083 (slice-to-string Heap %ecx) # => eax -2084 89/<- *edi 0/r32/eax # Function-name -2085 # initialize default subx-name as well -2086 89/<- *(edi+4) 0/r32/eax # Function-subx-name -2087 # save function inouts -2088 { -2089 $populate-mu-function-header:check-for-inout: -2090 (next-mu-token *(ebp+8) %ecx) -2091 # if (word-slice == '{') goto done -2092 (slice-equal? %ecx "{") # => eax -2093 3d/compare-eax-and 0/imm32/false -2094 0f 85/jump-if-!= $populate-mu-function-header:done/disp32 -2095 # if (word-slice == '->') break -2096 (slice-equal? %ecx "->") # => eax -2097 3d/compare-eax-and 0/imm32/false -2098 0f 85/jump-if-!= break/disp32 -2099 # if (word-slice == '}') abort -2100 (slice-equal? %ecx "}") # => eax -2101 3d/compare-eax-and 0/imm32/false -2102 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -2103 # var v/ebx: (handle var) = parse-var-with-type(word-slice, first-line) -2104 (parse-var-with-type %ecx *(ebp+8)) # => eax -2105 89/<- %ebx 0/r32/eax -2106 # assert(v->register == null) -2107 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -2108 0f 85/jump-if-!= $populate-mu-function-header:error2/disp32 -2109 # v->stack-offset = next-offset -2110 89/<- *(ebx+0xc) 2/r32/edx # Var-stack-offset -2111 # next-offset += size-of(v) -2112 (size-of %ebx) # => eax -2113 01/add %edx 0/r32/eax -2114 # v->block-depth is implicitly 0 -2115 # -2116 (append-list Heap %ebx *(edi+8)) # Function-inouts => eax -2117 89/<- *(edi+8) 0/r32/eax # Function-inouts -2118 (push *(ebp+0x10) %ebx) -2119 # -2120 e9/jump loop/disp32 -2121 } -2122 # save function outputs -2123 { -2124 $populate-mu-function-header:check-for-out: -2125 (next-mu-token *(ebp+8) %ecx) -2126 # if (word-slice == '{') break -2127 (slice-equal? %ecx "{") # => eax -2128 3d/compare-eax-and 0/imm32/false -2129 0f 85/jump-if-!= break/disp32 -2130 # if (word-slice == '->') abort -2131 (slice-equal? %ecx "->") # => eax -2132 3d/compare-eax-and 0/imm32/false -2133 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -2134 # if (word-slice == '}') abort -2135 (slice-equal? %ecx "}") # => eax -2136 3d/compare-eax-and 0/imm32/false -2137 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -2138 # -2139 (parse-var-with-type %ecx *(ebp+8)) # => eax -2140 89/<- %ebx 0/r32/eax -2141 # assert(var->register != null) -2142 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -2143 0f 84/jump-if-= $populate-mu-function-header:error3/disp32 -2144 (append-list Heap %ebx *(edi+0xc)) # Function-outputs => eax -2145 89/<- *(edi+0xc) 0/r32/eax # Function-outputs -2146 e9/jump loop/disp32 -2147 } -2148 $populate-mu-function-header:done: -2149 (check-no-tokens-left *(ebp+8)) -2150 $populate-mu-function-header:end: -2151 # . reclaim locals -2152 81 0/subop/add %esp 8/imm32 -2153 # . restore registers -2154 5f/pop-to-edi -2155 5b/pop-to-ebx -2156 5a/pop-to-edx -2157 59/pop-to-ecx -2158 58/pop-to-eax -2159 # . epilogue -2160 89/<- %esp 5/r32/ebp -2161 5d/pop-to-ebp -2162 c3/return -2163 -2164 $populate-mu-function-header:error1: -2165 # error("function header not in form 'fn <name> {'") -2166 (write-buffered Stderr "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '") -2167 (flush Stderr) -2168 (rewind-stream *(ebp+8)) -2169 (write-stream 2 *(ebp+8)) -2170 (write-buffered Stderr "'\n") -2171 (flush Stderr) -2172 # . syscall(exit, 1) -2173 bb/copy-to-ebx 1/imm32 -2174 b8/copy-to-eax 1/imm32/exit -2175 cd/syscall 0x80/imm8 -2176 # never gets here -2177 -2178 $populate-mu-function-header:error2: -2179 # error("function input '" var "' cannot be in a register") -2180 (write-buffered Stderr "function input '") -2181 (write-buffered Stderr *ebx) # Var-name -2182 (write-buffered Stderr "' cannot be in a register") -2183 (flush Stderr) -2184 # . syscall(exit, 1) -2185 bb/copy-to-ebx 1/imm32 -2186 b8/copy-to-eax 1/imm32/exit -2187 cd/syscall 0x80/imm8 -2188 # never gets here -2189 -2190 $populate-mu-function-header:error3: -2191 # error("function input '" var "' must be in a register") -2192 (write-buffered Stderr "function input '") -2193 (write-buffered Stderr *eax) # Var-name -2194 (write-buffered Stderr " must be in a register'") -2195 (flush Stderr) -2196 (rewind-stream *(ebp+8)) -2197 (write-stream 2 *(ebp+8)) -2198 (write-buffered Stderr "'\n") -2199 (flush Stderr) -2200 # . syscall(exit, 1) -2201 bb/copy-to-ebx 1/imm32 -2202 b8/copy-to-eax 1/imm32/exit -2203 cd/syscall 0x80/imm8 -2204 # never gets here -2205 -2206 test-function-header-with-arg: -2207 # . prologue -2208 55/push-ebp -2209 89/<- %ebp 4/r32/esp -2210 # setup -2211 (clear-stream _test-input-stream) -2212 (write _test-input-stream "foo n: int {\n") -2213 # var result/ecx: function -2214 2b/subtract-> *Function-size 4/r32/esp -2215 89/<- %ecx 4/r32/esp -2216 (zero-out %ecx *Function-size) -2217 # var vars/ebx: (stack (addr var) 16) -2218 81 5/subop/subtract %esp 0x10/imm32 -2219 68/push 0x10/imm32/length -2220 68/push 0/imm32/top -2221 89/<- %ebx 4/r32/esp -2222 # convert -2223 (populate-mu-function-header _test-input-stream %ecx %ebx) -2224 # check result -2225 (check-strings-equal *ecx "foo" "F - test-function-header-with-arg/name") # Function-name -2226 # edx: (handle list var) = result->inouts -2227 8b/-> *(ecx+8) 2/r32/edx # Function-inouts -2228 # ebx: (handle var) = result->inouts->value -2229 8b/-> *edx 3/r32/ebx # List-value -2230 (check-strings-equal *ebx "n" "F - test-function-header-with-arg/inout:0") # Var-name -2231 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2232 (check-ints-equal *ebx 1 "F - test-function-header-with-arg/inout:0/type:0") # Tree-left -2233 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-arg/inout:0/type:1") # Tree-right -2234 # . epilogue -2235 89/<- %esp 5/r32/ebp -2236 5d/pop-to-ebp -2237 c3/return -2238 -2239 test-function-header-with-multiple-args: -2240 # . prologue -2241 55/push-ebp -2242 89/<- %ebp 4/r32/esp -2243 # setup -2244 (clear-stream _test-input-stream) -2245 (write _test-input-stream "foo a: int, b: int c: int {\n") -2246 # result/ecx: (handle function) -2247 2b/subtract-> *Function-size 4/r32/esp -2248 89/<- %ecx 4/r32/esp -2249 (zero-out %ecx *Function-size) -2250 # var vars/ebx: (stack (addr var) 16) -2251 81 5/subop/subtract %esp 0x10/imm32 -2252 68/push 0x10/imm32/length -2253 68/push 0/imm32/top -2254 89/<- %ebx 4/r32/esp -2255 # convert -2256 (populate-mu-function-header _test-input-stream %ecx %ebx) -2257 # check result -2258 (check-strings-equal *ecx "foo") # Function-name -2259 # edx: (handle list var) = result->inouts -2260 8b/-> *(ecx+8) 2/r32/edx # Function-inouts -2261 $test-function-header-with-multiple-args:inout0: -2262 # ebx: (handle var) = result->inouts->value -2263 8b/-> *edx 3/r32/ebx # List-value -2264 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name -2265 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2266 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:0/type:0") # Tree-left -2267 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:0/type:1") # Tree-right -2268 # edx = result->inouts->next -2269 8b/-> *(edx+4) 2/r32/edx # List-next -2270 $test-function-header-with-multiple-args:inout1: -2271 # ebx = result->inouts->next->value -2272 8b/-> *edx 3/r32/ebx # List-value -2273 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args/inout:1") # Var-name -2274 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2275 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:1/type:0") # Tree-left -2276 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:1/type:1") # Tree-right -2277 # edx = result->inouts->next->next -2278 8b/-> *(edx+4) 2/r32/edx # List-next -2279 $test-function-header-with-multiple-args:inout2: -2280 # ebx = result->inouts->next->next->value -2281 8b/-> *edx 3/r32/ebx # List-value -2282 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args/inout:2") # Var-name -2283 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2284 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:2/type:0") # Tree-left -2285 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:2/type:1") # Tree-right -2286 # . epilogue -2287 89/<- %esp 5/r32/ebp -2288 5d/pop-to-ebp -2289 c3/return -2290 -2291 test-function-with-multiple-args-and-outputs: -2292 # . prologue -2293 55/push-ebp -2294 89/<- %ebp 4/r32/esp -2295 # setup -2296 (clear-stream _test-input-stream) -2297 (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx: int {\n") -2298 # result/ecx: (handle function) -2299 2b/subtract-> *Function-size 4/r32/esp -2300 89/<- %ecx 4/r32/esp -2301 (zero-out %ecx *Function-size) -2302 # var vars/ebx: (stack (addr var) 16) -2303 81 5/subop/subtract %esp 0x10/imm32 -2304 68/push 0x10/imm32/length -2305 68/push 0/imm32/top -2306 89/<- %ebx 4/r32/esp -2307 # convert -2308 (populate-mu-function-header _test-input-stream %ecx %ebx) -2309 # check result -2310 (check-strings-equal *ecx "foo") # Function-name -2311 # edx: (handle list var) = result->inouts -2312 8b/-> *(ecx+8) 2/r32/edx # Function-inouts -2313 # ebx: (handle var) = result->inouts->value -2314 8b/-> *edx 3/r32/ebx # List-value -2315 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0") # Var-name -2316 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2317 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0") # Tree-left -2318 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1") # Tree-right -2319 # edx = result->inouts->next -2320 8b/-> *(edx+4) 2/r32/edx # List-next -2321 # ebx = result->inouts->next->value -2322 8b/-> *edx 3/r32/ebx # List-value -2323 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1") # Var-name -2324 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2325 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0") # Tree-left -2326 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1") # Tree-right -2327 # edx = result->inouts->next->next -2328 8b/-> *(edx+4) 2/r32/edx # List-next -2329 # ebx = result->inouts->next->next->value -2330 8b/-> *edx 3/r32/ebx # List-value -2331 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2") # Var-name -2332 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2333 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0") # Tree-left -2334 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1") # Tree-right -2335 # edx: (handle list var) = result->outputs -2336 8b/-> *(ecx+0xc) 2/r32/edx # Function-outputs -2337 # ebx: (handle var) = result->outputs->value -2338 8b/-> *edx 3/r32/ebx # List-value -2339 (check-strings-equal *ebx "x" "F - test-function-header-with-multiple-args-and-outputs/output:0") # Var-name -2340 (check-strings-equal *(ebx+0x10) "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register -2341 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2342 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-left -2343 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-right -2344 # edx = result->outputs->next -2345 8b/-> *(edx+4) 2/r32/edx # List-next -2346 # ebx = result->outputs->next->value -2347 8b/-> *edx 3/r32/ebx # List-value -2348 (check-strings-equal *ebx "y" "F - test-function-header-with-multiple-args-and-outputs/output:1") # Var-name -2349 (check-strings-equal *(ebx+0x10) "edx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register -2350 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2351 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-left -2352 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-right -2353 # . epilogue -2354 89/<- %esp 5/r32/ebp -2355 5d/pop-to-ebp -2356 c3/return -2357 -2358 # format for variables with types -2359 # x: int -2360 # x: int, -2361 # x/eax: int -2362 # x/eax: int, -2363 # ignores at most one trailing comma -2364 # WARNING: modifies name -2365 parse-var-with-type: # name: (addr slice), first-line: (addr stream byte) -> result/eax: (handle var) -2366 # pseudocode: -2367 # var v: (handle var) = allocate(Heap, Var-size) -2368 # var s: slice -2369 # if (!slice-ends-with(name, ":")) -2370 # abort -2371 # --name->end to skip ':' -2372 # next-token-from-slice(name->start, name->end, '/', s) -2373 # v->name = slice-to-string(s) -2374 # ## register -2375 # next-token-from-slice(s->end, name->end, '/', s) -2376 # if (!slice-empty?(s)) -2377 # v->register = slice-to-string(s) -2378 # ## type -2379 # var type: (handle tree type-id) = parse-type(first-line) -2380 # v->type = type -2381 # return v -2382 # -2383 # . prologue -2384 55/push-ebp -2385 89/<- %ebp 4/r32/esp -2386 # . save registers -2387 51/push-ecx -2388 52/push-edx -2389 53/push-ebx -2390 56/push-esi -2391 57/push-edi -2392 # esi = name -2393 8b/-> *(ebp+8) 6/r32/esi -2394 # if (!slice-ends-with?(name, ":")) abort -2395 8b/-> *(esi+4) 1/r32/ecx # Slice-end -2396 49/decrement-ecx -2397 8a/copy-byte *ecx 1/r32/CL -2398 81 4/subop/and %ecx 0xff/imm32 -2399 81 7/subop/compare %ecx 0x3a/imm32/colon -2400 0f 85/jump-if-!= $parse-var-with-type:abort/disp32 -2401 # --name->end to skip ':' -2402 ff 1/subop/decrement *(esi+4) -2403 # var result/edi: (handle var) = allocate(Heap, Var-size) -2404 (allocate Heap *Var-size) # => eax -2405 (zero-out %eax *Var-size) -2406 89/<- %edi 0/r32/eax -2407 # var s/ecx: slice -2408 68/push 0/imm32/end -2409 68/push 0/imm32/start -2410 89/<- %ecx 4/r32/esp -2411 $parse-var-with-type:save-name: -2412 # save v->name -2413 (next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/' -2414 # . end/edx = s->end -2415 8b/-> *(ecx+4) 2/r32/edx -2416 $parse-var-with-type:write-name: -2417 (slice-to-string Heap %ecx) # => eax -2418 89/<- *edi 0/r32/eax # Var-name -2419 # save v->register -2420 $parse-var-with-type:save-register: -2421 (next-token-from-slice %edx *(esi+4) 0x2f %ecx) # end, name->end, '/' -2422 # if (!slice-empty?(s)) v->register = slice-to-string(s) -2423 { -2424 $parse-var-with-type:write-register: -2425 (slice-empty? %ecx) # => eax -2426 3d/compare-eax-and 0/imm32/false -2427 75/jump-if-!= break/disp8 -2428 (slice-to-string Heap %ecx) -2429 89/<- *(edi+0x10) 0/r32/eax # Var-register -2430 } -2431 $parse-var-with-type:save-type: -2432 (parse-type Heap *(ebp+0xc)) # => eax -2433 89/<- *(edi+4) 0/r32/eax # Var-type -2434 $parse-var-with-type:end: -2435 # return result -2436 89/<- %eax 7/r32/edi -2437 # . reclaim locals -2438 81 0/subop/add %esp 8/imm32 -2439 # . restore registers -2440 5f/pop-to-edi -2441 5e/pop-to-esi -2442 5b/pop-to-ebx -2443 5a/pop-to-edx -2444 59/pop-to-ecx -2445 # . epilogue -2446 89/<- %esp 5/r32/ebp -2447 5d/pop-to-ebp -2448 c3/return -2449 -2450 $parse-var-with-type:abort: -2451 # error("var should have form 'name: type' in '" line "'\n") -2452 (write-buffered Stderr "var should have form 'name: type' in '") -2453 (flush Stderr) -2454 (rewind-stream *(ebp+0xc)) -2455 (write-stream 2 *(ebp+0xc)) -2456 (write-buffered Stderr "'\n") -2457 (flush Stderr) -2458 # . syscall(exit, 1) -2459 bb/copy-to-ebx 1/imm32 -2460 b8/copy-to-eax 1/imm32/exit -2461 cd/syscall 0x80/imm8 -2462 # never gets here -2463 -2464 parse-type: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) -2465 # pseudocode: -2466 # var s: slice = next-mu-token(in) -2467 # assert s != "" -2468 # assert s != "->" -2469 # assert s != "{" -2470 # assert s != "}" -2471 # if s == ")" -2472 # return 0 -2473 # result = allocate(Tree) -2474 # zero-out(result, *Tree-size) -2475 # if s != "(" -2476 # result->left = pos-slice(Type-id, s) -2477 # return -2478 # result->left = parse-type(ad, in) -2479 # result->right = parse-type-tree(ad, in) -2480 # -2481 # . prologue -2482 55/push-ebp -2483 89/<- %ebp 4/r32/esp -2484 # . save registers -2485 51/push-ecx -2486 52/push-edx -2487 # var s/ecx: slice -2488 68/push 0/imm32 -2489 68/push 0/imm32 -2490 89/<- %ecx 4/r32/esp -2491 # s = next-mu-token(in) -2492 (next-mu-token *(ebp+0xc) %ecx) -2493 #? (write-buffered Stderr "tok: ") -2494 #? (write-slice-buffered Stderr %ecx) -2495 #? (write-buffered Stderr "$\n") -2496 #? (flush Stderr) -2497 # assert s != "" -2498 (slice-equal? %ecx "") -2499 3d/compare-eax-and 0/imm32/false -2500 0f 85/jump-if-!= $parse-type:abort/disp32 -2501 # assert s != "{" -2502 (slice-equal? %ecx "{") -2503 3d/compare-eax-and 0/imm32/false -2504 0f 85/jump-if-!= $parse-type:abort/disp32 -2505 # assert s != "}" -2506 (slice-equal? %ecx "}") -2507 3d/compare-eax-and 0/imm32/false -2508 0f 85/jump-if-!= $parse-type:abort/disp32 -2509 # assert s != "->" -2510 (slice-equal? %ecx "->") -2511 3d/compare-eax-and 0/imm32/false -2512 0f 85/jump-if-!= $parse-type:abort/disp32 -2513 # if (s == ")") return 0 -2514 (slice-equal? %ecx ")") -2515 3d/compare-eax-and 0/imm32/false -2516 b8/copy-to-eax 0/imm32 -2517 0f 85/jump-if-!= $parse-type:end/disp32 -2518 # var result/edx: (handle tree type-id) -2519 (allocate *(ebp+8) *Tree-size) # => eax -2520 (zero-out %eax *Tree-size) -2521 89/<- %edx 0/r32/eax -2522 { -2523 # if (s != "(") break -2524 (slice-equal? %ecx "(") -2525 3d/compare-eax-and 0/imm32/false -2526 75/jump-if-!= break/disp8 -2527 # result->left = pos-slice(Type-id, s) -2528 (pos-slice Type-id %ecx) -2529 #? (write-buffered Stderr "=> {") -2530 #? (print-int32-buffered Stderr %eax) -2531 #? (write-buffered Stderr ", 0}\n") -2532 #? (flush Stderr) -2533 89/<- *edx 0/r32/eax # Tree-left -2534 e9/jump $parse-type:return-edx/disp32 -2535 } -2536 # otherwise s == "(" -2537 # result->left = parse-type(ad, in) -2538 (parse-type *(ebp+8) *(ebp+0xc)) -2539 #? (write-buffered Stderr "=> {") -2540 #? (print-int32-buffered Stderr %eax) -2541 89/<- *edx 0/r32/eax # Tree-left -2542 # result->right = parse-type-tree(ad, in) -2543 (parse-type-tree *(ebp+8) *(ebp+0xc)) -2544 #? (write-buffered Stderr Space) -2545 #? (print-int32-buffered Stderr %eax) -2546 #? (write-buffered Stderr "}\n") -2547 #? (flush Stderr) -2548 89/<- *(edx+4) 0/r32/eax # Tree-right -2549 $parse-type:return-edx: -2550 89/<- %eax 2/r32/edx -2551 $parse-type:end: -2552 # . reclaim locals -2553 81 0/subop/add %esp 8/imm32 -2554 # . restore registers -2555 5a/pop-to-edx -2556 59/pop-to-ecx -2557 # . epilogue -2558 89/<- %esp 5/r32/ebp -2559 5d/pop-to-ebp -2560 c3/return -2561 -2562 $parse-type:abort: -2563 # error("unexpected token when parsing type: '" s "'\n") -2564 (write-buffered Stderr "unexpected token when parsing type: '") -2565 (write-slice-buffered Stderr %ecx) -2566 (write-buffered Stderr "'\n") -2567 (flush Stderr) -2568 # . syscall(exit, 1) -2569 bb/copy-to-ebx 1/imm32 -2570 b8/copy-to-eax 1/imm32/exit -2571 cd/syscall 0x80/imm8 -2572 # never gets here -2573 -2574 parse-type-tree: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) -2575 # pseudocode: -2576 # var tmp: (handle tree type-id) = parse-type(ad, in) -2577 # if tmp == 0 -2578 # return 0 -2579 # result = allocate(Tree) -2580 # zero-out(result, *Tree-size) -2581 # result->left = tmp -2582 # result->right = parse-type-tree(ad, in) -2583 # -2584 # . prologue -2585 55/push-ebp -2586 89/<- %ebp 4/r32/esp -2587 # . save registers -2588 51/push-ecx -2589 52/push-edx -2590 # var tmp/eax: (handle tree type-id) = parse-type(ad, in) -2591 (parse-type *(ebp+8) *(ebp+0xc)) -2592 # if (tmp == 0) return tmp -2593 3d/compare-eax-and 0/imm32 -2594 74/jump-if-= $parse-type-tree:end/disp8 -2595 # var tmp2/ecx = tmp -2596 89/<- %ecx 0/r32/eax -2597 # var result/edx: (handle tree type-id) -2598 (allocate *(ebp+8) *Tree-size) # => eax -2599 (zero-out %eax *Tree-size) -2600 89/<- %edx 0/r32/eax -2601 # result->left = tmp2 -2602 89/<- *edx 1/r32/ecx # Tree-left -2603 # result->right = parse-type-tree(ad, in) -2604 (parse-type-tree *(ebp+8) *(ebp+0xc)) -2605 89/<- *(edx+4) 0/r32/eax # Tree-right -2606 $parse-type-tree:return-edx: -2607 89/<- %eax 2/r32/edx -2608 $parse-type-tree:end: -2609 # . restore registers -2610 5a/pop-to-edx -2611 59/pop-to-ecx -2612 # . epilogue -2613 89/<- %esp 5/r32/ebp -2614 5d/pop-to-ebp -2615 c3/return -2616 -2617 next-mu-token: # in: (addr stream byte), out: (addr slice) -2618 # pseudocode: -2619 # start: -2620 # skip-chars-matching-whitespace(in) -2621 # if in->read >= in->write # end of in -2622 # out = {0, 0} -2623 # return -2624 # out->start = &in->data[in->read] -2625 # var curr-byte/eax: byte = in->data[in->read] -2626 # if curr->byte == ',' # comment token -2627 # ++in->read -2628 # goto start -2629 # if curr-byte == '#' # comment -2630 # goto done # treat as eof -2631 # if curr-byte == '"' # string literal -2632 # skip-string(in) -2633 # goto done # no metadata -2634 # if curr-byte == '(' -2635 # ++in->read -2636 # goto done -2637 # if curr-byte == ')' -2638 # ++in->read -2639 # goto done -2640 # # read a word -2641 # while true -2642 # if in->read >= in->write -2643 # break -2644 # curr-byte = in->data[in->read] -2645 # if curr-byte == ' ' -2646 # break -2647 # if curr-byte == '\r' -2648 # break -2649 # if curr-byte == '\n' -2650 # break -2651 # if curr-byte == '(' -2652 # break -2653 # if curr-byte == ')' -2654 # break -2655 # if curr-byte == ',' -2656 # break -2657 # ++in->read -2658 # done: -2659 # out->end = &in->data[in->read] -2660 # -2661 # . prologue -2662 55/push-ebp -2663 89/<- %ebp 4/r32/esp -2664 # . save registers -2665 50/push-eax -2666 51/push-ecx -2667 56/push-esi -2668 57/push-edi -2669 # esi = in -2670 8b/-> *(ebp+8) 6/r32/esi -2671 # edi = out -2672 8b/-> *(ebp+0xc) 7/r32/edi -2673 $next-mu-token:start: -2674 (skip-chars-matching-whitespace %esi) -2675 $next-mu-token:check0: -2676 # if (in->read >= in->write) return out = {0, 0} -2677 # . ecx = in->read -2678 8b/-> *(esi+4) 1/r32/ecx -2679 # . if (ecx >= in->write) return out = {0, 0} -2680 3b/compare 1/r32/ecx *esi -2681 c7 0/subop/copy *edi 0/imm32 -2682 c7 0/subop/copy *(edi+4) 0/imm32 -2683 0f 8d/jump-if->= $next-mu-token:end/disp32 -2684 # out->start = &in->data[in->read] -2685 8d/copy-address *(esi+ecx+0xc) 0/r32/eax -2686 89/<- *edi 0/r32/eax -2687 # var curr-byte/eax: byte = in->data[in->read] -2688 31/xor %eax 0/r32/eax -2689 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -2690 { -2691 $next-mu-token:check-for-comma: -2692 # if (curr-byte != ',') break -2693 3d/compare-eax-and 0x2c/imm32/comma -2694 75/jump-if-!= break/disp8 -2695 # ++in->read -2696 ff 0/subop/increment *(esi+4) -2697 # restart -2698 e9/jump $next-mu-token:start/disp32 -2699 } -2700 { -2701 $next-mu-token:check-for-comment: -2702 # if (curr-byte != '#') break -2703 3d/compare-eax-and 0x23/imm32/pound -2704 75/jump-if-!= break/disp8 -2705 # return eof -2706 e9/jump $next-mu-token:done/disp32 -2707 } -2708 { -2709 $next-mu-token:check-for-string-literal: -2710 # if (curr-byte != '"') break -2711 3d/compare-eax-and 0x22/imm32/dquote -2712 75/jump-if-!= break/disp8 -2713 (skip-string %esi) -2714 # return -2715 e9/jump $next-mu-token:done/disp32 -2716 } -2717 { -2718 $next-mu-token:check-for-open-paren: -2719 # if (curr-byte != '(') break -2720 3d/compare-eax-and 0x28/imm32/open-paren -2721 75/jump-if-!= break/disp8 -2722 # ++in->read -2723 ff 0/subop/increment *(esi+4) -2724 # return -2725 e9/jump $next-mu-token:done/disp32 -2726 } -2727 { -2728 $next-mu-token:check-for-close-paren: -2729 # if (curr-byte != ')') break -2730 3d/compare-eax-and 0x29/imm32/close-paren -2731 75/jump-if-!= break/disp8 -2732 # ++in->read -2733 ff 0/subop/increment *(esi+4) -2734 # return -2735 e9/jump $next-mu-token:done/disp32 -2736 } -2737 { -2738 $next-mu-token:regular-word-without-metadata: -2739 # if (in->read >= in->write) break -2740 # . ecx = in->read -2741 8b/-> *(esi+4) 1/r32/ecx -2742 # . if (ecx >= in->write) break -2743 3b/compare *esi 1/r32/ecx -2744 7d/jump-if->= break/disp8 -2745 # var c/eax: byte = in->data[in->read] -2746 31/xor %eax 0/r32/eax -2747 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -2748 # if (c == ' ') break -2749 3d/compare-eax-and 0x20/imm32/space -2750 74/jump-if-= break/disp8 -2751 # if (c == '\r') break -2752 3d/compare-eax-and 0xd/imm32/carriage-return -2753 74/jump-if-= break/disp8 -2754 # if (c == '\n') break -2755 3d/compare-eax-and 0xa/imm32/newline -2756 74/jump-if-= break/disp8 -2757 # if (c == '(') break -2758 3d/compare-eax-and 0x28/imm32/open-paren -2759 0f 84/jump-if-= break/disp32 -2760 # if (c == ')') break -2761 3d/compare-eax-and 0x29/imm32/close-paren -2762 0f 84/jump-if-= break/disp32 -2763 # if (c == ',') break -2764 3d/compare-eax-and 0x2c/imm32/comma -2765 0f 84/jump-if-= break/disp32 -2766 # ++in->read -2767 ff 0/subop/increment *(esi+4) -2768 # -2769 e9/jump loop/disp32 -2770 } -2771 $next-mu-token:done: -2772 # out->end = &in->data[in->read] -2773 8b/-> *(esi+4) 1/r32/ecx -2774 8d/copy-address *(esi+ecx+0xc) 0/r32/eax -2775 89/<- *(edi+4) 0/r32/eax -2776 $next-mu-token:end: -2777 # . restore registers -2778 5f/pop-to-edi -2779 5e/pop-to-esi -2780 59/pop-to-ecx -2781 58/pop-to-eax -2782 # . epilogue -2783 89/<- %esp 5/r32/ebp -2784 5d/pop-to-ebp -2785 c3/return -2786 -2787 # return the index in an array of strings matching 's' -2788 # index is denominated in elements, not bytes -2789 pos-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int -2790 # . prologue -2791 55/push-ebp -2792 89/<- %ebp 4/r32/esp -2793 # . save registers -2794 51/push-ecx -2795 52/push-edx -2796 53/push-ebx -2797 56/push-esi -2798 #? (write-buffered Stderr "pos-slice: ") -2799 #? (write-slice-buffered Stderr *(ebp+0xc)) -2800 #? (write-buffered Stderr "\n") -2801 #? (flush Stderr) -2802 # esi = arr -2803 8b/-> *(ebp+8) 6/r32/esi -2804 # var index/ecx: int = 0 -2805 b9/copy-to-ecx 0/imm32 -2806 # var curr/edx: (addr (addr array byte)) = arr->data -2807 8d/copy-address *(esi+0xc) 2/r32/edx -2808 # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write] -2809 8b/-> *esi 3/r32/ebx -2810 8d/copy-address *(esi+ebx+0xc) 3/r32/ebx -2811 { -2812 #? (write-buffered Stderr " ") -2813 #? (print-int32-buffered Stderr %ecx) -2814 #? (write-buffered Stderr "\n") -2815 #? (flush Stderr) -2816 # if (curr >= max) return -1 -2817 39/compare %edx 3/r32/ebx -2818 b8/copy-to-eax -1/imm32 -2819 73/jump-if-addr>= $pos-slice:end/disp8 -2820 # if (slice-equal?(s, *curr)) break -2821 (slice-equal? *(ebp+0xc) *edx) # => eax -2822 3d/compare-eax-and 0/imm32/false -2823 75/jump-if-!= break/disp8 -2824 # ++index -2825 41/increment-ecx -2826 # curr += 4 -2827 81 0/subop/add %edx 4/imm32 -2828 # -2829 eb/jump loop/disp8 -2830 } -2831 # return index -2832 89/<- %eax 1/r32/ecx -2833 $pos-slice:end: -2834 #? (write-buffered Stderr "=> ") -2835 #? (print-int32-buffered Stderr %eax) -2836 #? (write-buffered Stderr "\n") -2837 # . restore registers -2838 5e/pop-to-esi -2839 5b/pop-to-ebx -2840 5a/pop-to-edx -2841 59/pop-to-ecx -2842 # . epilogue -2843 89/<- %esp 5/r32/ebp -2844 5d/pop-to-ebp -2845 c3/return -2846 -2847 == data -2848 -2849 Type-id: # (stream (address array byte)) -2850 0x18/imm32/write -2851 0/imm32/read -2852 0x100/imm32/length -2853 # data -2854 "literal"/imm32 # 0 -2855 "int"/imm32 # 1 -2856 "addr"/imm32 # 2 -2857 "array"/imm32 # 3 -2858 "handle"/imm32 # 4 -2859 "bool"/imm32 # 5 -2860 0/imm32 -2861 0/imm32 -2862 # 0x20 -2863 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2864 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2865 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2866 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2867 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2868 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2869 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2870 -2871 == code -2872 -2873 test-parse-var-with-type: -2874 # . prologue -2875 55/push-ebp -2876 89/<- %ebp 4/r32/esp -2877 # (eax..ecx) = "x:" -2878 b8/copy-to-eax "x:"/imm32 -2879 8b/-> *eax 1/r32/ecx -2880 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2881 05/add-to-eax 4/imm32 -2882 # var slice/ecx: slice = {eax, ecx} -2883 51/push-ecx -2884 50/push-eax -2885 89/<- %ecx 4/r32/esp -2886 # _test-input-stream contains "int" -2887 (clear-stream _test-input-stream) -2888 (write _test-input-stream "int") -2889 # -2890 (parse-var-with-type %ecx _test-input-stream) -2891 8b/-> *eax 2/r32/edx # Var-name -2892 (check-strings-equal %edx "x" "F - test-var-with-type/name") -2893 8b/-> *(eax+4) 2/r32/edx # Var-type -2894 (check-ints-equal *edx 1 "F - test-var-with-type/type") -2895 (check-ints-equal *(edx+4) 0 "F - test-var-with-type/type") -2896 # . epilogue -2897 89/<- %esp 5/r32/ebp -2898 5d/pop-to-ebp -2899 c3/return -2900 -2901 test-parse-var-with-type-and-register: -2902 # . prologue -2903 55/push-ebp -2904 89/<- %ebp 4/r32/esp -2905 # (eax..ecx) = "x/eax:" -2906 b8/copy-to-eax "x/eax:"/imm32 -2907 8b/-> *eax 1/r32/ecx -2908 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2909 05/add-to-eax 4/imm32 -2910 # var slice/ecx: slice = {eax, ecx} -2911 51/push-ecx -2912 50/push-eax -2913 89/<- %ecx 4/r32/esp -2914 # _test-input-stream contains "int" -2915 (clear-stream _test-input-stream) -2916 (write _test-input-stream "int") -2917 # -2918 (parse-var-with-type %ecx _test-input-stream) -2919 8b/-> *eax 2/r32/edx # Var-name -2920 (check-strings-equal %edx "x" "F - test-var-with-type-and-register/name") -2921 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2922 (check-strings-equal %edx "eax" "F - test-var-with-type-and-register/register") -2923 8b/-> *(eax+4) 2/r32/edx # Var-type -2924 (check-ints-equal *edx 1 "F - test-var-with-type-and-register/type") -2925 (check-ints-equal *(edx+4) 0 "F - test-var-with-type-and-register/type") -2926 # . epilogue -2927 89/<- %esp 5/r32/ebp -2928 5d/pop-to-ebp -2929 c3/return -2930 -2931 test-parse-var-with-trailing-characters: -2932 # . prologue -2933 55/push-ebp -2934 89/<- %ebp 4/r32/esp -2935 # (eax..ecx) = "x:" -2936 b8/copy-to-eax "x:"/imm32 -2937 8b/-> *eax 1/r32/ecx -2938 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2939 05/add-to-eax 4/imm32 -2940 # var slice/ecx: slice = {eax, ecx} -2941 51/push-ecx -2942 50/push-eax -2943 89/<- %ecx 4/r32/esp -2944 # _test-input-stream contains "int," -2945 (clear-stream _test-input-stream) -2946 (write _test-input-stream "int,") -2947 # -2948 (parse-var-with-type %ecx _test-input-stream) -2949 8b/-> *eax 2/r32/edx # Var-name -2950 (check-strings-equal %edx "x" "F - test-var-with-trailing-characters/name") -2951 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2952 (check-ints-equal %edx 0 "F - test-var-with-trailing-characters/register") -2953 8b/-> *(eax+4) 2/r32/edx # Var-type -2954 (check-ints-equal *edx 1 "F - test-var-with-trailing-characters/type") -2955 (check-ints-equal *(edx+4) 0 "F - test-var-with-trailing-characters/type") -2956 # . epilogue -2957 89/<- %esp 5/r32/ebp -2958 5d/pop-to-ebp -2959 c3/return -2960 -2961 test-parse-var-with-register-and-trailing-characters: -2962 # . prologue -2963 55/push-ebp -2964 89/<- %ebp 4/r32/esp -2965 # (eax..ecx) = "x/eax:" -2966 b8/copy-to-eax "x/eax:"/imm32 -2967 8b/-> *eax 1/r32/ecx -2968 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2969 05/add-to-eax 4/imm32 -2970 # var slice/ecx: slice = {eax, ecx} -2971 51/push-ecx -2972 50/push-eax -2973 89/<- %ecx 4/r32/esp -2974 # _test-input-stream contains "int," -2975 (clear-stream _test-input-stream) -2976 (write _test-input-stream "int,") -2977 # -2978 (parse-var-with-type %ecx _test-input-stream) -2979 8b/-> *eax 2/r32/edx # Var-name -2980 (check-strings-equal %edx "x" "F - test-var-with-register-and-trailing-characters/name") -2981 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2982 (check-strings-equal %edx "eax" "F - test-var-with-register-and-trailing-characters/register") -2983 8b/-> *(eax+4) 2/r32/edx # Var-type -2984 (check-ints-equal *edx 1 "F - test-var-with-register-and-trailing-characters/type") -2985 (check-ints-equal *(edx+4) 0 "F - test-var-with-register-and-trailing-characters/type") -2986 # . epilogue -2987 89/<- %esp 5/r32/ebp -2988 5d/pop-to-ebp -2989 c3/return -2990 -2991 test-parse-var-with-compound-type: -2992 # . prologue -2993 55/push-ebp -2994 89/<- %ebp 4/r32/esp -2995 # (eax..ecx) = "x:" -2996 b8/copy-to-eax "x:"/imm32 -2997 8b/-> *eax 1/r32/ecx -2998 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2999 05/add-to-eax 4/imm32 -3000 # var slice/ecx: slice = {eax, ecx} -3001 51/push-ecx -3002 50/push-eax -3003 89/<- %ecx 4/r32/esp -3004 # _test-input-stream contains "(addr int)" -3005 (clear-stream _test-input-stream) -3006 (write _test-input-stream "(addr int)") -3007 # -3008 (parse-var-with-type %ecx _test-input-stream) -3009 8b/-> *eax 2/r32/edx # Var-name -3010 (check-strings-equal %edx "x" "F - test-var-with-compound-type/name") -3011 8b/-> *(eax+0x10) 2/r32/edx # Var-register -3012 (check-ints-equal %edx 0 "F - test-var-with-compound-type/register") -3013 # var type/edx: (handle tree type-id) = var->type -3014 8b/-> *(eax+4) 2/r32/edx # Var-type -3015 # type->left == atom(addr) -3016 8b/-> *edx 0/r32/eax # Atom-value -3017 (check-ints-equal *eax 2 "F - test-var-with-compound-type/type:0") # Tree-left -3018 # type->right->left == atom(int) -3019 8b/-> *(edx+4) 2/r32/edx # Tree-right -3020 8b/-> *edx 0/r32/eax # Tree-left -3021 (check-ints-equal *eax 1 "F - test-var-with-compound-type/type:1") # Atom-value -3022 # type->right->right == null -3023 (check-ints-equal *(edx+4) 0 "F - test-var-with-compound-type/type:2") # Tree-right -3024 # . epilogue -3025 89/<- %esp 5/r32/ebp -3026 5d/pop-to-ebp -3027 c3/return -3028 -3029 # identifier starts with a letter or '$' or '_' -3030 # no constraints at the moment on later letters -3031 # all we really want to do so far is exclude '{', '}' and '->' -3032 is-identifier?: # in: (addr slice) -> result/eax: boolean -3033 # . prologue -3034 55/push-ebp -3035 89/<- %ebp 4/r32/esp -3036 # if (slice-empty?(in)) return false -3037 (slice-empty? *(ebp+8)) # => eax -3038 3d/compare-eax-and 0/imm32/false -3039 75/jump-if-!= $is-identifier?:false/disp8 -3040 # var c/eax: byte = *in->start -3041 8b/-> *(ebp+8) 0/r32/eax -3042 8b/-> *eax 0/r32/eax -3043 8a/copy-byte *eax 0/r32/AL -3044 81 4/subop/and %eax 0xff/imm32 -3045 # if (c == '$') return true -3046 3d/compare-eax-and 0x24/imm32/$ -3047 74/jump-if-= $is-identifier?:true/disp8 -3048 # if (c == '_') return true -3049 3d/compare-eax-and 0x5f/imm32/_ -3050 74/jump-if-= $is-identifier?:true/disp8 -3051 # drop case -3052 25/and-eax-with 0x5f/imm32 -3053 # if (c < 'A') return false -3054 3d/compare-eax-and 0x41/imm32/A -3055 7c/jump-if-< $is-identifier?:false/disp8 -3056 # if (c > 'Z') return false -3057 3d/compare-eax-and 0x5a/imm32/Z -3058 7f/jump-if-> $is-identifier?:false/disp8 -3059 # otherwise return true -3060 $is-identifier?:true: -3061 b8/copy-to-eax 1/imm32/true -3062 eb/jump $is-identifier?:end/disp8 -3063 $is-identifier?:false: -3064 b8/copy-to-eax 0/imm32/false -3065 $is-identifier?:end: -3066 # . epilogue -3067 89/<- %esp 5/r32/ebp -3068 5d/pop-to-ebp -3069 c3/return -3070 -3071 test-is-identifier-dollar: -3072 # . prologue -3073 55/push-ebp -3074 89/<- %ebp 4/r32/esp -3075 # (eax..ecx) = "$a" -3076 b8/copy-to-eax "$a"/imm32 -3077 8b/-> *eax 1/r32/ecx -3078 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3079 05/add-to-eax 4/imm32 -3080 # var slice/ecx: slice = {eax, ecx} -3081 51/push-ecx -3082 50/push-eax -3083 89/<- %ecx 4/r32/esp -3084 # -3085 (is-identifier? %ecx) -3086 (check-ints-equal %eax 1 "F - test-is-identifier-dollar") -3087 # . epilogue -3088 89/<- %esp 5/r32/ebp -3089 5d/pop-to-ebp -3090 c3/return -3091 -3092 test-is-identifier-underscore: -3093 # . prologue -3094 55/push-ebp -3095 89/<- %ebp 4/r32/esp -3096 # (eax..ecx) = "_a" -3097 b8/copy-to-eax "_a"/imm32 -3098 8b/-> *eax 1/r32/ecx -3099 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3100 05/add-to-eax 4/imm32 -3101 # var slice/ecx: slice = {eax, ecx} -3102 51/push-ecx -3103 50/push-eax -3104 89/<- %ecx 4/r32/esp -3105 # -3106 (is-identifier? %ecx) -3107 (check-ints-equal %eax 1 "F - test-is-identifier-underscore") -3108 # . epilogue -3109 89/<- %esp 5/r32/ebp -3110 5d/pop-to-ebp -3111 c3/return -3112 -3113 test-is-identifier-a: -3114 # . prologue -3115 55/push-ebp -3116 89/<- %ebp 4/r32/esp -3117 # (eax..ecx) = "a$" -3118 b8/copy-to-eax "a$"/imm32 -3119 8b/-> *eax 1/r32/ecx -3120 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3121 05/add-to-eax 4/imm32 -3122 # var slice/ecx: slice = {eax, ecx} -3123 51/push-ecx -3124 50/push-eax -3125 89/<- %ecx 4/r32/esp -3126 # -3127 (is-identifier? %ecx) -3128 (check-ints-equal %eax 1 "F - test-is-identifier-a") -3129 # . epilogue -3130 89/<- %esp 5/r32/ebp -3131 5d/pop-to-ebp -3132 c3/return -3133 -3134 test-is-identifier-z: -3135 # . prologue -3136 55/push-ebp -3137 89/<- %ebp 4/r32/esp -3138 # (eax..ecx) = "z$" -3139 b8/copy-to-eax "z$"/imm32 -3140 8b/-> *eax 1/r32/ecx -3141 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3142 05/add-to-eax 4/imm32 -3143 # var slice/ecx: slice = {eax, ecx} -3144 51/push-ecx -3145 50/push-eax -3146 89/<- %ecx 4/r32/esp -3147 # -3148 (is-identifier? %ecx) -3149 (check-ints-equal %eax 1 "F - test-is-identifier-z") -3150 # . epilogue -3151 89/<- %esp 5/r32/ebp -3152 5d/pop-to-ebp -3153 c3/return -3154 -3155 test-is-identifier-A: -3156 # . prologue -3157 55/push-ebp -3158 89/<- %ebp 4/r32/esp -3159 # (eax..ecx) = "A$" -3160 b8/copy-to-eax "A$"/imm32 -3161 8b/-> *eax 1/r32/ecx -3162 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3163 05/add-to-eax 4/imm32 -3164 # var slice/ecx: slice = {eax, ecx} -3165 51/push-ecx -3166 50/push-eax -3167 89/<- %ecx 4/r32/esp -3168 # -3169 (is-identifier? %ecx) -3170 (check-ints-equal %eax 1 "F - test-is-identifier-A") -3171 # . epilogue -3172 89/<- %esp 5/r32/ebp -3173 5d/pop-to-ebp -3174 c3/return -3175 -3176 test-is-identifier-Z: -3177 # . prologue -3178 55/push-ebp -3179 89/<- %ebp 4/r32/esp -3180 # (eax..ecx) = "Z$" -3181 b8/copy-to-eax "Z$"/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 1 "F - test-is-identifier-Z") -3192 # . epilogue -3193 89/<- %esp 5/r32/ebp -3194 5d/pop-to-ebp -3195 c3/return -3196 -3197 test-is-identifier-@: -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-@") -3214 # . epilogue -3215 89/<- %esp 5/r32/ebp -3216 5d/pop-to-ebp -3217 c3/return -3218 -3219 test-is-identifier-square-bracket: -3220 # character after 'Z' is invalid -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-@") -3236 # . epilogue -3237 89/<- %esp 5/r32/ebp -3238 5d/pop-to-ebp -3239 c3/return -3240 -3241 test-is-identifier-backtick: -3242 # character before 'a' is invalid -3243 # . prologue -3244 55/push-ebp -3245 89/<- %ebp 4/r32/esp -3246 # (eax..ecx) = "`a" -3247 b8/copy-to-eax "`a"/imm32 -3248 8b/-> *eax 1/r32/ecx -3249 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3250 05/add-to-eax 4/imm32 -3251 # var slice/ecx: slice = {eax, ecx} -3252 51/push-ecx -3253 50/push-eax -3254 89/<- %ecx 4/r32/esp -3255 # -3256 (is-identifier? %ecx) -3257 (check-ints-equal %eax 0 "F - test-is-identifier-backtick") -3258 # . epilogue -3259 89/<- %esp 5/r32/ebp -3260 5d/pop-to-ebp -3261 c3/return -3262 -3263 test-is-identifier-curly-brace-open: -3264 # character after 'z' is invalid; also used for blocks -3265 # . prologue -3266 55/push-ebp -3267 89/<- %ebp 4/r32/esp -3268 # (eax..ecx) = "{a" -3269 b8/copy-to-eax "{a"/imm32 -3270 8b/-> *eax 1/r32/ecx -3271 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3272 05/add-to-eax 4/imm32 -3273 # var slice/ecx: slice = {eax, ecx} -3274 51/push-ecx -3275 50/push-eax -3276 89/<- %ecx 4/r32/esp -3277 # -3278 (is-identifier? %ecx) -3279 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open") -3280 # . epilogue -3281 89/<- %esp 5/r32/ebp -3282 5d/pop-to-ebp -3283 c3/return -3284 -3285 test-is-identifier-curly-brace-close: -3286 # . prologue -3287 55/push-ebp -3288 89/<- %ebp 4/r32/esp -3289 # (eax..ecx) = "}a" -3290 b8/copy-to-eax "}a"/imm32 -3291 8b/-> *eax 1/r32/ecx -3292 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3293 05/add-to-eax 4/imm32 -3294 # var slice/ecx: slice = {eax, ecx} -3295 51/push-ecx -3296 50/push-eax -3297 89/<- %ecx 4/r32/esp -3298 # -3299 (is-identifier? %ecx) -3300 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close") -3301 # . epilogue -3302 89/<- %esp 5/r32/ebp -3303 5d/pop-to-ebp -3304 c3/return -3305 -3306 test-is-identifier-hyphen: -3307 # disallow leading '-' since '->' has special meaning -3308 # . prologue -3309 55/push-ebp -3310 89/<- %ebp 4/r32/esp -3311 # (eax..ecx) = "-a" -3312 b8/copy-to-eax "-a"/imm32 -3313 8b/-> *eax 1/r32/ecx -3314 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3315 05/add-to-eax 4/imm32 -3316 # var slice/ecx: slice = {eax, ecx} -3317 51/push-ecx -3318 50/push-eax -3319 89/<- %ecx 4/r32/esp -3320 # -3321 (is-identifier? %ecx) -3322 (check-ints-equal %eax 0 "F - test-is-identifier-hyphen") -3323 # . epilogue -3324 89/<- %esp 5/r32/ebp -3325 5d/pop-to-ebp -3326 c3/return -3327 -3328 populate-mu-function-body: # in: (addr buffered-file), out: (handle function), vars: (addr stack (handle var)) -3329 # . prologue -3330 55/push-ebp -3331 89/<- %ebp 4/r32/esp -3332 # . save registers -3333 50/push-eax -3334 56/push-esi -3335 57/push-edi -3336 # esi = in -3337 8b/-> *(ebp+8) 6/r32/esi -3338 # edi = out -3339 8b/-> *(ebp+0xc) 7/r32/edi -3340 # initialize some global state -3341 c7 0/subop/copy *Curr-block-depth 1/imm32 -3342 c7 0/subop/copy *Next-local-stack-offset -4/imm32 -3343 # var eax: (handle block) = parse-mu-block(in, vars, fn) -3344 (parse-mu-block %esi *(ebp+0x10) %edi) # => eax -3345 # out->body = eax -3346 89/<- *(edi+0x10) 0/r32/eax # Function-body -3347 $populate-mu-function-body:end: -3348 # . restore registers -3349 5f/pop-to-edi -3350 5e/pop-to-esi -3351 58/pop-to-eax -3352 # . epilogue -3353 89/<- %esp 5/r32/ebp -3354 5d/pop-to-ebp -3355 c3/return -3356 -3357 == data -3358 -3359 # Global state added to each var record when parsing a function -3360 -3361 Curr-block-depth: # (addr int) -3362 0/imm32 -3363 Next-local-stack-offset: # (addr int) -3364 -4/imm32 -3365 -3366 Next-block-index: # (addr int) -3367 1/imm32 -3368 -3369 == code -3370 -3371 # parses a block, assuming that the leading '{' has already been read by the caller -3372 parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle block) -3373 # pseudocode: -3374 # var line: (stream byte 512) -3375 # var word-slice: slice -3376 # increment *Curr-block-depth -3377 # result/eax = allocate(Heap, Stmt-size) -3378 # result->tag = 0/block -3379 # result->name = some unique name -3380 # while true # line loop -3381 # clear-stream(line) -3382 # read-line-buffered(in, line) -3383 # if (line->write == 0) break # end of file -3384 # word-slice = next-mu-token(line) -3385 # if slice-empty?(word-slice) # end of line -3386 # continue -3387 # else if slice-starts-with?(word-slice, "#") -3388 # continue -3389 # else if slice-equal?(word-slice, "{") -3390 # assert(no-tokens-in(line)) -3391 # block = parse-mu-block(in, vars, fn) -3392 # append-to-block(result, block) -3393 # else if slice-equal?(word-slice, "}") -3394 # break -3395 # else if slice-ends-with?(word-slice, ":") -3396 # # TODO: error-check the rest of 'line' -3397 # --word-slice->end to skip ':' -3398 # named-block = parse-mu-named-block(word-slice, in, vars, fn) -3399 # append-to-block(result, named-block) -3400 # else if slice-equal?(word-slice, "var") -3401 # var-def = parse-mu-var-def(line, vars) -3402 # append-to-block(result, var-def) -3403 # else -3404 # stmt = parse-mu-stmt(line, vars, fn) -3405 # append-to-block(result, stmt) -3406 # decrement *Curr-block-depth -3407 # return result -3408 # -3409 # . prologue -3410 55/push-ebp -3411 89/<- %ebp 4/r32/esp -3412 # . save registers -3413 51/push-ecx -3414 52/push-edx -3415 53/push-ebx -3416 57/push-edi -3417 # var line/ecx: (stream byte 512) -3418 81 5/subop/subtract %esp 0x200/imm32 -3419 68/push 0x200/imm32/length -3420 68/push 0/imm32/read -3421 68/push 0/imm32/write -3422 89/<- %ecx 4/r32/esp -3423 # var word-slice/edx: slice -3424 68/push 0/imm32/end -3425 68/push 0/imm32/start -3426 89/<- %edx 4/r32/esp -3427 # edi = result -3428 (allocate Heap *Stmt-size) # => eax -3429 (zero-out %eax *Stmt-size) -3430 89/<- %edi 0/r32/eax -3431 # set result->tag -3432 c7 0/subop/copy *edi 0/imm32/block # Stmt-tag -3433 # set result->var -3434 (new-block-name *(ebp+0x10)) # => eax -3435 89/<- *(edi+8) 0/r32/eax # Block-var -3436 # push result->var to vars -3437 (push *(ebp+0xc) %eax) -3438 # increment *Curr-block-depth -3439 ff 0/subop/increment *Curr-block-depth -3440 { -3441 $parse-mu-block:line-loop: -3442 # line = read-line-buffered(in) -3443 (clear-stream %ecx) -3444 (read-line-buffered *(ebp+8) %ecx) -3445 #? (write-buffered Stderr "line: ") -3446 #? (write-stream-data Stderr %ecx) -3447 #? (write-buffered Stderr Newline) -3448 #? (flush Stderr) -3449 # if (line->write == 0) break -3450 81 7/subop/compare *ecx 0/imm32 -3451 0f 84/jump-if-= break/disp32 -3452 # word-slice = next-mu-token(line) -3453 (next-mu-token %ecx %edx) -3454 #? (write-buffered Stderr "word: ") -3455 #? (write-slice-buffered Stderr %edx) -3456 #? (write-buffered Stderr Newline) -3457 #? (flush Stderr) -3458 # if slice-empty?(word-slice) continue -3459 (slice-empty? %edx) -3460 3d/compare-eax-and 0/imm32/false -3461 0f 85/jump-if-!= loop/disp32 -3462 # if (slice-starts-with?(word-slice, '#') continue -3463 # . eax = *word-slice->start -3464 8b/-> *edx 0/r32/eax -3465 8a/copy-byte *eax 0/r32/AL -3466 81 4/subop/and %eax 0xff/imm32 -3467 # . if (eax == '#') continue -3468 3d/compare-eax-and 0x23/imm32/hash -3469 0f 84/jump-if-= loop/disp32 -3470 # if slice-equal?(word-slice, "{") -3471 { -3472 $parse-mu-block:check-for-block: -3473 (slice-equal? %edx "{") -3474 3d/compare-eax-and 0/imm32/false -3475 74/jump-if-= break/disp8 -3476 (check-no-tokens-left %ecx) -3477 # parse new block and append -3478 (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax -3479 (append-to-block Heap %edi %eax) -3480 e9/jump $parse-mu-block:line-loop/disp32 -3481 } -3482 # if slice-equal?(word-slice, "}") break -3483 $parse-mu-block:check-for-end: -3484 (slice-equal? %edx "}") -3485 3d/compare-eax-and 0/imm32/false -3486 0f 85/jump-if-!= break/disp32 -3487 # if slice-ends-with?(word-slice, ":") parse named block and append -3488 { -3489 $parse-mu-block:check-for-named-block: -3490 # . eax = *(word-slice->end-1) -3491 8b/-> *(edx+4) 0/r32/eax -3492 48/decrement-eax -3493 8a/copy-byte *eax 0/r32/AL -3494 81 4/subop/and %eax 0xff/imm32 -3495 # . if (eax != ':') break -3496 3d/compare-eax-and 0x3a/imm32/colon -3497 0f 85/jump-if-!= break/disp32 -3498 # TODO: error-check the rest of 'line' -3499 # -3500 # skip ':' -3501 ff 1/subop/decrement *(edx+4) # Slice-end -3502 # -3503 (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax -3504 (append-to-block Heap %edi %eax) -3505 e9/jump $parse-mu-block:line-loop/disp32 -3506 } -3507 # if slice-equal?(word-slice, "var") -3508 { -3509 $parse-mu-block:check-for-var: -3510 (slice-equal? %edx "var") -3511 3d/compare-eax-and 0/imm32/false -3512 74/jump-if-= break/disp8 -3513 # -3514 (parse-mu-var-def %ecx *(ebp+0xc)) # => eax -3515 (append-to-block Heap %edi %eax) -3516 e9/jump $parse-mu-block:line-loop/disp32 -3517 } -3518 $parse-mu-block:regular-stmt: -3519 # otherwise -3520 (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10)) # => eax -3521 (append-to-block Heap %edi %eax) -3522 e9/jump loop/disp32 -3523 } # end line loop -3524 # decrement *Curr-block-depth -3525 ff 1/subop/decrement *Curr-block-depth -3526 # -3527 (pop *(ebp+0xc)) # => eax -3528 # return result -3529 89/<- %eax 7/r32/edi -3530 $parse-mu-block:end: -3531 # . reclaim locals -3532 81 0/subop/add %esp 0x214/imm32 -3533 # . restore registers -3534 5f/pop-to-edi -3535 5b/pop-to-ebx -3536 5a/pop-to-edx -3537 59/pop-to-ecx -3538 # . epilogue -3539 89/<- %esp 5/r32/ebp -3540 5d/pop-to-ebp -3541 c3/return -3542 -3543 $parse-mu-block:abort: -3544 # error("'{' or '}' should be on its own line, but got '") -3545 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") -3546 (rewind-stream %ecx) -3547 (write-stream 2 %ecx) -3548 (write-buffered Stderr "'\n") -3549 (flush Stderr) -3550 # . syscall(exit, 1) -3551 bb/copy-to-ebx 1/imm32 -3552 b8/copy-to-eax 1/imm32/exit -3553 cd/syscall 0x80/imm8 -3554 # never gets here -3555 -3556 new-block-name: # fn: (handle function) -> result/eax: (handle var) -3557 # . prologue -3558 55/push-ebp -3559 89/<- %ebp 4/r32/esp -3560 # . save registers -3561 51/push-ecx -3562 52/push-edx -3563 # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:' -3564 8b/-> *(ebp+8) 0/r32/eax -3565 8b/-> *eax 0/r32/eax # Function-name -3566 8b/-> *eax 0/r32/eax # String-length -3567 05/add-to-eax 0xd/imm32 # 10 + 2 for '$:' -3568 89/<- %ecx 0/r32/eax -3569 # var name/edx: (stream byte n) -3570 29/subtract %esp 1/r32/ecx -3571 ff 6/subop/push %ecx -3572 68/push 0/imm32/read -3573 68/push 0/imm32/write -3574 89/<- %edx 4/r32/esp -3575 (clear-stream %edx) -3576 # eax = fn->name -3577 8b/-> *(ebp+8) 0/r32/eax -3578 8b/-> *eax 0/r32/eax # Function-name -3579 # construct result using Next-block-index (and increment it) -3580 (write %edx "$") -3581 (write %edx %eax) -3582 (write %edx ":") -3583 (print-int32 %edx *Next-block-index) -3584 ff 0/subop/increment *Next-block-index -3585 # var s/eax: slice = {name->data, name->data + name->write} (clobbering edx) -3586 # . eax = name->write -3587 8b/-> *edx 0/r32/eax -3588 # . edx = name->data -3589 8d/copy-address *(edx+0xc) 2/r32/edx -3590 # . eax = name->write + name->data -3591 01/add %eax 2/r32/edx -3592 # . push {edx, eax} -3593 ff 6/subop/push %eax -3594 ff 6/subop/push %edx -3595 89/<- %eax 4/r32/esp -3596 # var final-name/edx: (addr array byte) = slice-to-string(s) -3597 (slice-to-string Heap %eax) # => eax -3598 89/<- %edx 0/r32/eax -3599 # set result->var -3600 # . var type/eax: (handle tree type-id) = literal -3601 (allocate Heap *Tree-size) # => eax -3602 (zero-out %eax *Tree-size) # default type is 'literal' -3603 # . var result/eax: (handle var) = new-var(final-name, type) -3604 (new-var Heap %edx %eax *Curr-block-depth 0 0) # => eax -3605 $new-block-name:end: -3606 # . reclaim locals -3607 81 0/subop/add %ecx 0xc/imm32 # name.{read/write/len} -3608 81 0/subop/add %ecx 8/imm32 # slice -3609 01/add %esp 1/r32/ecx -3610 # . restore registers -3611 5a/pop-to-edx -3612 59/pop-to-ecx -3613 # . epilogue -3614 89/<- %esp 5/r32/ebp -3615 5d/pop-to-ebp -3616 c3/return -3617 -3618 check-no-tokens-left: # line: (addr stream byte) -3619 # . prologue -3620 55/push-ebp -3621 89/<- %ebp 4/r32/esp -3622 # . save registers -3623 50/push-eax -3624 51/push-ecx -3625 # var s/ecx: slice -3626 68/push 0/imm32/end -3627 68/push 0/imm32/start -3628 89/<- %ecx 4/r32/esp -3629 # -3630 (next-mu-token *(ebp+8) %ecx) -3631 # if slice-empty?(s) return -3632 (slice-empty? %ecx) -3633 3d/compare-eax-and 0/imm32/false -3634 75/jump-if-!= $check-no-tokens-left:end/disp8 -3635 # if (slice-starts-with?(s, '#') return -3636 # . eax = *s->start -3637 8b/-> *edx 0/r32/eax -3638 8a/copy-byte *eax 0/r32/AL -3639 81 4/subop/and %eax 0xff/imm32 -3640 # . if (eax == '#') continue -3641 3d/compare-eax-and 0x23/imm32/hash -3642 74/jump-if-= $check-no-tokens-left:end/disp8 -3643 # abort -3644 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") -3645 (rewind-stream %ecx) -3646 (write-stream 2 %ecx) -3647 (write-buffered Stderr "'\n") -3648 (flush Stderr) -3649 # . syscall(exit, 1) -3650 bb/copy-to-ebx 1/imm32 -3651 b8/copy-to-eax 1/imm32/exit -3652 cd/syscall 0x80/imm8 -3653 # never gets here -3654 $check-no-tokens-left:end: -3655 # . reclaim locals -3656 81 0/subop/add %esp 8/imm32 -3657 # . restore registers -3658 59/pop-to-ecx -3659 58/pop-to-eax -3660 # . epilogue -3661 89/<- %esp 5/r32/ebp -3662 5d/pop-to-ebp -3663 c3/return -3664 -3665 parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) -3666 # pseudocode: -3667 # var s: (addr array byte) = slice-to-string(name) -3668 # var v: (handle var) = new-var(s, 0) -3669 # v->block-depth = *Curr-block-depth # containing block depth -3670 # push(vars, v) -3671 # result = parse-mu-block(in, vars, fn) -3672 # pop(vars) -3673 # result->name = s -3674 # return result -3675 # -3676 # . prologue -3677 55/push-ebp -3678 89/<- %ebp 4/r32/esp -3679 # . save registers -3680 51/push-ecx -3681 # var s/ecx: (addr array byte) = slice-to-string(name) -3682 (slice-to-string Heap *(ebp+8)) # => eax -3683 89/<- %ecx 0/r32/eax -3684 # var type/eax: (handle tree type-id) = literal -3685 (allocate Heap *Tree-size) # => eax -3686 (zero-out %eax *Tree-size) # default type is 'literal' -3687 # var v/ecx: (handle var) = new-var(s, type) -3688 (new-var Heap %ecx %eax *Curr-block-depth 0 0) # => eax -3689 89/<- %ecx 0/r32/eax -3690 # push(vars, v) -3691 (push *(ebp+0x10) %ecx) -3692 # eax = result -3693 (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) # => eax -3694 # pop the var -3695 50/push-eax -3696 (pop *(ebp+0x10)) # => eax -3697 58/pop-to-eax -3698 # result->tag = named-block -3699 c7 0/subop/copy *eax 0/imm32/block # Stmt-tag -3700 # result->var = v -3701 89/<- *(eax+8) 1/r32/ecx # Block-var -3702 $parse-mu-named-block:end: -3703 # . restore registers -3704 59/pop-to-ecx -3705 # . epilogue -3706 89/<- %esp 5/r32/ebp -3707 5d/pop-to-ebp -3708 c3/return -3709 -3710 parse-mu-var-def: # line: (addr stream byte), vars: (addr stack (handle var)) -> result/eax: (handle stmt) -3711 # . prologue -3712 55/push-ebp -3713 89/<- %ebp 4/r32/esp -3714 # . save registers -3715 51/push-ecx -3716 52/push-edx -3717 # var word-slice/ecx: slice -3718 68/push 0/imm32/end -3719 68/push 0/imm32/start -3720 89/<- %ecx 4/r32/esp -3721 # var v/edx: (handle var) = parse-var-with-type(line) -3722 (next-mu-token *(ebp+8) %ecx) -3723 (parse-var-with-type %ecx *(ebp+8)) # => eax -3724 89/<- %edx 0/r32/eax -3725 # v->block-depth = *Curr-block-depth -3726 8b/-> *Curr-block-depth 0/r32/eax -3727 89/<- *(edx+8) 0/r32/eax -3728 # -3729 (push *(ebp+0xc) %edx) -3730 # either v has no register and there's no more to this line -3731 8b/-> *(edx+0x10) 0/r32/eax # Var-register -3732 3d/compare-eax-and 0/imm32 -3733 { -3734 75/jump-if-!= break/disp8 -3735 # v->stack-offset = *Next-local-stack-offset -3736 8b/-> *Next-local-stack-offset 0/r32/eax -3737 89/<- *(edx+0xc) 0/r32/eax # Var-stack-offset -3738 # TODO: ensure that there's nothing else on this line -3739 (new-vardef Heap %edx) # => eax -3740 eb/jump $parse-mu-var-def:end/disp8 -3741 } -3742 # or v has a register and there's more to this line -3743 { -3744 74/jump-if-= break/disp8 -3745 # ensure that the next word is '<-' -3746 (next-mu-token *(ebp+8) %ecx) -3747 (slice-equal? %ecx "<-") # => eax -3748 3d/compare-eax-and 0/imm32/false -3749 74/jump-if-= $parse-mu-var-def:abort/disp8 -3750 # -3751 (new-regvardef Heap %edx) # => eax -3752 (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc)) -3753 } -3754 $parse-mu-var-def:end: -3755 # *Next-local-stack-offset -= size-of(v) -3756 50/push-eax -3757 (size-of %edx) # => eax -3758 29/subtract-from *Next-local-stack-offset 0/r32/eax -3759 58/pop-to-eax -3760 # . reclaim locals -3761 81 0/subop/add %esp 8/imm32 -3762 # . restore registers -3763 5a/pop-to-edx -3764 59/pop-to-ecx -3765 # . epilogue -3766 89/<- %esp 5/r32/ebp -3767 5d/pop-to-ebp -3768 c3/return -3769 -3770 $parse-mu-var-def:abort: -3771 (rewind-stream *(ebp+8)) -3772 # error("register variable requires a valid instruction to initialize but got '" line "'\n") -3773 (write-buffered Stderr "register variable requires a valid instruction to initialize but got '") -3774 (flush Stderr) -3775 (write-stream 2 *(ebp+8)) -3776 (write-buffered Stderr "'\n") -3777 (flush Stderr) -3778 # . syscall(exit, 1) -3779 bb/copy-to-ebx 1/imm32 -3780 b8/copy-to-eax 1/imm32/exit -3781 cd/syscall 0x80/imm8 -3782 # never gets here -3783 -3784 test-parse-mu-var-def: -3785 # 'var n: int' -3786 # . prologue -3787 55/push-ebp -3788 89/<- %ebp 4/r32/esp -3789 # setup -3790 (clear-stream _test-input-stream) -3791 (write _test-input-stream "n: int\n") # caller has consumed the 'var' -3792 c7 0/subop/copy *Curr-block-depth 1/imm32 -3793 c7 0/subop/copy *Next-local-stack-offset -4/imm32 -3794 # var vars/ecx: (stack (addr var) 4) -3795 81 5/subop/subtract %esp 0x10/imm32 -3796 68/push 0x10/imm32/length -3797 68/push 0/imm32/top -3798 89/<- %ecx 4/r32/esp -3799 (clear-stack %ecx) -3800 # convert -3801 (parse-mu-var-def _test-input-stream %ecx) # => eax -3802 # check result -3803 (check-ints-equal *eax 2 "F - test-parse-mu-var-def/tag") # Stmt-tag is vardef -3804 8b/-> *(eax+4) 0/r32/eax # Vardef-var -3805 (check-strings-equal *eax "n" "F - test-parse-mu-var-def/var-name") # Var-name -3806 (check-ints-equal *(eax+0x10) 0 "F - test-parse-mu-var-def/var-register") # Var-register -3807 (check-ints-equal *(eax+8) 1 "F - test-parse-mu-reg-var-def/output-block-depth") # Var-block-depth -3808 (check-ints-equal *(eax+0xc) -4 "F - test-parse-mu-reg-var-def/output-stack-offset") # Var-stack-offset -3809 # ensure type is int -3810 8b/-> *(eax+4) 0/r32/eax # Var-type -3811 (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0") # Tree-left -3812 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-var-def/var-type:0") # Tree-right -3813 # globals -3814 (check-ints-equal *Next-local-stack-offset -8 "F - test-parse-mu-reg-var-def/Next-local-stack-offset") -3815 # . epilogue -3816 89/<- %esp 5/r32/ebp -3817 5d/pop-to-ebp -3818 c3/return -3819 -3820 test-parse-mu-reg-var-def: -3821 # 'var n/eax: int <- copy 0' -3822 # . prologue -3823 55/push-ebp -3824 89/<- %ebp 4/r32/esp -3825 # setup -3826 (clear-stream _test-input-stream) -3827 (write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var' -3828 c7 0/subop/copy *Curr-block-depth 1/imm32 -3829 c7 0/subop/copy *Next-local-stack-offset -4/imm32 -3830 # var vars/ecx: (stack (addr var) 4) -3831 81 5/subop/subtract %esp 0x10/imm32 -3832 68/push 0x10/imm32/length -3833 68/push 0/imm32/top -3834 89/<- %ecx 4/r32/esp -3835 (clear-stack %ecx) -3836 # convert -3837 (parse-mu-var-def _test-input-stream %ecx) # => eax -3838 # check result -3839 (check-ints-equal *eax 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is regvardef -3840 8b/-> *(eax+0xc) 0/r32/eax # Regvardef-outputs -3841 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/single-output") # List-next -3842 8b/-> *eax 0/r32/eax # Stmt-var-value -3843 (check-strings-equal *eax "n" "F - test-parse-mu-reg-var-def/output-name") # Var-name -3844 (check-strings-equal *(eax+0x10) "eax" "F - test-parse-mu-reg-var-def/output-register") # Var-register -3845 (check-ints-equal *(eax+8) 1 "F - test-parse-mu-reg-var-def/output-block-depth") # Var-block-depth -3846 (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-stack-offset") # Var-stack-offset -3847 # ensure type is int -3848 8b/-> *(eax+4) 0/r32/eax # Var-type -3849 (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-left -3850 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-right -3851 # globals -3852 (check-ints-equal *Next-local-stack-offset -8 "F - test-parse-mu-reg-var-def/Next-local-stack-offset") -3853 # . epilogue -3854 89/<- %esp 5/r32/ebp -3855 5d/pop-to-ebp -3856 c3/return -3857 -3858 parse-mu-stmt: # line: (addr stream byte), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) -3859 # pseudocode: -3860 # var name: slice -3861 # result = allocate(Heap, Stmt-size) -3862 # if stmt-has-outputs?(line) -3863 # while true -3864 # name = next-mu-token(line) -3865 # if (name == '<-') break -3866 # assert(is-identifier?(name)) -3867 # var v: (handle var) = lookup-or-define-var(name, vars, fn) # regular stmts may define vars in fn outputs -3868 # result->outputs = append(result->outputs, v) -3869 # add-operation-and-inputs-to-stmt(result, line, vars) -3870 # -3871 # . prologue -3872 55/push-ebp -3873 89/<- %ebp 4/r32/esp -3874 # . save registers -3875 51/push-ecx -3876 52/push-edx -3877 57/push-edi -3878 # var name/ecx: slice -3879 68/push 0/imm32/end -3880 68/push 0/imm32/start -3881 89/<- %ecx 4/r32/esp -3882 # var is-deref?/edx: boolean = false -3883 ba/copy-to-edx 0/imm32/false -3884 # result/edi: (handle stmt) -3885 (allocate Heap *Stmt-size) # => eax -3886 (zero-out %eax *Stmt-size) -3887 89/<- %edi 0/r32/eax -3888 # result->tag = 1/stmt -3889 c7 0/subop/copy *edi 1/imm32/stmt1 # Stmt-tag -3890 { -3891 (stmt-has-outputs? *(ebp+8)) -3892 3d/compare-eax-and 0/imm32/false -3893 0f 84/jump-if-= break/disp32 -3894 { -3895 $parse-mu-stmt:read-outputs: -3896 # name = next-mu-token(line) -3897 (next-mu-token *(ebp+8) %ecx) -3898 # if slice-empty?(word-slice) break -3899 (slice-empty? %ecx) # => eax -3900 3d/compare-eax-and 0/imm32/false -3901 0f 85/jump-if-!= break/disp32 -3902 # if (name == "<-") break -3903 (slice-equal? %ecx "<-") # => eax -3904 3d/compare-eax-and 0/imm32/false -3905 0f 85/jump-if-!= break/disp32 -3906 # is-deref? = false -3907 ba/copy-to-edx 0/imm32/false -3908 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? -3909 8b/-> *ecx 0/r32/eax # Slice-start -3910 8a/copy-byte *eax 0/r32/AL -3911 81 4/subop/and %eax 0xff/imm32 -3912 3d/compare-eax-and 0x2a/imm32/asterisk -3913 { -3914 75/jump-if-!= break/disp8 -3915 ff 0/subop/increment *ecx -3916 ba/copy-to-edx 1/imm32/true -3917 } -3918 # assert(is-identifier?(name)) -3919 (is-identifier? %ecx) # => eax -3920 3d/compare-eax-and 0/imm32/false -3921 0f 84/jump-if-= $parse-mu-stmt:abort/disp32 -3922 # result->outputs = new stmt-var(lookup(name, vars, fn), result->outputs, is-deref?) -3923 (lookup-or-define-var %ecx *(ebp+0xc) *(ebp+0x10)) # => eax -3924 (append-stmt-var Heap %eax *(edi+0xc) %edx) # Stmt1-outputs => eax -3925 89/<- *(edi+0xc) 0/r32/eax # Stmt1-outputs -3926 e9/jump loop/disp32 -3927 } -3928 } -3929 (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc)) -3930 $parse-mu-stmt:end: -3931 # return result -3932 89/<- %eax 7/r32/edi -3933 # . reclaim locals -3934 81 0/subop/add %esp 8/imm32 -3935 # . restore registers -3936 5f/pop-to-edi -3937 5a/pop-to-edx -3938 59/pop-to-ecx -3939 # . epilogue -3940 89/<- %esp 5/r32/ebp -3941 5d/pop-to-ebp -3942 c3/return -3943 -3944 $parse-mu-stmt:abort: -3945 # error("invalid identifier '" name "'\n") -3946 (write-buffered Stderr "invalid identifier '") -3947 (write-slice-buffered Stderr %ecx) -3948 (write-buffered Stderr "'\n") -3949 (flush Stderr) -3950 # . syscall(exit, 1) -3951 bb/copy-to-ebx 1/imm32 -3952 b8/copy-to-eax 1/imm32/exit -3953 cd/syscall 0x80/imm8 -3954 # never gets here -3955 -3956 add-operation-and-inputs-to-stmt: # stmt: (handle stmt), line: (addr stream byte), vars: (addr stack (handle var)) -3957 # pseudocode: -3958 # stmt->name = slice-to-string(next-mu-token(line)) -3959 # while true -3960 # name = next-mu-token(line) -3961 # v = lookup-var-or-literal(name) -3962 # stmt->inouts = append(stmt->inouts, v) -3963 # -3964 # . prologue -3965 55/push-ebp -3966 89/<- %ebp 4/r32/esp -3967 # . save registers -3968 50/push-eax -3969 51/push-ecx -3970 52/push-edx -3971 57/push-edi -3972 # edi = stmt -3973 8b/-> *(ebp+8) 7/r32/edi -3974 # var name/ecx: slice -3975 68/push 0/imm32/end -3976 68/push 0/imm32/start -3977 89/<- %ecx 4/r32/esp -3978 # var is-deref?/edx: boolean = false -3979 ba/copy-to-edx 0/imm32/false -3980 $add-operation-and-inputs-to-stmt:read-operation: -3981 (next-mu-token *(ebp+0xc) %ecx) -3982 (slice-to-string Heap %ecx) # => eax -3983 89/<- *(edi+4) 0/r32/eax # Stmt1-operation or Regvardef-operation -3984 { -3985 $add-operation-and-inputs-to-stmt:read-inouts: -3986 # name = next-mu-token(line) -3987 (next-mu-token *(ebp+0xc) %ecx) -3988 # if slice-empty?(word-slice) break -3989 (slice-empty? %ecx) # => eax -3990 3d/compare-eax-and 0/imm32/false -3991 0f 85/jump-if-!= break/disp32 -3992 # if (name == "<-") abort -3993 (slice-equal? %ecx "<-") -3994 3d/compare-eax-and 0/imm32/false -3995 0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32 -3996 # is-deref? = false -3997 ba/copy-to-edx 0/imm32/false -3998 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? -3999 8b/-> *ecx 0/r32/eax # Slice-start -4000 8a/copy-byte *eax 0/r32/AL -4001 81 4/subop/and %eax 0xff/imm32 -4002 3d/compare-eax-and 0x2a/imm32/asterisk -4003 { -4004 75/jump-if-!= break/disp8 -4005 $add-operation-and-inputs-to-stmt:inout-is-deref: -4006 ff 0/subop/increment *ecx -4007 ba/copy-to-edx 1/imm32/true -4008 } -4009 (lookup-var-or-literal %ecx *(ebp+0x10)) # => eax -4010 (append-stmt-var Heap %eax *(edi+8) %edx) # Stmt1-inouts or Regvardef-inouts => eax -4011 89/<- *(edi+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts -4012 e9/jump loop/disp32 -4013 } -4014 $add-operation-and-inputs-to-stmt:end: -4015 # . reclaim locals -4016 81 0/subop/add %esp 8/imm32 -4017 # . restore registers -4018 5f/pop-to-edi -4019 5a/pop-to-edx -4020 59/pop-to-ecx -4021 58/pop-to-eax -4022 # . epilogue -4023 89/<- %esp 5/r32/ebp -4024 5d/pop-to-ebp -4025 c3/return -4026 -4027 $add-operation-and-inputs-to-stmt:abort: -4028 # error("invalid statement '" line "'\n") -4029 (rewind-stream *(ebp+8)) -4030 (write-buffered Stderr "invalid identifier '") -4031 (flush Stderr) -4032 (write-stream 2 *(ebp+8)) -4033 (write-buffered Stderr "'\n") -4034 (flush Stderr) -4035 # . syscall(exit, 1) -4036 bb/copy-to-ebx 1/imm32 -4037 b8/copy-to-eax 1/imm32/exit -4038 cd/syscall 0x80/imm8 -4039 # never gets here -4040 -4041 stmt-has-outputs?: # line: (addr stream byte) -> result/eax: boolean -4042 # . prologue -4043 55/push-ebp -4044 89/<- %ebp 4/r32/esp -4045 # . save registers -4046 51/push-ecx -4047 # var word-slice/ecx: slice -4048 68/push 0/imm32/end -4049 68/push 0/imm32/start -4050 89/<- %ecx 4/r32/esp -4051 # result = false -4052 b8/copy-to-eax 0/imm32/false -4053 (rewind-stream *(ebp+8)) -4054 { -4055 (next-mu-token *(ebp+8) %ecx) -4056 # if slice-empty?(word-slice) break -4057 (slice-empty? %ecx) -4058 3d/compare-eax-and 0/imm32/false -4059 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) -4060 0f 85/jump-if-!= break/disp32 -4061 # if slice-starts-with?(word-slice, '#') break -4062 # . eax = *word-slice->start -4063 8b/-> *ecx 0/r32/eax -4064 8a/copy-byte *eax 0/r32/AL -4065 81 4/subop/and %eax 0xff/imm32 -4066 # . if (eax == '#') break -4067 3d/compare-eax-and 0x23/imm32/hash -4068 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) -4069 0f 84/jump-if-= break/disp32 -4070 # if slice-equal?(word-slice, '<-') return true -4071 (slice-equal? %ecx "<-") -4072 3d/compare-eax-and 0/imm32/false -4073 74/jump-if-= loop/disp8 -4074 b8/copy-to-eax 1/imm32/true -4075 } -4076 $stmt-has-outputs:end: -4077 (rewind-stream *(ebp+8)) -4078 # . reclaim locals -4079 81 0/subop/add %esp 8/imm32 -4080 # . restore registers -4081 59/pop-to-ecx -4082 # . epilogue -4083 89/<- %esp 5/r32/ebp -4084 5d/pop-to-ebp -4085 c3/return -4086 -4087 # if 'name' starts with a digit, create a new literal var for it -4088 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found -4089 lookup-var-or-literal: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) -4090 # . prologue -4091 55/push-ebp -4092 89/<- %ebp 4/r32/esp -4093 # . save registers -4094 51/push-ecx -4095 56/push-esi -4096 # esi = name -4097 8b/-> *(ebp+8) 6/r32/esi -4098 # if slice-empty?(name) abort -4099 (slice-empty? %esi) # => eax -4100 3d/compare-eax-and 0/imm32/false -4101 0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32 -4102 # var c/ecx: byte = *name->start -4103 8b/-> *esi 1/r32/ecx -4104 8a/copy-byte *ecx 1/r32/CL -4105 81 4/subop/and %ecx 0xff/imm32 -4106 # if is-decimal-digit?(c) return new var(name) -4107 { -4108 (is-decimal-digit? %ecx) # => eax -4109 81 7/subop/compare %eax 0/imm32/false -4110 74/jump-if-= break/disp8 -4111 (new-literal-integer Heap %esi) # => eax -4112 eb/jump $lookup-var-or-literal:end/disp8 -4113 } -4114 # else if (c == '"') return new var(name) -4115 { -4116 81 7/subop/compare %ecx 0x22/imm32/dquote -4117 75/jump-if-!= break/disp8 -4118 (new-literal-string Heap %esi) # => eax -4119 eb/jump $lookup-var-or-literal:end/disp8 -4120 } -4121 # otherwise return lookup-var(name, vars) -4122 { -4123 (lookup-var %esi *(ebp+0xc)) # => eax -4124 } -4125 $lookup-var-or-literal:end: -4126 # . restore registers -4127 5e/pop-to-esi -4128 59/pop-to-ecx -4129 # . epilogue -4130 89/<- %esp 5/r32/ebp -4131 5d/pop-to-ebp -4132 c3/return -4133 -4134 $lookup-var-or-literal:abort: -4135 (write-buffered Stderr "empty variable!") -4136 (flush Stderr) -4137 # . syscall(exit, 1) -4138 bb/copy-to-ebx 1/imm32 -4139 b8/copy-to-eax 1/imm32/exit -4140 cd/syscall 0x80/imm8 -4141 # never gets here -4142 -4143 # return first 'name' from the top (back) of 'vars' and abort if not found -4144 lookup-var: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) -4145 # . prologue -4146 55/push-ebp -4147 89/<- %ebp 4/r32/esp -4148 # var target/eax: (handle array byte) = slice-to-string(name) -4149 (slice-to-string Heap *(ebp+8)) # => eax -4150 # -4151 (lookup-var-helper %eax *(ebp+0xc)) # => eax -4152 # if (result == 0) abort -4153 3d/compare-eax-and 0/imm32 -4154 74/jump-if-= $lookup-var:abort/disp8 -4155 $lookup-var:end: -4156 # . epilogue -4157 89/<- %esp 5/r32/ebp -4158 5d/pop-to-ebp -4159 c3/return -4160 -4161 $lookup-var:abort: -4162 (write-buffered Stderr "unknown variable '") -4163 (write-slice-buffered Stderr *(ebp+8)) -4164 (write-buffered Stderr "'\n") -4165 (flush Stderr) -4166 # . syscall(exit, 1) -4167 bb/copy-to-ebx 1/imm32 -4168 b8/copy-to-eax 1/imm32/exit -4169 cd/syscall 0x80/imm8 -4170 # never gets here -4171 -4172 # return first 'name' from the top (back) of 'vars', and 0/null if not found -4173 lookup-var-helper: # name: (addr array byte), vars: (addr stack (handle var)) -> result/eax: (handle var) -4174 # pseudocode: -4175 # var curr: (addr handle var) = &vars->data[vars->top - 4] -4176 # var min = vars->data -4177 # while curr >= min -4178 # var v: (handle var) = *curr -4179 # if v->name == name -4180 # return v -4181 # return 0 -4182 # -4183 # . prologue -4184 55/push-ebp -4185 89/<- %ebp 4/r32/esp -4186 # . save registers -4187 52/push-edx -4188 53/push-ebx -4189 56/push-esi -4190 # esi = vars -4191 8b/-> *(ebp+0xc) 6/r32/esi -4192 # ebx = vars->top -4193 8b/-> *esi 3/r32/ebx -4194 # if (vars->top > vars->length) abort -4195 3b/compare 0/r32/eax *(esi+4) -4196 0f 8f/jump-if-> $lookup-var-helper:error1/disp32 -4197 # var min/edx: (addr handle var) = vars->data -4198 8d/copy-address *(esi+8) 2/r32/edx -4199 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 4] -4200 81 5/subop/subtract %ebx 4/imm32 -4201 8d/copy-address *(esi+ebx+8) 3/r32/ebx -4202 { -4203 # if (curr < min) return 0 -4204 39/compare %ebx 2/r32/edx -4205 b8/copy-to-eax 0/imm32 -4206 0f 82/jump-if-addr< break/disp32 -4207 # var v/eax: (handle var) = *curr -4208 8b/-> *ebx 0/r32/eax -4209 # if (v->name == name) return v -4210 (string-equal? *eax *(ebp+8)) # Var-name -4211 3d/compare-eax-and 0/imm32/false -4212 8b/-> *ebx 0/r32/eax -4213 75/jump-if-!= break/disp8 -4214 # curr -= 4 -4215 81 5/subop/subtract %ebx 4/imm32 -4216 e9/jump loop/disp32 -4217 } -4218 $lookup-var-helper:end: -4219 # . restore registers -4220 5e/pop-to-esi -4221 5b/pop-to-ebx -4222 5a/pop-to-edx -4223 # . epilogue -4224 89/<- %esp 5/r32/ebp -4225 5d/pop-to-ebp -4226 c3/return -4227 -4228 $lookup-var-helper:error1: -4229 (write-buffered Stderr "malformed stack when looking up '") -4230 (write-slice-buffered Stderr *(ebp+8)) -4231 (write-buffered Stderr "'\n") -4232 (flush Stderr) -4233 # . syscall(exit, 1) -4234 bb/copy-to-ebx 1/imm32 -4235 b8/copy-to-eax 1/imm32/exit -4236 cd/syscall 0x80/imm8 -4237 # never gets here -4238 -4239 # return first 'name' from the top (back) of 'vars' and create a new var for a fn output if not found -4240 lookup-or-define-var: # name: (addr slice), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle var) -4241 # . prologue -4242 55/push-ebp -4243 89/<- %ebp 4/r32/esp -4244 # . save registers -4245 51/push-ecx -4246 # var target/ecx: (handle array byte) = slice-to-string(name) -4247 (slice-to-string Heap *(ebp+8)) # => eax -4248 89/<- %ecx 0/r32/eax -4249 # -4250 (lookup-var-helper %ecx *(ebp+0xc)) # => eax -4251 { -4252 # if (result != 0) return -4253 3d/compare-eax-and 0/imm32 -4254 75/jump-if-!= break/disp8 -4255 # if name is one of fn's outputs, return it -4256 { -4257 (find-in-function-outputs *(ebp+0x10) %ecx) # => eax -4258 3d/compare-eax-and 0/imm32 -4259 # otherwise abort -4260 0f 84/jump-if-!= $lookup-var:abort/disp32 -4261 } -4262 } -4263 $lookup-or-define-var:end: -4264 # . restore registers -4265 59/pop-to-ecx -4266 # . epilogue -4267 89/<- %esp 5/r32/ebp -4268 5d/pop-to-ebp -4269 c3/return -4270 -4271 find-in-function-outputs: # fn: (handle function), name: (handle array byte) -> result/eax: (handle var) -4272 # . prologue -4273 55/push-ebp -4274 89/<- %ebp 4/r32/esp -4275 # . save registers -4276 51/push-ecx -4277 # var curr/ecx: (handle list var) = fn->outputs -4278 8b/-> *(ebp+8) 1/r32/ecx -4279 8b/-> *(ecx+0xc) 1/r32/ecx -4280 # while curr != null -4281 { -4282 81 7/subop/compare %ecx 0/imm32 -4283 74/jump-if-= break/disp8 -4284 # var v: (handle var) = *curr -4285 8b/-> *ecx 0/r32/eax # List-value -4286 # if (curr->name == name) return curr -4287 50/push-eax -4288 (string-equal? *eax *(ebp+0xc)) -4289 3d/compare-eax-and 0/imm32/false -4290 58/pop-to-eax -4291 75/jump-if-!= $find-in-function-outputs:end/disp8 -4292 # curr = curr->next -4293 8b/-> *(ecx+4) 1/r32/ecx # List-next -4294 eb/jump loop/disp8 -4295 } -4296 b8/copy-to-eax 0/imm32 -4297 $find-in-function-outputs:end: -4298 # . restore registers -4299 59/pop-to-ecx -4300 # . epilogue -4301 89/<- %esp 5/r32/ebp -4302 5d/pop-to-ebp -4303 c3/return -4304 -4305 test-parse-mu-stmt: -4306 # . prologue -4307 55/push-ebp -4308 89/<- %ebp 4/r32/esp -4309 # setup -4310 (clear-stream _test-input-stream) -4311 (write _test-input-stream "increment n\n") -4312 # var vars/ecx: (stack (addr var) 4) -4313 81 5/subop/subtract %esp 0x10/imm32 -4314 68/push 0x10/imm32/length -4315 68/push 0/imm32/top -4316 89/<- %ecx 4/r32/esp -4317 (clear-stack %ecx) -4318 # var v/edx: var -4319 81 5/subop/subtract %esp 0x14/imm32 # Var-size -4320 89/<- %edx 4/r32/esp -4321 (zero-out %edx 0x14) # Var-size -4322 # v->name = "n" -4323 c7 0/subop/copy *edx "n"/imm32 # Var-name -4324 # -4325 (push %ecx %edx) -4326 # convert -4327 (parse-mu-stmt _test-input-stream %ecx) # => eax -4328 # check result -4329 (check-ints-equal *eax 1 "F - test-parse-mu-stmt/tag") # Stmt-tag is Stmt1 -4330 (check-strings-equal *(eax+4) "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation -4331 # edx: (handle list var) = result->inouts -4332 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts -4333 # ebx: (handle var) = result->inouts->value -4334 8b/-> *edx 3/r32/ebx # Stmt-var-value -4335 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt/inout:0") # Var-name -4336 # . epilogue -4337 89/<- %esp 5/r32/ebp -4338 5d/pop-to-ebp -4339 c3/return -4340 -4341 test-parse-mu-stmt-with-comma: -4342 # . prologue -4343 55/push-ebp -4344 89/<- %ebp 4/r32/esp -4345 # setup -4346 (clear-stream _test-input-stream) -4347 (write _test-input-stream "copy-to n, 3\n") -4348 # var vars/ecx: (stack (addr var) 4) -4349 81 5/subop/subtract %esp 0x10/imm32 -4350 68/push 0x10/imm32/length -4351 68/push 0/imm32/top -4352 89/<- %ecx 4/r32/esp -4353 (clear-stack %ecx) -4354 # var v/edx: var -4355 81 5/subop/subtract %esp 0x14/imm32 # Var-size -4356 89/<- %edx 4/r32/esp -4357 (zero-out %edx 0x14) # Var-size -4358 # v->name = "n" -4359 c7 0/subop/copy *edx "n"/imm32 # Var-name -4360 # -4361 (push %ecx %edx) -4362 # convert -4363 (parse-mu-stmt _test-input-stream %ecx) # => eax -4364 # check result -4365 (check-ints-equal *eax 1 "F - test-parse-mu-stmt-with-comma/tag") # Stmt-tag is Stmt1 -4366 (check-strings-equal *(eax+4) "copy-to" "F - test-parse-mu-stmt-with-comma/name") # Stmt1-operation -4367 # edx: (handle list var) = result->inouts -4368 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts -4369 # ebx: (handle var) = result->inouts->value -4370 8b/-> *edx 3/r32/ebx # Stmt-var-value -4371 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt-with-comma/inout:0") # Var-name -4372 # . epilogue -4373 89/<- %esp 5/r32/ebp -4374 5d/pop-to-ebp -4375 c3/return -4376 -4377 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) -4378 # . prologue -4379 55/push-ebp -4380 89/<- %ebp 4/r32/esp -4381 # . save registers -4382 51/push-ecx -4383 # -4384 (allocate *(ebp+8) *Function-size) # => eax -4385 8b/-> *(ebp+0xc) 1/r32/ecx -4386 89/<- *eax 1/r32/ecx # Function-name -4387 8b/-> *(ebp+0x10) 1/r32/ecx -4388 89/<- *(eax+4) 1/r32/ecx # Function-subx-name -4389 8b/-> *(ebp+0x14) 1/r32/ecx -4390 89/<- *(eax+8) 1/r32/ecx # Function-inouts -4391 8b/-> *(ebp+0x18) 1/r32/ecx -4392 89/<- *(eax+0xc) 1/r32/ecx # Function-outputs -4393 8b/-> *(ebp+0x1c) 1/r32/ecx -4394 89/<- *(eax+0x10) 1/r32/ecx # Function-body -4395 8b/-> *(ebp+0x20) 1/r32/ecx -4396 89/<- *(eax+0x14) 1/r32/ecx # Function-next -4397 $new-function:end: -4398 # . restore registers -4399 59/pop-to-ecx -4400 # . epilogue -4401 89/<- %esp 5/r32/ebp -4402 5d/pop-to-ebp -4403 c3/return -4404 -4405 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) -4406 # . prologue -4407 55/push-ebp -4408 89/<- %ebp 4/r32/esp -4409 # . save registers -4410 51/push-ecx -4411 # -4412 (allocate *(ebp+8) *Var-size) # => eax -4413 8b/-> *(ebp+0xc) 1/r32/ecx -4414 89/<- *eax 1/r32/ecx # Var-name -4415 8b/-> *(ebp+0x10) 1/r32/ecx -4416 89/<- *(eax+4) 1/r32/ecx # Var-type -4417 8b/-> *(ebp+0x14) 1/r32/ecx -4418 89/<- *(eax+8) 1/r32/ecx # Var-block-depth -4419 8b/-> *(ebp+0x18) 1/r32/ecx -4420 89/<- *(eax+0xc) 1/r32/ecx # Var-stack-offset -4421 8b/-> *(ebp+0x1c) 1/r32/ecx -4422 89/<- *(eax+0x10) 1/r32/ecx # Var-register -4423 $new-var:end: -4424 # . restore registers -4425 59/pop-to-ecx -4426 # . epilogue -4427 89/<- %esp 5/r32/ebp -4428 5d/pop-to-ebp -4429 c3/return -4430 -4431 new-literal-integer: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -4432 # . prologue -4433 55/push-ebp -4434 89/<- %ebp 4/r32/esp -4435 # . save registers -4436 51/push-ecx -4437 # if (!is-hex-int?(name)) abort -4438 (is-hex-int? *(ebp+0xc)) # => eax -4439 3d/compare-eax-and 0/imm32/false -4440 0f 84/jump-if-= $new-literal-integer:abort/disp32 -4441 # var s/ecx: (addr array byte) -4442 (slice-to-string Heap *(ebp+0xc)) # => eax -4443 89/<- %ecx 0/r32/eax -4444 # result/ecx = new var(s) -4445 (allocate *(ebp+8) *Var-size) # => eax -4446 (zero-out %eax *Var-size) -4447 89/<- *eax 1/r32/ecx # Var-name -4448 89/<- %ecx 0/r32/eax -4449 # result->type = new type() -4450 (allocate *(ebp+8) *Tree-size) # => eax -4451 (zero-out %eax *Tree-size) # default type is 'literal' -4452 89/<- *(ecx+4) 0/r32/eax # Var-type -4453 # move result to eax -4454 89/<- %eax 1/r32/ecx -4455 $new-literal-integer:end: -4456 # . restore registers -4457 59/pop-to-ecx -4458 # . epilogue -4459 89/<- %esp 5/r32/ebp -4460 5d/pop-to-ebp -4461 c3/return -4462 -4463 $new-literal-integer:abort: -4464 (write-buffered Stderr "variable cannot begin with a digit '") -4465 (write-slice-buffered Stderr *(ebp+0xc)) -4466 (write-buffered Stderr "'\n") -4467 (flush Stderr) -4468 # . syscall(exit, 1) -4469 bb/copy-to-ebx 1/imm32 -4470 b8/copy-to-eax 1/imm32/exit -4471 cd/syscall 0x80/imm8 -4472 # never gets here -4473 -4474 new-literal-string: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -4475 # . prologue -4476 55/push-ebp -4477 89/<- %ebp 4/r32/esp -4478 # . save registers -4479 51/push-ecx -4480 # var s/ecx: (addr array byte) -4481 (slice-to-string Heap *(ebp+0xc)) # => eax -4482 89/<- %ecx 0/r32/eax -4483 # result/ecx = new var(s) -4484 (allocate *(ebp+8) *Var-size) # => eax -4485 (zero-out %eax *Var-size) -4486 89/<- *eax 1/r32/ecx # Var-name -4487 89/<- %ecx 0/r32/eax -4488 # result->type = new type() -4489 (allocate *(ebp+8) *Tree-size) # => eax -4490 (zero-out %eax *Tree-size) # default type is 'literal' -4491 89/<- *(ecx+4) 0/r32/eax # Var-type -4492 # move result to eax -4493 89/<- %eax 1/r32/ecx -4494 $new-literal-string:end: -4495 # . restore registers -4496 59/pop-to-ecx -4497 # . epilogue -4498 89/<- %esp 5/r32/ebp -4499 5d/pop-to-ebp -4500 c3/return -4501 -4502 new-label: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -4503 # . prologue -4504 55/push-ebp -4505 89/<- %ebp 4/r32/esp -4506 # . save registers -4507 51/push-ecx -4508 # var s/ecx: (addr array byte) -4509 (slice-to-string Heap *(ebp+0xc)) # => eax -4510 89/<- %ecx 0/r32/eax -4511 # -4512 (allocate *(ebp+8) *Var-size) # => eax -4513 89/<- *eax 1/r32/ecx # Var-name -4514 89/<- %ecx 0/r32/eax -4515 (allocate *(ebp+8) *Tree-size) # => eax -4516 (zero-out %eax *Tree-size) # labels are literals -4517 89/<- *(ecx+4) 0/r32/eax # Var-type -4518 89/<- %eax 1/r32/ecx -4519 c7 0/subop/copy *(eax+8) 0/imm32 # Var-block-depth -4520 c7 0/subop/copy *(eax+0xc) 0/imm32 # Var-stack-offset -4521 c7 0/subop/copy *(eax+0x10) 0/imm32 # Var-register -4522 $new-label:end: -4523 # . restore registers -4524 59/pop-to-ecx -4525 # . epilogue -4526 89/<- %esp 5/r32/ebp -4527 5d/pop-to-ebp -4528 c3/return -4529 -4530 new-block: # ad: (addr allocation-descriptor), data: (handle list statement) -> result/eax: (handle statement) -4531 # . prologue -4532 55/push-ebp -4533 89/<- %ebp 4/r32/esp -4534 # . save registers -4535 51/push-ecx -4536 # -4537 (allocate *(ebp+8) *Stmt-size) # => eax -4538 (zero-out %eax *Stmt-size) -4539 c7 0/subop/copy *eax 0/imm32/tag/block # Stmt-tag -4540 8b/-> *(ebp+0xc) 1/r32/ecx -4541 89/<- *(eax+4) 1/r32/ecx # Block-statements -4542 $new-block:end: -4543 # . restore registers -4544 59/pop-to-ecx -4545 # . epilogue -4546 89/<- %esp 5/r32/ebp -4547 5d/pop-to-ebp -4548 c3/return -4549 -4550 new-vardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) -4551 # . prologue -4552 55/push-ebp -4553 89/<- %ebp 4/r32/esp -4554 # . save registers -4555 51/push-ecx -4556 # -4557 (allocate *(ebp+8) *Stmt-size) # => eax -4558 (zero-out %eax *Stmt-size) -4559 c7 0/subop/copy *eax 2/imm32/tag/var-on-stack # Stmt-tag -4560 # result->var = var -4561 8b/-> *(ebp+0xc) 1/r32/ecx -4562 89/<- *(eax+4) 1/r32/ecx # Vardef-var -4563 $new-vardef:end: -4564 # . restore registers -4565 59/pop-to-ecx -4566 # . epilogue -4567 89/<- %esp 5/r32/ebp -4568 5d/pop-to-ebp -4569 c3/return -4570 -4571 new-regvardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) -4572 # . prologue -4573 55/push-ebp -4574 89/<- %ebp 4/r32/esp -4575 # . save registers -4576 51/push-ecx -4577 57/push-edi -4578 # ecx = var -4579 8b/-> *(ebp+0xc) 1/r32/ecx -4580 # edi = result -4581 (allocate *(ebp+8) *Stmt-size) # => eax -4582 89/<- %edi 0/r32/eax -4583 (zero-out %edi *Stmt-size) -4584 # set tag -4585 c7 0/subop/copy *edi 3/imm32/tag/var-in-register # Stmt-tag -4586 # set output -4587 (append-stmt-var Heap %ecx *(edi+0xc) 0) # Regvardef-outputs => eax -4588 89/<- *(edi+0xc) 0/r32/eax # Regvardef-outputs -4589 $new-regvardef:end: -4590 89/<- %eax 7/r32/edi -4591 # . restore registers -4592 5f/pop-to-edi -4593 59/pop-to-ecx -4594 # . epilogue -4595 89/<- %esp 5/r32/ebp -4596 5d/pop-to-ebp -4597 c3/return -4598 -4599 append-list: # ad: (addr allocation-descriptor), value: _type, list: (handle list _type) -> result/eax: (handle list _type) -4600 # . prologue -4601 55/push-ebp -4602 89/<- %ebp 4/r32/esp -4603 # . save registers -4604 51/push-ecx -4605 # -4606 (allocate *(ebp+8) *List-size) # => eax -4607 (zero-out %eax *List-size) -4608 8b/-> *(ebp+0xc) 1/r32/ecx -4609 89/<- *eax 1/r32/ecx # List-value -4610 # if (list == null) return result -4611 81 7/subop/compare *(ebp+0x10) 0/imm32 -4612 74/jump-if-= $append-list:end/disp8 -4613 # otherwise append -4614 # var curr/ecx = list -4615 8b/-> *(ebp+0x10) 1/r32/ecx -4616 # while (curr->next != null) curr = curr->next -4617 { -4618 81 7/subop/compare *(ecx+4) 0/imm32 # List-next -4619 74/jump-if-= break/disp8 -4620 # curr = curr->next -4621 8b/-> *(ecx+4) 1/r32/ecx -4622 eb/jump loop/disp8 -4623 } -4624 # curr->next = result -4625 89/<- *(ecx+4) 0/r32/eax -4626 # return list -4627 8b/-> *(ebp+0x10) 0/r32/eax -4628 $append-list:end: -4629 # . restore registers -4630 59/pop-to-ecx -4631 # . epilogue -4632 89/<- %esp 5/r32/ebp -4633 5d/pop-to-ebp -4634 c3/return -4635 -4636 append-stmt-var: # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean -> result/eax: (handle stmt-var) -4637 # . prologue -4638 55/push-ebp -4639 89/<- %ebp 4/r32/esp -4640 # . save registers -4641 51/push-ecx -4642 # -4643 (allocate *(ebp+8) *Stmt-var-size) # => eax -4644 (zero-out %eax *Stmt-var-size) -4645 8b/-> *(ebp+0xc) 1/r32/ecx -4646 89/<- *eax 1/r32/ecx # Stmt-var-value -4647 8b/-> *(ebp+0x14) 1/r32/ecx -4648 89/<- *(eax+8) 1/r32/ecx # Stmt-var-is-deref -4649 # if (list == null) return result -4650 81 7/subop/compare *(ebp+0x10) 0/imm32 -4651 74/jump-if-= $append-stmt-var:end/disp8 -4652 # otherwise append -4653 # var curr/ecx: (handle stmt-var) = vars -4654 8b/-> *(ebp+0x10) 1/r32/ecx -4655 # while (curr->next != null) curr = curr->next -4656 { -4657 81 7/subop/compare *(ecx+4) 0/imm32 # List-next -4658 74/jump-if-= break/disp8 -4659 # curr = curr->next -4660 8b/-> *(ecx+4) 1/r32/ecx -4661 eb/jump loop/disp8 -4662 } -4663 # curr->next = result -4664 89/<- *(ecx+4) 0/r32/eax -4665 # return vars -4666 8b/-> *(ebp+0x10) 0/r32/eax -4667 $append-stmt-var:end: -4668 # . restore registers -4669 59/pop-to-ecx -4670 # . epilogue -4671 89/<- %esp 5/r32/ebp -4672 5d/pop-to-ebp -4673 c3/return -4674 -4675 append-to-block: # ad: (addr allocation-descriptor), block: (handle block), x: (handle stmt) -4676 # . prologue -4677 55/push-ebp -4678 89/<- %ebp 4/r32/esp -4679 # . save registers -4680 56/push-esi -4681 # esi = block -4682 8b/-> *(ebp+0xc) 6/r32/esi -4683 (append-list *(ebp+8) *(ebp+0x10) *(esi+4)) # ad, x, Block-statements -4684 89/<- *(esi+4) 0/r32/eax # Block-statements -4685 $append-to-block:end: -4686 # . restore registers -4687 5e/pop-to-esi -4688 # . epilogue -4689 89/<- %esp 5/r32/ebp -4690 5d/pop-to-ebp -4691 c3/return -4692 -4693 ####################################################### -4694 # Type-checking -4695 ####################################################### -4696 -4697 check-mu-types: -4698 # . prologue -4699 55/push-ebp -4700 89/<- %ebp 4/r32/esp -4701 # -4702 $check-mu-types:end: -4703 # . epilogue -4704 89/<- %esp 5/r32/ebp -4705 5d/pop-to-ebp -4706 c3/return -4707 -4708 size-of: # v: (addr var) -> result/eax: int -4709 # . prologue -4710 55/push-ebp -4711 89/<- %ebp 4/r32/esp -4712 # if v is a literal, return 0 -4713 8b/-> *(ebp+8) 0/r32/eax -4714 8b/-> *(eax+4) 0/r32/eax # Var-type -4715 81 7/subop/compare *eax 0/imm32 # Tree-left -4716 b8/copy-to-eax 0/imm32 -4717 74/jump-if-= $size-of:end/disp8 -4718 # hard-coded since we only support 'int' types for now -4719 b8/copy-to-eax 4/imm32 -4720 $size-of:end: -4721 # . epilogue -4722 89/<- %esp 5/r32/ebp -4723 5d/pop-to-ebp -4724 c3/return -4725 -4726 type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean -4727 # . prologue -4728 55/push-ebp -4729 89/<- %ebp 4/r32/esp -4730 # . save registers -4731 51/push-ecx -4732 52/push-edx -4733 # ecx = a -4734 8b/-> *(ebp+8) 1/r32/ecx -4735 # edx = b -4736 8b/-> *(ebp+0xc) 2/r32/edx -4737 # if (a == b) return true -4738 8b/-> %ecx 0/r32/eax # Var-type -4739 39/compare %edx 0/r32/eax # Var-type -4740 b8/copy-to-eax 1/imm32/true -4741 74/jump-if-= $type-equal?:end/disp8 -4742 # if (a < MAX_TYPE_ID) return false -4743 81 7/subop/compare %ecx 0x10000/imm32 -4744 b8/copy-to-eax 0/imm32/false -4745 72/jump-if-addr< $type-equal?:end/disp8 -4746 # if (b < MAX_TYPE_ID) return false -4747 81 7/subop/compare %edx 0x10000/imm32 -4748 b8/copy-to-eax 0/imm32/false -4749 72/jump-if-addr< $type-equal?:end/disp8 -4750 # if (!type-equal?(a->left, b->left)) return false -4751 (type-equal? *ecx *edx) # Tree-left, Tree-left => eax -4752 3d/compare-eax-and 0/imm32/false -4753 74/jump-if-= $type-equal?:end/disp8 -4754 # return type-equal?(a->right, b->right) -4755 (type-equal? *(ecx+4) *(edx+4)) # Tree-right, Tree-right => eax -4756 $type-equal?:end: -4757 # . restore registers -4758 5a/pop-to-edx -4759 59/pop-to-ecx -4760 # . epilogue -4761 89/<- %esp 5/r32/ebp -4762 5d/pop-to-ebp -4763 c3/return -4764 -4765 == data -4766 -4767 # not yet used, but it will be -4768 Type-size: # (stream int) -4769 0x18/imm32/write -4770 0/imm32/read -4771 0x100/imm32/length -4772 # data -4773 4/imm32 # literal -4774 4/imm32 # int -4775 4/imm32 # addr -4776 0/imm32 # array (logic elsewhere) -4777 8/imm32 # handle (fat pointer) -4778 4/imm32 # bool -4779 0/imm32 -4780 0/imm32 -4781 # 0x20 -4782 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4783 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4784 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4785 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4786 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4787 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4788 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4789 -4790 == code -4791 -4792 ####################################################### -4793 # Code-generation -4794 ####################################################### -4795 -4796 emit-subx: # out: (addr buffered-file) -4797 # . prologue -4798 55/push-ebp -4799 89/<- %ebp 4/r32/esp -4800 # . save registers -4801 50/push-eax -4802 51/push-ecx -4803 57/push-edi -4804 # edi = out -4805 8b/-> *(ebp+8) 7/r32/edi -4806 # var curr/ecx: (handle function) = *Program -4807 8b/-> *Program 1/r32/ecx -4808 { -4809 # if (curr == null) break -4810 81 7/subop/compare %ecx 0/imm32 -4811 0f 84/jump-if-= break/disp32 -4812 (emit-subx-function %edi %ecx) -4813 # curr = curr->next -4814 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next -4815 e9/jump loop/disp32 -4816 } -4817 $emit-subx:end: -4818 # . restore registers -4819 5f/pop-to-edi -4820 59/pop-to-ecx -4821 58/pop-to-eax -4822 # . epilogue -4823 89/<- %esp 5/r32/ebp -4824 5d/pop-to-ebp -4825 c3/return -4826 -4827 emit-subx-function: # out: (addr buffered-file), f: (handle function) -4828 # . prologue -4829 55/push-ebp -4830 89/<- %ebp 4/r32/esp -4831 # . save registers -4832 50/push-eax -4833 51/push-ecx -4834 52/push-edx -4835 57/push-edi -4836 # edi = out -4837 8b/-> *(ebp+8) 7/r32/edi -4838 # ecx = f -4839 8b/-> *(ebp+0xc) 1/r32/ecx -4840 # var vars/edx: (stack (addr var) 256) -4841 81 5/subop/subtract %esp 0x400/imm32 -4842 68/push 0x400/imm32/length -4843 68/push 0/imm32/top -4844 89/<- %edx 4/r32/esp -4845 # -4846 (write-buffered %edi *ecx) -4847 (write-buffered %edi ":\n") -4848 # Important: each block's depth during code-generation should be identical -4849 # to what it was during parsing. -4850 c7 0/subop/copy *Curr-block-depth 1/imm32 -4851 (emit-subx-prologue %edi) -4852 (emit-subx-block %edi *(ecx+0x10) %edx) # Function-body -4853 (emit-subx-epilogue %edi) -4854 $emit-subx-function:end: -4855 # . reclaim locals -4856 81 0/subop/add %esp 408/imm32 -4857 # . restore registers -4858 5f/pop-to-edi -4859 5a/pop-to-edx -4860 59/pop-to-ecx -4861 58/pop-to-eax -4862 # . epilogue -4863 89/<- %esp 5/r32/ebp -4864 5d/pop-to-ebp -4865 c3/return -4866 -4867 emit-subx-stmt-list: # out: (addr buffered-file), stmts: (handle list stmt), vars: (addr stack (handle var)) -4868 # . prologue -4869 55/push-ebp -4870 89/<- %ebp 4/r32/esp -4871 # . save registers -4872 50/push-eax -4873 51/push-ecx -4874 52/push-edx -4875 53/push-ebx -4876 56/push-esi -4877 # esi = stmts -4878 8b/-> *(ebp+0xc) 6/r32/esi -4879 # var var-seen?/edx: boolean <- copy false -4880 ba/copy-to-edx 0/imm32/false -4881 # -4882 { -4883 $emit-subx-stmt-list:loop: -4884 81 7/subop/compare %esi 0/imm32 -4885 0f 84/jump-if-= break/disp32 -4886 # var curr-stmt/ecx = stmts->value -4887 8b/-> *esi 1/r32/ecx # List-value -4888 { -4889 $emit-subx-stmt-list:check-for-block: -4890 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag -4891 75/jump-if-!= break/disp8 -4892 $emit-subx-stmt-list:block: -4893 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10)) -4894 } -4895 { -4896 $emit-subx-stmt-list:check-for-stmt: -4897 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag -4898 0f 85/jump-if-!= break/disp32 -4899 $emit-subx-stmt-list:stmt1: -4900 { -4901 (is-mu-branch? %ecx) # => eax -4902 3d/compare-eax-and 0/imm32/false -4903 0f 84/jump-if-= break/disp32 -4904 $emit-subx-stmt-list:branch-stmt: -4905 # if !var-seen? break -4906 81 7/subop/compare %edx 0/imm32/false -4907 0f 84/jump-if-= break/disp32 -4908 $emit-subx-stmt-list:branch-stmt-and-var-seen: -4909 +-- 26 lines: # unconditional loops ----------------------------------------------------------------------------------------------------------------------------------------------------- -4935 +-- 15 lines: # unconditional breaks ---------------------------------------------------------------------------------------------------------------------------------------------------- -4950 +-- 37 lines: # simple conditional branches without a target ---------------------------------------------------------------------------------------------------------------------------- -4987 +-- 19 lines: # conditional branches with an explicit target ---------------------------------------------------------------------------------------------------------------------------- -5006 } -5007 $emit-subx-stmt-list:1-to-1: -5008 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) -5009 } -5010 { -5011 $emit-subx-stmt-list:check-for-vardef: -5012 81 7/subop/compare *ecx 2/imm32/vardef # Stmt-tag -5013 75/jump-if-!= break/disp8 -5014 $emit-subx-stmt-list:vardef: -5015 (emit-subx-var-def *(ebp+8) %ecx) -5016 (push *(ebp+0x10) *(ecx+4)) # Vardef-var -5017 # var-seen? = true -5018 ba/copy-to-edx 1/imm32/true -5019 } -5020 { -5021 $emit-subx-stmt-list:check-for-regvardef: -5022 81 7/subop/compare *ecx 3/imm32/regvardef # Stmt-tag -5023 0f 85/jump-if-!= break/disp32 -5024 $emit-subx-stmt-list:regvardef: -5025 # TODO: ensure that there's exactly one output -5026 # var output/eax: (handle var) = curr-stmt->outputs->value -5027 8b/-> *(ecx+0xc) 0/r32/eax -5028 8b/-> *eax 0/r32/eax -5029 # ensure that output is in a register -5030 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -5031 0f 84/jump-if-= $emit-subx-stmt-list:abort-regvardef-without-register/disp32 -5032 # emit spill -5033 (emit-indent *(ebp+8) *Curr-block-depth) -5034 (write-buffered *(ebp+8) "ff 6/subop/push %") -5035 (write-buffered *(ebp+8) *(eax+0x10)) -5036 (write-buffered *(ebp+8) Newline) -5037 # register variable definition -5038 (push *(ebp+0x10) %eax) -5039 # emit the instruction as usual -5040 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) -5041 # var-seen? = true -5042 ba/copy-to-edx 1/imm32/true -5043 } -5044 $emit-subx-stmt-list:continue: -5045 # TODO: raise an error on unrecognized Stmt-tag -5046 8b/-> *(esi+4) 6/r32/esi # List-next -5047 e9/jump loop/disp32 -5048 } -5049 $emit-subx-stmt-list:emit-cleanup: -5050 (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth) -5051 $emit-subx-stmt-list:cleanup: -5052 (clean-up-blocks *(ebp+0x10) *Curr-block-depth) -5053 $emit-subx-stmt-list:end: -5054 # . restore registers -5055 5e/pop-to-esi -5056 5b/pop-to-ebx -5057 5a/pop-to-edx -5058 59/pop-to-ecx -5059 58/pop-to-eax -5060 # . epilogue -5061 89/<- %esp 5/r32/ebp -5062 5d/pop-to-ebp -5063 c3/return -5064 -5065 $emit-subx-stmt-list:abort-regvardef-without-register: -5066 # error("var '" var->name "' initialized from an instruction must live in a register\n") -5067 (write-buffered Stderr "var '") -5068 (write-buffered Stderr *eax) # Var-name -5069 (write-buffered Stderr "' initialized from an instruction must live in a register\n") -5070 (flush Stderr) -5071 # . syscall(exit, 1) -5072 bb/copy-to-ebx 1/imm32 -5073 b8/copy-to-eax 1/imm32/exit -5074 cd/syscall 0x80/imm8 -5075 # never gets here -5076 -5077 emit-subx-cleanup-and-unconditional-nonlocal-branch: # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack (handle var)) -5078 # . prologue -5079 55/push-ebp -5080 89/<- %ebp 4/r32/esp -5081 # . save registers -5082 50/push-eax -5083 51/push-ecx -5084 52/push-edx -5085 # ecx = stmt -5086 8b/-> *(ebp+0xc) 1/r32/ecx -5087 # var target/edx: (addr array byte) = curr-stmt->inouts->value->name -5088 8b/-> *(ecx+8) 2/r32/edx # Stmt1-inouts -5089 8b/-> *edx 2/r32/edx # Stmt-var-value -5090 8b/-> *edx 2/r32/edx # Var-name -5091 # clean up until target block -5092 (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %edx) -5093 # emit jump to target block -5094 (emit-indent *(ebp+8) *Curr-block-depth) -5095 (write-buffered *(ebp+8) "e9/jump ") -5096 (write-buffered *(ebp+8) %edx) -5097 (string-starts-with? *(ecx+4) "break") -5098 3d/compare-eax-and 0/imm32/false -5099 { -5100 74/jump-if-= break/disp8 -5101 (write-buffered *(ebp+8) ":break/disp32\n") -5102 } -5103 3d/compare-eax-and 0/imm32/false # just in case the function call modified flags -5104 { -5105 75/jump-if-!= break/disp8 -5106 (write-buffered *(ebp+8) ":loop/disp32\n") -5107 } -5108 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end: -5109 # . restore registers -5110 5a/pop-to-edx -5111 59/pop-to-ecx -5112 58/pop-to-eax -5113 # . epilogue -5114 89/<- %esp 5/r32/ebp -5115 5d/pop-to-ebp -5116 c3/return -5117 -5118 is-mu-branch?: # stmt: (addr stmt1) -> result/eax: boolean -5119 # . prologue -5120 55/push-ebp -5121 89/<- %ebp 4/r32/esp -5122 # . save registers -5123 51/push-ecx -5124 # ecx = stmt -5125 8b/-> *(ebp+8) 1/r32/ecx -5126 # if (stmt->operation starts with "loop") return true -5127 (string-starts-with? *(ecx+4) "loop") # Stmt1-operation => eax -5128 3d/compare-eax-and 0/imm32/false -5129 75/jump-if-not-equal $is-mu-branch?:end/disp8 -5130 # otherwise return (stmt->operation starts with "break") -5131 (string-starts-with? *(ecx+4) "break") # Stmt1-operation => eax -5132 $is-mu-branch?:end: -5133 # . restore registers -5134 59/pop-to-ecx -5135 # . epilogue -5136 89/<- %esp 5/r32/ebp -5137 5d/pop-to-ebp -5138 c3/return -5139 -5140 emit-reverse-break: # out: (addr buffered-file), stmt: (addr stmt1) -5141 # . prologue -5142 55/push-ebp -5143 89/<- %ebp 4/r32/esp -5144 # . save registers -5145 50/push-eax -5146 # eax = stmt -5147 8b/-> *(ebp+0xc) 0/r32/eax -5148 # -5149 (get Reverse-branch *(eax+4) 8 "reverse-branch: ") # Stmt1-operation => eax: (addr addr array byte) -5150 (emit-indent *(ebp+8) *Curr-block-depth) -5151 (write-buffered *(ebp+8) *eax) -5152 (write-buffered *(ebp+8) " break/disp32\n") -5153 $emit-reverse-break:end: -5154 # . restore registers -5155 58/pop-to-eax -5156 # . epilogue -5157 89/<- %esp 5/r32/ebp -5158 5d/pop-to-ebp -5159 c3/return -5160 -5161 == data -5162 -5163 Reverse-branch: # (table string string) -5164 # a table is a stream -5165 0xa0/imm32/write -5166 0/imm32/read -5167 0xa0/imm32/length -5168 # data -5169 "break-if-="/imm32 "0f 85/jump-if-!="/imm32 -5170 "loop-if-="/imm32 "0f 85/jump-if-!="/imm32 -5171 "break-if-!="/imm32 "0f 84/jump-if-="/imm32 -5172 "loop-if-!="/imm32 "0f 84/jump-if-="/imm32 -5173 "break-if-<"/imm32 "0f 8d/jump-if->="/imm32 -5174 "loop-if-<"/imm32 "0f 8d/jump-if->="/imm32 -5175 "break-if->"/imm32 "0f 8e/jump-if-<="/imm32 -5176 "loop-if->"/imm32 "0f 8e/jump-if-<="/imm32 -5177 "break-if-<="/imm32 "0f 87/jump-if->"/imm32 -5178 "loop-if-<="/imm32 "0f 87/jump-if->"/imm32 -5179 "break-if->="/imm32 "0f 8c/jump-if-<"/imm32 -5180 "loop-if->="/imm32 "0f 8c/jump-if-<"/imm32 -5181 "break-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 -5182 "loop-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 -5183 "break-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 -5184 "loop-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 -5185 "break-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 -5186 "loop-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 -5187 "break-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 -5188 "loop-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 -5189 -5190 == code -5191 -5192 emit-unconditional-jump-to-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), depth: int, label-suffix: (addr array byte) -5193 # . prologue -5194 55/push-ebp -5195 89/<- %ebp 4/r32/esp -5196 # . save registers -5197 50/push-eax -5198 51/push-ecx -5199 52/push-edx -5200 53/push-ebx -5201 # ecx = vars -5202 8b/-> *(ebp+0xc) 1/r32/ecx -5203 # var eax: int = vars->top -5204 8b/-> *ecx 0/r32/eax -5205 # var min/ecx: (address (handle var)) = vars->data -5206 81 0/subop/add %ecx 8/imm32 -5207 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] -5208 81 5/subop/subtract %eax 4/imm32 -5209 8d/copy-address *(ecx+eax) 0/r32/eax -5210 # edx = depth -5211 8b/-> *(ebp+0x10) 2/r32/edx -5212 { -5213 $emit-unconditional-jump-to-depth:loop: -5214 # if (curr < min) break -5215 39/compare %eax 1/r32/ecx -5216 0f 82/jump-if-addr< break/disp32 -5217 # var v/ebx: (handle var) = *curr -5218 8b/-> *eax 3/r32/ebx -5219 # if (v->block-depth < until-block-depth) break -5220 39/compare *(ebx+8) 2/r32/edx # Var-block-depth -5221 0f 8c/jump-if-< break/disp32 -5222 { -5223 $emit-unconditional-jump-to-depth:check: -5224 # if v->block-depth != until-block-depth, continue -5225 39/compare *(ebx+8) 2/r32/edx # Var-block-depth -5226 0f 85/jump-if-!= break/disp32 -5227 $emit-unconditional-jump-to-depth:depth-found: -5228 # if v is not a literal, continue -5229 # . var eax: int = size-of(v) -5230 50/push-eax -5231 (size-of %ebx) # => eax -5232 # . if (eax != 0) continue -5233 3d/compare-eax-and 0/imm32 -5234 58/pop-to-eax -5235 # -5236 0f 85/jump-if-!= break/disp32 -5237 $emit-unconditional-jump-to-depth:label-found: -5238 # emit unconditional jump, then return -5239 (emit-indent *(ebp+8) *Curr-block-depth) -5240 (write-buffered *(ebp+8) "e9/jump ") -5241 (write-buffered *(ebp+8) *ebx) # Var-name -5242 (write-buffered *(ebp+8) ":") -5243 (write-buffered *(ebp+8) *(ebp+0x14)) -5244 (write-buffered *(ebp+8) "/disp32\n") -5245 eb/jump $emit-unconditional-jump-to-depth:end/disp8 -5246 } -5247 # curr -= 4 -5248 2d/subtract-from-eax 4/imm32 -5249 e9/jump loop/disp32 -5250 } -5251 # TODO: error if no label at 'depth' was found -5252 $emit-unconditional-jump-to-depth:end: -5253 # . restore registers -5254 5b/pop-to-ebx -5255 5a/pop-to-edx -5256 59/pop-to-ecx -5257 58/pop-to-eax -5258 # . epilogue -5259 89/<- %esp 5/r32/ebp -5260 5d/pop-to-ebp -5261 c3/return -5262 -5263 # emit clean-up code for 'vars' until some block depth -5264 # doesn't actually modify 'vars' so we need traverse manually inside the stack -5265 emit-cleanup-code-until-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-depth: int -5266 # . prologue -5267 55/push-ebp -5268 89/<- %ebp 4/r32/esp -5269 # . save registers -5270 50/push-eax -5271 51/push-ecx -5272 52/push-edx -5273 53/push-ebx -5274 # ecx = vars -5275 8b/-> *(ebp+0xc) 1/r32/ecx -5276 # var eax: int = vars->top -5277 8b/-> *ecx 0/r32/eax -5278 # var min/ecx: (address (handle var)) = vars->data -5279 81 0/subop/add %ecx 8/imm32 -5280 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] -5281 81 5/subop/subtract %eax 4/imm32 -5282 8d/copy-address *(ecx+eax) 0/r32/eax -5283 # edx = until-block-depth -5284 8b/-> *(ebp+0x10) 2/r32/edx -5285 { -5286 $emit-cleanup-code-until-depth:loop: -5287 # if (curr < min) break -5288 39/compare %eax 1/r32/ecx -5289 0f 82/jump-if-addr< break/disp32 -5290 # var v/ebx: (handle var) = *curr -5291 8b/-> *eax 3/r32/ebx -5292 # if (v->block-depth < until-block-depth) break -5293 39/compare *(ebx+8) 2/r32/edx # Var-block-depth -5294 0f 8c/jump-if-< break/disp32 -5295 # if v is in a register -5296 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -5297 { -5298 74/jump-if-= break/disp8 -5299 $emit-cleanup-code-until-depth:reclaim-var-in-register: -5300 (emit-indent *(ebp+8) *Curr-block-depth) -5301 (write-buffered *(ebp+8) "8f 0/subop/pop %") -5302 (write-buffered *(ebp+8) *(ebx+0x10)) -5303 (write-buffered *(ebp+8) Newline) -5304 } -5305 # otherwise v is on the stack -5306 { -5307 75/jump-if-!= break/disp8 -5308 $emit-cleanup-code-until-depth:reclaim-var-on-stack: -5309 50/push-eax -5310 (size-of %ebx) # => eax -5311 # don't emit code for labels -5312 3d/compare-eax-and 0/imm32 -5313 74/jump-if-= break/disp8 -5314 # -5315 (emit-indent *(ebp+8) *Curr-block-depth) -5316 (write-buffered *(ebp+8) "81 0/subop/add %esp ") -5317 (print-int32-buffered *(ebp+8) %eax) -5318 (write-buffered *(ebp+8) "/imm32\n") -5319 58/pop-to-eax -5320 } -5321 # curr -= 4 -5322 2d/subtract-from-eax 4/imm32 -5323 e9/jump loop/disp32 -5324 } -5325 $emit-cleanup-code-until-depth:end: -5326 # . restore registers -5327 5b/pop-to-ebx -5328 5a/pop-to-edx -5329 59/pop-to-ecx -5330 58/pop-to-eax -5331 # . epilogue -5332 89/<- %esp 5/r32/ebp -5333 5d/pop-to-ebp -5334 c3/return -5335 -5336 # emit clean-up code for 'vars' until a given label is encountered -5337 # doesn't actually modify 'vars' so we need traverse manually inside the stack -5338 emit-cleanup-code-until-target: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-label: (addr array byte) -5339 # . prologue -5340 55/push-ebp -5341 89/<- %ebp 4/r32/esp -5342 # . save registers -5343 50/push-eax -5344 51/push-ecx -5345 52/push-edx -5346 53/push-ebx -5347 # ecx = vars -5348 8b/-> *(ebp+0xc) 1/r32/ecx -5349 # var eax: int = vars->top -5350 8b/-> *ecx 0/r32/eax -5351 # var min/ecx: (address (handle var)) = vars->data -5352 81 0/subop/add %ecx 8/imm32 -5353 # var curr/edx: (address (handle var)) = &vars->data[vars->top - 4] -5354 81 5/subop/subtract %eax 4/imm32 -5355 8d/copy-address *(ecx+eax) 2/r32/edx -5356 { -5357 $emit-cleanup-code-until-target:loop: -5358 # if (curr < min) break -5359 39/compare %edx 1/r32/ecx -5360 0f 82/jump-if-addr< break/disp32 -5361 # var v/ebx: (handle var) = *curr -5362 8b/-> *edx 3/r32/ebx -5363 # if (v->name == until-block-label) break -5364 (string-equal? *ebx *(ebp+0x10)) # => eax -5365 3d/compare-eax-and 0/imm32/false -5366 0f 85/jump-if-!= break/disp32 -5367 # if v is in a register -5368 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -5369 { -5370 74/jump-if-= break/disp8 -5371 $emit-cleanup-code-until-target:reclaim-var-in-register: -5372 (emit-indent *(ebp+8) *Curr-block-depth) -5373 (write-buffered *(ebp+8) "8f 0/subop/pop %") -5374 (write-buffered *(ebp+8) *(ebx+0x10)) -5375 (write-buffered *(ebp+8) Newline) -5376 } -5377 # otherwise v is on the stack -5378 { -5379 75/jump-if-!= break/disp8 -5380 $emit-cleanup-code-until-target:reclaim-var-on-stack: -5381 (size-of %ebx) # => eax -5382 # don't emit code for labels -5383 3d/compare-eax-and 0/imm32 -5384 74/jump-if-= break/disp8 -5385 # -5386 (emit-indent *(ebp+8) *Curr-block-depth) -5387 (write-buffered *(ebp+8) "81 0/subop/add %esp ") -5388 (print-int32-buffered *(ebp+8) %eax) -5389 (write-buffered *(ebp+8) "/imm32\n") -5390 } -5391 # curr -= 4 -5392 81 5/subop/subtract %edx 4/imm32 -5393 e9/jump loop/disp32 -5394 } -5395 $emit-cleanup-code-until-target:end: -5396 # . restore registers -5397 5b/pop-to-ebx -5398 5a/pop-to-edx -5399 59/pop-to-ecx -5400 58/pop-to-eax -5401 # . epilogue -5402 89/<- %esp 5/r32/ebp -5403 5d/pop-to-ebp -5404 c3/return -5405 -5406 # clean up global state for 'vars' until some block depth -5407 clean-up-blocks: # vars: (addr stack (handle var)), until-block-depth: int -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 = vars -5416 8b/-> *(ebp+8) 6/r32/esi -5417 # ecx = until-block-depth -5418 8b/-> *(ebp+0xc) 1/r32/ecx -5419 { -5420 $clean-up-blocks:reclaim-loop: -5421 # if (vars->top <= 0) break -5422 81 7/subop/compare *esi 0/imm32 # Stack-top -5423 7e/jump-if-<= break/disp8 -5424 # var v/eax: (handle var) = top(vars) -5425 (top %esi) # => eax -5426 # if (v->block-depth < until-block-depth) break -5427 39/compare *(eax+8) 1/r32/ecx # Var-block-depth -5428 7c/jump-if-< break/disp8 -5429 # if v is on the stack, update Next-local-stack-offset -5430 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -5431 { -5432 75/jump-if-!= break/disp8 -5433 $clean-up-blocks:reclaim-var-on-stack: -5434 (size-of %eax) # => eax -5435 01/add *Next-local-stack-offset 0/r32/eax -5436 } -5437 (pop %esi) -5438 e9/jump loop/disp32 -5439 } -5440 $clean-up-blocks: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 emit-subx-var-def: # out: (addr buffered-file), stmt: (handle statement) -5451 # . prologue -5452 55/push-ebp -5453 89/<- %ebp 4/r32/esp -5454 # . save registers -5455 50/push-eax -5456 51/push-ecx -5457 # eax = stmt -5458 8b/-> *(ebp+0xc) 0/r32/eax -5459 # var n/eax: int = size-of(stmt->var) -5460 (size-of *(eax+4)) # Vardef-var => eax -5461 # while n > 0 -5462 { -5463 3d/compare-eax-with 0/imm32 -5464 7e/jump-if-<= break/disp8 -5465 (emit-indent *(ebp+8) *Curr-block-depth) -5466 (write-buffered *(ebp+8) "68/push 0/imm32\n") -5467 # n -= 4 -5468 2d/subtract-from-eax 4/imm32 -5469 # -5470 eb/jump loop/disp8 -5471 } -5472 $emit-subx-var-def:end: -5473 # . restore registers -5474 59/pop-to-ecx -5475 58/pop-to-eax -5476 # . epilogue -5477 89/<- %esp 5/r32/ebp -5478 5d/pop-to-ebp -5479 c3/return -5480 -5481 emit-subx-statement: # out: (addr buffered-file), stmt: (handle statement), primitives: (handle primitive), functions: (handle function) -5482 # . prologue -5483 55/push-ebp -5484 89/<- %ebp 4/r32/esp -5485 # . save registers -5486 50/push-eax -5487 51/push-ecx -5488 # handle some special cases -5489 # ecx = stmt -5490 8b/-> *(ebp+0xc) 1/r32/ecx -5491 +-- 24 lines: # array length ------------------------------------------------------------------------------------------------------------------------------------------------------------ -5515 +-- 32 lines: # array index ------------------------------------------------------------------------------------------------------------------------------------------------------------- -5547 # if stmt matches a primitive, emit it -5548 { -5549 $emit-subx-statement:check-for-primitive: -5550 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => curr/eax -5551 3d/compare-eax-and 0/imm32 -5552 74/jump-if-= break/disp8 -5553 $emit-subx-statement:primitive: -5554 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr -5555 e9/jump $emit-subx-statement:end/disp32 -5556 } -5557 # else if stmt matches a function, emit a call to it -5558 { -5559 $emit-subx-statement:check-for-call: -5560 (find-matching-function *(ebp+0x14) *(ebp+0xc)) # functions, stmt => curr/eax -5561 3d/compare-eax-and 0/imm32 -5562 74/jump-if-= break/disp8 -5563 $emit-subx-statement:call: -5564 (emit-subx-call *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr -5565 e9/jump $emit-subx-statement:end/disp32 -5566 } -5567 # else assume it's a SubX function (TODO: how to type-check?!) -5568 (emit-hailmary-call *(ebp+8) *(ebp+0xc)) -5569 $emit-subx-statement:end: -5570 # . restore registers -5571 59/pop-to-ecx -5572 58/pop-to-eax -5573 # . epilogue -5574 89/<- %esp 5/r32/ebp -5575 5d/pop-to-ebp -5576 c3/return -5577 -5578 $emit-subx-statement:abort: -5579 # error("couldn't translate '" stmt "'\n") -5580 (write-buffered Stderr "couldn't translate an instruction with operation '") -5581 8b/-> *(ebp+0xc) 0/r32/eax -5582 (write-buffered Stderr *(eax+4)) # Stmt1-operation -5583 (write-buffered Stderr "'\n") -5584 (flush Stderr) -5585 # . syscall(exit, 1) -5586 bb/copy-to-ebx 1/imm32 -5587 b8/copy-to-eax 1/imm32/exit -5588 cd/syscall 0x80/imm8 -5589 # never gets here -5590 -5591 emit-subx-block: # out: (addr buffered-file), block: (handle block), vars: (addr stack (handle var)) -5592 # . prologue -5593 55/push-ebp -5594 89/<- %ebp 4/r32/esp -5595 # . save registers -5596 50/push-eax -5597 51/push-ecx -5598 56/push-esi -5599 # esi = block -5600 8b/-> *(ebp+0xc) 6/r32/esi -5601 # var stmts/eax: (handle list statement) = block->statements -5602 8b/-> *(esi+4) 0/r32/eax # Block-statements -5603 # -5604 { -5605 $emit-subx-block:check-empty: -5606 81 7/subop/compare %eax 0/imm32 -5607 0f 84/jump-if-= break/disp32 -5608 (emit-indent *(ebp+8) *Curr-block-depth) -5609 (write-buffered *(ebp+8) "{\n") -5610 # var v/ecx: (addr array byte) = block->var->name -5611 8b/-> *(esi+8) 1/r32/ecx # Block-var -5612 (write-buffered *(ebp+8) *ecx) # Var-name -5613 (write-buffered *(ebp+8) ":loop:\n") -5614 ff 0/subop/increment *Curr-block-depth -5615 (push *(ebp+0x10) %ecx) -5616 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10)) -5617 (pop *(ebp+0x10)) # => eax -5618 ff 1/subop/decrement *Curr-block-depth -5619 (emit-indent *(ebp+8) *Curr-block-depth) -5620 (write-buffered *(ebp+8) "}\n") -5621 (write-buffered *(ebp+8) *ecx) # Var-name -5622 (write-buffered *(ebp+8) ":break:\n") -5623 } -5624 $emit-subx-block:end: -5625 # . restore registers -5626 5e/pop-to-esi -5627 59/pop-to-ecx -5628 58/pop-to-eax -5629 # . epilogue -5630 89/<- %esp 5/r32/ebp -5631 5d/pop-to-ebp -5632 c3/return -5633 -5634 # Primitives supported -5635 # For each operation, put variants with hard-coded registers before flexible ones. -5636 == data -5637 Primitives: -5638 # - increment/decrement -5639 _Primitive-inc-eax: -5640 # var/eax <- increment => 40/increment-eax -5641 "increment"/imm32/name -5642 0/imm32/no-inouts -5643 Single-int-var-in-eax/imm32/outputs -5644 "40/increment-eax"/imm32/subx-name -5645 0/imm32/no-rm32 -5646 0/imm32/no-r32 -5647 0/imm32/no-imm32 -5648 0/imm32/no-disp32 -5649 0/imm32/output-is-write-only -5650 _Primitive-inc-ecx/imm32/next -5651 _Primitive-inc-ecx: -5652 # var/ecx <- increment => 41/increment-ecx -5653 "increment"/imm32/name -5654 0/imm32/no-inouts -5655 Single-int-var-in-ecx/imm32/outputs -5656 "41/increment-ecx"/imm32/subx-name -5657 0/imm32/no-rm32 -5658 0/imm32/no-r32 -5659 0/imm32/no-imm32 -5660 0/imm32/no-disp32 -5661 0/imm32/output-is-write-only -5662 _Primitive-inc-edx/imm32/next -5663 _Primitive-inc-edx: -5664 # var/edx <- increment => 42/increment-edx -5665 "increment"/imm32/name -5666 0/imm32/no-inouts -5667 Single-int-var-in-edx/imm32/outputs -5668 "42/increment-edx"/imm32/subx-name -5669 0/imm32/no-rm32 -5670 0/imm32/no-r32 -5671 0/imm32/no-imm32 -5672 0/imm32/no-disp32 -5673 0/imm32/output-is-write-only -5674 _Primitive-inc-ebx/imm32/next -5675 _Primitive-inc-ebx: -5676 # var/ebx <- increment => 43/increment-ebx -5677 "increment"/imm32/name -5678 0/imm32/no-inouts -5679 Single-int-var-in-ebx/imm32/outputs -5680 "43/increment-ebx"/imm32/subx-name -5681 0/imm32/no-rm32 -5682 0/imm32/no-r32 -5683 0/imm32/no-imm32 -5684 0/imm32/no-disp32 -5685 0/imm32/output-is-write-only -5686 _Primitive-inc-esi/imm32/next -5687 _Primitive-inc-esi: -5688 # var/esi <- increment => 46/increment-esi -5689 "increment"/imm32/name -5690 0/imm32/no-inouts -5691 Single-int-var-in-esi/imm32/outputs -5692 "46/increment-esi"/imm32/subx-name -5693 0/imm32/no-rm32 -5694 0/imm32/no-r32 -5695 0/imm32/no-imm32 -5696 0/imm32/no-disp32 -5697 0/imm32/output-is-write-only -5698 _Primitive-inc-edi/imm32/next -5699 _Primitive-inc-edi: -5700 # var/edi <- increment => 47/increment-edi -5701 "increment"/imm32/name -5702 0/imm32/no-inouts -5703 Single-int-var-in-edi/imm32/outputs -5704 "47/increment-edi"/imm32/subx-name -5705 0/imm32/no-rm32 -5706 0/imm32/no-r32 -5707 0/imm32/no-imm32 -5708 0/imm32/no-disp32 -5709 0/imm32/output-is-write-only -5710 _Primitive-dec-eax/imm32/next -5711 _Primitive-dec-eax: -5712 # var/eax <- decrement => 48/decrement-eax -5713 "decrement"/imm32/name -5714 0/imm32/no-inouts -5715 Single-int-var-in-eax/imm32/outputs -5716 "48/decrement-eax"/imm32/subx-name -5717 0/imm32/no-rm32 -5718 0/imm32/no-r32 -5719 0/imm32/no-imm32 -5720 0/imm32/no-disp32 -5721 0/imm32/output-is-write-only -5722 _Primitive-dec-ecx/imm32/next -5723 _Primitive-dec-ecx: -5724 # var/ecx <- decrement => 49/decrement-ecx -5725 "decrement"/imm32/name -5726 0/imm32/no-inouts -5727 Single-int-var-in-ecx/imm32/outputs -5728 "49/decrement-ecx"/imm32/subx-name -5729 0/imm32/no-rm32 -5730 0/imm32/no-r32 -5731 0/imm32/no-imm32 -5732 0/imm32/no-disp32 -5733 0/imm32/output-is-write-only -5734 _Primitive-dec-edx/imm32/next -5735 _Primitive-dec-edx: -5736 # var/edx <- decrement => 4a/decrement-edx -5737 "decrement"/imm32/name -5738 0/imm32/no-inouts -5739 Single-int-var-in-edx/imm32/outputs -5740 "4a/decrement-edx"/imm32/subx-name -5741 0/imm32/no-rm32 -5742 0/imm32/no-r32 -5743 0/imm32/no-imm32 -5744 0/imm32/no-disp32 -5745 0/imm32/output-is-write-only -5746 _Primitive-dec-ebx/imm32/next -5747 _Primitive-dec-ebx: -5748 # var/ebx <- decrement => 4b/decrement-ebx -5749 "decrement"/imm32/name -5750 0/imm32/no-inouts -5751 Single-int-var-in-ebx/imm32/outputs -5752 "4b/decrement-ebx"/imm32/subx-name -5753 0/imm32/no-rm32 -5754 0/imm32/no-r32 -5755 0/imm32/no-imm32 -5756 0/imm32/no-disp32 -5757 0/imm32/output-is-write-only -5758 _Primitive-dec-esi/imm32/next -5759 _Primitive-dec-esi: -5760 # var/esi <- decrement => 4e/decrement-esi -5761 "decrement"/imm32/name -5762 0/imm32/no-inouts -5763 Single-int-var-in-esi/imm32/outputs -5764 "4e/decrement-esi"/imm32/subx-name -5765 0/imm32/no-rm32 -5766 0/imm32/no-r32 -5767 0/imm32/no-imm32 -5768 0/imm32/no-disp32 -5769 0/imm32/output-is-write-only -5770 _Primitive-dec-edi/imm32/next -5771 _Primitive-dec-edi: -5772 # var/edi <- decrement => 4f/decrement-edi -5773 "decrement"/imm32/name -5774 0/imm32/no-inouts -5775 Single-int-var-in-edi/imm32/outputs -5776 "4f/decrement-edi"/imm32/subx-name -5777 0/imm32/no-rm32 -5778 0/imm32/no-r32 -5779 0/imm32/no-imm32 -5780 0/imm32/no-disp32 -5781 0/imm32/output-is-write-only -5782 _Primitive-inc-mem/imm32/next -5783 _Primitive-inc-mem: -5784 # increment var => ff 0/subop/increment *(ebp+__) -5785 "increment"/imm32/name -5786 Single-int-var-in-mem/imm32/inouts -5787 0/imm32/no-outputs -5788 "ff 0/subop/increment"/imm32/subx-name -5789 1/imm32/rm32-is-first-inout -5790 0/imm32/no-r32 -5791 0/imm32/no-imm32 -5792 0/imm32/no-disp32 -5793 0/imm32/output-is-write-only -5794 _Primitive-inc-reg/imm32/next -5795 _Primitive-inc-reg: -5796 # var/reg <- increment => ff 0/subop/increment %__ -5797 "increment"/imm32/name -5798 0/imm32/no-inouts -5799 Single-int-var-in-some-register/imm32/outputs -5800 "ff 0/subop/increment"/imm32/subx-name -5801 3/imm32/rm32-is-first-output -5802 0/imm32/no-r32 -5803 0/imm32/no-imm32 -5804 0/imm32/no-disp32 -5805 0/imm32/output-is-write-only -5806 _Primitive-dec-mem/imm32/next -5807 _Primitive-dec-mem: -5808 # decrement var => ff 1/subop/decrement *(ebp+__) -5809 "decrement"/imm32/name -5810 Single-int-var-in-mem/imm32/inouts -5811 0/imm32/no-outputs -5812 "ff 1/subop/decrement"/imm32/subx-name -5813 1/imm32/rm32-is-first-inout -5814 0/imm32/no-r32 -5815 0/imm32/no-imm32 -5816 0/imm32/no-disp32 -5817 0/imm32/output-is-write-only -5818 _Primitive-dec-reg/imm32/next -5819 _Primitive-dec-reg: -5820 # var/reg <- decrement => ff 1/subop/decrement %__ -5821 "decrement"/imm32/name -5822 0/imm32/no-inouts -5823 Single-int-var-in-some-register/imm32/outputs -5824 "ff 1/subop/decrement"/imm32/subx-name -5825 3/imm32/rm32-is-first-output -5826 0/imm32/no-r32 -5827 0/imm32/no-imm32 -5828 0/imm32/no-disp32 -5829 0/imm32/output-is-write-only -5830 _Primitive-add-to-eax/imm32/next -5831 # - add -5832 _Primitive-add-to-eax: -5833 # var/eax <- add lit => 05/add-to-eax lit/imm32 -5834 "add"/imm32/name -5835 Single-lit-var/imm32/inouts -5836 Single-int-var-in-eax/imm32/outputs -5837 "05/add-to-eax"/imm32/subx-name -5838 0/imm32/no-rm32 -5839 0/imm32/no-r32 -5840 1/imm32/imm32-is-first-inout -5841 0/imm32/no-disp32 -5842 0/imm32/output-is-write-only -5843 _Primitive-add-reg-to-reg/imm32/next -5844 _Primitive-add-reg-to-reg: -5845 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 -5846 "add"/imm32/name -5847 Single-int-var-in-some-register/imm32/inouts -5848 Single-int-var-in-some-register/imm32/outputs -5849 "01/add-to"/imm32/subx-name -5850 3/imm32/rm32-is-first-output -5851 1/imm32/r32-is-first-inout -5852 0/imm32/no-imm32 -5853 0/imm32/no-disp32 -5854 0/imm32/output-is-write-only -5855 _Primitive-add-reg-to-mem/imm32/next -5856 _Primitive-add-reg-to-mem: -5857 # add-to var1 var2/reg => 01/add-to var1 var2/r32 -5858 "add-to"/imm32/name -5859 Two-args-int-stack-int-reg/imm32/inouts -5860 0/imm32/outputs -5861 "01/add-to"/imm32/subx-name -5862 1/imm32/rm32-is-first-inout -5863 2/imm32/r32-is-second-inout -5864 0/imm32/no-imm32 -5865 0/imm32/no-disp32 -5866 0/imm32/output-is-write-only -5867 _Primitive-add-mem-to-reg/imm32/next -5868 _Primitive-add-mem-to-reg: -5869 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 -5870 "add"/imm32/name -5871 Single-int-var-in-mem/imm32/inouts -5872 Single-int-var-in-some-register/imm32/outputs -5873 "03/add"/imm32/subx-name -5874 1/imm32/rm32-is-first-inout -5875 3/imm32/r32-is-first-output -5876 0/imm32/no-imm32 -5877 0/imm32/no-disp32 -5878 0/imm32/output-is-write-only -5879 _Primitive-add-lit-to-reg/imm32/next -5880 _Primitive-add-lit-to-reg: -5881 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 -5882 "add"/imm32/name -5883 Single-lit-var/imm32/inouts -5884 Single-int-var-in-some-register/imm32/outputs -5885 "81 0/subop/add"/imm32/subx-name -5886 3/imm32/rm32-is-first-output -5887 0/imm32/no-r32 -5888 1/imm32/imm32-is-first-inout -5889 0/imm32/no-disp32 -5890 0/imm32/output-is-write-only -5891 _Primitive-add-lit-to-mem/imm32/next -5892 _Primitive-add-lit-to-mem: -5893 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 -5894 "add-to"/imm32/name -5895 Int-var-and-literal/imm32/inouts -5896 0/imm32/outputs -5897 "81 0/subop/add"/imm32/subx-name -5898 1/imm32/rm32-is-first-inout -5899 0/imm32/no-r32 -5900 2/imm32/imm32-is-second-inout -5901 0/imm32/no-disp32 -5902 0/imm32/output-is-write-only -5903 _Primitive-subtract-from-eax/imm32/next -5904 # - subtract -5905 _Primitive-subtract-from-eax: -5906 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 -5907 "subtract"/imm32/name -5908 Single-lit-var/imm32/inouts -5909 Single-int-var-in-eax/imm32/outputs -5910 "2d/subtract-from-eax"/imm32/subx-name -5911 0/imm32/no-rm32 -5912 0/imm32/no-r32 -5913 1/imm32/imm32-is-first-inout -5914 0/imm32/no-disp32 -5915 0/imm32/output-is-write-only -5916 _Primitive-subtract-reg-from-reg/imm32/next -5917 _Primitive-subtract-reg-from-reg: -5918 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 -5919 "subtract"/imm32/name -5920 Single-int-var-in-some-register/imm32/inouts -5921 Single-int-var-in-some-register/imm32/outputs -5922 "29/subtract-from"/imm32/subx-name -5923 3/imm32/rm32-is-first-output -5924 1/imm32/r32-is-first-inout -5925 0/imm32/no-imm32 -5926 0/imm32/no-disp32 -5927 0/imm32/output-is-write-only -5928 _Primitive-subtract-reg-from-mem/imm32/next -5929 _Primitive-subtract-reg-from-mem: -5930 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 -5931 "subtract-from"/imm32/name -5932 Two-args-int-stack-int-reg/imm32/inouts -5933 0/imm32/outputs -5934 "29/subtract-from"/imm32/subx-name -5935 1/imm32/rm32-is-first-inout -5936 2/imm32/r32-is-second-inout -5937 0/imm32/no-imm32 -5938 0/imm32/no-disp32 -5939 0/imm32/output-is-write-only -5940 _Primitive-subtract-mem-from-reg/imm32/next -5941 _Primitive-subtract-mem-from-reg: -5942 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 -5943 "subtract"/imm32/name -5944 Single-int-var-in-mem/imm32/inouts -5945 Single-int-var-in-some-register/imm32/outputs -5946 "2b/subtract"/imm32/subx-name -5947 1/imm32/rm32-is-first-inout -5948 3/imm32/r32-is-first-output -5949 0/imm32/no-imm32 -5950 0/imm32/no-disp32 -5951 0/imm32/output-is-write-only -5952 _Primitive-subtract-lit-from-reg/imm32/next -5953 _Primitive-subtract-lit-from-reg: -5954 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 -5955 "subtract"/imm32/name -5956 Single-lit-var/imm32/inouts -5957 Single-int-var-in-some-register/imm32/outputs -5958 "81 5/subop/subtract"/imm32/subx-name -5959 3/imm32/rm32-is-first-output -5960 0/imm32/no-r32 -5961 1/imm32/imm32-is-first-inout -5962 0/imm32/no-disp32 -5963 0/imm32/output-is-write-only -5964 _Primitive-subtract-lit-from-mem/imm32/next -5965 _Primitive-subtract-lit-from-mem: -5966 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 -5967 "subtract-from"/imm32/name -5968 Int-var-and-literal/imm32/inouts -5969 0/imm32/outputs -5970 "81 5/subop/subtract"/imm32/subx-name -5971 1/imm32/rm32-is-first-inout -5972 0/imm32/no-r32 -5973 2/imm32/imm32-is-first-inout -5974 0/imm32/no-disp32 -5975 0/imm32/output-is-write-only -5976 _Primitive-and-with-eax/imm32/next -5977 # - and -5978 _Primitive-and-with-eax: -5979 # var/eax <- and lit => 25/and-with-eax lit/imm32 -5980 "and"/imm32/name -5981 Single-lit-var/imm32/inouts -5982 Single-int-var-in-eax/imm32/outputs -5983 "25/and-with-eax"/imm32/subx-name -5984 0/imm32/no-rm32 -5985 0/imm32/no-r32 -5986 1/imm32/imm32-is-first-inout -5987 0/imm32/no-disp32 -5988 0/imm32/output-is-write-only -5989 _Primitive-and-reg-with-reg/imm32/next -5990 _Primitive-and-reg-with-reg: -5991 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 -5992 "and"/imm32/name -5993 Single-int-var-in-some-register/imm32/inouts -5994 Single-int-var-in-some-register/imm32/outputs -5995 "21/and-with"/imm32/subx-name -5996 3/imm32/rm32-is-first-output -5997 1/imm32/r32-is-first-inout -5998 0/imm32/no-imm32 -5999 0/imm32/no-disp32 -6000 0/imm32/output-is-write-only -6001 _Primitive-and-reg-with-mem/imm32/next -6002 _Primitive-and-reg-with-mem: -6003 # and-with var1 var2/reg => 21/and-with var1 var2/r32 -6004 "and-with"/imm32/name -6005 Two-args-int-stack-int-reg/imm32/inouts -6006 0/imm32/outputs -6007 "21/and-with"/imm32/subx-name -6008 1/imm32/rm32-is-first-inout -6009 2/imm32/r32-is-second-inout -6010 0/imm32/no-imm32 -6011 0/imm32/no-disp32 -6012 0/imm32/output-is-write-only -6013 _Primitive-and-mem-with-reg/imm32/next -6014 _Primitive-and-mem-with-reg: -6015 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 -6016 "and"/imm32/name -6017 Single-int-var-in-mem/imm32/inouts -6018 Single-int-var-in-some-register/imm32/outputs -6019 "23/and"/imm32/subx-name -6020 1/imm32/rm32-is-first-inout -6021 3/imm32/r32-is-first-output -6022 0/imm32/no-imm32 -6023 0/imm32/no-disp32 -6024 0/imm32/output-is-write-only -6025 _Primitive-and-lit-with-reg/imm32/next -6026 _Primitive-and-lit-with-reg: -6027 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 -6028 "and"/imm32/name -6029 Single-lit-var/imm32/inouts -6030 Single-int-var-in-some-register/imm32/outputs -6031 "81 4/subop/and"/imm32/subx-name -6032 3/imm32/rm32-is-first-output -6033 0/imm32/no-r32 -6034 1/imm32/imm32-is-first-inout -6035 0/imm32/no-disp32 -6036 0/imm32/output-is-write-only -6037 _Primitive-and-lit-with-mem/imm32/next -6038 _Primitive-and-lit-with-mem: -6039 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 -6040 "and-with"/imm32/name -6041 Int-var-and-literal/imm32/inouts -6042 0/imm32/outputs -6043 "81 4/subop/and"/imm32/subx-name -6044 1/imm32/rm32-is-first-inout -6045 0/imm32/no-r32 -6046 2/imm32/imm32-is-first-inout -6047 0/imm32/no-disp32 -6048 0/imm32/output-is-write-only -6049 _Primitive-or-with-eax/imm32/next -6050 # - or -6051 _Primitive-or-with-eax: -6052 # var/eax <- or lit => 0d/or-with-eax lit/imm32 -6053 "or"/imm32/name -6054 Single-lit-var/imm32/inouts -6055 Single-int-var-in-eax/imm32/outputs -6056 "0d/or-with-eax"/imm32/subx-name -6057 0/imm32/no-rm32 -6058 0/imm32/no-r32 -6059 1/imm32/imm32-is-first-inout -6060 0/imm32/no-disp32 -6061 0/imm32/output-is-write-only -6062 _Primitive-or-reg-with-reg/imm32/next -6063 _Primitive-or-reg-with-reg: -6064 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 -6065 "or"/imm32/name -6066 Single-int-var-in-some-register/imm32/inouts -6067 Single-int-var-in-some-register/imm32/outputs -6068 "09/or-with"/imm32/subx-name -6069 3/imm32/rm32-is-first-output -6070 1/imm32/r32-is-first-inout -6071 0/imm32/no-imm32 -6072 0/imm32/no-disp32 -6073 0/imm32/output-is-write-only -6074 _Primitive-or-reg-with-mem/imm32/next -6075 _Primitive-or-reg-with-mem: -6076 # or-with var1 var2/reg => 09/or-with var1 var2/r32 -6077 "or-with"/imm32/name -6078 Two-args-int-stack-int-reg/imm32/inouts -6079 0/imm32/outputs -6080 "09/or-with"/imm32/subx-name -6081 1/imm32/rm32-is-first-inout -6082 2/imm32/r32-is-second-inout -6083 0/imm32/no-imm32 -6084 0/imm32/no-disp32 -6085 0/imm32/output-is-write-only -6086 _Primitive-or-mem-with-reg/imm32/next -6087 _Primitive-or-mem-with-reg: -6088 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 -6089 "or"/imm32/name -6090 Single-int-var-in-mem/imm32/inouts -6091 Single-int-var-in-some-register/imm32/outputs -6092 "0b/or"/imm32/subx-name -6093 1/imm32/rm32-is-first-inout -6094 3/imm32/r32-is-first-output -6095 0/imm32/no-imm32 -6096 0/imm32/no-disp32 -6097 0/imm32/output-is-write-only -6098 _Primitive-or-lit-with-reg/imm32/next -6099 _Primitive-or-lit-with-reg: -6100 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 -6101 "or"/imm32/name -6102 Single-lit-var/imm32/inouts -6103 Single-int-var-in-some-register/imm32/outputs -6104 "81 1/subop/or"/imm32/subx-name -6105 3/imm32/rm32-is-first-output -6106 0/imm32/no-r32 -6107 1/imm32/imm32-is-first-inout -6108 0/imm32/no-disp32 -6109 0/imm32/output-is-write-only -6110 _Primitive-or-lit-with-mem/imm32/next -6111 _Primitive-or-lit-with-mem: -6112 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 -6113 "or-with"/imm32/name -6114 Int-var-and-literal/imm32/inouts -6115 0/imm32/outputs -6116 "81 1/subop/or"/imm32/subx-name -6117 1/imm32/rm32-is-first-inout -6118 0/imm32/no-r32 -6119 2/imm32/imm32-is-second-inout -6120 0/imm32/no-disp32 -6121 0/imm32/output-is-write-only -6122 _Primitive-xor-with-eax/imm32/next -6123 # - xor -6124 _Primitive-xor-with-eax: -6125 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 -6126 "xor"/imm32/name -6127 Single-lit-var/imm32/inouts -6128 Single-int-var-in-eax/imm32/outputs -6129 "35/xor-with-eax"/imm32/subx-name -6130 0/imm32/no-rm32 -6131 0/imm32/no-r32 -6132 1/imm32/imm32-is-first-inout -6133 0/imm32/no-disp32 -6134 0/imm32/output-is-write-only -6135 _Primitive-xor-reg-with-reg/imm32/next -6136 _Primitive-xor-reg-with-reg: -6137 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 -6138 "xor"/imm32/name -6139 Single-int-var-in-some-register/imm32/inouts -6140 Single-int-var-in-some-register/imm32/outputs -6141 "31/xor-with"/imm32/subx-name -6142 3/imm32/rm32-is-first-output -6143 1/imm32/r32-is-first-inout -6144 0/imm32/no-imm32 -6145 0/imm32/no-disp32 -6146 0/imm32/output-is-write-only -6147 _Primitive-xor-reg-with-mem/imm32/next -6148 _Primitive-xor-reg-with-mem: -6149 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 -6150 "xor-with"/imm32/name -6151 Two-args-int-stack-int-reg/imm32/inouts -6152 0/imm32/outputs -6153 "31/xor-with"/imm32/subx-name -6154 1/imm32/rm32-is-first-inout -6155 2/imm32/r32-is-second-inout -6156 0/imm32/no-imm32 -6157 0/imm32/no-disp32 -6158 0/imm32/output-is-write-only -6159 _Primitive-xor-mem-with-reg/imm32/next -6160 _Primitive-xor-mem-with-reg: -6161 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 -6162 "xor"/imm32/name -6163 Single-int-var-in-mem/imm32/inouts -6164 Single-int-var-in-some-register/imm32/outputs -6165 "33/xor"/imm32/subx-name -6166 1/imm32/rm32-is-first-inout -6167 3/imm32/r32-is-first-output -6168 0/imm32/no-imm32 -6169 0/imm32/no-disp32 -6170 0/imm32/output-is-write-only -6171 _Primitive-xor-lit-with-reg/imm32/next -6172 _Primitive-xor-lit-with-reg: -6173 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 -6174 "xor"/imm32/name -6175 Single-lit-var/imm32/inouts -6176 Single-int-var-in-some-register/imm32/outputs -6177 "81 6/subop/xor"/imm32/subx-name -6178 3/imm32/rm32-is-first-output -6179 0/imm32/no-r32 -6180 1/imm32/imm32-is-first-inout -6181 0/imm32/no-disp32 -6182 0/imm32/output-is-write-only -6183 _Primitive-xor-lit-with-mem/imm32/next -6184 _Primitive-xor-lit-with-mem: -6185 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 -6186 "xor-with"/imm32/name -6187 Int-var-and-literal/imm32/inouts -6188 0/imm32/outputs -6189 "81 6/subop/xor"/imm32/subx-name -6190 1/imm32/rm32-is-first-inout -6191 0/imm32/no-r32 -6192 2/imm32/imm32-is-first-inout -6193 0/imm32/no-disp32 -6194 0/imm32/output-is-write-only -6195 _Primitive-copy-to-eax/imm32/next -6196 # - copy -6197 _Primitive-copy-to-eax: -6198 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 -6199 "copy"/imm32/name -6200 Single-lit-var/imm32/inouts -6201 Single-int-var-in-eax/imm32/outputs -6202 "b8/copy-to-eax"/imm32/subx-name -6203 0/imm32/no-rm32 -6204 0/imm32/no-r32 -6205 1/imm32/imm32-is-first-inout -6206 0/imm32/no-disp32 -6207 1/imm32/output-is-write-only -6208 _Primitive-copy-to-ecx/imm32/next -6209 _Primitive-copy-to-ecx: -6210 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 -6211 "copy"/imm32/name -6212 Single-lit-var/imm32/inouts -6213 Single-int-var-in-ecx/imm32/outputs -6214 "b9/copy-to-ecx"/imm32/subx-name -6215 0/imm32/no-rm32 -6216 0/imm32/no-r32 -6217 1/imm32/imm32-is-first-inout -6218 0/imm32/no-disp32 -6219 1/imm32/output-is-write-only -6220 _Primitive-copy-to-edx/imm32/next -6221 _Primitive-copy-to-edx: -6222 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 -6223 "copy"/imm32/name -6224 Single-lit-var/imm32/inouts -6225 Single-int-var-in-edx/imm32/outputs -6226 "ba/copy-to-edx"/imm32/subx-name -6227 0/imm32/no-rm32 -6228 0/imm32/no-r32 -6229 1/imm32/imm32-is-first-inout -6230 0/imm32/no-disp32 -6231 1/imm32/output-is-write-only -6232 _Primitive-copy-to-ebx/imm32/next -6233 _Primitive-copy-to-ebx: -6234 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 -6235 "copy"/imm32/name -6236 Single-lit-var/imm32/inouts -6237 Single-int-var-in-ebx/imm32/outputs -6238 "bb/copy-to-ebx"/imm32/subx-name -6239 0/imm32/no-rm32 -6240 0/imm32/no-r32 -6241 1/imm32/imm32-is-first-inout -6242 0/imm32/no-disp32 -6243 1/imm32/output-is-write-only -6244 _Primitive-copy-to-esi/imm32/next -6245 _Primitive-copy-to-esi: -6246 # var/esi <- copy lit => be/copy-to-esi lit/imm32 -6247 "copy"/imm32/name -6248 Single-lit-var/imm32/inouts -6249 Single-int-var-in-esi/imm32/outputs -6250 "be/copy-to-esi"/imm32/subx-name -6251 0/imm32/no-rm32 -6252 0/imm32/no-r32 -6253 1/imm32/imm32-is-first-inout -6254 0/imm32/no-disp32 -6255 1/imm32/output-is-write-only -6256 _Primitive-copy-to-edi/imm32/next -6257 _Primitive-copy-to-edi: -6258 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 -6259 "copy"/imm32/name -6260 Single-lit-var/imm32/inouts -6261 Single-int-var-in-edi/imm32/outputs -6262 "bf/copy-to-edi"/imm32/subx-name -6263 0/imm32/no-rm32 -6264 0/imm32/no-r32 -6265 1/imm32/imm32-is-first-inout -6266 0/imm32/no-disp32 -6267 1/imm32/output-is-write-only -6268 _Primitive-copy-reg-to-reg/imm32/next -6269 _Primitive-copy-reg-to-reg: -6270 # var1/reg <- copy var2/reg => 89/copy-to var1/rm32 var2/r32 -6271 "copy"/imm32/name -6272 Single-int-var-in-some-register/imm32/inouts -6273 Single-int-var-in-some-register/imm32/outputs -6274 "89/copy-to"/imm32/subx-name -6275 3/imm32/rm32-is-first-output -6276 1/imm32/r32-is-first-inout -6277 0/imm32/no-imm32 -6278 0/imm32/no-disp32 -6279 1/imm32/output-is-write-only -6280 _Primitive-copy-reg-to-mem/imm32/next -6281 _Primitive-copy-reg-to-mem: -6282 # copy-to var1 var2/reg => 89/copy-to var1 var2/r32 -6283 "copy-to"/imm32/name -6284 Two-args-int-stack-int-reg/imm32/inouts -6285 0/imm32/outputs -6286 "89/copy-to"/imm32/subx-name -6287 1/imm32/rm32-is-first-inout -6288 2/imm32/r32-is-second-inout -6289 0/imm32/no-imm32 -6290 0/imm32/no-disp32 -6291 1/imm32/output-is-write-only -6292 _Primitive-copy-mem-to-reg/imm32/next -6293 _Primitive-copy-mem-to-reg: -6294 # var1/reg <- copy var2 => 8b/copy-from var2/rm32 var1/r32 -6295 "copy"/imm32/name -6296 Single-int-var-in-mem/imm32/inouts -6297 Single-int-var-in-some-register/imm32/outputs -6298 "8b/copy-from"/imm32/subx-name -6299 1/imm32/rm32-is-first-inout -6300 3/imm32/r32-is-first-output -6301 0/imm32/no-imm32 -6302 0/imm32/no-disp32 -6303 1/imm32/output-is-write-only -6304 _Primitive-copy-lit-to-reg/imm32/next -6305 _Primitive-copy-lit-to-reg: -6306 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 -6307 "copy"/imm32/name -6308 Single-lit-var/imm32/inouts -6309 Single-int-var-in-some-register/imm32/outputs -6310 "c7 0/subop/copy"/imm32/subx-name -6311 3/imm32/rm32-is-first-output -6312 0/imm32/no-r32 -6313 1/imm32/imm32-is-first-inout -6314 0/imm32/no-disp32 -6315 1/imm32/output-is-write-only -6316 _Primitive-copy-lit-to-mem/imm32/next -6317 _Primitive-copy-lit-to-mem: -6318 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 -6319 "copy-to"/imm32/name -6320 Int-var-and-literal/imm32/inouts -6321 0/imm32/outputs -6322 "c7 0/subop/copy"/imm32/subx-name -6323 1/imm32/rm32-is-first-inout -6324 0/imm32/no-r32 -6325 2/imm32/imm32-is-first-inout -6326 0/imm32/no-disp32 -6327 1/imm32/output-is-write-only -6328 _Primitive-compare-mem-with-reg/imm32/next -6329 # - compare -6330 _Primitive-compare-mem-with-reg: -6331 # compare var1 var2/reg => 39/compare-> var1/rm32 var2/r32 -6332 "compare"/imm32/name -6333 Two-args-int-stack-int-reg/imm32/inouts -6334 0/imm32/outputs -6335 "39/compare->"/imm32/subx-name -6336 1/imm32/rm32-is-first-inout -6337 2/imm32/r32-is-second-inout -6338 0/imm32/no-imm32 -6339 0/imm32/no-disp32 -6340 0/imm32/output-is-write-only -6341 _Primitive-compare-reg-with-mem/imm32/next -6342 _Primitive-compare-reg-with-mem: -6343 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 -6344 "compare"/imm32/name -6345 Two-args-int-reg-int-stack/imm32/inouts -6346 0/imm32/outputs -6347 "3b/compare<-"/imm32/subx-name -6348 2/imm32/rm32-is-second-inout -6349 1/imm32/r32-is-first-inout -6350 0/imm32/no-imm32 -6351 0/imm32/no-disp32 -6352 0/imm32/output-is-write-only -6353 _Primitive-compare-eax-with-literal/imm32/next -6354 _Primitive-compare-eax-with-literal: -6355 # compare var1/eax n => 3d/compare-eax-with n/imm32 -6356 "compare"/imm32/name -6357 Two-args-int-eax-int-literal/imm32/inouts -6358 0/imm32/outputs -6359 "3d/compare-eax-with"/imm32/subx-name -6360 0/imm32/no-rm32 -6361 0/imm32/no-r32 -6362 2/imm32/imm32-is-second-inout -6363 0/imm32/no-disp32 -6364 0/imm32/output-is-write-only -6365 _Primitive-compare-reg-with-literal/imm32/next -6366 _Primitive-compare-reg-with-literal: -6367 # compare var1/reg n => 81 7/subop/compare %reg n/imm32 -6368 "compare"/imm32/name -6369 Int-var-in-register-and-literal/imm32/inouts -6370 0/imm32/outputs -6371 "81 7/subop/compare"/imm32/subx-name -6372 1/imm32/rm32-is-first-inout -6373 0/imm32/no-r32 -6374 2/imm32/imm32-is-second-inout -6375 0/imm32/no-disp32 -6376 0/imm32/output-is-write-only -6377 _Primitive-compare-mem-with-literal/imm32/next -6378 _Primitive-compare-mem-with-literal: -6379 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 -6380 "compare"/imm32/name -6381 Int-var-and-literal/imm32/inouts -6382 0/imm32/outputs -6383 "81 7/subop/compare"/imm32/subx-name -6384 1/imm32/rm32-is-first-inout -6385 0/imm32/no-r32 -6386 2/imm32/imm32-is-second-inout -6387 0/imm32/no-disp32 -6388 0/imm32/output-is-write-only -6389 _Primitive-multiply-reg-by-mem/imm32/next -6390 # - multiply -6391 _Primitive-multiply-reg-by-mem: -6392 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 -6393 "multiply"/imm32/name -6394 Single-int-var-in-mem/imm32/inouts -6395 Single-int-var-in-some-register/imm32/outputs -6396 "0f af/multiply"/imm32/subx-name -6397 1/imm32/rm32-is-first-inout -6398 3/imm32/r32-is-first-output -6399 0/imm32/no-imm32 -6400 0/imm32/no-disp32 -6401 0/imm32/output-is-write-only -6402 _Primitive-break-if-addr</imm32/next -6403 # - branches -6404 _Primitive-break-if-addr<: -6405 "break-if-addr<"/imm32/name -6406 0/imm32/inouts -6407 0/imm32/outputs -6408 "0f 82/jump-if-addr< 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-addr>=/imm32/next -6415 _Primitive-break-if-addr>=: -6416 "break-if-addr>="/imm32/name -6417 0/imm32/inouts -6418 0/imm32/outputs -6419 "0f 83/jump-if-addr>= 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 84/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-if-!=/imm32/next -6437 _Primitive-break-if-!=: -6438 "break-if-!="/imm32/name -6439 0/imm32/inouts -6440 0/imm32/outputs -6441 "0f 85/jump-if-!= 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-break-if-addr<=/imm32/next -6448 _Primitive-break-if-addr<=: -6449 "break-if-addr<="/imm32/name -6450 0/imm32/inouts -6451 0/imm32/outputs -6452 "0f 86/jump-if-addr<= break/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-break-if-addr>/imm32/next -6459 _Primitive-break-if-addr>: -6460 "break-if-addr>"/imm32/name -6461 0/imm32/inouts -6462 0/imm32/outputs -6463 "0f 87/jump-if-addr> break/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-break-if-</imm32/next -6470 _Primitive-break-if-<: -6471 "break-if-<"/imm32/name -6472 0/imm32/inouts -6473 0/imm32/outputs -6474 "0f 8c/jump-if-< break/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-break-if->=/imm32/next -6481 _Primitive-break-if->=: -6482 "break-if->="/imm32/name -6483 0/imm32/inouts -6484 0/imm32/outputs -6485 "0f 8d/jump-if->= break/disp32"/imm32/subx-name -6486 0/imm32/no-rm32 -6487 0/imm32/no-r32 +1870 test-convert-length-of-array: +1871 # . prologue +1872 55/push-ebp +1873 89/<- %ebp 4/r32/esp +1874 # setup +1875 (clear-stream _test-input-stream) +1876 (clear-stream $_test-input-buffered-file->buffer) +1877 (clear-stream _test-output-stream) +1878 (clear-stream $_test-output-buffered-file->buffer) +1879 c7 0/subop/copy *Next-block-index 1/imm32 +1880 # +1881 (write _test-input-stream "fn foo a: (addr array int) {\n") +1882 (write _test-input-stream " var b/eax: (addr array int) <- copy a\n") +1883 (write _test-input-stream " var c/eax: int <- length b\n") +1884 (write _test-input-stream "}\n") +1885 # convert +1886 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1887 (flush _test-output-buffered-file) +1888 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1894 # check output +1895 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array/0") +1896 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array/1") +1897 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array/2") +1898 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array/3") +1899 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array/4") +1900 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array/5") +1901 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/6") +1902 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-length-of-array/7") +1903 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/8") +1904 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *eax 0x00000000/r32" "F - test-convert-length-of-array/9") +1905 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/10") +1906 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/11") +1907 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array/12") +1908 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array/13") +1909 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array/14") +1910 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array/15") +1911 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array/16") +1912 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array/17") +1913 # . epilogue +1914 89/<- %esp 5/r32/ebp +1915 5d/pop-to-ebp +1916 c3/return +1917 +1918 test-convert-index-into-array: +1919 # . prologue +1920 55/push-ebp +1921 89/<- %ebp 4/r32/esp +1922 # setup +1923 (clear-stream _test-input-stream) +1924 (clear-stream $_test-input-buffered-file->buffer) +1925 (clear-stream _test-output-stream) +1926 (clear-stream $_test-output-buffered-file->buffer) +1927 c7 0/subop/copy *Next-block-index 1/imm32 +1928 # +1929 (write _test-input-stream "fn foo {\n") +1930 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") +1931 (write _test-input-stream " var idx/ecx: int <- copy 3\n") +1932 (write _test-input-stream " var x/eax: (addr int) <- index arr, idx\n") +1933 (write _test-input-stream "}\n") +1934 # convert +1935 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1936 (flush _test-output-buffered-file) +1937 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1943 # check output +1944 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array/0") +1945 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array/1") +1946 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array/2") +1947 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array/3") +1948 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array/4") +1949 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array/5") +1950 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/6") +1951 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-length-of-array/7") +1952 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-length-of-array/8") +1953 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-length-of-array/9") +1954 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/10") +1955 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx<<2 + 4) 0x00000000/r32" "F - test-convert-length-of-array/11") +1956 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/12") +1957 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-length-of-array/13") +1958 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/14") +1959 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array/15") +1960 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array/16") +1961 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array/17") +1962 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array/18") +1963 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array/19") +1964 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array/20") +1965 # . epilogue +1966 89/<- %esp 5/r32/ebp +1967 5d/pop-to-ebp +1968 c3/return +1969 +1970 test-convert-type-definition: +1971 # . prologue +1972 55/push-ebp +1973 89/<- %ebp 4/r32/esp +1974 # setup +1975 (clear-stream _test-input-stream) +1976 (clear-stream $_test-input-buffered-file->buffer) +1977 (clear-stream _test-output-stream) +1978 (clear-stream $_test-output-buffered-file->buffer) +1979 c7 0/subop/copy *Next-block-index 1/imm32 +1980 # +1981 (write _test-input-stream "fn foo a: (addr t) {\n") +1982 (write _test-input-stream " var _a/eax: (addr t) <- copy a\n") +1983 (write _test-input-stream " var b/ecx: (addr int) <- get _a, x\n") +1984 (write _test-input-stream " var c/ecx: (addr int) <- get _a, y\n") +1985 (write _test-input-stream "}\n") +1986 (write _test-input-stream "type t {\n") +1987 (write _test-input-stream " x: int\n") +1988 (write _test-input-stream " y: int\n") +1989 (write _test-input-stream "}\n") +1990 # convert +1991 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1992 (flush _test-output-buffered-file) +1993 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1999 # check output +2000 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-user-defined-type/0") +2001 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-user-defined-type/1") +2002 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-user-defined-type/2") +2003 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-user-defined-type/3") +2004 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-user-defined-type/4") +2005 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-user-defined-type/5") +2006 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-with-user-defined-type/6") +2007 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-with-user-defined-type/7") +2008 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-user-defined-type/8") +2009 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000000) 0x00000001/r32" "F - test-convert-function-with-user-defined-type/9") +2010 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-user-defined-type/10") +2011 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000004) 0x00000001/r32" "F - test-convert-function-with-user-defined-type/11") +2012 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-user-defined-type/12") +2013 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-user-defined-type/13") +2014 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-with-user-defined-type/14") +2015 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-user-defined-type/15") +2016 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-user-defined-type/16") +2017 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-user-defined-type/17") +2018 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-user-defined-type/18") +2019 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-user-defined-type/19") +2020 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-user-defined-type/20") +2021 # . epilogue +2022 89/<- %esp 5/r32/ebp +2023 5d/pop-to-ebp +2024 c3/return +2025 +2026 ####################################################### +2027 # Parsing +2028 ####################################################### +2029 +2030 parse-mu: # in: (addr buffered-file) +2031 # pseudocode +2032 # var curr-function: (addr (handle function)) = Program->functions +2033 # var curr-type: (addr (handle typeinfo)) = Program->types +2034 # var line: (stream byte 512) +2035 # var word-slice: slice +2036 # while true # line loop +2037 # clear-stream(line) +2038 # read-line-buffered(in, line) +2039 # if (line->write == 0) break # end of file +2040 # word-slice = next-mu-token(line) +2041 # if slice-empty?(word-slice) # end of line +2042 # continue +2043 # else if slice-starts-with?(word-slice, "#") # comment +2044 # continue # end of line +2045 # else if slice-equal?(word-slice, "fn") +2046 # var new-function: (handle function) = allocate(function) +2047 # var vars: (stack (addr var) 256) +2048 # populate-mu-function-header(in, new-function, vars) +2049 # populate-mu-function-body(in, new-function, vars) +2050 # assert(vars->top == 0) +2051 # *curr-function = new-function +2052 # curr-function = &new-function->next +2053 # else if slice-equal?(word-slice, "type") +2054 # word-slice = next-mu-token(line) +2055 # type-id = pos-or-insert-slice(Type-id, word-slice) +2056 # var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id) +2057 # assert(next-word(line) == "{") +2058 # populate-mu-type(in, new-type) +2059 # else +2060 # abort() +2061 # +2062 # . prologue +2063 55/push-ebp +2064 89/<- %ebp 4/r32/esp +2065 # . save registers +2066 50/push-eax +2067 51/push-ecx +2068 52/push-edx +2069 53/push-ebx +2070 56/push-esi +2071 57/push-edi +2072 # var line/ecx: (stream byte 512) +2073 81 5/subop/subtract %esp 0x200/imm32 +2074 68/push 0x200/imm32/length +2075 68/push 0/imm32/read +2076 68/push 0/imm32/write +2077 89/<- %ecx 4/r32/esp +2078 # var word-slice/edx: slice +2079 68/push 0/imm32/end +2080 68/push 0/imm32/start +2081 89/<- %edx 4/r32/esp +2082 # var curr-function/edi: (addr (handle function)) +2083 bf/copy-to-edi _Program-functions/imm32 +2084 # var curr-type/esi: (addr (handle typeinfo)) +2085 be/copy-to-esi _Program-types/imm32 +2086 # var vars/ebx: (stack (addr var) 256) +2087 81 5/subop/subtract %esp 0x400/imm32 +2088 68/push 0x400/imm32/length +2089 68/push 0/imm32/top +2090 89/<- %ebx 4/r32/esp +2091 { +2092 $parse-mu:line-loop: +2093 (clear-stream %ecx) +2094 (read-line-buffered *(ebp+8) %ecx) +2095 # if (line->write == 0) break +2096 81 7/subop/compare *ecx 0/imm32 +2097 0f 84/jump-if-= break/disp32 +2098 +-- 6 lines: #? # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------ +2104 (next-mu-token %ecx %edx) +2105 # if slice-empty?(word-slice) continue +2106 (slice-empty? %edx) +2107 3d/compare-eax-and 0/imm32/false +2108 0f 85/jump-if-!= loop/disp32 +2109 # if (*word-slice->start == "#") continue +2110 # . eax = *word-slice->start +2111 8b/-> *edx 0/r32/eax +2112 8a/copy-byte *eax 0/r32/AL +2113 81 4/subop/and %eax 0xff/imm32 +2114 # . if (eax == '#') continue +2115 3d/compare-eax-and 0x23/imm32/hash +2116 0f 84/jump-if-= loop/disp32 +2117 # if (slice-equal?(word-slice, "fn")) parse a function +2118 { +2119 $parse-mu:fn: +2120 (slice-equal? %edx "fn") +2121 3d/compare-eax-and 0/imm32/false +2122 0f 84/jump-if-= break/disp32 +2123 # var new-function/eax: (handle function) = populate-mu-function(line, in, vars) +2124 (allocate Heap *Function-size) # => eax +2125 (zero-out %eax *Function-size) +2126 (clear-stack %ebx) +2127 (populate-mu-function-header %ecx %eax %ebx) +2128 (populate-mu-function-body *(ebp+8) %eax %ebx) +2129 # *curr-function = new-function +2130 89/<- *edi 0/r32/eax +2131 # curr-function = &new-function->next +2132 8d/address-> *(eax+0x14) 7/r32/edi # Function-next +2133 e9/jump $parse-mu:line-loop/disp32 +2134 } +2135 # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition +2136 { +2137 $parse-mu:type: +2138 (slice-equal? %edx "type") +2139 3d/compare-eax-and 0/imm32 +2140 0f 84/jump-if-= break/disp32 +2141 (next-mu-token %ecx %edx) +2142 # var type-id/eax: int +2143 (pos-or-insert-slice Type-id %edx) # => eax +2144 # var new-type/eax: (handle typeinfo) +2145 (find-or-create-typeinfo %eax) # => eax +2146 # TODO: ensure that 'line' has nothing else but '{' +2147 (populate-mu-type *(ebp+8) %eax) # => eax +2148 e9/jump $parse-mu:line-loop/disp32 +2149 } +2150 # otherwise abort +2151 e9/jump $parse-mu:error1/disp32 +2152 } # end line loop +2153 $parse-mu:end: +2154 # . reclaim locals +2155 81 0/subop/add %esp 0x630/imm32 +2156 # . restore registers +2157 5f/pop-to-edi +2158 5e/pop-to-esi +2159 5b/pop-to-ebx +2160 5a/pop-to-edx +2161 59/pop-to-ecx +2162 58/pop-to-eax +2163 # . epilogue +2164 89/<- %esp 5/r32/ebp +2165 5d/pop-to-ebp +2166 c3/return +2167 +2168 $parse-mu:error1: +2169 # error("unexpected top-level command: " word-slice "\n") +2170 (write-buffered Stderr "unexpected top-level command: ") +2171 (write-slice-buffered Stderr %edx) +2172 (write-buffered Stderr "\n") +2173 (flush Stderr) +2174 # . syscall(exit, 1) +2175 bb/copy-to-ebx 1/imm32 +2176 b8/copy-to-eax 1/imm32/exit +2177 cd/syscall 0x80/imm8 +2178 # never gets here +2179 +2180 $parse-mu:error2: +2181 # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n") +2182 (print-int32-buffered Stderr *ebx) +2183 (write-buffered Stderr " vars not reclaimed after fn '") +2184 (write-slice-buffered Stderr *eax) # Function-name +2185 (write-buffered Stderr "'\n") +2186 (flush Stderr) +2187 # . syscall(exit, 1) +2188 bb/copy-to-ebx 1/imm32 +2189 b8/copy-to-eax 1/imm32/exit +2190 cd/syscall 0x80/imm8 +2191 # never gets here +2192 +2193 # scenarios considered: +2194 # ✗ fn foo # no block +2195 # ✓ fn foo { +2196 # ✗ fn foo { { +2197 # ✗ fn foo { } +2198 # ✗ fn foo { } { +2199 # ✗ fn foo x { +2200 # ✗ fn foo x: { +2201 # ✓ fn foo x: int { +2202 # ✓ fn foo x: int { +2203 # ✓ fn foo x: int -> y/eax: int { +2204 populate-mu-function-header: # first-line: (addr stream byte), out: (handle function), vars: (addr stack (handle var)) +2205 # pseudocode: +2206 # var name: slice +2207 # next-mu-token(first-line, name) +2208 # assert(name not in '{' '}' '->') +2209 # out->name = slice-to-string(name) +2210 # var next-offset: int = 8 +2211 # ## inouts +2212 # while true +2213 # ## name +2214 # name = next-mu-token(first-line) +2215 # if (name == '{') goto done +2216 # if (name == '->') break +2217 # assert(name != '}') +2218 # var v: (handle var) = parse-var-with-type(name, first-line) +2219 # assert(v->register == null) +2220 # v->stack-offset = next-offset +2221 # next-offset += size-of(v) +2222 # # v->block-depth is implicitly 0 +2223 # out->inouts = append(out->inouts, v) +2224 # push(vars, v) +2225 # ## outputs +2226 # while true +2227 # ## name +2228 # name = next-mu-token(first-line) +2229 # assert(name not in '{' '}' '->') +2230 # var v: (handle var) = parse-var-with-type(name, first-line) +2231 # assert(v->register != null) +2232 # out->outputs = append(out->outputs, v) +2233 # done: +2234 # +2235 # . prologue +2236 55/push-ebp +2237 89/<- %ebp 4/r32/esp +2238 # . save registers +2239 50/push-eax +2240 51/push-ecx +2241 52/push-edx +2242 53/push-ebx +2243 57/push-edi +2244 # edi = out +2245 8b/-> *(ebp+0xc) 7/r32/edi +2246 # var word-slice/ecx: slice +2247 68/push 0/imm32/end +2248 68/push 0/imm32/start +2249 89/<- %ecx 4/r32/esp +2250 # var next-offset/edx = 8 +2251 ba/copy-to-edx 8/imm32 +2252 # read function name +2253 (next-mu-token *(ebp+8) %ecx) +2254 # error checking +2255 # TODO: error if name starts with 'break' or 'loop' +2256 # if (word-slice == '{') abort +2257 (slice-equal? %ecx "{") # => eax +2258 3d/compare-eax-and 0/imm32/false +2259 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +2260 # if (word-slice == '->') abort +2261 (slice-equal? %ecx "->") # => eax +2262 3d/compare-eax-and 0/imm32/false +2263 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +2264 # if (word-slice == '}') abort +2265 (slice-equal? %ecx "}") # => eax +2266 3d/compare-eax-and 0/imm32/false +2267 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +2268 # save function name +2269 (slice-to-string Heap %ecx) # => eax +2270 89/<- *edi 0/r32/eax # Function-name +2271 # initialize default subx-name as well +2272 89/<- *(edi+4) 0/r32/eax # Function-subx-name +2273 # save function inouts +2274 { +2275 $populate-mu-function-header:check-for-inout: +2276 (next-mu-token *(ebp+8) %ecx) +2277 # if (word-slice == '{') goto done +2278 (slice-equal? %ecx "{") # => eax +2279 3d/compare-eax-and 0/imm32/false +2280 0f 85/jump-if-!= $populate-mu-function-header:done/disp32 +2281 # if (word-slice == '->') break +2282 (slice-equal? %ecx "->") # => eax +2283 3d/compare-eax-and 0/imm32/false +2284 0f 85/jump-if-!= break/disp32 +2285 # if (word-slice == '}') abort +2286 (slice-equal? %ecx "}") # => eax +2287 3d/compare-eax-and 0/imm32/false +2288 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +2289 # var v/ebx: (handle var) = parse-var-with-type(word-slice, first-line) +2290 (parse-var-with-type %ecx *(ebp+8)) # => eax +2291 89/<- %ebx 0/r32/eax +2292 # assert(v->register == null) +2293 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register +2294 0f 85/jump-if-!= $populate-mu-function-header:error2/disp32 +2295 # v->stack-offset = next-offset +2296 89/<- *(ebx+0xc) 2/r32/edx # Var-offset +2297 # next-offset += size-of(v) +2298 (size-of %ebx) # => eax +2299 01/add %edx 0/r32/eax +2300 # v->block-depth is implicitly 0 +2301 # +2302 # out->inouts = append(out->inouts, v) +2303 (append-list Heap %ebx *(edi+8)) # Function-inouts => eax +2304 89/<- *(edi+8) 0/r32/eax # Function-inouts +2305 # push(vars, v) +2306 (push *(ebp+0x10) %ebx) +2307 # +2308 e9/jump loop/disp32 +2309 } +2310 # save function outputs +2311 { +2312 $populate-mu-function-header:check-for-out: +2313 (next-mu-token *(ebp+8) %ecx) +2314 # if (word-slice == '{') break +2315 (slice-equal? %ecx "{") # => eax +2316 3d/compare-eax-and 0/imm32/false +2317 0f 85/jump-if-!= break/disp32 +2318 # if (word-slice == '->') abort +2319 (slice-equal? %ecx "->") # => eax +2320 3d/compare-eax-and 0/imm32/false +2321 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +2322 # if (word-slice == '}') abort +2323 (slice-equal? %ecx "}") # => eax +2324 3d/compare-eax-and 0/imm32/false +2325 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +2326 # +2327 (parse-var-with-type %ecx *(ebp+8)) # => eax +2328 89/<- %ebx 0/r32/eax +2329 # assert(var->register != null) +2330 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register +2331 0f 84/jump-if-= $populate-mu-function-header:error3/disp32 +2332 (append-list Heap %ebx *(edi+0xc)) # Function-outputs => eax +2333 89/<- *(edi+0xc) 0/r32/eax # Function-outputs +2334 e9/jump loop/disp32 +2335 } +2336 $populate-mu-function-header:done: +2337 (check-no-tokens-left *(ebp+8)) +2338 $populate-mu-function-header:end: +2339 # . reclaim locals +2340 81 0/subop/add %esp 8/imm32 +2341 # . restore registers +2342 5f/pop-to-edi +2343 5b/pop-to-ebx +2344 5a/pop-to-edx +2345 59/pop-to-ecx +2346 58/pop-to-eax +2347 # . epilogue +2348 89/<- %esp 5/r32/ebp +2349 5d/pop-to-ebp +2350 c3/return +2351 +2352 $populate-mu-function-header:error1: +2353 # error("function header not in form 'fn <name> {'") +2354 (write-buffered Stderr "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '") +2355 (flush Stderr) +2356 (rewind-stream *(ebp+8)) +2357 (write-stream 2 *(ebp+8)) +2358 (write-buffered Stderr "'\n") +2359 (flush Stderr) +2360 # . syscall(exit, 1) +2361 bb/copy-to-ebx 1/imm32 +2362 b8/copy-to-eax 1/imm32/exit +2363 cd/syscall 0x80/imm8 +2364 # never gets here +2365 +2366 $populate-mu-function-header:error2: +2367 # error("function input '" var "' cannot be in a register") +2368 (write-buffered Stderr "function input '") +2369 (write-buffered Stderr *ebx) # Var-name +2370 (write-buffered Stderr "' cannot be in a register") +2371 (flush Stderr) +2372 # . syscall(exit, 1) +2373 bb/copy-to-ebx 1/imm32 +2374 b8/copy-to-eax 1/imm32/exit +2375 cd/syscall 0x80/imm8 +2376 # never gets here +2377 +2378 $populate-mu-function-header:error3: +2379 # error("function input '" var "' must be in a register") +2380 (write-buffered Stderr "function input '") +2381 (write-buffered Stderr *eax) # Var-name +2382 (write-buffered Stderr " must be in a register'") +2383 (flush Stderr) +2384 (rewind-stream *(ebp+8)) +2385 (write-stream 2 *(ebp+8)) +2386 (write-buffered Stderr "'\n") +2387 (flush Stderr) +2388 # . syscall(exit, 1) +2389 bb/copy-to-ebx 1/imm32 +2390 b8/copy-to-eax 1/imm32/exit +2391 cd/syscall 0x80/imm8 +2392 # never gets here +2393 +2394 test-function-header-with-arg: +2395 # . prologue +2396 55/push-ebp +2397 89/<- %ebp 4/r32/esp +2398 # setup +2399 (clear-stream _test-input-stream) +2400 (write _test-input-stream "foo n: int {\n") +2401 # var result/ecx: function +2402 2b/subtract-> *Function-size 4/r32/esp +2403 89/<- %ecx 4/r32/esp +2404 (zero-out %ecx *Function-size) +2405 # var vars/ebx: (stack (addr var) 16) +2406 81 5/subop/subtract %esp 0x10/imm32 +2407 68/push 0x10/imm32/length +2408 68/push 0/imm32/top +2409 89/<- %ebx 4/r32/esp +2410 # convert +2411 (populate-mu-function-header _test-input-stream %ecx %ebx) +2412 # check result +2413 (check-strings-equal *ecx "foo" "F - test-function-header-with-arg/name") # Function-name +2414 # edx: (handle list var) = result->inouts +2415 8b/-> *(ecx+8) 2/r32/edx # Function-inouts +2416 # ebx: (handle var) = result->inouts->value +2417 8b/-> *edx 3/r32/ebx # List-value +2418 (check-strings-equal *ebx "n" "F - test-function-header-with-arg/inout:0") # Var-name +2419 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2420 (check-ints-equal *ebx 1 "F - test-function-header-with-arg/inout:0/type:0") # Tree-left +2421 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-arg/inout:0/type:1") # Tree-right +2422 # . epilogue +2423 89/<- %esp 5/r32/ebp +2424 5d/pop-to-ebp +2425 c3/return +2426 +2427 test-function-header-with-multiple-args: +2428 # . prologue +2429 55/push-ebp +2430 89/<- %ebp 4/r32/esp +2431 # setup +2432 (clear-stream _test-input-stream) +2433 (write _test-input-stream "foo a: int, b: int c: int {\n") +2434 # result/ecx: (handle function) +2435 2b/subtract-> *Function-size 4/r32/esp +2436 89/<- %ecx 4/r32/esp +2437 (zero-out %ecx *Function-size) +2438 # var vars/ebx: (stack (addr var) 16) +2439 81 5/subop/subtract %esp 0x10/imm32 +2440 68/push 0x10/imm32/length +2441 68/push 0/imm32/top +2442 89/<- %ebx 4/r32/esp +2443 # convert +2444 (populate-mu-function-header _test-input-stream %ecx %ebx) +2445 # check result +2446 (check-strings-equal *ecx "foo") # Function-name +2447 # edx: (handle list var) = result->inouts +2448 8b/-> *(ecx+8) 2/r32/edx # Function-inouts +2449 $test-function-header-with-multiple-args:inout0: +2450 # ebx: (handle var) = result->inouts->value +2451 8b/-> *edx 3/r32/ebx # List-value +2452 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name +2453 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2454 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:0/type:0") # Tree-left +2455 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:0/type:1") # Tree-right +2456 # edx = result->inouts->next +2457 8b/-> *(edx+4) 2/r32/edx # List-next +2458 $test-function-header-with-multiple-args:inout1: +2459 # ebx = result->inouts->next->value +2460 8b/-> *edx 3/r32/ebx # List-value +2461 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args/inout:1") # Var-name +2462 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2463 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:1/type:0") # Tree-left +2464 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:1/type:1") # Tree-right +2465 # edx = result->inouts->next->next +2466 8b/-> *(edx+4) 2/r32/edx # List-next +2467 $test-function-header-with-multiple-args:inout2: +2468 # ebx = result->inouts->next->next->value +2469 8b/-> *edx 3/r32/ebx # List-value +2470 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args/inout:2") # Var-name +2471 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2472 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:2/type:0") # Tree-left +2473 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:2/type:1") # Tree-right +2474 # . epilogue +2475 89/<- %esp 5/r32/ebp +2476 5d/pop-to-ebp +2477 c3/return +2478 +2479 test-function-with-multiple-args-and-outputs: +2480 # . prologue +2481 55/push-ebp +2482 89/<- %ebp 4/r32/esp +2483 # setup +2484 (clear-stream _test-input-stream) +2485 (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx: int {\n") +2486 # result/ecx: (handle function) +2487 2b/subtract-> *Function-size 4/r32/esp +2488 89/<- %ecx 4/r32/esp +2489 (zero-out %ecx *Function-size) +2490 # var vars/ebx: (stack (addr var) 16) +2491 81 5/subop/subtract %esp 0x10/imm32 +2492 68/push 0x10/imm32/length +2493 68/push 0/imm32/top +2494 89/<- %ebx 4/r32/esp +2495 # convert +2496 (populate-mu-function-header _test-input-stream %ecx %ebx) +2497 # check result +2498 (check-strings-equal *ecx "foo") # Function-name +2499 # edx: (handle list var) = result->inouts +2500 8b/-> *(ecx+8) 2/r32/edx # Function-inouts +2501 # ebx: (handle var) = result->inouts->value +2502 8b/-> *edx 3/r32/ebx # List-value +2503 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0") # Var-name +2504 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2505 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0") # Tree-left +2506 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1") # Tree-right +2507 # edx = result->inouts->next +2508 8b/-> *(edx+4) 2/r32/edx # List-next +2509 # ebx = result->inouts->next->value +2510 8b/-> *edx 3/r32/ebx # List-value +2511 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1") # Var-name +2512 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2513 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0") # Tree-left +2514 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1") # Tree-right +2515 # edx = result->inouts->next->next +2516 8b/-> *(edx+4) 2/r32/edx # List-next +2517 # ebx = result->inouts->next->next->value +2518 8b/-> *edx 3/r32/ebx # List-value +2519 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2") # Var-name +2520 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2521 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0") # Tree-left +2522 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1") # Tree-right +2523 # edx: (handle list var) = result->outputs +2524 8b/-> *(ecx+0xc) 2/r32/edx # Function-outputs +2525 # ebx: (handle var) = result->outputs->value +2526 8b/-> *edx 3/r32/ebx # List-value +2527 (check-strings-equal *ebx "x" "F - test-function-header-with-multiple-args-and-outputs/output:0") # Var-name +2528 (check-strings-equal *(ebx+0x10) "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register +2529 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2530 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-left +2531 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-right +2532 # edx = result->outputs->next +2533 8b/-> *(edx+4) 2/r32/edx # List-next +2534 # ebx = result->outputs->next->value +2535 8b/-> *edx 3/r32/ebx # List-value +2536 (check-strings-equal *ebx "y" "F - test-function-header-with-multiple-args-and-outputs/output:1") # Var-name +2537 (check-strings-equal *(ebx+0x10) "edx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register +2538 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2539 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-left +2540 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-right +2541 # . epilogue +2542 89/<- %esp 5/r32/ebp +2543 5d/pop-to-ebp +2544 c3/return +2545 +2546 # format for variables with types +2547 # x: int +2548 # x: int, +2549 # x/eax: int +2550 # x/eax: int, +2551 # ignores at most one trailing comma +2552 # WARNING: modifies name +2553 parse-var-with-type: # name: (addr slice), first-line: (addr stream byte) -> result/eax: (handle var) +2554 # pseudocode: +2555 # var v: (handle var) = allocate(Heap, Var-size) +2556 # var s: slice +2557 # if (!slice-ends-with(name, ":")) +2558 # abort +2559 # --name->end to skip ':' +2560 # next-token-from-slice(name->start, name->end, '/', s) +2561 # v->name = slice-to-string(s) +2562 # ## register +2563 # next-token-from-slice(s->end, name->end, '/', s) +2564 # if (!slice-empty?(s)) +2565 # v->register = slice-to-string(s) +2566 # ## type +2567 # var type: (handle tree type-id) = parse-type(first-line) +2568 # v->type = type +2569 # return v +2570 # +2571 # . prologue +2572 55/push-ebp +2573 89/<- %ebp 4/r32/esp +2574 # . save registers +2575 51/push-ecx +2576 52/push-edx +2577 53/push-ebx +2578 56/push-esi +2579 57/push-edi +2580 # esi = name +2581 8b/-> *(ebp+8) 6/r32/esi +2582 # if (!slice-ends-with?(name, ":")) abort +2583 8b/-> *(esi+4) 1/r32/ecx # Slice-end +2584 49/decrement-ecx +2585 8a/copy-byte *ecx 1/r32/CL +2586 81 4/subop/and %ecx 0xff/imm32 +2587 81 7/subop/compare %ecx 0x3a/imm32/colon +2588 0f 85/jump-if-!= $parse-var-with-type:abort/disp32 +2589 # --name->end to skip ':' +2590 ff 1/subop/decrement *(esi+4) +2591 # var result/edi: (handle var) = allocate(Heap, Var-size) +2592 (allocate Heap *Var-size) # => eax +2593 (zero-out %eax *Var-size) +2594 89/<- %edi 0/r32/eax +2595 # var s/ecx: slice +2596 68/push 0/imm32/end +2597 68/push 0/imm32/start +2598 89/<- %ecx 4/r32/esp +2599 $parse-var-with-type:save-name: +2600 # save v->name +2601 (next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/' +2602 # . end/edx = s->end +2603 8b/-> *(ecx+4) 2/r32/edx +2604 $parse-var-with-type:write-name: +2605 (slice-to-string Heap %ecx) # => eax +2606 89/<- *edi 0/r32/eax # Var-name +2607 # save v->register +2608 $parse-var-with-type:save-register: +2609 (next-token-from-slice %edx *(esi+4) 0x2f %ecx) # end, name->end, '/' +2610 # if (!slice-empty?(s)) v->register = slice-to-string(s) +2611 { +2612 $parse-var-with-type:write-register: +2613 (slice-empty? %ecx) # => eax +2614 3d/compare-eax-and 0/imm32/false +2615 75/jump-if-!= break/disp8 +2616 (slice-to-string Heap %ecx) +2617 89/<- *(edi+0x10) 0/r32/eax # Var-register +2618 } +2619 $parse-var-with-type:save-type: +2620 (parse-type Heap *(ebp+0xc)) # => eax +2621 89/<- *(edi+4) 0/r32/eax # Var-type +2622 $parse-var-with-type:end: +2623 # return result +2624 89/<- %eax 7/r32/edi +2625 # . reclaim locals +2626 81 0/subop/add %esp 8/imm32 +2627 # . restore registers +2628 5f/pop-to-edi +2629 5e/pop-to-esi +2630 5b/pop-to-ebx +2631 5a/pop-to-edx +2632 59/pop-to-ecx +2633 # . epilogue +2634 89/<- %esp 5/r32/ebp +2635 5d/pop-to-ebp +2636 c3/return +2637 +2638 $parse-var-with-type:abort: +2639 # error("var should have form 'name: type' in '" line "'\n") +2640 (write-buffered Stderr "var should have form 'name: type' in '") +2641 (flush Stderr) +2642 (rewind-stream *(ebp+0xc)) +2643 (write-stream 2 *(ebp+0xc)) +2644 (write-buffered Stderr "'\n") +2645 (flush Stderr) +2646 # . syscall(exit, 1) +2647 bb/copy-to-ebx 1/imm32 +2648 b8/copy-to-eax 1/imm32/exit +2649 cd/syscall 0x80/imm8 +2650 # never gets here +2651 +2652 parse-type: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) +2653 # pseudocode: +2654 # var s: slice = next-mu-token(in) +2655 # assert s != "" +2656 # assert s != "->" +2657 # assert s != "{" +2658 # assert s != "}" +2659 # if s == ")" +2660 # return 0 +2661 # result = allocate(Tree) +2662 # zero-out(result, *Tree-size) +2663 # if s != "(" +2664 # result->left = pos-or-insert-slice(Type-id, s) +2665 # return +2666 # result->left = parse-type(ad, in) +2667 # result->right = parse-type-tree(ad, in) +2668 # +2669 # . prologue +2670 55/push-ebp +2671 89/<- %ebp 4/r32/esp +2672 # . save registers +2673 51/push-ecx +2674 52/push-edx +2675 # var s/ecx: slice +2676 68/push 0/imm32 +2677 68/push 0/imm32 +2678 89/<- %ecx 4/r32/esp +2679 # s = next-mu-token(in) +2680 (next-mu-token *(ebp+0xc) %ecx) +2681 #? (write-buffered Stderr "tok: ") +2682 #? (write-slice-buffered Stderr %ecx) +2683 #? (write-buffered Stderr "$\n") +2684 #? (flush Stderr) +2685 # assert s != "" +2686 (slice-equal? %ecx "") +2687 3d/compare-eax-and 0/imm32/false +2688 0f 85/jump-if-!= $parse-type:abort/disp32 +2689 # assert s != "{" +2690 (slice-equal? %ecx "{") +2691 3d/compare-eax-and 0/imm32/false +2692 0f 85/jump-if-!= $parse-type:abort/disp32 +2693 # assert s != "}" +2694 (slice-equal? %ecx "}") +2695 3d/compare-eax-and 0/imm32/false +2696 0f 85/jump-if-!= $parse-type:abort/disp32 +2697 # assert s != "->" +2698 (slice-equal? %ecx "->") +2699 3d/compare-eax-and 0/imm32/false +2700 0f 85/jump-if-!= $parse-type:abort/disp32 +2701 # if (s == ")") return 0 +2702 (slice-equal? %ecx ")") +2703 3d/compare-eax-and 0/imm32/false +2704 b8/copy-to-eax 0/imm32 +2705 0f 85/jump-if-!= $parse-type:end/disp32 +2706 # var result/edx: (handle tree type-id) +2707 (allocate *(ebp+8) *Tree-size) # => eax +2708 (zero-out %eax *Tree-size) +2709 89/<- %edx 0/r32/eax +2710 { +2711 # if (s != "(") break +2712 (slice-equal? %ecx "(") +2713 3d/compare-eax-and 0/imm32/false +2714 75/jump-if-!= break/disp8 +2715 # result->left = pos-or-insert-slice(Type-id, s) +2716 (pos-or-insert-slice Type-id %ecx) # => eax +2717 #? (write-buffered Stderr "=> {") +2718 #? (print-int32-buffered Stderr %eax) +2719 #? (write-buffered Stderr ", 0}\n") +2720 #? (flush Stderr) +2721 89/<- *edx 0/r32/eax # Tree-left +2722 e9/jump $parse-type:return-edx/disp32 +2723 } +2724 # otherwise s == "(" +2725 # result->left = parse-type(ad, in) +2726 (parse-type *(ebp+8) *(ebp+0xc)) +2727 #? (write-buffered Stderr "=> {") +2728 #? (print-int32-buffered Stderr %eax) +2729 89/<- *edx 0/r32/eax # Tree-left +2730 # result->right = parse-type-tree(ad, in) +2731 (parse-type-tree *(ebp+8) *(ebp+0xc)) +2732 #? (write-buffered Stderr Space) +2733 #? (print-int32-buffered Stderr %eax) +2734 #? (write-buffered Stderr "}\n") +2735 #? (flush Stderr) +2736 89/<- *(edx+4) 0/r32/eax # Tree-right +2737 $parse-type:return-edx: +2738 89/<- %eax 2/r32/edx +2739 $parse-type:end: +2740 # . reclaim locals +2741 81 0/subop/add %esp 8/imm32 +2742 # . restore registers +2743 5a/pop-to-edx +2744 59/pop-to-ecx +2745 # . epilogue +2746 89/<- %esp 5/r32/ebp +2747 5d/pop-to-ebp +2748 c3/return +2749 +2750 $parse-type:abort: +2751 # error("unexpected token when parsing type: '" s "'\n") +2752 (write-buffered Stderr "unexpected token when parsing type: '") +2753 (write-slice-buffered Stderr %ecx) +2754 (write-buffered Stderr "'\n") +2755 (flush Stderr) +2756 # . syscall(exit, 1) +2757 bb/copy-to-ebx 1/imm32 +2758 b8/copy-to-eax 1/imm32/exit +2759 cd/syscall 0x80/imm8 +2760 # never gets here +2761 +2762 parse-type-tree: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) +2763 # pseudocode: +2764 # var tmp: (handle tree type-id) = parse-type(ad, in) +2765 # if tmp == 0 +2766 # return 0 +2767 # result = allocate(Tree) +2768 # zero-out(result, *Tree-size) +2769 # result->left = tmp +2770 # result->right = parse-type-tree(ad, in) +2771 # +2772 # . prologue +2773 55/push-ebp +2774 89/<- %ebp 4/r32/esp +2775 # . save registers +2776 51/push-ecx +2777 52/push-edx +2778 # var tmp/eax: (handle tree type-id) = parse-type(ad, in) +2779 (parse-type *(ebp+8) *(ebp+0xc)) +2780 # if (tmp == 0) return tmp +2781 3d/compare-eax-and 0/imm32 +2782 74/jump-if-= $parse-type-tree:end/disp8 +2783 # var tmp2/ecx = tmp +2784 89/<- %ecx 0/r32/eax +2785 # var result/edx: (handle tree type-id) +2786 (allocate *(ebp+8) *Tree-size) # => eax +2787 (zero-out %eax *Tree-size) +2788 89/<- %edx 0/r32/eax +2789 # result->left = tmp2 +2790 89/<- *edx 1/r32/ecx # Tree-left +2791 # result->right = parse-type-tree(ad, in) +2792 (parse-type-tree *(ebp+8) *(ebp+0xc)) +2793 89/<- *(edx+4) 0/r32/eax # Tree-right +2794 $parse-type-tree:return-edx: +2795 89/<- %eax 2/r32/edx +2796 $parse-type-tree:end: +2797 # . restore registers +2798 5a/pop-to-edx +2799 59/pop-to-ecx +2800 # . epilogue +2801 89/<- %esp 5/r32/ebp +2802 5d/pop-to-ebp +2803 c3/return +2804 +2805 next-mu-token: # in: (addr stream byte), out: (addr slice) +2806 # pseudocode: +2807 # start: +2808 # skip-chars-matching-whitespace(in) +2809 # if in->read >= in->write # end of in +2810 # out = {0, 0} +2811 # return +2812 # out->start = &in->data[in->read] +2813 # var curr-byte/eax: byte = in->data[in->read] +2814 # if curr->byte == ',' # comment token +2815 # ++in->read +2816 # goto start +2817 # if curr-byte == '#' # comment +2818 # goto done # treat as eof +2819 # if curr-byte == '"' # string literal +2820 # skip-string(in) +2821 # goto done # no metadata +2822 # if curr-byte == '(' +2823 # ++in->read +2824 # goto done +2825 # if curr-byte == ')' +2826 # ++in->read +2827 # goto done +2828 # # read a word +2829 # while true +2830 # if in->read >= in->write +2831 # break +2832 # curr-byte = in->data[in->read] +2833 # if curr-byte == ' ' +2834 # break +2835 # if curr-byte == '\r' +2836 # break +2837 # if curr-byte == '\n' +2838 # break +2839 # if curr-byte == '(' +2840 # break +2841 # if curr-byte == ')' +2842 # break +2843 # if curr-byte == ',' +2844 # break +2845 # ++in->read +2846 # done: +2847 # out->end = &in->data[in->read] +2848 # +2849 # . prologue +2850 55/push-ebp +2851 89/<- %ebp 4/r32/esp +2852 # . save registers +2853 50/push-eax +2854 51/push-ecx +2855 56/push-esi +2856 57/push-edi +2857 # esi = in +2858 8b/-> *(ebp+8) 6/r32/esi +2859 # edi = out +2860 8b/-> *(ebp+0xc) 7/r32/edi +2861 $next-mu-token:start: +2862 (skip-chars-matching-whitespace %esi) +2863 $next-mu-token:check0: +2864 # if (in->read >= in->write) return out = {0, 0} +2865 # . ecx = in->read +2866 8b/-> *(esi+4) 1/r32/ecx +2867 # . if (ecx >= in->write) return out = {0, 0} +2868 3b/compare 1/r32/ecx *esi +2869 c7 0/subop/copy *edi 0/imm32 +2870 c7 0/subop/copy *(edi+4) 0/imm32 +2871 0f 8d/jump-if->= $next-mu-token:end/disp32 +2872 # out->start = &in->data[in->read] +2873 8d/copy-address *(esi+ecx+0xc) 0/r32/eax +2874 89/<- *edi 0/r32/eax +2875 # var curr-byte/eax: byte = in->data[in->read] +2876 31/xor %eax 0/r32/eax +2877 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL +2878 { +2879 $next-mu-token:check-for-comma: +2880 # if (curr-byte != ',') break +2881 3d/compare-eax-and 0x2c/imm32/comma +2882 75/jump-if-!= break/disp8 +2883 # ++in->read +2884 ff 0/subop/increment *(esi+4) +2885 # restart +2886 e9/jump $next-mu-token:start/disp32 +2887 } +2888 { +2889 $next-mu-token:check-for-comment: +2890 # if (curr-byte != '#') break +2891 3d/compare-eax-and 0x23/imm32/pound +2892 75/jump-if-!= break/disp8 +2893 # return eof +2894 e9/jump $next-mu-token:done/disp32 +2895 } +2896 { +2897 $next-mu-token:check-for-string-literal: +2898 # if (curr-byte != '"') break +2899 3d/compare-eax-and 0x22/imm32/dquote +2900 75/jump-if-!= break/disp8 +2901 (skip-string %esi) +2902 # return +2903 e9/jump $next-mu-token:done/disp32 +2904 } +2905 { +2906 $next-mu-token:check-for-open-paren: +2907 # if (curr-byte != '(') break +2908 3d/compare-eax-and 0x28/imm32/open-paren +2909 75/jump-if-!= break/disp8 +2910 # ++in->read +2911 ff 0/subop/increment *(esi+4) +2912 # return +2913 e9/jump $next-mu-token:done/disp32 +2914 } +2915 { +2916 $next-mu-token:check-for-close-paren: +2917 # if (curr-byte != ')') break +2918 3d/compare-eax-and 0x29/imm32/close-paren +2919 75/jump-if-!= break/disp8 +2920 # ++in->read +2921 ff 0/subop/increment *(esi+4) +2922 # return +2923 e9/jump $next-mu-token:done/disp32 +2924 } +2925 { +2926 $next-mu-token:regular-word-without-metadata: +2927 # if (in->read >= in->write) break +2928 # . ecx = in->read +2929 8b/-> *(esi+4) 1/r32/ecx +2930 # . if (ecx >= in->write) break +2931 3b/compare *esi 1/r32/ecx +2932 7d/jump-if->= break/disp8 +2933 # var c/eax: byte = in->data[in->read] +2934 31/xor %eax 0/r32/eax +2935 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL +2936 # if (c == ' ') break +2937 3d/compare-eax-and 0x20/imm32/space +2938 74/jump-if-= break/disp8 +2939 # if (c == '\r') break +2940 3d/compare-eax-and 0xd/imm32/carriage-return +2941 74/jump-if-= break/disp8 +2942 # if (c == '\n') break +2943 3d/compare-eax-and 0xa/imm32/newline +2944 74/jump-if-= break/disp8 +2945 # if (c == '(') break +2946 3d/compare-eax-and 0x28/imm32/open-paren +2947 0f 84/jump-if-= break/disp32 +2948 # if (c == ')') break +2949 3d/compare-eax-and 0x29/imm32/close-paren +2950 0f 84/jump-if-= break/disp32 +2951 # if (c == ',') break +2952 3d/compare-eax-and 0x2c/imm32/comma +2953 0f 84/jump-if-= break/disp32 +2954 # ++in->read +2955 ff 0/subop/increment *(esi+4) +2956 # +2957 e9/jump loop/disp32 +2958 } +2959 $next-mu-token:done: +2960 # out->end = &in->data[in->read] +2961 8b/-> *(esi+4) 1/r32/ecx +2962 8d/copy-address *(esi+ecx+0xc) 0/r32/eax +2963 89/<- *(edi+4) 0/r32/eax +2964 $next-mu-token:end: +2965 # . restore registers +2966 5f/pop-to-edi +2967 5e/pop-to-esi +2968 59/pop-to-ecx +2969 58/pop-to-eax +2970 # . epilogue +2971 89/<- %esp 5/r32/ebp +2972 5d/pop-to-ebp +2973 c3/return +2974 +2975 pos-or-insert-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int +2976 # . prologue +2977 55/push-ebp +2978 89/<- %ebp 4/r32/esp +2979 # if (pos-slice(arr, s) != -1) return it +2980 (pos-slice *(ebp+8) *(ebp+0xc)) # => eax +2981 3d/compare-eax-and -1/imm32 +2982 75/jump-if-not-equal $pos-or-insert-slice:end/disp8 +2983 # +2984 (slice-to-string Heap *(ebp+0xc)) # => eax +2985 (write-int *(ebp+8) %eax) +2986 (pos-slice *(ebp+8) *(ebp+0xc)) # => eax +2987 $pos-or-insert-slice:end: +2988 # . epilogue +2989 89/<- %esp 5/r32/ebp +2990 5d/pop-to-ebp +2991 c3/return +2992 +2993 # return the index in an array of strings matching 's', -1 if not found +2994 # index is denominated in elements, not bytes +2995 pos-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int +2996 # . prologue +2997 55/push-ebp +2998 89/<- %ebp 4/r32/esp +2999 # . save registers +3000 51/push-ecx +3001 52/push-edx +3002 53/push-ebx +3003 56/push-esi +3004 #? (write-buffered Stderr "pos-slice: ") +3005 #? (write-slice-buffered Stderr *(ebp+0xc)) +3006 #? (write-buffered Stderr "\n") +3007 #? (flush Stderr) +3008 # esi = arr +3009 8b/-> *(ebp+8) 6/r32/esi +3010 # var index/ecx: int = 0 +3011 b9/copy-to-ecx 0/imm32 +3012 # var curr/edx: (addr (addr array byte)) = arr->data +3013 8d/copy-address *(esi+0xc) 2/r32/edx +3014 # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write] +3015 8b/-> *esi 3/r32/ebx +3016 8d/copy-address *(esi+ebx+0xc) 3/r32/ebx +3017 { +3018 #? (write-buffered Stderr " ") +3019 #? (print-int32-buffered Stderr %ecx) +3020 #? (write-buffered Stderr "\n") +3021 #? (flush Stderr) +3022 # if (curr >= max) return -1 +3023 39/compare %edx 3/r32/ebx +3024 b8/copy-to-eax -1/imm32 +3025 73/jump-if-addr>= $pos-slice:end/disp8 +3026 # if (slice-equal?(s, *curr)) break +3027 (slice-equal? *(ebp+0xc) *edx) # => eax +3028 3d/compare-eax-and 0/imm32/false +3029 75/jump-if-!= break/disp8 +3030 # ++index +3031 41/increment-ecx +3032 # curr += 4 +3033 81 0/subop/add %edx 4/imm32 +3034 # +3035 eb/jump loop/disp8 +3036 } +3037 # return index +3038 89/<- %eax 1/r32/ecx +3039 $pos-slice:end: +3040 #? (write-buffered Stderr "=> ") +3041 #? (print-int32-buffered Stderr %eax) +3042 #? (write-buffered Stderr "\n") +3043 # . restore registers +3044 5e/pop-to-esi +3045 5b/pop-to-ebx +3046 5a/pop-to-edx +3047 59/pop-to-ecx +3048 # . epilogue +3049 89/<- %esp 5/r32/ebp +3050 5d/pop-to-ebp +3051 c3/return +3052 +3053 test-parse-var-with-type: +3054 # . prologue +3055 55/push-ebp +3056 89/<- %ebp 4/r32/esp +3057 # (eax..ecx) = "x:" +3058 b8/copy-to-eax "x:"/imm32 +3059 8b/-> *eax 1/r32/ecx +3060 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3061 05/add-to-eax 4/imm32 +3062 # var slice/ecx: slice = {eax, ecx} +3063 51/push-ecx +3064 50/push-eax +3065 89/<- %ecx 4/r32/esp +3066 # _test-input-stream contains "int" +3067 (clear-stream _test-input-stream) +3068 (write _test-input-stream "int") +3069 # +3070 (parse-var-with-type %ecx _test-input-stream) +3071 8b/-> *eax 2/r32/edx # Var-name +3072 (check-strings-equal %edx "x" "F - test-var-with-type/name") +3073 8b/-> *(eax+4) 2/r32/edx # Var-type +3074 (check-ints-equal *edx 1 "F - test-var-with-type/type") +3075 (check-ints-equal *(edx+4) 0 "F - test-var-with-type/type") +3076 # . epilogue +3077 89/<- %esp 5/r32/ebp +3078 5d/pop-to-ebp +3079 c3/return +3080 +3081 test-parse-var-with-type-and-register: +3082 # . prologue +3083 55/push-ebp +3084 89/<- %ebp 4/r32/esp +3085 # (eax..ecx) = "x/eax:" +3086 b8/copy-to-eax "x/eax:"/imm32 +3087 8b/-> *eax 1/r32/ecx +3088 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3089 05/add-to-eax 4/imm32 +3090 # var slice/ecx: slice = {eax, ecx} +3091 51/push-ecx +3092 50/push-eax +3093 89/<- %ecx 4/r32/esp +3094 # _test-input-stream contains "int" +3095 (clear-stream _test-input-stream) +3096 (write _test-input-stream "int") +3097 # +3098 (parse-var-with-type %ecx _test-input-stream) +3099 8b/-> *eax 2/r32/edx # Var-name +3100 (check-strings-equal %edx "x" "F - test-var-with-type-and-register/name") +3101 8b/-> *(eax+0x10) 2/r32/edx # Var-register +3102 (check-strings-equal %edx "eax" "F - test-var-with-type-and-register/register") +3103 8b/-> *(eax+4) 2/r32/edx # Var-type +3104 (check-ints-equal *edx 1 "F - test-var-with-type-and-register/type") +3105 (check-ints-equal *(edx+4) 0 "F - test-var-with-type-and-register/type") +3106 # . epilogue +3107 89/<- %esp 5/r32/ebp +3108 5d/pop-to-ebp +3109 c3/return +3110 +3111 test-parse-var-with-trailing-characters: +3112 # . prologue +3113 55/push-ebp +3114 89/<- %ebp 4/r32/esp +3115 # (eax..ecx) = "x:" +3116 b8/copy-to-eax "x:"/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 # _test-input-stream contains "int," +3125 (clear-stream _test-input-stream) +3126 (write _test-input-stream "int,") +3127 # +3128 (parse-var-with-type %ecx _test-input-stream) +3129 8b/-> *eax 2/r32/edx # Var-name +3130 (check-strings-equal %edx "x" "F - test-var-with-trailing-characters/name") +3131 8b/-> *(eax+0x10) 2/r32/edx # Var-register +3132 (check-ints-equal %edx 0 "F - test-var-with-trailing-characters/register") +3133 8b/-> *(eax+4) 2/r32/edx # Var-type +3134 (check-ints-equal *edx 1 "F - test-var-with-trailing-characters/type") +3135 (check-ints-equal *(edx+4) 0 "F - test-var-with-trailing-characters/type") +3136 # . epilogue +3137 89/<- %esp 5/r32/ebp +3138 5d/pop-to-ebp +3139 c3/return +3140 +3141 test-parse-var-with-register-and-trailing-characters: +3142 # . prologue +3143 55/push-ebp +3144 89/<- %ebp 4/r32/esp +3145 # (eax..ecx) = "x/eax:" +3146 b8/copy-to-eax "x/eax:"/imm32 +3147 8b/-> *eax 1/r32/ecx +3148 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3149 05/add-to-eax 4/imm32 +3150 # var slice/ecx: slice = {eax, ecx} +3151 51/push-ecx +3152 50/push-eax +3153 89/<- %ecx 4/r32/esp +3154 # _test-input-stream contains "int," +3155 (clear-stream _test-input-stream) +3156 (write _test-input-stream "int,") +3157 # +3158 (parse-var-with-type %ecx _test-input-stream) +3159 8b/-> *eax 2/r32/edx # Var-name +3160 (check-strings-equal %edx "x" "F - test-var-with-register-and-trailing-characters/name") +3161 8b/-> *(eax+0x10) 2/r32/edx # Var-register +3162 (check-strings-equal %edx "eax" "F - test-var-with-register-and-trailing-characters/register") +3163 8b/-> *(eax+4) 2/r32/edx # Var-type +3164 (check-ints-equal *edx 1 "F - test-var-with-register-and-trailing-characters/type") +3165 (check-ints-equal *(edx+4) 0 "F - test-var-with-register-and-trailing-characters/type") +3166 # . epilogue +3167 89/<- %esp 5/r32/ebp +3168 5d/pop-to-ebp +3169 c3/return +3170 +3171 test-parse-var-with-compound-type: +3172 # . prologue +3173 55/push-ebp +3174 89/<- %ebp 4/r32/esp +3175 # (eax..ecx) = "x:" +3176 b8/copy-to-eax "x:"/imm32 +3177 8b/-> *eax 1/r32/ecx +3178 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3179 05/add-to-eax 4/imm32 +3180 # var slice/ecx: slice = {eax, ecx} +3181 51/push-ecx +3182 50/push-eax +3183 89/<- %ecx 4/r32/esp +3184 # _test-input-stream contains "(addr int)" +3185 (clear-stream _test-input-stream) +3186 (write _test-input-stream "(addr int)") +3187 # +3188 (parse-var-with-type %ecx _test-input-stream) +3189 8b/-> *eax 2/r32/edx # Var-name +3190 (check-strings-equal %edx "x" "F - test-var-with-compound-type/name") +3191 8b/-> *(eax+0x10) 2/r32/edx # Var-register +3192 (check-ints-equal %edx 0 "F - test-var-with-compound-type/register") +3193 # var type/edx: (handle tree type-id) = var->type +3194 8b/-> *(eax+4) 2/r32/edx # Var-type +3195 # type->left == atom(addr) +3196 8b/-> *edx 0/r32/eax # Atom-value +3197 (check-ints-equal *eax 2 "F - test-var-with-compound-type/type:0") # Tree-left +3198 # type->right->left == atom(int) +3199 8b/-> *(edx+4) 2/r32/edx # Tree-right +3200 8b/-> *edx 0/r32/eax # Tree-left +3201 (check-ints-equal *eax 1 "F - test-var-with-compound-type/type:1") # Atom-value +3202 # type->right->right == null +3203 (check-ints-equal *(edx+4) 0 "F - test-var-with-compound-type/type:2") # Tree-right +3204 # . epilogue +3205 89/<- %esp 5/r32/ebp +3206 5d/pop-to-ebp +3207 c3/return +3208 +3209 # identifier starts with a letter or '$' or '_' +3210 # no constraints at the moment on later letters +3211 # all we really want to do so far is exclude '{', '}' and '->' +3212 is-identifier?: # in: (addr slice) -> result/eax: boolean +3213 # . prologue +3214 55/push-ebp +3215 89/<- %ebp 4/r32/esp +3216 # if (slice-empty?(in)) return false +3217 (slice-empty? *(ebp+8)) # => eax +3218 3d/compare-eax-and 0/imm32/false +3219 75/jump-if-!= $is-identifier?:false/disp8 +3220 # var c/eax: byte = *in->start +3221 8b/-> *(ebp+8) 0/r32/eax +3222 8b/-> *eax 0/r32/eax +3223 8a/copy-byte *eax 0/r32/AL +3224 81 4/subop/and %eax 0xff/imm32 +3225 # if (c == '$') return true +3226 3d/compare-eax-and 0x24/imm32/$ +3227 74/jump-if-= $is-identifier?:true/disp8 +3228 # if (c == '_') return true +3229 3d/compare-eax-and 0x5f/imm32/_ +3230 74/jump-if-= $is-identifier?:true/disp8 +3231 # drop case +3232 25/and-eax-with 0x5f/imm32 +3233 # if (c < 'A') return false +3234 3d/compare-eax-and 0x41/imm32/A +3235 7c/jump-if-< $is-identifier?:false/disp8 +3236 # if (c > 'Z') return false +3237 3d/compare-eax-and 0x5a/imm32/Z +3238 7f/jump-if-> $is-identifier?:false/disp8 +3239 # otherwise return true +3240 $is-identifier?:true: +3241 b8/copy-to-eax 1/imm32/true +3242 eb/jump $is-identifier?:end/disp8 +3243 $is-identifier?:false: +3244 b8/copy-to-eax 0/imm32/false +3245 $is-identifier?:end: +3246 # . epilogue +3247 89/<- %esp 5/r32/ebp +3248 5d/pop-to-ebp +3249 c3/return +3250 +3251 test-is-identifier-dollar: +3252 # . prologue +3253 55/push-ebp +3254 89/<- %ebp 4/r32/esp +3255 # (eax..ecx) = "$a" +3256 b8/copy-to-eax "$a"/imm32 +3257 8b/-> *eax 1/r32/ecx +3258 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3259 05/add-to-eax 4/imm32 +3260 # var slice/ecx: slice = {eax, ecx} +3261 51/push-ecx +3262 50/push-eax +3263 89/<- %ecx 4/r32/esp +3264 # +3265 (is-identifier? %ecx) +3266 (check-ints-equal %eax 1 "F - test-is-identifier-dollar") +3267 # . epilogue +3268 89/<- %esp 5/r32/ebp +3269 5d/pop-to-ebp +3270 c3/return +3271 +3272 test-is-identifier-underscore: +3273 # . prologue +3274 55/push-ebp +3275 89/<- %ebp 4/r32/esp +3276 # (eax..ecx) = "_a" +3277 b8/copy-to-eax "_a"/imm32 +3278 8b/-> *eax 1/r32/ecx +3279 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3280 05/add-to-eax 4/imm32 +3281 # var slice/ecx: slice = {eax, ecx} +3282 51/push-ecx +3283 50/push-eax +3284 89/<- %ecx 4/r32/esp +3285 # +3286 (is-identifier? %ecx) +3287 (check-ints-equal %eax 1 "F - test-is-identifier-underscore") +3288 # . epilogue +3289 89/<- %esp 5/r32/ebp +3290 5d/pop-to-ebp +3291 c3/return +3292 +3293 test-is-identifier-a: +3294 # . prologue +3295 55/push-ebp +3296 89/<- %ebp 4/r32/esp +3297 # (eax..ecx) = "a$" +3298 b8/copy-to-eax "a$"/imm32 +3299 8b/-> *eax 1/r32/ecx +3300 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3301 05/add-to-eax 4/imm32 +3302 # var slice/ecx: slice = {eax, ecx} +3303 51/push-ecx +3304 50/push-eax +3305 89/<- %ecx 4/r32/esp +3306 # +3307 (is-identifier? %ecx) +3308 (check-ints-equal %eax 1 "F - test-is-identifier-a") +3309 # . epilogue +3310 89/<- %esp 5/r32/ebp +3311 5d/pop-to-ebp +3312 c3/return +3313 +3314 test-is-identifier-z: +3315 # . prologue +3316 55/push-ebp +3317 89/<- %ebp 4/r32/esp +3318 # (eax..ecx) = "z$" +3319 b8/copy-to-eax "z$"/imm32 +3320 8b/-> *eax 1/r32/ecx +3321 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3322 05/add-to-eax 4/imm32 +3323 # var slice/ecx: slice = {eax, ecx} +3324 51/push-ecx +3325 50/push-eax +3326 89/<- %ecx 4/r32/esp +3327 # +3328 (is-identifier? %ecx) +3329 (check-ints-equal %eax 1 "F - test-is-identifier-z") +3330 # . epilogue +3331 89/<- %esp 5/r32/ebp +3332 5d/pop-to-ebp +3333 c3/return +3334 +3335 test-is-identifier-A: +3336 # . prologue +3337 55/push-ebp +3338 89/<- %ebp 4/r32/esp +3339 # (eax..ecx) = "A$" +3340 b8/copy-to-eax "A$"/imm32 +3341 8b/-> *eax 1/r32/ecx +3342 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3343 05/add-to-eax 4/imm32 +3344 # var slice/ecx: slice = {eax, ecx} +3345 51/push-ecx +3346 50/push-eax +3347 89/<- %ecx 4/r32/esp +3348 # +3349 (is-identifier? %ecx) +3350 (check-ints-equal %eax 1 "F - test-is-identifier-A") +3351 # . epilogue +3352 89/<- %esp 5/r32/ebp +3353 5d/pop-to-ebp +3354 c3/return +3355 +3356 test-is-identifier-Z: +3357 # . prologue +3358 55/push-ebp +3359 89/<- %ebp 4/r32/esp +3360 # (eax..ecx) = "Z$" +3361 b8/copy-to-eax "Z$"/imm32 +3362 8b/-> *eax 1/r32/ecx +3363 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3364 05/add-to-eax 4/imm32 +3365 # var slice/ecx: slice = {eax, ecx} +3366 51/push-ecx +3367 50/push-eax +3368 89/<- %ecx 4/r32/esp +3369 # +3370 (is-identifier? %ecx) +3371 (check-ints-equal %eax 1 "F - test-is-identifier-Z") +3372 # . epilogue +3373 89/<- %esp 5/r32/ebp +3374 5d/pop-to-ebp +3375 c3/return +3376 +3377 test-is-identifier-@: +3378 # character before 'A' is invalid +3379 # . prologue +3380 55/push-ebp +3381 89/<- %ebp 4/r32/esp +3382 # (eax..ecx) = "@a" +3383 b8/copy-to-eax "@a"/imm32 +3384 8b/-> *eax 1/r32/ecx +3385 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3386 05/add-to-eax 4/imm32 +3387 # var slice/ecx: slice = {eax, ecx} +3388 51/push-ecx +3389 50/push-eax +3390 89/<- %ecx 4/r32/esp +3391 # +3392 (is-identifier? %ecx) +3393 (check-ints-equal %eax 0 "F - test-is-identifier-@") +3394 # . epilogue +3395 89/<- %esp 5/r32/ebp +3396 5d/pop-to-ebp +3397 c3/return +3398 +3399 test-is-identifier-square-bracket: +3400 # character after 'Z' is invalid +3401 # . prologue +3402 55/push-ebp +3403 89/<- %ebp 4/r32/esp +3404 # (eax..ecx) = "[a" +3405 b8/copy-to-eax "[a"/imm32 +3406 8b/-> *eax 1/r32/ecx +3407 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3408 05/add-to-eax 4/imm32 +3409 # var slice/ecx: slice = {eax, ecx} +3410 51/push-ecx +3411 50/push-eax +3412 89/<- %ecx 4/r32/esp +3413 # +3414 (is-identifier? %ecx) +3415 (check-ints-equal %eax 0 "F - test-is-identifier-@") +3416 # . epilogue +3417 89/<- %esp 5/r32/ebp +3418 5d/pop-to-ebp +3419 c3/return +3420 +3421 test-is-identifier-backtick: +3422 # character before 'a' is invalid +3423 # . prologue +3424 55/push-ebp +3425 89/<- %ebp 4/r32/esp +3426 # (eax..ecx) = "`a" +3427 b8/copy-to-eax "`a"/imm32 +3428 8b/-> *eax 1/r32/ecx +3429 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3430 05/add-to-eax 4/imm32 +3431 # var slice/ecx: slice = {eax, ecx} +3432 51/push-ecx +3433 50/push-eax +3434 89/<- %ecx 4/r32/esp +3435 # +3436 (is-identifier? %ecx) +3437 (check-ints-equal %eax 0 "F - test-is-identifier-backtick") +3438 # . epilogue +3439 89/<- %esp 5/r32/ebp +3440 5d/pop-to-ebp +3441 c3/return +3442 +3443 test-is-identifier-curly-brace-open: +3444 # character after 'z' is invalid; also used for blocks +3445 # . prologue +3446 55/push-ebp +3447 89/<- %ebp 4/r32/esp +3448 # (eax..ecx) = "{a" +3449 b8/copy-to-eax "{a"/imm32 +3450 8b/-> *eax 1/r32/ecx +3451 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3452 05/add-to-eax 4/imm32 +3453 # var slice/ecx: slice = {eax, ecx} +3454 51/push-ecx +3455 50/push-eax +3456 89/<- %ecx 4/r32/esp +3457 # +3458 (is-identifier? %ecx) +3459 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open") +3460 # . epilogue +3461 89/<- %esp 5/r32/ebp +3462 5d/pop-to-ebp +3463 c3/return +3464 +3465 test-is-identifier-curly-brace-close: +3466 # . prologue +3467 55/push-ebp +3468 89/<- %ebp 4/r32/esp +3469 # (eax..ecx) = "}a" +3470 b8/copy-to-eax "}a"/imm32 +3471 8b/-> *eax 1/r32/ecx +3472 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3473 05/add-to-eax 4/imm32 +3474 # var slice/ecx: slice = {eax, ecx} +3475 51/push-ecx +3476 50/push-eax +3477 89/<- %ecx 4/r32/esp +3478 # +3479 (is-identifier? %ecx) +3480 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close") +3481 # . epilogue +3482 89/<- %esp 5/r32/ebp +3483 5d/pop-to-ebp +3484 c3/return +3485 +3486 test-is-identifier-hyphen: +3487 # disallow leading '-' since '->' has special meaning +3488 # . prologue +3489 55/push-ebp +3490 89/<- %ebp 4/r32/esp +3491 # (eax..ecx) = "-a" +3492 b8/copy-to-eax "-a"/imm32 +3493 8b/-> *eax 1/r32/ecx +3494 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3495 05/add-to-eax 4/imm32 +3496 # var slice/ecx: slice = {eax, ecx} +3497 51/push-ecx +3498 50/push-eax +3499 89/<- %ecx 4/r32/esp +3500 # +3501 (is-identifier? %ecx) +3502 (check-ints-equal %eax 0 "F - test-is-identifier-hyphen") +3503 # . epilogue +3504 89/<- %esp 5/r32/ebp +3505 5d/pop-to-ebp +3506 c3/return +3507 +3508 populate-mu-function-body: # in: (addr buffered-file), out: (handle function), vars: (addr stack (handle var)) +3509 # . prologue +3510 55/push-ebp +3511 89/<- %ebp 4/r32/esp +3512 # . save registers +3513 50/push-eax +3514 56/push-esi +3515 57/push-edi +3516 # esi = in +3517 8b/-> *(ebp+8) 6/r32/esi +3518 # edi = out +3519 8b/-> *(ebp+0xc) 7/r32/edi +3520 # initialize some global state +3521 c7 0/subop/copy *Curr-block-depth 1/imm32 +3522 c7 0/subop/copy *Next-local-stack-offset -4/imm32 +3523 # var eax: (handle block) = parse-mu-block(in, vars, fn) +3524 (parse-mu-block %esi *(ebp+0x10) %edi) # => eax +3525 # out->body = eax +3526 89/<- *(edi+0x10) 0/r32/eax # Function-body +3527 $populate-mu-function-body:end: +3528 # . restore registers +3529 5f/pop-to-edi +3530 5e/pop-to-esi +3531 58/pop-to-eax +3532 # . epilogue +3533 89/<- %esp 5/r32/ebp +3534 5d/pop-to-ebp +3535 c3/return +3536 +3537 == data +3538 +3539 # Global state added to each var record when parsing a function +3540 +3541 Curr-block-depth: # (addr int) +3542 0/imm32 +3543 Next-local-stack-offset: # (addr int) +3544 -4/imm32 +3545 +3546 Next-block-index: # (addr int) +3547 1/imm32 +3548 +3549 == code +3550 +3551 # parses a block, assuming that the leading '{' has already been read by the caller +3552 parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle block) +3553 # pseudocode: +3554 # var line: (stream byte 512) +3555 # var word-slice: slice +3556 # increment *Curr-block-depth +3557 # result/eax = allocate(Heap, Stmt-size) +3558 # result->tag = 0/block +3559 # result->name = some unique name +3560 # while true # line loop +3561 # clear-stream(line) +3562 # read-line-buffered(in, line) +3563 # if (line->write == 0) break # end of file +3564 # word-slice = next-mu-token(line) +3565 # if slice-empty?(word-slice) # end of line +3566 # continue +3567 # else if slice-starts-with?(word-slice, "#") +3568 # continue +3569 # else if slice-equal?(word-slice, "{") +3570 # assert(no-tokens-in(line)) +3571 # block = parse-mu-block(in, vars, fn) +3572 # append-to-block(result, block) +3573 # else if slice-equal?(word-slice, "}") +3574 # break +3575 # else if slice-ends-with?(word-slice, ":") +3576 # # TODO: error-check the rest of 'line' +3577 # --word-slice->end to skip ':' +3578 # named-block = parse-mu-named-block(word-slice, in, vars, fn) +3579 # append-to-block(result, named-block) +3580 # else if slice-equal?(word-slice, "var") +3581 # var-def = parse-mu-var-def(line, vars) +3582 # append-to-block(result, var-def) +3583 # else +3584 # stmt = parse-mu-stmt(line, vars, fn) +3585 # append-to-block(result, stmt) +3586 # decrement *Curr-block-depth +3587 # return result +3588 # +3589 # . prologue +3590 55/push-ebp +3591 89/<- %ebp 4/r32/esp +3592 # . save registers +3593 51/push-ecx +3594 52/push-edx +3595 53/push-ebx +3596 57/push-edi +3597 # var line/ecx: (stream byte 512) +3598 81 5/subop/subtract %esp 0x200/imm32 +3599 68/push 0x200/imm32/length +3600 68/push 0/imm32/read +3601 68/push 0/imm32/write +3602 89/<- %ecx 4/r32/esp +3603 # var word-slice/edx: slice +3604 68/push 0/imm32/end +3605 68/push 0/imm32/start +3606 89/<- %edx 4/r32/esp +3607 # edi = result +3608 (allocate Heap *Stmt-size) # => eax +3609 (zero-out %eax *Stmt-size) +3610 89/<- %edi 0/r32/eax +3611 # set result->tag +3612 c7 0/subop/copy *edi 0/imm32/block # Stmt-tag +3613 # set result->var +3614 (new-block-name *(ebp+0x10)) # => eax +3615 89/<- *(edi+8) 0/r32/eax # Block-var +3616 # push result->var to vars +3617 (push *(ebp+0xc) %eax) +3618 # increment *Curr-block-depth +3619 ff 0/subop/increment *Curr-block-depth +3620 { +3621 $parse-mu-block:line-loop: +3622 # line = read-line-buffered(in) +3623 (clear-stream %ecx) +3624 (read-line-buffered *(ebp+8) %ecx) +3625 #? (write-buffered Stderr "line: ") +3626 #? (write-stream-data Stderr %ecx) +3627 #? (write-buffered Stderr Newline) +3628 #? (flush Stderr) +3629 # if (line->write == 0) break +3630 81 7/subop/compare *ecx 0/imm32 +3631 0f 84/jump-if-= break/disp32 +3632 # word-slice = next-mu-token(line) +3633 (next-mu-token %ecx %edx) +3634 #? (write-buffered Stderr "word: ") +3635 #? (write-slice-buffered Stderr %edx) +3636 #? (write-buffered Stderr Newline) +3637 #? (flush Stderr) +3638 # if slice-empty?(word-slice) continue +3639 (slice-empty? %edx) +3640 3d/compare-eax-and 0/imm32/false +3641 0f 85/jump-if-!= loop/disp32 +3642 # if (slice-starts-with?(word-slice, '#') continue +3643 # . eax = *word-slice->start +3644 8b/-> *edx 0/r32/eax +3645 8a/copy-byte *eax 0/r32/AL +3646 81 4/subop/and %eax 0xff/imm32 +3647 # . if (eax == '#') continue +3648 3d/compare-eax-and 0x23/imm32/hash +3649 0f 84/jump-if-= loop/disp32 +3650 # if slice-equal?(word-slice, "{") +3651 { +3652 $parse-mu-block:check-for-block: +3653 (slice-equal? %edx "{") +3654 3d/compare-eax-and 0/imm32/false +3655 74/jump-if-= break/disp8 +3656 (check-no-tokens-left %ecx) +3657 # parse new block and append +3658 (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax +3659 (append-to-block Heap %edi %eax) +3660 e9/jump $parse-mu-block:line-loop/disp32 +3661 } +3662 # if slice-equal?(word-slice, "}") break +3663 $parse-mu-block:check-for-end: +3664 (slice-equal? %edx "}") +3665 3d/compare-eax-and 0/imm32/false +3666 0f 85/jump-if-!= break/disp32 +3667 # if slice-ends-with?(word-slice, ":") parse named block and append +3668 { +3669 $parse-mu-block:check-for-named-block: +3670 # . eax = *(word-slice->end-1) +3671 8b/-> *(edx+4) 0/r32/eax +3672 48/decrement-eax +3673 8a/copy-byte *eax 0/r32/AL +3674 81 4/subop/and %eax 0xff/imm32 +3675 # . if (eax != ':') break +3676 3d/compare-eax-and 0x3a/imm32/colon +3677 0f 85/jump-if-!= break/disp32 +3678 # TODO: error-check the rest of 'line' +3679 # +3680 # skip ':' +3681 ff 1/subop/decrement *(edx+4) # Slice-end +3682 # +3683 (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax +3684 (append-to-block Heap %edi %eax) +3685 e9/jump $parse-mu-block:line-loop/disp32 +3686 } +3687 # if slice-equal?(word-slice, "var") +3688 { +3689 $parse-mu-block:check-for-var: +3690 (slice-equal? %edx "var") +3691 3d/compare-eax-and 0/imm32/false +3692 74/jump-if-= break/disp8 +3693 # +3694 (parse-mu-var-def %ecx *(ebp+0xc)) # => eax +3695 (append-to-block Heap %edi %eax) +3696 e9/jump $parse-mu-block:line-loop/disp32 +3697 } +3698 $parse-mu-block:regular-stmt: +3699 # otherwise +3700 (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10)) # => eax +3701 (append-to-block Heap %edi %eax) +3702 e9/jump loop/disp32 +3703 } # end line loop +3704 # decrement *Curr-block-depth +3705 ff 1/subop/decrement *Curr-block-depth +3706 # +3707 (pop *(ebp+0xc)) # => eax +3708 # return result +3709 89/<- %eax 7/r32/edi +3710 $parse-mu-block:end: +3711 # . reclaim locals +3712 81 0/subop/add %esp 0x214/imm32 +3713 # . restore registers +3714 5f/pop-to-edi +3715 5b/pop-to-ebx +3716 5a/pop-to-edx +3717 59/pop-to-ecx +3718 # . epilogue +3719 89/<- %esp 5/r32/ebp +3720 5d/pop-to-ebp +3721 c3/return +3722 +3723 $parse-mu-block:abort: +3724 # error("'{' or '}' should be on its own line, but got '") +3725 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") +3726 (rewind-stream %ecx) +3727 (write-stream 2 %ecx) +3728 (write-buffered Stderr "'\n") +3729 (flush Stderr) +3730 # . syscall(exit, 1) +3731 bb/copy-to-ebx 1/imm32 +3732 b8/copy-to-eax 1/imm32/exit +3733 cd/syscall 0x80/imm8 +3734 # never gets here +3735 +3736 new-block-name: # fn: (handle function) -> result/eax: (handle var) +3737 # . prologue +3738 55/push-ebp +3739 89/<- %ebp 4/r32/esp +3740 # . save registers +3741 51/push-ecx +3742 52/push-edx +3743 # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:' +3744 8b/-> *(ebp+8) 0/r32/eax +3745 8b/-> *eax 0/r32/eax # Function-name +3746 8b/-> *eax 0/r32/eax # String-length +3747 05/add-to-eax 0xd/imm32 # 10 + 2 for '$:' +3748 89/<- %ecx 0/r32/eax +3749 # var name/edx: (stream byte n) +3750 29/subtract %esp 1/r32/ecx +3751 ff 6/subop/push %ecx +3752 68/push 0/imm32/read +3753 68/push 0/imm32/write +3754 89/<- %edx 4/r32/esp +3755 (clear-stream %edx) +3756 # eax = fn->name +3757 8b/-> *(ebp+8) 0/r32/eax +3758 8b/-> *eax 0/r32/eax # Function-name +3759 # construct result using Next-block-index (and increment it) +3760 (write %edx "$") +3761 (write %edx %eax) +3762 (write %edx ":") +3763 (print-int32 %edx *Next-block-index) +3764 ff 0/subop/increment *Next-block-index +3765 # var s/eax: slice = {name->data, name->data + name->write} (clobbering edx) +3766 # . eax = name->write +3767 8b/-> *edx 0/r32/eax +3768 # . edx = name->data +3769 8d/copy-address *(edx+0xc) 2/r32/edx +3770 # . eax = name->write + name->data +3771 01/add %eax 2/r32/edx +3772 # . push {edx, eax} +3773 ff 6/subop/push %eax +3774 ff 6/subop/push %edx +3775 89/<- %eax 4/r32/esp +3776 # result->var = new literal(s) +3777 (new-literal Heap %eax) # => eax +3778 $new-block-name:end: +3779 # . reclaim locals +3780 81 0/subop/add %ecx 0xc/imm32 # name.{read/write/len} +3781 81 0/subop/add %ecx 8/imm32 # slice +3782 01/add %esp 1/r32/ecx +3783 # . restore registers +3784 5a/pop-to-edx +3785 59/pop-to-ecx +3786 # . epilogue +3787 89/<- %esp 5/r32/ebp +3788 5d/pop-to-ebp +3789 c3/return +3790 +3791 check-no-tokens-left: # line: (addr stream byte) +3792 # . prologue +3793 55/push-ebp +3794 89/<- %ebp 4/r32/esp +3795 # . save registers +3796 50/push-eax +3797 51/push-ecx +3798 # var s/ecx: slice +3799 68/push 0/imm32/end +3800 68/push 0/imm32/start +3801 89/<- %ecx 4/r32/esp +3802 # +3803 (next-mu-token *(ebp+8) %ecx) +3804 # if slice-empty?(s) return +3805 (slice-empty? %ecx) +3806 3d/compare-eax-and 0/imm32/false +3807 75/jump-if-!= $check-no-tokens-left:end/disp8 +3808 # if (slice-starts-with?(s, '#') return +3809 # . eax = *s->start +3810 8b/-> *edx 0/r32/eax +3811 8a/copy-byte *eax 0/r32/AL +3812 81 4/subop/and %eax 0xff/imm32 +3813 # . if (eax == '#') continue +3814 3d/compare-eax-and 0x23/imm32/hash +3815 74/jump-if-= $check-no-tokens-left:end/disp8 +3816 # abort +3817 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") +3818 (rewind-stream %ecx) +3819 (write-stream 2 %ecx) +3820 (write-buffered Stderr "'\n") +3821 (flush Stderr) +3822 # . syscall(exit, 1) +3823 bb/copy-to-ebx 1/imm32 +3824 b8/copy-to-eax 1/imm32/exit +3825 cd/syscall 0x80/imm8 +3826 # never gets here +3827 $check-no-tokens-left:end: +3828 # . reclaim locals +3829 81 0/subop/add %esp 8/imm32 +3830 # . restore registers +3831 59/pop-to-ecx +3832 58/pop-to-eax +3833 # . epilogue +3834 89/<- %esp 5/r32/ebp +3835 5d/pop-to-ebp +3836 c3/return +3837 +3838 parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) +3839 # pseudocode: +3840 # var s: (addr array byte) = slice-to-string(name) +3841 # var v: (handle var) = new-var(s, 0) +3842 # v->block-depth = *Curr-block-depth # containing block depth +3843 # push(vars, v) +3844 # result = parse-mu-block(in, vars, fn) +3845 # pop(vars) +3846 # result->name = s +3847 # return result +3848 # +3849 # . prologue +3850 55/push-ebp +3851 89/<- %ebp 4/r32/esp +3852 # . save registers +3853 51/push-ecx +3854 # var v/ecx: (handle var) +3855 (new-literal Heap *(ebp+8)) # => eax +3856 89/<- %ecx 0/r32/eax +3857 # push(vars, v) +3858 (push *(ebp+0x10) %ecx) +3859 # eax = result +3860 (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) # => eax +3861 # pop the var +3862 50/push-eax +3863 (pop *(ebp+0x10)) # => eax +3864 58/pop-to-eax +3865 # result->tag = named-block +3866 c7 0/subop/copy *eax 0/imm32/block # Stmt-tag +3867 # result->var = v +3868 89/<- *(eax+8) 1/r32/ecx # Block-var +3869 $parse-mu-named-block:end: +3870 # . restore registers +3871 59/pop-to-ecx +3872 # . epilogue +3873 89/<- %esp 5/r32/ebp +3874 5d/pop-to-ebp +3875 c3/return +3876 +3877 parse-mu-var-def: # line: (addr stream byte), vars: (addr stack (handle var)) -> result/eax: (handle stmt) +3878 # . prologue +3879 55/push-ebp +3880 89/<- %ebp 4/r32/esp +3881 # . save registers +3882 51/push-ecx +3883 52/push-edx +3884 # var word-slice/ecx: slice +3885 68/push 0/imm32/end +3886 68/push 0/imm32/start +3887 89/<- %ecx 4/r32/esp +3888 # var v/edx: (handle var) = parse-var-with-type(line) +3889 (next-mu-token *(ebp+8) %ecx) +3890 (parse-var-with-type %ecx *(ebp+8)) # => eax +3891 89/<- %edx 0/r32/eax +3892 # v->block-depth = *Curr-block-depth +3893 8b/-> *Curr-block-depth 0/r32/eax +3894 89/<- *(edx+8) 0/r32/eax +3895 # +3896 (push *(ebp+0xc) %edx) +3897 # either v has no register and there's no more to this line +3898 8b/-> *(edx+0x10) 0/r32/eax # Var-register +3899 3d/compare-eax-and 0/imm32 +3900 { +3901 75/jump-if-!= break/disp8 +3902 # v->stack-offset = *Next-local-stack-offset +3903 8b/-> *Next-local-stack-offset 0/r32/eax +3904 89/<- *(edx+0xc) 0/r32/eax # Var-offset +3905 # TODO: ensure that there's nothing else on this line +3906 (new-var-def Heap %edx) # => eax +3907 eb/jump $parse-mu-var-def:end/disp8 +3908 } +3909 # or v has a register and there's more to this line +3910 { +3911 74/jump-if-= break/disp8 +3912 # ensure that the next word is '<-' +3913 (next-mu-token *(ebp+8) %ecx) +3914 (slice-equal? %ecx "<-") # => eax +3915 3d/compare-eax-and 0/imm32/false +3916 74/jump-if-= $parse-mu-var-def:abort/disp8 +3917 # +3918 (new-reg-var-def Heap %edx) # => eax +3919 (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc)) +3920 } +3921 $parse-mu-var-def:end: +3922 # *Next-local-stack-offset -= size-of(v) +3923 50/push-eax +3924 (size-of %edx) # => eax +3925 29/subtract-from *Next-local-stack-offset 0/r32/eax +3926 58/pop-to-eax +3927 # . reclaim locals +3928 81 0/subop/add %esp 8/imm32 +3929 # . restore registers +3930 5a/pop-to-edx +3931 59/pop-to-ecx +3932 # . epilogue +3933 89/<- %esp 5/r32/ebp +3934 5d/pop-to-ebp +3935 c3/return +3936 +3937 $parse-mu-var-def:abort: +3938 (rewind-stream *(ebp+8)) +3939 # error("register variable requires a valid instruction to initialize but got '" line "'\n") +3940 (write-buffered Stderr "register variable requires a valid instruction to initialize but got '") +3941 (flush Stderr) +3942 (write-stream 2 *(ebp+8)) +3943 (write-buffered Stderr "'\n") +3944 (flush Stderr) +3945 # . syscall(exit, 1) +3946 bb/copy-to-ebx 1/imm32 +3947 b8/copy-to-eax 1/imm32/exit +3948 cd/syscall 0x80/imm8 +3949 # never gets here +3950 +3951 test-parse-mu-var-def: +3952 # 'var n: int' +3953 # . prologue +3954 55/push-ebp +3955 89/<- %ebp 4/r32/esp +3956 # setup +3957 (clear-stream _test-input-stream) +3958 (write _test-input-stream "n: int\n") # caller has consumed the 'var' +3959 c7 0/subop/copy *Curr-block-depth 1/imm32 +3960 c7 0/subop/copy *Next-local-stack-offset -4/imm32 +3961 # var vars/ecx: (stack (addr var) 4) +3962 81 5/subop/subtract %esp 0x10/imm32 +3963 68/push 0x10/imm32/length +3964 68/push 0/imm32/top +3965 89/<- %ecx 4/r32/esp +3966 (clear-stack %ecx) +3967 # convert +3968 (parse-mu-var-def _test-input-stream %ecx) # => eax +3969 # check result +3970 (check-ints-equal *eax 2 "F - test-parse-mu-var-def/tag") # Stmt-tag is var-def +3971 8b/-> *(eax+4) 0/r32/eax # Vardef-var +3972 (check-strings-equal *eax "n" "F - test-parse-mu-var-def/var-name") # Var-name +3973 (check-ints-equal *(eax+0x10) 0 "F - test-parse-mu-var-def/var-register") # Var-register +3974 (check-ints-equal *(eax+8) 1 "F - test-parse-mu-reg-var-def/output-block-depth") # Var-block-depth +3975 (check-ints-equal *(eax+0xc) -4 "F - test-parse-mu-reg-var-def/output-stack-offset") # Var-offset +3976 # ensure type is int +3977 8b/-> *(eax+4) 0/r32/eax # Var-type +3978 (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0") # Tree-left +3979 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-var-def/var-type:0") # Tree-right +3980 # globals +3981 (check-ints-equal *Next-local-stack-offset -8 "F - test-parse-mu-reg-var-def/Next-local-stack-offset") +3982 # . epilogue +3983 89/<- %esp 5/r32/ebp +3984 5d/pop-to-ebp +3985 c3/return +3986 +3987 test-parse-mu-reg-var-def: +3988 # 'var n/eax: int <- copy 0' +3989 # . prologue +3990 55/push-ebp +3991 89/<- %ebp 4/r32/esp +3992 # setup +3993 (clear-stream _test-input-stream) +3994 (write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var' +3995 c7 0/subop/copy *Curr-block-depth 1/imm32 +3996 c7 0/subop/copy *Next-local-stack-offset -4/imm32 +3997 # var vars/ecx: (stack (addr var) 4) +3998 81 5/subop/subtract %esp 0x10/imm32 +3999 68/push 0x10/imm32/length +4000 68/push 0/imm32/top +4001 89/<- %ecx 4/r32/esp +4002 (clear-stack %ecx) +4003 # convert +4004 (parse-mu-var-def _test-input-stream %ecx) # => eax +4005 # check result +4006 (check-ints-equal *eax 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is reg-var-def +4007 8b/-> *(eax+0xc) 0/r32/eax # Regvardef-outputs +4008 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/single-output") # List-next +4009 8b/-> *eax 0/r32/eax # Stmt-var-value +4010 (check-strings-equal *eax "n" "F - test-parse-mu-reg-var-def/output-name") # Var-name +4011 (check-strings-equal *(eax+0x10) "eax" "F - test-parse-mu-reg-var-def/output-register") # Var-register +4012 (check-ints-equal *(eax+8) 1 "F - test-parse-mu-reg-var-def/output-block-depth") # Var-block-depth +4013 (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-stack-offset") # Var-offset +4014 # ensure type is int +4015 8b/-> *(eax+4) 0/r32/eax # Var-type +4016 (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-left +4017 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-right +4018 # globals +4019 (check-ints-equal *Next-local-stack-offset -8 "F - test-parse-mu-reg-var-def/Next-local-stack-offset") +4020 # . epilogue +4021 89/<- %esp 5/r32/ebp +4022 5d/pop-to-ebp +4023 c3/return +4024 +4025 parse-mu-stmt: # line: (addr stream byte), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) +4026 # pseudocode: +4027 # var name: slice +4028 # result = allocate(Heap, Stmt-size) +4029 # if stmt-has-outputs?(line) +4030 # while true +4031 # name = next-mu-token(line) +4032 # if (name == '<-') break +4033 # assert(is-identifier?(name)) +4034 # var v: (handle var) = lookup-or-define-var(name, vars, fn) # regular stmts may define vars in fn outputs +4035 # result->outputs = append(result->outputs, v) +4036 # add-operation-and-inputs-to-stmt(result, line, vars) +4037 # +4038 # . prologue +4039 55/push-ebp +4040 89/<- %ebp 4/r32/esp +4041 # . save registers +4042 51/push-ecx +4043 52/push-edx +4044 57/push-edi +4045 # var name/ecx: slice +4046 68/push 0/imm32/end +4047 68/push 0/imm32/start +4048 89/<- %ecx 4/r32/esp +4049 # var is-deref?/edx: boolean = false +4050 ba/copy-to-edx 0/imm32/false +4051 # result/edi: (handle stmt) +4052 (allocate Heap *Stmt-size) # => eax +4053 (zero-out %eax *Stmt-size) +4054 89/<- %edi 0/r32/eax +4055 # result->tag = 1/stmt +4056 c7 0/subop/copy *edi 1/imm32/stmt1 # Stmt-tag +4057 { +4058 (stmt-has-outputs? *(ebp+8)) +4059 3d/compare-eax-and 0/imm32/false +4060 0f 84/jump-if-= break/disp32 +4061 { +4062 $parse-mu-stmt:read-outputs: +4063 # name = next-mu-token(line) +4064 (next-mu-token *(ebp+8) %ecx) +4065 # if slice-empty?(word-slice) break +4066 (slice-empty? %ecx) # => eax +4067 3d/compare-eax-and 0/imm32/false +4068 0f 85/jump-if-!= break/disp32 +4069 # if (name == "<-") break +4070 (slice-equal? %ecx "<-") # => eax +4071 3d/compare-eax-and 0/imm32/false +4072 0f 85/jump-if-!= break/disp32 +4073 # is-deref? = false +4074 ba/copy-to-edx 0/imm32/false +4075 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? +4076 8b/-> *ecx 0/r32/eax # Slice-start +4077 8a/copy-byte *eax 0/r32/AL +4078 81 4/subop/and %eax 0xff/imm32 +4079 3d/compare-eax-and 0x2a/imm32/asterisk +4080 { +4081 75/jump-if-!= break/disp8 +4082 ff 0/subop/increment *ecx +4083 ba/copy-to-edx 1/imm32/true +4084 } +4085 # assert(is-identifier?(name)) +4086 (is-identifier? %ecx) # => eax +4087 3d/compare-eax-and 0/imm32/false +4088 0f 84/jump-if-= $parse-mu-stmt:abort/disp32 +4089 # result->outputs = new stmt-var(lookup(name, vars, fn), result->outputs, is-deref?) +4090 (lookup-or-define-var %ecx *(ebp+0xc) *(ebp+0x10)) # => eax +4091 (append-stmt-var Heap %eax *(edi+0xc) %edx) # Stmt1-outputs => eax +4092 89/<- *(edi+0xc) 0/r32/eax # Stmt1-outputs +4093 e9/jump loop/disp32 +4094 } +4095 } +4096 (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc)) +4097 $parse-mu-stmt:end: +4098 # return result +4099 89/<- %eax 7/r32/edi +4100 # . reclaim locals +4101 81 0/subop/add %esp 8/imm32 +4102 # . restore registers +4103 5f/pop-to-edi +4104 5a/pop-to-edx +4105 59/pop-to-ecx +4106 # . epilogue +4107 89/<- %esp 5/r32/ebp +4108 5d/pop-to-ebp +4109 c3/return +4110 +4111 $parse-mu-stmt:abort: +4112 # error("invalid identifier '" name "'\n") +4113 (write-buffered Stderr "invalid identifier '") +4114 (write-slice-buffered Stderr %ecx) +4115 (write-buffered Stderr "'\n") +4116 (flush Stderr) +4117 # . syscall(exit, 1) +4118 bb/copy-to-ebx 1/imm32 +4119 b8/copy-to-eax 1/imm32/exit +4120 cd/syscall 0x80/imm8 +4121 # never gets here +4122 +4123 add-operation-and-inputs-to-stmt: # stmt: (handle stmt), line: (addr stream byte), vars: (addr stack (handle var)) +4124 # pseudocode: +4125 # stmt->name = slice-to-string(next-mu-token(line)) +4126 # while true +4127 # name = next-mu-token(line) +4128 # v = lookup-var-or-literal(name) +4129 # stmt->inouts = append(stmt->inouts, v) +4130 # +4131 # . prologue +4132 55/push-ebp +4133 89/<- %ebp 4/r32/esp +4134 # . save registers +4135 50/push-eax +4136 51/push-ecx +4137 52/push-edx +4138 53/push-ebx +4139 57/push-edi +4140 # edi = stmt +4141 8b/-> *(ebp+8) 7/r32/edi +4142 # var name/ecx: slice +4143 68/push 0/imm32/end +4144 68/push 0/imm32/start +4145 89/<- %ecx 4/r32/esp +4146 # var is-deref?/edx: boolean = false +4147 ba/copy-to-edx 0/imm32/false +4148 $add-operation-and-inputs-to-stmt:read-operation: +4149 (next-mu-token *(ebp+0xc) %ecx) +4150 (slice-to-string Heap %ecx) # => eax +4151 89/<- *(edi+4) 0/r32/eax # Stmt1-operation or Regvardef-operation +4152 # var is-get?/ebx: boolean = (name == "get") +4153 (slice-equal? %ecx "get") # => eax +4154 89/<- %ebx 0/r32/eax +4155 { +4156 $add-operation-and-inputs-to-stmt:read-inouts: +4157 # name = next-mu-token(line) +4158 (next-mu-token *(ebp+0xc) %ecx) +4159 # if slice-empty?(word-slice) break +4160 (slice-empty? %ecx) # => eax +4161 3d/compare-eax-and 0/imm32/false +4162 0f 85/jump-if-!= break/disp32 +4163 # if (name == "<-") abort +4164 (slice-equal? %ecx "<-") +4165 3d/compare-eax-and 0/imm32/false +4166 0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32 +4167 # if (is-get? && second operand) lookup or create offset +4168 { +4169 81 7/subop/compare %ebx 0/imm32/false +4170 74/jump-if-= break/disp8 +4171 81 7/subop/compare *(edi+8) 0/imm32 # Stmt1-inouts or Regvardef-inouts +4172 74/jump-if-= break/disp8 +4173 (lookup-or-create-constant *(edi+8) %ecx) # Stmt1-inouts => eax +4174 #? (write-buffered Stderr "creating new output var ") +4175 #? (print-int32-buffered Stderr %eax) +4176 #? (write-buffered Stderr " for field called ") +4177 #? (write-slice-buffered Stderr %ecx) +4178 #? (write-buffered Stderr Newline) +4179 #? (flush Stderr) +4180 e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32 +4181 } +4182 # is-deref? = false +4183 ba/copy-to-edx 0/imm32/false +4184 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? +4185 8b/-> *ecx 0/r32/eax # Slice-start +4186 8a/copy-byte *eax 0/r32/AL +4187 81 4/subop/and %eax 0xff/imm32 +4188 3d/compare-eax-and 0x2a/imm32/asterisk +4189 { +4190 75/jump-if-!= break/disp8 +4191 $add-operation-and-inputs-to-stmt:inout-is-deref: +4192 ff 0/subop/increment *ecx +4193 ba/copy-to-edx 1/imm32/true +4194 } +4195 (lookup-var-or-literal %ecx *(ebp+0x10)) # => eax +4196 $add-operation-and-inputs-to-stmt:save-var: +4197 (append-stmt-var Heap %eax *(edi+8) %edx) # Stmt1-inouts or Regvardef-inouts => eax +4198 89/<- *(edi+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts +4199 e9/jump loop/disp32 +4200 } +4201 $add-operation-and-inputs-to-stmt:end: +4202 # . reclaim locals +4203 81 0/subop/add %esp 8/imm32 +4204 # . restore registers +4205 5f/pop-to-edi +4206 5b/pop-to-ebx +4207 5a/pop-to-edx +4208 59/pop-to-ecx +4209 58/pop-to-eax +4210 # . epilogue +4211 89/<- %esp 5/r32/ebp +4212 5d/pop-to-ebp +4213 c3/return +4214 +4215 $add-operation-and-inputs-to-stmt:abort: +4216 # error("invalid statement '" line "'\n") +4217 (rewind-stream *(ebp+8)) +4218 (write-buffered Stderr "invalid identifier '") +4219 (flush Stderr) +4220 (write-stream 2 *(ebp+8)) +4221 (write-buffered Stderr "'\n") +4222 (flush Stderr) +4223 # . syscall(exit, 1) +4224 bb/copy-to-ebx 1/imm32 +4225 b8/copy-to-eax 1/imm32/exit +4226 cd/syscall 0x80/imm8 +4227 # never gets here +4228 +4229 stmt-has-outputs?: # line: (addr stream byte) -> result/eax: boolean +4230 # . prologue +4231 55/push-ebp +4232 89/<- %ebp 4/r32/esp +4233 # . save registers +4234 51/push-ecx +4235 # var word-slice/ecx: slice +4236 68/push 0/imm32/end +4237 68/push 0/imm32/start +4238 89/<- %ecx 4/r32/esp +4239 # result = false +4240 b8/copy-to-eax 0/imm32/false +4241 (rewind-stream *(ebp+8)) +4242 { +4243 (next-mu-token *(ebp+8) %ecx) +4244 # if slice-empty?(word-slice) break +4245 (slice-empty? %ecx) +4246 3d/compare-eax-and 0/imm32/false +4247 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) +4248 0f 85/jump-if-!= break/disp32 +4249 # if slice-starts-with?(word-slice, '#') break +4250 # . eax = *word-slice->start +4251 8b/-> *ecx 0/r32/eax +4252 8a/copy-byte *eax 0/r32/AL +4253 81 4/subop/and %eax 0xff/imm32 +4254 # . if (eax == '#') break +4255 3d/compare-eax-and 0x23/imm32/hash +4256 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) +4257 0f 84/jump-if-= break/disp32 +4258 # if slice-equal?(word-slice, '<-') return true +4259 (slice-equal? %ecx "<-") +4260 3d/compare-eax-and 0/imm32/false +4261 74/jump-if-= loop/disp8 +4262 b8/copy-to-eax 1/imm32/true +4263 } +4264 $stmt-has-outputs:end: +4265 (rewind-stream *(ebp+8)) +4266 # . reclaim locals +4267 81 0/subop/add %esp 8/imm32 +4268 # . restore registers +4269 59/pop-to-ecx +4270 # . epilogue +4271 89/<- %esp 5/r32/ebp +4272 5d/pop-to-ebp +4273 c3/return +4274 +4275 # if 'name' starts with a digit, create a new literal var for it +4276 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found +4277 lookup-var-or-literal: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) +4278 # . prologue +4279 55/push-ebp +4280 89/<- %ebp 4/r32/esp +4281 # . save registers +4282 51/push-ecx +4283 56/push-esi +4284 # esi = name +4285 8b/-> *(ebp+8) 6/r32/esi +4286 # if slice-empty?(name) abort +4287 (slice-empty? %esi) # => eax +4288 3d/compare-eax-and 0/imm32/false +4289 0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32 +4290 # var c/ecx: byte = *name->start +4291 8b/-> *esi 1/r32/ecx +4292 8a/copy-byte *ecx 1/r32/CL +4293 81 4/subop/and %ecx 0xff/imm32 +4294 # if is-decimal-digit?(c) return new var(name) +4295 { +4296 (is-decimal-digit? %ecx) # => eax +4297 3d/compare-eax-and 0/imm32/false +4298 74/jump-if-= break/disp8 +4299 (new-literal-integer Heap %esi) # => eax +4300 eb/jump $lookup-var-or-literal:end/disp8 +4301 } +4302 # else if (c == '"') return new var(name) +4303 { +4304 81 7/subop/compare %ecx 0x22/imm32/dquote +4305 75/jump-if-!= break/disp8 +4306 (new-literal Heap %esi) # => eax +4307 eb/jump $lookup-var-or-literal:end/disp8 +4308 } +4309 # otherwise return lookup-var(name, vars) +4310 { +4311 (lookup-var %esi *(ebp+0xc)) # => eax +4312 } +4313 $lookup-var-or-literal:end: +4314 # . restore registers +4315 5e/pop-to-esi +4316 59/pop-to-ecx +4317 # . epilogue +4318 89/<- %esp 5/r32/ebp +4319 5d/pop-to-ebp +4320 c3/return +4321 +4322 $lookup-var-or-literal:abort: +4323 (write-buffered Stderr "empty variable!") +4324 (flush Stderr) +4325 # . syscall(exit, 1) +4326 bb/copy-to-ebx 1/imm32 +4327 b8/copy-to-eax 1/imm32/exit +4328 cd/syscall 0x80/imm8 +4329 # never gets here +4330 +4331 # return first 'name' from the top (back) of 'vars' and abort if not found +4332 lookup-var: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) +4333 # . prologue +4334 55/push-ebp +4335 89/<- %ebp 4/r32/esp +4336 # var target/eax: (handle array byte) = slice-to-string(name) +4337 (slice-to-string Heap *(ebp+8)) # => eax +4338 # +4339 (lookup-var-helper %eax *(ebp+0xc)) # => eax +4340 # if (result == 0) abort +4341 3d/compare-eax-and 0/imm32 +4342 74/jump-if-= $lookup-var:abort/disp8 +4343 $lookup-var:end: +4344 # . epilogue +4345 89/<- %esp 5/r32/ebp +4346 5d/pop-to-ebp +4347 c3/return +4348 +4349 $lookup-var:abort: +4350 (write-buffered Stderr "unknown variable '") +4351 (write-slice-buffered Stderr *(ebp+8)) +4352 (write-buffered Stderr "'\n") +4353 (flush Stderr) +4354 # . syscall(exit, 1) +4355 bb/copy-to-ebx 1/imm32 +4356 b8/copy-to-eax 1/imm32/exit +4357 cd/syscall 0x80/imm8 +4358 # never gets here +4359 +4360 # return first 'name' from the top (back) of 'vars', and 0/null if not found +4361 lookup-var-helper: # name: (addr array byte), vars: (addr stack (handle var)) -> result/eax: (handle var) +4362 # pseudocode: +4363 # var curr: (addr handle var) = &vars->data[vars->top - 4] +4364 # var min = vars->data +4365 # while curr >= min +4366 # var v: (handle var) = *curr +4367 # if v->name == name +4368 # return v +4369 # return 0 +4370 # +4371 # . prologue +4372 55/push-ebp +4373 89/<- %ebp 4/r32/esp +4374 # . save registers +4375 52/push-edx +4376 53/push-ebx +4377 56/push-esi +4378 # esi = vars +4379 8b/-> *(ebp+0xc) 6/r32/esi +4380 # ebx = vars->top +4381 8b/-> *esi 3/r32/ebx +4382 # if (vars->top > vars->length) abort +4383 3b/compare 0/r32/eax *(esi+4) +4384 0f 8f/jump-if-> $lookup-var-helper:error1/disp32 +4385 # var min/edx: (addr handle var) = vars->data +4386 8d/copy-address *(esi+8) 2/r32/edx +4387 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 4] +4388 81 5/subop/subtract %ebx 4/imm32 +4389 8d/copy-address *(esi+ebx+8) 3/r32/ebx +4390 { +4391 # if (curr < min) return 0 +4392 39/compare %ebx 2/r32/edx +4393 b8/copy-to-eax 0/imm32 +4394 0f 82/jump-if-addr< break/disp32 +4395 # var v/eax: (handle var) = *curr +4396 8b/-> *ebx 0/r32/eax +4397 # if (v->name == name) return v +4398 (string-equal? *eax *(ebp+8)) # Var-name +4399 3d/compare-eax-and 0/imm32/false +4400 8b/-> *ebx 0/r32/eax +4401 75/jump-if-!= break/disp8 +4402 # curr -= 4 +4403 81 5/subop/subtract %ebx 4/imm32 +4404 e9/jump loop/disp32 +4405 } +4406 $lookup-var-helper:end: +4407 # . restore registers +4408 5e/pop-to-esi +4409 5b/pop-to-ebx +4410 5a/pop-to-edx +4411 # . epilogue +4412 89/<- %esp 5/r32/ebp +4413 5d/pop-to-ebp +4414 c3/return +4415 +4416 $lookup-var-helper:error1: +4417 (write-buffered Stderr "malformed stack when looking up '") +4418 (write-slice-buffered Stderr *(ebp+8)) +4419 (write-buffered Stderr "'\n") +4420 (flush Stderr) +4421 # . syscall(exit, 1) +4422 bb/copy-to-ebx 1/imm32 +4423 b8/copy-to-eax 1/imm32/exit +4424 cd/syscall 0x80/imm8 +4425 # never gets here +4426 +4427 # return first 'name' from the top (back) of 'vars' and create a new var for a fn output if not found +4428 lookup-or-define-var: # name: (addr slice), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle var) +4429 # . prologue +4430 55/push-ebp +4431 89/<- %ebp 4/r32/esp +4432 # . save registers +4433 51/push-ecx +4434 # var target/ecx: (handle array byte) = slice-to-string(name) +4435 (slice-to-string Heap *(ebp+8)) # => eax +4436 89/<- %ecx 0/r32/eax +4437 # +4438 (lookup-var-helper %ecx *(ebp+0xc)) # => eax +4439 { +4440 # if (result != 0) return +4441 3d/compare-eax-and 0/imm32 +4442 75/jump-if-!= break/disp8 +4443 # if name is one of fn's outputs, return it +4444 { +4445 (find-in-function-outputs *(ebp+0x10) %ecx) # => eax +4446 3d/compare-eax-and 0/imm32 +4447 # otherwise abort +4448 0f 84/jump-if-!= $lookup-var:abort/disp32 +4449 } +4450 } +4451 $lookup-or-define-var:end: +4452 # . restore registers +4453 59/pop-to-ecx +4454 # . epilogue +4455 89/<- %esp 5/r32/ebp +4456 5d/pop-to-ebp +4457 c3/return +4458 +4459 find-in-function-outputs: # fn: (handle function), name: (handle array byte) -> result/eax: (handle var) +4460 # . prologue +4461 55/push-ebp +4462 89/<- %ebp 4/r32/esp +4463 # . save registers +4464 51/push-ecx +4465 # var curr/ecx: (handle list var) = fn->outputs +4466 8b/-> *(ebp+8) 1/r32/ecx +4467 8b/-> *(ecx+0xc) 1/r32/ecx +4468 # while curr != null +4469 { +4470 81 7/subop/compare %ecx 0/imm32 +4471 74/jump-if-= break/disp8 +4472 # var v: (handle var) = *curr +4473 8b/-> *ecx 0/r32/eax # List-value +4474 # if (curr->name == name) return curr +4475 50/push-eax +4476 (string-equal? *eax *(ebp+0xc)) +4477 3d/compare-eax-and 0/imm32/false +4478 58/pop-to-eax +4479 75/jump-if-!= $find-in-function-outputs:end/disp8 +4480 # curr = curr->next +4481 8b/-> *(ecx+4) 1/r32/ecx # List-next +4482 eb/jump loop/disp8 +4483 } +4484 b8/copy-to-eax 0/imm32 +4485 $find-in-function-outputs:end: +4486 # . restore registers +4487 59/pop-to-ecx +4488 # . epilogue +4489 89/<- %esp 5/r32/ebp +4490 5d/pop-to-ebp +4491 c3/return +4492 +4493 test-parse-mu-stmt: +4494 # . prologue +4495 55/push-ebp +4496 89/<- %ebp 4/r32/esp +4497 # setup +4498 (clear-stream _test-input-stream) +4499 (write _test-input-stream "increment n\n") +4500 # var vars/ecx: (stack (addr var) 4) +4501 81 5/subop/subtract %esp 0x10/imm32 +4502 68/push 0x10/imm32/length +4503 68/push 0/imm32/top +4504 89/<- %ecx 4/r32/esp +4505 (clear-stack %ecx) +4506 # var v/edx: var +4507 81 5/subop/subtract %esp 0x14/imm32 # Var-size +4508 89/<- %edx 4/r32/esp +4509 (zero-out %edx 0x14) # Var-size +4510 # v->name = "n" +4511 c7 0/subop/copy *edx "n"/imm32 # Var-name +4512 # +4513 (push %ecx %edx) +4514 # convert +4515 (parse-mu-stmt _test-input-stream %ecx) # => eax +4516 # check result +4517 (check-ints-equal *eax 1 "F - test-parse-mu-stmt/tag") # Stmt-tag is Stmt1 +4518 (check-strings-equal *(eax+4) "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation +4519 # edx: (handle list var) = result->inouts +4520 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts +4521 # ebx: (handle var) = result->inouts->value +4522 8b/-> *edx 3/r32/ebx # Stmt-var-value +4523 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt/inout:0") # Var-name +4524 # . epilogue +4525 89/<- %esp 5/r32/ebp +4526 5d/pop-to-ebp +4527 c3/return +4528 +4529 test-parse-mu-stmt-with-comma: +4530 # . prologue +4531 55/push-ebp +4532 89/<- %ebp 4/r32/esp +4533 # setup +4534 (clear-stream _test-input-stream) +4535 (write _test-input-stream "copy-to n, 3\n") +4536 # var vars/ecx: (stack (addr var) 4) +4537 81 5/subop/subtract %esp 0x10/imm32 +4538 68/push 0x10/imm32/length +4539 68/push 0/imm32/top +4540 89/<- %ecx 4/r32/esp +4541 (clear-stack %ecx) +4542 # var v/edx: var +4543 81 5/subop/subtract %esp 0x14/imm32 # Var-size +4544 89/<- %edx 4/r32/esp +4545 (zero-out %edx 0x14) # Var-size +4546 # v->name = "n" +4547 c7 0/subop/copy *edx "n"/imm32 # Var-name +4548 # +4549 (push %ecx %edx) +4550 # convert +4551 (parse-mu-stmt _test-input-stream %ecx) # => eax +4552 # check result +4553 (check-ints-equal *eax 1 "F - test-parse-mu-stmt-with-comma/tag") # Stmt-tag is Stmt1 +4554 (check-strings-equal *(eax+4) "copy-to" "F - test-parse-mu-stmt-with-comma/name") # Stmt1-operation +4555 # edx: (handle list var) = result->inouts +4556 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts +4557 # ebx: (handle var) = result->inouts->value +4558 8b/-> *edx 3/r32/ebx # Stmt-var-value +4559 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt-with-comma/inout:0") # Var-name +4560 # . epilogue +4561 89/<- %esp 5/r32/ebp +4562 5d/pop-to-ebp +4563 c3/return +4564 +4565 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) +4566 # . prologue +4567 55/push-ebp +4568 89/<- %ebp 4/r32/esp +4569 # . save registers +4570 51/push-ecx +4571 # +4572 (allocate *(ebp+8) *Function-size) # => eax +4573 8b/-> *(ebp+0xc) 1/r32/ecx +4574 89/<- *eax 1/r32/ecx # Function-name +4575 8b/-> *(ebp+0x10) 1/r32/ecx +4576 89/<- *(eax+4) 1/r32/ecx # Function-subx-name +4577 8b/-> *(ebp+0x14) 1/r32/ecx +4578 89/<- *(eax+8) 1/r32/ecx # Function-inouts +4579 8b/-> *(ebp+0x18) 1/r32/ecx +4580 89/<- *(eax+0xc) 1/r32/ecx # Function-outputs +4581 8b/-> *(ebp+0x1c) 1/r32/ecx +4582 89/<- *(eax+0x10) 1/r32/ecx # Function-body +4583 8b/-> *(ebp+0x20) 1/r32/ecx +4584 89/<- *(eax+0x14) 1/r32/ecx # Function-next +4585 $new-function:end: +4586 # . restore registers +4587 59/pop-to-ecx +4588 # . epilogue +4589 89/<- %esp 5/r32/ebp +4590 5d/pop-to-ebp +4591 c3/return +4592 +4593 new-var: # ad: (addr allocation-descriptor), name: (addr array byte), type: (addr tree type-id), block: int, offset: int, register: (addr array byte) -> result/eax: (handle var) +4594 # . prologue +4595 55/push-ebp +4596 89/<- %ebp 4/r32/esp +4597 # . save registers +4598 51/push-ecx +4599 # +4600 (allocate *(ebp+8) *Var-size) # => eax +4601 8b/-> *(ebp+0xc) 1/r32/ecx +4602 89/<- *eax 1/r32/ecx # Var-name +4603 8b/-> *(ebp+0x10) 1/r32/ecx +4604 89/<- *(eax+4) 1/r32/ecx # Var-type +4605 8b/-> *(ebp+0x14) 1/r32/ecx +4606 89/<- *(eax+8) 1/r32/ecx # Var-block-depth +4607 8b/-> *(ebp+0x18) 1/r32/ecx +4608 89/<- *(eax+0xc) 1/r32/ecx # Var-offset +4609 8b/-> *(ebp+0x1c) 1/r32/ecx +4610 89/<- *(eax+0x10) 1/r32/ecx # Var-register +4611 $new-var:end: +4612 # . restore registers +4613 59/pop-to-ecx +4614 # . epilogue +4615 89/<- %esp 5/r32/ebp +4616 5d/pop-to-ebp +4617 c3/return +4618 +4619 new-literal-integer: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) +4620 # . prologue +4621 55/push-ebp +4622 89/<- %ebp 4/r32/esp +4623 # . save registers +4624 51/push-ecx +4625 # if (!is-hex-int?(name)) abort +4626 (is-hex-int? *(ebp+0xc)) # => eax +4627 3d/compare-eax-and 0/imm32/false +4628 0f 84/jump-if-= $new-literal-integer:abort/disp32 +4629 # var s/ecx: (addr array byte) +4630 (slice-to-string Heap *(ebp+0xc)) # => eax +4631 89/<- %ecx 0/r32/eax +4632 # result/ecx = new var(s) +4633 (allocate *(ebp+8) *Var-size) # => eax +4634 (zero-out %eax *Var-size) +4635 89/<- *eax 1/r32/ecx # Var-name +4636 89/<- %ecx 0/r32/eax +4637 # result->type = new type() +4638 (allocate *(ebp+8) *Tree-size) # => eax +4639 (zero-out %eax *Tree-size) # default type is 'literal' +4640 89/<- *(ecx+4) 0/r32/eax # Var-type +4641 # move result to eax +4642 89/<- %eax 1/r32/ecx +4643 $new-literal-integer:end: +4644 # . restore registers +4645 59/pop-to-ecx +4646 # . epilogue +4647 89/<- %esp 5/r32/ebp +4648 5d/pop-to-ebp +4649 c3/return +4650 +4651 $new-literal-integer:abort: +4652 (write-buffered Stderr "variable cannot begin with a digit '") +4653 (write-slice-buffered Stderr *(ebp+0xc)) +4654 (write-buffered Stderr "'\n") +4655 (flush Stderr) +4656 # . syscall(exit, 1) +4657 bb/copy-to-ebx 1/imm32 +4658 b8/copy-to-eax 1/imm32/exit +4659 cd/syscall 0x80/imm8 +4660 # never gets here +4661 +4662 new-literal: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) +4663 # . prologue +4664 55/push-ebp +4665 89/<- %ebp 4/r32/esp +4666 # . save registers +4667 51/push-ecx +4668 # var s/ecx: (addr array byte) +4669 (slice-to-string Heap *(ebp+0xc)) # => eax +4670 89/<- %ecx 0/r32/eax +4671 # result->type = new type() +4672 (allocate *(ebp+8) *Tree-size) # => eax +4673 (zero-out %eax *Tree-size) # default type is 'literal' +4674 # +4675 (new-var *(ebp+8) %ecx %eax *Curr-block-depth 0 0) # => eax +4676 $new-literal:end: +4677 # . restore registers +4678 59/pop-to-ecx +4679 # . epilogue +4680 89/<- %esp 5/r32/ebp +4681 5d/pop-to-ebp +4682 c3/return +4683 +4684 new-label: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) +4685 # . prologue +4686 55/push-ebp +4687 89/<- %ebp 4/r32/esp +4688 # . save registers +4689 51/push-ecx +4690 # var s/ecx: (addr array byte) +4691 (slice-to-string Heap *(ebp+0xc)) # => eax +4692 89/<- %ecx 0/r32/eax +4693 # +4694 (allocate *(ebp+8) *Var-size) # => eax +4695 89/<- *eax 1/r32/ecx # Var-name +4696 89/<- %ecx 0/r32/eax +4697 (allocate *(ebp+8) *Tree-size) # => eax +4698 (zero-out %eax *Tree-size) # labels are literals +4699 89/<- *(ecx+4) 0/r32/eax # Var-type +4700 89/<- %eax 1/r32/ecx +4701 c7 0/subop/copy *(eax+8) 0/imm32 # Var-block-depth +4702 c7 0/subop/copy *(eax+0xc) 0/imm32 # Var-offset +4703 c7 0/subop/copy *(eax+0x10) 0/imm32 # Var-register +4704 $new-label:end: +4705 # . restore registers +4706 59/pop-to-ecx +4707 # . epilogue +4708 89/<- %esp 5/r32/ebp +4709 5d/pop-to-ebp +4710 c3/return +4711 +4712 new-block: # ad: (addr allocation-descriptor), data: (handle list stmt) -> result/eax: (handle stmt) +4713 # . prologue +4714 55/push-ebp +4715 89/<- %ebp 4/r32/esp +4716 # . save registers +4717 51/push-ecx +4718 # +4719 (allocate *(ebp+8) *Stmt-size) # => eax +4720 (zero-out %eax *Stmt-size) +4721 c7 0/subop/copy *eax 0/imm32/tag/block # Stmt-tag +4722 8b/-> *(ebp+0xc) 1/r32/ecx +4723 89/<- *(eax+4) 1/r32/ecx # Block-stmts +4724 $new-block:end: +4725 # . restore registers +4726 59/pop-to-ecx +4727 # . epilogue +4728 89/<- %esp 5/r32/ebp +4729 5d/pop-to-ebp +4730 c3/return +4731 +4732 new-var-def: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle stmt) +4733 # . prologue +4734 55/push-ebp +4735 89/<- %ebp 4/r32/esp +4736 # . save registers +4737 51/push-ecx +4738 # +4739 (allocate *(ebp+8) *Stmt-size) # => eax +4740 (zero-out %eax *Stmt-size) +4741 c7 0/subop/copy *eax 2/imm32/tag/var-on-stack # Stmt-tag +4742 # result->var = var +4743 8b/-> *(ebp+0xc) 1/r32/ecx +4744 89/<- *(eax+4) 1/r32/ecx # Vardef-var +4745 $new-var-def:end: +4746 # . restore registers +4747 59/pop-to-ecx +4748 # . epilogue +4749 89/<- %esp 5/r32/ebp +4750 5d/pop-to-ebp +4751 c3/return +4752 +4753 new-reg-var-def: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle stmt) +4754 # . prologue +4755 55/push-ebp +4756 89/<- %ebp 4/r32/esp +4757 # . save registers +4758 51/push-ecx +4759 57/push-edi +4760 # ecx = var +4761 8b/-> *(ebp+0xc) 1/r32/ecx +4762 # edi = result +4763 (allocate *(ebp+8) *Stmt-size) # => eax +4764 89/<- %edi 0/r32/eax +4765 (zero-out %edi *Stmt-size) +4766 # set tag +4767 c7 0/subop/copy *edi 3/imm32/tag/var-in-register # Stmt-tag +4768 # set output +4769 (append-stmt-var Heap %ecx *(edi+0xc) 0) # Regvardef-outputs => eax +4770 89/<- *(edi+0xc) 0/r32/eax # Regvardef-outputs +4771 $new-reg-var-def:end: +4772 89/<- %eax 7/r32/edi +4773 # . restore registers +4774 5f/pop-to-edi +4775 59/pop-to-ecx +4776 # . epilogue +4777 89/<- %esp 5/r32/ebp +4778 5d/pop-to-ebp +4779 c3/return +4780 +4781 append-list: # ad: (addr allocation-descriptor), value: _type, list: (handle list _type) -> result/eax: (handle list _type) +4782 # . prologue +4783 55/push-ebp +4784 89/<- %ebp 4/r32/esp +4785 # . save registers +4786 51/push-ecx +4787 # +4788 (allocate *(ebp+8) *List-size) # => eax +4789 (zero-out %eax *List-size) +4790 8b/-> *(ebp+0xc) 1/r32/ecx +4791 89/<- *eax 1/r32/ecx # List-value +4792 # if (list == null) return result +4793 81 7/subop/compare *(ebp+0x10) 0/imm32 +4794 74/jump-if-= $append-list:end/disp8 +4795 # otherwise append +4796 # var curr/ecx = list +4797 8b/-> *(ebp+0x10) 1/r32/ecx +4798 # while (curr->next != null) curr = curr->next +4799 { +4800 81 7/subop/compare *(ecx+4) 0/imm32 # List-next +4801 74/jump-if-= break/disp8 +4802 # curr = curr->next +4803 8b/-> *(ecx+4) 1/r32/ecx +4804 eb/jump loop/disp8 +4805 } +4806 # curr->next = result +4807 89/<- *(ecx+4) 0/r32/eax +4808 # return list +4809 8b/-> *(ebp+0x10) 0/r32/eax +4810 $append-list:end: +4811 # . restore registers +4812 59/pop-to-ecx +4813 # . epilogue +4814 89/<- %esp 5/r32/ebp +4815 5d/pop-to-ebp +4816 c3/return +4817 +4818 append-stmt-var: # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean -> result/eax: (handle stmt-var) +4819 # . prologue +4820 55/push-ebp +4821 89/<- %ebp 4/r32/esp +4822 # . save registers +4823 51/push-ecx +4824 # +4825 (allocate *(ebp+8) *Stmt-var-size) # => eax +4826 (zero-out %eax *Stmt-var-size) +4827 8b/-> *(ebp+0xc) 1/r32/ecx +4828 89/<- *eax 1/r32/ecx # Stmt-var-value +4829 8b/-> *(ebp+0x14) 1/r32/ecx +4830 89/<- *(eax+8) 1/r32/ecx # Stmt-var-is-deref +4831 # if (list == null) return result +4832 81 7/subop/compare *(ebp+0x10) 0/imm32 +4833 74/jump-if-= $append-stmt-var:end/disp8 +4834 # otherwise append +4835 # var curr/ecx: (handle stmt-var) = vars +4836 8b/-> *(ebp+0x10) 1/r32/ecx +4837 # while (curr->next != null) curr = curr->next +4838 { +4839 81 7/subop/compare *(ecx+4) 0/imm32 # List-next +4840 74/jump-if-= break/disp8 +4841 # curr = curr->next +4842 8b/-> *(ecx+4) 1/r32/ecx +4843 eb/jump loop/disp8 +4844 } +4845 # curr->next = result +4846 89/<- *(ecx+4) 0/r32/eax +4847 # return vars +4848 8b/-> *(ebp+0x10) 0/r32/eax +4849 $append-stmt-var:end: +4850 # . restore registers +4851 59/pop-to-ecx +4852 # . epilogue +4853 89/<- %esp 5/r32/ebp +4854 5d/pop-to-ebp +4855 c3/return +4856 +4857 append-to-block: # ad: (addr allocation-descriptor), block: (handle block), x: (handle stmt) +4858 # . prologue +4859 55/push-ebp +4860 89/<- %ebp 4/r32/esp +4861 # . save registers +4862 56/push-esi +4863 # esi = block +4864 8b/-> *(ebp+0xc) 6/r32/esi +4865 (append-list *(ebp+8) *(ebp+0x10) *(esi+4)) # ad, x, Block-stmts +4866 89/<- *(esi+4) 0/r32/eax # Block-stmts +4867 $append-to-block:end: +4868 # . restore registers +4869 5e/pop-to-esi +4870 # . epilogue +4871 89/<- %esp 5/r32/ebp +4872 5d/pop-to-ebp +4873 c3/return +4874 +4875 ## Parsing types +4876 # We need to create metadata on user-defined types, and we need to use this +4877 # metadata as we parse instructions. +4878 # However, we also want to allow types to be used before their definitions. +4879 # This means we can't ever assume any type data structures exist. +4880 +4881 lookup-or-create-constant: # container: (handle stmt-var), field-name: (addr slice) -> result/eax: (handle var) +4882 # . prologue +4883 55/push-ebp +4884 89/<- %ebp 4/r32/esp +4885 # . save registers +4886 56/push-esi +4887 # var container-type/esi: type-id +4888 (container-type *(ebp+8)) # => eax +4889 #? (write-buffered Stderr "lookup-or-create-constant: container type-id: ") +4890 #? (print-int32-buffered Stderr %eax) +4891 #? (write-buffered Stderr Newline) +4892 #? (flush Stderr) +4893 89/<- %esi 0/r32/eax +4894 # var typeinfo/eax: (addr typeinfo) +4895 (find-or-create-typeinfo %esi) # => eax +4896 #? (write-buffered Stderr "lookup-or-create-constant: typeinfo: ") +4897 #? (print-int32-buffered Stderr %eax) +4898 #? (write-buffered Stderr Newline) +4899 #? (flush Stderr) +4900 # result = find-or-create-typeinfo-constant(typeinfo, field-name) +4901 (find-or-create-typeinfo-constant %eax *(ebp+0xc)) # => eax +4902 $lookup-or-create-constant:end: +4903 # . restore registers +4904 5e/pop-to-esi +4905 # . epilogue +4906 89/<- %esp 5/r32/ebp +4907 5d/pop-to-ebp +4908 c3/return +4909 +4910 # container->var->type->right->left->value +4911 container-type: # container: (handle stmt-var) -> result/eax: type-id +4912 # . prologue +4913 55/push-ebp +4914 89/<- %ebp 4/r32/esp +4915 # +4916 8b/-> *(ebp+8) 0/r32/eax +4917 8b/-> *eax 0/r32/eax # Stmt-var-value +4918 8b/-> *(eax+4) 0/r32/eax # Var-type +4919 8b/-> *(eax+4) 0/r32/eax # Tree-right +4920 8b/-> *eax 0/r32/eax # Tree-left +4921 8b/-> *eax 0/r32/eax # Atom-value +4922 $container-type:end: +4923 # . epilogue +4924 89/<- %esp 5/r32/ebp +4925 5d/pop-to-ebp +4926 c3/return +4927 +4928 find-or-create-typeinfo: # t: type-id -> result/eax: (handle typeinfo) +4929 # . prologue +4930 55/push-ebp +4931 89/<- %ebp 4/r32/esp +4932 # . save registers +4933 51/push-ecx +4934 # eax = find-typeinfo(t) +4935 (find-typeinfo *(ebp+8)) # => eax +4936 { +4937 # if (curr != 0) break +4938 3d/compare-eax-and 0/imm32 +4939 75/jump-if-!= break/disp8 +4940 $find-or-create-typeinfo:create: +4941 (allocate Heap *Typeinfo-size) # => eax +4942 (zero-out %eax *Typeinfo-size) +4943 # result->id = t +4944 8b/-> *(ebp+8) 1/r32/ecx +4945 89/<- *eax 1/r32/ecx # Typeinfo-id +4946 # result->fields = new table +4947 50/push-eax +4948 (new-stream Heap 0x40 0xc) # => eax +4949 89/<- %ecx 0/r32/eax +4950 58/pop-to-eax +4951 89/<- *(eax+4) 1/r32/ecx +4952 # result->next = Program->types +4953 8b/-> *_Program-types 1/r32/ecx +4954 89/<- *(eax+8) 1/r32/ecx # Typeinfo-next +4955 # Program->types = result +4956 89/<- *_Program-types 0/r32/eax +4957 } +4958 $find-or-create-typeinfo:end: +4959 # . restore registers +4960 59/pop-to-ecx +4961 # . epilogue +4962 89/<- %esp 5/r32/ebp +4963 5d/pop-to-ebp +4964 c3/return +4965 +4966 find-typeinfo: # t: type-id -> result/eax: (handle typeinfo) +4967 # . prologue +4968 55/push-ebp +4969 89/<- %ebp 4/r32/esp +4970 # . save registers +4971 51/push-ecx +4972 # ecx = t +4973 8b/-> *(ebp+8) 1/r32/ecx +4974 # var curr/eax: (handle typeinfo) = Program->types +4975 8b/-> *_Program-types 0/r32/eax +4976 { +4977 # if (curr == 0) break +4978 3d/compare-eax-and 0/imm32 +4979 74/jump-if-= break/disp8 +4980 # if (curr->id == t) return curr +4981 39/compare *eax 1/r32/ecx # Typeinfo-id +4982 0f 84/jump-if-= $find-or-create-typeinfo:end/disp32 +4983 # curr = curr->next +4984 8b/-> *(eax+8) 0/r32/eax +4985 # +4986 eb/jump loop/disp8 +4987 } +4988 $find-typeinfo:end: +4989 # . restore registers +4990 59/pop-to-ecx +4991 # . epilogue +4992 89/<- %esp 5/r32/ebp +4993 5d/pop-to-ebp +4994 c3/return +4995 +4996 find-or-create-typeinfo-constant: # T: (handle typeinfo), f: (addr slice) -> result/eax: (handle var) +4997 # . prologue +4998 55/push-ebp +4999 89/<- %ebp 4/r32/esp +5000 # . save registers +5001 51/push-ecx +5002 56/push-esi +5003 # esi = T->fields +5004 8b/-> *(ebp+8) 6/r32/esi +5005 8b/-> *(esi+4) 6/r32/esi # Typeinfo-fields +5006 # esi = get-or-insert(T->fields, f) +5007 (leaky-get-or-insert-slice %esi *(ebp+0xc) 0xc) # => eax +5008 89/<- %esi 0/r32/eax +5009 # if output var exists, return it +5010 81 7/subop/compare *(esi+4) 0/imm32 # output var +5011 8b/-> *(esi+4) 0/r32/eax # output var +5012 75/jump-if-!= $find-or-create-typeinfo-constant:end/disp8 +5013 # var type/ecx: (handle tree type-id) = new var("dummy name", constant type, -1 offset) +5014 (allocate Heap *Tree-size) # => eax +5015 c7 0/subop/copy *eax 6/imm32/constant # Atom-value +5016 c7 0/subop/copy *(eax+4) 0/imm32 # Tree-right +5017 (new-var Heap "field" %eax 0 -1 0) # => eax +5018 # offset (constant value) isn't filled out yet +5019 # save output var in row +5020 89/<- *(esi+4) 0/r32/eax +5021 $find-or-create-typeinfo-constant:end: +5022 # . restore registers +5023 5e/pop-to-esi +5024 59/pop-to-ecx +5025 # . epilogue +5026 89/<- %esp 5/r32/ebp +5027 5d/pop-to-ebp +5028 c3/return +5029 +5030 populate-mu-type: # in: (addr stream byte), t: (handle typeinfo) +5031 # pseudocode: +5032 # var line: (stream byte 512) +5033 # curr-offset = 0 +5034 # while true +5035 # clear-stream(line) +5036 # read-line-buffered(in, line) +5037 # if line->write == 0 +5038 # abort +5039 # word-slice = next-mu-token(line) +5040 # if slice-empty?(word-slice) # end of line +5041 # continue +5042 # if slice-equal?(word-slice, "}") +5043 # break +5044 # var v: (handle var) = parse-var-with-type(word-slice, line) +5045 # var r: (addr {(handle var) (handle var)}) = get-or-insert(t, v->name, row-size=12) +5046 # TODO: ensure that r->first is null +5047 # r->first = v +5048 # if r->second == 0 +5049 # r->second = new var("dummy name", constant type, -1 offset) +5050 # r->second->offset = curr-offset +5051 # curr-offset += size-of(existing) +5052 # TODO: ensure nothing else in line +5053 # +5054 # . prologue +5055 55/push-ebp +5056 89/<- %ebp 4/r32/esp +5057 # . save registers +5058 50/push-eax +5059 51/push-ecx +5060 52/push-edx +5061 53/push-ebx +5062 56/push-esi +5063 57/push-edi +5064 # edi = t +5065 8b/-> *(ebp+0xc) 7/r32/edi +5066 # var line/ecx: (stream byte 512) +5067 81 5/subop/subtract %esp 0x200/imm32 +5068 68/push 0x200/imm32/length +5069 68/push 0/imm32/read +5070 68/push 0/imm32/write +5071 89/<- %ecx 4/r32/esp +5072 # var word-slice/edx: slice +5073 68/push 0/imm32/end +5074 68/push 0/imm32/start +5075 89/<- %edx 4/r32/esp +5076 # var curr-offset/ebx: int = 0 +5077 bb/copy-to-ebx 0/imm32 +5078 { +5079 $populate-mu-type:line-loop: +5080 (clear-stream %ecx) +5081 (read-line-buffered *(ebp+8) %ecx) +5082 # if (line->write == 0) abort +5083 81 7/subop/compare *ecx 0/imm32 +5084 0f 84/jump-if-= $populate-mu-type:abort/disp32 +5085 +-- 6 lines: #? # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------ +5091 (next-mu-token %ecx %edx) +5092 # if slice-empty?(word-slice) continue +5093 (slice-empty? %edx) +5094 3d/compare-eax-and 0/imm32 +5095 0f 85/jump-if-!= loop/disp32 +5096 # if slice-equal?(word-slice, "}") break +5097 (slice-equal? %edx "}") +5098 3d/compare-eax-and 0/imm32 +5099 0f 85/jump-if-!= break/disp32 +5100 # var v/esi: (handle var) = parse-var-with-type(word-slice, first-line) +5101 (parse-var-with-type %edx %ecx) # => eax +5102 89/<- %esi 0/r32/eax +5103 # var r/eax: (addr {(handle var) (handle var)}) +5104 #? (write-buffered Stderr "populate-mu-type: typeinfo: ") +5105 #? (print-int32-buffered Stderr %edi) +5106 #? (write-buffered Stderr Newline) +5107 #? (flush Stderr) +5108 (get-or-insert *(edi+4) *esi 0xc) # Typeinfo-fields Var-name => eax +5109 # r->first = v +5110 89/<- *eax 6/r32/esi +5111 # if (r->second == 0) create a new var with some placeholder data +5112 { +5113 81 7/subop/compare *(eax+4) 0/imm32 +5114 75/jump-if-!= break/disp8 +5115 # temporarily spill r to esi +5116 89/<- %esi 0/r32/eax +5117 (new-literal Heap %edx) # => eax +5118 89/<- *(esi+4) 0/r32/eax +5119 89/<- %eax 6/r32/esi +5120 #? (write-buffered Stderr "creating new output var ") +5121 #? (print-int32-buffered Stderr %eax) +5122 #? (write-buffered Stderr Newline) +5123 #? (flush Stderr) +5124 } +5125 # r->second->offset = curr-offset +5126 8b/-> *(eax+4) 0/r32/eax +5127 #? (write-buffered Stderr "writing offset ") +5128 #? (print-int32-buffered Stderr %ebx) +5129 #? (write-buffered Stderr " to output var ") +5130 #? (print-int32-buffered Stderr %eax) +5131 #? (write-buffered Stderr Newline) +5132 #? (flush Stderr) +5133 89/<- *(eax+0xc) 3/r32/ebx +5134 # curr-offset += size-of(v) +5135 50/push-eax +5136 (size-of %eax) # => eax +5137 01/add-to %ebx 0/r32/eax +5138 58/pop-to-eax +5139 # +5140 e9/jump loop/disp32 +5141 } +5142 $populate-mu-type:end: +5143 # . reclaim locals +5144 81 0/subop/add %esp 0x214/imm32 +5145 # . restore registers +5146 5f/pop-to-edi +5147 5e/pop-to-esi +5148 5b/pop-to-ebx +5149 5a/pop-to-edx +5150 59/pop-to-ecx +5151 58/pop-to-eax +5152 # . epilogue +5153 89/<- %esp 5/r32/ebp +5154 5d/pop-to-ebp +5155 c3/return +5156 +5157 $populate-mu-type:abort: +5158 # error("unexpected top-level command: " word-slice "\n") +5159 (write-buffered Stderr "incomplete type definition '") +5160 (type-name *edi) # Typeinfo-id => eax +5161 (write-buffered Stderr %eax) +5162 (write-buffered Stderr "\n") +5163 (flush Stderr) +5164 # . syscall(exit, 1) +5165 bb/copy-to-ebx 1/imm32 +5166 b8/copy-to-eax 1/imm32/exit +5167 cd/syscall 0x80/imm8 +5168 # never gets here +5169 +5170 type-name: # index: int -> result/eax: (addr array byte) +5171 # . prologue +5172 55/push-ebp +5173 89/<- %ebp 4/r32/esp +5174 # +5175 (index Type-id *(ebp+8)) +5176 $type-name:end: +5177 # . epilogue +5178 89/<- %esp 5/r32/ebp +5179 5d/pop-to-ebp +5180 c3/return +5181 +5182 index: # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte) +5183 # . prologue +5184 55/push-ebp +5185 89/<- %ebp 4/r32/esp +5186 # . save registers +5187 56/push-esi +5188 # TODO: bounds-check index +5189 # esi = arr +5190 8b/-> *(ebp+8) 6/r32/esi +5191 # eax = index +5192 8b/-> *(ebp+0xc) 0/r32/eax +5193 # eax = *(arr + 12 + index) +5194 8b/-> *(esi+eax+0xc) 0/r32/eax +5195 $index:end: +5196 # . restore registers +5197 5e/pop-to-esi +5198 # . epilogue +5199 89/<- %esp 5/r32/ebp +5200 5d/pop-to-ebp +5201 c3/return +5202 +5203 ####################################################### +5204 # Type-checking +5205 ####################################################### +5206 +5207 check-mu-types: +5208 # . prologue +5209 55/push-ebp +5210 89/<- %ebp 4/r32/esp +5211 # +5212 $check-mu-types:end: +5213 # . epilogue +5214 89/<- %esp 5/r32/ebp +5215 5d/pop-to-ebp +5216 c3/return +5217 +5218 size-of: # v: (addr var) -> result/eax: int +5219 # . prologue +5220 55/push-ebp +5221 89/<- %ebp 4/r32/esp +5222 # if v is a literal, return 0 +5223 8b/-> *(ebp+8) 0/r32/eax +5224 8b/-> *(eax+4) 0/r32/eax # Var-type +5225 81 7/subop/compare *eax 0/imm32 # Tree-left +5226 b8/copy-to-eax 0/imm32 +5227 74/jump-if-= $size-of:end/disp8 +5228 # hard-coded since we only support 'int' types for now +5229 b8/copy-to-eax 4/imm32 +5230 $size-of:end: +5231 # . epilogue +5232 89/<- %esp 5/r32/ebp +5233 5d/pop-to-ebp +5234 c3/return +5235 +5236 type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean +5237 # . prologue +5238 55/push-ebp +5239 89/<- %ebp 4/r32/esp +5240 # . save registers +5241 51/push-ecx +5242 52/push-edx +5243 # ecx = a +5244 8b/-> *(ebp+8) 1/r32/ecx +5245 # edx = b +5246 8b/-> *(ebp+0xc) 2/r32/edx +5247 # if (a == b) return true +5248 8b/-> %ecx 0/r32/eax # Var-type +5249 39/compare %edx 0/r32/eax # Var-type +5250 b8/copy-to-eax 1/imm32/true +5251 74/jump-if-= $type-equal?:end/disp8 +5252 # if (a < MAX_TYPE_ID) return false +5253 81 7/subop/compare %ecx 0x10000/imm32 +5254 b8/copy-to-eax 0/imm32/false +5255 72/jump-if-addr< $type-equal?:end/disp8 +5256 # if (b < MAX_TYPE_ID) return false +5257 81 7/subop/compare %edx 0x10000/imm32 +5258 b8/copy-to-eax 0/imm32/false +5259 72/jump-if-addr< $type-equal?:end/disp8 +5260 # if (!type-equal?(a->left, b->left)) return false +5261 (type-equal? *ecx *edx) # Tree-left, Tree-left => eax +5262 3d/compare-eax-and 0/imm32/false +5263 74/jump-if-= $type-equal?:end/disp8 +5264 # return type-equal?(a->right, b->right) +5265 (type-equal? *(ecx+4) *(edx+4)) # Tree-right, Tree-right => eax +5266 $type-equal?:end: +5267 # . restore registers +5268 5a/pop-to-edx +5269 59/pop-to-ecx +5270 # . epilogue +5271 89/<- %esp 5/r32/ebp +5272 5d/pop-to-ebp +5273 c3/return +5274 +5275 == data +5276 +5277 # not yet used, but it will be +5278 Type-size: # (stream int) +5279 0x18/imm32/write +5280 0/imm32/read +5281 0x100/imm32/length +5282 # data +5283 4/imm32 # literal +5284 4/imm32 # int +5285 4/imm32 # addr +5286 0/imm32 # array (logic elsewhere) +5287 8/imm32 # handle (fat pointer) +5288 4/imm32 # boolean +5289 0/imm32 +5290 0/imm32 +5291 # 0x20 +5292 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +5293 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +5294 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +5295 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +5296 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +5297 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +5298 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +5299 +5300 == code +5301 +5302 ####################################################### +5303 # Code-generation +5304 ####################################################### +5305 +5306 emit-subx: # out: (addr buffered-file) +5307 # . prologue +5308 55/push-ebp +5309 89/<- %ebp 4/r32/esp +5310 # . save registers +5311 50/push-eax +5312 51/push-ecx +5313 57/push-edi +5314 # edi = out +5315 8b/-> *(ebp+8) 7/r32/edi +5316 # var curr/ecx: (handle function) = *Program->functions +5317 8b/-> *_Program-functions 1/r32/ecx +5318 { +5319 # if (curr == null) break +5320 81 7/subop/compare %ecx 0/imm32 +5321 0f 84/jump-if-= break/disp32 +5322 (emit-subx-function %edi %ecx) +5323 # curr = curr->next +5324 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next +5325 e9/jump loop/disp32 +5326 } +5327 $emit-subx:end: +5328 # . restore registers +5329 5f/pop-to-edi +5330 59/pop-to-ecx +5331 58/pop-to-eax +5332 # . epilogue +5333 89/<- %esp 5/r32/ebp +5334 5d/pop-to-ebp +5335 c3/return +5336 +5337 emit-subx-function: # out: (addr buffered-file), f: (handle function) +5338 # . prologue +5339 55/push-ebp +5340 89/<- %ebp 4/r32/esp +5341 # . save registers +5342 50/push-eax +5343 51/push-ecx +5344 52/push-edx +5345 57/push-edi +5346 # edi = out +5347 8b/-> *(ebp+8) 7/r32/edi +5348 # ecx = f +5349 8b/-> *(ebp+0xc) 1/r32/ecx +5350 # var vars/edx: (stack (addr var) 256) +5351 81 5/subop/subtract %esp 0x400/imm32 +5352 68/push 0x400/imm32/length +5353 68/push 0/imm32/top +5354 89/<- %edx 4/r32/esp +5355 # +5356 (write-buffered %edi *ecx) +5357 (write-buffered %edi ":\n") +5358 # Important: each block's depth during code-generation should be identical +5359 # to what it was during parsing. +5360 c7 0/subop/copy *Curr-block-depth 1/imm32 +5361 (emit-subx-prologue %edi) +5362 (emit-subx-block %edi *(ecx+0x10) %edx) # Function-body +5363 (emit-subx-epilogue %edi) +5364 $emit-subx-function:end: +5365 # . reclaim locals +5366 81 0/subop/add %esp 408/imm32 +5367 # . restore registers +5368 5f/pop-to-edi +5369 5a/pop-to-edx +5370 59/pop-to-ecx +5371 58/pop-to-eax +5372 # . epilogue +5373 89/<- %esp 5/r32/ebp +5374 5d/pop-to-ebp +5375 c3/return +5376 +5377 emit-subx-stmt-list: # out: (addr buffered-file), stmts: (handle list stmt), vars: (addr stack (handle var)) +5378 # . prologue +5379 55/push-ebp +5380 89/<- %ebp 4/r32/esp +5381 # . save registers +5382 50/push-eax +5383 51/push-ecx +5384 52/push-edx +5385 53/push-ebx +5386 56/push-esi +5387 # esi = stmts +5388 8b/-> *(ebp+0xc) 6/r32/esi +5389 # var var-seen?/edx: boolean <- copy false +5390 ba/copy-to-edx 0/imm32/false +5391 # +5392 { +5393 $emit-subx-stmt-list:loop: +5394 81 7/subop/compare %esi 0/imm32 +5395 0f 84/jump-if-= break/disp32 +5396 # var curr-stmt/ecx = stmts->value +5397 8b/-> *esi 1/r32/ecx # List-value +5398 { +5399 $emit-subx-stmt-list:check-for-block: +5400 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag +5401 75/jump-if-!= break/disp8 +5402 $emit-subx-stmt-list:block: +5403 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10)) +5404 } +5405 { +5406 $emit-subx-stmt-list:check-for-stmt: +5407 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag +5408 0f 85/jump-if-!= break/disp32 +5409 $emit-subx-stmt-list:stmt1: +5410 { +5411 (is-mu-branch? %ecx) # => eax +5412 3d/compare-eax-and 0/imm32/false +5413 0f 84/jump-if-= break/disp32 +5414 $emit-subx-stmt-list:branch-stmt: +5415 # if !var-seen? break +5416 81 7/subop/compare %edx 0/imm32/false +5417 0f 84/jump-if-= break/disp32 +5418 $emit-subx-stmt-list:branch-stmt-and-var-seen: +5419 +-- 26 lines: # unconditional loops ----------------------------------------------------------------------------------------------------------------------------------------------------- +5445 +-- 15 lines: # unconditional breaks ---------------------------------------------------------------------------------------------------------------------------------------------------- +5460 +-- 37 lines: # simple conditional branches without a target ---------------------------------------------------------------------------------------------------------------------------- +5497 +-- 19 lines: # conditional branches with an explicit target ---------------------------------------------------------------------------------------------------------------------------- +5516 } +5517 $emit-subx-stmt-list:1-to-1: +5518 (emit-subx-stmt *(ebp+8) %ecx Primitives *_Program-functions) +5519 } +5520 { +5521 $emit-subx-stmt-list:check-for-var-def: +5522 81 7/subop/compare *ecx 2/imm32/var-def # Stmt-tag +5523 75/jump-if-!= break/disp8 +5524 $emit-subx-stmt-list:var-def: +5525 (emit-subx-var-def *(ebp+8) %ecx) +5526 (push *(ebp+0x10) *(ecx+4)) # Vardef-var +5527 # var-seen? = true +5528 ba/copy-to-edx 1/imm32/true +5529 } +5530 { +5531 $emit-subx-stmt-list:check-for-reg-var-def: +5532 81 7/subop/compare *ecx 3/imm32/reg-var-def # Stmt-tag +5533 0f 85/jump-if-!= break/disp32 +5534 $emit-subx-stmt-list:reg-var-def: +5535 # TODO: ensure that there's exactly one output +5536 # var output/eax: (handle var) = curr-stmt->outputs->value +5537 8b/-> *(ecx+0xc) 0/r32/eax +5538 8b/-> *eax 0/r32/eax +5539 # ensure that output is in a register +5540 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register +5541 0f 84/jump-if-= $emit-subx-stmt-list:abort-reg-var-def-without-register/disp32 +5542 # emit spill +5543 (emit-indent *(ebp+8) *Curr-block-depth) +5544 (write-buffered *(ebp+8) "ff 6/subop/push %") +5545 (write-buffered *(ebp+8) *(eax+0x10)) +5546 (write-buffered *(ebp+8) Newline) +5547 # register variable definition +5548 (push *(ebp+0x10) %eax) +5549 # emit the instruction as usual +5550 (emit-subx-stmt *(ebp+8) %ecx Primitives *_Program-functions) +5551 # var-seen? = true +5552 ba/copy-to-edx 1/imm32/true +5553 } +5554 $emit-subx-stmt-list:continue: +5555 # TODO: raise an error on unrecognized Stmt-tag +5556 8b/-> *(esi+4) 6/r32/esi # List-next +5557 e9/jump loop/disp32 +5558 } +5559 $emit-subx-stmt-list:emit-cleanup: +5560 (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth) +5561 $emit-subx-stmt-list:cleanup: +5562 (clean-up-blocks *(ebp+0x10) *Curr-block-depth) +5563 $emit-subx-stmt-list:end: +5564 # . restore registers +5565 5e/pop-to-esi +5566 5b/pop-to-ebx +5567 5a/pop-to-edx +5568 59/pop-to-ecx +5569 58/pop-to-eax +5570 # . epilogue +5571 89/<- %esp 5/r32/ebp +5572 5d/pop-to-ebp +5573 c3/return +5574 +5575 $emit-subx-stmt-list:abort-reg-var-def-without-register: +5576 # error("var '" var->name "' initialized from an instruction must live in a register\n") +5577 (write-buffered Stderr "var '") +5578 (write-buffered Stderr *eax) # Var-name +5579 (write-buffered Stderr "' initialized from an instruction must live in a register\n") +5580 (flush Stderr) +5581 # . syscall(exit, 1) +5582 bb/copy-to-ebx 1/imm32 +5583 b8/copy-to-eax 1/imm32/exit +5584 cd/syscall 0x80/imm8 +5585 # never gets here +5586 +5587 emit-subx-cleanup-and-unconditional-nonlocal-branch: # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack (handle var)) +5588 # . prologue +5589 55/push-ebp +5590 89/<- %ebp 4/r32/esp +5591 # . save registers +5592 50/push-eax +5593 51/push-ecx +5594 52/push-edx +5595 # ecx = stmt +5596 8b/-> *(ebp+0xc) 1/r32/ecx +5597 # var target/edx: (addr array byte) = curr-stmt->inouts->value->name +5598 8b/-> *(ecx+8) 2/r32/edx # Stmt1-inouts +5599 8b/-> *edx 2/r32/edx # Stmt-var-value +5600 8b/-> *edx 2/r32/edx # Var-name +5601 # clean up until target block +5602 (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %edx) +5603 # emit jump to target block +5604 (emit-indent *(ebp+8) *Curr-block-depth) +5605 (write-buffered *(ebp+8) "e9/jump ") +5606 (write-buffered *(ebp+8) %edx) +5607 (string-starts-with? *(ecx+4) "break") +5608 3d/compare-eax-and 0/imm32/false +5609 { +5610 74/jump-if-= break/disp8 +5611 (write-buffered *(ebp+8) ":break/disp32\n") +5612 } +5613 3d/compare-eax-and 0/imm32/false # just in case the function call modified flags +5614 { +5615 75/jump-if-!= break/disp8 +5616 (write-buffered *(ebp+8) ":loop/disp32\n") +5617 } +5618 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end: +5619 # . restore registers +5620 5a/pop-to-edx +5621 59/pop-to-ecx +5622 58/pop-to-eax +5623 # . epilogue +5624 89/<- %esp 5/r32/ebp +5625 5d/pop-to-ebp +5626 c3/return +5627 +5628 is-mu-branch?: # stmt: (addr stmt1) -> result/eax: boolean +5629 # . prologue +5630 55/push-ebp +5631 89/<- %ebp 4/r32/esp +5632 # . save registers +5633 51/push-ecx +5634 # ecx = stmt +5635 8b/-> *(ebp+8) 1/r32/ecx +5636 # if (stmt->operation starts with "loop") return true +5637 (string-starts-with? *(ecx+4) "loop") # Stmt1-operation => eax +5638 3d/compare-eax-and 0/imm32/false +5639 75/jump-if-not-equal $is-mu-branch?:end/disp8 +5640 # otherwise return (stmt->operation starts with "break") +5641 (string-starts-with? *(ecx+4) "break") # Stmt1-operation => eax +5642 $is-mu-branch?:end: +5643 # . restore registers +5644 59/pop-to-ecx +5645 # . epilogue +5646 89/<- %esp 5/r32/ebp +5647 5d/pop-to-ebp +5648 c3/return +5649 +5650 emit-reverse-break: # out: (addr buffered-file), stmt: (addr stmt1) +5651 # . prologue +5652 55/push-ebp +5653 89/<- %ebp 4/r32/esp +5654 # . save registers +5655 50/push-eax +5656 # eax = stmt +5657 8b/-> *(ebp+0xc) 0/r32/eax +5658 # +5659 (get Reverse-branch *(eax+4) 8 "reverse-branch: ") # Stmt1-operation => eax: (addr addr array byte) +5660 (emit-indent *(ebp+8) *Curr-block-depth) +5661 (write-buffered *(ebp+8) *eax) +5662 (write-buffered *(ebp+8) " break/disp32\n") +5663 $emit-reverse-break:end: +5664 # . restore registers +5665 58/pop-to-eax +5666 # . epilogue +5667 89/<- %esp 5/r32/ebp +5668 5d/pop-to-ebp +5669 c3/return +5670 +5671 == data +5672 +5673 Reverse-branch: # (table string string) +5674 # a table is a stream +5675 0xa0/imm32/write +5676 0/imm32/read +5677 0xa0/imm32/length +5678 # data +5679 "break-if-="/imm32 "0f 85/jump-if-!="/imm32 +5680 "loop-if-="/imm32 "0f 85/jump-if-!="/imm32 +5681 "break-if-!="/imm32 "0f 84/jump-if-="/imm32 +5682 "loop-if-!="/imm32 "0f 84/jump-if-="/imm32 +5683 "break-if-<"/imm32 "0f 8d/jump-if->="/imm32 +5684 "loop-if-<"/imm32 "0f 8d/jump-if->="/imm32 +5685 "break-if->"/imm32 "0f 8e/jump-if-<="/imm32 +5686 "loop-if->"/imm32 "0f 8e/jump-if-<="/imm32 +5687 "break-if-<="/imm32 "0f 87/jump-if->"/imm32 +5688 "loop-if-<="/imm32 "0f 87/jump-if->"/imm32 +5689 "break-if->="/imm32 "0f 8c/jump-if-<"/imm32 +5690 "loop-if->="/imm32 "0f 8c/jump-if-<"/imm32 +5691 "break-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 +5692 "loop-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 +5693 "break-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 +5694 "loop-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 +5695 "break-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 +5696 "loop-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 +5697 "break-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 +5698 "loop-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 +5699 +5700 == code +5701 +5702 emit-unconditional-jump-to-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), depth: int, label-suffix: (addr array byte) +5703 # . prologue +5704 55/push-ebp +5705 89/<- %ebp 4/r32/esp +5706 # . save registers +5707 50/push-eax +5708 51/push-ecx +5709 52/push-edx +5710 53/push-ebx +5711 # ecx = vars +5712 8b/-> *(ebp+0xc) 1/r32/ecx +5713 # var eax: int = vars->top +5714 8b/-> *ecx 0/r32/eax +5715 # var min/ecx: (address (handle var)) = vars->data +5716 81 0/subop/add %ecx 8/imm32 +5717 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] +5718 81 5/subop/subtract %eax 4/imm32 +5719 8d/copy-address *(ecx+eax) 0/r32/eax +5720 # edx = depth +5721 8b/-> *(ebp+0x10) 2/r32/edx +5722 { +5723 $emit-unconditional-jump-to-depth:loop: +5724 # if (curr < min) break +5725 39/compare %eax 1/r32/ecx +5726 0f 82/jump-if-addr< break/disp32 +5727 # var v/ebx: (handle var) = *curr +5728 8b/-> *eax 3/r32/ebx +5729 # if (v->block-depth < until-block-depth) break +5730 39/compare *(ebx+8) 2/r32/edx # Var-block-depth +5731 0f 8c/jump-if-< break/disp32 +5732 { +5733 $emit-unconditional-jump-to-depth:check: +5734 # if v->block-depth != until-block-depth, continue +5735 39/compare *(ebx+8) 2/r32/edx # Var-block-depth +5736 0f 85/jump-if-!= break/disp32 +5737 $emit-unconditional-jump-to-depth:depth-found: +5738 # if v is not a literal, continue +5739 # . var eax: int = size-of(v) +5740 50/push-eax +5741 (size-of %ebx) # => eax +5742 # . if (eax != 0) continue +5743 3d/compare-eax-and 0/imm32 +5744 58/pop-to-eax +5745 # +5746 0f 85/jump-if-!= break/disp32 +5747 $emit-unconditional-jump-to-depth:label-found: +5748 # emit unconditional jump, then return +5749 (emit-indent *(ebp+8) *Curr-block-depth) +5750 (write-buffered *(ebp+8) "e9/jump ") +5751 (write-buffered *(ebp+8) *ebx) # Var-name +5752 (write-buffered *(ebp+8) ":") +5753 (write-buffered *(ebp+8) *(ebp+0x14)) +5754 (write-buffered *(ebp+8) "/disp32\n") +5755 eb/jump $emit-unconditional-jump-to-depth:end/disp8 +5756 } +5757 # curr -= 4 +5758 2d/subtract-from-eax 4/imm32 +5759 e9/jump loop/disp32 +5760 } +5761 # TODO: error if no label at 'depth' was found +5762 $emit-unconditional-jump-to-depth:end: +5763 # . restore registers +5764 5b/pop-to-ebx +5765 5a/pop-to-edx +5766 59/pop-to-ecx +5767 58/pop-to-eax +5768 # . epilogue +5769 89/<- %esp 5/r32/ebp +5770 5d/pop-to-ebp +5771 c3/return +5772 +5773 # emit clean-up code for 'vars' until some block depth +5774 # doesn't actually modify 'vars' so we need traverse manually inside the stack +5775 emit-cleanup-code-until-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-depth: int +5776 # . prologue +5777 55/push-ebp +5778 89/<- %ebp 4/r32/esp +5779 # . save registers +5780 50/push-eax +5781 51/push-ecx +5782 52/push-edx +5783 53/push-ebx +5784 # ecx = vars +5785 8b/-> *(ebp+0xc) 1/r32/ecx +5786 # var eax: int = vars->top +5787 8b/-> *ecx 0/r32/eax +5788 # var min/ecx: (address (handle var)) = vars->data +5789 81 0/subop/add %ecx 8/imm32 +5790 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] +5791 81 5/subop/subtract %eax 4/imm32 +5792 8d/copy-address *(ecx+eax) 0/r32/eax +5793 # edx = until-block-depth +5794 8b/-> *(ebp+0x10) 2/r32/edx +5795 { +5796 $emit-cleanup-code-until-depth:loop: +5797 # if (curr < min) break +5798 39/compare %eax 1/r32/ecx +5799 0f 82/jump-if-addr< break/disp32 +5800 # var v/ebx: (handle var) = *curr +5801 8b/-> *eax 3/r32/ebx +5802 # if (v->block-depth < until-block-depth) break +5803 39/compare *(ebx+8) 2/r32/edx # Var-block-depth +5804 0f 8c/jump-if-< break/disp32 +5805 # if v is in a register +5806 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register +5807 { +5808 74/jump-if-= break/disp8 +5809 $emit-cleanup-code-until-depth:reclaim-var-in-register: +5810 (emit-indent *(ebp+8) *Curr-block-depth) +5811 (write-buffered *(ebp+8) "8f 0/subop/pop %") +5812 (write-buffered *(ebp+8) *(ebx+0x10)) +5813 (write-buffered *(ebp+8) Newline) +5814 } +5815 # otherwise v is on the stack +5816 { +5817 75/jump-if-!= break/disp8 +5818 $emit-cleanup-code-until-depth:reclaim-var-on-stack: +5819 50/push-eax +5820 (size-of %ebx) # => eax +5821 # don't emit code for labels +5822 3d/compare-eax-and 0/imm32 +5823 74/jump-if-= break/disp8 +5824 # +5825 (emit-indent *(ebp+8) *Curr-block-depth) +5826 (write-buffered *(ebp+8) "81 0/subop/add %esp ") +5827 (print-int32-buffered *(ebp+8) %eax) +5828 (write-buffered *(ebp+8) "/imm32\n") +5829 58/pop-to-eax +5830 } +5831 # curr -= 4 +5832 2d/subtract-from-eax 4/imm32 +5833 e9/jump loop/disp32 +5834 } +5835 $emit-cleanup-code-until-depth:end: +5836 # . restore registers +5837 5b/pop-to-ebx +5838 5a/pop-to-edx +5839 59/pop-to-ecx +5840 58/pop-to-eax +5841 # . epilogue +5842 89/<- %esp 5/r32/ebp +5843 5d/pop-to-ebp +5844 c3/return +5845 +5846 # emit clean-up code for 'vars' until a given label is encountered +5847 # doesn't actually modify 'vars' so we need traverse manually inside the stack +5848 emit-cleanup-code-until-target: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-label: (addr array byte) +5849 # . prologue +5850 55/push-ebp +5851 89/<- %ebp 4/r32/esp +5852 # . save registers +5853 50/push-eax +5854 51/push-ecx +5855 52/push-edx +5856 53/push-ebx +5857 # ecx = vars +5858 8b/-> *(ebp+0xc) 1/r32/ecx +5859 # var eax: int = vars->top +5860 8b/-> *ecx 0/r32/eax +5861 # var min/ecx: (address (handle var)) = vars->data +5862 81 0/subop/add %ecx 8/imm32 +5863 # var curr/edx: (address (handle var)) = &vars->data[vars->top - 4] +5864 81 5/subop/subtract %eax 4/imm32 +5865 8d/copy-address *(ecx+eax) 2/r32/edx +5866 { +5867 $emit-cleanup-code-until-target:loop: +5868 # if (curr < min) break +5869 39/compare %edx 1/r32/ecx +5870 0f 82/jump-if-addr< break/disp32 +5871 # var v/ebx: (handle var) = *curr +5872 8b/-> *edx 3/r32/ebx +5873 # if (v->name == until-block-label) break +5874 (string-equal? *ebx *(ebp+0x10)) # => eax +5875 3d/compare-eax-and 0/imm32/false +5876 0f 85/jump-if-!= break/disp32 +5877 # if v is in a register +5878 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register +5879 { +5880 74/jump-if-= break/disp8 +5881 $emit-cleanup-code-until-target:reclaim-var-in-register: +5882 (emit-indent *(ebp+8) *Curr-block-depth) +5883 (write-buffered *(ebp+8) "8f 0/subop/pop %") +5884 (write-buffered *(ebp+8) *(ebx+0x10)) +5885 (write-buffered *(ebp+8) Newline) +5886 } +5887 # otherwise v is on the stack +5888 { +5889 75/jump-if-!= break/disp8 +5890 $emit-cleanup-code-until-target:reclaim-var-on-stack: +5891 (size-of %ebx) # => eax +5892 # don't emit code for labels +5893 3d/compare-eax-and 0/imm32 +5894 74/jump-if-= break/disp8 +5895 # +5896 (emit-indent *(ebp+8) *Curr-block-depth) +5897 (write-buffered *(ebp+8) "81 0/subop/add %esp ") +5898 (print-int32-buffered *(ebp+8) %eax) +5899 (write-buffered *(ebp+8) "/imm32\n") +5900 } +5901 # curr -= 4 +5902 81 5/subop/subtract %edx 4/imm32 +5903 e9/jump loop/disp32 +5904 } +5905 $emit-cleanup-code-until-target:end: +5906 # . restore registers +5907 5b/pop-to-ebx +5908 5a/pop-to-edx +5909 59/pop-to-ecx +5910 58/pop-to-eax +5911 # . epilogue +5912 89/<- %esp 5/r32/ebp +5913 5d/pop-to-ebp +5914 c3/return +5915 +5916 # clean up global state for 'vars' until some block depth +5917 clean-up-blocks: # vars: (addr stack (handle var)), until-block-depth: int +5918 # . prologue +5919 55/push-ebp +5920 89/<- %ebp 4/r32/esp +5921 # . save registers +5922 50/push-eax +5923 51/push-ecx +5924 56/push-esi +5925 # esi = vars +5926 8b/-> *(ebp+8) 6/r32/esi +5927 # ecx = until-block-depth +5928 8b/-> *(ebp+0xc) 1/r32/ecx +5929 { +5930 $clean-up-blocks:reclaim-loop: +5931 # if (vars->top <= 0) break +5932 81 7/subop/compare *esi 0/imm32 # Stack-top +5933 7e/jump-if-<= break/disp8 +5934 # var v/eax: (handle var) = top(vars) +5935 (top %esi) # => eax +5936 # if (v->block-depth < until-block-depth) break +5937 39/compare *(eax+8) 1/r32/ecx # Var-block-depth +5938 7c/jump-if-< break/disp8 +5939 # if v is on the stack, update Next-local-stack-offset +5940 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register +5941 { +5942 75/jump-if-!= break/disp8 +5943 $clean-up-blocks:reclaim-var-on-stack: +5944 (size-of %eax) # => eax +5945 01/add *Next-local-stack-offset 0/r32/eax +5946 } +5947 (pop %esi) +5948 e9/jump loop/disp32 +5949 } +5950 $clean-up-blocks:end: +5951 # . restore registers +5952 5e/pop-to-esi +5953 59/pop-to-ecx +5954 58/pop-to-eax +5955 # . epilogue +5956 89/<- %esp 5/r32/ebp +5957 5d/pop-to-ebp +5958 c3/return +5959 +5960 emit-subx-var-def: # out: (addr buffered-file), stmt: (handle stmt) +5961 # . prologue +5962 55/push-ebp +5963 89/<- %ebp 4/r32/esp +5964 # . save registers +5965 50/push-eax +5966 51/push-ecx +5967 # eax = stmt +5968 8b/-> *(ebp+0xc) 0/r32/eax +5969 # var n/eax: int = size-of(stmt->var) +5970 (size-of *(eax+4)) # Vardef-var => eax +5971 # while n > 0 +5972 { +5973 3d/compare-eax-with 0/imm32 +5974 7e/jump-if-<= break/disp8 +5975 (emit-indent *(ebp+8) *Curr-block-depth) +5976 (write-buffered *(ebp+8) "68/push 0/imm32\n") +5977 # n -= 4 +5978 2d/subtract-from-eax 4/imm32 +5979 # +5980 eb/jump loop/disp8 +5981 } +5982 $emit-subx-var-def:end: +5983 # . restore registers +5984 59/pop-to-ecx +5985 58/pop-to-eax +5986 # . epilogue +5987 89/<- %esp 5/r32/ebp +5988 5d/pop-to-ebp +5989 c3/return +5990 +5991 emit-subx-stmt: # out: (addr buffered-file), stmt: (handle stmt), primitives: (handle primitive), functions: (handle function) +5992 # . prologue +5993 55/push-ebp +5994 89/<- %ebp 4/r32/esp +5995 # . save registers +5996 50/push-eax +5997 51/push-ecx +5998 # handle some special cases +5999 # ecx = stmt +6000 8b/-> *(ebp+0xc) 1/r32/ecx +6001 +-- 24 lines: # array length ------------------------------------------------------------------------------------------------------------------------------------------------------------ +6025 +-- 33 lines: # index into array -------------------------------------------------------------------------------------------------------------------------------------------------------- +6058 +-- 26 lines: # get field from record --------------------------------------------------------------------------------------------------------------------------------------------------- +6084 # if stmt matches a primitive, emit it +6085 { +6086 $emit-subx-stmt:check-for-primitive: +6087 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => curr/eax +6088 3d/compare-eax-and 0/imm32 +6089 74/jump-if-= break/disp8 +6090 $emit-subx-stmt:primitive: +6091 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr +6092 e9/jump $emit-subx-stmt:end/disp32 +6093 } +6094 # else if stmt matches a function, emit a call to it +6095 { +6096 $emit-subx-stmt:check-for-call: +6097 (find-matching-function *(ebp+0x14) *(ebp+0xc)) # functions, stmt => curr/eax +6098 3d/compare-eax-and 0/imm32 +6099 74/jump-if-= break/disp8 +6100 $emit-subx-stmt:call: +6101 (emit-subx-call *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr +6102 e9/jump $emit-subx-stmt:end/disp32 +6103 } +6104 # else assume it's a SubX function (TODO: how to type-check?!) +6105 (emit-hailmary-call *(ebp+8) *(ebp+0xc)) +6106 $emit-subx-stmt:end: +6107 # . restore registers +6108 59/pop-to-ecx +6109 58/pop-to-eax +6110 # . epilogue +6111 89/<- %esp 5/r32/ebp +6112 5d/pop-to-ebp +6113 c3/return +6114 +6115 $emit-subx-stmt:abort: +6116 # error("couldn't translate '" stmt "'\n") +6117 (write-buffered Stderr "couldn't translate an instruction with operation '") +6118 8b/-> *(ebp+0xc) 0/r32/eax +6119 (write-buffered Stderr *(eax+4)) # Stmt1-operation +6120 (write-buffered Stderr "'\n") +6121 (flush Stderr) +6122 # . syscall(exit, 1) +6123 bb/copy-to-ebx 1/imm32 +6124 b8/copy-to-eax 1/imm32/exit +6125 cd/syscall 0x80/imm8 +6126 # never gets here +6127 +6128 print-mu-get-offset: # out: (addr buffered-file), stmt: (handle stmt) +6129 # . prologue +6130 55/push-ebp +6131 89/<- %ebp 4/r32/esp +6132 # . save registers +6133 50/push-eax +6134 # var second-inout/eax: (handle stmt-var) = stmt->inouts->next +6135 8b/-> *(ebp+0xc) 0/r32/eax +6136 8b/-> *(eax+8) 0/r32/eax # Stmt1-inouts +6137 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next +6138 # var output-var/eax: (handle var) = second-inout->value +6139 8b/-> *eax 0/r32/eax # Stmt-var-value +6140 # print offset +6141 #? (write-buffered Stderr "emitting offset from output var ") +6142 #? (print-int32-buffered Stderr %eax) +6143 #? (write-buffered Stderr Newline) +6144 #? (flush Stderr) +6145 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-offset +6146 $emit-get-offset:end: +6147 # . restore registers +6148 58/pop-to-eax +6149 # . epilogue +6150 89/<- %esp 5/r32/ebp +6151 5d/pop-to-ebp +6152 c3/return +6153 +6154 emit-subx-block: # out: (addr buffered-file), block: (handle block), vars: (addr stack (handle var)) +6155 # . prologue +6156 55/push-ebp +6157 89/<- %ebp 4/r32/esp +6158 # . save registers +6159 50/push-eax +6160 51/push-ecx +6161 56/push-esi +6162 # esi = block +6163 8b/-> *(ebp+0xc) 6/r32/esi +6164 # var stmts/eax: (handle list stmt) = block->statements +6165 8b/-> *(esi+4) 0/r32/eax # Block-stmts +6166 # +6167 { +6168 $emit-subx-block:check-empty: +6169 3d/compare-eax-and 0/imm32 +6170 0f 84/jump-if-= break/disp32 +6171 (emit-indent *(ebp+8) *Curr-block-depth) +6172 (write-buffered *(ebp+8) "{\n") +6173 # var v/ecx: (addr array byte) = block->var->name +6174 8b/-> *(esi+8) 1/r32/ecx # Block-var +6175 (write-buffered *(ebp+8) *ecx) # Var-name +6176 (write-buffered *(ebp+8) ":loop:\n") +6177 ff 0/subop/increment *Curr-block-depth +6178 (push *(ebp+0x10) %ecx) +6179 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10)) +6180 (pop *(ebp+0x10)) # => eax +6181 ff 1/subop/decrement *Curr-block-depth +6182 (emit-indent *(ebp+8) *Curr-block-depth) +6183 (write-buffered *(ebp+8) "}\n") +6184 (write-buffered *(ebp+8) *ecx) # Var-name +6185 (write-buffered *(ebp+8) ":break:\n") +6186 } +6187 $emit-subx-block:end: +6188 # . restore registers +6189 5e/pop-to-esi +6190 59/pop-to-ecx +6191 58/pop-to-eax +6192 # . epilogue +6193 89/<- %esp 5/r32/ebp +6194 5d/pop-to-ebp +6195 c3/return +6196 +6197 # Primitives supported +6198 # For each operation, put variants with hard-coded registers before flexible ones. +6199 == data +6200 Primitives: +6201 # - increment/decrement +6202 _Primitive-inc-eax: +6203 # var/eax <- increment => 40/increment-eax +6204 "increment"/imm32/name +6205 0/imm32/no-inouts +6206 Single-int-var-in-eax/imm32/outputs +6207 "40/increment-eax"/imm32/subx-name +6208 0/imm32/no-rm32 +6209 0/imm32/no-r32 +6210 0/imm32/no-imm32 +6211 0/imm32/no-disp32 +6212 0/imm32/output-is-write-only +6213 _Primitive-inc-ecx/imm32/next +6214 _Primitive-inc-ecx: +6215 # var/ecx <- increment => 41/increment-ecx +6216 "increment"/imm32/name +6217 0/imm32/no-inouts +6218 Single-int-var-in-ecx/imm32/outputs +6219 "41/increment-ecx"/imm32/subx-name +6220 0/imm32/no-rm32 +6221 0/imm32/no-r32 +6222 0/imm32/no-imm32 +6223 0/imm32/no-disp32 +6224 0/imm32/output-is-write-only +6225 _Primitive-inc-edx/imm32/next +6226 _Primitive-inc-edx: +6227 # var/edx <- increment => 42/increment-edx +6228 "increment"/imm32/name +6229 0/imm32/no-inouts +6230 Single-int-var-in-edx/imm32/outputs +6231 "42/increment-edx"/imm32/subx-name +6232 0/imm32/no-rm32 +6233 0/imm32/no-r32 +6234 0/imm32/no-imm32 +6235 0/imm32/no-disp32 +6236 0/imm32/output-is-write-only +6237 _Primitive-inc-ebx/imm32/next +6238 _Primitive-inc-ebx: +6239 # var/ebx <- increment => 43/increment-ebx +6240 "increment"/imm32/name +6241 0/imm32/no-inouts +6242 Single-int-var-in-ebx/imm32/outputs +6243 "43/increment-ebx"/imm32/subx-name +6244 0/imm32/no-rm32 +6245 0/imm32/no-r32 +6246 0/imm32/no-imm32 +6247 0/imm32/no-disp32 +6248 0/imm32/output-is-write-only +6249 _Primitive-inc-esi/imm32/next +6250 _Primitive-inc-esi: +6251 # var/esi <- increment => 46/increment-esi +6252 "increment"/imm32/name +6253 0/imm32/no-inouts +6254 Single-int-var-in-esi/imm32/outputs +6255 "46/increment-esi"/imm32/subx-name +6256 0/imm32/no-rm32 +6257 0/imm32/no-r32 +6258 0/imm32/no-imm32 +6259 0/imm32/no-disp32 +6260 0/imm32/output-is-write-only +6261 _Primitive-inc-edi/imm32/next +6262 _Primitive-inc-edi: +6263 # var/edi <- increment => 47/increment-edi +6264 "increment"/imm32/name +6265 0/imm32/no-inouts +6266 Single-int-var-in-edi/imm32/outputs +6267 "47/increment-edi"/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/output-is-write-only +6273 _Primitive-dec-eax/imm32/next +6274 _Primitive-dec-eax: +6275 # var/eax <- decrement => 48/decrement-eax +6276 "decrement"/imm32/name +6277 0/imm32/no-inouts +6278 Single-int-var-in-eax/imm32/outputs +6279 "48/decrement-eax"/imm32/subx-name +6280 0/imm32/no-rm32 +6281 0/imm32/no-r32 +6282 0/imm32/no-imm32 +6283 0/imm32/no-disp32 +6284 0/imm32/output-is-write-only +6285 _Primitive-dec-ecx/imm32/next +6286 _Primitive-dec-ecx: +6287 # var/ecx <- decrement => 49/decrement-ecx +6288 "decrement"/imm32/name +6289 0/imm32/no-inouts +6290 Single-int-var-in-ecx/imm32/outputs +6291 "49/decrement-ecx"/imm32/subx-name +6292 0/imm32/no-rm32 +6293 0/imm32/no-r32 +6294 0/imm32/no-imm32 +6295 0/imm32/no-disp32 +6296 0/imm32/output-is-write-only +6297 _Primitive-dec-edx/imm32/next +6298 _Primitive-dec-edx: +6299 # var/edx <- decrement => 4a/decrement-edx +6300 "decrement"/imm32/name +6301 0/imm32/no-inouts +6302 Single-int-var-in-edx/imm32/outputs +6303 "4a/decrement-edx"/imm32/subx-name +6304 0/imm32/no-rm32 +6305 0/imm32/no-r32 +6306 0/imm32/no-imm32 +6307 0/imm32/no-disp32 +6308 0/imm32/output-is-write-only +6309 _Primitive-dec-ebx/imm32/next +6310 _Primitive-dec-ebx: +6311 # var/ebx <- decrement => 4b/decrement-ebx +6312 "decrement"/imm32/name +6313 0/imm32/no-inouts +6314 Single-int-var-in-ebx/imm32/outputs +6315 "4b/decrement-ebx"/imm32/subx-name +6316 0/imm32/no-rm32 +6317 0/imm32/no-r32 +6318 0/imm32/no-imm32 +6319 0/imm32/no-disp32 +6320 0/imm32/output-is-write-only +6321 _Primitive-dec-esi/imm32/next +6322 _Primitive-dec-esi: +6323 # var/esi <- decrement => 4e/decrement-esi +6324 "decrement"/imm32/name +6325 0/imm32/no-inouts +6326 Single-int-var-in-esi/imm32/outputs +6327 "4e/decrement-esi"/imm32/subx-name +6328 0/imm32/no-rm32 +6329 0/imm32/no-r32 +6330 0/imm32/no-imm32 +6331 0/imm32/no-disp32 +6332 0/imm32/output-is-write-only +6333 _Primitive-dec-edi/imm32/next +6334 _Primitive-dec-edi: +6335 # var/edi <- decrement => 4f/decrement-edi +6336 "decrement"/imm32/name +6337 0/imm32/no-inouts +6338 Single-int-var-in-edi/imm32/outputs +6339 "4f/decrement-edi"/imm32/subx-name +6340 0/imm32/no-rm32 +6341 0/imm32/no-r32 +6342 0/imm32/no-imm32 +6343 0/imm32/no-disp32 +6344 0/imm32/output-is-write-only +6345 _Primitive-inc-mem/imm32/next +6346 _Primitive-inc-mem: +6347 # increment var => ff 0/subop/increment *(ebp+__) +6348 "increment"/imm32/name +6349 Single-int-var-in-mem/imm32/inouts +6350 0/imm32/no-outputs +6351 "ff 0/subop/increment"/imm32/subx-name +6352 1/imm32/rm32-is-first-inout +6353 0/imm32/no-r32 +6354 0/imm32/no-imm32 +6355 0/imm32/no-disp32 +6356 0/imm32/output-is-write-only +6357 _Primitive-inc-reg/imm32/next +6358 _Primitive-inc-reg: +6359 # var/reg <- increment => ff 0/subop/increment %__ +6360 "increment"/imm32/name +6361 0/imm32/no-inouts +6362 Single-int-var-in-some-register/imm32/outputs +6363 "ff 0/subop/increment"/imm32/subx-name +6364 3/imm32/rm32-is-first-output +6365 0/imm32/no-r32 +6366 0/imm32/no-imm32 +6367 0/imm32/no-disp32 +6368 0/imm32/output-is-write-only +6369 _Primitive-dec-mem/imm32/next +6370 _Primitive-dec-mem: +6371 # decrement var => ff 1/subop/decrement *(ebp+__) +6372 "decrement"/imm32/name +6373 Single-int-var-in-mem/imm32/inouts +6374 0/imm32/no-outputs +6375 "ff 1/subop/decrement"/imm32/subx-name +6376 1/imm32/rm32-is-first-inout +6377 0/imm32/no-r32 +6378 0/imm32/no-imm32 +6379 0/imm32/no-disp32 +6380 0/imm32/output-is-write-only +6381 _Primitive-dec-reg/imm32/next +6382 _Primitive-dec-reg: +6383 # var/reg <- decrement => ff 1/subop/decrement %__ +6384 "decrement"/imm32/name +6385 0/imm32/no-inouts +6386 Single-int-var-in-some-register/imm32/outputs +6387 "ff 1/subop/decrement"/imm32/subx-name +6388 3/imm32/rm32-is-first-output +6389 0/imm32/no-r32 +6390 0/imm32/no-imm32 +6391 0/imm32/no-disp32 +6392 0/imm32/output-is-write-only +6393 _Primitive-add-to-eax/imm32/next +6394 # - add +6395 _Primitive-add-to-eax: +6396 # var/eax <- add lit => 05/add-to-eax lit/imm32 +6397 "add"/imm32/name +6398 Single-lit-var/imm32/inouts +6399 Single-int-var-in-eax/imm32/outputs +6400 "05/add-to-eax"/imm32/subx-name +6401 0/imm32/no-rm32 +6402 0/imm32/no-r32 +6403 1/imm32/imm32-is-first-inout +6404 0/imm32/no-disp32 +6405 0/imm32/output-is-write-only +6406 _Primitive-add-reg-to-reg/imm32/next +6407 _Primitive-add-reg-to-reg: +6408 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 +6409 "add"/imm32/name +6410 Single-int-var-in-some-register/imm32/inouts +6411 Single-int-var-in-some-register/imm32/outputs +6412 "01/add-to"/imm32/subx-name +6413 3/imm32/rm32-is-first-output +6414 1/imm32/r32-is-first-inout +6415 0/imm32/no-imm32 +6416 0/imm32/no-disp32 +6417 0/imm32/output-is-write-only +6418 _Primitive-add-reg-to-mem/imm32/next +6419 _Primitive-add-reg-to-mem: +6420 # add-to var1 var2/reg => 01/add-to var1 var2/r32 +6421 "add-to"/imm32/name +6422 Two-args-int-stack-int-reg/imm32/inouts +6423 0/imm32/outputs +6424 "01/add-to"/imm32/subx-name +6425 1/imm32/rm32-is-first-inout +6426 2/imm32/r32-is-second-inout +6427 0/imm32/no-imm32 +6428 0/imm32/no-disp32 +6429 0/imm32/output-is-write-only +6430 _Primitive-add-mem-to-reg/imm32/next +6431 _Primitive-add-mem-to-reg: +6432 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 +6433 "add"/imm32/name +6434 Single-int-var-in-mem/imm32/inouts +6435 Single-int-var-in-some-register/imm32/outputs +6436 "03/add"/imm32/subx-name +6437 1/imm32/rm32-is-first-inout +6438 3/imm32/r32-is-first-output +6439 0/imm32/no-imm32 +6440 0/imm32/no-disp32 +6441 0/imm32/output-is-write-only +6442 _Primitive-add-lit-to-reg/imm32/next +6443 _Primitive-add-lit-to-reg: +6444 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 +6445 "add"/imm32/name +6446 Single-lit-var/imm32/inouts +6447 Single-int-var-in-some-register/imm32/outputs +6448 "81 0/subop/add"/imm32/subx-name +6449 3/imm32/rm32-is-first-output +6450 0/imm32/no-r32 +6451 1/imm32/imm32-is-first-inout +6452 0/imm32/no-disp32 +6453 0/imm32/output-is-write-only +6454 _Primitive-add-lit-to-mem/imm32/next +6455 _Primitive-add-lit-to-mem: +6456 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 +6457 "add-to"/imm32/name +6458 Int-var-and-literal/imm32/inouts +6459 0/imm32/outputs +6460 "81 0/subop/add"/imm32/subx-name +6461 1/imm32/rm32-is-first-inout +6462 0/imm32/no-r32 +6463 2/imm32/imm32-is-second-inout +6464 0/imm32/no-disp32 +6465 0/imm32/output-is-write-only +6466 _Primitive-subtract-from-eax/imm32/next +6467 # - subtract +6468 _Primitive-subtract-from-eax: +6469 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 +6470 "subtract"/imm32/name +6471 Single-lit-var/imm32/inouts +6472 Single-int-var-in-eax/imm32/outputs +6473 "2d/subtract-from-eax"/imm32/subx-name +6474 0/imm32/no-rm32 +6475 0/imm32/no-r32 +6476 1/imm32/imm32-is-first-inout +6477 0/imm32/no-disp32 +6478 0/imm32/output-is-write-only +6479 _Primitive-subtract-reg-from-reg/imm32/next +6480 _Primitive-subtract-reg-from-reg: +6481 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 +6482 "subtract"/imm32/name +6483 Single-int-var-in-some-register/imm32/inouts +6484 Single-int-var-in-some-register/imm32/outputs +6485 "29/subtract-from"/imm32/subx-name +6486 3/imm32/rm32-is-first-output +6487 1/imm32/r32-is-first-inout 6488 0/imm32/no-imm32 6489 0/imm32/no-disp32 -6490 0/imm32/no-output -6491 _Primitive-break-if-<=/imm32/next -6492 _Primitive-break-if-<=: -6493 "break-if-<="/imm32/name -6494 0/imm32/inouts -6495 0/imm32/outputs -6496 "0f 8e/jump-if-<= break/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-break-if->/imm32/next -6503 _Primitive-break-if->: -6504 "break-if->"/imm32/name -6505 0/imm32/inouts -6506 0/imm32/outputs -6507 "0f 8f/jump-if-> break/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-break/imm32/next -6514 _Primitive-break: -6515 "break"/imm32/name -6516 0/imm32/inouts -6517 0/imm32/outputs -6518 "e9/jump break/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-addr</imm32/next -6525 _Primitive-loop-if-addr<: -6526 "loop-if-addr<"/imm32/name -6527 0/imm32/inouts -6528 0/imm32/outputs -6529 "0f 82/jump-if-addr< 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-addr>=/imm32/next -6536 _Primitive-loop-if-addr>=: -6537 "loop-if-addr>="/imm32/name -6538 0/imm32/inouts -6539 0/imm32/outputs -6540 "0f 83/jump-if-addr>= 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 84/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-if-!=/imm32/next -6558 _Primitive-loop-if-!=: -6559 "loop-if-!="/imm32/name -6560 0/imm32/inouts -6561 0/imm32/outputs -6562 "0f 85/jump-if-!= 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-loop-if-addr<=/imm32/next -6569 _Primitive-loop-if-addr<=: -6570 "loop-if-addr<="/imm32/name -6571 0/imm32/inouts -6572 0/imm32/outputs -6573 "0f 86/jump-if-addr<= loop/disp32"/imm32/subx-name -6574 0/imm32/no-rm32 -6575 0/imm32/no-r32 -6576 0/imm32/no-imm32 -6577 0/imm32/no-disp32 -6578 0/imm32/no-output -6579 _Primitive-loop-if-addr>/imm32/next -6580 _Primitive-loop-if-addr>: -6581 "loop-if-addr>"/imm32/name -6582 0/imm32/inouts -6583 0/imm32/outputs -6584 "0f 87/jump-if-addr> loop/disp32"/imm32/subx-name -6585 0/imm32/no-rm32 -6586 0/imm32/no-r32 -6587 0/imm32/no-imm32 -6588 0/imm32/no-disp32 -6589 0/imm32/no-output -6590 _Primitive-loop-if-</imm32/next -6591 _Primitive-loop-if-<: -6592 "loop-if-<"/imm32/name -6593 0/imm32/inouts -6594 0/imm32/outputs -6595 "0f 8c/jump-if-< loop/disp32"/imm32/subx-name -6596 0/imm32/no-rm32 -6597 0/imm32/no-r32 -6598 0/imm32/no-imm32 -6599 0/imm32/no-disp32 -6600 0/imm32/no-output -6601 _Primitive-loop-if->=/imm32/next -6602 _Primitive-loop-if->=: -6603 "loop-if->="/imm32/name -6604 0/imm32/inouts +6490 0/imm32/output-is-write-only +6491 _Primitive-subtract-reg-from-mem/imm32/next +6492 _Primitive-subtract-reg-from-mem: +6493 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 +6494 "subtract-from"/imm32/name +6495 Two-args-int-stack-int-reg/imm32/inouts +6496 0/imm32/outputs +6497 "29/subtract-from"/imm32/subx-name +6498 1/imm32/rm32-is-first-inout +6499 2/imm32/r32-is-second-inout +6500 0/imm32/no-imm32 +6501 0/imm32/no-disp32 +6502 0/imm32/output-is-write-only +6503 _Primitive-subtract-mem-from-reg/imm32/next +6504 _Primitive-subtract-mem-from-reg: +6505 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 +6506 "subtract"/imm32/name +6507 Single-int-var-in-mem/imm32/inouts +6508 Single-int-var-in-some-register/imm32/outputs +6509 "2b/subtract"/imm32/subx-name +6510 1/imm32/rm32-is-first-inout +6511 3/imm32/r32-is-first-output +6512 0/imm32/no-imm32 +6513 0/imm32/no-disp32 +6514 0/imm32/output-is-write-only +6515 _Primitive-subtract-lit-from-reg/imm32/next +6516 _Primitive-subtract-lit-from-reg: +6517 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 +6518 "subtract"/imm32/name +6519 Single-lit-var/imm32/inouts +6520 Single-int-var-in-some-register/imm32/outputs +6521 "81 5/subop/subtract"/imm32/subx-name +6522 3/imm32/rm32-is-first-output +6523 0/imm32/no-r32 +6524 1/imm32/imm32-is-first-inout +6525 0/imm32/no-disp32 +6526 0/imm32/output-is-write-only +6527 _Primitive-subtract-lit-from-mem/imm32/next +6528 _Primitive-subtract-lit-from-mem: +6529 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 +6530 "subtract-from"/imm32/name +6531 Int-var-and-literal/imm32/inouts +6532 0/imm32/outputs +6533 "81 5/subop/subtract"/imm32/subx-name +6534 1/imm32/rm32-is-first-inout +6535 0/imm32/no-r32 +6536 2/imm32/imm32-is-first-inout +6537 0/imm32/no-disp32 +6538 0/imm32/output-is-write-only +6539 _Primitive-and-with-eax/imm32/next +6540 # - and +6541 _Primitive-and-with-eax: +6542 # var/eax <- and lit => 25/and-with-eax lit/imm32 +6543 "and"/imm32/name +6544 Single-lit-var/imm32/inouts +6545 Single-int-var-in-eax/imm32/outputs +6546 "25/and-with-eax"/imm32/subx-name +6547 0/imm32/no-rm32 +6548 0/imm32/no-r32 +6549 1/imm32/imm32-is-first-inout +6550 0/imm32/no-disp32 +6551 0/imm32/output-is-write-only +6552 _Primitive-and-reg-with-reg/imm32/next +6553 _Primitive-and-reg-with-reg: +6554 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 +6555 "and"/imm32/name +6556 Single-int-var-in-some-register/imm32/inouts +6557 Single-int-var-in-some-register/imm32/outputs +6558 "21/and-with"/imm32/subx-name +6559 3/imm32/rm32-is-first-output +6560 1/imm32/r32-is-first-inout +6561 0/imm32/no-imm32 +6562 0/imm32/no-disp32 +6563 0/imm32/output-is-write-only +6564 _Primitive-and-reg-with-mem/imm32/next +6565 _Primitive-and-reg-with-mem: +6566 # and-with var1 var2/reg => 21/and-with var1 var2/r32 +6567 "and-with"/imm32/name +6568 Two-args-int-stack-int-reg/imm32/inouts +6569 0/imm32/outputs +6570 "21/and-with"/imm32/subx-name +6571 1/imm32/rm32-is-first-inout +6572 2/imm32/r32-is-second-inout +6573 0/imm32/no-imm32 +6574 0/imm32/no-disp32 +6575 0/imm32/output-is-write-only +6576 _Primitive-and-mem-with-reg/imm32/next +6577 _Primitive-and-mem-with-reg: +6578 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 +6579 "and"/imm32/name +6580 Single-int-var-in-mem/imm32/inouts +6581 Single-int-var-in-some-register/imm32/outputs +6582 "23/and"/imm32/subx-name +6583 1/imm32/rm32-is-first-inout +6584 3/imm32/r32-is-first-output +6585 0/imm32/no-imm32 +6586 0/imm32/no-disp32 +6587 0/imm32/output-is-write-only +6588 _Primitive-and-lit-with-reg/imm32/next +6589 _Primitive-and-lit-with-reg: +6590 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 +6591 "and"/imm32/name +6592 Single-lit-var/imm32/inouts +6593 Single-int-var-in-some-register/imm32/outputs +6594 "81 4/subop/and"/imm32/subx-name +6595 3/imm32/rm32-is-first-output +6596 0/imm32/no-r32 +6597 1/imm32/imm32-is-first-inout +6598 0/imm32/no-disp32 +6599 0/imm32/output-is-write-only +6600 _Primitive-and-lit-with-mem/imm32/next +6601 _Primitive-and-lit-with-mem: +6602 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 +6603 "and-with"/imm32/name +6604 Int-var-and-literal/imm32/inouts 6605 0/imm32/outputs -6606 "0f 8d/jump-if->= loop/disp32"/imm32/subx-name -6607 0/imm32/no-rm32 +6606 "81 4/subop/and"/imm32/subx-name +6607 1/imm32/rm32-is-first-inout 6608 0/imm32/no-r32 -6609 0/imm32/no-imm32 +6609 2/imm32/imm32-is-first-inout 6610 0/imm32/no-disp32 -6611 0/imm32/no-output -6612 _Primitive-loop-if-<=/imm32/next -6613 _Primitive-loop-if-<=: -6614 "loop-if-<="/imm32/name -6615 0/imm32/inouts -6616 0/imm32/outputs -6617 "0f 8e/jump-if-<= loop/disp32"/imm32/subx-name -6618 0/imm32/no-rm32 -6619 0/imm32/no-r32 -6620 0/imm32/no-imm32 -6621 0/imm32/no-disp32 -6622 0/imm32/no-output -6623 _Primitive-loop-if->/imm32/next -6624 _Primitive-loop-if->: -6625 "loop-if->"/imm32/name -6626 0/imm32/inouts -6627 0/imm32/outputs -6628 "0f 8f/jump-if-> loop/disp32"/imm32/subx-name -6629 0/imm32/no-rm32 -6630 0/imm32/no-r32 -6631 0/imm32/no-imm32 -6632 0/imm32/no-disp32 -6633 0/imm32/no-output -6634 _Primitive-loop/imm32/next # we probably don't need an unconditional break -6635 _Primitive-loop: -6636 "loop"/imm32/name -6637 0/imm32/inouts -6638 0/imm32/outputs -6639 "e9/jump loop/disp32"/imm32/subx-name -6640 0/imm32/no-rm32 -6641 0/imm32/no-r32 -6642 0/imm32/no-imm32 -6643 0/imm32/no-disp32 -6644 0/imm32/no-output -6645 _Primitive-break-if-addr<-named/imm32/next -6646 # - branches to named blocks -6647 _Primitive-break-if-addr<-named: -6648 "break-if-addr<"/imm32/name -6649 Single-lit-var/imm32/inouts -6650 0/imm32/outputs -6651 "0f 82/jump-if-addr<"/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-addr>=-named/imm32/next -6658 _Primitive-break-if-addr>=-named: -6659 "break-if-addr>="/imm32/name -6660 Single-lit-var/imm32/inouts -6661 0/imm32/outputs -6662 "0f 83/jump-if-addr>="/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 84/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-if-!=-named/imm32/next -6680 _Primitive-break-if-!=-named: -6681 "break-if-!="/imm32/name -6682 Single-lit-var/imm32/inouts -6683 0/imm32/outputs -6684 "0f 85/jump-if-!="/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-break-if-addr<=-named/imm32/next -6691 _Primitive-break-if-addr<=-named: -6692 "break-if-addr<="/imm32/name -6693 Single-lit-var/imm32/inouts -6694 0/imm32/outputs -6695 "0f 86/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-break-if-addr>-named/imm32/next -6702 _Primitive-break-if-addr>-named: -6703 "break-if-addr>"/imm32/name -6704 Single-lit-var/imm32/inouts -6705 0/imm32/outputs -6706 "0f 87/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-break-if-<-named/imm32/next -6713 _Primitive-break-if-<-named: -6714 "break-if-<"/imm32/name -6715 Single-lit-var/imm32/inouts -6716 0/imm32/outputs -6717 "0f 8c/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-break-if->=-named/imm32/next -6724 _Primitive-break-if->=-named: -6725 "break-if->="/imm32/name -6726 Single-lit-var/imm32/inouts -6727 0/imm32/outputs -6728 "0f 8d/jump-if->="/imm32/subx-name -6729 0/imm32/no-rm32 -6730 0/imm32/no-r32 +6611 0/imm32/output-is-write-only +6612 _Primitive-or-with-eax/imm32/next +6613 # - or +6614 _Primitive-or-with-eax: +6615 # var/eax <- or lit => 0d/or-with-eax lit/imm32 +6616 "or"/imm32/name +6617 Single-lit-var/imm32/inouts +6618 Single-int-var-in-eax/imm32/outputs +6619 "0d/or-with-eax"/imm32/subx-name +6620 0/imm32/no-rm32 +6621 0/imm32/no-r32 +6622 1/imm32/imm32-is-first-inout +6623 0/imm32/no-disp32 +6624 0/imm32/output-is-write-only +6625 _Primitive-or-reg-with-reg/imm32/next +6626 _Primitive-or-reg-with-reg: +6627 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 +6628 "or"/imm32/name +6629 Single-int-var-in-some-register/imm32/inouts +6630 Single-int-var-in-some-register/imm32/outputs +6631 "09/or-with"/imm32/subx-name +6632 3/imm32/rm32-is-first-output +6633 1/imm32/r32-is-first-inout +6634 0/imm32/no-imm32 +6635 0/imm32/no-disp32 +6636 0/imm32/output-is-write-only +6637 _Primitive-or-reg-with-mem/imm32/next +6638 _Primitive-or-reg-with-mem: +6639 # or-with var1 var2/reg => 09/or-with var1 var2/r32 +6640 "or-with"/imm32/name +6641 Two-args-int-stack-int-reg/imm32/inouts +6642 0/imm32/outputs +6643 "09/or-with"/imm32/subx-name +6644 1/imm32/rm32-is-first-inout +6645 2/imm32/r32-is-second-inout +6646 0/imm32/no-imm32 +6647 0/imm32/no-disp32 +6648 0/imm32/output-is-write-only +6649 _Primitive-or-mem-with-reg/imm32/next +6650 _Primitive-or-mem-with-reg: +6651 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 +6652 "or"/imm32/name +6653 Single-int-var-in-mem/imm32/inouts +6654 Single-int-var-in-some-register/imm32/outputs +6655 "0b/or"/imm32/subx-name +6656 1/imm32/rm32-is-first-inout +6657 3/imm32/r32-is-first-output +6658 0/imm32/no-imm32 +6659 0/imm32/no-disp32 +6660 0/imm32/output-is-write-only +6661 _Primitive-or-lit-with-reg/imm32/next +6662 _Primitive-or-lit-with-reg: +6663 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 +6664 "or"/imm32/name +6665 Single-lit-var/imm32/inouts +6666 Single-int-var-in-some-register/imm32/outputs +6667 "81 1/subop/or"/imm32/subx-name +6668 3/imm32/rm32-is-first-output +6669 0/imm32/no-r32 +6670 1/imm32/imm32-is-first-inout +6671 0/imm32/no-disp32 +6672 0/imm32/output-is-write-only +6673 _Primitive-or-lit-with-mem/imm32/next +6674 _Primitive-or-lit-with-mem: +6675 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 +6676 "or-with"/imm32/name +6677 Int-var-and-literal/imm32/inouts +6678 0/imm32/outputs +6679 "81 1/subop/or"/imm32/subx-name +6680 1/imm32/rm32-is-first-inout +6681 0/imm32/no-r32 +6682 2/imm32/imm32-is-second-inout +6683 0/imm32/no-disp32 +6684 0/imm32/output-is-write-only +6685 _Primitive-xor-with-eax/imm32/next +6686 # - xor +6687 _Primitive-xor-with-eax: +6688 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 +6689 "xor"/imm32/name +6690 Single-lit-var/imm32/inouts +6691 Single-int-var-in-eax/imm32/outputs +6692 "35/xor-with-eax"/imm32/subx-name +6693 0/imm32/no-rm32 +6694 0/imm32/no-r32 +6695 1/imm32/imm32-is-first-inout +6696 0/imm32/no-disp32 +6697 0/imm32/output-is-write-only +6698 _Primitive-xor-reg-with-reg/imm32/next +6699 _Primitive-xor-reg-with-reg: +6700 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 +6701 "xor"/imm32/name +6702 Single-int-var-in-some-register/imm32/inouts +6703 Single-int-var-in-some-register/imm32/outputs +6704 "31/xor-with"/imm32/subx-name +6705 3/imm32/rm32-is-first-output +6706 1/imm32/r32-is-first-inout +6707 0/imm32/no-imm32 +6708 0/imm32/no-disp32 +6709 0/imm32/output-is-write-only +6710 _Primitive-xor-reg-with-mem/imm32/next +6711 _Primitive-xor-reg-with-mem: +6712 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 +6713 "xor-with"/imm32/name +6714 Two-args-int-stack-int-reg/imm32/inouts +6715 0/imm32/outputs +6716 "31/xor-with"/imm32/subx-name +6717 1/imm32/rm32-is-first-inout +6718 2/imm32/r32-is-second-inout +6719 0/imm32/no-imm32 +6720 0/imm32/no-disp32 +6721 0/imm32/output-is-write-only +6722 _Primitive-xor-mem-with-reg/imm32/next +6723 _Primitive-xor-mem-with-reg: +6724 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 +6725 "xor"/imm32/name +6726 Single-int-var-in-mem/imm32/inouts +6727 Single-int-var-in-some-register/imm32/outputs +6728 "33/xor"/imm32/subx-name +6729 1/imm32/rm32-is-first-inout +6730 3/imm32/r32-is-first-output 6731 0/imm32/no-imm32 -6732 1/imm32/disp32-is-first-inout -6733 0/imm32/no-output -6734 _Primitive-break-if-<=-named/imm32/next -6735 _Primitive-break-if-<=-named: -6736 "break-if-<="/imm32/name -6737 Single-lit-var/imm32/inouts -6738 0/imm32/outputs -6739 "0f 8e/jump-if-<="/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-break-if->-named/imm32/next -6746 _Primitive-break-if->-named: -6747 "break-if->"/imm32/name -6748 Single-lit-var/imm32/inouts -6749 0/imm32/outputs -6750 "0f 8f/jump-if->"/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-break-named/imm32/next -6757 _Primitive-break-named: -6758 "break"/imm32/name -6759 Single-lit-var/imm32/inouts -6760 0/imm32/outputs -6761 "e9/jump"/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-addr<-named/imm32/next -6768 _Primitive-loop-if-addr<-named: -6769 "loop-if-addr<"/imm32/name -6770 Single-lit-var/imm32/inouts -6771 0/imm32/outputs -6772 "0f 82/jump-if-addr<"/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-addr>=-named/imm32/next -6779 _Primitive-loop-if-addr>=-named: -6780 "loop-if-addr>="/imm32/name -6781 Single-lit-var/imm32/inouts -6782 0/imm32/outputs -6783 "0f 83/jump-if-addr>="/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 84/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-if-!=-named/imm32/next -6801 _Primitive-loop-if-!=-named: -6802 "loop-if-!="/imm32/name -6803 Single-lit-var/imm32/inouts -6804 0/imm32/outputs -6805 "0f 85/jump-if-!="/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 _Primitive-loop-if-addr<=-named/imm32/next -6812 _Primitive-loop-if-addr<=-named: -6813 "loop-if-addr<="/imm32/name -6814 Single-lit-var/imm32/inouts -6815 0/imm32/outputs -6816 "0f 86/jump-if-addr<="/imm32/subx-name -6817 0/imm32/no-rm32 -6818 0/imm32/no-r32 -6819 0/imm32/no-imm32 -6820 1/imm32/disp32-is-first-inout -6821 0/imm32/no-output -6822 _Primitive-loop-if-addr>-named/imm32/next -6823 _Primitive-loop-if-addr>-named: -6824 "loop-if-addr>"/imm32/name -6825 Single-lit-var/imm32/inouts -6826 0/imm32/outputs -6827 "0f 87/jump-if-addr>"/imm32/subx-name -6828 0/imm32/no-rm32 -6829 0/imm32/no-r32 -6830 0/imm32/no-imm32 -6831 1/imm32/disp32-is-first-inout -6832 0/imm32/no-output -6833 _Primitive-loop-if-<-named/imm32/next -6834 _Primitive-loop-if-<-named: -6835 "loop-if-<"/imm32/name -6836 Single-lit-var/imm32/inouts -6837 0/imm32/outputs -6838 "0f 8c/jump-if-<"/imm32/subx-name -6839 0/imm32/no-rm32 -6840 0/imm32/no-r32 -6841 0/imm32/no-imm32 -6842 1/imm32/disp32-is-first-inout -6843 0/imm32/no-output -6844 _Primitive-loop-if->=-named/imm32/next -6845 _Primitive-loop-if->=-named: -6846 "loop-if->="/imm32/name -6847 Single-lit-var/imm32/inouts +6732 0/imm32/no-disp32 +6733 0/imm32/output-is-write-only +6734 _Primitive-xor-lit-with-reg/imm32/next +6735 _Primitive-xor-lit-with-reg: +6736 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 +6737 "xor"/imm32/name +6738 Single-lit-var/imm32/inouts +6739 Single-int-var-in-some-register/imm32/outputs +6740 "81 6/subop/xor"/imm32/subx-name +6741 3/imm32/rm32-is-first-output +6742 0/imm32/no-r32 +6743 1/imm32/imm32-is-first-inout +6744 0/imm32/no-disp32 +6745 0/imm32/output-is-write-only +6746 _Primitive-xor-lit-with-mem/imm32/next +6747 _Primitive-xor-lit-with-mem: +6748 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 +6749 "xor-with"/imm32/name +6750 Int-var-and-literal/imm32/inouts +6751 0/imm32/outputs +6752 "81 6/subop/xor"/imm32/subx-name +6753 1/imm32/rm32-is-first-inout +6754 0/imm32/no-r32 +6755 2/imm32/imm32-is-first-inout +6756 0/imm32/no-disp32 +6757 0/imm32/output-is-write-only +6758 _Primitive-copy-to-eax/imm32/next +6759 # - copy +6760 _Primitive-copy-to-eax: +6761 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 +6762 "copy"/imm32/name +6763 Single-lit-var/imm32/inouts +6764 Single-int-var-in-eax/imm32/outputs +6765 "b8/copy-to-eax"/imm32/subx-name +6766 0/imm32/no-rm32 +6767 0/imm32/no-r32 +6768 1/imm32/imm32-is-first-inout +6769 0/imm32/no-disp32 +6770 1/imm32/output-is-write-only +6771 _Primitive-copy-to-ecx/imm32/next +6772 _Primitive-copy-to-ecx: +6773 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 +6774 "copy"/imm32/name +6775 Single-lit-var/imm32/inouts +6776 Single-int-var-in-ecx/imm32/outputs +6777 "b9/copy-to-ecx"/imm32/subx-name +6778 0/imm32/no-rm32 +6779 0/imm32/no-r32 +6780 1/imm32/imm32-is-first-inout +6781 0/imm32/no-disp32 +6782 1/imm32/output-is-write-only +6783 _Primitive-copy-to-edx/imm32/next +6784 _Primitive-copy-to-edx: +6785 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 +6786 "copy"/imm32/name +6787 Single-lit-var/imm32/inouts +6788 Single-int-var-in-edx/imm32/outputs +6789 "ba/copy-to-edx"/imm32/subx-name +6790 0/imm32/no-rm32 +6791 0/imm32/no-r32 +6792 1/imm32/imm32-is-first-inout +6793 0/imm32/no-disp32 +6794 1/imm32/output-is-write-only +6795 _Primitive-copy-to-ebx/imm32/next +6796 _Primitive-copy-to-ebx: +6797 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 +6798 "copy"/imm32/name +6799 Single-lit-var/imm32/inouts +6800 Single-int-var-in-ebx/imm32/outputs +6801 "bb/copy-to-ebx"/imm32/subx-name +6802 0/imm32/no-rm32 +6803 0/imm32/no-r32 +6804 1/imm32/imm32-is-first-inout +6805 0/imm32/no-disp32 +6806 1/imm32/output-is-write-only +6807 _Primitive-copy-to-esi/imm32/next +6808 _Primitive-copy-to-esi: +6809 # var/esi <- copy lit => be/copy-to-esi lit/imm32 +6810 "copy"/imm32/name +6811 Single-lit-var/imm32/inouts +6812 Single-int-var-in-esi/imm32/outputs +6813 "be/copy-to-esi"/imm32/subx-name +6814 0/imm32/no-rm32 +6815 0/imm32/no-r32 +6816 1/imm32/imm32-is-first-inout +6817 0/imm32/no-disp32 +6818 1/imm32/output-is-write-only +6819 _Primitive-copy-to-edi/imm32/next +6820 _Primitive-copy-to-edi: +6821 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 +6822 "copy"/imm32/name +6823 Single-lit-var/imm32/inouts +6824 Single-int-var-in-edi/imm32/outputs +6825 "bf/copy-to-edi"/imm32/subx-name +6826 0/imm32/no-rm32 +6827 0/imm32/no-r32 +6828 1/imm32/imm32-is-first-inout +6829 0/imm32/no-disp32 +6830 1/imm32/output-is-write-only +6831 _Primitive-copy-reg-to-reg/imm32/next +6832 _Primitive-copy-reg-to-reg: +6833 # var1/reg <- copy var2/reg => 89/copy-to var1/rm32 var2/r32 +6834 "copy"/imm32/name +6835 Single-int-var-in-some-register/imm32/inouts +6836 Single-int-var-in-some-register/imm32/outputs +6837 "89/copy-to"/imm32/subx-name +6838 3/imm32/rm32-is-first-output +6839 1/imm32/r32-is-first-inout +6840 0/imm32/no-imm32 +6841 0/imm32/no-disp32 +6842 1/imm32/output-is-write-only +6843 _Primitive-copy-reg-to-mem/imm32/next +6844 _Primitive-copy-reg-to-mem: +6845 # copy-to var1 var2/reg => 89/copy-to var1 var2/r32 +6846 "copy-to"/imm32/name +6847 Two-args-int-stack-int-reg/imm32/inouts 6848 0/imm32/outputs -6849 "0f 8d/jump-if->="/imm32/subx-name -6850 0/imm32/no-rm32 -6851 0/imm32/no-r32 +6849 "89/copy-to"/imm32/subx-name +6850 1/imm32/rm32-is-first-inout +6851 2/imm32/r32-is-second-inout 6852 0/imm32/no-imm32 -6853 1/imm32/disp32-is-first-inout -6854 0/imm32/no-output -6855 _Primitive-loop-if-<=-named/imm32/next -6856 _Primitive-loop-if-<=-named: -6857 "loop-if-<="/imm32/name -6858 Single-lit-var/imm32/inouts -6859 0/imm32/outputs -6860 "0f 8e/jump-if-<="/imm32/subx-name -6861 0/imm32/no-rm32 -6862 0/imm32/no-r32 -6863 0/imm32/no-imm32 -6864 1/imm32/disp32-is-first-inout -6865 0/imm32/no-output -6866 _Primitive-loop-if->-named/imm32/next -6867 _Primitive-loop-if->-named: -6868 "loop-if->"/imm32/name -6869 Single-lit-var/imm32/inouts -6870 0/imm32/outputs -6871 "0f 8f/jump-if->"/imm32/subx-name -6872 0/imm32/no-rm32 -6873 0/imm32/no-r32 -6874 0/imm32/no-imm32 -6875 1/imm32/disp32-is-first-inout -6876 0/imm32/no-output -6877 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break -6878 _Primitive-loop-named: -6879 "loop"/imm32/name -6880 Single-lit-var/imm32/inouts -6881 0/imm32/outputs -6882 "e9/jump"/imm32/subx-name -6883 0/imm32/no-rm32 -6884 0/imm32/no-r32 -6885 0/imm32/no-imm32 -6886 1/imm32/disp32-is-first-inout -6887 0/imm32/no-output -6888 0/imm32/next -6889 -6890 Single-int-var-in-mem: -6891 Int-var-in-mem/imm32 -6892 0/imm32/next -6893 -6894 Int-var-in-mem: -6895 "arg1"/imm32/name -6896 Type-int/imm32 -6897 1/imm32/some-block-depth -6898 1/imm32/some-stack-offset -6899 0/imm32/no-register -6900 -6901 Two-args-int-stack-int-reg: -6902 Int-var-in-mem/imm32 -6903 Single-int-var-in-some-register/imm32/next -6904 -6905 Two-args-int-reg-int-stack: -6906 Int-var-in-some-register/imm32 -6907 Single-int-var-in-mem/imm32/next -6908 -6909 Two-args-int-eax-int-literal: -6910 Int-var-in-eax/imm32 -6911 Single-lit-var/imm32/next -6912 -6913 Int-var-and-literal: -6914 Int-var-in-mem/imm32 -6915 Single-lit-var/imm32/next -6916 -6917 Int-var-in-register-and-literal: -6918 Int-var-in-some-register/imm32 -6919 Single-lit-var/imm32/next -6920 -6921 Single-int-var-in-some-register: -6922 Int-var-in-some-register/imm32 -6923 0/imm32/next -6924 -6925 Int-var-in-some-register: -6926 "arg1"/imm32/name -6927 Type-int/imm32 -6928 1/imm32/some-block-depth -6929 0/imm32/no-stack-offset -6930 Any-register/imm32 -6931 -6932 Single-int-var-in-eax: -6933 Int-var-in-eax/imm32 -6934 0/imm32/next -6935 -6936 Int-var-in-eax: -6937 "arg1"/imm32/name -6938 Type-int/imm32 -6939 1/imm32/some-block-depth -6940 0/imm32/no-stack-offset -6941 "eax"/imm32/register -6942 -6943 Single-int-var-in-ecx: -6944 Int-var-in-ecx/imm32 -6945 0/imm32/next -6946 -6947 Int-var-in-ecx: -6948 "arg1"/imm32/name -6949 Type-int/imm32 -6950 1/imm32/some-block-depth -6951 0/imm32/no-stack-offset -6952 "ecx"/imm32/register -6953 -6954 Single-int-var-in-edx: -6955 Int-var-in-edx/imm32 -6956 0/imm32/next -6957 -6958 Int-var-in-edx: -6959 "arg1"/imm32/name -6960 Type-int/imm32 -6961 1/imm32/some-block-depth -6962 0/imm32/no-stack-offset -6963 "edx"/imm32/register -6964 -6965 Single-int-var-in-ebx: -6966 Int-var-in-ebx/imm32 -6967 0/imm32/next -6968 -6969 Int-var-in-ebx: -6970 "arg1"/imm32/name -6971 Type-int/imm32 -6972 1/imm32/some-block-depth -6973 0/imm32/no-stack-offset -6974 "ebx"/imm32/register -6975 -6976 Single-int-var-in-esi: -6977 Int-var-in-esi/imm32 -6978 0/imm32/next -6979 -6980 Int-var-in-esi: -6981 "arg1"/imm32/name -6982 Type-int/imm32 -6983 1/imm32/some-block-depth -6984 0/imm32/no-stack-offset -6985 "esi"/imm32/register -6986 -6987 Single-int-var-in-edi: -6988 Int-var-in-edi/imm32 -6989 0/imm32/next -6990 -6991 Int-var-in-edi: -6992 "arg1"/imm32/name -6993 Type-int/imm32 -6994 1/imm32/some-block-depth -6995 0/imm32/no-stack-offset -6996 "edi"/imm32/register -6997 -6998 Single-lit-var: -6999 Lit-var/imm32 -7000 0/imm32/next -7001 -7002 Lit-var: -7003 "literal"/imm32/name -7004 Type-literal/imm32 -7005 1/imm32/some-block-depth -7006 0/imm32/no-stack-offset -7007 0/imm32/no-register -7008 -7009 Type-int: -7010 1/imm32/left/int -7011 0/imm32/right/null -7012 -7013 Type-literal: -7014 0/imm32/left/literal -7015 0/imm32/right/null -7016 -7017 == code -7018 emit-subx-primitive: # out: (addr buffered-file), stmt: (handle statement), primitive: (handle function) -7019 # . prologue -7020 55/push-ebp -7021 89/<- %ebp 4/r32/esp -7022 # . save registers -7023 50/push-eax -7024 51/push-ecx -7025 # ecx = primitive -7026 8b/-> *(ebp+0x10) 1/r32/ecx -7027 # emit primitive name -7028 (emit-indent *(ebp+8) *Curr-block-depth) -7029 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name -7030 # emit rm32 if necessary -7031 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt -7032 # emit r32 if necessary -7033 (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt -7034 # emit imm32 if necessary -7035 (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt -7036 # emit disp32 if necessary -7037 (emit-subx-disp32 *(ebp+8) *(ecx+0x1c) *(ebp+0xc)) # out, Primitive-subx-disp32, stmt -7038 (write-buffered *(ebp+8) Newline) -7039 $emit-subx-primitive:end: -7040 # . restore registers -7041 59/pop-to-ecx -7042 58/pop-to-eax -7043 # . epilogue -7044 89/<- %esp 5/r32/ebp -7045 5d/pop-to-ebp -7046 c3/return -7047 -7048 emit-subx-rm32: # 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 # if (l == 0) return -7055 81 7/subop/compare *(ebp+0xc) 0/imm32 -7056 74/jump-if-= $emit-subx-rm32:end/disp8 -7057 # var v/eax: (handle var) -7058 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax -7059 (emit-subx-var-as-rm32 *(ebp+8) %eax) -7060 $emit-subx-rm32:end: -7061 # . restore registers -7062 58/pop-to-eax -7063 # . epilogue -7064 89/<- %esp 5/r32/ebp -7065 5d/pop-to-ebp -7066 c3/return -7067 -7068 get-stmt-operand-from-arg-location: # stmt: (handle statement), l: arg-location -> var/eax: (handle stmt-var) -7069 # . prologue -7070 55/push-ebp -7071 89/<- %ebp 4/r32/esp -7072 # . save registers -7073 51/push-ecx -7074 # eax = l -7075 8b/-> *(ebp+0xc) 0/r32/eax -7076 # ecx = stmt -7077 8b/-> *(ebp+8) 1/r32/ecx -7078 # if (l == 1) return stmt->inouts -7079 { -7080 3d/compare-eax-and 1/imm32 -7081 75/jump-if-!= break/disp8 -7082 $get-stmt-operand-from-arg-location:1: -7083 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts -7084 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -7085 } -7086 # if (l == 2) return stmt->inouts->next -7087 { -7088 3d/compare-eax-and 2/imm32 -7089 75/jump-if-!= break/disp8 -7090 $get-stmt-operand-from-arg-location:2: -7091 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts -7092 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next -7093 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -7094 } -7095 # if (l == 3) return stmt->outputs -7096 { -7097 3d/compare-eax-and 3/imm32 -7098 75/jump-if-!= break/disp8 -7099 $get-stmt-operand-from-arg-location:3: -7100 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs -7101 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -7102 } -7103 # abort -7104 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 -7105 $get-stmt-operand-from-arg-location:end: -7106 # . restore registers -7107 59/pop-to-ecx -7108 # . epilogue -7109 89/<- %esp 5/r32/ebp -7110 5d/pop-to-ebp -7111 c3/return -7112 -7113 $get-stmt-operand-from-arg-location:abort: -7114 # error("invalid arg-location " eax) -7115 (write-buffered Stderr "invalid arg-location ") -7116 (print-int32-buffered Stderr %eax) -7117 (write-buffered Stderr Newline) -7118 (flush Stderr) -7119 # . syscall(exit, 1) -7120 bb/copy-to-ebx 1/imm32 -7121 b8/copy-to-eax 1/imm32/exit -7122 cd/syscall 0x80/imm8 -7123 # never gets here -7124 -7125 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -7126 # . prologue -7127 55/push-ebp -7128 89/<- %ebp 4/r32/esp -7129 # . save registers -7130 50/push-eax -7131 51/push-ecx -7132 # if (location == 0) return -7133 81 7/subop/compare *(ebp+0xc) 0/imm32 -7134 0f 84/jump-if-= $emit-subx-r32:end/disp32 -7135 # var v/eax: (handle var) -7136 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax -7137 8b/-> *eax 0/r32/eax # Stmt-var-value -7138 (maybe-get Registers *(eax+0x10) 8) # Var-register => eax: (addr register-index) -7139 (write-buffered *(ebp+8) Space) -7140 (print-int32-buffered *(ebp+8) *eax) -7141 (write-buffered *(ebp+8) "/r32") -7142 $emit-subx-r32:end: -7143 # . restore registers -7144 59/pop-to-ecx -7145 58/pop-to-eax -7146 # . epilogue -7147 89/<- %esp 5/r32/ebp -7148 5d/pop-to-ebp -7149 c3/return -7150 -7151 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -7152 # . prologue -7153 55/push-ebp -7154 89/<- %ebp 4/r32/esp -7155 # . save registers -7156 50/push-eax -7157 51/push-ecx -7158 # if (location == 0) return -7159 81 7/subop/compare *(ebp+0xc) 0/imm32 -7160 74/jump-if-= $emit-subx-imm32:end/disp8 -7161 # var v/eax: (handle var) -7162 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax -7163 8b/-> *eax 0/r32/eax # Stmt-var-value -7164 (write-buffered *(ebp+8) Space) -7165 (write-buffered *(ebp+8) *eax) # Var-name -7166 (write-buffered *(ebp+8) "/imm32") -7167 $emit-subx-imm32:end: -7168 # . restore registers -7169 59/pop-to-ecx -7170 58/pop-to-eax -7171 # . epilogue -7172 89/<- %esp 5/r32/ebp -7173 5d/pop-to-ebp -7174 c3/return -7175 -7176 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -7177 # . prologue -7178 55/push-ebp -7179 89/<- %ebp 4/r32/esp -7180 # . save registers -7181 50/push-eax -7182 51/push-ecx -7183 # if (location == 0) return -7184 81 7/subop/compare *(ebp+0xc) 0/imm32 -7185 0f 84/jump-if-= $emit-subx-disp32:end/disp32 -7186 # var v/eax: (handle var) -7187 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax -7188 8b/-> *eax 0/r32/eax # Stmt-var-value -7189 (write-buffered *(ebp+8) Space) -7190 (write-buffered *(ebp+8) *eax) # Var-name -7191 # hack: if instruction operation starts with "break", emit ":break" -7192 # var name/ecx: (addr array byte) = stmt->operation -7193 8b/-> *(ebp+0x10) 0/r32/eax -7194 8b/-> *(eax+4) 1/r32/ecx -7195 { -7196 (string-starts-with? %ecx "break") # => eax -7197 3d/compare-eax-and 0/imm32/false -7198 74/jump-if-= break/disp8 -7199 (write-buffered *(ebp+8) ":break") -7200 } -7201 # hack: if instruction operation starts with "loop", emit ":loop" -7202 { -7203 (string-starts-with? %ecx "loop") # => eax -7204 3d/compare-eax-and 0/imm32/false -7205 74/jump-if-= break/disp8 -7206 (write-buffered *(ebp+8) ":loop") -7207 } -7208 (write-buffered *(ebp+8) "/disp32") -7209 $emit-subx-disp32:end: -7210 # . restore registers -7211 59/pop-to-ecx -7212 58/pop-to-eax -7213 # . epilogue -7214 89/<- %esp 5/r32/ebp -7215 5d/pop-to-ebp -7216 c3/return -7217 -7218 emit-subx-call: # out: (addr buffered-file), stmt: (handle statement), callee: (handle function) -7219 # . prologue -7220 55/push-ebp -7221 89/<- %ebp 4/r32/esp -7222 # . save registers -7223 51/push-ecx -7224 # -7225 (emit-indent *(ebp+8) *Curr-block-depth) -7226 (write-buffered *(ebp+8) "(") -7227 # - emit function name -7228 8b/-> *(ebp+0x10) 1/r32/ecx -7229 (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name -7230 # - emit arguments -7231 # var curr/ecx: (handle stmt-var) = stmt->inouts -7232 8b/-> *(ebp+0xc) 1/r32/ecx -7233 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts -7234 { -7235 # if (curr == null) break -7236 81 7/subop/compare %ecx 0/imm32 -7237 74/jump-if-= break/disp8 -7238 # -7239 (emit-subx-call-operand *(ebp+8) %ecx) -7240 # curr = curr->next -7241 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next -7242 eb/jump loop/disp8 -7243 } -7244 # -7245 (write-buffered *(ebp+8) ")\n") -7246 $emit-subx-call:end: -7247 # . restore registers -7248 59/pop-to-ecx -7249 # . epilogue -7250 89/<- %esp 5/r32/ebp -7251 5d/pop-to-ebp -7252 c3/return -7253 -7254 # like a function call, except we have no idea what function it is -7255 # we hope it's defined in SubX and that the types are ok -7256 emit-hailmary-call: # out: (addr buffered-file), stmt: (handle statement) -7257 # . prologue -7258 55/push-ebp -7259 89/<- %ebp 4/r32/esp -7260 # . save registers -7261 51/push-ecx -7262 # -7263 (emit-indent *(ebp+8) *Curr-block-depth) -7264 (write-buffered *(ebp+8) "(") -7265 # ecx = stmt -7266 8b/-> *(ebp+0xc) 1/r32/ecx -7267 # - emit function name -7268 (write-buffered *(ebp+8) *(ecx+4)) # Stmt1-operation -7269 # - emit arguments -7270 # var curr/ecx: (handle stmt-var) = stmt->inouts -7271 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts -7272 { -7273 # if (curr == null) break -7274 81 7/subop/compare %ecx 0/imm32 -7275 74/jump-if-= break/disp8 -7276 # -7277 (emit-subx-call-operand *(ebp+8) %ecx) -7278 # curr = curr->next -7279 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next -7280 eb/jump loop/disp8 -7281 } -7282 # -7283 (write-buffered *(ebp+8) ")\n") -7284 $emit-hailmary-call:end: -7285 # . restore registers -7286 59/pop-to-ecx -7287 # . epilogue -7288 89/<- %esp 5/r32/ebp -7289 5d/pop-to-ebp -7290 c3/return -7291 -7292 emit-subx-call-operand: # out: (addr buffered-file), s: (handle stmt-var) -7293 # shares code with emit-subx-var-as-rm32 -7294 # . prologue -7295 55/push-ebp -7296 89/<- %ebp 4/r32/esp -7297 # . save registers -7298 50/push-eax -7299 51/push-ecx -7300 56/push-esi -7301 # ecx = s -7302 8b/-> *(ebp+0xc) 1/r32/ecx -7303 # var operand/esi: (handle var) = s->value -7304 8b/-> *ecx 6/r32/esi # Stmt-var-value -7305 # if (operand->register && s->is-deref?) emit "*__" -7306 { -7307 $emit-subx-call-operand:check-for-register-indirect: -7308 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register -7309 74/jump-if-= break/disp8 -7310 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref -7311 74/jump-if-= break/disp8 -7312 $emit-subx-call-operand:register-indirect: -7313 (write-buffered *(ebp+8) " *") -7314 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register -7315 e9/jump $emit-subx-call-operand:end/disp32 -7316 } -7317 # if (operand->register && !s->is-deref?) emit "%__" -7318 { -7319 $emit-subx-call-operand:check-for-register-direct: -7320 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register -7321 74/jump-if-= break/disp8 -7322 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref -7323 75/jump-if-!= break/disp8 -7324 $emit-subx-call-operand:register-direct: -7325 (write-buffered *(ebp+8) " %") -7326 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register -7327 e9/jump $emit-subx-call-operand:end/disp32 -7328 } -7329 # else if (operand->stack-offset) emit "*(ebp+__)" -7330 { -7331 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-stack-offset -7332 74/jump-if-= break/disp8 -7333 $emit-subx-call-operand:stack: -7334 (write-buffered *(ebp+8) Space) -7335 (write-buffered *(ebp+8) "*(ebp+") -7336 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-stack-offset -7337 (write-buffered *(ebp+8) ")") -7338 e9/jump $emit-subx-call-operand:end/disp32 -7339 } -7340 # else if (operand->type == literal) emit "__" -7341 { -7342 8b/-> *(esi+4) 0/r32/eax # Var-type -7343 81 7/subop/compare *eax 0/imm32 # Tree-left -7344 75/jump-if-!= break/disp8 -7345 $emit-subx-call-operand:literal: -7346 (write-buffered *(ebp+8) Space) -7347 (write-buffered *(ebp+8) *esi) -7348 } -7349 $emit-subx-call-operand:end: -7350 # . restore registers -7351 5e/pop-to-esi -7352 59/pop-to-ecx -7353 58/pop-to-eax -7354 # . epilogue -7355 89/<- %esp 5/r32/ebp -7356 5d/pop-to-ebp -7357 c3/return -7358 -7359 emit-subx-var-as-rm32: # out: (addr buffered-file), s: (handle stmt-var) -7360 # . prologue -7361 55/push-ebp -7362 89/<- %ebp 4/r32/esp -7363 # . save registers -7364 50/push-eax -7365 51/push-ecx -7366 56/push-esi -7367 # ecx = s -7368 8b/-> *(ebp+0xc) 1/r32/ecx -7369 # var operand/esi: (handle var) = s->value -7370 8b/-> *ecx 6/r32/esi # Stmt-var-value -7371 # if (operand->register && s->is-deref?) emit "*__" -7372 { -7373 $emit-subx-var-as-rm32:check-for-register-indirect: -7374 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register -7375 74/jump-if-= break/disp8 -7376 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref -7377 74/jump-if-= break/disp8 -7378 $emit-subx-var-as-rm32:register-indirect: -7379 (write-buffered *(ebp+8) " *") -7380 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register -7381 } -7382 # if (operand->register && !s->is-deref?) emit "%__" -7383 { -7384 $emit-subx-var-as-rm32:check-for-register-direct: -7385 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register -7386 74/jump-if-= break/disp8 -7387 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref -7388 75/jump-if-!= break/disp8 -7389 $emit-subx-var-as-rm32:register-direct: -7390 (write-buffered *(ebp+8) " %") -7391 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register -7392 } -7393 # else if (operand->stack-offset) emit "*(ebp+__)" -7394 { -7395 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-stack-offset -7396 74/jump-if-= break/disp8 -7397 $emit-subx-var-as-rm32:stack: -7398 (write-buffered *(ebp+8) Space) -7399 (write-buffered *(ebp+8) "*(ebp+") -7400 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-stack-offset -7401 (write-buffered *(ebp+8) ")") -7402 } -7403 $emit-subx-var-as-rm32:end: -7404 # . restore registers -7405 5e/pop-to-esi -7406 59/pop-to-ecx -7407 58/pop-to-eax -7408 # . epilogue -7409 89/<- %esp 5/r32/ebp -7410 5d/pop-to-ebp -7411 c3/return -7412 -7413 find-matching-function: # functions: (addr function), stmt: (handle statement) -> result/eax: (handle function) -7414 # . prologue -7415 55/push-ebp -7416 89/<- %ebp 4/r32/esp -7417 # . save registers -7418 51/push-ecx -7419 # var curr/ecx: (handle function) = functions -7420 8b/-> *(ebp+8) 1/r32/ecx -7421 { -7422 # if (curr == null) break -7423 81 7/subop/compare %ecx 0/imm32 -7424 74/jump-if-= break/disp8 -7425 # if match(stmt, curr) return curr -7426 { -7427 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax -7428 3d/compare-eax-and 0/imm32/false -7429 74/jump-if-= break/disp8 -7430 89/<- %eax 1/r32/ecx -7431 eb/jump $find-matching-function:end/disp8 -7432 } -7433 # curr = curr->next -7434 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next -7435 eb/jump loop/disp8 -7436 } -7437 # return null -7438 b8/copy-to-eax 0/imm32 -7439 $find-matching-function:end: -7440 # . restore registers -7441 59/pop-to-ecx -7442 # . epilogue -7443 89/<- %esp 5/r32/ebp -7444 5d/pop-to-ebp -7445 c3/return -7446 -7447 find-matching-primitive: # primitives: (handle primitive), stmt: (handle statement) -> result/eax: (handle primitive) -7448 # . prologue -7449 55/push-ebp -7450 89/<- %ebp 4/r32/esp -7451 # . save registers -7452 51/push-ecx -7453 # var curr/ecx: (handle primitive) = primitives -7454 8b/-> *(ebp+8) 1/r32/ecx -7455 { -7456 $find-matching-primitive:loop: -7457 # if (curr == null) break -7458 81 7/subop/compare %ecx 0/imm32 -7459 0f 84/jump-if-= break/disp32 -7460 #? (write-buffered Stderr "prim: ") -7461 #? (write-buffered Stderr *ecx) # Primitive-name -7462 #? (write-buffered Stderr " => ") -7463 #? (write-buffered Stderr *(ecx+0xc)) # Primitive-subx-name -7464 #? (write-buffered Stderr Newline) -7465 #? (flush Stderr) -7466 # if match(curr, stmt) return curr -7467 { -7468 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax -7469 3d/compare-eax-and 0/imm32/false -7470 74/jump-if-= break/disp8 -7471 89/<- %eax 1/r32/ecx -7472 eb/jump $find-matching-primitive:end/disp8 -7473 } -7474 $find-matching-primitive:next-primitive: -7475 # curr = curr->next -7476 8b/-> *(ecx+0x24) 1/r32/ecx # Primitive-next -7477 e9/jump loop/disp32 -7478 } -7479 # return null -7480 b8/copy-to-eax 0/imm32 -7481 $find-matching-primitive:end: -7482 # . restore registers -7483 59/pop-to-ecx -7484 # . epilogue -7485 89/<- %esp 5/r32/ebp -7486 5d/pop-to-ebp -7487 c3/return -7488 -7489 mu-stmt-matches-function?: # stmt: (handle statement), function: (handle function) -> result/eax: boolean -7490 # . prologue -7491 55/push-ebp -7492 89/<- %ebp 4/r32/esp -7493 # . save registers -7494 51/push-ecx -7495 # return function->name == stmt->operation -7496 8b/-> *(ebp+8) 1/r32/ecx -7497 8b/-> *(ebp+0xc) 0/r32/eax -7498 (string-equal? *(ecx+4) *eax) # Stmt1-operation, Function-name => eax -7499 $mu-stmt-matches-function?:end: -7500 # . restore registers -7501 59/pop-to-ecx -7502 # . epilogue -7503 89/<- %esp 5/r32/ebp -7504 5d/pop-to-ebp -7505 c3/return -7506 -7507 mu-stmt-matches-primitive?: # stmt: (handle statement), primitive: (handle primitive) -> result/eax: boolean -7508 # A mu stmt matches a primitive if the name matches, all the inout vars -7509 # match, and all the output vars match. -7510 # Vars match if types match and registers match. -7511 # In addition, a stmt output matches a primitive's output if types match -7512 # and the primitive has a wildcard register. -7513 # . prologue -7514 55/push-ebp -7515 89/<- %ebp 4/r32/esp -7516 # . save registers -7517 51/push-ecx -7518 52/push-edx -7519 53/push-ebx -7520 56/push-esi -7521 57/push-edi -7522 # ecx = stmt -7523 8b/-> *(ebp+8) 1/r32/ecx -7524 # edx = primitive -7525 8b/-> *(ebp+0xc) 2/r32/edx -7526 { -7527 $mu-stmt-matches-primitive?:check-name: -7528 # if (primitive->name != stmt->operation) return false -7529 (string-equal? *(ecx+4) *edx) # Stmt1-operation, Primitive-name => eax -7530 3d/compare-eax-and 0/imm32/false -7531 75/jump-if-!= break/disp8 -7532 b8/copy-to-eax 0/imm32 -7533 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7534 } -7535 $mu-stmt-matches-primitive?:check-inouts: -7536 # for (curr/esi in stmt->inouts, curr2/edi in primitive->inouts) -7537 8b/-> *(ecx+8) 6/r32/esi # Stmt1-inouts or Regvardef-inouts -7538 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts -7539 { -7540 # if (curr == 0 && curr2 == 0) move on to check outputs -7541 { -7542 81 7/subop/compare %esi 0/imm32 -7543 75/jump-if-!= break/disp8 -7544 $mu-stmt-matches-primitive?:stmt-inout-is-null: -7545 { -7546 81 7/subop/compare %edi 0/imm32 -7547 75/jump-if-!= break/disp8 -7548 # -7549 e9/jump $mu-stmt-matches-primitive?:check-outputs/disp32 -7550 } -7551 # return false -7552 b8/copy-to-eax 0/imm32/false -7553 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7554 } -7555 # if (curr2 == 0) return false -7556 { -7557 81 7/subop/compare %edi 0/imm32 -7558 75/jump-if-!= break/disp8 -7559 $mu-stmt-matches-primitive?:prim-inout-is-null: -7560 b8/copy-to-eax 0/imm32/false -7561 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7562 } -7563 # if (curr != curr2) return false -7564 { -7565 (operand-matches-primitive? %esi *edi) # List-value => eax -7566 3d/compare-eax-and 0/imm32/false -7567 75/jump-if-!= break/disp8 -7568 b8/copy-to-eax 0/imm32/false -7569 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7570 } -7571 # curr=curr->next -7572 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next -7573 # curr2=curr2->next -7574 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next -7575 eb/jump loop/disp8 -7576 } -7577 $mu-stmt-matches-primitive?:check-outputs: -7578 # for (curr/esi in stmt->outputs, curr2/edi in primitive->outputs) -7579 8b/-> *(ecx+0xc) 6/r32/esi # Stmt1-outputs -7580 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs -7581 { -7582 # if (curr == 0) return (curr2 == 0) -7583 { -7584 $mu-stmt-matches-primitive?:check-output: -7585 81 7/subop/compare %esi 0/imm32 -7586 75/jump-if-!= break/disp8 -7587 { -7588 81 7/subop/compare %edi 0/imm32 -7589 75/jump-if-!= break/disp8 -7590 # return true -7591 b8/copy-to-eax 1/imm32 -7592 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7593 } -7594 # return false -7595 b8/copy-to-eax 0/imm32 -7596 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7597 } -7598 # if (curr2 == 0) return false -7599 { -7600 81 7/subop/compare %edi 0/imm32 -7601 75/jump-if-!= break/disp8 -7602 b8/copy-to-eax 0/imm32 -7603 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7604 } -7605 # if (curr != curr2) return false -7606 { -7607 (operand-matches-primitive? %esi *edi) # List-value => eax -7608 3d/compare-eax-and 0/imm32/false -7609 75/jump-if-!= break/disp8 -7610 b8/copy-to-eax 0/imm32 -7611 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7612 } -7613 # curr=curr->next -7614 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next -7615 # curr2=curr2->next -7616 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next -7617 eb/jump loop/disp8 -7618 } -7619 $mu-stmt-matches-primitive?:return-true: -7620 b8/copy-to-eax 1/imm32 -7621 $mu-stmt-matches-primitive?:end: -7622 # . restore registers -7623 5f/pop-to-edi -7624 5e/pop-to-esi -7625 5b/pop-to-ebx -7626 5a/pop-to-edx -7627 59/pop-to-ecx -7628 # . epilogue -7629 89/<- %esp 5/r32/ebp -7630 5d/pop-to-ebp -7631 c3/return -7632 -7633 operand-matches-primitive?: # s: (handle stmt-var), prim-var: (handle var) -> result/eax: boolean -7634 # . prologue -7635 55/push-ebp -7636 89/<- %ebp 4/r32/esp -7637 # . save registers -7638 51/push-ecx -7639 56/push-esi -7640 57/push-edi -7641 # ecx = s -7642 8b/-> *(ebp+8) 1/r32/ecx -7643 # var var/esi : (handle var) = s->value -7644 8b/-> *ecx 6/r32/esi # Stmt-var-value -7645 # edi = prim-var -7646 8b/-> *(ebp+0xc) 7/r32/edi -7647 $operand-matches-primitive?:check-type: -7648 # if (var->type != prim-var->type) return false -7649 (subx-type-equal? *(esi+4) *(edi+4)) # Var-type, Var-type => eax -7650 3d/compare-eax-and 0/imm32/false -7651 b8/copy-to-eax 0/imm32/false -7652 0f 84/jump-if-= $operand-matches-primitive?:end/disp32 -7653 { -7654 $operand-matches-primitive?:check-register: -7655 # if prim-var is in memory and var is in register but dereference, match -7656 { -7657 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register -7658 0f 85/jump-if-!= break/disp32 -7659 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register -7660 74/jump-if-= break/disp8 -7661 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref -7662 74/jump-if-= break/disp8 -7663 e9/jump $operand-matches-primitive?:return-true/disp32 -7664 } -7665 # if prim-var is in register and var is in register but dereference, no match -7666 { -7667 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register -7668 0f 84/jump-if-= break/disp32 -7669 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register -7670 0f 84/jump-if-= break/disp32 -7671 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref -7672 74/jump-if-= break/disp8 -7673 e9/jump $operand-matches-primitive?:return-false/disp32 -7674 } -7675 # return false if var->register doesn't match prim-var->register -7676 { -7677 # if register addresses are equal, it's a match -7678 8b/-> *(esi+0x10) 0/r32/eax # Var-register -7679 39/compare *(edi+0x10) 0/r32/eax # Var-register -7680 74/jump-if-= break/disp8 -7681 # if either address is 0, return false -7682 3d/compare-eax-and 0/imm32 -7683 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result -7684 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register -7685 74/jump-if-= $operand-matches-primitive?:return-false/disp8 -7686 # if prim-var->register is wildcard, it's a match -7687 (string-equal? *(edi+0x10) Any-register) # Var-register => eax -7688 3d/compare-eax-and 0/imm32/false -7689 75/jump-if-!= break/disp8 -7690 # if string contents aren't equal, return false -7691 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register => eax -7692 3d/compare-eax-and 0/imm32/false -7693 74/jump-if-= $operand-matches-primitive?:return-false/disp8 -7694 } -7695 } -7696 $operand-matches-primitive?:return-true: -7697 b8/copy-to-eax 1/imm32/true -7698 eb/jump $operand-matches-primitive?:end/disp8 -7699 $operand-matches-primitive?:return-false: -7700 b8/copy-to-eax 0/imm32/false -7701 $operand-matches-primitive?:end: -7702 # . restore registers -7703 5f/pop-to-edi -7704 5e/pop-to-esi -7705 59/pop-to-ecx -7706 # . epilogue -7707 89/<- %esp 5/r32/ebp -7708 5d/pop-to-ebp -7709 c3/return -7710 -7711 subx-type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean -7712 # . prologue -7713 55/push-ebp -7714 89/<- %ebp 4/r32/esp -7715 # . save registers -7716 51/push-ecx -7717 # var alit/ecx: boolean = is-literal-type?(a) -7718 (is-literal-type? *(ebp+8)) # => eax -7719 89/<- %ecx 0/r32/eax -7720 # var blit/eax: boolean = is-literal-type?(b) -7721 (is-literal-type? *(ebp+0xc)) # => eax -7722 # return alit == blit -7723 39/compare %eax 1/r32/ecx -7724 74/jump-if-= $subx-type-equal?:true/disp8 -7725 $subx-type-equal?:false: -7726 b8/copy-to-eax 0/imm32/false -7727 eb/jump $subx-type-equal?:end/disp8 -7728 $subx-type-equal?:true: -7729 b8/copy-to-eax 1/imm32/true -7730 $subx-type-equal?:end: +6853 0/imm32/no-disp32 +6854 1/imm32/output-is-write-only +6855 _Primitive-copy-mem-to-reg/imm32/next +6856 _Primitive-copy-mem-to-reg: +6857 # var1/reg <- copy var2 => 8b/copy-from var2/rm32 var1/r32 +6858 "copy"/imm32/name +6859 Single-int-var-in-mem/imm32/inouts +6860 Single-int-var-in-some-register/imm32/outputs +6861 "8b/copy-from"/imm32/subx-name +6862 1/imm32/rm32-is-first-inout +6863 3/imm32/r32-is-first-output +6864 0/imm32/no-imm32 +6865 0/imm32/no-disp32 +6866 1/imm32/output-is-write-only +6867 _Primitive-copy-lit-to-reg/imm32/next +6868 _Primitive-copy-lit-to-reg: +6869 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 +6870 "copy"/imm32/name +6871 Single-lit-var/imm32/inouts +6872 Single-int-var-in-some-register/imm32/outputs +6873 "c7 0/subop/copy"/imm32/subx-name +6874 3/imm32/rm32-is-first-output +6875 0/imm32/no-r32 +6876 1/imm32/imm32-is-first-inout +6877 0/imm32/no-disp32 +6878 1/imm32/output-is-write-only +6879 _Primitive-copy-lit-to-mem/imm32/next +6880 _Primitive-copy-lit-to-mem: +6881 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 +6882 "copy-to"/imm32/name +6883 Int-var-and-literal/imm32/inouts +6884 0/imm32/outputs +6885 "c7 0/subop/copy"/imm32/subx-name +6886 1/imm32/rm32-is-first-inout +6887 0/imm32/no-r32 +6888 2/imm32/imm32-is-first-inout +6889 0/imm32/no-disp32 +6890 1/imm32/output-is-write-only +6891 _Primitive-compare-mem-with-reg/imm32/next +6892 # - compare +6893 _Primitive-compare-mem-with-reg: +6894 # compare var1 var2/reg => 39/compare-> var1/rm32 var2/r32 +6895 "compare"/imm32/name +6896 Two-args-int-stack-int-reg/imm32/inouts +6897 0/imm32/outputs +6898 "39/compare->"/imm32/subx-name +6899 1/imm32/rm32-is-first-inout +6900 2/imm32/r32-is-second-inout +6901 0/imm32/no-imm32 +6902 0/imm32/no-disp32 +6903 0/imm32/output-is-write-only +6904 _Primitive-compare-reg-with-mem/imm32/next +6905 _Primitive-compare-reg-with-mem: +6906 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 +6907 "compare"/imm32/name +6908 Two-args-int-reg-int-stack/imm32/inouts +6909 0/imm32/outputs +6910 "3b/compare<-"/imm32/subx-name +6911 2/imm32/rm32-is-second-inout +6912 1/imm32/r32-is-first-inout +6913 0/imm32/no-imm32 +6914 0/imm32/no-disp32 +6915 0/imm32/output-is-write-only +6916 _Primitive-compare-eax-with-literal/imm32/next +6917 _Primitive-compare-eax-with-literal: +6918 # compare var1/eax n => 3d/compare-eax-with n/imm32 +6919 "compare"/imm32/name +6920 Two-args-int-eax-int-literal/imm32/inouts +6921 0/imm32/outputs +6922 "3d/compare-eax-with"/imm32/subx-name +6923 0/imm32/no-rm32 +6924 0/imm32/no-r32 +6925 2/imm32/imm32-is-second-inout +6926 0/imm32/no-disp32 +6927 0/imm32/output-is-write-only +6928 _Primitive-compare-reg-with-literal/imm32/next +6929 _Primitive-compare-reg-with-literal: +6930 # compare var1/reg n => 81 7/subop/compare %reg n/imm32 +6931 "compare"/imm32/name +6932 Int-var-in-register-and-literal/imm32/inouts +6933 0/imm32/outputs +6934 "81 7/subop/compare"/imm32/subx-name +6935 1/imm32/rm32-is-first-inout +6936 0/imm32/no-r32 +6937 2/imm32/imm32-is-second-inout +6938 0/imm32/no-disp32 +6939 0/imm32/output-is-write-only +6940 _Primitive-compare-mem-with-literal/imm32/next +6941 _Primitive-compare-mem-with-literal: +6942 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 +6943 "compare"/imm32/name +6944 Int-var-and-literal/imm32/inouts +6945 0/imm32/outputs +6946 "81 7/subop/compare"/imm32/subx-name +6947 1/imm32/rm32-is-first-inout +6948 0/imm32/no-r32 +6949 2/imm32/imm32-is-second-inout +6950 0/imm32/no-disp32 +6951 0/imm32/output-is-write-only +6952 _Primitive-multiply-reg-by-mem/imm32/next +6953 # - multiply +6954 _Primitive-multiply-reg-by-mem: +6955 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 +6956 "multiply"/imm32/name +6957 Single-int-var-in-mem/imm32/inouts +6958 Single-int-var-in-some-register/imm32/outputs +6959 "0f af/multiply"/imm32/subx-name +6960 1/imm32/rm32-is-first-inout +6961 3/imm32/r32-is-first-output +6962 0/imm32/no-imm32 +6963 0/imm32/no-disp32 +6964 0/imm32/output-is-write-only +6965 _Primitive-break-if-addr</imm32/next +6966 # - branches +6967 _Primitive-break-if-addr<: +6968 "break-if-addr<"/imm32/name +6969 0/imm32/inouts +6970 0/imm32/outputs +6971 "0f 82/jump-if-addr< break/disp32"/imm32/subx-name +6972 0/imm32/no-rm32 +6973 0/imm32/no-r32 +6974 0/imm32/no-imm32 +6975 0/imm32/no-disp32 +6976 0/imm32/no-output +6977 _Primitive-break-if-addr>=/imm32/next +6978 _Primitive-break-if-addr>=: +6979 "break-if-addr>="/imm32/name +6980 0/imm32/inouts +6981 0/imm32/outputs +6982 "0f 83/jump-if-addr>= break/disp32"/imm32/subx-name +6983 0/imm32/no-rm32 +6984 0/imm32/no-r32 +6985 0/imm32/no-imm32 +6986 0/imm32/no-disp32 +6987 0/imm32/no-output +6988 _Primitive-break-if-=/imm32/next +6989 _Primitive-break-if-=: +6990 "break-if-="/imm32/name +6991 0/imm32/inouts +6992 0/imm32/outputs +6993 "0f 84/jump-if-= break/disp32"/imm32/subx-name +6994 0/imm32/no-rm32 +6995 0/imm32/no-r32 +6996 0/imm32/no-imm32 +6997 0/imm32/no-disp32 +6998 0/imm32/no-output +6999 _Primitive-break-if-!=/imm32/next +7000 _Primitive-break-if-!=: +7001 "break-if-!="/imm32/name +7002 0/imm32/inouts +7003 0/imm32/outputs +7004 "0f 85/jump-if-!= break/disp32"/imm32/subx-name +7005 0/imm32/no-rm32 +7006 0/imm32/no-r32 +7007 0/imm32/no-imm32 +7008 0/imm32/no-disp32 +7009 0/imm32/no-output +7010 _Primitive-break-if-addr<=/imm32/next +7011 _Primitive-break-if-addr<=: +7012 "break-if-addr<="/imm32/name +7013 0/imm32/inouts +7014 0/imm32/outputs +7015 "0f 86/jump-if-addr<= break/disp32"/imm32/subx-name +7016 0/imm32/no-rm32 +7017 0/imm32/no-r32 +7018 0/imm32/no-imm32 +7019 0/imm32/no-disp32 +7020 0/imm32/no-output +7021 _Primitive-break-if-addr>/imm32/next +7022 _Primitive-break-if-addr>: +7023 "break-if-addr>"/imm32/name +7024 0/imm32/inouts +7025 0/imm32/outputs +7026 "0f 87/jump-if-addr> break/disp32"/imm32/subx-name +7027 0/imm32/no-rm32 +7028 0/imm32/no-r32 +7029 0/imm32/no-imm32 +7030 0/imm32/no-disp32 +7031 0/imm32/no-output +7032 _Primitive-break-if-</imm32/next +7033 _Primitive-break-if-<: +7034 "break-if-<"/imm32/name +7035 0/imm32/inouts +7036 0/imm32/outputs +7037 "0f 8c/jump-if-< break/disp32"/imm32/subx-name +7038 0/imm32/no-rm32 +7039 0/imm32/no-r32 +7040 0/imm32/no-imm32 +7041 0/imm32/no-disp32 +7042 0/imm32/no-output +7043 _Primitive-break-if->=/imm32/next +7044 _Primitive-break-if->=: +7045 "break-if->="/imm32/name +7046 0/imm32/inouts +7047 0/imm32/outputs +7048 "0f 8d/jump-if->= break/disp32"/imm32/subx-name +7049 0/imm32/no-rm32 +7050 0/imm32/no-r32 +7051 0/imm32/no-imm32 +7052 0/imm32/no-disp32 +7053 0/imm32/no-output +7054 _Primitive-break-if-<=/imm32/next +7055 _Primitive-break-if-<=: +7056 "break-if-<="/imm32/name +7057 0/imm32/inouts +7058 0/imm32/outputs +7059 "0f 8e/jump-if-<= break/disp32"/imm32/subx-name +7060 0/imm32/no-rm32 +7061 0/imm32/no-r32 +7062 0/imm32/no-imm32 +7063 0/imm32/no-disp32 +7064 0/imm32/no-output +7065 _Primitive-break-if->/imm32/next +7066 _Primitive-break-if->: +7067 "break-if->"/imm32/name +7068 0/imm32/inouts +7069 0/imm32/outputs +7070 "0f 8f/jump-if-> break/disp32"/imm32/subx-name +7071 0/imm32/no-rm32 +7072 0/imm32/no-r32 +7073 0/imm32/no-imm32 +7074 0/imm32/no-disp32 +7075 0/imm32/no-output +7076 _Primitive-break/imm32/next +7077 _Primitive-break: +7078 "break"/imm32/name +7079 0/imm32/inouts +7080 0/imm32/outputs +7081 "e9/jump break/disp32"/imm32/subx-name +7082 0/imm32/no-rm32 +7083 0/imm32/no-r32 +7084 0/imm32/no-imm32 +7085 0/imm32/no-disp32 +7086 0/imm32/no-output +7087 _Primitive-loop-if-addr</imm32/next +7088 _Primitive-loop-if-addr<: +7089 "loop-if-addr<"/imm32/name +7090 0/imm32/inouts +7091 0/imm32/outputs +7092 "0f 82/jump-if-addr< loop/disp32"/imm32/subx-name +7093 0/imm32/no-rm32 +7094 0/imm32/no-r32 +7095 0/imm32/no-imm32 +7096 0/imm32/no-disp32 +7097 0/imm32/no-output +7098 _Primitive-loop-if-addr>=/imm32/next +7099 _Primitive-loop-if-addr>=: +7100 "loop-if-addr>="/imm32/name +7101 0/imm32/inouts +7102 0/imm32/outputs +7103 "0f 83/jump-if-addr>= loop/disp32"/imm32/subx-name +7104 0/imm32/no-rm32 +7105 0/imm32/no-r32 +7106 0/imm32/no-imm32 +7107 0/imm32/no-disp32 +7108 0/imm32/no-output +7109 _Primitive-loop-if-=/imm32/next +7110 _Primitive-loop-if-=: +7111 "loop-if-="/imm32/name +7112 0/imm32/inouts +7113 0/imm32/outputs +7114 "0f 84/jump-if-= loop/disp32"/imm32/subx-name +7115 0/imm32/no-rm32 +7116 0/imm32/no-r32 +7117 0/imm32/no-imm32 +7118 0/imm32/no-disp32 +7119 0/imm32/no-output +7120 _Primitive-loop-if-!=/imm32/next +7121 _Primitive-loop-if-!=: +7122 "loop-if-!="/imm32/name +7123 0/imm32/inouts +7124 0/imm32/outputs +7125 "0f 85/jump-if-!= loop/disp32"/imm32/subx-name +7126 0/imm32/no-rm32 +7127 0/imm32/no-r32 +7128 0/imm32/no-imm32 +7129 0/imm32/no-disp32 +7130 0/imm32/no-output +7131 _Primitive-loop-if-addr<=/imm32/next +7132 _Primitive-loop-if-addr<=: +7133 "loop-if-addr<="/imm32/name +7134 0/imm32/inouts +7135 0/imm32/outputs +7136 "0f 86/jump-if-addr<= loop/disp32"/imm32/subx-name +7137 0/imm32/no-rm32 +7138 0/imm32/no-r32 +7139 0/imm32/no-imm32 +7140 0/imm32/no-disp32 +7141 0/imm32/no-output +7142 _Primitive-loop-if-addr>/imm32/next +7143 _Primitive-loop-if-addr>: +7144 "loop-if-addr>"/imm32/name +7145 0/imm32/inouts +7146 0/imm32/outputs +7147 "0f 87/jump-if-addr> loop/disp32"/imm32/subx-name +7148 0/imm32/no-rm32 +7149 0/imm32/no-r32 +7150 0/imm32/no-imm32 +7151 0/imm32/no-disp32 +7152 0/imm32/no-output +7153 _Primitive-loop-if-</imm32/next +7154 _Primitive-loop-if-<: +7155 "loop-if-<"/imm32/name +7156 0/imm32/inouts +7157 0/imm32/outputs +7158 "0f 8c/jump-if-< loop/disp32"/imm32/subx-name +7159 0/imm32/no-rm32 +7160 0/imm32/no-r32 +7161 0/imm32/no-imm32 +7162 0/imm32/no-disp32 +7163 0/imm32/no-output +7164 _Primitive-loop-if->=/imm32/next +7165 _Primitive-loop-if->=: +7166 "loop-if->="/imm32/name +7167 0/imm32/inouts +7168 0/imm32/outputs +7169 "0f 8d/jump-if->= loop/disp32"/imm32/subx-name +7170 0/imm32/no-rm32 +7171 0/imm32/no-r32 +7172 0/imm32/no-imm32 +7173 0/imm32/no-disp32 +7174 0/imm32/no-output +7175 _Primitive-loop-if-<=/imm32/next +7176 _Primitive-loop-if-<=: +7177 "loop-if-<="/imm32/name +7178 0/imm32/inouts +7179 0/imm32/outputs +7180 "0f 8e/jump-if-<= loop/disp32"/imm32/subx-name +7181 0/imm32/no-rm32 +7182 0/imm32/no-r32 +7183 0/imm32/no-imm32 +7184 0/imm32/no-disp32 +7185 0/imm32/no-output +7186 _Primitive-loop-if->/imm32/next +7187 _Primitive-loop-if->: +7188 "loop-if->"/imm32/name +7189 0/imm32/inouts +7190 0/imm32/outputs +7191 "0f 8f/jump-if-> loop/disp32"/imm32/subx-name +7192 0/imm32/no-rm32 +7193 0/imm32/no-r32 +7194 0/imm32/no-imm32 +7195 0/imm32/no-disp32 +7196 0/imm32/no-output +7197 _Primitive-loop/imm32/next # we probably don't need an unconditional break +7198 _Primitive-loop: +7199 "loop"/imm32/name +7200 0/imm32/inouts +7201 0/imm32/outputs +7202 "e9/jump loop/disp32"/imm32/subx-name +7203 0/imm32/no-rm32 +7204 0/imm32/no-r32 +7205 0/imm32/no-imm32 +7206 0/imm32/no-disp32 +7207 0/imm32/no-output +7208 _Primitive-break-if-addr<-named/imm32/next +7209 # - branches to named blocks +7210 _Primitive-break-if-addr<-named: +7211 "break-if-addr<"/imm32/name +7212 Single-lit-var/imm32/inouts +7213 0/imm32/outputs +7214 "0f 82/jump-if-addr<"/imm32/subx-name +7215 0/imm32/no-rm32 +7216 0/imm32/no-r32 +7217 0/imm32/no-imm32 +7218 1/imm32/disp32-is-first-inout +7219 0/imm32/no-output +7220 _Primitive-break-if-addr>=-named/imm32/next +7221 _Primitive-break-if-addr>=-named: +7222 "break-if-addr>="/imm32/name +7223 Single-lit-var/imm32/inouts +7224 0/imm32/outputs +7225 "0f 83/jump-if-addr>="/imm32/subx-name +7226 0/imm32/no-rm32 +7227 0/imm32/no-r32 +7228 0/imm32/no-imm32 +7229 1/imm32/disp32-is-first-inout +7230 0/imm32/no-output +7231 _Primitive-break-if-=-named/imm32/next +7232 _Primitive-break-if-=-named: +7233 "break-if-="/imm32/name +7234 Single-lit-var/imm32/inouts +7235 0/imm32/outputs +7236 "0f 84/jump-if-="/imm32/subx-name +7237 0/imm32/no-rm32 +7238 0/imm32/no-r32 +7239 0/imm32/no-imm32 +7240 1/imm32/disp32-is-first-inout +7241 0/imm32/no-output +7242 _Primitive-break-if-!=-named/imm32/next +7243 _Primitive-break-if-!=-named: +7244 "break-if-!="/imm32/name +7245 Single-lit-var/imm32/inouts +7246 0/imm32/outputs +7247 "0f 85/jump-if-!="/imm32/subx-name +7248 0/imm32/no-rm32 +7249 0/imm32/no-r32 +7250 0/imm32/no-imm32 +7251 1/imm32/disp32-is-first-inout +7252 0/imm32/no-output +7253 _Primitive-break-if-addr<=-named/imm32/next +7254 _Primitive-break-if-addr<=-named: +7255 "break-if-addr<="/imm32/name +7256 Single-lit-var/imm32/inouts +7257 0/imm32/outputs +7258 "0f 86/jump-if-addr<="/imm32/subx-name +7259 0/imm32/no-rm32 +7260 0/imm32/no-r32 +7261 0/imm32/no-imm32 +7262 1/imm32/disp32-is-first-inout +7263 0/imm32/no-output +7264 _Primitive-break-if-addr>-named/imm32/next +7265 _Primitive-break-if-addr>-named: +7266 "break-if-addr>"/imm32/name +7267 Single-lit-var/imm32/inouts +7268 0/imm32/outputs +7269 "0f 87/jump-if-addr>"/imm32/subx-name +7270 0/imm32/no-rm32 +7271 0/imm32/no-r32 +7272 0/imm32/no-imm32 +7273 1/imm32/disp32-is-first-inout +7274 0/imm32/no-output +7275 _Primitive-break-if-<-named/imm32/next +7276 _Primitive-break-if-<-named: +7277 "break-if-<"/imm32/name +7278 Single-lit-var/imm32/inouts +7279 0/imm32/outputs +7280 "0f 8c/jump-if-<"/imm32/subx-name +7281 0/imm32/no-rm32 +7282 0/imm32/no-r32 +7283 0/imm32/no-imm32 +7284 1/imm32/disp32-is-first-inout +7285 0/imm32/no-output +7286 _Primitive-break-if->=-named/imm32/next +7287 _Primitive-break-if->=-named: +7288 "break-if->="/imm32/name +7289 Single-lit-var/imm32/inouts +7290 0/imm32/outputs +7291 "0f 8d/jump-if->="/imm32/subx-name +7292 0/imm32/no-rm32 +7293 0/imm32/no-r32 +7294 0/imm32/no-imm32 +7295 1/imm32/disp32-is-first-inout +7296 0/imm32/no-output +7297 _Primitive-break-if-<=-named/imm32/next +7298 _Primitive-break-if-<=-named: +7299 "break-if-<="/imm32/name +7300 Single-lit-var/imm32/inouts +7301 0/imm32/outputs +7302 "0f 8e/jump-if-<="/imm32/subx-name +7303 0/imm32/no-rm32 +7304 0/imm32/no-r32 +7305 0/imm32/no-imm32 +7306 1/imm32/disp32-is-first-inout +7307 0/imm32/no-output +7308 _Primitive-break-if->-named/imm32/next +7309 _Primitive-break-if->-named: +7310 "break-if->"/imm32/name +7311 Single-lit-var/imm32/inouts +7312 0/imm32/outputs +7313 "0f 8f/jump-if->"/imm32/subx-name +7314 0/imm32/no-rm32 +7315 0/imm32/no-r32 +7316 0/imm32/no-imm32 +7317 1/imm32/disp32-is-first-inout +7318 0/imm32/no-output +7319 _Primitive-break-named/imm32/next +7320 _Primitive-break-named: +7321 "break"/imm32/name +7322 Single-lit-var/imm32/inouts +7323 0/imm32/outputs +7324 "e9/jump"/imm32/subx-name +7325 0/imm32/no-rm32 +7326 0/imm32/no-r32 +7327 0/imm32/no-imm32 +7328 1/imm32/disp32-is-first-inout +7329 0/imm32/no-output +7330 _Primitive-loop-if-addr<-named/imm32/next +7331 _Primitive-loop-if-addr<-named: +7332 "loop-if-addr<"/imm32/name +7333 Single-lit-var/imm32/inouts +7334 0/imm32/outputs +7335 "0f 82/jump-if-addr<"/imm32/subx-name +7336 0/imm32/no-rm32 +7337 0/imm32/no-r32 +7338 0/imm32/no-imm32 +7339 1/imm32/disp32-is-first-inout +7340 0/imm32/no-output +7341 _Primitive-loop-if-addr>=-named/imm32/next +7342 _Primitive-loop-if-addr>=-named: +7343 "loop-if-addr>="/imm32/name +7344 Single-lit-var/imm32/inouts +7345 0/imm32/outputs +7346 "0f 83/jump-if-addr>="/imm32/subx-name +7347 0/imm32/no-rm32 +7348 0/imm32/no-r32 +7349 0/imm32/no-imm32 +7350 1/imm32/disp32-is-first-inout +7351 0/imm32/no-output +7352 _Primitive-loop-if-=-named/imm32/next +7353 _Primitive-loop-if-=-named: +7354 "loop-if-="/imm32/name +7355 Single-lit-var/imm32/inouts +7356 0/imm32/outputs +7357 "0f 84/jump-if-="/imm32/subx-name +7358 0/imm32/no-rm32 +7359 0/imm32/no-r32 +7360 0/imm32/no-imm32 +7361 1/imm32/disp32-is-first-inout +7362 0/imm32/no-output +7363 _Primitive-loop-if-!=-named/imm32/next +7364 _Primitive-loop-if-!=-named: +7365 "loop-if-!="/imm32/name +7366 Single-lit-var/imm32/inouts +7367 0/imm32/outputs +7368 "0f 85/jump-if-!="/imm32/subx-name +7369 0/imm32/no-rm32 +7370 0/imm32/no-r32 +7371 0/imm32/no-imm32 +7372 1/imm32/disp32-is-first-inout +7373 0/imm32/no-output +7374 _Primitive-loop-if-addr<=-named/imm32/next +7375 _Primitive-loop-if-addr<=-named: +7376 "loop-if-addr<="/imm32/name +7377 Single-lit-var/imm32/inouts +7378 0/imm32/outputs +7379 "0f 86/jump-if-addr<="/imm32/subx-name +7380 0/imm32/no-rm32 +7381 0/imm32/no-r32 +7382 0/imm32/no-imm32 +7383 1/imm32/disp32-is-first-inout +7384 0/imm32/no-output +7385 _Primitive-loop-if-addr>-named/imm32/next +7386 _Primitive-loop-if-addr>-named: +7387 "loop-if-addr>"/imm32/name +7388 Single-lit-var/imm32/inouts +7389 0/imm32/outputs +7390 "0f 87/jump-if-addr>"/imm32/subx-name +7391 0/imm32/no-rm32 +7392 0/imm32/no-r32 +7393 0/imm32/no-imm32 +7394 1/imm32/disp32-is-first-inout +7395 0/imm32/no-output +7396 _Primitive-loop-if-<-named/imm32/next +7397 _Primitive-loop-if-<-named: +7398 "loop-if-<"/imm32/name +7399 Single-lit-var/imm32/inouts +7400 0/imm32/outputs +7401 "0f 8c/jump-if-<"/imm32/subx-name +7402 0/imm32/no-rm32 +7403 0/imm32/no-r32 +7404 0/imm32/no-imm32 +7405 1/imm32/disp32-is-first-inout +7406 0/imm32/no-output +7407 _Primitive-loop-if->=-named/imm32/next +7408 _Primitive-loop-if->=-named: +7409 "loop-if->="/imm32/name +7410 Single-lit-var/imm32/inouts +7411 0/imm32/outputs +7412 "0f 8d/jump-if->="/imm32/subx-name +7413 0/imm32/no-rm32 +7414 0/imm32/no-r32 +7415 0/imm32/no-imm32 +7416 1/imm32/disp32-is-first-inout +7417 0/imm32/no-output +7418 _Primitive-loop-if-<=-named/imm32/next +7419 _Primitive-loop-if-<=-named: +7420 "loop-if-<="/imm32/name +7421 Single-lit-var/imm32/inouts +7422 0/imm32/outputs +7423 "0f 8e/jump-if-<="/imm32/subx-name +7424 0/imm32/no-rm32 +7425 0/imm32/no-r32 +7426 0/imm32/no-imm32 +7427 1/imm32/disp32-is-first-inout +7428 0/imm32/no-output +7429 _Primitive-loop-if->-named/imm32/next +7430 _Primitive-loop-if->-named: +7431 "loop-if->"/imm32/name +7432 Single-lit-var/imm32/inouts +7433 0/imm32/outputs +7434 "0f 8f/jump-if->"/imm32/subx-name +7435 0/imm32/no-rm32 +7436 0/imm32/no-r32 +7437 0/imm32/no-imm32 +7438 1/imm32/disp32-is-first-inout +7439 0/imm32/no-output +7440 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break +7441 _Primitive-loop-named: +7442 "loop"/imm32/name +7443 Single-lit-var/imm32/inouts +7444 0/imm32/outputs +7445 "e9/jump"/imm32/subx-name +7446 0/imm32/no-rm32 +7447 0/imm32/no-r32 +7448 0/imm32/no-imm32 +7449 1/imm32/disp32-is-first-inout +7450 0/imm32/no-output +7451 0/imm32/next +7452 +7453 Single-int-var-in-mem: +7454 Int-var-in-mem/imm32 +7455 0/imm32/next +7456 +7457 Int-var-in-mem: +7458 "arg1"/imm32/name +7459 Type-int/imm32 +7460 1/imm32/some-block-depth +7461 1/imm32/some-stack-offset +7462 0/imm32/no-register +7463 +7464 Two-args-int-stack-int-reg: +7465 Int-var-in-mem/imm32 +7466 Single-int-var-in-some-register/imm32/next +7467 +7468 Two-args-int-reg-int-stack: +7469 Int-var-in-some-register/imm32 +7470 Single-int-var-in-mem/imm32/next +7471 +7472 Two-args-int-eax-int-literal: +7473 Int-var-in-eax/imm32 +7474 Single-lit-var/imm32/next +7475 +7476 Int-var-and-literal: +7477 Int-var-in-mem/imm32 +7478 Single-lit-var/imm32/next +7479 +7480 Int-var-in-register-and-literal: +7481 Int-var-in-some-register/imm32 +7482 Single-lit-var/imm32/next +7483 +7484 Single-int-var-in-some-register: +7485 Int-var-in-some-register/imm32 +7486 0/imm32/next +7487 +7488 Int-var-in-some-register: +7489 "arg1"/imm32/name +7490 Type-int/imm32 +7491 1/imm32/some-block-depth +7492 0/imm32/no-stack-offset +7493 Any-register/imm32 +7494 +7495 Single-int-var-in-eax: +7496 Int-var-in-eax/imm32 +7497 0/imm32/next +7498 +7499 Int-var-in-eax: +7500 "arg1"/imm32/name +7501 Type-int/imm32 +7502 1/imm32/some-block-depth +7503 0/imm32/no-stack-offset +7504 "eax"/imm32/register +7505 +7506 Single-int-var-in-ecx: +7507 Int-var-in-ecx/imm32 +7508 0/imm32/next +7509 +7510 Int-var-in-ecx: +7511 "arg1"/imm32/name +7512 Type-int/imm32 +7513 1/imm32/some-block-depth +7514 0/imm32/no-stack-offset +7515 "ecx"/imm32/register +7516 +7517 Single-int-var-in-edx: +7518 Int-var-in-edx/imm32 +7519 0/imm32/next +7520 +7521 Int-var-in-edx: +7522 "arg1"/imm32/name +7523 Type-int/imm32 +7524 1/imm32/some-block-depth +7525 0/imm32/no-stack-offset +7526 "edx"/imm32/register +7527 +7528 Single-int-var-in-ebx: +7529 Int-var-in-ebx/imm32 +7530 0/imm32/next +7531 +7532 Int-var-in-ebx: +7533 "arg1"/imm32/name +7534 Type-int/imm32 +7535 1/imm32/some-block-depth +7536 0/imm32/no-stack-offset +7537 "ebx"/imm32/register +7538 +7539 Single-int-var-in-esi: +7540 Int-var-in-esi/imm32 +7541 0/imm32/next +7542 +7543 Int-var-in-esi: +7544 "arg1"/imm32/name +7545 Type-int/imm32 +7546 1/imm32/some-block-depth +7547 0/imm32/no-stack-offset +7548 "esi"/imm32/register +7549 +7550 Single-int-var-in-edi: +7551 Int-var-in-edi/imm32 +7552 0/imm32/next +7553 +7554 Int-var-in-edi: +7555 "arg1"/imm32/name +7556 Type-int/imm32 +7557 1/imm32/some-block-depth +7558 0/imm32/no-stack-offset +7559 "edi"/imm32/register +7560 +7561 Single-lit-var: +7562 Lit-var/imm32 +7563 0/imm32/next +7564 +7565 Lit-var: +7566 "literal"/imm32/name +7567 Type-literal/imm32 +7568 1/imm32/some-block-depth +7569 0/imm32/no-stack-offset +7570 0/imm32/no-register +7571 +7572 Type-int: +7573 1/imm32/left/int +7574 0/imm32/right/null +7575 +7576 Type-literal: +7577 0/imm32/left/literal +7578 0/imm32/right/null +7579 +7580 == code +7581 emit-subx-primitive: # out: (addr buffered-file), stmt: (handle stmt), primitive: (handle function) +7582 # . prologue +7583 55/push-ebp +7584 89/<- %ebp 4/r32/esp +7585 # . save registers +7586 50/push-eax +7587 51/push-ecx +7588 # ecx = primitive +7589 8b/-> *(ebp+0x10) 1/r32/ecx +7590 # emit primitive name +7591 (emit-indent *(ebp+8) *Curr-block-depth) +7592 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name +7593 # emit rm32 if necessary +7594 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt +7595 # emit r32 if necessary +7596 (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt +7597 # emit imm32 if necessary +7598 (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt +7599 # emit disp32 if necessary +7600 (emit-subx-disp32 *(ebp+8) *(ecx+0x1c) *(ebp+0xc)) # out, Primitive-subx-disp32, stmt +7601 (write-buffered *(ebp+8) Newline) +7602 $emit-subx-primitive:end: +7603 # . restore registers +7604 59/pop-to-ecx +7605 58/pop-to-eax +7606 # . epilogue +7607 89/<- %esp 5/r32/ebp +7608 5d/pop-to-ebp +7609 c3/return +7610 +7611 emit-subx-rm32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) +7612 # . prologue +7613 55/push-ebp +7614 89/<- %ebp 4/r32/esp +7615 # . save registers +7616 50/push-eax +7617 # if (l == 0) return +7618 81 7/subop/compare *(ebp+0xc) 0/imm32 +7619 74/jump-if-= $emit-subx-rm32:end/disp8 +7620 # var v/eax: (handle var) +7621 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax +7622 (emit-subx-var-as-rm32 *(ebp+8) %eax) +7623 $emit-subx-rm32:end: +7624 # . restore registers +7625 58/pop-to-eax +7626 # . epilogue +7627 89/<- %esp 5/r32/ebp +7628 5d/pop-to-ebp +7629 c3/return +7630 +7631 get-stmt-operand-from-arg-location: # stmt: (handle stmt), l: arg-location -> var/eax: (handle stmt-var) +7632 # . prologue +7633 55/push-ebp +7634 89/<- %ebp 4/r32/esp +7635 # . save registers +7636 51/push-ecx +7637 # eax = l +7638 8b/-> *(ebp+0xc) 0/r32/eax +7639 # ecx = stmt +7640 8b/-> *(ebp+8) 1/r32/ecx +7641 # if (l == 1) return stmt->inouts +7642 { +7643 3d/compare-eax-and 1/imm32 +7644 75/jump-if-!= break/disp8 +7645 $get-stmt-operand-from-arg-location:1: +7646 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts +7647 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +7648 } +7649 # if (l == 2) return stmt->inouts->next +7650 { +7651 3d/compare-eax-and 2/imm32 +7652 75/jump-if-!= break/disp8 +7653 $get-stmt-operand-from-arg-location:2: +7654 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts +7655 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next +7656 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +7657 } +7658 # if (l == 3) return stmt->outputs +7659 { +7660 3d/compare-eax-and 3/imm32 +7661 75/jump-if-!= break/disp8 +7662 $get-stmt-operand-from-arg-location:3: +7663 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs +7664 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +7665 } +7666 # abort +7667 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 +7668 $get-stmt-operand-from-arg-location:end: +7669 # . restore registers +7670 59/pop-to-ecx +7671 # . epilogue +7672 89/<- %esp 5/r32/ebp +7673 5d/pop-to-ebp +7674 c3/return +7675 +7676 $get-stmt-operand-from-arg-location:abort: +7677 # error("invalid arg-location " eax) +7678 (write-buffered Stderr "invalid arg-location ") +7679 (print-int32-buffered Stderr %eax) +7680 (write-buffered Stderr Newline) +7681 (flush Stderr) +7682 # . syscall(exit, 1) +7683 bb/copy-to-ebx 1/imm32 +7684 b8/copy-to-eax 1/imm32/exit +7685 cd/syscall 0x80/imm8 +7686 # never gets here +7687 +7688 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) +7689 # . prologue +7690 55/push-ebp +7691 89/<- %ebp 4/r32/esp +7692 # . save registers +7693 50/push-eax +7694 51/push-ecx +7695 # if (location == 0) return +7696 81 7/subop/compare *(ebp+0xc) 0/imm32 +7697 0f 84/jump-if-= $emit-subx-r32:end/disp32 +7698 # var v/eax: (handle var) +7699 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax +7700 8b/-> *eax 0/r32/eax # Stmt-var-value +7701 (maybe-get Registers *(eax+0x10) 8) # Var-register => eax: (addr register-index) +7702 (write-buffered *(ebp+8) Space) +7703 (print-int32-buffered *(ebp+8) *eax) +7704 (write-buffered *(ebp+8) "/r32") +7705 $emit-subx-r32:end: +7706 # . restore registers +7707 59/pop-to-ecx +7708 58/pop-to-eax +7709 # . epilogue +7710 89/<- %esp 5/r32/ebp +7711 5d/pop-to-ebp +7712 c3/return +7713 +7714 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) +7715 # . prologue +7716 55/push-ebp +7717 89/<- %ebp 4/r32/esp +7718 # . save registers +7719 50/push-eax +7720 51/push-ecx +7721 # if (location == 0) return +7722 81 7/subop/compare *(ebp+0xc) 0/imm32 +7723 74/jump-if-= $emit-subx-imm32:end/disp8 +7724 # var v/eax: (handle var) +7725 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax +7726 8b/-> *eax 0/r32/eax # Stmt-var-value +7727 (write-buffered *(ebp+8) Space) +7728 (write-buffered *(ebp+8) *eax) # Var-name +7729 (write-buffered *(ebp+8) "/imm32") +7730 $emit-subx-imm32:end: 7731 # . restore registers 7732 59/pop-to-ecx -7733 # . epilogue -7734 89/<- %esp 5/r32/ebp -7735 5d/pop-to-ebp -7736 c3/return -7737 -7738 is-literal-type?: # a: (handle tree type-id) -> result/eax: boolean -7739 # . prologue -7740 55/push-ebp -7741 89/<- %ebp 4/r32/esp -7742 # -7743 8b/-> *(ebp+8) 0/r32/eax -7744 8b/-> *eax 0/r32/eax # Atom-value -7745 3d/compare-eax-and 0/imm32/false -7746 74/jump-if-equal $is-literal-type?:end/disp8 -7747 b8/copy-to-eax 1/imm32/true -7748 $is-literal-type?:end: -7749 # . epilogue -7750 89/<- %esp 5/r32/ebp -7751 5d/pop-to-ebp -7752 c3/return -7753 -7754 test-emit-subx-statement-primitive: -7755 # Primitive operation on a variable on the stack. -7756 # increment foo -7757 # => -7758 # ff 0/subop/increment *(ebp-8) -7759 # -7760 # There's a variable on the var stack as follows: -7761 # name: 'foo' -7762 # type: int -7763 # stack-offset: -8 -7764 # -7765 # There's a primitive with this info: -7766 # name: 'increment' -7767 # inouts: int/mem -7768 # value: 'ff 0/subop/increment' -7769 # -7770 # There's nothing in functions. -7771 # -7772 # . prologue -7773 55/push-ebp -7774 89/<- %ebp 4/r32/esp -7775 # setup -7776 (clear-stream _test-output-stream) -7777 (clear-stream $_test-output-buffered-file->buffer) -7778 # var type/ecx: (handle tree type-id) = int -7779 68/push 0/imm32/right/null -7780 68/push 1/imm32/left/int -7781 89/<- %ecx 4/r32/esp -7782 # var var-foo/ecx: var -7783 68/push 0/imm32/no-register -7784 68/push -8/imm32/stack-offset -7785 68/push 1/imm32/block-depth +7733 58/pop-to-eax +7734 # . epilogue +7735 89/<- %esp 5/r32/ebp +7736 5d/pop-to-ebp +7737 c3/return +7738 +7739 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) +7740 # . prologue +7741 55/push-ebp +7742 89/<- %ebp 4/r32/esp +7743 # . save registers +7744 50/push-eax +7745 51/push-ecx +7746 # if (location == 0) return +7747 81 7/subop/compare *(ebp+0xc) 0/imm32 +7748 0f 84/jump-if-= $emit-subx-disp32:end/disp32 +7749 # var v/eax: (handle var) +7750 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax +7751 8b/-> *eax 0/r32/eax # Stmt-var-value +7752 (write-buffered *(ebp+8) Space) +7753 (write-buffered *(ebp+8) *eax) # Var-name +7754 # hack: if instruction operation starts with "break", emit ":break" +7755 # var name/ecx: (addr array byte) = stmt->operation +7756 8b/-> *(ebp+0x10) 0/r32/eax +7757 8b/-> *(eax+4) 1/r32/ecx +7758 { +7759 (string-starts-with? %ecx "break") # => eax +7760 3d/compare-eax-and 0/imm32/false +7761 74/jump-if-= break/disp8 +7762 (write-buffered *(ebp+8) ":break") +7763 } +7764 # hack: if instruction operation starts with "loop", emit ":loop" +7765 { +7766 (string-starts-with? %ecx "loop") # => eax +7767 3d/compare-eax-and 0/imm32/false +7768 74/jump-if-= break/disp8 +7769 (write-buffered *(ebp+8) ":loop") +7770 } +7771 (write-buffered *(ebp+8) "/disp32") +7772 $emit-subx-disp32:end: +7773 # . restore registers +7774 59/pop-to-ecx +7775 58/pop-to-eax +7776 # . epilogue +7777 89/<- %esp 5/r32/ebp +7778 5d/pop-to-ebp +7779 c3/return +7780 +7781 emit-subx-call: # out: (addr buffered-file), stmt: (handle stmt), callee: (handle function) +7782 # . prologue +7783 55/push-ebp +7784 89/<- %ebp 4/r32/esp +7785 # . save registers 7786 51/push-ecx -7787 68/push "foo"/imm32 -7788 89/<- %ecx 4/r32/esp -7789 # var operand/ebx: (handle stmt-var) -7790 68/push 0/imm32/is-deref:false -7791 68/push 0/imm32/next -7792 51/push-ecx/var-foo -7793 89/<- %ebx 4/r32/esp -7794 # var stmt/esi: statement -7795 68/push 0/imm32/next -7796 68/push 0/imm32/outputs -7797 53/push-ebx/operands -7798 68/push "increment"/imm32/operation -7799 68/push 1/imm32 -7800 89/<- %esi 4/r32/esp -7801 # var primitives/ebx: primitive -7802 68/push 0/imm32/next -7803 68/push 0/imm32/output-is-write-only -7804 68/push 0/imm32/no-disp32 -7805 68/push 0/imm32/no-imm32 -7806 68/push 0/imm32/no-r32 -7807 68/push 1/imm32/rm32-is-first-inout -7808 68/push "ff 0/subop/increment"/imm32/subx-name -7809 68/push 0/imm32/outputs -7810 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call -7811 68/push "increment"/imm32/name -7812 89/<- %ebx 4/r32/esp -7813 # convert -7814 c7 0/subop/copy *Curr-block-depth 0/imm32 -7815 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -7816 (flush _test-output-buffered-file) -7817 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -7823 # check output -7824 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-statement-primitive") -7825 # . epilogue -7826 89/<- %esp 5/r32/ebp -7827 5d/pop-to-ebp -7828 c3/return -7829 -7830 test-emit-subx-statement-primitive-register: -7831 # Primitive operation on a variable in a register. -7832 # foo <- increment -7833 # => -7834 # ff 0/subop/increment %eax # sub-optimal, but should suffice -7835 # -7836 # There's a variable on the var stack as follows: -7837 # name: 'foo' -7838 # type: int -7839 # register: 'eax' -7840 # -7841 # There's a primitive with this info: -7842 # name: 'increment' -7843 # out: int/reg -7844 # value: 'ff 0/subop/increment' +7787 # +7788 (emit-indent *(ebp+8) *Curr-block-depth) +7789 (write-buffered *(ebp+8) "(") +7790 # - emit function name +7791 8b/-> *(ebp+0x10) 1/r32/ecx +7792 (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name +7793 # - emit arguments +7794 # var curr/ecx: (handle stmt-var) = stmt->inouts +7795 8b/-> *(ebp+0xc) 1/r32/ecx +7796 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts +7797 { +7798 # if (curr == null) break +7799 81 7/subop/compare %ecx 0/imm32 +7800 74/jump-if-= break/disp8 +7801 # +7802 (emit-subx-call-operand *(ebp+8) %ecx) +7803 # curr = curr->next +7804 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next +7805 eb/jump loop/disp8 +7806 } +7807 # +7808 (write-buffered *(ebp+8) ")\n") +7809 $emit-subx-call:end: +7810 # . restore registers +7811 59/pop-to-ecx +7812 # . epilogue +7813 89/<- %esp 5/r32/ebp +7814 5d/pop-to-ebp +7815 c3/return +7816 +7817 # like a function call, except we have no idea what function it is +7818 # we hope it's defined in SubX and that the types are ok +7819 emit-hailmary-call: # out: (addr buffered-file), stmt: (handle stmt) +7820 # . prologue +7821 55/push-ebp +7822 89/<- %ebp 4/r32/esp +7823 # . save registers +7824 51/push-ecx +7825 # +7826 (emit-indent *(ebp+8) *Curr-block-depth) +7827 (write-buffered *(ebp+8) "(") +7828 # ecx = stmt +7829 8b/-> *(ebp+0xc) 1/r32/ecx +7830 # - emit function name +7831 (write-buffered *(ebp+8) *(ecx+4)) # Stmt1-operation +7832 # - emit arguments +7833 # var curr/ecx: (handle stmt-var) = stmt->inouts +7834 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts +7835 { +7836 # if (curr == null) break +7837 81 7/subop/compare %ecx 0/imm32 +7838 74/jump-if-= break/disp8 +7839 # +7840 (emit-subx-call-operand *(ebp+8) %ecx) +7841 # curr = curr->next +7842 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next +7843 eb/jump loop/disp8 +7844 } 7845 # -7846 # There's nothing in functions. -7847 # -7848 # . prologue -7849 55/push-ebp -7850 89/<- %ebp 4/r32/esp -7851 # setup -7852 (clear-stream _test-output-stream) -7853 (clear-stream $_test-output-buffered-file->buffer) -7854 # var type/ecx: (handle tree type-id) = int -7855 68/push 0/imm32/right/null -7856 68/push 1/imm32/left/int -7857 89/<- %ecx 4/r32/esp -7858 # var var-foo/ecx: var in eax -7859 68/push "eax"/imm32/register -7860 68/push 0/imm32/no-stack-offset -7861 68/push 1/imm32/block-depth +7846 (write-buffered *(ebp+8) ")\n") +7847 $emit-hailmary-call:end: +7848 # . restore registers +7849 59/pop-to-ecx +7850 # . epilogue +7851 89/<- %esp 5/r32/ebp +7852 5d/pop-to-ebp +7853 c3/return +7854 +7855 emit-subx-call-operand: # out: (addr buffered-file), s: (handle stmt-var) +7856 # shares code with emit-subx-var-as-rm32 +7857 # . prologue +7858 55/push-ebp +7859 89/<- %ebp 4/r32/esp +7860 # . save registers +7861 50/push-eax 7862 51/push-ecx -7863 68/push "foo"/imm32 -7864 89/<- %ecx 4/r32/esp -7865 # var operand/ebx: (handle stmt-var) -7866 68/push 0/imm32/is-deref:false -7867 68/push 0/imm32/next -7868 51/push-ecx/var-foo -7869 89/<- %ebx 4/r32/esp -7870 # var stmt/esi: statement -7871 68/push 0/imm32/next -7872 53/push-ebx/outputs -7873 68/push 0/imm32/inouts -7874 68/push "increment"/imm32/operation -7875 68/push 1/imm32 -7876 89/<- %esi 4/r32/esp -7877 # var formal-var/ebx: var in any register -7878 68/push Any-register/imm32 -7879 68/push 0/imm32/no-stack-offset -7880 68/push 1/imm32/block-depth -7881 ff 6/subop/push *(ecx+4) # Var-type -7882 68/push "dummy"/imm32 -7883 89/<- %ebx 4/r32/esp -7884 # var operand/ebx: (handle stmt-var) -7885 68/push 0/imm32/is-deref:false -7886 68/push 0/imm32/next -7887 53/push-ebx/formal-var -7888 89/<- %ebx 4/r32/esp -7889 # var primitives/ebx: primitive -7890 68/push 0/imm32/next -7891 68/push 0/imm32/output-is-write-only -7892 68/push 0/imm32/no-disp32 -7893 68/push 0/imm32/no-imm32 -7894 68/push 0/imm32/no-r32 -7895 68/push 3/imm32/rm32-in-first-output -7896 68/push "ff 0/subop/increment"/imm32/subx-name -7897 53/push-ebx/outputs -7898 68/push 0/imm32/inouts -7899 68/push "increment"/imm32/name -7900 89/<- %ebx 4/r32/esp -7901 # convert -7902 c7 0/subop/copy *Curr-block-depth 0/imm32 -7903 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -7904 (flush _test-output-buffered-file) -7905 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -7911 # check output -7912 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-primitive-register") -7913 # . epilogue -7914 89/<- %esp 5/r32/ebp -7915 5d/pop-to-ebp -7916 c3/return -7917 -7918 test-emit-subx-statement-select-primitive: -7919 # Select the right primitive between overloads. -7920 # foo <- increment -7921 # => -7922 # ff 0/subop/increment %eax # sub-optimal, but should suffice -7923 # -7924 # There's a variable on the var stack as follows: -7925 # name: 'foo' -7926 # type: int -7927 # register: 'eax' -7928 # -7929 # There's two primitives, as follows: -7930 # - name: 'increment' -7931 # out: int/reg -7932 # value: 'ff 0/subop/increment' -7933 # - name: 'increment' -7934 # inout: int/mem -7935 # value: 'ff 0/subop/increment' -7936 # -7937 # There's nothing in functions. -7938 # -7939 # . prologue -7940 55/push-ebp -7941 89/<- %ebp 4/r32/esp -7942 # setup -7943 (clear-stream _test-output-stream) -7944 (clear-stream $_test-output-buffered-file->buffer) -7945 # var type/ecx: (handle tree type-id) = int -7946 68/push 0/imm32/right/null -7947 68/push 1/imm32/left/int -7948 89/<- %ecx 4/r32/esp -7949 # var var-foo/ecx: var in eax -7950 68/push "eax"/imm32/register -7951 68/push 0/imm32/no-stack-offset -7952 68/push 1/imm32/block-depth -7953 51/push-ecx -7954 68/push "foo"/imm32 -7955 89/<- %ecx 4/r32/esp -7956 # var real-outputs/edi: (handle stmt-var) -7957 68/push 0/imm32/is-deref:false -7958 68/push 0/imm32/next -7959 51/push-ecx/var-foo -7960 89/<- %edi 4/r32/esp -7961 # var stmt/esi: statement -7962 68/push 0/imm32/next -7963 57/push-edi/outputs -7964 68/push 0/imm32/inouts -7965 68/push "increment"/imm32/operation -7966 68/push 1/imm32 -7967 89/<- %esi 4/r32/esp -7968 # var formal-var/ebx: var in any register -7969 68/push Any-register/imm32 -7970 68/push 0/imm32/no-stack-offset -7971 68/push 1/imm32/block-depth -7972 ff 6/subop/push *(ecx+4) # Var-type -7973 68/push "dummy"/imm32 -7974 89/<- %ebx 4/r32/esp -7975 # var formal-outputs/ebx: (handle stmt-var) -7976 68/push 0/imm32/is-deref:false -7977 68/push 0/imm32/next -7978 53/push-ebx/formal-var -7979 89/<- %ebx 4/r32/esp -7980 # var primitive1/ebx: primitive -7981 68/push 0/imm32/next -7982 68/push 0/imm32/output-is-write-only -7983 68/push 0/imm32/no-disp32 -7984 68/push 0/imm32/no-imm32 -7985 68/push 0/imm32/no-r32 -7986 68/push 3/imm32/rm32-in-first-output -7987 68/push "ff 0/subop/increment"/imm32/subx-name -7988 53/push-ebx/outputs/formal-outputs -7989 68/push 0/imm32/inouts -7990 68/push "increment"/imm32/name -7991 89/<- %ebx 4/r32/esp -7992 # var primitives/ebx: primitive -7993 53/push-ebx/next -7994 68/push 0/imm32/output-is-write-only -7995 68/push 0/imm32/no-disp32 -7996 68/push 0/imm32/no-imm32 -7997 68/push 0/imm32/no-r32 -7998 68/push 1/imm32/rm32-is-first-inout -7999 68/push "ff 0/subop/increment"/imm32/subx-name -8000 68/push 0/imm32/outputs -8001 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -8002 68/push "increment"/imm32/name -8003 89/<- %ebx 4/r32/esp -8004 # convert -8005 c7 0/subop/copy *Curr-block-depth 0/imm32 -8006 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -8007 (flush _test-output-buffered-file) -8008 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8014 # check output -8015 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive") -8016 # . epilogue -8017 89/<- %esp 5/r32/ebp -8018 5d/pop-to-ebp -8019 c3/return -8020 -8021 test-emit-subx-statement-select-primitive-2: -8022 # Select the right primitive between overloads. -8023 # foo <- increment -8024 # => -8025 # ff 0/subop/increment %eax # sub-optimal, but should suffice -8026 # -8027 # There's a variable on the var stack as follows: -8028 # name: 'foo' -8029 # type: int -8030 # register: 'eax' -8031 # -8032 # There's two primitives, as follows: -8033 # - name: 'increment' -8034 # out: int/reg -8035 # value: 'ff 0/subop/increment' -8036 # - name: 'increment' -8037 # inout: int/mem -8038 # value: 'ff 0/subop/increment' -8039 # -8040 # There's nothing in functions. -8041 # -8042 # . prologue -8043 55/push-ebp -8044 89/<- %ebp 4/r32/esp -8045 # setup -8046 (clear-stream _test-output-stream) -8047 (clear-stream $_test-output-buffered-file->buffer) -8048 # var type/ecx: (handle tree type-id) = int -8049 68/push 0/imm32/right/null -8050 68/push 1/imm32/left/int -8051 89/<- %ecx 4/r32/esp -8052 # var var-foo/ecx: var in eax -8053 68/push "eax"/imm32/register -8054 68/push 0/imm32/no-stack-offset -8055 68/push 1/imm32/block-depth -8056 51/push-ecx -8057 68/push "foo"/imm32 -8058 89/<- %ecx 4/r32/esp -8059 # var inouts/edi: (handle stmt-var) -8060 68/push 0/imm32/is-deref:false -8061 68/push 0/imm32/next -8062 51/push-ecx/var-foo -8063 89/<- %edi 4/r32/esp -8064 # var stmt/esi: statement -8065 68/push 0/imm32/next -8066 68/push 0/imm32/outputs -8067 57/push-edi/inouts -8068 68/push "increment"/imm32/operation -8069 68/push 1/imm32 -8070 89/<- %esi 4/r32/esp -8071 # var formal-var/ebx: var in any register -8072 68/push Any-register/imm32 -8073 68/push 0/imm32/no-stack-offset -8074 68/push 1/imm32/block-depth -8075 ff 6/subop/push *(ecx+4) # Var-type -8076 68/push "dummy"/imm32 -8077 89/<- %ebx 4/r32/esp -8078 # var operand/ebx: (handle stmt-var) -8079 68/push 0/imm32/is-deref:false -8080 68/push 0/imm32/next -8081 53/push-ebx/formal-var -8082 89/<- %ebx 4/r32/esp -8083 # var primitive1/ebx: primitive -8084 68/push 0/imm32/next -8085 68/push 0/imm32/output-is-write-only -8086 68/push 0/imm32/no-disp32 -8087 68/push 0/imm32/no-imm32 -8088 68/push 0/imm32/no-r32 -8089 68/push 3/imm32/rm32-in-first-output -8090 68/push "ff 0/subop/increment"/imm32/subx-name -8091 53/push-ebx/outputs/formal-outputs -8092 68/push 0/imm32/inouts -8093 68/push "increment"/imm32/name -8094 89/<- %ebx 4/r32/esp -8095 # var primitives/ebx: primitive -8096 53/push-ebx/next -8097 68/push 0/imm32/output-is-write-only -8098 68/push 0/imm32/no-disp32 -8099 68/push 0/imm32/no-imm32 -8100 68/push 0/imm32/no-r32 -8101 68/push 1/imm32/rm32-is-first-inout -8102 68/push "ff 0/subop/increment"/imm32/subx-name -8103 68/push 0/imm32/outputs -8104 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -8105 68/push "increment"/imm32/name -8106 89/<- %ebx 4/r32/esp -8107 # convert -8108 c7 0/subop/copy *Curr-block-depth 0/imm32 -8109 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -8110 (flush _test-output-buffered-file) -8111 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8117 # check output -8118 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2") -8119 # . epilogue -8120 89/<- %esp 5/r32/ebp -8121 5d/pop-to-ebp -8122 c3/return -8123 -8124 test-increment-register: -8125 # Select the right register between overloads. -8126 # foo <- increment -8127 # => -8128 # 50/increment-eax -8129 # -8130 # There's a variable on the var stack as follows: -8131 # name: 'foo' -8132 # type: int -8133 # register: 'eax' -8134 # -8135 # Primitives are the global definitions. -8136 # -8137 # There are no functions defined. -8138 # -8139 # . prologue -8140 55/push-ebp -8141 89/<- %ebp 4/r32/esp -8142 # setup -8143 (clear-stream _test-output-stream) -8144 (clear-stream $_test-output-buffered-file->buffer) -8145 # var type/ecx: (handle tree type-id) = int -8146 68/push 0/imm32/right/null -8147 68/push 1/imm32/left/int -8148 89/<- %ecx 4/r32/esp -8149 # var var-foo/ecx: var in eax -8150 68/push "eax"/imm32/register -8151 68/push 0/imm32/no-stack-offset -8152 68/push 1/imm32/block-depth -8153 51/push-ecx -8154 68/push "foo"/imm32 -8155 89/<- %ecx 4/r32/esp -8156 # var real-outputs/edi: (handle stmt-var) -8157 68/push 0/imm32/is-deref:false -8158 68/push 0/imm32/next -8159 51/push-ecx/var-foo -8160 89/<- %edi 4/r32/esp -8161 # var stmt/esi: statement -8162 68/push 0/imm32/next -8163 57/push-edi/outputs -8164 68/push 0/imm32/inouts -8165 68/push "increment"/imm32/operation -8166 68/push 1/imm32/regular-statement -8167 89/<- %esi 4/r32/esp -8168 # convert -8169 c7 0/subop/copy *Curr-block-depth 0/imm32 -8170 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8171 (flush _test-output-buffered-file) -8172 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8178 # check output -8179 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") -8180 # . epilogue -8181 89/<- %esp 5/r32/ebp -8182 5d/pop-to-ebp -8183 c3/return -8184 -8185 test-increment-var: -8186 # Select the right primitive between overloads. -8187 # foo <- increment -8188 # => -8189 # ff 0/subop/increment %eax # sub-optimal, but should suffice -8190 # -8191 # There's a variable on the var stack as follows: -8192 # name: 'foo' -8193 # type: int -8194 # register: 'eax' -8195 # -8196 # Primitives are the global definitions. -8197 # -8198 # There are no functions defined. -8199 # -8200 # . prologue -8201 55/push-ebp -8202 89/<- %ebp 4/r32/esp -8203 # setup -8204 (clear-stream _test-output-stream) -8205 (clear-stream $_test-output-buffered-file->buffer) -8206 # var type/ecx: (handle tree type-id) = int -8207 68/push 0/imm32/right/null -8208 68/push 1/imm32/left/int -8209 89/<- %ecx 4/r32/esp -8210 # var var-foo/ecx: var in eax -8211 68/push "eax"/imm32/register -8212 68/push 0/imm32/no-stack-offset -8213 68/push 1/imm32/block-depth -8214 51/push-ecx -8215 68/push "foo"/imm32 -8216 89/<- %ecx 4/r32/esp -8217 # var inouts/edi: (handle stmt-var) -8218 68/push 0/imm32/is-deref:false -8219 68/push 0/imm32/next -8220 51/push-ecx/var-foo -8221 89/<- %edi 4/r32/esp -8222 # var stmt/esi: statement -8223 68/push 0/imm32/next -8224 57/push-edi/outputs -8225 68/push 0/imm32/inouts -8226 68/push "increment"/imm32/operation -8227 68/push 1/imm32 -8228 89/<- %esi 4/r32/esp -8229 # convert -8230 c7 0/subop/copy *Curr-block-depth 0/imm32 -8231 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8232 (flush _test-output-buffered-file) -8233 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8239 # check output -8240 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-var") -8241 # . epilogue -8242 89/<- %esp 5/r32/ebp -8243 5d/pop-to-ebp -8244 c3/return -8245 -8246 test-add-reg-to-reg: -8247 # var1/reg <- add var2/reg -8248 # => -8249 # 01/add %var1 var2 -8250 # -8251 # . prologue -8252 55/push-ebp -8253 89/<- %ebp 4/r32/esp -8254 # setup -8255 (clear-stream _test-output-stream) -8256 (clear-stream $_test-output-buffered-file->buffer) -8257 # var type/ecx: (handle tree type-id) = int -8258 68/push 0/imm32/right/null -8259 68/push 1/imm32/left/int -8260 89/<- %ecx 4/r32/esp -8261 # var var-var1/ecx: var in eax -8262 68/push "eax"/imm32/register -8263 68/push 0/imm32/no-stack-offset -8264 68/push 1/imm32/block-depth -8265 51/push-ecx -8266 68/push "var1"/imm32 -8267 89/<- %ecx 4/r32/esp -8268 # var var-var2/edx: var in ecx -8269 68/push "ecx"/imm32/register -8270 68/push 0/imm32/no-stack-offset -8271 68/push 1/imm32/block-depth -8272 ff 6/subop/push *(ecx+4) # Var-type -8273 68/push "var2"/imm32 -8274 89/<- %edx 4/r32/esp -8275 # var inouts/esi: (handle stmt-var) = [var2] -8276 68/push 0/imm32/is-deref:false -8277 68/push 0/imm32/next -8278 52/push-edx/var-var2 -8279 89/<- %esi 4/r32/esp -8280 # var outputs/edi: (handle stmt-var) = [var1, var2] -8281 68/push 0/imm32/is-deref:false -8282 68/push 0/imm32/next -8283 51/push-ecx/var-var1 -8284 89/<- %edi 4/r32/esp -8285 # var stmt/esi: statement -8286 68/push 0/imm32/next -8287 57/push-edi/outputs -8288 56/push-esi/inouts -8289 68/push "add"/imm32/operation -8290 68/push 1/imm32 -8291 89/<- %esi 4/r32/esp -8292 # convert -8293 c7 0/subop/copy *Curr-block-depth 0/imm32 -8294 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8295 (flush _test-output-buffered-file) -8296 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8302 # check output -8303 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") -8304 # . epilogue -8305 89/<- %esp 5/r32/ebp -8306 5d/pop-to-ebp -8307 c3/return -8308 -8309 test-add-reg-to-mem: -8310 # add-to var1 var2/reg -8311 # => -8312 # 01/add *(ebp+__) var2 -8313 # -8314 # . prologue -8315 55/push-ebp -8316 89/<- %ebp 4/r32/esp -8317 # setup -8318 (clear-stream _test-output-stream) -8319 (clear-stream $_test-output-buffered-file->buffer) -8320 # var type/ecx: (handle tree type-id) = int -8321 68/push 0/imm32/right/null -8322 68/push 1/imm32/left/int -8323 89/<- %ecx 4/r32/esp -8324 # var var-var1/ecx: var -8325 68/push 0/imm32/no-register -8326 68/push 8/imm32/stack-offset -8327 68/push 1/imm32/block-depth -8328 51/push-ecx -8329 68/push "var1"/imm32 -8330 89/<- %ecx 4/r32/esp -8331 # var var-var2/edx: var in ecx -8332 68/push "ecx"/imm32/register -8333 68/push 0/imm32/no-stack-offset -8334 68/push 1/imm32/block-depth -8335 ff 6/subop/push *(ecx+4) # Var-type -8336 68/push "var2"/imm32 -8337 89/<- %edx 4/r32/esp -8338 # var inouts/esi: (handle stmt-var) = [var2] -8339 68/push 0/imm32/is-deref:false -8340 68/push 0/imm32/next -8341 52/push-edx/var-var2 -8342 89/<- %esi 4/r32/esp -8343 # var inouts = (handle stmt-var) = [var1, var2] -8344 56/push-esi/next -8345 51/push-ecx/var-var1 -8346 89/<- %esi 4/r32/esp -8347 # var stmt/esi: statement -8348 68/push 0/imm32/next -8349 68/push 0/imm32/outputs -8350 56/push-esi/inouts -8351 68/push "add-to"/imm32/operation -8352 68/push 1/imm32 -8353 89/<- %esi 4/r32/esp -8354 # convert -8355 c7 0/subop/copy *Curr-block-depth 0/imm32 -8356 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8357 (flush _test-output-buffered-file) -8358 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8364 # check output -8365 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") -8366 # . epilogue -8367 89/<- %esp 5/r32/ebp -8368 5d/pop-to-ebp -8369 c3/return -8370 -8371 test-add-mem-to-reg: -8372 # var1/reg <- add var2 -8373 # => -8374 # 03/add *(ebp+__) var1 -8375 # -8376 # . prologue -8377 55/push-ebp -8378 89/<- %ebp 4/r32/esp -8379 # setup -8380 (clear-stream _test-output-stream) -8381 (clear-stream $_test-output-buffered-file->buffer) -8382 # var type/ecx: (handle tree type-id) = int -8383 68/push 0/imm32/right/null -8384 68/push 1/imm32/left/int -8385 89/<- %ecx 4/r32/esp -8386 # var var-var1/ecx: var in eax -8387 68/push "eax"/imm32/register -8388 68/push 0/imm32/no-stack-offset -8389 68/push 1/imm32/block-depth -8390 51/push-ecx -8391 68/push "var1"/imm32 -8392 89/<- %ecx 4/r32/esp -8393 # var var-var2/edx: var -8394 68/push 0/imm32/no-register -8395 68/push 8/imm32/stack-offset -8396 68/push 1/imm32/block-depth -8397 ff 6/subop/push *(ecx+4) # Var-type -8398 68/push "var2"/imm32 -8399 89/<- %edx 4/r32/esp -8400 # var inouts/esi: (handle stmt-var) = [var2] -8401 68/push 0/imm32/is-deref:false -8402 68/push 0/imm32/next -8403 52/push-edx/var-var2 -8404 89/<- %esi 4/r32/esp -8405 # var outputs/edi = (handle stmt-var) = [var1] -8406 68/push 0/imm32/is-deref:false -8407 68/push 0/imm32/next -8408 51/push-ecx/var-var1 -8409 89/<- %edi 4/r32/esp -8410 # var stmt/esi: statement -8411 68/push 0/imm32/next -8412 57/push-edi/outputs -8413 56/push-esi/inouts -8414 68/push "add"/imm32/operation -8415 68/push 1/imm32 -8416 89/<- %esi 4/r32/esp -8417 # convert -8418 c7 0/subop/copy *Curr-block-depth 0/imm32 -8419 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8420 (flush _test-output-buffered-file) -8421 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8427 # check output -8428 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") -8429 # . epilogue -8430 89/<- %esp 5/r32/ebp -8431 5d/pop-to-ebp -8432 c3/return -8433 -8434 test-add-literal-to-eax: -8435 # var1/eax <- add 0x34 -8436 # => -8437 # 05/add-to-eax 0x34/imm32 -8438 # -8439 # . prologue -8440 55/push-ebp -8441 89/<- %ebp 4/r32/esp -8442 # setup -8443 (clear-stream _test-output-stream) -8444 (clear-stream $_test-output-buffered-file->buffer) -8445 # var type/ecx: (handle tree type-id) = int -8446 68/push 0/imm32/right/null -8447 68/push 1/imm32/left/int -8448 89/<- %ecx 4/r32/esp -8449 # var var-var1/ecx: var in eax -8450 68/push "eax"/imm32/register -8451 68/push 0/imm32/no-stack-offset -8452 68/push 1/imm32/block-depth -8453 51/push-ecx -8454 68/push "var1"/imm32 -8455 89/<- %ecx 4/r32/esp -8456 # var type/edx: (handle tree type-id) = literal -8457 68/push 0/imm32/right/null -8458 68/push 0/imm32/left/literal -8459 89/<- %edx 4/r32/esp -8460 # var var-var2/edx: var literal -8461 68/push 0/imm32/no-register -8462 68/push 0/imm32/no-stack-offset -8463 68/push 1/imm32/block-depth -8464 52/push-edx -8465 68/push "0x34"/imm32 -8466 89/<- %edx 4/r32/esp -8467 # var inouts/esi: (handle stmt-var) = [var2] -8468 68/push 0/imm32/is-deref:false -8469 68/push 0/imm32/next -8470 52/push-edx/var-var2 -8471 89/<- %esi 4/r32/esp -8472 # var outputs/edi: (handle stmt-var) = [var1] -8473 68/push 0/imm32/is-deref:false -8474 68/push 0/imm32/next -8475 51/push-ecx/var-var1 -8476 89/<- %edi 4/r32/esp -8477 # var stmt/esi: statement -8478 68/push 0/imm32/next -8479 57/push-edi/outputs -8480 56/push-esi/inouts -8481 68/push "add"/imm32/operation -8482 68/push 1/imm32 -8483 89/<- %esi 4/r32/esp -8484 # convert -8485 c7 0/subop/copy *Curr-block-depth 0/imm32 -8486 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8487 (flush _test-output-buffered-file) -8488 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8494 # check output -8495 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") -8496 # . epilogue -8497 89/<- %esp 5/r32/ebp -8498 5d/pop-to-ebp -8499 c3/return -8500 -8501 test-add-literal-to-reg: -8502 # var1/ecx <- add 0x34 -8503 # => -8504 # 81 0/subop/add %ecx 0x34/imm32 -8505 # -8506 # . prologue -8507 55/push-ebp -8508 89/<- %ebp 4/r32/esp -8509 # setup -8510 (clear-stream _test-output-stream) -8511 (clear-stream $_test-output-buffered-file->buffer) -8512 # var type/ecx: (handle tree type-id) = int -8513 68/push 0/imm32/right/null -8514 68/push 1/imm32/left/int -8515 89/<- %ecx 4/r32/esp -8516 # var var-var1/ecx: var in ecx -8517 68/push "ecx"/imm32/register -8518 68/push 0/imm32/no-stack-offset -8519 68/push 1/imm32/block-depth -8520 51/push-ecx -8521 68/push "var1"/imm32 -8522 89/<- %ecx 4/r32/esp -8523 # var type/edx: (handle tree type-id) = literal -8524 68/push 0/imm32/right/null -8525 68/push 0/imm32/left/literal -8526 89/<- %edx 4/r32/esp -8527 # var var-var2/edx: var literal -8528 68/push 0/imm32/no-register -8529 68/push 0/imm32/no-stack-offset -8530 68/push 1/imm32/block-depth -8531 52/push-edx -8532 68/push "0x34"/imm32 -8533 89/<- %edx 4/r32/esp -8534 # var inouts/esi: (handle stmt-var) = [var2] -8535 68/push 0/imm32/is-deref:false -8536 68/push 0/imm32/next -8537 52/push-edx/var-var2 -8538 89/<- %esi 4/r32/esp -8539 # var outputs/edi: (handle stmt-var) = [var1] -8540 68/push 0/imm32/is-deref:false -8541 68/push 0/imm32/next -8542 51/push-ecx/var-var1 -8543 89/<- %edi 4/r32/esp -8544 # var stmt/esi: statement -8545 68/push 0/imm32/next -8546 57/push-edi/outputs -8547 56/push-esi/inouts -8548 68/push "add"/imm32/operation -8549 68/push 1/imm32 -8550 89/<- %esi 4/r32/esp -8551 # convert -8552 c7 0/subop/copy *Curr-block-depth 0/imm32 -8553 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8554 (flush _test-output-buffered-file) -8555 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8561 # check output -8562 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") -8563 # . epilogue -8564 89/<- %esp 5/r32/ebp -8565 5d/pop-to-ebp -8566 c3/return -8567 -8568 test-add-literal-to-mem: -8569 # add-to var1, 0x34 -8570 # => -8571 # 81 0/subop/add %eax 0x34/imm32 -8572 # -8573 # . prologue -8574 55/push-ebp -8575 89/<- %ebp 4/r32/esp -8576 # setup -8577 (clear-stream _test-output-stream) -8578 (clear-stream $_test-output-buffered-file->buffer) -8579 # var type/ecx: (handle tree type-id) = int -8580 68/push 0/imm32/right/null -8581 68/push 1/imm32/left/int -8582 89/<- %ecx 4/r32/esp -8583 # var var-var1/ecx: var -8584 68/push 0/imm32/no-register -8585 68/push 8/imm32/stack-offset -8586 68/push 1/imm32/block-depth -8587 51/push-ecx -8588 68/push "var1"/imm32 -8589 89/<- %ecx 4/r32/esp -8590 # var type/edx: (handle tree type-id) = literal -8591 68/push 0/imm32/right/null -8592 68/push 0/imm32/left/literal -8593 89/<- %edx 4/r32/esp -8594 # var var-var2/edx: var literal -8595 68/push 0/imm32/no-register -8596 68/push 0/imm32/no-stack-offset -8597 68/push 1/imm32/block-depth -8598 52/push-edx -8599 68/push "0x34"/imm32 -8600 89/<- %edx 4/r32/esp -8601 # var inouts/esi: (handle stmt-var) = [var2] -8602 68/push 0/imm32/is-deref:false -8603 68/push 0/imm32/next -8604 52/push-edx/var-var2 -8605 89/<- %esi 4/r32/esp -8606 # var inouts = (handle stmt-var) = [var1, var2] -8607 68/push 0/imm32/is-deref:false -8608 56/push-esi/next -8609 51/push-ecx/var-var1 -8610 89/<- %esi 4/r32/esp -8611 # var stmt/esi: statement -8612 68/push 0/imm32/next -8613 68/push 0/imm32/outputs -8614 56/push-esi/inouts -8615 68/push "add-to"/imm32/operation -8616 68/push 1/imm32 -8617 89/<- %esi 4/r32/esp -8618 # convert -8619 c7 0/subop/copy *Curr-block-depth 0/imm32 -8620 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8621 (flush _test-output-buffered-file) -8622 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8628 # check output -8629 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") -8630 # . epilogue -8631 89/<- %esp 5/r32/ebp -8632 5d/pop-to-ebp -8633 c3/return -8634 -8635 test-compare-mem-with-reg: -8636 # compare var1, var2/eax -8637 # => -8638 # 39/compare *(ebp+___) 0/r32/eax -8639 # -8640 # . prologue -8641 55/push-ebp -8642 89/<- %ebp 4/r32/esp -8643 # setup -8644 (clear-stream _test-output-stream) -8645 (clear-stream $_test-output-buffered-file->buffer) -8646 # var type/ecx: (handle tree type-id) = int -8647 68/push 0/imm32/right/null -8648 68/push 1/imm32/left/int -8649 89/<- %ecx 4/r32/esp -8650 # var var-var2/ecx: var in eax -8651 68/push "eax"/imm32/register -8652 68/push 0/imm32/no-stack-offset -8653 68/push 1/imm32/block-depth -8654 51/push-ecx -8655 68/push "var2"/imm32 -8656 89/<- %ecx 4/r32/esp -8657 # var var-var1/edx: var -8658 68/push 0/imm32/no-register -8659 68/push 8/imm32/stack-offset -8660 68/push 1/imm32/block-depth -8661 ff 6/subop/push *(ecx+4) # Var-type -8662 68/push "var1"/imm32 -8663 89/<- %edx 4/r32/esp -8664 # var inouts/esi: (handle stmt-var) = [var2] -8665 68/push 0/imm32/is-deref:false -8666 68/push 0/imm32/next -8667 51/push-ecx/var-var2 -8668 89/<- %esi 4/r32/esp -8669 # inouts = [var1, var2] -8670 68/push 0/imm32/is-deref:false -8671 56/push-esi -8672 52/push-edx/var-var1 -8673 89/<- %esi 4/r32/esp -8674 # var stmt/esi: statement -8675 68/push 0/imm32/next -8676 68/push 0/imm32/outputs -8677 56/push-esi/inouts -8678 68/push "compare"/imm32/operation -8679 68/push 1/imm32 -8680 89/<- %esi 4/r32/esp -8681 # convert -8682 c7 0/subop/copy *Curr-block-depth 0/imm32 -8683 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8684 (flush _test-output-buffered-file) -8685 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8691 # check output -8692 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") -8693 # . epilogue -8694 89/<- %esp 5/r32/ebp -8695 5d/pop-to-ebp -8696 c3/return -8697 -8698 test-compare-reg-with-mem: -8699 # compare var1/eax, var2 -8700 # => -8701 # 3b/compare *(ebp+___) 0/r32/eax -8702 # -8703 # . prologue -8704 55/push-ebp -8705 89/<- %ebp 4/r32/esp -8706 # setup -8707 (clear-stream _test-output-stream) -8708 (clear-stream $_test-output-buffered-file->buffer) -8709 # var type/ecx: (handle tree type-id) = int -8710 68/push 0/imm32/right/null -8711 68/push 1/imm32/left/int -8712 89/<- %ecx 4/r32/esp -8713 # var var-var1/ecx: var in eax -8714 68/push "eax"/imm32/register -8715 68/push 0/imm32/no-stack-offset -8716 68/push 1/imm32/block-depth -8717 51/push-ecx -8718 68/push "var1"/imm32 -8719 89/<- %ecx 4/r32/esp -8720 # var var-var2/edx: var -8721 68/push 0/imm32/no-register -8722 68/push 8/imm32/stack-offset -8723 68/push 1/imm32/block-depth -8724 ff 6/subop/push *(ecx+4) # Var-type -8725 68/push "var2"/imm32 -8726 89/<- %edx 4/r32/esp -8727 # var inouts/esi: (handle stmt-var) = [var2] -8728 68/push 0/imm32/is-deref:false -8729 68/push 0/imm32/next -8730 52/push-edx/var-var2 -8731 89/<- %esi 4/r32/esp -8732 # inouts = [var1, var2] -8733 68/push 0/imm32/is-deref:false -8734 56/push-esi -8735 51/push-ecx/var-var1 -8736 89/<- %esi 4/r32/esp -8737 # var stmt/esi: statement -8738 68/push 0/imm32/next -8739 68/push 0/imm32/outputs -8740 56/push-esi/inouts -8741 68/push "compare"/imm32/operation -8742 68/push 1/imm32 -8743 89/<- %esi 4/r32/esp -8744 # convert -8745 c7 0/subop/copy *Curr-block-depth 0/imm32 -8746 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8747 (flush _test-output-buffered-file) -8748 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8754 # check output -8755 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") -8756 # . epilogue -8757 89/<- %esp 5/r32/ebp -8758 5d/pop-to-ebp -8759 c3/return -8760 -8761 test-compare-mem-with-literal: -8762 # compare var1, 0x34 -8763 # => -8764 # 81 7/subop/compare *(ebp+___) 0x34/imm32 -8765 # -8766 # . prologue -8767 55/push-ebp -8768 89/<- %ebp 4/r32/esp -8769 # setup -8770 (clear-stream _test-output-stream) -8771 (clear-stream $_test-output-buffered-file->buffer) -8772 # var type/ecx: (handle tree type-id) = int -8773 68/push 0/imm32/right/null -8774 68/push 1/imm32/left/int -8775 89/<- %ecx 4/r32/esp -8776 # var var-var1/ecx: var -8777 68/push 0/imm32/no-register -8778 68/push 8/imm32/stack-offset -8779 68/push 1/imm32/block-depth -8780 51/push-ecx -8781 68/push "var1"/imm32 -8782 89/<- %ecx 4/r32/esp -8783 # var type/edx: (handle tree type-id) = literal -8784 68/push 0/imm32/right/null -8785 68/push 0/imm32/left/literal -8786 89/<- %edx 4/r32/esp -8787 # var var-var2/edx: var literal -8788 68/push 0/imm32/no-register -8789 68/push 0/imm32/no-stack-offset -8790 68/push 1/imm32/block-depth -8791 52/push-edx -8792 68/push "0x34"/imm32 -8793 89/<- %edx 4/r32/esp -8794 # var inouts/esi: (handle stmt-var) = [var2] -8795 68/push 0/imm32/is-deref:false -8796 68/push 0/imm32/next -8797 52/push-edx/var-var2 -8798 89/<- %esi 4/r32/esp -8799 # inouts = [var1, var2] -8800 68/push 0/imm32/is-deref:false -8801 56/push-esi/next -8802 51/push-ecx/var-var1 -8803 89/<- %esi 4/r32/esp -8804 # var stmt/esi: statement -8805 68/push 0/imm32/next -8806 68/push 0/imm32/outputs -8807 56/push-esi/inouts -8808 68/push "compare"/imm32/operation -8809 68/push 1/imm32 -8810 89/<- %esi 4/r32/esp -8811 # convert -8812 c7 0/subop/copy *Curr-block-depth 0/imm32 -8813 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8814 (flush _test-output-buffered-file) -8815 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8821 # check output -8822 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") -8823 # . epilogue -8824 89/<- %esp 5/r32/ebp -8825 5d/pop-to-ebp -8826 c3/return -8827 -8828 test-compare-eax-with-literal: -8829 # compare var1/eax 0x34 -8830 # => -8831 # 3d/compare-eax-with 0x34/imm32 -8832 # -8833 # . prologue -8834 55/push-ebp -8835 89/<- %ebp 4/r32/esp -8836 # setup -8837 (clear-stream _test-output-stream) -8838 (clear-stream $_test-output-buffered-file->buffer) -8839 # var type/ecx: (handle tree type-id) = int -8840 68/push 0/imm32/right/null -8841 68/push 1/imm32/left/int -8842 89/<- %ecx 4/r32/esp -8843 # var var-var1/ecx: var in eax -8844 68/push "eax"/imm32/register -8845 68/push 0/imm32/no-stack-offset -8846 68/push 1/imm32/block-depth -8847 51/push-ecx -8848 68/push "var1"/imm32 -8849 89/<- %ecx 4/r32/esp -8850 # var type/edx: (handle tree type-id) = literal -8851 68/push 0/imm32/right/null -8852 68/push 0/imm32/left/literal -8853 89/<- %edx 4/r32/esp -8854 # var var-var2/edx: var literal -8855 68/push 0/imm32/no-register -8856 68/push 0/imm32/no-stack-offset -8857 68/push 1/imm32/block-depth -8858 52/push-edx -8859 68/push "0x34"/imm32 -8860 89/<- %edx 4/r32/esp -8861 # var inouts/esi: (handle stmt-var) = [var2] -8862 68/push 0/imm32/is-deref:false -8863 68/push 0/imm32/next -8864 52/push-edx/var-var2 -8865 89/<- %esi 4/r32/esp -8866 # inouts = [var1, var2] -8867 68/push 0/imm32/is-deref:false -8868 56/push-esi/next -8869 51/push-ecx/var-var1 -8870 89/<- %esi 4/r32/esp -8871 # var stmt/esi: statement -8872 68/push 0/imm32/next -8873 68/push 0/imm32/outputs -8874 56/push-esi/inouts -8875 68/push "compare"/imm32/operation -8876 68/push 1/imm32/regular-stmt -8877 89/<- %esi 4/r32/esp -8878 # convert -8879 c7 0/subop/copy *Curr-block-depth 0/imm32 -8880 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8881 (flush _test-output-buffered-file) -8882 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8888 # check output -8889 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") -8890 # . epilogue -8891 89/<- %esp 5/r32/ebp -8892 5d/pop-to-ebp -8893 c3/return -8894 -8895 test-compare-reg-with-literal: -8896 # compare var1/ecx 0x34 -8897 # => -8898 # 81 7/subop/compare %ecx 0x34/imm32 -8899 # -8900 # . prologue -8901 55/push-ebp -8902 89/<- %ebp 4/r32/esp -8903 # setup -8904 (clear-stream _test-output-stream) -8905 (clear-stream $_test-output-buffered-file->buffer) -8906 # var type/ecx: (handle tree type-id) = int -8907 68/push 0/imm32/right/null -8908 68/push 1/imm32/left/int -8909 89/<- %ecx 4/r32/esp -8910 # var var-var1/ecx: var in ecx -8911 68/push "ecx"/imm32/register -8912 68/push 0/imm32/no-stack-offset -8913 68/push 1/imm32/block-depth -8914 51/push-ecx -8915 68/push "var1"/imm32 -8916 89/<- %ecx 4/r32/esp -8917 # var type/edx: (handle tree type-id) = literal -8918 68/push 0/imm32/right/null -8919 68/push 0/imm32/left/literal -8920 89/<- %edx 4/r32/esp -8921 # var var-var2/edx: var literal -8922 68/push 0/imm32/no-register -8923 68/push 0/imm32/no-stack-offset -8924 68/push 1/imm32/block-depth -8925 52/push-edx -8926 68/push "0x34"/imm32 -8927 89/<- %edx 4/r32/esp -8928 # var inouts/esi: (handle stmt-var) = [var2] -8929 68/push 0/imm32/is-deref:false -8930 68/push 0/imm32/next -8931 52/push-edx/var-var2 -8932 89/<- %esi 4/r32/esp -8933 # inouts = [var1, var2] -8934 68/push 0/imm32/is-deref:false -8935 56/push-esi/next -8936 51/push-ecx/var-var1 -8937 89/<- %esi 4/r32/esp -8938 # var stmt/esi: statement -8939 68/push 0/imm32/next -8940 68/push 0/imm32/outputs -8941 56/push-esi/inouts -8942 68/push "compare"/imm32/operation -8943 68/push 1/imm32/regular-stmt -8944 89/<- %esi 4/r32/esp -8945 # convert -8946 c7 0/subop/copy *Curr-block-depth 0/imm32 -8947 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8948 (flush _test-output-buffered-file) -8949 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8955 # check output -8956 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") -8957 # . epilogue -8958 89/<- %esp 5/r32/ebp -8959 5d/pop-to-ebp -8960 c3/return -8961 -8962 test-emit-subx-statement-function-call: -8963 # Call a function on a variable on the stack. -8964 # f foo -8965 # => -8966 # (f2 *(ebp-8)) -8967 # (Changing the function name supports overloading in general, but here it -8968 # just serves to help disambiguate things.) -8969 # -8970 # There's a variable on the var stack as follows: -8971 # name: 'foo' -8972 # type: int -8973 # stack-offset: -8 -8974 # -8975 # There's nothing in primitives. -8976 # -8977 # There's a function with this info: -8978 # name: 'f' -8979 # inout: int/mem -8980 # value: 'f2' -8981 # -8982 # . prologue -8983 55/push-ebp -8984 89/<- %ebp 4/r32/esp -8985 # setup -8986 (clear-stream _test-output-stream) -8987 (clear-stream $_test-output-buffered-file->buffer) -8988 # var type/ecx: (handle tree type-id) = int -8989 68/push 0/imm32/right/null -8990 68/push 1/imm32/left/int -8991 89/<- %ecx 4/r32/esp -8992 # var var-foo/ecx: var -8993 68/push 0/imm32/no-register -8994 68/push -8/imm32/stack-offset -8995 68/push 0/imm32/block-depth -8996 51/push-ecx -8997 68/push "foo"/imm32 -8998 89/<- %ecx 4/r32/esp -8999 # var inouts/esi: (handle stmt-var) -9000 68/push 0/imm32/is-deref:false -9001 68/push 0/imm32/next -9002 51/push-ecx/var-foo -9003 89/<- %esi 4/r32/esp -9004 # var stmt/esi: statement -9005 68/push 0/imm32/next -9006 68/push 0/imm32/outputs -9007 56/push-esi/inouts -9008 68/push "f"/imm32/operation -9009 68/push 1/imm32 -9010 89/<- %esi 4/r32/esp -9011 # var functions/ebx: function -9012 68/push 0/imm32/next -9013 68/push 0/imm32/body -9014 68/push 0/imm32/outputs -9015 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -9016 68/push "f2"/imm32/subx-name -9017 68/push "f"/imm32/name -9018 89/<- %ebx 4/r32/esp -9019 # convert -9020 c7 0/subop/copy *Curr-block-depth 0/imm32 -9021 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) -9022 (flush _test-output-buffered-file) -9023 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -9029 # check output -9030 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-statement-function-call") -9031 # . epilogue -9032 89/<- %esp 5/r32/ebp -9033 5d/pop-to-ebp -9034 c3/return -9035 -9036 test-emit-subx-statement-function-call-with-literal-arg: -9037 # Call a function on a literal. -9038 # f 34 -9039 # => -9040 # (f2 34) -9041 # -9042 # . prologue -9043 55/push-ebp -9044 89/<- %ebp 4/r32/esp -9045 # setup -9046 (clear-stream _test-output-stream) -9047 (clear-stream $_test-output-buffered-file->buffer) -9048 # var type/ecx: (handle tree type-id) = literal -9049 68/push 0/imm32/right/null -9050 68/push 0/imm32/left/literal -9051 89/<- %ecx 4/r32/esp -9052 # var var-foo/ecx: var literal -9053 68/push 0/imm32/no-register -9054 68/push 0/imm32/no-stack-offset -9055 68/push 0/imm32/block-depth -9056 51/push-ecx -9057 68/push "34"/imm32 -9058 89/<- %ecx 4/r32/esp -9059 # var inouts/esi: (handle stmt-var) -9060 68/push 0/imm32/is-deref:false -9061 68/push 0/imm32/next -9062 51/push-ecx/var-foo -9063 89/<- %esi 4/r32/esp -9064 # var stmt/esi: statement -9065 68/push 0/imm32/next -9066 68/push 0/imm32/outputs -9067 56/push-esi/inouts -9068 68/push "f"/imm32/operation -9069 68/push 1/imm32 -9070 89/<- %esi 4/r32/esp -9071 # var functions/ebx: function -9072 68/push 0/imm32/next -9073 68/push 0/imm32/body -9074 68/push 0/imm32/outputs -9075 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -9076 68/push "f2"/imm32/subx-name -9077 68/push "f"/imm32/name -9078 89/<- %ebx 4/r32/esp -9079 # convert -9080 c7 0/subop/copy *Curr-block-depth 0/imm32 -9081 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) -9082 (flush _test-output-buffered-file) -9083 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -9089 # check output -9090 (check-next-stream-line-equal _test-output-stream "(f2 34)" "F - test-emit-subx-statement-function-call-with-literal-arg") -9091 # . epilogue -9092 89/<- %esp 5/r32/ebp -9093 5d/pop-to-ebp -9094 c3/return -9095 -9096 emit-indent: # out: (addr buffered-file), n: int -9097 # . prologue -9098 55/push-ebp -9099 89/<- %ebp 4/r32/esp -9100 # . save registers -9101 50/push-eax -9102 # var i/eax: int = n -9103 8b/-> *(ebp+0xc) 0/r32/eax -9104 { -9105 # if (i <= 0) break -9106 3d/compare-eax-with 0/imm32 -9107 7e/jump-if-<= break/disp8 -9108 (write-buffered *(ebp+8) " ") -9109 48/decrement-eax -9110 eb/jump loop/disp8 -9111 } -9112 $emit-indent:end: -9113 # . restore registers -9114 58/pop-to-eax -9115 # . epilogue -9116 89/<- %esp 5/r32/ebp -9117 5d/pop-to-ebp -9118 c3/return -9119 -9120 emit-subx-prologue: # out: (addr buffered-file) -9121 # . prologue -9122 55/push-ebp -9123 89/<- %ebp 4/r32/esp -9124 # -9125 (write-buffered *(ebp+8) " # . prologue\n") -9126 (write-buffered *(ebp+8) " 55/push-ebp\n") -9127 (write-buffered *(ebp+8) " 89/<- %ebp 4/r32/esp\n") -9128 $emit-subx-prologue:end: -9129 # . epilogue -9130 89/<- %esp 5/r32/ebp -9131 5d/pop-to-ebp -9132 c3/return -9133 -9134 emit-subx-epilogue: # out: (addr buffered-file) -9135 # . prologue -9136 55/push-ebp -9137 89/<- %ebp 4/r32/esp -9138 # -9139 (write-buffered *(ebp+8) " # . epilogue\n") -9140 (write-buffered *(ebp+8) " 89/<- %esp 5/r32/ebp\n") -9141 (write-buffered *(ebp+8) " 5d/pop-to-ebp\n") -9142 (write-buffered *(ebp+8) " c3/return\n") -9143 $emit-subx-epilogue:end: -9144 # . epilogue -9145 89/<- %esp 5/r32/ebp -9146 5d/pop-to-ebp -9147 c3/return +7863 56/push-esi +7864 # ecx = s +7865 8b/-> *(ebp+0xc) 1/r32/ecx +7866 # var operand/esi: (handle var) = s->value +7867 8b/-> *ecx 6/r32/esi # Stmt-var-value +7868 # if (operand->register && s->is-deref?) emit "*__" +7869 { +7870 $emit-subx-call-operand:check-for-register-indirect: +7871 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +7872 74/jump-if-= break/disp8 +7873 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +7874 74/jump-if-= break/disp8 +7875 $emit-subx-call-operand:register-indirect: +7876 (write-buffered *(ebp+8) " *") +7877 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register +7878 e9/jump $emit-subx-call-operand:end/disp32 +7879 } +7880 # if (operand->register && !s->is-deref?) emit "%__" +7881 { +7882 $emit-subx-call-operand:check-for-register-direct: +7883 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +7884 74/jump-if-= break/disp8 +7885 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +7886 75/jump-if-!= break/disp8 +7887 $emit-subx-call-operand:register-direct: +7888 (write-buffered *(ebp+8) " %") +7889 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register +7890 e9/jump $emit-subx-call-operand:end/disp32 +7891 } +7892 # else if (operand->stack-offset) emit "*(ebp+__)" +7893 { +7894 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-offset +7895 74/jump-if-= break/disp8 +7896 $emit-subx-call-operand:stack: +7897 (write-buffered *(ebp+8) Space) +7898 (write-buffered *(ebp+8) "*(ebp+") +7899 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-offset +7900 (write-buffered *(ebp+8) ")") +7901 e9/jump $emit-subx-call-operand:end/disp32 +7902 } +7903 # else if (operand->type == literal) emit "__" +7904 { +7905 8b/-> *(esi+4) 0/r32/eax # Var-type +7906 81 7/subop/compare *eax 0/imm32 # Tree-left +7907 75/jump-if-!= break/disp8 +7908 $emit-subx-call-operand:literal: +7909 (write-buffered *(ebp+8) Space) +7910 (write-buffered *(ebp+8) *esi) +7911 } +7912 $emit-subx-call-operand:end: +7913 # . restore registers +7914 5e/pop-to-esi +7915 59/pop-to-ecx +7916 58/pop-to-eax +7917 # . epilogue +7918 89/<- %esp 5/r32/ebp +7919 5d/pop-to-ebp +7920 c3/return +7921 +7922 emit-subx-var-as-rm32: # out: (addr buffered-file), s: (handle stmt-var) +7923 # . prologue +7924 55/push-ebp +7925 89/<- %ebp 4/r32/esp +7926 # . save registers +7927 50/push-eax +7928 51/push-ecx +7929 56/push-esi +7930 # ecx = s +7931 8b/-> *(ebp+0xc) 1/r32/ecx +7932 # var operand/esi: (handle var) = s->value +7933 8b/-> *ecx 6/r32/esi # Stmt-var-value +7934 # if (operand->register && s->is-deref?) emit "*__" +7935 { +7936 $emit-subx-var-as-rm32:check-for-register-indirect: +7937 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +7938 74/jump-if-= break/disp8 +7939 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +7940 74/jump-if-= break/disp8 +7941 $emit-subx-var-as-rm32:register-indirect: +7942 (write-buffered *(ebp+8) " *") +7943 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register +7944 } +7945 # if (operand->register && !s->is-deref?) emit "%__" +7946 { +7947 $emit-subx-var-as-rm32:check-for-register-direct: +7948 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +7949 74/jump-if-= break/disp8 +7950 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +7951 75/jump-if-!= break/disp8 +7952 $emit-subx-var-as-rm32:register-direct: +7953 (write-buffered *(ebp+8) " %") +7954 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register +7955 } +7956 # else if (operand->stack-offset) emit "*(ebp+__)" +7957 { +7958 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-offset +7959 74/jump-if-= break/disp8 +7960 $emit-subx-var-as-rm32:stack: +7961 (write-buffered *(ebp+8) Space) +7962 (write-buffered *(ebp+8) "*(ebp+") +7963 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-offset +7964 (write-buffered *(ebp+8) ")") +7965 } +7966 $emit-subx-var-as-rm32:end: +7967 # . restore registers +7968 5e/pop-to-esi +7969 59/pop-to-ecx +7970 58/pop-to-eax +7971 # . epilogue +7972 89/<- %esp 5/r32/ebp +7973 5d/pop-to-ebp +7974 c3/return +7975 +7976 find-matching-function: # functions: (addr function), stmt: (handle stmt) -> result/eax: (handle function) +7977 # . prologue +7978 55/push-ebp +7979 89/<- %ebp 4/r32/esp +7980 # . save registers +7981 51/push-ecx +7982 # var curr/ecx: (handle function) = functions +7983 8b/-> *(ebp+8) 1/r32/ecx +7984 { +7985 # if (curr == null) break +7986 81 7/subop/compare %ecx 0/imm32 +7987 74/jump-if-= break/disp8 +7988 # if match(stmt, curr) return curr +7989 { +7990 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax +7991 3d/compare-eax-and 0/imm32/false +7992 74/jump-if-= break/disp8 +7993 89/<- %eax 1/r32/ecx +7994 eb/jump $find-matching-function:end/disp8 +7995 } +7996 # curr = curr->next +7997 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next +7998 eb/jump loop/disp8 +7999 } +8000 # return null +8001 b8/copy-to-eax 0/imm32 +8002 $find-matching-function:end: +8003 # . restore registers +8004 59/pop-to-ecx +8005 # . epilogue +8006 89/<- %esp 5/r32/ebp +8007 5d/pop-to-ebp +8008 c3/return +8009 +8010 find-matching-primitive: # primitives: (handle primitive), stmt: (handle stmt) -> result/eax: (handle primitive) +8011 # . prologue +8012 55/push-ebp +8013 89/<- %ebp 4/r32/esp +8014 # . save registers +8015 51/push-ecx +8016 # var curr/ecx: (handle primitive) = primitives +8017 8b/-> *(ebp+8) 1/r32/ecx +8018 { +8019 $find-matching-primitive:loop: +8020 # if (curr == null) break +8021 81 7/subop/compare %ecx 0/imm32 +8022 0f 84/jump-if-= break/disp32 +8023 #? (write-buffered Stderr "prim: ") +8024 #? (write-buffered Stderr *ecx) # Primitive-name +8025 #? (write-buffered Stderr " => ") +8026 #? (write-buffered Stderr *(ecx+0xc)) # Primitive-subx-name +8027 #? (write-buffered Stderr Newline) +8028 #? (flush Stderr) +8029 # if match(curr, stmt) return curr +8030 { +8031 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax +8032 3d/compare-eax-and 0/imm32/false +8033 74/jump-if-= break/disp8 +8034 89/<- %eax 1/r32/ecx +8035 eb/jump $find-matching-primitive:end/disp8 +8036 } +8037 $find-matching-primitive:next-primitive: +8038 # curr = curr->next +8039 8b/-> *(ecx+0x24) 1/r32/ecx # Primitive-next +8040 e9/jump loop/disp32 +8041 } +8042 # return null +8043 b8/copy-to-eax 0/imm32 +8044 $find-matching-primitive:end: +8045 # . restore registers +8046 59/pop-to-ecx +8047 # . epilogue +8048 89/<- %esp 5/r32/ebp +8049 5d/pop-to-ebp +8050 c3/return +8051 +8052 mu-stmt-matches-function?: # stmt: (handle stmt), function: (handle function) -> result/eax: boolean +8053 # . prologue +8054 55/push-ebp +8055 89/<- %ebp 4/r32/esp +8056 # . save registers +8057 51/push-ecx +8058 # return function->name == stmt->operation +8059 8b/-> *(ebp+8) 1/r32/ecx +8060 8b/-> *(ebp+0xc) 0/r32/eax +8061 (string-equal? *(ecx+4) *eax) # Stmt1-operation, Function-name => eax +8062 $mu-stmt-matches-function?:end: +8063 # . restore registers +8064 59/pop-to-ecx +8065 # . epilogue +8066 89/<- %esp 5/r32/ebp +8067 5d/pop-to-ebp +8068 c3/return +8069 +8070 mu-stmt-matches-primitive?: # stmt: (handle stmt), primitive: (handle primitive) -> result/eax: boolean +8071 # A mu stmt matches a primitive if the name matches, all the inout vars +8072 # match, and all the output vars match. +8073 # Vars match if types match and registers match. +8074 # In addition, a stmt output matches a primitive's output if types match +8075 # and the primitive has a wildcard register. +8076 # . prologue +8077 55/push-ebp +8078 89/<- %ebp 4/r32/esp +8079 # . save registers +8080 51/push-ecx +8081 52/push-edx +8082 53/push-ebx +8083 56/push-esi +8084 57/push-edi +8085 # ecx = stmt +8086 8b/-> *(ebp+8) 1/r32/ecx +8087 # edx = primitive +8088 8b/-> *(ebp+0xc) 2/r32/edx +8089 { +8090 $mu-stmt-matches-primitive?:check-name: +8091 # if (primitive->name != stmt->operation) return false +8092 (string-equal? *(ecx+4) *edx) # Stmt1-operation, Primitive-name => eax +8093 3d/compare-eax-and 0/imm32/false +8094 75/jump-if-!= break/disp8 +8095 b8/copy-to-eax 0/imm32 +8096 e9/jump $mu-stmt-matches-primitive?:end/disp32 +8097 } +8098 $mu-stmt-matches-primitive?:check-inouts: +8099 # for (curr/esi in stmt->inouts, curr2/edi in primitive->inouts) +8100 8b/-> *(ecx+8) 6/r32/esi # Stmt1-inouts or Regvardef-inouts +8101 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts +8102 { +8103 # if (curr == 0 && curr2 == 0) move on to check outputs +8104 { +8105 81 7/subop/compare %esi 0/imm32 +8106 75/jump-if-!= break/disp8 +8107 $mu-stmt-matches-primitive?:stmt-inout-is-null: +8108 { +8109 81 7/subop/compare %edi 0/imm32 +8110 75/jump-if-!= break/disp8 +8111 # +8112 e9/jump $mu-stmt-matches-primitive?:check-outputs/disp32 +8113 } +8114 # return false +8115 b8/copy-to-eax 0/imm32/false +8116 e9/jump $mu-stmt-matches-primitive?:end/disp32 +8117 } +8118 # if (curr2 == 0) return false +8119 { +8120 81 7/subop/compare %edi 0/imm32 +8121 75/jump-if-!= break/disp8 +8122 $mu-stmt-matches-primitive?:prim-inout-is-null: +8123 b8/copy-to-eax 0/imm32/false +8124 e9/jump $mu-stmt-matches-primitive?:end/disp32 +8125 } +8126 # if (curr != curr2) return false +8127 { +8128 (operand-matches-primitive? %esi *edi) # List-value => eax +8129 3d/compare-eax-and 0/imm32/false +8130 75/jump-if-!= break/disp8 +8131 b8/copy-to-eax 0/imm32/false +8132 e9/jump $mu-stmt-matches-primitive?:end/disp32 +8133 } +8134 # curr=curr->next +8135 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next +8136 # curr2=curr2->next +8137 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next +8138 eb/jump loop/disp8 +8139 } +8140 $mu-stmt-matches-primitive?:check-outputs: +8141 # for (curr/esi in stmt->outputs, curr2/edi in primitive->outputs) +8142 8b/-> *(ecx+0xc) 6/r32/esi # Stmt1-outputs +8143 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs +8144 { +8145 # if (curr == 0) return (curr2 == 0) +8146 { +8147 $mu-stmt-matches-primitive?:check-output: +8148 81 7/subop/compare %esi 0/imm32 +8149 75/jump-if-!= break/disp8 +8150 { +8151 81 7/subop/compare %edi 0/imm32 +8152 75/jump-if-!= break/disp8 +8153 # return true +8154 b8/copy-to-eax 1/imm32 +8155 e9/jump $mu-stmt-matches-primitive?:end/disp32 +8156 } +8157 # return false +8158 b8/copy-to-eax 0/imm32 +8159 e9/jump $mu-stmt-matches-primitive?:end/disp32 +8160 } +8161 # if (curr2 == 0) return false +8162 { +8163 81 7/subop/compare %edi 0/imm32 +8164 75/jump-if-!= break/disp8 +8165 b8/copy-to-eax 0/imm32 +8166 e9/jump $mu-stmt-matches-primitive?:end/disp32 +8167 } +8168 # if (curr != curr2) return false +8169 { +8170 (operand-matches-primitive? %esi *edi) # List-value => eax +8171 3d/compare-eax-and 0/imm32/false +8172 75/jump-if-!= break/disp8 +8173 b8/copy-to-eax 0/imm32 +8174 e9/jump $mu-stmt-matches-primitive?:end/disp32 +8175 } +8176 # curr=curr->next +8177 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next +8178 # curr2=curr2->next +8179 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next +8180 eb/jump loop/disp8 +8181 } +8182 $mu-stmt-matches-primitive?:return-true: +8183 b8/copy-to-eax 1/imm32 +8184 $mu-stmt-matches-primitive?:end: +8185 # . restore registers +8186 5f/pop-to-edi +8187 5e/pop-to-esi +8188 5b/pop-to-ebx +8189 5a/pop-to-edx +8190 59/pop-to-ecx +8191 # . epilogue +8192 89/<- %esp 5/r32/ebp +8193 5d/pop-to-ebp +8194 c3/return +8195 +8196 operand-matches-primitive?: # s: (handle stmt-var), prim-var: (handle var) -> result/eax: boolean +8197 # . prologue +8198 55/push-ebp +8199 89/<- %ebp 4/r32/esp +8200 # . save registers +8201 51/push-ecx +8202 56/push-esi +8203 57/push-edi +8204 # ecx = s +8205 8b/-> *(ebp+8) 1/r32/ecx +8206 # var var/esi : (handle var) = s->value +8207 8b/-> *ecx 6/r32/esi # Stmt-var-value +8208 # edi = prim-var +8209 8b/-> *(ebp+0xc) 7/r32/edi +8210 $operand-matches-primitive?:check-type: +8211 # if (var->type != prim-var->type) return false +8212 (subx-type-equal? *(esi+4) *(edi+4)) # Var-type, Var-type => eax +8213 3d/compare-eax-and 0/imm32/false +8214 b8/copy-to-eax 0/imm32/false +8215 0f 84/jump-if-= $operand-matches-primitive?:end/disp32 +8216 { +8217 $operand-matches-primitive?:check-register: +8218 # if prim-var is in memory and var is in register but dereference, match +8219 { +8220 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register +8221 0f 85/jump-if-!= break/disp32 +8222 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +8223 74/jump-if-= break/disp8 +8224 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +8225 74/jump-if-= break/disp8 +8226 e9/jump $operand-matches-primitive?:return-true/disp32 +8227 } +8228 # if prim-var is in register and var is in register but dereference, no match +8229 { +8230 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register +8231 0f 84/jump-if-= break/disp32 +8232 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +8233 0f 84/jump-if-= break/disp32 +8234 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +8235 74/jump-if-= break/disp8 +8236 e9/jump $operand-matches-primitive?:return-false/disp32 +8237 } +8238 # return false if var->register doesn't match prim-var->register +8239 { +8240 # if register addresses are equal, it's a match +8241 8b/-> *(esi+0x10) 0/r32/eax # Var-register +8242 39/compare *(edi+0x10) 0/r32/eax # Var-register +8243 74/jump-if-= break/disp8 +8244 # if either address is 0, return false +8245 3d/compare-eax-and 0/imm32 +8246 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result +8247 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register +8248 74/jump-if-= $operand-matches-primitive?:return-false/disp8 +8249 # if prim-var->register is wildcard, it's a match +8250 (string-equal? *(edi+0x10) Any-register) # Var-register => eax +8251 3d/compare-eax-and 0/imm32/false +8252 75/jump-if-!= break/disp8 +8253 # if string contents aren't equal, return false +8254 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register => eax +8255 3d/compare-eax-and 0/imm32/false +8256 74/jump-if-= $operand-matches-primitive?:return-false/disp8 +8257 } +8258 } +8259 $operand-matches-primitive?:return-true: +8260 b8/copy-to-eax 1/imm32/true +8261 eb/jump $operand-matches-primitive?:end/disp8 +8262 $operand-matches-primitive?:return-false: +8263 b8/copy-to-eax 0/imm32/false +8264 $operand-matches-primitive?:end: +8265 # . restore registers +8266 5f/pop-to-edi +8267 5e/pop-to-esi +8268 59/pop-to-ecx +8269 # . epilogue +8270 89/<- %esp 5/r32/ebp +8271 5d/pop-to-ebp +8272 c3/return +8273 +8274 subx-type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean +8275 # . prologue +8276 55/push-ebp +8277 89/<- %ebp 4/r32/esp +8278 # . save registers +8279 51/push-ecx +8280 # var alit/ecx: boolean = is-literal-type?(a) +8281 (is-literal-type? *(ebp+8)) # => eax +8282 89/<- %ecx 0/r32/eax +8283 # var blit/eax: boolean = is-literal-type?(b) +8284 (is-literal-type? *(ebp+0xc)) # => eax +8285 # return alit == blit +8286 39/compare %eax 1/r32/ecx +8287 74/jump-if-= $subx-type-equal?:true/disp8 +8288 $subx-type-equal?:false: +8289 b8/copy-to-eax 0/imm32/false +8290 eb/jump $subx-type-equal?:end/disp8 +8291 $subx-type-equal?:true: +8292 b8/copy-to-eax 1/imm32/true +8293 $subx-type-equal?:end: +8294 # . restore registers +8295 59/pop-to-ecx +8296 # . epilogue +8297 89/<- %esp 5/r32/ebp +8298 5d/pop-to-ebp +8299 c3/return +8300 +8301 is-literal-type?: # a: (handle tree type-id) -> result/eax: boolean +8302 # . prologue +8303 55/push-ebp +8304 89/<- %ebp 4/r32/esp +8305 # +8306 8b/-> *(ebp+8) 0/r32/eax +8307 8b/-> *eax 0/r32/eax # Atom-value +8308 3d/compare-eax-and 0/imm32/false +8309 74/jump-if-equal $is-literal-type?:end/disp8 +8310 b8/copy-to-eax 1/imm32/true +8311 $is-literal-type?:end: +8312 # . epilogue +8313 89/<- %esp 5/r32/ebp +8314 5d/pop-to-ebp +8315 c3/return +8316 +8317 test-emit-subx-stmt-primitive: +8318 # Primitive operation on a variable on the stack. +8319 # increment foo +8320 # => +8321 # ff 0/subop/increment *(ebp-8) +8322 # +8323 # There's a variable on the var stack as follows: +8324 # name: 'foo' +8325 # type: int +8326 # stack-offset: -8 +8327 # +8328 # There's a primitive with this info: +8329 # name: 'increment' +8330 # inouts: int/mem +8331 # value: 'ff 0/subop/increment' +8332 # +8333 # There's nothing in functions. +8334 # +8335 # . prologue +8336 55/push-ebp +8337 89/<- %ebp 4/r32/esp +8338 # setup +8339 (clear-stream _test-output-stream) +8340 (clear-stream $_test-output-buffered-file->buffer) +8341 # var type/ecx: (handle tree type-id) = int +8342 68/push 0/imm32/right/null +8343 68/push 1/imm32/left/int +8344 89/<- %ecx 4/r32/esp +8345 # var var-foo/ecx: var +8346 68/push 0/imm32/no-register +8347 68/push -8/imm32/stack-offset +8348 68/push 1/imm32/block-depth +8349 51/push-ecx +8350 68/push "foo"/imm32 +8351 89/<- %ecx 4/r32/esp +8352 # var operand/ebx: (handle stmt-var) +8353 68/push 0/imm32/is-deref:false +8354 68/push 0/imm32/next +8355 51/push-ecx/var-foo +8356 89/<- %ebx 4/r32/esp +8357 # var stmt/esi: statement +8358 68/push 0/imm32/next +8359 68/push 0/imm32/outputs +8360 53/push-ebx/operands +8361 68/push "increment"/imm32/operation +8362 68/push 1/imm32 +8363 89/<- %esi 4/r32/esp +8364 # var primitives/ebx: primitive +8365 68/push 0/imm32/next +8366 68/push 0/imm32/output-is-write-only +8367 68/push 0/imm32/no-disp32 +8368 68/push 0/imm32/no-imm32 +8369 68/push 0/imm32/no-r32 +8370 68/push 1/imm32/rm32-is-first-inout +8371 68/push "ff 0/subop/increment"/imm32/subx-name +8372 68/push 0/imm32/outputs +8373 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call +8374 68/push "increment"/imm32/name +8375 89/<- %ebx 4/r32/esp +8376 # convert +8377 c7 0/subop/copy *Curr-block-depth 0/imm32 +8378 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) +8379 (flush _test-output-buffered-file) +8380 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8386 # check output +8387 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive") +8388 # . epilogue +8389 89/<- %esp 5/r32/ebp +8390 5d/pop-to-ebp +8391 c3/return +8392 +8393 test-emit-subx-stmt-primitive-register: +8394 # Primitive operation on a variable in a register. +8395 # foo <- increment +8396 # => +8397 # ff 0/subop/increment %eax # sub-optimal, but should suffice +8398 # +8399 # There's a variable on the var stack as follows: +8400 # name: 'foo' +8401 # type: int +8402 # register: 'eax' +8403 # +8404 # There's a primitive with this info: +8405 # name: 'increment' +8406 # out: int/reg +8407 # value: 'ff 0/subop/increment' +8408 # +8409 # There's nothing in functions. +8410 # +8411 # . prologue +8412 55/push-ebp +8413 89/<- %ebp 4/r32/esp +8414 # setup +8415 (clear-stream _test-output-stream) +8416 (clear-stream $_test-output-buffered-file->buffer) +8417 # var type/ecx: (handle tree type-id) = int +8418 68/push 0/imm32/right/null +8419 68/push 1/imm32/left/int +8420 89/<- %ecx 4/r32/esp +8421 # var var-foo/ecx: var in eax +8422 68/push "eax"/imm32/register +8423 68/push 0/imm32/no-stack-offset +8424 68/push 1/imm32/block-depth +8425 51/push-ecx +8426 68/push "foo"/imm32 +8427 89/<- %ecx 4/r32/esp +8428 # var operand/ebx: (handle stmt-var) +8429 68/push 0/imm32/is-deref:false +8430 68/push 0/imm32/next +8431 51/push-ecx/var-foo +8432 89/<- %ebx 4/r32/esp +8433 # var stmt/esi: statement +8434 68/push 0/imm32/next +8435 53/push-ebx/outputs +8436 68/push 0/imm32/inouts +8437 68/push "increment"/imm32/operation +8438 68/push 1/imm32 +8439 89/<- %esi 4/r32/esp +8440 # var formal-var/ebx: var in any register +8441 68/push Any-register/imm32 +8442 68/push 0/imm32/no-stack-offset +8443 68/push 1/imm32/block-depth +8444 ff 6/subop/push *(ecx+4) # Var-type +8445 68/push "dummy"/imm32 +8446 89/<- %ebx 4/r32/esp +8447 # var operand/ebx: (handle stmt-var) +8448 68/push 0/imm32/is-deref:false +8449 68/push 0/imm32/next +8450 53/push-ebx/formal-var +8451 89/<- %ebx 4/r32/esp +8452 # var primitives/ebx: primitive +8453 68/push 0/imm32/next +8454 68/push 0/imm32/output-is-write-only +8455 68/push 0/imm32/no-disp32 +8456 68/push 0/imm32/no-imm32 +8457 68/push 0/imm32/no-r32 +8458 68/push 3/imm32/rm32-in-first-output +8459 68/push "ff 0/subop/increment"/imm32/subx-name +8460 53/push-ebx/outputs +8461 68/push 0/imm32/inouts +8462 68/push "increment"/imm32/name +8463 89/<- %ebx 4/r32/esp +8464 # convert +8465 c7 0/subop/copy *Curr-block-depth 0/imm32 +8466 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) +8467 (flush _test-output-buffered-file) +8468 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8474 # check output +8475 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register") +8476 # . epilogue +8477 89/<- %esp 5/r32/ebp +8478 5d/pop-to-ebp +8479 c3/return +8480 +8481 test-emit-subx-stmt-select-primitive: +8482 # Select the right primitive between overloads. +8483 # foo <- increment +8484 # => +8485 # ff 0/subop/increment %eax # sub-optimal, but should suffice +8486 # +8487 # There's a variable on the var stack as follows: +8488 # name: 'foo' +8489 # type: int +8490 # register: 'eax' +8491 # +8492 # There's two primitives, as follows: +8493 # - name: 'increment' +8494 # out: int/reg +8495 # value: 'ff 0/subop/increment' +8496 # - name: 'increment' +8497 # inout: int/mem +8498 # value: 'ff 0/subop/increment' +8499 # +8500 # There's nothing in functions. +8501 # +8502 # . prologue +8503 55/push-ebp +8504 89/<- %ebp 4/r32/esp +8505 # setup +8506 (clear-stream _test-output-stream) +8507 (clear-stream $_test-output-buffered-file->buffer) +8508 # var type/ecx: (handle tree type-id) = int +8509 68/push 0/imm32/right/null +8510 68/push 1/imm32/left/int +8511 89/<- %ecx 4/r32/esp +8512 # var var-foo/ecx: var in eax +8513 68/push "eax"/imm32/register +8514 68/push 0/imm32/no-stack-offset +8515 68/push 1/imm32/block-depth +8516 51/push-ecx +8517 68/push "foo"/imm32 +8518 89/<- %ecx 4/r32/esp +8519 # var real-outputs/edi: (handle stmt-var) +8520 68/push 0/imm32/is-deref:false +8521 68/push 0/imm32/next +8522 51/push-ecx/var-foo +8523 89/<- %edi 4/r32/esp +8524 # var stmt/esi: statement +8525 68/push 0/imm32/next +8526 57/push-edi/outputs +8527 68/push 0/imm32/inouts +8528 68/push "increment"/imm32/operation +8529 68/push 1/imm32 +8530 89/<- %esi 4/r32/esp +8531 # var formal-var/ebx: var in any register +8532 68/push Any-register/imm32 +8533 68/push 0/imm32/no-stack-offset +8534 68/push 1/imm32/block-depth +8535 ff 6/subop/push *(ecx+4) # Var-type +8536 68/push "dummy"/imm32 +8537 89/<- %ebx 4/r32/esp +8538 # var formal-outputs/ebx: (handle stmt-var) +8539 68/push 0/imm32/is-deref:false +8540 68/push 0/imm32/next +8541 53/push-ebx/formal-var +8542 89/<- %ebx 4/r32/esp +8543 # var primitive1/ebx: primitive +8544 68/push 0/imm32/next +8545 68/push 0/imm32/output-is-write-only +8546 68/push 0/imm32/no-disp32 +8547 68/push 0/imm32/no-imm32 +8548 68/push 0/imm32/no-r32 +8549 68/push 3/imm32/rm32-in-first-output +8550 68/push "ff 0/subop/increment"/imm32/subx-name +8551 53/push-ebx/outputs/formal-outputs +8552 68/push 0/imm32/inouts +8553 68/push "increment"/imm32/name +8554 89/<- %ebx 4/r32/esp +8555 # var primitives/ebx: primitive +8556 53/push-ebx/next +8557 68/push 0/imm32/output-is-write-only +8558 68/push 0/imm32/no-disp32 +8559 68/push 0/imm32/no-imm32 +8560 68/push 0/imm32/no-r32 +8561 68/push 1/imm32/rm32-is-first-inout +8562 68/push "ff 0/subop/increment"/imm32/subx-name +8563 68/push 0/imm32/outputs +8564 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call +8565 68/push "increment"/imm32/name +8566 89/<- %ebx 4/r32/esp +8567 # convert +8568 c7 0/subop/copy *Curr-block-depth 0/imm32 +8569 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) +8570 (flush _test-output-buffered-file) +8571 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8577 # check output +8578 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive") +8579 # . epilogue +8580 89/<- %esp 5/r32/ebp +8581 5d/pop-to-ebp +8582 c3/return +8583 +8584 test-emit-subx-stmt-select-primitive-2: +8585 # Select the right primitive between overloads. +8586 # foo <- increment +8587 # => +8588 # ff 0/subop/increment %eax # sub-optimal, but should suffice +8589 # +8590 # There's a variable on the var stack as follows: +8591 # name: 'foo' +8592 # type: int +8593 # register: 'eax' +8594 # +8595 # There's two primitives, as follows: +8596 # - name: 'increment' +8597 # out: int/reg +8598 # value: 'ff 0/subop/increment' +8599 # - name: 'increment' +8600 # inout: int/mem +8601 # value: 'ff 0/subop/increment' +8602 # +8603 # There's nothing in functions. +8604 # +8605 # . prologue +8606 55/push-ebp +8607 89/<- %ebp 4/r32/esp +8608 # setup +8609 (clear-stream _test-output-stream) +8610 (clear-stream $_test-output-buffered-file->buffer) +8611 # var type/ecx: (handle tree type-id) = int +8612 68/push 0/imm32/right/null +8613 68/push 1/imm32/left/int +8614 89/<- %ecx 4/r32/esp +8615 # var var-foo/ecx: var in eax +8616 68/push "eax"/imm32/register +8617 68/push 0/imm32/no-stack-offset +8618 68/push 1/imm32/block-depth +8619 51/push-ecx +8620 68/push "foo"/imm32 +8621 89/<- %ecx 4/r32/esp +8622 # var inouts/edi: (handle stmt-var) +8623 68/push 0/imm32/is-deref:false +8624 68/push 0/imm32/next +8625 51/push-ecx/var-foo +8626 89/<- %edi 4/r32/esp +8627 # var stmt/esi: statement +8628 68/push 0/imm32/next +8629 68/push 0/imm32/outputs +8630 57/push-edi/inouts +8631 68/push "increment"/imm32/operation +8632 68/push 1/imm32 +8633 89/<- %esi 4/r32/esp +8634 # var formal-var/ebx: var in any register +8635 68/push Any-register/imm32 +8636 68/push 0/imm32/no-stack-offset +8637 68/push 1/imm32/block-depth +8638 ff 6/subop/push *(ecx+4) # Var-type +8639 68/push "dummy"/imm32 +8640 89/<- %ebx 4/r32/esp +8641 # var operand/ebx: (handle stmt-var) +8642 68/push 0/imm32/is-deref:false +8643 68/push 0/imm32/next +8644 53/push-ebx/formal-var +8645 89/<- %ebx 4/r32/esp +8646 # var primitive1/ebx: primitive +8647 68/push 0/imm32/next +8648 68/push 0/imm32/output-is-write-only +8649 68/push 0/imm32/no-disp32 +8650 68/push 0/imm32/no-imm32 +8651 68/push 0/imm32/no-r32 +8652 68/push 3/imm32/rm32-in-first-output +8653 68/push "ff 0/subop/increment"/imm32/subx-name +8654 53/push-ebx/outputs/formal-outputs +8655 68/push 0/imm32/inouts +8656 68/push "increment"/imm32/name +8657 89/<- %ebx 4/r32/esp +8658 # var primitives/ebx: primitive +8659 53/push-ebx/next +8660 68/push 0/imm32/output-is-write-only +8661 68/push 0/imm32/no-disp32 +8662 68/push 0/imm32/no-imm32 +8663 68/push 0/imm32/no-r32 +8664 68/push 1/imm32/rm32-is-first-inout +8665 68/push "ff 0/subop/increment"/imm32/subx-name +8666 68/push 0/imm32/outputs +8667 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call +8668 68/push "increment"/imm32/name +8669 89/<- %ebx 4/r32/esp +8670 # convert +8671 c7 0/subop/copy *Curr-block-depth 0/imm32 +8672 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) +8673 (flush _test-output-buffered-file) +8674 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8680 # check output +8681 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2") +8682 # . epilogue +8683 89/<- %esp 5/r32/ebp +8684 5d/pop-to-ebp +8685 c3/return +8686 +8687 test-increment-register: +8688 # Select the right register between overloads. +8689 # foo <- increment +8690 # => +8691 # 50/increment-eax +8692 # +8693 # There's a variable on the var stack as follows: +8694 # name: 'foo' +8695 # type: int +8696 # register: 'eax' +8697 # +8698 # Primitives are the global definitions. +8699 # +8700 # There are no functions defined. +8701 # +8702 # . prologue +8703 55/push-ebp +8704 89/<- %ebp 4/r32/esp +8705 # setup +8706 (clear-stream _test-output-stream) +8707 (clear-stream $_test-output-buffered-file->buffer) +8708 # var type/ecx: (handle tree type-id) = int +8709 68/push 0/imm32/right/null +8710 68/push 1/imm32/left/int +8711 89/<- %ecx 4/r32/esp +8712 # var var-foo/ecx: var in eax +8713 68/push "eax"/imm32/register +8714 68/push 0/imm32/no-stack-offset +8715 68/push 1/imm32/block-depth +8716 51/push-ecx +8717 68/push "foo"/imm32 +8718 89/<- %ecx 4/r32/esp +8719 # var real-outputs/edi: (handle stmt-var) +8720 68/push 0/imm32/is-deref:false +8721 68/push 0/imm32/next +8722 51/push-ecx/var-foo +8723 89/<- %edi 4/r32/esp +8724 # var stmt/esi: statement +8725 68/push 0/imm32/next +8726 57/push-edi/outputs +8727 68/push 0/imm32/inouts +8728 68/push "increment"/imm32/operation +8729 68/push 1/imm32/regular-stmt +8730 89/<- %esi 4/r32/esp +8731 # convert +8732 c7 0/subop/copy *Curr-block-depth 0/imm32 +8733 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +8734 (flush _test-output-buffered-file) +8735 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8741 # check output +8742 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") +8743 # . epilogue +8744 89/<- %esp 5/r32/ebp +8745 5d/pop-to-ebp +8746 c3/return +8747 +8748 test-increment-var: +8749 # Select the right primitive between overloads. +8750 # foo <- increment +8751 # => +8752 # ff 0/subop/increment %eax # sub-optimal, but should suffice +8753 # +8754 # There's a variable on the var stack as follows: +8755 # name: 'foo' +8756 # type: int +8757 # register: 'eax' +8758 # +8759 # Primitives are the global definitions. +8760 # +8761 # There are no functions defined. +8762 # +8763 # . prologue +8764 55/push-ebp +8765 89/<- %ebp 4/r32/esp +8766 # setup +8767 (clear-stream _test-output-stream) +8768 (clear-stream $_test-output-buffered-file->buffer) +8769 # var type/ecx: (handle tree type-id) = int +8770 68/push 0/imm32/right/null +8771 68/push 1/imm32/left/int +8772 89/<- %ecx 4/r32/esp +8773 # var var-foo/ecx: var in eax +8774 68/push "eax"/imm32/register +8775 68/push 0/imm32/no-stack-offset +8776 68/push 1/imm32/block-depth +8777 51/push-ecx +8778 68/push "foo"/imm32 +8779 89/<- %ecx 4/r32/esp +8780 # var inouts/edi: (handle stmt-var) +8781 68/push 0/imm32/is-deref:false +8782 68/push 0/imm32/next +8783 51/push-ecx/var-foo +8784 89/<- %edi 4/r32/esp +8785 # var stmt/esi: statement +8786 68/push 0/imm32/next +8787 57/push-edi/outputs +8788 68/push 0/imm32/inouts +8789 68/push "increment"/imm32/operation +8790 68/push 1/imm32 +8791 89/<- %esi 4/r32/esp +8792 # convert +8793 c7 0/subop/copy *Curr-block-depth 0/imm32 +8794 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +8795 (flush _test-output-buffered-file) +8796 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8802 # check output +8803 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-var") +8804 # . epilogue +8805 89/<- %esp 5/r32/ebp +8806 5d/pop-to-ebp +8807 c3/return +8808 +8809 test-add-reg-to-reg: +8810 # var1/reg <- add var2/reg +8811 # => +8812 # 01/add %var1 var2 +8813 # +8814 # . prologue +8815 55/push-ebp +8816 89/<- %ebp 4/r32/esp +8817 # setup +8818 (clear-stream _test-output-stream) +8819 (clear-stream $_test-output-buffered-file->buffer) +8820 # var type/ecx: (handle tree type-id) = int +8821 68/push 0/imm32/right/null +8822 68/push 1/imm32/left/int +8823 89/<- %ecx 4/r32/esp +8824 # var var-var1/ecx: var in eax +8825 68/push "eax"/imm32/register +8826 68/push 0/imm32/no-stack-offset +8827 68/push 1/imm32/block-depth +8828 51/push-ecx +8829 68/push "var1"/imm32 +8830 89/<- %ecx 4/r32/esp +8831 # var var-var2/edx: var in ecx +8832 68/push "ecx"/imm32/register +8833 68/push 0/imm32/no-stack-offset +8834 68/push 1/imm32/block-depth +8835 ff 6/subop/push *(ecx+4) # Var-type +8836 68/push "var2"/imm32 +8837 89/<- %edx 4/r32/esp +8838 # var inouts/esi: (handle stmt-var) = [var2] +8839 68/push 0/imm32/is-deref:false +8840 68/push 0/imm32/next +8841 52/push-edx/var-var2 +8842 89/<- %esi 4/r32/esp +8843 # var outputs/edi: (handle stmt-var) = [var1, var2] +8844 68/push 0/imm32/is-deref:false +8845 68/push 0/imm32/next +8846 51/push-ecx/var-var1 +8847 89/<- %edi 4/r32/esp +8848 # var stmt/esi: statement +8849 68/push 0/imm32/next +8850 57/push-edi/outputs +8851 56/push-esi/inouts +8852 68/push "add"/imm32/operation +8853 68/push 1/imm32 +8854 89/<- %esi 4/r32/esp +8855 # convert +8856 c7 0/subop/copy *Curr-block-depth 0/imm32 +8857 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +8858 (flush _test-output-buffered-file) +8859 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8865 # check output +8866 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") +8867 # . epilogue +8868 89/<- %esp 5/r32/ebp +8869 5d/pop-to-ebp +8870 c3/return +8871 +8872 test-add-reg-to-mem: +8873 # add-to var1 var2/reg +8874 # => +8875 # 01/add *(ebp+__) var2 +8876 # +8877 # . prologue +8878 55/push-ebp +8879 89/<- %ebp 4/r32/esp +8880 # setup +8881 (clear-stream _test-output-stream) +8882 (clear-stream $_test-output-buffered-file->buffer) +8883 # var type/ecx: (handle tree type-id) = int +8884 68/push 0/imm32/right/null +8885 68/push 1/imm32/left/int +8886 89/<- %ecx 4/r32/esp +8887 # var var-var1/ecx: var +8888 68/push 0/imm32/no-register +8889 68/push 8/imm32/stack-offset +8890 68/push 1/imm32/block-depth +8891 51/push-ecx +8892 68/push "var1"/imm32 +8893 89/<- %ecx 4/r32/esp +8894 # var var-var2/edx: var in ecx +8895 68/push "ecx"/imm32/register +8896 68/push 0/imm32/no-stack-offset +8897 68/push 1/imm32/block-depth +8898 ff 6/subop/push *(ecx+4) # Var-type +8899 68/push "var2"/imm32 +8900 89/<- %edx 4/r32/esp +8901 # var inouts/esi: (handle stmt-var) = [var2] +8902 68/push 0/imm32/is-deref:false +8903 68/push 0/imm32/next +8904 52/push-edx/var-var2 +8905 89/<- %esi 4/r32/esp +8906 # var inouts = (handle stmt-var) = [var1, var2] +8907 56/push-esi/next +8908 51/push-ecx/var-var1 +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 "add-to"/imm32/operation +8915 68/push 1/imm32 +8916 89/<- %esi 4/r32/esp +8917 # convert +8918 c7 0/subop/copy *Curr-block-depth 0/imm32 +8919 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +8920 (flush _test-output-buffered-file) +8921 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8927 # check output +8928 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") +8929 # . epilogue +8930 89/<- %esp 5/r32/ebp +8931 5d/pop-to-ebp +8932 c3/return +8933 +8934 test-add-mem-to-reg: +8935 # var1/reg <- add var2 +8936 # => +8937 # 03/add *(ebp+__) var1 +8938 # +8939 # . prologue +8940 55/push-ebp +8941 89/<- %ebp 4/r32/esp +8942 # setup +8943 (clear-stream _test-output-stream) +8944 (clear-stream $_test-output-buffered-file->buffer) +8945 # var type/ecx: (handle tree type-id) = int +8946 68/push 0/imm32/right/null +8947 68/push 1/imm32/left/int +8948 89/<- %ecx 4/r32/esp +8949 # var var-var1/ecx: var in eax +8950 68/push "eax"/imm32/register +8951 68/push 0/imm32/no-stack-offset +8952 68/push 1/imm32/block-depth +8953 51/push-ecx +8954 68/push "var1"/imm32 +8955 89/<- %ecx 4/r32/esp +8956 # var var-var2/edx: var +8957 68/push 0/imm32/no-register +8958 68/push 8/imm32/stack-offset +8959 68/push 1/imm32/block-depth +8960 ff 6/subop/push *(ecx+4) # Var-type +8961 68/push "var2"/imm32 +8962 89/<- %edx 4/r32/esp +8963 # var inouts/esi: (handle stmt-var) = [var2] +8964 68/push 0/imm32/is-deref:false +8965 68/push 0/imm32/next +8966 52/push-edx/var-var2 +8967 89/<- %esi 4/r32/esp +8968 # var outputs/edi = (handle stmt-var) = [var1] +8969 68/push 0/imm32/is-deref:false +8970 68/push 0/imm32/next +8971 51/push-ecx/var-var1 +8972 89/<- %edi 4/r32/esp +8973 # var stmt/esi: statement +8974 68/push 0/imm32/next +8975 57/push-edi/outputs +8976 56/push-esi/inouts +8977 68/push "add"/imm32/operation +8978 68/push 1/imm32 +8979 89/<- %esi 4/r32/esp +8980 # convert +8981 c7 0/subop/copy *Curr-block-depth 0/imm32 +8982 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +8983 (flush _test-output-buffered-file) +8984 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8990 # check output +8991 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") +8992 # . epilogue +8993 89/<- %esp 5/r32/ebp +8994 5d/pop-to-ebp +8995 c3/return +8996 +8997 test-add-literal-to-eax: +8998 # var1/eax <- add 0x34 +8999 # => +9000 # 05/add-to-eax 0x34/imm32 +9001 # +9002 # . prologue +9003 55/push-ebp +9004 89/<- %ebp 4/r32/esp +9005 # setup +9006 (clear-stream _test-output-stream) +9007 (clear-stream $_test-output-buffered-file->buffer) +9008 # var type/ecx: (handle tree type-id) = int +9009 68/push 0/imm32/right/null +9010 68/push 1/imm32/left/int +9011 89/<- %ecx 4/r32/esp +9012 # var var-var1/ecx: var in eax +9013 68/push "eax"/imm32/register +9014 68/push 0/imm32/no-stack-offset +9015 68/push 1/imm32/block-depth +9016 51/push-ecx +9017 68/push "var1"/imm32 +9018 89/<- %ecx 4/r32/esp +9019 # var type/edx: (handle tree type-id) = literal +9020 68/push 0/imm32/right/null +9021 68/push 0/imm32/left/literal +9022 89/<- %edx 4/r32/esp +9023 # var var-var2/edx: var literal +9024 68/push 0/imm32/no-register +9025 68/push 0/imm32/no-stack-offset +9026 68/push 1/imm32/block-depth +9027 52/push-edx +9028 68/push "0x34"/imm32 +9029 89/<- %edx 4/r32/esp +9030 # var inouts/esi: (handle stmt-var) = [var2] +9031 68/push 0/imm32/is-deref:false +9032 68/push 0/imm32/next +9033 52/push-edx/var-var2 +9034 89/<- %esi 4/r32/esp +9035 # var outputs/edi: (handle stmt-var) = [var1] +9036 68/push 0/imm32/is-deref:false +9037 68/push 0/imm32/next +9038 51/push-ecx/var-var1 +9039 89/<- %edi 4/r32/esp +9040 # var stmt/esi: statement +9041 68/push 0/imm32/next +9042 57/push-edi/outputs +9043 56/push-esi/inouts +9044 68/push "add"/imm32/operation +9045 68/push 1/imm32 +9046 89/<- %esi 4/r32/esp +9047 # convert +9048 c7 0/subop/copy *Curr-block-depth 0/imm32 +9049 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +9050 (flush _test-output-buffered-file) +9051 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +9057 # check output +9058 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") +9059 # . epilogue +9060 89/<- %esp 5/r32/ebp +9061 5d/pop-to-ebp +9062 c3/return +9063 +9064 test-add-literal-to-reg: +9065 # var1/ecx <- add 0x34 +9066 # => +9067 # 81 0/subop/add %ecx 0x34/imm32 +9068 # +9069 # . prologue +9070 55/push-ebp +9071 89/<- %ebp 4/r32/esp +9072 # setup +9073 (clear-stream _test-output-stream) +9074 (clear-stream $_test-output-buffered-file->buffer) +9075 # var type/ecx: (handle tree type-id) = int +9076 68/push 0/imm32/right/null +9077 68/push 1/imm32/left/int +9078 89/<- %ecx 4/r32/esp +9079 # var var-var1/ecx: var in ecx +9080 68/push "ecx"/imm32/register +9081 68/push 0/imm32/no-stack-offset +9082 68/push 1/imm32/block-depth +9083 51/push-ecx +9084 68/push "var1"/imm32 +9085 89/<- %ecx 4/r32/esp +9086 # var type/edx: (handle tree type-id) = literal +9087 68/push 0/imm32/right/null +9088 68/push 0/imm32/left/literal +9089 89/<- %edx 4/r32/esp +9090 # var var-var2/edx: var literal +9091 68/push 0/imm32/no-register +9092 68/push 0/imm32/no-stack-offset +9093 68/push 1/imm32/block-depth +9094 52/push-edx +9095 68/push "0x34"/imm32 +9096 89/<- %edx 4/r32/esp +9097 # var inouts/esi: (handle stmt-var) = [var2] +9098 68/push 0/imm32/is-deref:false +9099 68/push 0/imm32/next +9100 52/push-edx/var-var2 +9101 89/<- %esi 4/r32/esp +9102 # var outputs/edi: (handle stmt-var) = [var1] +9103 68/push 0/imm32/is-deref:false +9104 68/push 0/imm32/next +9105 51/push-ecx/var-var1 +9106 89/<- %edi 4/r32/esp +9107 # var stmt/esi: statement +9108 68/push 0/imm32/next +9109 57/push-edi/outputs +9110 56/push-esi/inouts +9111 68/push "add"/imm32/operation +9112 68/push 1/imm32 +9113 89/<- %esi 4/r32/esp +9114 # convert +9115 c7 0/subop/copy *Curr-block-depth 0/imm32 +9116 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +9117 (flush _test-output-buffered-file) +9118 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +9124 # check output +9125 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") +9126 # . epilogue +9127 89/<- %esp 5/r32/ebp +9128 5d/pop-to-ebp +9129 c3/return +9130 +9131 test-add-literal-to-mem: +9132 # add-to var1, 0x34 +9133 # => +9134 # 81 0/subop/add %eax 0x34/imm32 +9135 # +9136 # . prologue +9137 55/push-ebp +9138 89/<- %ebp 4/r32/esp +9139 # setup +9140 (clear-stream _test-output-stream) +9141 (clear-stream $_test-output-buffered-file->buffer) +9142 # var type/ecx: (handle tree type-id) = int +9143 68/push 0/imm32/right/null +9144 68/push 1/imm32/left/int +9145 89/<- %ecx 4/r32/esp +9146 # var var-var1/ecx: var +9147 68/push 0/imm32/no-register +9148 68/push 8/imm32/stack-offset +9149 68/push 1/imm32/block-depth +9150 51/push-ecx +9151 68/push "var1"/imm32 +9152 89/<- %ecx 4/r32/esp +9153 # var type/edx: (handle tree type-id) = literal +9154 68/push 0/imm32/right/null +9155 68/push 0/imm32/left/literal +9156 89/<- %edx 4/r32/esp +9157 # var var-var2/edx: var literal +9158 68/push 0/imm32/no-register +9159 68/push 0/imm32/no-stack-offset +9160 68/push 1/imm32/block-depth +9161 52/push-edx +9162 68/push "0x34"/imm32 +9163 89/<- %edx 4/r32/esp +9164 # var inouts/esi: (handle stmt-var) = [var2] +9165 68/push 0/imm32/is-deref:false +9166 68/push 0/imm32/next +9167 52/push-edx/var-var2 +9168 89/<- %esi 4/r32/esp +9169 # var inouts = (handle stmt-var) = [var1, var2] +9170 68/push 0/imm32/is-deref:false +9171 56/push-esi/next +9172 51/push-ecx/var-var1 +9173 89/<- %esi 4/r32/esp +9174 # var stmt/esi: statement +9175 68/push 0/imm32/next +9176 68/push 0/imm32/outputs +9177 56/push-esi/inouts +9178 68/push "add-to"/imm32/operation +9179 68/push 1/imm32 +9180 89/<- %esi 4/r32/esp +9181 # convert +9182 c7 0/subop/copy *Curr-block-depth 0/imm32 +9183 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +9184 (flush _test-output-buffered-file) +9185 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +9191 # check output +9192 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") +9193 # . epilogue +9194 89/<- %esp 5/r32/ebp +9195 5d/pop-to-ebp +9196 c3/return +9197 +9198 test-compare-mem-with-reg: +9199 # compare var1, var2/eax +9200 # => +9201 # 39/compare *(ebp+___) 0/r32/eax +9202 # +9203 # . prologue +9204 55/push-ebp +9205 89/<- %ebp 4/r32/esp +9206 # setup +9207 (clear-stream _test-output-stream) +9208 (clear-stream $_test-output-buffered-file->buffer) +9209 # var type/ecx: (handle tree type-id) = int +9210 68/push 0/imm32/right/null +9211 68/push 1/imm32/left/int +9212 89/<- %ecx 4/r32/esp +9213 # var var-var2/ecx: var in eax +9214 68/push "eax"/imm32/register +9215 68/push 0/imm32/no-stack-offset +9216 68/push 1/imm32/block-depth +9217 51/push-ecx +9218 68/push "var2"/imm32 +9219 89/<- %ecx 4/r32/esp +9220 # var var-var1/edx: var +9221 68/push 0/imm32/no-register +9222 68/push 8/imm32/stack-offset +9223 68/push 1/imm32/block-depth +9224 ff 6/subop/push *(ecx+4) # Var-type +9225 68/push "var1"/imm32 +9226 89/<- %edx 4/r32/esp +9227 # var inouts/esi: (handle stmt-var) = [var2] +9228 68/push 0/imm32/is-deref:false +9229 68/push 0/imm32/next +9230 51/push-ecx/var-var2 +9231 89/<- %esi 4/r32/esp +9232 # inouts = [var1, var2] +9233 68/push 0/imm32/is-deref:false +9234 56/push-esi +9235 52/push-edx/var-var1 +9236 89/<- %esi 4/r32/esp +9237 # var stmt/esi: statement +9238 68/push 0/imm32/next +9239 68/push 0/imm32/outputs +9240 56/push-esi/inouts +9241 68/push "compare"/imm32/operation +9242 68/push 1/imm32 +9243 89/<- %esi 4/r32/esp +9244 # convert +9245 c7 0/subop/copy *Curr-block-depth 0/imm32 +9246 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +9247 (flush _test-output-buffered-file) +9248 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +9254 # check output +9255 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") +9256 # . epilogue +9257 89/<- %esp 5/r32/ebp +9258 5d/pop-to-ebp +9259 c3/return +9260 +9261 test-compare-reg-with-mem: +9262 # compare var1/eax, var2 +9263 # => +9264 # 3b/compare *(ebp+___) 0/r32/eax +9265 # +9266 # . prologue +9267 55/push-ebp +9268 89/<- %ebp 4/r32/esp +9269 # setup +9270 (clear-stream _test-output-stream) +9271 (clear-stream $_test-output-buffered-file->buffer) +9272 # var type/ecx: (handle tree type-id) = int +9273 68/push 0/imm32/right/null +9274 68/push 1/imm32/left/int +9275 89/<- %ecx 4/r32/esp +9276 # var var-var1/ecx: var in eax +9277 68/push "eax"/imm32/register +9278 68/push 0/imm32/no-stack-offset +9279 68/push 1/imm32/block-depth +9280 51/push-ecx +9281 68/push "var1"/imm32 +9282 89/<- %ecx 4/r32/esp +9283 # var var-var2/edx: var +9284 68/push 0/imm32/no-register +9285 68/push 8/imm32/stack-offset +9286 68/push 1/imm32/block-depth +9287 ff 6/subop/push *(ecx+4) # Var-type +9288 68/push "var2"/imm32 +9289 89/<- %edx 4/r32/esp +9290 # var inouts/esi: (handle stmt-var) = [var2] +9291 68/push 0/imm32/is-deref:false +9292 68/push 0/imm32/next +9293 52/push-edx/var-var2 +9294 89/<- %esi 4/r32/esp +9295 # inouts = [var1, var2] +9296 68/push 0/imm32/is-deref:false +9297 56/push-esi +9298 51/push-ecx/var-var1 +9299 89/<- %esi 4/r32/esp +9300 # var stmt/esi: statement +9301 68/push 0/imm32/next +9302 68/push 0/imm32/outputs +9303 56/push-esi/inouts +9304 68/push "compare"/imm32/operation +9305 68/push 1/imm32 +9306 89/<- %esi 4/r32/esp +9307 # convert +9308 c7 0/subop/copy *Curr-block-depth 0/imm32 +9309 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +9310 (flush _test-output-buffered-file) +9311 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +9317 # check output +9318 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") +9319 # . epilogue +9320 89/<- %esp 5/r32/ebp +9321 5d/pop-to-ebp +9322 c3/return +9323 +9324 test-compare-mem-with-literal: +9325 # compare var1, 0x34 +9326 # => +9327 # 81 7/subop/compare *(ebp+___) 0x34/imm32 +9328 # +9329 # . prologue +9330 55/push-ebp +9331 89/<- %ebp 4/r32/esp +9332 # setup +9333 (clear-stream _test-output-stream) +9334 (clear-stream $_test-output-buffered-file->buffer) +9335 # var type/ecx: (handle tree type-id) = int +9336 68/push 0/imm32/right/null +9337 68/push 1/imm32/left/int +9338 89/<- %ecx 4/r32/esp +9339 # var var-var1/ecx: var +9340 68/push 0/imm32/no-register +9341 68/push 8/imm32/stack-offset +9342 68/push 1/imm32/block-depth +9343 51/push-ecx +9344 68/push "var1"/imm32 +9345 89/<- %ecx 4/r32/esp +9346 # var type/edx: (handle tree type-id) = literal +9347 68/push 0/imm32/right/null +9348 68/push 0/imm32/left/literal +9349 89/<- %edx 4/r32/esp +9350 # var var-var2/edx: var literal +9351 68/push 0/imm32/no-register +9352 68/push 0/imm32/no-stack-offset +9353 68/push 1/imm32/block-depth +9354 52/push-edx +9355 68/push "0x34"/imm32 +9356 89/<- %edx 4/r32/esp +9357 # var inouts/esi: (handle stmt-var) = [var2] +9358 68/push 0/imm32/is-deref:false +9359 68/push 0/imm32/next +9360 52/push-edx/var-var2 +9361 89/<- %esi 4/r32/esp +9362 # inouts = [var1, var2] +9363 68/push 0/imm32/is-deref:false +9364 56/push-esi/next +9365 51/push-ecx/var-var1 +9366 89/<- %esi 4/r32/esp +9367 # var stmt/esi: statement +9368 68/push 0/imm32/next +9369 68/push 0/imm32/outputs +9370 56/push-esi/inouts +9371 68/push "compare"/imm32/operation +9372 68/push 1/imm32 +9373 89/<- %esi 4/r32/esp +9374 # convert +9375 c7 0/subop/copy *Curr-block-depth 0/imm32 +9376 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +9377 (flush _test-output-buffered-file) +9378 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +9384 # check output +9385 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") +9386 # . epilogue +9387 89/<- %esp 5/r32/ebp +9388 5d/pop-to-ebp +9389 c3/return +9390 +9391 test-compare-eax-with-literal: +9392 # compare var1/eax 0x34 +9393 # => +9394 # 3d/compare-eax-with 0x34/imm32 +9395 # +9396 # . prologue +9397 55/push-ebp +9398 89/<- %ebp 4/r32/esp +9399 # setup +9400 (clear-stream _test-output-stream) +9401 (clear-stream $_test-output-buffered-file->buffer) +9402 # var type/ecx: (handle tree type-id) = int +9403 68/push 0/imm32/right/null +9404 68/push 1/imm32/left/int +9405 89/<- %ecx 4/r32/esp +9406 # var var-var1/ecx: var in eax +9407 68/push "eax"/imm32/register +9408 68/push 0/imm32/no-stack-offset +9409 68/push 1/imm32/block-depth +9410 51/push-ecx +9411 68/push "var1"/imm32 +9412 89/<- %ecx 4/r32/esp +9413 # var type/edx: (handle tree type-id) = literal +9414 68/push 0/imm32/right/null +9415 68/push 0/imm32/left/literal +9416 89/<- %edx 4/r32/esp +9417 # var var-var2/edx: var literal +9418 68/push 0/imm32/no-register +9419 68/push 0/imm32/no-stack-offset +9420 68/push 1/imm32/block-depth +9421 52/push-edx +9422 68/push "0x34"/imm32 +9423 89/<- %edx 4/r32/esp +9424 # var inouts/esi: (handle stmt-var) = [var2] +9425 68/push 0/imm32/is-deref:false +9426 68/push 0/imm32/next +9427 52/push-edx/var-var2 +9428 89/<- %esi 4/r32/esp +9429 # inouts = [var1, var2] +9430 68/push 0/imm32/is-deref:false +9431 56/push-esi/next +9432 51/push-ecx/var-var1 +9433 89/<- %esi 4/r32/esp +9434 # var stmt/esi: statement +9435 68/push 0/imm32/next +9436 68/push 0/imm32/outputs +9437 56/push-esi/inouts +9438 68/push "compare"/imm32/operation +9439 68/push 1/imm32/regular-stmt +9440 89/<- %esi 4/r32/esp +9441 # convert +9442 c7 0/subop/copy *Curr-block-depth 0/imm32 +9443 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +9444 (flush _test-output-buffered-file) +9445 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +9451 # check output +9452 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") +9453 # . epilogue +9454 89/<- %esp 5/r32/ebp +9455 5d/pop-to-ebp +9456 c3/return +9457 +9458 test-compare-reg-with-literal: +9459 # compare var1/ecx 0x34 +9460 # => +9461 # 81 7/subop/compare %ecx 0x34/imm32 +9462 # +9463 # . prologue +9464 55/push-ebp +9465 89/<- %ebp 4/r32/esp +9466 # setup +9467 (clear-stream _test-output-stream) +9468 (clear-stream $_test-output-buffered-file->buffer) +9469 # var type/ecx: (handle tree type-id) = int +9470 68/push 0/imm32/right/null +9471 68/push 1/imm32/left/int +9472 89/<- %ecx 4/r32/esp +9473 # var var-var1/ecx: var in ecx +9474 68/push "ecx"/imm32/register +9475 68/push 0/imm32/no-stack-offset +9476 68/push 1/imm32/block-depth +9477 51/push-ecx +9478 68/push "var1"/imm32 +9479 89/<- %ecx 4/r32/esp +9480 # var type/edx: (handle tree type-id) = literal +9481 68/push 0/imm32/right/null +9482 68/push 0/imm32/left/literal +9483 89/<- %edx 4/r32/esp +9484 # var var-var2/edx: var literal +9485 68/push 0/imm32/no-register +9486 68/push 0/imm32/no-stack-offset +9487 68/push 1/imm32/block-depth +9488 52/push-edx +9489 68/push "0x34"/imm32 +9490 89/<- %edx 4/r32/esp +9491 # var inouts/esi: (handle stmt-var) = [var2] +9492 68/push 0/imm32/is-deref:false +9493 68/push 0/imm32/next +9494 52/push-edx/var-var2 +9495 89/<- %esi 4/r32/esp +9496 # inouts = [var1, var2] +9497 68/push 0/imm32/is-deref:false +9498 56/push-esi/next +9499 51/push-ecx/var-var1 +9500 89/<- %esi 4/r32/esp +9501 # var stmt/esi: statement +9502 68/push 0/imm32/next +9503 68/push 0/imm32/outputs +9504 56/push-esi/inouts +9505 68/push "compare"/imm32/operation +9506 68/push 1/imm32/regular-stmt +9507 89/<- %esi 4/r32/esp +9508 # convert +9509 c7 0/subop/copy *Curr-block-depth 0/imm32 +9510 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +9511 (flush _test-output-buffered-file) +9512 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +9518 # check output +9519 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") +9520 # . epilogue +9521 89/<- %esp 5/r32/ebp +9522 5d/pop-to-ebp +9523 c3/return +9524 +9525 test-emit-subx-stmt-function-call: +9526 # Call a function on a variable on the stack. +9527 # f foo +9528 # => +9529 # (f2 *(ebp-8)) +9530 # (Changing the function name supports overloading in general, but here it +9531 # just serves to help disambiguate things.) +9532 # +9533 # There's a variable on the var stack as follows: +9534 # name: 'foo' +9535 # type: int +9536 # stack-offset: -8 +9537 # +9538 # There's nothing in primitives. +9539 # +9540 # There's a function with this info: +9541 # name: 'f' +9542 # inout: int/mem +9543 # value: 'f2' +9544 # +9545 # . prologue +9546 55/push-ebp +9547 89/<- %ebp 4/r32/esp +9548 # setup +9549 (clear-stream _test-output-stream) +9550 (clear-stream $_test-output-buffered-file->buffer) +9551 # var type/ecx: (handle tree type-id) = int +9552 68/push 0/imm32/right/null +9553 68/push 1/imm32/left/int +9554 89/<- %ecx 4/r32/esp +9555 # var var-foo/ecx: var +9556 68/push 0/imm32/no-register +9557 68/push -8/imm32/stack-offset +9558 68/push 0/imm32/block-depth +9559 51/push-ecx +9560 68/push "foo"/imm32 +9561 89/<- %ecx 4/r32/esp +9562 # var inouts/esi: (handle stmt-var) +9563 68/push 0/imm32/is-deref:false +9564 68/push 0/imm32/next +9565 51/push-ecx/var-foo +9566 89/<- %esi 4/r32/esp +9567 # var stmt/esi: statement +9568 68/push 0/imm32/next +9569 68/push 0/imm32/outputs +9570 56/push-esi/inouts +9571 68/push "f"/imm32/operation +9572 68/push 1/imm32 +9573 89/<- %esi 4/r32/esp +9574 # var functions/ebx: function +9575 68/push 0/imm32/next +9576 68/push 0/imm32/body +9577 68/push 0/imm32/outputs +9578 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call +9579 68/push "f2"/imm32/subx-name +9580 68/push "f"/imm32/name +9581 89/<- %ebx 4/r32/esp +9582 # convert +9583 c7 0/subop/copy *Curr-block-depth 0/imm32 +9584 (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx) +9585 (flush _test-output-buffered-file) +9586 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +9592 # check output +9593 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call") +9594 # . epilogue +9595 89/<- %esp 5/r32/ebp +9596 5d/pop-to-ebp +9597 c3/return +9598 +9599 test-emit-subx-stmt-function-call-with-literal-arg: +9600 # Call a function on a literal. +9601 # f 34 +9602 # => +9603 # (f2 34) +9604 # +9605 # . prologue +9606 55/push-ebp +9607 89/<- %ebp 4/r32/esp +9608 # setup +9609 (clear-stream _test-output-stream) +9610 (clear-stream $_test-output-buffered-file->buffer) +9611 # var type/ecx: (handle tree type-id) = literal +9612 68/push 0/imm32/right/null +9613 68/push 0/imm32/left/literal +9614 89/<- %ecx 4/r32/esp +9615 # var var-foo/ecx: var literal +9616 68/push 0/imm32/no-register +9617 68/push 0/imm32/no-stack-offset +9618 68/push 0/imm32/block-depth +9619 51/push-ecx +9620 68/push "34"/imm32 +9621 89/<- %ecx 4/r32/esp +9622 # var inouts/esi: (handle stmt-var) +9623 68/push 0/imm32/is-deref:false +9624 68/push 0/imm32/next +9625 51/push-ecx/var-foo +9626 89/<- %esi 4/r32/esp +9627 # var stmt/esi: statement +9628 68/push 0/imm32/next +9629 68/push 0/imm32/outputs +9630 56/push-esi/inouts +9631 68/push "f"/imm32/operation +9632 68/push 1/imm32 +9633 89/<- %esi 4/r32/esp +9634 # var functions/ebx: function +9635 68/push 0/imm32/next +9636 68/push 0/imm32/body +9637 68/push 0/imm32/outputs +9638 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call +9639 68/push "f2"/imm32/subx-name +9640 68/push "f"/imm32/name +9641 89/<- %ebx 4/r32/esp +9642 # convert +9643 c7 0/subop/copy *Curr-block-depth 0/imm32 +9644 (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx) +9645 (flush _test-output-buffered-file) +9646 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +9652 # check output +9653 (check-next-stream-line-equal _test-output-stream "(f2 34)" "F - test-emit-subx-stmt-function-call-with-literal-arg") +9654 # . epilogue +9655 89/<- %esp 5/r32/ebp +9656 5d/pop-to-ebp +9657 c3/return +9658 +9659 emit-indent: # out: (addr buffered-file), n: int +9660 # . prologue +9661 55/push-ebp +9662 89/<- %ebp 4/r32/esp +9663 # . save registers +9664 50/push-eax +9665 # var i/eax: int = n +9666 8b/-> *(ebp+0xc) 0/r32/eax +9667 { +9668 # if (i <= 0) break +9669 3d/compare-eax-with 0/imm32 +9670 7e/jump-if-<= break/disp8 +9671 (write-buffered *(ebp+8) " ") +9672 48/decrement-eax +9673 eb/jump loop/disp8 +9674 } +9675 $emit-indent:end: +9676 # . restore registers +9677 58/pop-to-eax +9678 # . epilogue +9679 89/<- %esp 5/r32/ebp +9680 5d/pop-to-ebp +9681 c3/return +9682 +9683 emit-subx-prologue: # out: (addr buffered-file) +9684 # . prologue +9685 55/push-ebp +9686 89/<- %ebp 4/r32/esp +9687 # +9688 (write-buffered *(ebp+8) " # . prologue\n") +9689 (write-buffered *(ebp+8) " 55/push-ebp\n") +9690 (write-buffered *(ebp+8) " 89/<- %ebp 4/r32/esp\n") +9691 $emit-subx-prologue:end: +9692 # . epilogue +9693 89/<- %esp 5/r32/ebp +9694 5d/pop-to-ebp +9695 c3/return +9696 +9697 emit-subx-epilogue: # out: (addr buffered-file) +9698 # . prologue +9699 55/push-ebp +9700 89/<- %ebp 4/r32/esp +9701 # +9702 (write-buffered *(ebp+8) " # . epilogue\n") +9703 (write-buffered *(ebp+8) " 89/<- %esp 5/r32/ebp\n") +9704 (write-buffered *(ebp+8) " 5d/pop-to-ebp\n") +9705 (write-buffered *(ebp+8) " c3/return\n") +9706 $emit-subx-epilogue:end: +9707 # . epilogue +9708 89/<- %esp 5/r32/ebp +9709 5d/pop-to-ebp +9710 c3/return diff --git a/html/apps/tests.subx.html b/html/apps/tests.subx.html index 0411bb81..7147a0f6 100644 --- a/html/apps/tests.subx.html +++ b/html/apps/tests.subx.html @@ -129,7 +129,7 @@ if ('onhashchange' in window) { 69 70 subx-gen-run-tests: # in: (addr buffered-file), out: (addr buffered-file) 71 # pseudocode - 72 # bool tests-found = false + 72 # boolean tests-found = false 73 # var line: (stream byte 512) 74 # var new-code-segment: (handle stream byte) = new-stream(Segment-size, 1) 75 # write(new-code-segment, "\n== code\n") -- cgit 1.4.1-2-gfad0