Check-in [4f7b3a4d01]
Bounty program for improvements to Tcl and certain Tcl packages.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Bug fixes to make all the 'expandtest' cases work
Timelines: family | ancestors | descendants | both | notworking | kbk-refactor-callframe
Files: files | file ages | folders
SHA3-256: 4f7b3a4d01211450fd3d4b4e993cd17c4b358f60ac483f1eac8bdc05fbd6a3d8
User & Date: kbk 2019-01-22 02:35:48
Context
2019-01-22
02:36
Run dead code elimination before copy propagation because copyprop explodes otherwise. check-in: 9e16d3b8d6 user: kbk tags: notworking, kbk-refactor-callframe
02:35
Bug fixes to make all the 'expandtest' cases work check-in: 4f7b3a4d01 user: kbk tags: notworking, kbk-refactor-callframe
2019-01-21
22:33
Enough partial implementation for expandtest::test1-test3 check-in: 89030dcc42 user: kbk tags: notworking, kbk-refactor-callframe
Changes

Changes to quadcode/varargs.tcl.

292
293
294
295
296
297
298




299
300
301
302
303
304
305
...
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
...
420
421
422
423
424
425
426






427
428
429
430
431
432


433
434
435
436
437
438
439
440
441
442
443
444
445


446
447
448
449
450
451
452
...
464
465
466
467
468
469
470


471
472
473
474
475
476
477
478
479



480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
...
568
569
570
571
572
573
574




575
576
577
578
579
580
581
...
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
728
729
730
731
732
733
734
735
736
737
738






739
740
741
742
743
744
745
...
748
749
750
751
752
753
754
755



756
757


758
759
760
761
762
763
764
...
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
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
887
888
889
890
891


892
893
894



895
896


897
898
899



900
901
902
903
904
905
906
...
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
....
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
....
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
    # Any leading plain arguments that do not have {*} can simply be retained
    # in the parameter list of [invoke].
    # $pos will be the position in the parameter list of the first
    # parameter that needs special handling. 
    set argl [lrange $q 4 end]
    set pos 0




    while {$pos < $nPlainParams} {
        if {[my va_NonExpandedArgument newq $arginfo $pos $argl]} break
        incr pos
    }

    my debug-varargs {
        puts "varargs: $b:$pc: matched $pos out of $nPlainParams\
................................................................................
        
            info default $callee [lindex $arginfo $i] defaultVal

            my debug-varargs {
                puts "Emit length check and extraction for optional param \
                      $i: [lindex $arginfo $i] (default=$defaultVal)"
            }
            lassign [my va_UnpackOptional $B $newq $j] \
                newq fromBlock argLoc
            lappend optInfo [list $fromBlock $defaultVal $argLoc]
            incr i
            incr j
        }

        error "NOT FINISHED - Close out the optional params."

        # Close out the last basic block, switch to the 'finish' block
        # and emit 'phi' instructions to get the correct parameter set
        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
    }

    return $newq
}
 
# quadcode::transformer method va_NonExpandedArgument --
#
................................................................................
#	end of the possible static transfers.

oo::define quadcode::transformer method va_NonExpandedArgument {newqVar arginfo
                                                                pos argl} {

    upvar 1 $newqVar newq
    






    set param [lindex $arginfo $pos]
    set arg [lindex $argl $pos]
    my debug-varargs {
        puts "varargs: transfer actual arg [list $arg] into formal arg\
              \"$param\""
    }


    switch -exact -- [lindex $arg 0] {
        "literal" {
        }
        "temp" - "var" {
            lassign [my findDef $arg] defb defpc defstmt
            if {[lindex $defstmt 0] eq "expand"} {
                return 1
            }
        }
        default {
            return 1
        }
    }


    lappend newq $arg
    return 0
}
 
