Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Move callframe moves to the actual points where callframe values are moved. They can then be optimized by avaiability and liveness analysis. |
---|---|
Timelines: | family | ancestors | descendants | both | notworking | kbk-refactor-callframe |
Files: | files | file ages | folders |
SHA3-256: |
dbd9571178f097cefc9361707c89a48e |
User & Date: | kbk 2019-01-01 21:57:35.086 |
Context
2019-01-01
| ||
23:06 | Update quadcode generation and documentation so that 'direct' operations refer to the callframe (which is necessary in the event that they are emitted to deal with double-dereference). CODE ISSUER IS NOT YET UPDATED TO COPE WITH THE CHANGE. check-in: 104debc734 user: kbk tags: notworking, kbk-refactor-callframe | |
21:57 | Move callframe moves to the actual points where callframe values are moved. They can then be optimized by avaiability and liveness analysis. check-in: dbd9571178 user: kbk tags: notworking, kbk-refactor-callframe | |
2018-12-29
| ||
21:00 | Keep dictionary iterations out of the callframe - they can never be addressed by upvar check-in: ea7b788fb4 user: kbk tags: kbk-refactor-callframe | |
Changes
Changes to quadcode/callframe.tcl.
︙ | ︙ | |||
29 30 31 32 33 34 35 | foreach bb $bbcontent { if {[lsearch -exact -index 0 $bb upvar] >= 0} { return 1 } } return 0 } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | foreach bb $bbcontent { if {[lsearch -exact -index 0 $bb upvar] >= 0} { return 1 } } return 0 } # quadcode::transformer method cleanupMoveFromCallFrame -- # # Removes and replaces 'moveFromCallFrame' where it is known that # a target procedure does not write a callframe variable # # Results: |
︙ | ︙ |
Changes to quadcode/transformer.tcl.
︙ | ︙ | |||
314 315 316 317 318 319 320 | # renameTemps foreach pass { bbpartition constJumpPeephole sortbb loopinv | < | 314 315 316 317 318 319 320 321 322 323 324 325 326 327 | # renameTemps foreach pass { bbpartition constJumpPeephole sortbb loopinv ssa ud_du_chain copyprop fqcmd varargs deadbb bbidom |
︙ | ︙ |
Changes to quadcode/translate.tcl.
︙ | ︙ | |||
49 50 51 52 53 54 55 | my debug-translate { puts "Translate bytecode: $originProc" } # Construct a header that sets parameters and provides a fake point # to which live-on-entry variables can be attached. | > > > > | < > < > > > > > > > > > > > > > | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | my debug-translate { puts "Translate bytecode: $originProc" } # Construct a header that sets parameters and provides a fake point # to which live-on-entry variables can be attached. set vlist {} foreach v [dict get $bytecode variables] { if {!("temp" in [lindex $v 0])} { lappend vlist [lindex $v 1] } } my quads entry {temp @callframe} [list literal $vlist] my quads @debug-context {} [list literal [list proc $originProc]] if {[dict exists $bytecode sourcefile]} { my quads @debug-file {} [list literal [dict get $bytecode sourcefile]] } if {[dict exists $bytecode initiallinenumber]} { my quads @debug-line {} \ [list literal [list [dict get $bytecode initiallinenumber] 0]] } if {[dict exists $bytecode script]} { my quads @debug-script {} [list literal [dict get $bytecode script]] } # Also set the variable list in this transformer for later. set vars [lmap v $vlist {list var $v}] # Put in code to transfer arguments set idx 0 foreach v [dict get $bytecode variables] { if {{arg} in [lindex $v 0]} { my quads param [list var [lindex $v 1]] [list arg $idx] } incr idx } # Make sure that the args are in the callframe. set q [list moveToCallFrame {temp @callframe} {temp @callframe}] foreach v [dict get $bytecode variables] { if {{arg} in [lindex $v 0]} { lappend q [list literal [lindex $v 1]] [list var [lindex $v 1]] } } if {[llength $q] > 3} { my quads {*}$q } # Iterate the instruction list dict for {pc insn} [dict get $bytecode instructions] { if {![dict exists $bytecode stackState $pc]} { my debug-translate { puts "$pc: (unreachable): $insn" } |
︙ | ︙ | |||
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 | my generate-scalar-check $pc $var {TCL READ VARNAME} \ "can't read \"%s\": variable is array" set auxNum [string range [lindex $insn 2] 1 end] set aux [lindex [dict get $bytecode auxiliary] $auxNum] set mid [list temp opnd0] set val [list temp [incr depth -1]] set idx 0 foreach v [dict get $aux variables] { set r [my index-to-var $v] my generate-scalar-check $pc $r {TCL WRITE VARNAME} \ "can't set \"%s\": variable is array" my error-quads $pc listIndex $mid $val [list literal $idx] my error-quads $pc dictGetOrNexist $r $var $mid incr idx } } dictUpdateEnd { set var [my index-to-var [lindex $insn 1]] set auxNum [string range [lindex $insn 2] 1 end] set aux [lindex [dict get $bytecode auxiliary] $auxNum] set key [list temp opnd1] set isary [list temp opnd2] | > > > | 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 | my generate-scalar-check $pc $var {TCL READ VARNAME} \ "can't read \"%s\": variable is array" set auxNum [string range [lindex $insn 2] 1 end] set aux [lindex [dict get $bytecode auxiliary] $auxNum] set mid [list temp opnd0] set val [list temp [incr depth -1]] set idx 0 set toUpdate {} foreach v [dict get $aux variables] { set r [my index-to-var $v] my generate-scalar-check $pc $r {TCL WRITE VARNAME} \ "can't set \"%s\": variable is array" my error-quads $pc listIndex $mid $val [list literal $idx] my error-quads $pc dictGetOrNexist $r $var $mid lappend toUpdate [list literal [lindex $r 1]] $r incr idx } my update-in-callframe {*}$toUpdate } dictUpdateEnd { set var [my index-to-var [lindex $insn 1]] set auxNum [string range [lindex $insn 2] 1 end] set aux [lindex [dict get $bytecode auxiliary] $auxNum] set key [list temp opnd1] set isary [list temp opnd2] |
︙ | ︙ | |||
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 | my quads copy $mid Nothing my quads jump [list pc [expr {$n + 4}]] my quads extractScalar $mid $r # Write the value to the right key of the dict my error-quads $pc dictSetOrUnset $updating $updating $key $mid } my quads copy $var $updating } unsetScalar { # TODO - This doesn't complain on unsetting a nonexistent # variable, it ignores '-nocomplain' set var [my index-to-var [lindex $insn 2]] my quads unset $var } unsetArray { # TODO - This doesn't complain on unsetting a nonexistent # element, it ignores '-nocomplain' set idx [list temp [incr depth -1]] set ary [my index-to-var [lindex $insn 2]] my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \ "can't unset \"%s(%s)\": variable isn't array" my quads initArrayIfNotExists $ary $ary my quads arrayUnset $ary $ary $idx } dictDone { # Do nothing; general free will clean up. } verifyDict { set r [list temp [incr depth -1]] my error-quads $pc dictSize $r $r | > > > | 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 | my quads copy $mid Nothing my quads jump [list pc [expr {$n + 4}]] my quads extractScalar $mid $r # Write the value to the right key of the dict my error-quads $pc dictSetOrUnset $updating $updating $key $mid } my quads copy $var $updating my update-in-callframe [list literal [lindex $var 1]] $var } unsetScalar { # TODO - This doesn't complain on unsetting a nonexistent # variable, it ignores '-nocomplain' set var [my index-to-var [lindex $insn 2]] my quads unset $var my update-in-callframe [list literal [lindex $var 1]] Nothing } unsetArray { # TODO - This doesn't complain on unsetting a nonexistent # element, it ignores '-nocomplain' set idx [list temp [incr depth -1]] set ary [my index-to-var [lindex $insn 2]] my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \ "can't unset \"%s(%s)\": variable isn't array" my quads initArrayIfNotExists $ary $ary my quads arrayUnset $ary $ary $idx my update-in-callframe [list literal [lindex $ary 1]] $ary } dictDone { # Do nothing; general free will clean up. } verifyDict { set r [list temp [incr depth -1]] my error-quads $pc dictSize $r $r |
︙ | ︙ | |||
574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 | "can't set \"%s\": variable is array" my quads initIfNotExists $var $var {literal 0} my quads copy $result [list literal $delta] my generate-arith-domain-check $pc incr $var $result my quads purify {temp opd0} $var my quads purify {temp opd1} $result my quads add $var {temp opd0} {temp opd1} my quads copy $result $var } incrScalar1 { set result [list temp $depth] set val [list temp [incr depth -1]] set var [my index-to-var [lindex $insn 1]] my generate-scalar-check $pc $var {TCL WRITE VARNAME} \ "can't set \"%s\": variable is array" my quads initIfNotExists $var $var {literal 0} my generate-arith-domain-check $pc incr $var $val my quads purify {temp opd0} $var my quads purify {temp opd1} $val my quads add $var {temp opd0} {temp opd1} my quads copy $result $var } incrArray1Imm { set tmp [list temp $depth] set idx [list temp [incr depth -1]] set ary [my index-to-var [lindex $insn 1]] set delta [list literal [lindex $insn 2]] my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \ "can't read \"%s(%s)\": variable isn't array" my quads initArrayIfNotExists $ary $ary my quads copy $tmp $delta set res $idx set inval {temp opd0} my quads arrayGet $inval $ary $idx my quads initIfNotExists $inval $inval {literal 0} my generate-arith-domain-check $pc incr $inval $tmp my quads purify {temp opd1} $inval my quads purify {temp opd2} $tmp my quads add $inval {temp opd1} {temp opd2} my quads arraySet $ary $ary $idx $inval my quads copy $res $inval } incrArray1 { set delta [list temp [incr depth -1]] set idx [list temp [incr depth -1]] set ary [my index-to-var [lindex $insn 1]] my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \ "can't read \"%s(%s)\": variable isn't array" my quads initArrayIfNotExists $ary $ary set res $idx set inval {temp opd0} my quads arrayGet $inval $ary $idx my quads initIfNotExists $inval $inval {literal 0} my generate-arith-domain-check $pc incr $inval $delta my quads purify {temp opd1} $inval my quads purify {temp opd2} $delta my quads add $inval {temp opd1} {temp opd2} my quads arraySet $ary $ary $idx $inval my quads copy $res $inval } incrStkImm { set var [list temp [incr depth -1]] set delta [list literal [lindex $insn 1]] # TODO: This assumes we're dealing with qualified names! set val {temp opd2} | > > > > | 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 | "can't set \"%s\": variable is array" my quads initIfNotExists $var $var {literal 0} my quads copy $result [list literal $delta] my generate-arith-domain-check $pc incr $var $result my quads purify {temp opd0} $var my quads purify {temp opd1} $result my quads add $var {temp opd0} {temp opd1} my update-in-callframe [list literal [lindex $var 1]] $var my quads copy $result $var } incrScalar1 { set result [list temp $depth] set val [list temp [incr depth -1]] set var [my index-to-var [lindex $insn 1]] my generate-scalar-check $pc $var {TCL WRITE VARNAME} \ "can't set \"%s\": variable is array" my quads initIfNotExists $var $var {literal 0} my generate-arith-domain-check $pc incr $var $val my quads purify {temp opd0} $var my quads purify {temp opd1} $val my quads add $var {temp opd0} {temp opd1} my update-in-callframe [list literal [lindex $var 1]] $var my quads copy $result $var } incrArray1Imm { set tmp [list temp $depth] set idx [list temp [incr depth -1]] set ary [my index-to-var [lindex $insn 1]] set delta [list literal [lindex $insn 2]] my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \ "can't read \"%s(%s)\": variable isn't array" my quads initArrayIfNotExists $ary $ary my quads copy $tmp $delta set res $idx set inval {temp opd0} my quads arrayGet $inval $ary $idx my quads initIfNotExists $inval $inval {literal 0} my generate-arith-domain-check $pc incr $inval $tmp my quads purify {temp opd1} $inval my quads purify {temp opd2} $tmp my quads add $inval {temp opd1} {temp opd2} my quads arraySet $ary $ary $idx $inval my update-in-callframe [list literal [lindex $ary 1]] $ary my quads copy $res $inval } incrArray1 { set delta [list temp [incr depth -1]] set idx [list temp [incr depth -1]] set ary [my index-to-var [lindex $insn 1]] my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \ "can't read \"%s(%s)\": variable isn't array" my quads initArrayIfNotExists $ary $ary set res $idx set inval {temp opd0} my quads arrayGet $inval $ary $idx my quads initIfNotExists $inval $inval {literal 0} my generate-arith-domain-check $pc incr $inval $delta my quads purify {temp opd1} $inval my quads purify {temp opd2} $delta my quads add $inval {temp opd1} {temp opd2} my quads arraySet $ary $ary $idx $inval my update-in-callframe [list literal [lindex $ary 1]] $ary my quads copy $res $inval } incrStkImm { set var [list temp [incr depth -1]] set delta [list literal [lindex $insn 1]] # TODO: This assumes we're dealing with qualified names! set val {temp opd2} |
︙ | ︙ | |||
806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 | } set r [list temp $depth] my generate-scalar-check $pc $var {TCL READ VARNAME} \ "can't read \"%s\": variable is array" my quads initIfNotExists $var $var {literal {}} my error-quads $pc dictSet $r $var $val {*}[lreverse $q] my quads copy $var $r } dictUnset { set idxNum [expr [lindex $insn 1]] set var [my index-to-var [lindex $insn 2]] set q {} for {set i 0} {$i < $idxNum} {incr i} { # NOTE: Reversed lappend q [list temp [incr depth -1]] } set r [list temp $depth] my generate-scalar-check $pc $var {TCL READ VARNAME} \ "can't read \"%s\": variable is array" my quads initIfNotExists $var $var {literal {}} my error-quads $pc dictUnset $r $var {*}[lreverse $q] my quads copy $var $r } dictAppend - dictLappend { set var [my index-to-var [lindex $insn 1]] set val [list temp [incr depth -1]] set key [list temp [incr depth -1]] set res [list temp $depth] my generate-scalar-check $pc $var {TCL READ VARNAME} \ "can't read \"%s\": variable is array" my quads initIfNotExists $var $var {literal {}} my error-quads $pc [lindex $insn 0] $res $var $key $val my quads copy $var $res } dictIncrImm { set delta [list literal [lindex $insn 1]] set var [my index-to-var [lindex $insn 2]] set key [list temp [incr depth -1]] set res [list temp $depth] my generate-scalar-check $pc $var {TCL READ VARNAME} \ "can't read \"%s\": variable is array" my quads initIfNotExists $var $var {literal {}} my error-quads $pc dictIncr $res $var $key $delta my quads copy $var $res } list { set acount [lindex $insn 1] set depth [expr {$depth - $acount}] set result [list temp $depth] set qd {} for {set i 0} {$i < $acount} {incr i} { | > > > > | 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 | } set r [list temp $depth] my generate-scalar-check $pc $var {TCL READ VARNAME} \ "can't read \"%s\": variable is array" my quads initIfNotExists $var $var {literal {}} my error-quads $pc dictSet $r $var $val {*}[lreverse $q] my quads copy $var $r my update-in-callframe [list literal [lindex $var 1]] $var } dictUnset { set idxNum [expr [lindex $insn 1]] set var [my index-to-var [lindex $insn 2]] set q {} for {set i 0} {$i < $idxNum} {incr i} { # NOTE: Reversed lappend q [list temp [incr depth -1]] } set r [list temp $depth] my generate-scalar-check $pc $var {TCL READ VARNAME} \ "can't read \"%s\": variable is array" my quads initIfNotExists $var $var {literal {}} my error-quads $pc dictUnset $r $var {*}[lreverse $q] my quads copy $var $r my update-in-callframe [list literal [lindex $var 1]] $var } dictAppend - dictLappend { set var [my index-to-var [lindex $insn 1]] set val [list temp [incr depth -1]] set key [list temp [incr depth -1]] set res [list temp $depth] my generate-scalar-check $pc $var {TCL READ VARNAME} \ "can't read \"%s\": variable is array" my quads initIfNotExists $var $var {literal {}} my error-quads $pc [lindex $insn 0] $res $var $key $val my quads copy $var $res my update-in-callframe [list literal [lindex $var 1]] $var } dictIncrImm { set delta [list literal [lindex $insn 1]] set var [my index-to-var [lindex $insn 2]] set key [list temp [incr depth -1]] set res [list temp $depth] my generate-scalar-check $pc $var {TCL READ VARNAME} \ "can't read \"%s\": variable is array" my quads initIfNotExists $var $var {literal {}} my error-quads $pc dictIncr $res $var $key $delta my quads copy $var $res my update-in-callframe [list literal [lindex $var 1]] $var } list { set acount [lindex $insn 1] set depth [expr {$depth - $acount}] set result [list temp $depth] set qd {} for {set i 0} {$i < $acount} {incr i} { |
︙ | ︙ | |||
999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 | set to_pc [expr {$pc + $offset}] my generate-jump $to_pc true $test } } existScalar { set result [list temp $depth] set var [my index-to-var [lindex $insn 1]] my quads exists $result $var } existArray { set tmp [list temp $depth] set idx [list temp [incr depth -1]] set ary [my index-to-var [lindex $insn 1]] set result $idx my quads initArrayIfNotExists $tmp $ary my quads arrayElementExists $result $tmp $idx } loadScalar1 - loadScalar4 { # Load a variable set result [list temp $depth] | > > > > | 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 | set to_pc [expr {$pc + $offset}] my generate-jump $to_pc true $test } } existScalar { set result [list temp $depth] set var [my index-to-var [lindex $insn 1]] my quads moveFromCallFrame \ $var {temp @callframe} [list literal [lindex $var 1]] my quads exists $result $var } existArray { set tmp [list temp $depth] set idx [list temp [incr depth -1]] set ary [my index-to-var [lindex $insn 1]] set result $idx my quads moveFromCallFrame \ $var {temp @callframe} [list literal [lindex $var 1]] my quads initArrayIfNotExists $tmp $ary my quads arrayElementExists $result $tmp $idx } loadScalar1 - loadScalar4 { # Load a variable set result [list temp $depth] |
︙ | ︙ | |||
1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 | storeScalar1 - storeScalar4 { # Store a variable incr depth -1 set var [my index-to-var [lindex $insn 1]] my generate-scalar-check $pc $var {TCL WRITE VARNAME} \ "can't set \"%s\": variable is array" my quads copy $var [list temp $depth] } storeArray1 - storeArray4 { # Store into an array set val [list temp [incr depth -1]] set idx [list temp [incr depth -1]] set ary [my index-to-var [lindex $insn 1]] set res $idx my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \ "can't set \"%s(%s)\": variable isn't array" my quads initArrayIfNotExists $ary $ary my quads arraySet $ary $ary $idx $val my quads copy $res $val } tryCvtToNumeric { # No effect on value } tryCvtToBoolean { # Push whether we're dealing with a boolean set val [list temp [expr {$depth - 1}]] set res [list temp $depth] set typecode [quadcode::dataType::typeUnion \ | > > | 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 | storeScalar1 - storeScalar4 { # Store a variable incr depth -1 set var [my index-to-var [lindex $insn 1]] my generate-scalar-check $pc $var {TCL WRITE VARNAME} \ "can't set \"%s\": variable is array" my quads copy $var [list temp $depth] my update-in-callframe [list literal [lindex $var 1]] $var } storeArray1 - storeArray4 { # Store into an array set val [list temp [incr depth -1]] set idx [list temp [incr depth -1]] set ary [my index-to-var [lindex $insn 1]] set res $idx my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \ "can't set \"%s(%s)\": variable isn't array" my quads initArrayIfNotExists $ary $ary my quads arraySet $ary $ary $idx $val my quads copy $res $val my update-in-callframe [list literal [lindex $ary 1]] $ary } tryCvtToNumeric { # No effect on value } tryCvtToBoolean { # Push whether we're dealing with a boolean set val [list temp [expr {$depth - 1}]] set res [list temp $depth] set typecode [quadcode::dataType::typeUnion \ |
︙ | ︙ | |||
1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 | set var [my index-to-var [lindex $insn 1]] my generate-scalar-check $pc $var {TCL WRITE VARNAME} \ "can't set \"%s\": variable is array" my quads initIfNotExists $var $var {literal {}} set result [list temp $depth] my quads strcat $var $var $val my quads copy $result $var } appendArray1 - appendArray4 { set val [list temp [incr depth -1]] set idx [list temp [incr depth -1]] set ary [my index-to-var [lindex $insn 1]] set res [list temp $depth] set inval {temp opd0} my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \ "can't set \"%s(%s)\": variable isn't array" my quads initArrayIfNotExists $ary $ary my quads arrayGet $inval $ary $idx my quads initIfNotExists $inval $inval {literal {}} my quads strcat $inval $inval $val my quads arraySet $ary $ary $idx $inval my quads copy $res $inval } strcat - concatStk { lassign $insn op count set strcatvals {} for {set i 0} {$i < $count} {incr i} { lappend strcatvals [list temp [incr depth -1]] } | > > | 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 | set var [my index-to-var [lindex $insn 1]] my generate-scalar-check $pc $var {TCL WRITE VARNAME} \ "can't set \"%s\": variable is array" my quads initIfNotExists $var $var {literal {}} set result [list temp $depth] my quads strcat $var $var $val my quads copy $result $var my update-in-callframe [list literal [lindex $var 1]] $var } appendArray1 - appendArray4 { set val [list temp [incr depth -1]] set idx [list temp [incr depth -1]] set ary [my index-to-var [lindex $insn 1]] set res [list temp $depth] set inval {temp opd0} my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \ "can't set \"%s(%s)\": variable isn't array" my quads initArrayIfNotExists $ary $ary my quads arrayGet $inval $ary $idx my quads initIfNotExists $inval $inval {literal {}} my quads strcat $inval $inval $val my quads arraySet $ary $ary $idx $inval my quads copy $res $inval my update-in-callframe [list literal [lindex $ary 1]] $ary } strcat - concatStk { lassign $insn op count set strcatvals {} for {set i 0} {$i < $count} {incr i} { lappend strcatvals [list temp [incr depth -1]] } |
︙ | ︙ | |||
1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 | set res [list temp $depth] my generate-scalar-check $pc $var {TCL WRITE VARNAME} \ "can't set \"%s\": variable is array" my quads initIfNotExists $var $var {literal {}} # TODO: Typecheck: need list in $var my error-quads $pc listAppend $res $var $val my quads copy $var $res } lappendList { set listval [list temp [incr depth -1]] set var [my index-to-var [lindex $insn 1]] set res [list temp $depth] my generate-scalar-check $pc $var {TCL WRITE VARNAME} \ "can't set \"%s\": variable is array" my quads initIfNotExists $var $var {literal {}} # TODO: Typecheck: need lists in $var and $listval my error-quads $pc listConcat $res $var $listval my quads copy $var $res } lappendArray1 - lappendArray4 { set val [list temp [incr depth -1]] set idx [list temp [incr depth -1]] set ary [my index-to-var [lindex $insn 1]] set res [list temp $depth] set inval {temp opd0} my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \ "can't set \"%s(%s)\": variable isn't array" my quads initArrayIfNotExists $var $var my quads arrayGet $inval $ary $idx my quads initIfNotExists $inval $inval {literal {}} my error-quads $pc listAppend $inval $inval $val my quads arraySet $ary $ary $idx $inval my quads copy $res $inval } lappendListArray { set listval [list temp [incr depth -1]] set idx [list temp [incr depth -1]] set ary [my index-to-var [lindex $insn 1]] set res [list temp $depth] set inval {temp opd0} my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \ "can't set \"%s(%s)\": variable isn't array" my quads initArrayIfNotExists $ary $ary my quads arrayGet $inval $ary $idx my quads initIfNotExists $inval $inval {literal {}} # TODO: Typecheck: need lists in $inval and $listval my error-quads $pc listConcat $inval $inval $listval my quads arraySet $ary $ary $idx $inval my quads copy $res $inval } listConcat { set list2 [list temp [incr depth -1]] set list1 [list temp [incr depth -1]] set res [list temp $depth] # TODO: Typecheck: need lists in $list1 and $list2 my error-quads $pc listConcat $res $list1 $list2 } arrayExistsImm { set ary [my index-to-var [lindex $insn 1]] set res [list temp $depth] my quads arrayExists $res $ary } arrayMakeImm { set ary [my index-to-var [lindex $insn 1]] my generate-array-check $pc $ary {} {TCL WRITE ARRAY} \ "can't array set \"%s\": variable isn't array" my quads initArrayIfNotExists $ary $ary } arrayExistsStk { set ary [list temp [incr depth -1]] set res [list temp $depth] my error-quads $pc directIsArray $res $ary } arrayMakeStk { | > > > > > > > | 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 | set res [list temp $depth] my generate-scalar-check $pc $var {TCL WRITE VARNAME} \ "can't set \"%s\": variable is array" my quads initIfNotExists $var $var {literal {}} # TODO: Typecheck: need list in $var my error-quads $pc listAppend $res $var $val my quads copy $var $res my update-in-callframe [list literal [lindex $var 1]] $var } lappendList { set listval [list temp [incr depth -1]] set var [my index-to-var [lindex $insn 1]] set res [list temp $depth] my generate-scalar-check $pc $var {TCL WRITE VARNAME} \ "can't set \"%s\": variable is array" my quads initIfNotExists $var $var {literal {}} # TODO: Typecheck: need lists in $var and $listval my error-quads $pc listConcat $res $var $listval my quads copy $var $res my update-in-callframe [list literal [lindex $var 1]] $var } lappendArray1 - lappendArray4 { set val [list temp [incr depth -1]] set idx [list temp [incr depth -1]] set ary [my index-to-var [lindex $insn 1]] set res [list temp $depth] set inval {temp opd0} my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \ "can't set \"%s(%s)\": variable isn't array" my quads initArrayIfNotExists $var $var my quads arrayGet $inval $ary $idx my quads initIfNotExists $inval $inval {literal {}} my error-quads $pc listAppend $inval $inval $val my quads arraySet $ary $ary $idx $inval my quads copy $res $inval my update-in-callframe [list literal [lindex $ary 1]] $ary } lappendListArray { set listval [list temp [incr depth -1]] set idx [list temp [incr depth -1]] set ary [my index-to-var [lindex $insn 1]] set res [list temp $depth] set inval {temp opd0} my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \ "can't set \"%s(%s)\": variable isn't array" my quads initArrayIfNotExists $ary $ary my quads arrayGet $inval $ary $idx my quads initIfNotExists $inval $inval {literal {}} # TODO: Typecheck: need lists in $inval and $listval my error-quads $pc listConcat $inval $inval $listval my quads arraySet $ary $ary $idx $inval my quads copy $res $inval my update-in-callframe [list literal [lindex $ary 1]] $ary } listConcat { set list2 [list temp [incr depth -1]] set list1 [list temp [incr depth -1]] set res [list temp $depth] # TODO: Typecheck: need lists in $list1 and $list2 my error-quads $pc listConcat $res $list1 $list2 } arrayExistsImm { set ary [my index-to-var [lindex $insn 1]] my quads moveFromCallFrame \ $ary {temp @callframe} [list literal [lindex $ary 1]] set res [list temp $depth] my quads arrayExists $res $ary } arrayMakeImm { set ary [my index-to-var [lindex $insn 1]] my generate-array-check $pc $ary {} {TCL WRITE ARRAY} \ "can't array set \"%s\": variable isn't array" my quads initArrayIfNotExists $ary $ary my update-in-callframe [list literal [lindex $var 1]] $var } arrayExistsStk { set ary [list temp [incr depth -1]] set res [list temp $depth] my error-quads $pc directIsArray $res $ary } arrayMakeStk { |
︙ | ︙ | |||
1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 | error "Not implemented! generate-existence-check on non-constant name" } set varname [lindex $varname 1] set where [llength $quads] set newtemp [list temp @exists] my quads exists $newtemp $var ;# 0 my quads jumpTrue [list pc [expr {$where + 5}]] $newtemp ;# 1 set msg [list literal "can't read \"$varname\": no such variable"] set optionsDict \ [list literal [list -errorcode [list TCL LOOKUP VARNAME $varname]]] my quads initException {temp @exception} $msg $optionsDict \ {literal 1} {literal 0} ;# 2 | > > | 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 | error "Not implemented! generate-existence-check on non-constant name" } set varname [lindex $varname 1] set where [llength $quads] set newtemp [list temp @exists] my quads moveFromCallFrame \ $var {temp @callframe} [list literal [lindex $var 1]] my quads exists $newtemp $var ;# 0 my quads jumpTrue [list pc [expr {$where + 5}]] $newtemp ;# 1 set msg [list literal "can't read \"$varname\": no such variable"] set optionsDict \ [list literal [list -errorcode [list TCL LOOKUP VARNAME $varname]]] my quads initException {temp @exception} $msg $optionsDict \ {literal 1} {literal 0} ;# 2 |
︙ | ︙ | |||
1578 1579 1580 1581 1582 1583 1584 1585 1586 | ; # Name of the variable being checked set ok [list pc [expr {[llength $quads] + 11}]] ; # Quadcode address to jump to on success set fail [my exception-target $pc catch] ; # Bytecode address to jump to on failure # 0 my quads exists {temp @exists} $var | > > > > > > > > | | | | | | | | | | | > > > > > > > > | | | | | | 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 | ; # Name of the variable being checked set ok [list pc [expr {[llength $quads] + 11}]] ; # Quadcode address to jump to on success set fail [my exception-target $pc catch] ; # Bytecode address to jump to on failure # If this is a real variable and not a temporary (e.g. a dict iterator), # make sure that it's pulled from the callframe. Load elimination will # delete this instruction if possible. if {[lindex $var 0] eq "var"} { # 0 my quads moveFromCallFrame $var {temp @callframe} \ [list literal [lindex $var 1]] } # 1 my quads exists {temp @exists} $var # 2 my quads jumpFalse $ok {temp @exists} # 3 my quads arrayExists {temp @exists} $var # 4 my quads jumpTrue $ok {temp @exists} # 5 if {$idx ne {}} { my quads invoke {temp @callframe} {temp @callframe} \ {literal ::format} [list literal $msg] \ [list literal $varname] $idx } else { my quads invoke {temp @callframe} {temp @callframe} \ {literal ::format} [list literal $msg] \ [list literal $varname] } # 6 my quads retrieveResult {temp @msg} {temp @callframe} # 7 my quads extractCallFrame {temp @callframe} {temp @callframe} # 8 my quads extractMaybe {temp @msg} {temp @msg} # 9 my quads initException {temp @exception} {temp @msg} \ [list literal [list -errorcode $error]] \ {literal 1} {literal 0} # 10 my quads extractFail {temp @exception} {temp @exception} # 11 my generate-jump $fail # 12 # The narrowing pass will insert any necessary 'extract...' instructions } oo::define quadcode::transformer method generate-scalar-check {pc var error msg} { set varname [lindex $var 1] ; # Name of the variable being checked set msg [list literal [format $msg $varname]] ; # Preformatted message to return on error set ok [list pc [expr {[llength $quads] + 5}]] ; # Quadcode address to jump to on success set fail [my exception-target $pc catch] ; # Bytecode address to jump to on failure # If this is a real variable and not a temporary (e.g. a dict iterator), # make sure that it's pulled from the callframe. Load elimination will # delete this instruction if possible. if {[lindex $var 0] eq "var"} { # 0 my quads moveFromCallFrame $var {temp @callframe} \ [list literal [lindex $var 1]] } # 1 my quads arrayExists {temp @exists} $var # 2 my quads jumpFalse $ok {temp @exists} # 3 my quads initException {temp @exception} $msg \ [list literal [list -errorcode $error]] \ {literal 1} {literal 0} # 4 my quads extractFail {temp @exception} {temp @exception} # 5 my generate-jump $fail # 6 # The narrowing pass will insert any necessary 'extract...' instructions } # generate-arith-domain-check -- # # Generates a check to make sure that a value is NUMERIC or INT |
︙ | ︙ | |||
1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 | my generate-jump $target # 5 - ok: my quads [list purifyParam $i] $val $val $functionName # 6 # (next instruction) } } # quads -- # # Generate the given quadcode. # # Parameters: | > > > > > > > > > > > > > > > > > > > > > | 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 | my generate-jump $target # 5 - ok: my quads [list purifyParam $i] $val $val $functionName # 6 # (next instruction) } return } # update-in-callframe -- # # Generates code to update a variable's value in the callframe. # # Parameters: # args - Alternating list of variables names and variable values # # Results: # None. # # Side effects: # Emits `moveToCallFrame`. oo::define quadcode::transformer method update-in-callframe {args} { if {[llength $args] > 0} { my quads moveToCallFrame {temp @callframe} {temp @callframe} {*}$args } return } # quads -- # # Generate the given quadcode. # # Parameters: |
︙ | ︙ |