Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | More argument preparation code in 'varargs' |
---|---|
Timelines: | family | ancestors | descendants | both | notworking | kbk-refactor-callframe |
Files: | files | file ages | folders |
SHA3-256: |
76b943ad4a8bf322aaa2c4ca5f1bbf70 |
User & Date: | kbk 2019-01-16 02:30:51.106 |
Context
2019-01-18
| ||
04:22 | Add the final processing in 'varargs' - next, emit the error path. check-in: 305328fa6b user: kbk tags: notworking, kbk-refactor-callframe | |
2019-01-16
| ||
02:30 | More argument preparation code in 'varargs' check-in: 76b943ad4a user: kbk tags: notworking, kbk-refactor-callframe | |
2019-01-14
| ||
03:46 | Further development of varargs. Note that the invocation sequence is much, much simpler than it used to be, so 'invoke.tcl' is no more. check-in: 90e908dae3 user: kbk tags: notworking, kbk-refactor-callframe | |
Changes
Changes to quadcode/builder.tcl.
︙ | ︙ | |||
51 52 53 54 55 56 57 | set xfmr $xfmr_ set b $b_ set bb $bb_ set bbindex {} set varindex {} } | | > > > > > > > > > > > > > > > > > > > | 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 | set xfmr $xfmr_ set b $b_ set bb $bb_ set bbindex {} set varindex {} } # quadcode::builder method maketemp -- # # Makes a temporary variable. # # Parameters: # name - Base name for the temporary. # # Results: # Returns the name of the constructed temporary. # # Side effects: # Stores the name as the most recent instance of the temporary. oo::define quadcode::builder method maketemp {name} { set ssaname [$xfmr newVarInstance [list temp @$name]] dict set varindex $name $ssaname return $ssaname } # quadcode::builder method gettemp -- # # Gets the last instance of a temporary variable # # Parameters: # name - Base name of the temporary # # Results: # Returns the SSA name of the lastest instance of the temporary, # or "" if there is no instance. oo::define quadcode::builder method gettemp {name} { if {[dict exists $varindex $name]} { return [dict get $varindex $name] } else { return {} } } # quadcode::builder method emit -- # # Emits an instruction into the basic block under construction. # # Parameters: # q - Quadcode instruction to emit |
︙ | ︙ |
Changes to quadcode/varargs.tcl.
︙ | ︙ | |||
119 120 121 122 123 124 125 | set bb [my va_UnlinkTail $b $pc] set B [quadcode::builder new [self] $b $bb] # Prepare parameters for the 'invoke' (or 'invokeExpanded') call, and # add the call to the instruction sequence under construction. my va_PrepareArgs $B $b $pc $q $arginfo | | | | 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | set bb [my va_UnlinkTail $b $pc] set B [quadcode::builder new [self] $b $bb] # Prepare parameters for the 'invoke' (or 'invokeExpanded') call, and # add the call to the instruction sequence under construction. my va_PrepareArgs $B $b $pc $q $arginfo error "NOT FINISHED - rewriting invoke instruction" $B destroy $call destroy return } # quadcode::transformer method va_GetArgInfo -- # |
︙ | ︙ | |||
203 204 205 206 207 208 209 | my debug-varargs { puts "varargs: $b:$pc: matched $pos out of $nPlainParams\ leading non-expanded arg(s)." } # Generate code to make the rest of the args into a list | | | | < | 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | my debug-varargs { puts "varargs: $b:$pc: matched $pos out of $nPlainParams\ leading non-expanded arg(s)." } # Generate code to make the rest of the args into a list set mightThrow [my va_MakeArgList $B $argl $pos $cfin] # We are going to need the length of the list, so # extract that now. (If it turns out somehow that we # don't use it, 'deadvars' will get rid of this, anyway.) set lenLoc1 [my newVarInstance {temp @arglen}] set lenLoc [$B maketemp arglen] $B emit [list listLength $lenLoc1 [$B gettemp arglist]] my debug-varargs { $B log-last } $B emit [list extractMaybe $lenLoc $lenLoc1] my debug-varargs { $B log-last } |
︙ | ︙ | |||
241 242 243 244 245 246 247 | incr pos } my debug-varargs { puts "varargs: first optional arg is at position $pos" } set firstOptional $pos | < < < < < < < < < < < | < | < < | > > | 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 | incr pos } my debug-varargs { puts "varargs: first optional arg is at position $pos" } set firstOptional $pos set nMandatory 0 if {$firstOptional > $firstMandatory} { # Make code to check length of arg list set nMandatory [expr {$firstOptional - $firstMandatory}] my va_CheckEnough $B $nMandatory # Make code to transfer mandatory args my va_UnpackMandatory $B newq $nMandatory } # Now we have the parameters that have default values. set j $nMandatory if {$nPlainParams > $firstOptional} { error "NOT DONE - varargs doing optional arg(s)" # Emit a code burst for each optional parameter to # check the list length and extract the parameter set optInfo {} set finishB [llength $bbcontent] lappend bbcontent {} lappend bbpred {} |
︙ | ︙ | |||
297 298 299 300 301 302 303 | my va_FinishOptional b bb newq $finishB $optInfo } # If the procedure has 'args', then fill it in with the remainder of the # arg list. if {$haveargs} { | | > > > > > > > > > | 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | my va_FinishOptional b bb newq $finishB $optInfo } # If the procedure has 'args', then fill it in with the remainder of the # arg list. if {$haveargs} { my va_DoArgs $B newq $j } else { error "NOT DONE - varargs needs to check for excess args" my va_CheckTooMany b bb $lenLoc $compTemp $j $notokb } error "NOT DONE - varargs needs to emit call:\n $newq" } if 0 { # Create the normal invocation sequence. # 1. Create moveToCallFrame set cfin [$call cfin] set invars [$call invars] if {[$call pc0] < $pc} { |
︙ | ︙ | |||
349 350 351 352 353 354 355 | dict set errorphis $outval [list bb $err1b] $notokval } # 6. Make the terminal jumps my va_EmitAndTrack $b bb [list jumpMaybe [list bb $err0b] $okresult] my va_EmitAndTrack $b bb [list jump [list bb $norm0b]] | | | 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 | dict set errorphis $outval [list bb $err1b] $notokval } # 6. Make the terminal jumps my va_EmitAndTrack $b bb [list jumpMaybe [list bb $err0b] $okresult] my va_EmitAndTrack $b bb [list jump [list bb $norm0b]] q # Emit the final basic block rewrite lset bbcontent $b $bb # toRepair will have the variables that have to be fixed up by # repairSSAVariable after this stuff runs set toRepair {} |
︙ | ︙ | |||
514 515 516 517 518 519 520 | # B - quadcode::builder that is rewriting the invocation sequence. # argl - Argument list being analyzed # pos - Position in the argument list # cfin - Callframe input to the 'invoke' instruction. # # Results: # | < | < | | 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 | # B - quadcode::builder that is rewriting the invocation sequence. # argl - Argument list being analyzed # pos - Position in the argument list # cfin - Callframe input to the 'invoke' instruction. # # Results: # # Returns 1 if it is possible that the argument list is a non-list, # and 0 otherwise. oo::define quadcode::transformer method va_MakeArgList {B argl pos cfin} { my debug-varargs { puts "varargs: make arg list for [list $argl] from position $pos" } |
︙ | ︙ | |||
619 620 621 622 623 624 625 | $B emit [list $op $nloc $listLoc $arg] my debug-varargs { $B log-last } # If the concatenation might have failed, emit the error check if {$mightThrow} { | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < | | | > > > | 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 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 | $B emit [list $op $nloc $listLoc $arg] my debug-varargs { $B log-last } # If the concatenation might have failed, emit the error check if {$mightThrow} { my va_MakeErrorCheck $B $nloc set mightThrow 0 } # On normal exit from list construction, extract the result from the # 'maybe' returned by listAppend or listConcat set listLoc [$B maketemp arglist] $B emit [list extractMaybe $listLoc $nloc] my debug-varargs { $B log-last } } return $mightThrow } # quadcode::transformer method va_CheckEnough -- # # Emits code to check for too few args passed to invokeExpanded # # Parameters: # B - Builder that is managing code for this invocation # result - Return value from the call # cfin - Input call frame to the call # cmd - Name of the command being invoked # nMandatory - Number of non-defaulted args that must be provided # # Results: # None. # # Side effects: # Emits the check, the 'wrong # args' error if needed, and generates # the error block if needed oo::define quadcode::transformer method va_CheckEnough {B result cfin cmd nMandatory} { error "va_CheckEnough: Not yet reached in testing" set compLoc [my newVarInstance {temp @toofew}] set lenLoc [$B gettemp arglen] # compare args provided to args needed $B emit [list gt $compLoc [list literal $nMandatory] $lenLoc] my debug-varargs { $B log-last } # jump to errb if wrong set errb [$B makeblock] $B emit [list jumpTrue [list bb $errb] $compLoc] my debug-varargs { $B log-last } # jump to okb if right set okb [$B makeblock] $B emit [list jump [list bb $okb]] my debug-varargs { $B log-last } # make code to emit 'wrong # args' error set wrongb [my va_EmitWrongArgs $result $cfin $cmd] # jump from errb to code that throws error $B buildin $errb $B emit [list jump [list bb $wrongb]] my debug-varargs { $B log-last } # return to the 'no failure' branch $B buildin $okb } # quadcode::transformer method va_MakeErrorCheck -- # # Emits code to jump to an error block if a given value is FAIL. # # Parameters: # B - Builder that is emitting code # val - Value that might be FAIL # # Results: # None. # # Side effects: # Emits the necessary jumpMaybe, and adds FAIL value # to the phi operation at the head of the error block. oo::define quadcode::transformer method va_makeErrorCheck {B val} { error "va_MakeErrorCheck: Not yet reached in testing" # Emit any required error checking when building the variable # argument list. my va_MakeErrorBlock $B set errorb [$B getblock error] set intb [$B makeblock] set nextb [$B makeblock] # Close out the current block with jumpMaybe to an intermediate # block and jump to the normal return $B emit [list jumpMaybe [list bb $intb] $val] my debug-varargs { |
︙ | ︙ | |||
685 686 687 688 689 690 691 | $B emit [list jump [list bb $errorb]] my debug-varargs { $B log-last } # Add phis for the error result ant the callframe to the error block set errorInPhi [$B get-or-make-temp error] | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 | $B emit [list jump [list bb $errorb]] my debug-varargs { $B log-last } # Add phis for the error result ant the callframe to the error block set errorInPhi [$B get-or-make-temp error] $B phi $errorb $errorInPhi $val # Now continue building in the normal exit $B buildin $nextb } # quadcode::transformer method va_UnpackMandatory -- # # Unpacks the mandatory args to a proc from the list created # by argument expansion # # Parameters; |
︙ | ︙ | |||
764 765 766 767 768 769 770 771 772 773 774 775 776 777 | # Side effects: # Emits code to unpack the mandatory parameters oo::define quadcode::transformer method va_UnpackMandatory {tempIdxVar bbVar newqVar b listLoc nMandatory} { upvar 1 $tempIdxVar tempIdx $bbVar bb $newqVar newq for {set i 0} {$i < $nMandatory} {incr i} { # Emit the 'listIndex' instruction for one arg. It can't fail # because we know we have a list | > | 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 | # Side effects: # Emits code to unpack the mandatory parameters oo::define quadcode::transformer method va_UnpackMandatory {tempIdxVar bbVar newqVar b listLoc nMandatory} { error "va_UnpackMandatory: Not yet refactored or reached in testing" upvar 1 $tempIdxVar tempIdx $bbVar bb $newqVar newq for {set i 0} {$i < $nMandatory} {incr i} { # Emit the 'listIndex' instruction for one arg. It can't fail # because we know we have a list |
︙ | ︙ | |||
814 815 816 817 818 819 820 821 822 823 824 825 826 827 | # Emits code to unpack one value, or jump to the finish block if # there is nothing to unpack. oo::define quadcode::transformer method va_UnpackOptional {tempIdxVar bVar bbVar finishB compTemp listLoc lenLoc j} { upvar 1 $tempIdxVar tempIndex $bVar b $bbVar bb set pos [list literal $j] set compLoc [my newVarInstance $compTemp] set argTemp [list temp [incr tempIndex]] set argLoc1 [my newVarInstance $argTemp] set argLoc2 [my newVarInstance $argTemp] | > | 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 | # Emits code to unpack one value, or jump to the finish block if # there is nothing to unpack. oo::define quadcode::transformer method va_UnpackOptional {tempIdxVar bVar bbVar finishB compTemp listLoc lenLoc j} { error "va_UnpackOptional: Not yet refactored or reached in testing" upvar 1 $tempIdxVar tempIndex $bVar b $bbVar bb set pos [list literal $j] set compLoc [my newVarInstance $compTemp] set argTemp [list temp [incr tempIndex]] set argLoc1 [my newVarInstance $argTemp] set argLoc2 [my newVarInstance $argTemp] |
︙ | ︙ | |||
888 889 890 891 892 893 894 895 896 897 898 899 900 901 | # outputs of the phi instructions to the 'invoke' instruction # under construction. oo::define quadcode::transformer method va_FinishOptional {bVar bbVar newqVar finishB optInfo} { upvar 1 $bVar b $bbVar bb $newqVar newq # Finish the current block and start building into 'finishB' my va_EmitAndTrack $b bb [list jump [list bb $finishB]] lset bbcontent $b $bb set bb {} | > | 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 | # outputs of the phi instructions to the 'invoke' instruction # under construction. oo::define quadcode::transformer method va_FinishOptional {bVar bbVar newqVar finishB optInfo} { error "va_FinishOptional: not refactored or tested yet" upvar 1 $bVar b $bbVar bb $newqVar newq # Finish the current block and start building into 'finishB' my va_EmitAndTrack $b bb [list jump [list bb $finishB]] lset bbcontent $b $bb set bb {} |
︙ | ︙ | |||
930 931 932 933 934 935 936 | # quadcode::transformer method va_DoArgs -- # # Emits code to extract the parameter sequence needed to fill '$args' # from the parameter list. # # Parameters: | | < | | < < | | > | > > > | < > < | | | > > > > | | > | 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 | # quadcode::transformer method va_DoArgs -- # # Emits code to extract the parameter sequence needed to fill '$args' # from the parameter list. # # Parameters: # B - Builder that is emitting the code sequence # newqVar - Variable in caller's scope containing the quadcode # 'invoke' instruction under construction # i - Position in the argument list at which 'args' starts. # # Results: # None. # # Side effects: # Emits any code necessary to fill in 'args', and adds the resulting # variable onto the end of the new instruction. oo::define quadcode::transformer method va_DoArgs {B newqVar i} { upvar 1 $newqVar newq set listLoc [$B gettemp arglist] my debug-varargs { puts "varargs: args will come from positions $i-end in $listLoc" } # If args is the whole list, just concatenate it onto the invoke if {$i == 0} { lappend newq $listLoc } else { set argsLoc1 [$B maketemp \$args] $B build [list listRange $argsLoc1 $listLoc \ [list literal $i] {literal end}] my debug-varargs { $B log-last } set argsLoc2 [B maketemp \$args] $B build [list extractMaybe $argsLoc2 $argsLoc1] lappend newq $argsLoc2 } } # quadcode::transformer method va_CheckTooMany -- # # Emits a codeburst to check whether an 'invokeExpanded' has # too many args # |
︙ | ︙ | |||
1019 1020 1021 1022 1023 1024 1025 | # quadcode::transformer method va_EmitWrongArgs -- # # Generates code to throw the 'wrong # args' error when needed # # Parameters: # result - Quadcode value that will hold the command result | < < | < < < < | 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 | # quadcode::transformer method va_EmitWrongArgs -- # # Generates code to throw the 'wrong # args' error when needed # # Parameters: # result - Quadcode value that will hold the command result # cfin - Quadcode value that holds the pre-invoke callframe, # or Nothing if no callframe need be produced # cmd - Quadcode literal with the name of the command being invoked # # Results: # None. # # Side effects: # Returns a codeburst that throws the exception oo::define quadcode::transformer method va_EmitWrongArgs {result cfin cmd} { set burst {} set argl [info args [lindex $cmd 1]] set left [llength $argl] set sbval [list [lindex $cmd 1]] foreach a $argl { incr left -1 if {$a eq "args" && $left == 0} { |
︙ | ︙ |