# quadcode::transformer method va_MakeArgList --
#
#	Takes the non-fixed-position arguments of 'invokeExpanded'
................................................................................
#	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"
    }



    # Handle the first arg. 'listloc' will be the variable holding the
    # expanded arglist. 'mightThrow' will be 1 if 'listloc'
    # might be a non-list and 0 otherwise.
    if {$pos >= [llength $argl]} {
        my debug-varargs {
            puts "varargs: there are no args to list"
        }
        set listLoc "literal {}"



        set mightThrow 0
    } else {
        set arg [lindex $argl $pos]
        my debug-varargs {
            puts "varargs: transfer first arg [list $arg]"
        }
        switch -exact -- [lindex $arg 0] {
            "literal" {
                set listloc [$B maketemp arglist]
                $B emit [list list $listloc $arg]
                my debug-varargs {
                    $B log-last
                }
                set mightThrow 0
            }
            "temp" - "var" {
                lassign [my findDef $arg] defb defpc defstmt
                if {[lindex $defstmt 0] eq "expand"} {
                    my debug-varargs {
                        puts "  (which is expanded!)"
                    }
                    set listLoc [$B maketemp arglist]
                    $B emit [list copy $listLoc [lindex $defstmt 2]]
                    my debug-varargs {
                        $B log-last
                    }
                    set mightThrow 1
                } else {
                    set intLoc [$B maketemp arglist]
                    set listLoc [$B maketemp arglist]
                    my debug-varargs {
                        puts "  (which is not expanded)"
                    }
                    $B emit [list list $listLoc $arg]
                    my debug-varargs {
                        $B log-last
                    }
................................................................................
        set listLoc [$B maketemp arglist]
        $B emit [list extractMaybe $listLoc $nloc]
        my debug-varargs {
            $B log-last
        }
    }





    return $mightThrow

}
 
# quadcode::transformer method va_UnpackMandatory --
#
#	Unpacks the mandatory args to a proc from the list created
................................................................................
 
# quadcode::transformer method va_UnpackOptional --
#
#	Emits code to unpack one optional parameter in an invokeExpanded
#
# Parameters:
#	B - Builder that is emitting the invocation sequence
#	newq - 'invoke' instruction under construction
#	j - Position of the parameter being unpacked
#
# Results:

#	Returns a two-element list giving the block number that jumps
#	to the finish if the parameter is not supplied and the
#	location of a temporary holding the unpacked value if it is.


#
# Side effects:
#	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]


    # Emit the list length comparison
    my va_EmitAndTrack $b bb [list ge $compLoc $pos $lenLoc]




    # Emit the jump to the finish block We need to make an intermediate block
    # because otherwise the flowgraph edge would be critical
    set intb [llength $bbcontent]
    lappend bbcontent {}
    lappend bbpred {}

    my va_EmitAndTrack $b bb [list jumpTrue [list bb $intb] $compLoc]



    # Create the next block and jump to it
    set newb [llength $bbcontent]
    lappend bbcontent {}
    lappend bbpred {}
    my va_EmitAndTrack $b bb [list jump [list bb $newb]]
    lset bbcontent $b $bb



    # Make the intermediate block
    set b $intb
    set bb {}
    my va_EmitAndTrack $b bb [list jump [list bb $finishB]]
    lset bbcontent $b $bb

    # Advance to the new block


    set b $newb
    set bb {}



    # Emit the 'listIndex' to unpack the arg
    my va_EmitAndTrack $b bb [list listIndex $argLoc1 $listLoc $pos]




    # Emit the 'extractMaybe' on the 'listIndex' result
    my va_EmitAndTrack $b bb [list extractMaybe $argLoc2 $argLoc1]




    # Return the place where we stored the arg
    return [list $intb $argLoc2]

}
 
# quadcode::transformer method va_FinishOptional --
#
#	Finish transmitting the args that have default values when
#	compiling {*}
#
# Parameters:
#	bVar - Variable in caller holding the current basic block number
#	bbVar - Variable in caller's scope holding basic block content
#	newqVar - Variable in caller's scope holding the 'invoke'
#		  quadcode under construction
#	finishB - Basic block number reserved for the 'finish' block
#	optInfo - List of triples: fromBlock defaultValue tempLoc
#	          giving the phi inputs for the block under construction
#
# Results:
#	None.
#
# Side effects:
#	Closes out the current basic block, opens the finish block,
#	and emits phi instructions into the finish block. Adds the
#	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 {}
    set fromb $b
    set b $finishB

    # Emit the phi instructions

    set n 0
    foreach tuple $optInfo {
        lassign $tuple - defaultVal tempLoc






        set defaultLit [list literal $defaultVal]
        set newTemp [my newVarInstance $tempLoc]
        incr n
        set q [list phi $newTemp]
        set k -1
        foreach tuple2 $optInfo {
            lassign $tuple2 fromBlock
................................................................................
            if {$k >= $n} {
                lappend q $tempLoc
            } else {
                lappend q $defaultLit
            }
        }
        lappend q [list bb $fromb] $tempLoc
        my va_EmitAndTrack $b bb $q



        lappend newq $newTemp
    }


}

# quadcode::transformer method va_DoArgs --
#
#	Emits code to extract the parameter sequence needed to fill '$args'
#	from the parameter list.
#
................................................................................
#	the error block if needed
#
# The assumption is made that the 'arglen' temporary in $B has the
# length of the 

oo::define quadcode::transformer method va_CheckEnough {B callee minLength} {


    set compLoc [my newVarInstance {temp @toofew}]
    set lenLoc [$B gettemp arglen]

    # compare args provided to args needed
    $B emit [list gt $compLoc [list literal $minLength] $lenLoc]
    my debug-varargs {
        $B log-last
    }

    # jump to a 'wrong # args' error if wrong
    set errb [my va_MakeWrongArgs $B $callee]
    $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
    }

    # return to the 'no failure' branch
    $B buildin $okb


}
 
# quadcode::transformer method va_CheckTooMany --
#
#	Emits a codeburst to check whether an 'invokeExpanded' has
#	too many args
#
# Parameters:
#	bVar - Variable holding the basic block number
#	bbVar - Variable holding the content of the current basic block
#	lenLoc - LLVM location holding the argument list length
#	compTemp - Name of a temporary to use as a comparison result

#	i - Index of the next unclaimed argument
#	errorB - Basic block number to jump to if there are too many args
#



# Results:
#	None
#
# Side effects:
#	Emits code and closes the basic block

oo::define quadcode::transformer method va_CheckTooMany {bVar bbVar lenLoc
                                                             compTemp i
                                                             errorB} {

    upvar 1 $bVar b $bbVar bb








    set compLoc [my newVarInstance $compTemp]
    my va_EmitAndTrack $b bb [list gt $compLoc $lenLoc [list literal $i]]


























    set intb [llength $bbcontent]
    lappend bbcontent {}
    lappend bbpred {}

    my va_EmitAndTrack $b bb [list jumpTrue [list bb $intb] $compLoc]



    set newb [llength $bbcontent]
    lappend bbcontent {}
    lappend bbpred {}
    my va_EmitAndTrack $b bb [list jump [list bb $newb]]
    lset bbcontent $b $bb



    set b $intb
    set bb {}



    my va_EmitAndTrack $b bb [list jump [list bb $errorB]]
    lset bbcontent $b $bb



    set b $newb
    set bb {}




}
 
# quadcode::transformer method va_MakeWrongArgs --
#
#	Generates code to throw the 'wrong # args' error when needed
#
................................................................................
    my debug-varargs {
        $B log-last
    }

    set errorb [my va_MakeErrorBlock $B]
    $B emit [list jump [list bb $errorb]]

    # Add phis for the error result ant the callframe to the error block
    set errorInPhi [$B gettemp error]
    $B updatephi $errorb $errorInPhi $excloc
    
    $B buildin $currentb
    return $wrongb
    
}
................................................................................
    set errortemp [$B maketemp error]
    $B emit [list phi $errortemp]
    my debug-varargs {
        $B log-last
    }

    $B buildin $currentb
    return
}
 
# oo::transformer method va_ConvergeErrorPath --
#
#	Converges the code for the error and normal paths after an 'invoke'.
#
# Parameters:
................................................................................
        my debug-varargs {
            $B log-last
        }

        # Move to the finalization block, and emit phis for the callframe
        # and the result

        puts "* cfin = $cfin"
        $B buildin $finalb
        $B emit [list phi $cf \
                     [list bb $errorb] $cfin [list bb $normb] $normcf]
        my debug-varargs {
            $B log-last
        }
        $B emit [list phi $result \






>
>
>
>







 







|
<





<
<


|








<
|







 







>
>
>
>
>
>






>
>













>
>







 







>
>








|
>
>
>








<
|











<






<
<







 







>
>
>
>







 







<



>
|
<
|
>
>





|
<
<
<
<

<
<
<
<
<
>
|
<
<
>
>
>
|
<
<
|
<
<
>
|
>
>
|
<
<
<
<
|
<
>
>
|
<
<
<
<
<

<
>
|
<
<
>
>
|
<
<
>
>
>
|
<
|
>
>
|
>

|









|
<
<
|
<












|
<
<

<
<
<
|
>

|
<
<
|
|





|
>
>
>
>
>
>







 







|
>
>
>


>
>







 







>








<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
>








|
|
|
<
>
|
|

>
>
>






|
<
<

<
>
>
|
>
>
>
>
|
<
<
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
<
>
|
>
>
|
<
<
<
|
<
>
>
|
<
<
>
>
>
|
<
>
>
|
<
<
>
>
>







 







|







 







|







 







<







292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
...
376
377
378
379
380
381
382
383

384
385
386
387
388


389
390
391
392
393
394
395
396
397
398
399

400
401
402
403
404
405
406
407
...
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
...
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502

503
504
505
506
507
508
509
510
511
512
513
514

515
516
517
518
519
520


521
522
523
524
525
526
527
...
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
...
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
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
...
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
...
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
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
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902


903
904
905
906
907



908

909
910
911


912
913
914
915

916
917
918


919
920
921
922
923
924
925
926
927
928
...
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
....
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
....
1141
1142
1143
1144
1145
1146
1147

1148
1149
1150
1151
1152
1153
1154
    # Any leading plain arguments that do not have {*} can simply be retained
    # in the parameter list of [invoke].
    # $pos will be the position in the parameter list of the first
    # parameter that needs special handling. 
    set argl [lrange $q 4 end]
    set pos 0
    my debug-varargs {
        puts "varargs: pos = $pos (of $nPlainParams)"
        puts "         argl = $argl"
    }
    while {$pos < $nPlainParams} {
        if {[my va_NonExpandedArgument newq $arginfo $pos $argl]} break
        incr pos
    }

    my debug-varargs {
        puts "varargs: $b:$pc: matched $pos out of $nPlainParams\
................................................................................
        
            info default $callee [lindex $arginfo $i] defaultVal

            my debug-varargs {
                puts "Emit length check and extraction for optional param \
                      $i: [lindex $arginfo $i] (default=$defaultVal)"
            }
            lassign [my va_UnpackOptional $B $j] fromBlock argLoc

            lappend optInfo [list $fromBlock $defaultVal $argLoc]
            incr i
            incr j
        }



        # Close out the last basic block, switch to the 'finish' block
        # and emit 'phi' instructions to get the correct parameter set
        set newq [my va_FinishOptional $B $newq $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 {

        my va_CheckTooMany $B $callee $j
    }

    return $newq
}
 
# quadcode::transformer method va_NonExpandedArgument --
#
................................................................................
#	end of the possible static transfers.

oo::define quadcode::transformer method va_NonExpandedArgument {newqVar arginfo
                                                                pos argl} {

    upvar 1 $newqVar newq
    
    # If the list is exhausted, return.
    if {$pos >= [llength $argl]} {
        return 1
    }

    # Extract the parameter and its name
    set param [lindex $arginfo $pos]
    set arg [lindex $argl $pos]
    my debug-varargs {
        puts "varargs: transfer actual arg [list $arg] into formal arg\
              \"$param\""
    }

    # Quit at the first {*} expansion or on a parameter that is not understood
    switch -exact -- [lindex $arg 0] {
        "literal" {
        }
        "temp" - "var" {
            lassign [my findDef $arg] defb defpc defstmt
            if {[lindex $defstmt 0] eq "expand"} {
                return 1
            }
        }
        default {
            return 1
        }
    }

    # Put the parameter on the new 'invoke' instruction
    lappend newq $arg
    return 0
}
 
# quadcode::transformer method va_MakeArgList --
#
#	Takes the non-fixed-position arguments of 'invokeExpanded'
................................................................................
#	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"
    }

    set listLoc [$B maketemp arglist]

    # Handle the first arg. 'listloc' will be the variable holding the
    # expanded arglist. 'mightThrow' will be 1 if 'listloc'
    # might be a non-list and 0 otherwise.
    if {$pos >= [llength $argl]} {
        my debug-varargs {
            puts "varargs: there are no args to list"
        }
        $B emit [list copy $listLoc {literal {}}]
        my debug-varargs {
            $B log-last
        }
        set mightThrow 0
    } else {
        set arg [lindex $argl $pos]
        my debug-varargs {
            puts "varargs: transfer first arg [list $arg]"
        }
        switch -exact -- [lindex $arg 0] {
            "literal" {

                $B emit [list list $listLoc $arg]
                my debug-varargs {
                    $B log-last
                }
                set mightThrow 0
            }
            "temp" - "var" {
                lassign [my findDef $arg] defb defpc defstmt
                if {[lindex $defstmt 0] eq "expand"} {
                    my debug-varargs {
                        puts "  (which is expanded!)"
                    }

                    $B emit [list copy $listLoc [lindex $defstmt 2]]
                    my debug-varargs {
                        $B log-last
                    }
                    set mightThrow 1
                } else {


                    my debug-varargs {
                        puts "  (which is not expanded)"
                    }
                    $B emit [list list $listLoc $arg]
                    my debug-varargs {
                        $B log-last
                    }
................................................................................
        set listLoc [$B maketemp arglist]
        $B emit [list extractMaybe $listLoc $nloc]
        my debug-varargs {
            $B log-last
        }
    }

    my debug-varargs {
        puts "varargs: arg list assembled in [$B gettemp arglist]"
        puts "         mightThrow = $mightThrow"
    }
    return $mightThrow

}
 
# quadcode::transformer method va_UnpackMandatory --
#
#	Unpacks the mandatory args to a proc from the list created
................................................................................
 
# quadcode::transformer method va_UnpackOptional --
#
#	Emits code to unpack one optional parameter in an invokeExpanded
#
# Parameters:
#	B - Builder that is emitting the invocation sequence

#	j - Position of the parameter being unpacked
#
# Results:
#
#	Returns a two-element list: the block number that will jump to the

#	finish if there are too few arguments to match all optional
#	parameters, and the location of the argument if one was successfully
#	unpacked
#
# Side effects:
#	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 {B j} {










    set compLoc [$B maketemp arg${j}found]
    


    $B emit [list ge $compLoc [list literal $j] [$B gettemp arglen]]
    my debug-varargs {
        $B log-last
    }


    set intb [$B makeblock]


    set nextb [$B makeblock]
    $B emit [list jumpTrue [list bb $intb] $compLoc]
    my debug-varargs {
        $B log-last
    }




    $B emit [list jump [list bb $nextb]]

    my debug-varargs {
        $B log-last
    }







    $B buildin $nextb
    


    set intLoc [$B maketemp arg$j]
    set argLoc [$B maketemp arg$j]
    


    $B emit [list listIndex $intLoc [$B gettemp arglist] [list literal $j]]
    my debug-varargs {
        $B log-last
    }

    $B emit [list extractMaybe $argLoc $intLoc]
    my debug-varargs {
        $B log-last
    }
    
    # Return the place where we stored the arg
    return [list $intb $argLoc]

}
 
# quadcode::transformer method va_FinishOptional --
#
#	Finish transmitting the args that have default values when
#	compiling {*}
#
# Parameters:
#	B - Builder that is emitting the quadcode invocation sequence


#	newq - 'invoke' instruction under construction

#	optInfo - List of triples: fromBlock defaultValue tempLoc
#	          giving the phi inputs for the block under construction
#
# Results:
#	None.
#
# Side effects:
#	Closes out the current basic block, opens the finish block,
#	and emits phi instructions into the finish block. Adds the
#	outputs of the phi instructions to the 'invoke' instruction
#	under construction.

oo::define quadcode::transformer method va_FinishOptional {B newq optInfo} {






    # Finish the current block and make the join point
    set finishB [$B makeblock]

    $B emit [list jump [list bb $finishB]]


    set fromb [$B curblock]
    $B buildin $finishB

    # Emit the phi instructions

    set n 0
    foreach tuple $optInfo {
        lassign $tuple fblk defaultVal tempLoc
        $B buildin $fblk
        $B emit [list jump [list bb $finishB]]
        my debug-varargs {
            $B log-last
        }
        $B buildin $finishB
        set defaultLit [list literal $defaultVal]
        set newTemp [my newVarInstance $tempLoc]
        incr n
        set q [list phi $newTemp]
        set k -1
        foreach tuple2 $optInfo {
            lassign $tuple2 fromBlock
................................................................................
            if {$k >= $n} {
                lappend q $tempLoc
            } else {
                lappend q $defaultLit
            }
        }
        lappend q [list bb $fromb] $tempLoc
        $B emit $q
        my debug-varargs {
            $B log-last
        }
        lappend newq $newTemp
    }

    return $newq
}

# quadcode::transformer method va_DoArgs --
#
#	Emits code to extract the parameter sequence needed to fill '$args'
#	from the parameter list.
#
................................................................................
#	the error block if needed
#
# The assumption is made that the 'arglen' temporary in $B has the
# length of the 

oo::define quadcode::transformer method va_CheckEnough {B callee minLength} {

    set currentb [$B curblock]
    set compLoc [my newVarInstance {temp @toofew}]
    set lenLoc [$B gettemp arglen]

    # compare args provided to args needed
    $B emit [list gt $compLoc [list literal $minLength] $lenLoc]
    my debug-varargs {
        $B log-last
    }


    my va_JumpTrueToWrongArgs $B $callee $compLoc















    return
}
 
# quadcode::transformer method va_CheckTooMany --
#
#	Emits a codeburst to check whether an 'invokeExpanded' has
#	too many args
#
# Parameters:
#	B - Builder that is emitting the quadcode sequence
#	callee - Name of the called procedure
#	maxLength - Maximum length of the arg list

#
# Results:
#	None.
#
# Side effects:
#	Emits the check.
#
# Results:
#	None
#
# Side effects:
#	Emits code and closes the basic block

oo::define quadcode::transformer method va_CheckTooMany {B callee maxLength} {




    set compLoc [my newVarInstance {temp @toomany}]
    set lenLoc [$B gettemp arglen]
    
    # Compare args provided against maximum
    $B emit [list gt $compLoc $lenLoc [list literal $maxLength]]
    my debug-varargs {
        $B log-last
    }


    my va_JumpTrueToWrongArgs $B $callee $compLoc

    return
}
 
# quadcode::transformer method va_JumpTrueToWrongArgs
#
#	Common logic for va_CheckEnough and va_CheckTooMany
#
# Parameters:
#	B - Builder that is emitting an invocation sequence.
#	callee - Name of the called command
#	compLoc - Quadcode location that contains a true value iff
#	          the wrong number of arguments is supplied.
#
# Results:
#	None.
#
# Side effects:
#	Emits a 'jumpTrue' instruction to code that reports the wrong
#	number of arguments, and a 'jump' to the following block, and
#	builds in the following block

oo::define quadcode::transformer method va_JumpTrueToWrongArgs {B callee
                                                                compLoc} {

    set intb [$B makeblock]


    set okb [$B makeblock]
    $B emit [list jumpTrue [list bb $intb] $compLoc]
    my debug-varargs {
        $B log-last
    }



    $B emit [list jump [list bb $okb]]

    my debug-varargs {
        $B log-last
    }



    set errb [my va_MakeWrongArgs $B $callee]
    $B buildin $intb
    $B emit [list jump [list bb $errb]]

    my debug-varargs {
        $B log-last
    }



    # return to the 'no failure' branch
    $B buildin $okb

}
 
# quadcode::transformer method va_MakeWrongArgs --
#
#	Generates code to throw the 'wrong # args' error when needed
#
................................................................................
    my debug-varargs {
        $B log-last
    }

    set errorb [my va_MakeErrorBlock $B]
    $B emit [list jump [list bb $errorb]]

    # Add phis for the error result and the callframe to the error block
    set errorInPhi [$B gettemp error]
    $B updatephi $errorb $errorInPhi $excloc
    
    $B buildin $currentb
    return $wrongb
    
}
................................................................................
    set errortemp [$B maketemp error]
    $B emit [list phi $errortemp]
    my debug-varargs {
        $B log-last
    }

    $B buildin $currentb
    return $errorb
}
 
# oo::transformer method va_ConvergeErrorPath --
#
#	Converges the code for the error and normal paths after an 'invoke'.
#
# Parameters:
................................................................................
        my debug-varargs {
            $B log-last
        }

        # Move to the finalization block, and emit phis for the callframe
        # and the result


        $B buildin $finalb
        $B emit [list phi $cf \
                     [list bb $errorb] $cfin [list bb $normb] $normcf]
        my debug-varargs {
            $B log-last
        }
        $B emit [list phi $result \