Changes On Branch kbk-refactor-callframe

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

Changes In Branch kbk-refactor-callframe Excluding Merge-Ins

This is equivalent to a diff from 7a21900824 to 933c8a03f0

2020-01-13
03:57
Add elimination of LOAD-STORE redundancy - don't put into the callframe a value that we just got from there. This check may or may not be useful; the test suite exercises it but only on 'set x '. It does come up in other langauges. Leaf check-in: 933c8a03f0 user: kbk tags: kbk-refactor-callframe
2020-01-09
21:56
Handle 'invokeExpanded'. Restore the ability to remove references to the callframe when calling compiled functions or builtins that don't use it. check-in: b54d2746cb user: kbk tags: kbk-refactor-callframe
2019-11-26
09:58
Starting to support 8.7's arrays with defaults Leaf check-in: e7a8c3f643 user: dkf tags: dkf-array-default
2019-11-23
23:02
merge trunk check-in: c3fc2d4137 user: kbk tags: notworking, kbk-refactor-callframe
22:35
Merge trunk: a couple of ops that interact with the callframe and were missed while refactoring Leaf check-in: 19e26fa988 user: kbk tags: notworking, tcl_8_7_branch
22:29
Merge in refactoring of two operations, directIsArray and directMakeArray, that interact with the callframe and were missed on the first go. Leaf check-in: 7a21900824 user: kbk tags: trunk
22:24
directMakeArray interacts with the callframe Closed-Leaf check-in: 1f1e370993 user: kbk tags: kbk-refactor-directops
2019-11-19
03:52
Merge refactoring so that all direct operations interact correctly with the callframe. check-in: b9e2a13b96 user: kbk tags: trunk

Changes to codegen/build.tcl.

5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
    # Results:
    #	An IMPURE BOOLEAN LLVM value reference.

    method narrowToType.IMPURE_BOOLEAN(IMPURE\040ZEROONE\040BOOLEAN) {value {name ""}} {
	my addReference(STRING) [my impure.string $value]
	if {$name ne "" && [string match {[0-9]*} [GetValueName $value]]} {
	    SetValueName $value $name
	}
	return $value
    }

    # Builder:narrowToType.IMPURE_NUMERIC_BOOLEAN(STRING) --
    #
    #	Generate code to extract IMPURE NUMERIC BOOLEAN from a STRING.
    #







|







5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
    # Results:
    #	An IMPURE BOOLEAN LLVM value reference.

    method narrowToType.IMPURE_BOOLEAN(IMPURE\040ZEROONE\040BOOLEAN) {value {name ""}} {
	my addReference(STRING) [my impure.string $value]
	if {$name ne "" && [string match {[0-9]*} [GetValueName $value]]} {
	    SetValueName $value $name
}
	return $value
    }

    # Builder:narrowToType.IMPURE_NUMERIC_BOOLEAN(STRING) --
    #
    #	Generate code to extract IMPURE NUMERIC BOOLEAN from a STRING.
    #
5547
5548
5549
5550
5551
5552
5553

















5554
5555
5556
5557
5558
5559
5560
    #	An IMPURE NUMERIC LLVM value reference.

    method narrowToType.IMPURE_NUMERIC(STRING) {value {name ""}} {
	set nval [my call ${tcl.extractNumeric} [list $value]]
	my addReference(STRING) $value
	return [my impure NUMERIC $value $nval $name]
    }


















    # Builder:nothing --
    #
    #	Create a Nothing NEXIST of the given type.
    #
    # Parameters:
    #	type -	The type of the NEXIST.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
    #	An IMPURE NUMERIC LLVM value reference.

    method narrowToType.IMPURE_NUMERIC(STRING) {value {name ""}} {
	set nval [my call ${tcl.extractNumeric} [list $value]]
	my addReference(STRING) $value
	return [my impure NUMERIC $value $nval $name]
    }

    # Builder:narrowToType.IMPURE_ZEROONE_BOOLEAN(STRING) --
    #
    #	Generate code to parse the given STRING and extract a Boolean value,
    #	either the integer 0 or 1 or one of the Boolean words. The STRING
    #	is already known to contain a value of the right type. Quadcode
    #	implementation ('narrowToType')
    #
    # Parameters:
    #	value - The STRING LLVM reference to parse.
    #   name (optional) - A name to give to the result value.

    method narrowToType.IMPURE_ZEROONE_BOOLEAN(STRING) {value {name ""}} {
	set bval [my call ${tcl.extractZeroOneBoolean} [list $value]]
	my addReference(STRING) $value
	return [my impure {ZEROONE BOOLEAN} $value $bval $name]
    }

    # Builder:nothing --
    #
    #	Create a Nothing NEXIST of the given type.
    #
    # Parameters:
    #	type -	The type of the NEXIST.
6285
6286
6287
6288
6289
6290
6291
















6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
















6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326


















6327
6328
6329
6330
6331
6332
6333
    #
    # Results:
    #	Returns an LLVM INT reference

    method returnCode(FAIL) {src ecode name} {
	my packInt32 $ecode
    }

















    # Builder:returnCode(FAIL STRING) --
    #
    #   Pass the Tcl return code through to an LLVM value
    #
    # Parameters:
    #	src - The FAIL STRING value that encodes the last interpreter action
    #   ecode - The INT32 value that holds the return code
    #   name (optional) - A name to give to the result value
    #
    # Results:
    #	Returns an LLVM INT reference

    method returnCode(FAIL\040STRING) {src ecode name} {
	my dropReference(FAIL\040STRING) $src
	my packInt32 $ecode $name
    }

















    # Builder:returnOptions(FAIL,INT) --
    #
    #	Get the Tcl exception dictionary. Quadcode implementation
    #	('returnOptions').
    #
    # Parameters:
    #   src - The Tcl status, as a LLVM FAIL reference
    #	value -	The Tcl result code, as an LLVM INT value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM STRING reference.

    method returnOptions(FAIL,INT) {src value {name ""}} {
	my call ${tcl.getreturnopts} [list $value] $name
    }



















    # Builder:returnOptions(FAIL STRING,INT) --
    #
    #	Get the Tcl exception dictionary. Quadcode implementation
    #	('returnOptions').
    #
    # Parameters:







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
    #
    # Results:
    #	Returns an LLVM INT reference

    method returnCode(FAIL) {src ecode name} {
	my packInt32 $ecode
    }

    # Builder:returnCode(FAIL DOUBLE) --
    #
    #	Pass the Tcl return code through to an LLVM value
    #
    # Parameters:
    #	src - The FAIL DOUBLE value that encodes the last interpreter action
    #	ecode - The INT32 value that holds the return code
    #	name (optional) - A name to give to the result value
    #
    # Results:
    #	Returns an LLVM INT reference

    method returnCode(FAIL\040DOUBLE) {src ecode name} {
	my packInt32 $ecode
    }

    # Builder:returnCode(FAIL STRING) --
    #
    #   Pass the Tcl return code through to an LLVM value
    #
    # Parameters:
    #	src - The FAIL STRING value that encodes the last interpreter action
    #   ecode - The INT32 value that holds the return code
    #   name (optional) - A name to give to the result value
    #
    # Results:
    #	Returns an LLVM INT reference

    method returnCode(FAIL\040STRING) {src ecode name} {
	my dropReference(FAIL\040STRING) $src
	my packInt32 $ecode $name
    }

    # Builder:returnCode(FAIL ZEROONE) --
    #
    #	Pass the Tcl return code through to an LLVM value
    #
    # Parameters:
    #	src - The FAIL ZEROONE value that encodes the last interpreter action
    #	ecode - The INT32 value that holds the return code
    #	name (optional) - A name to give to the result value
    #
    # Results:
    #	Returns an LLVM INT reference

    method returnCode(FAIL\040ZEROONE) {src ecode name} {
	my packInt32 $ecode
    }

    # Builder:returnOptions(FAIL,INT) --
    #
    #	Get the Tcl exception dictionary. Quadcode implementation
    #	('returnOptions').
    #
    # Parameters:
    #   src - The Tcl status, as a LLVM FAIL reference
    #	value -	The Tcl result code, as an LLVM INT value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM STRING reference.

    method returnOptions(FAIL,INT) {src value {name ""}} {
	my call ${tcl.getreturnopts} [list $value] $name
    }

    # Builder:returnOptions(FAIL DOUBLE,INT) --
    #
    #	Get the Tcl exception dictionary. Quadcode implementation
    #	('returnOptions').
    #
    # Parameters:
    #   src - The Tcl status, as a LLVM FAIL DOUBLE reference
    #	value -	The Tcl result code, as an LLVM INT value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM STRING reference.

    method returnOptions(FAIL\040DOUBLE,INT) {src value {name ""}} {
	my call ${tcl.getreturnopts} [list $value] $name
    }

    # Builder:returnOptions(FAIL STRING,INT) --
    #
    #	Get the Tcl exception dictionary. Quadcode implementation
    #	('returnOptions').
    #
    # Parameters:

Changes to codegen/compile.tcl.

1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
    }

    method IssueInvokeFunction {tgt func arguments vname} {
	upvar 1 callframe callframe thecallframe thecallframe
	set BASETYPES {ZEROONE INT DOUBLE NUMERIC STRING}

	set result [$b call $func $arguments $vname]
	if {[my ValueTypes $tgt] eq "FAIL"} {
	    $b store $result $errorCode
	    my SetErrorLine $errorCode
	} else {
	    set ts [lmap t $BASETYPES {Type $t?}]
	    if {[TypeOf $result] in $ts} {
		$b store [$b extract $result 0] $errorCode
	    } elseif {[Type [TypeOf $result]?] eq [Type [my ValueTypes $tgt]]} {







|







1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
    }

    method IssueInvokeFunction {tgt func arguments vname} {
	upvar 1 callframe callframe thecallframe thecallframe
	set BASETYPES {ZEROONE INT DOUBLE NUMERIC STRING}

	set result [$b call $func $arguments $vname]
	if {[my ValueTypes $tgt] in {"FAIL" "CALLFRAME FAIL"}} {
	    $b store $result $errorCode
	    my SetErrorLine $errorCode
	} else {
	    set ts [lmap t $BASETYPES {Type $t?}]
	    if {[TypeOf $result] in $ts} {
		$b store [$b extract $result 0] $errorCode
	    } elseif {[Type [TypeOf $result]?] eq [Type [my ValueTypes $tgt]]} {

Changes to codegen/mathlib.tcl.

28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
    variable tcl.add.numeric tcl.sub.numeric tcl.mult.numeric tcl.div.numeric
    variable tcl.pow.numeric tcl.land.numeric tcl.lor.numeric tcl.not.numeric
    variable tcl.not.numericOrBoolean
    variable tcl.neg.numeric tcl.eq.numeric tcl.ne.numeric tcl.lt.numeric
    variable tcl.le.numeric tcl.gt.numeric tcl.ge.numeric
    variable tcl.isBoolean tcl.isInteger tcl.isDouble
    variable tcl.isNumeric tcl.isNumericOrBoolean
    variable tcl.isTrue.numerc tcl.isTrue.numericOrBoolean
    variable tcl.isZeroOneBoolean
    variable tcl.extractNumeric tcl.extractNumericOrBoolean
    variable tcl.extractDouble tcl.extractInteger

    variable tcl.stringify.double tcl.stringify.int
    variable tcl.stringify.numeric
    variable tcl.cmp.strstr tcl.cmp.strnum

    # Builder:GrowingBinaryFunction --
    #
    #	Generate a function that implements a (normal) mathematical operator







|



>







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    variable tcl.add.numeric tcl.sub.numeric tcl.mult.numeric tcl.div.numeric
    variable tcl.pow.numeric tcl.land.numeric tcl.lor.numeric tcl.not.numeric
    variable tcl.not.numericOrBoolean
    variable tcl.neg.numeric tcl.eq.numeric tcl.ne.numeric tcl.lt.numeric
    variable tcl.le.numeric tcl.gt.numeric tcl.ge.numeric
    variable tcl.isBoolean tcl.isInteger tcl.isDouble
    variable tcl.isNumeric tcl.isNumericOrBoolean
    variable tcl.isTrue.numeric tcl.isTrue.numericOrBoolean
    variable tcl.isZeroOneBoolean
    variable tcl.extractNumeric tcl.extractNumericOrBoolean
    variable tcl.extractDouble tcl.extractInteger
    variable tcl.extractZeroOneBoolean
    variable tcl.stringify.double tcl.stringify.int
    variable tcl.stringify.numeric
    variable tcl.cmp.strstr tcl.cmp.strnum

    # Builder:GrowingBinaryFunction --
    #
    #	Generate a function that implements a (normal) mathematical operator
1535
1536
1537
1538
1539
1540
1541
































1542
1543
1544
1545
1546
1547
1548
	    my condBr [my extract $b 0] $returnBoolean $getDouble
	label returnBoolean:
	    my ret [my packNumericOrBooleanBoolean [my extract $b 1]]
	label getDouble:
	    set i [my GetDouble $value]
	    my br $testType
	}
































			
	##### Function tcl.extractDouble #####
	#
	# Type signature: value:STRING -> DOUBLE
	#
	# Parse a STRING as a DOUBLE; the value is known to be parseable.
	# Part of the implementation of quadcode "narrowToType".







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
	    my condBr [my extract $b 0] $returnBoolean $getDouble
	label returnBoolean:
	    my ret [my packNumericOrBooleanBoolean [my extract $b 1]]
	label getDouble:
	    set i [my GetDouble $value]
	    my br $testType
	}

	##### Function tcl.extractZeroOneBoolean #####
	#
	# Type signature: value:STRING -> ZEROONE
	#
	# Parse a STRING as a Boolean value. The value is known to be
	# parsable.  Part of the implementation of quadcode 'narrowToType'.

	set f [$m local "tcl.extractZeroOneBoolean" "BOOLEAN<-STRING"]
	params value
	build {
	    nonnull $value
	    my br $testType
	label testType:
	    set type [my dereference $value 0 Tcl_Obj.typePtr]
	    my condBr [my nonnull $type] $testIsInt $testIsBoolean
	label testIsInt:
	    my condBr [my isInteger $value] $returnInt $testIsBoolean
	label returnInt:
	    set gw [my GetWide $value]
	    set i [my extract $gw 1]
	    my switch $i $no 0 $yes
	label no:
	    my ret [Const true bool]
	label yes:
	    my ret [Const false bool]
	label testIsBoolean:
	    set b [my GetBoolean $value]
	    my condBr [my extract $b 0] $returnBoolean $testIsInt
	label returnBoolean:
	    my ret [my extract $b 1]
	}
			
	##### Function tcl.extractDouble #####
	#
	# Type signature: value:STRING -> DOUBLE
	#
	# Parse a STRING as a DOUBLE; the value is known to be parseable.
	# Part of the implementation of quadcode "narrowToType".

Changes to codegen/stdlib.tcl.

2621
2622
2623
2624
2625
2626
2627

2628
2629
2630
2631
2632
2633
2634
	label setSublist:
	    $api TclListObjSetElement {} $parent $index $sublist
	    my br $loop7
	label loop7:
	    my condBr [my shared $sublist] $mustDuplicate $loop8
	label mustDuplicate:
	    set dupeSublist [$api Tcl_DuplicateObj $sublist]

	    $api TclListObjSetElement {} $parent $index $dupeSublist
	    my br $loop8
	label loop8:
	    my store [my load $chain] \
		[my cast(ptr) [my gep $parent 0 Tcl_Obj.internalRep 1] STRING]
	    my store $parent $chain
	    my br $loop1







>







2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
	label setSublist:
	    $api TclListObjSetElement {} $parent $index $sublist
	    my br $loop7
	label loop7:
	    my condBr [my shared $sublist] $mustDuplicate $loop8
	label mustDuplicate:
	    set dupeSublist [$api Tcl_DuplicateObj $sublist]
	    my store $dupeSublist $subList
	    $api TclListObjSetElement {} $parent $index $dupeSublist
	    my br $loop8
	label loop8:
	    my store [my load $chain] \
		[my cast(ptr) [my gep $parent 0 Tcl_Obj.internalRep 1] STRING]
	    my store $parent $chain
	    my br $loop1

Changes to codegen/varframe.tcl.

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
    variable tcl.arraystring.addRef tcl.arraystring.addRef.nexist
    variable tcl.array.dropRef tcl.array.dropRef.nexist tcl.array.dropRef.fail
    variable tcl.arraystring.dropRef tcl.arraystring.dropRef.nexist
    variable tcl.array.init tcl.arraystring.init
    variable tcl.arraystring.extractarray tcl.arraystring.extractarray.nexist
    variable tcl.arraystring.extractscalar tcl.arraystring.extractscalar.nexist
    variable tcl.array.elemexists tcl.arraystring.elemexists
    variable tcl.array.get tcl.array.set tcl.array.unset
    variable tcl.arraystring.isarray

    method VariableHelperFunctions {api} {
	set 0 [Const 0]
	set 1 [Const 1]

	# Various flag bits







|







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
    variable tcl.arraystring.addRef tcl.arraystring.addRef.nexist
    variable tcl.array.dropRef tcl.array.dropRef.nexist tcl.array.dropRef.fail
    variable tcl.arraystring.dropRef tcl.arraystring.dropRef.nexist
    variable tcl.array.init tcl.arraystring.init
    variable tcl.arraystring.extractarray tcl.arraystring.extractarray.nexist
    variable tcl.arraystring.extractscalar tcl.arraystring.extractscalar.nexist
    variable tcl.array.elemexists tcl.arraystring.elemexists
    variable tcl.array.get tcl.array.get.nexist tcl.array.set tcl.array.unset
    variable tcl.arraystring.isarray

    method VariableHelperFunctions {api} {
	set 0 [Const 0]
	set 1 [Const 1]

	# Various flag bits
2850
2851
2852
2853
2854
2855
2856





















2857
2858
2859
2860
2861
2862
2863
	    # TODO: What sort of flags should we watch out for?
	    my addReference(STRING) $val
	    my ret [my just $val]
	label unfound:
	    my ret [my nothing STRING]
	}






















	##### Function tcl.array.set #####
	#
	# Type signature: array:ARRAY * key:STRING * value:STRING -> ARRAY
	#
	# Sets the contents of an element in an array, returning the updated
	# array (which is actually the same as the input array; it is an
	# in-place modification).







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
	    # TODO: What sort of flags should we watch out for?
	    my addReference(STRING) $val
	    my ret [my just $val]
	label unfound:
	    my ret [my nothing STRING]
	}

	##### Function tcl.array.get.nexist #####
	#
	# Type signature: array:ARRAY! * key:STRING -> STRING!
	#
	# Retrieves the contents of an element from an array. Retrives
	# Nothing if the array does not exist
	#
	# TRICKY POINT: Does not handle traces or aliased elements. (Is the
	# latter even possible in Tcl?)

	set f [$m local tcl.array.get.nexist STRING!<-ARRAY!,STRING]
	params array key
	build {
	    nonnull $key
	    my condBr [my maybe $array] $nothing $realArray
	label nothing:
	    my ret [my nothing STRING]
	label realArray:
	    my ret [my Call tcl.array.get [my unmaybe $array] $key]
	}
	
	##### Function tcl.array.set #####
	#
	# Type signature: array:ARRAY * key:STRING * value:STRING -> ARRAY
	#
	# Sets the contents of an element in an array, returning the updated
	# array (which is actually the same as the input array; it is an
	# in-place modification).

Changes to demos/perftest/support.tcl.

104
105
106
107
108
109
110

111








112
113
114
115

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135


136
137
138
139
140
141
142
    global bytes

    # Copy/mod so that we don't have problems with bytecode caches
    set script " $op "

    # Run test multiple times to detect literal leakage problems
    set bytes [CleanByteArrayValue]

    namespace eval $NS $script








    set bytes [CleanByteArrayValue]
    set val($prefix,$op) [namespace eval $NS $script]
    if {$printout} {
	puts "eval ${op}: \"$val($prefix,$op)\""

    }
    set bytes [CleanByteArrayValue]
    set rep($prefix,$op) [tcl::unsupported::representation \
			      [namespace eval $NS $script]]
    set mem($prefix,$op) [memtest {
	set bytes [CleanByteArrayValue]
	namespace eval $NS $script
    }]
    set time($prefix,$op) [tcl::mathfunc::min {*}[lmap _ $innerIter {
	set bytes [CleanByteArrayValue]
	lindex [namespace eval $NS [list time $script $iterations]] 0
    }]]
    # Collect this info after the timing loop; makes sure that result leaks
    # show up cleanly.
    set bytes [CleanByteArrayValue]
    set rep($prefix,2,$op) [tcl::unsupported::representation \
				[namespace eval $NS $script]]
    append time($prefix,$op) " microseconds per iteration"
    if {$printout} {
	puts "time ${op}: $time($prefix,$op)"


    }
}

#########################################################################
#
# Demonstration runner for entire suite.








>
|
>
>
>
>
>
>
>
>
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>







104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
    global bytes

    # Copy/mod so that we don't have problems with bytecode caches
    set script " $op "

    # Run test multiple times to detect literal leakage problems
    set bytes [CleanByteArrayValue]
    puts -nonewline "eval $script:"; flush stdout
    if {[catch {namespace eval $NS $script} result opts]} {
	puts [dict get $opts -errorinfo]
	set val($prefix,$op) [list *error* $result]
	set rep($prefix,$op) FAILED
	set rep($prefix,2,$op) FAILED
	set mem($prefix,$op) 0;	# Don't report leakage
	append time($prefix,$op) Inf
    } else {

	set bytes [CleanByteArrayValue]
	set val($prefix,$op) [namespace eval $NS $script]
	if {$printout} {
	    puts " \"[lindex $val($prefix,$op) 1]\""
	    flush stdout
	}
	set bytes [CleanByteArrayValue]
	set rep($prefix,$op) [tcl::unsupported::representation \
				  [namespace eval $NS $script]]
	set mem($prefix,$op) [memtest {
	    set bytes [CleanByteArrayValue]
	    namespace eval $NS $script
	}]
	set time($prefix,$op) [tcl::mathfunc::min {*}[lmap _ $innerIter {
	    set bytes [CleanByteArrayValue]
	    lindex [namespace eval $NS [list time $script $iterations]] 0
	}]]
	# Collect this info after the timing loop; makes sure that result leaks
	# show up cleanly.
	set bytes [CleanByteArrayValue]
	set rep($prefix,2,$op) [tcl::unsupported::representation \
				    [namespace eval $NS $script]]
	append time($prefix,$op) " microseconds per iteration"
	if {$printout} {
	    puts "time ${op}: $time($prefix,$op)"
	    flush stdout
	}
    }
}

#########################################################################
#
# Demonstration runner for entire suite.

Changes to demos/perftest/tester.tcl.

563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
    set x [lrange $l 0 1]
    set y [lrange $l 2 end]
    list $l $x $y
}

proc lsetest {l {ix { 2 }}} {
    for {set i 0} {$i < [llength $l]} {incr i} {
	lset l $i >[lindex $l $i]<
    }
    lset l $ix abc
    lset l 1 1 def
    return $l
}
proc lappendtest {l} {
    lappend l a







|







563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
    set x [lrange $l 0 1]
    set y [lrange $l 2 end]
    list $l $x $y
}

proc lsetest {l {ix { 2 }}} {
    for {set i 0} {$i < [llength $l]} {incr i} {
    	lset l $i >[lindex $l $i]<
    }
    lset l $ix abc
    lset l 1 1 def
    return $l
}
proc lappendtest {l} {
    lappend l a
1845
1846
1847
1848
1849
1850
1851






1852
1853
1854
1855
1856
1857
1858
    for {set i 0} {$i < 100} {incr i} {
	incr x $adder
	incr y $adder
	incr y $adder
    }
    list $x $y
}







namespace eval ::inlinetwice {

    proc carry limb { 
        list [expr {$limb & 0x0FFFFFFF}] [expr {$limb >> 28}] 
    }








>
>
>
>
>
>







1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
    for {set i 0} {$i < 100} {incr i} {
	incr x $adder
	incr y $adder
	incr y $adder
    }
    list $x $y
}

proc redundant-set {x} {
    set x $x
    set x $x
    return $x
}

namespace eval ::inlinetwice {

    proc carry limb { 
        list [expr {$limb & 0x0FFFFFFF}] [expr {$limb >> 28}] 
    }

2237
2238
2239
2240
2241
2242
2243











2244
2245
2246
2247
2248
2249
2250
proc toHex bin {
    regsub -all {..(?=.)} [binary encode hex $bin] {&:}
}
set key [fromHex {85:d6:be:78:57:55:6d:33:7f:44:52:fe:42:d5:06:a8:01:0
      3:80:8a:fb:0d:b2:fd:4a:bf:f6:af:41:49:f5:1b}]
set msg "Cryptographic Forum Research Group"
set tag [fromHex {a8:06:1d:c1:30:51:36:c6:c2:2b:8b:af:0c:01:27:a9}]












# A simple helper that is not compiled, but rather just shortens code below

proc cleanopt {script} {
    variable cleanopt
    set code [uplevel 1 [list catch $script cleanopt(msg) cleanopt(opt)]]
    set msg $cleanopt(msg)







>
>
>
>
>
>
>
>
>
>
>







2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
proc toHex bin {
    regsub -all {..(?=.)} [binary encode hex $bin] {&:}
}
set key [fromHex {85:d6:be:78:57:55:6d:33:7f:44:52:fe:42:d5:06:a8:01:0
      3:80:8a:fb:0d:b2:fd:4a:bf:f6:af:41:49:f5:1b}]
set msg "Cryptographic Forum Research Group"
set tag [fromHex {a8:06:1d:c1:30:51:36:c6:c2:2b:8b:af:0c:01:27:a9}]

namespace eval minfunc {

    proc a {p q} {
	expr {min($p,$q)}
    }

    proc b {} {
	a 21 3
    }
}	    

# A simple helper that is not compiled, but rather just shortens code below

proc cleanopt {script} {
    variable cleanopt
    set code [uplevel 1 [list catch $script cleanopt(msg) cleanopt(opt)]]
    set msg $cleanopt(msg)
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582

2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
    upvartest1::check1
    upvartest1::check2
    upvartest2::test1
    upvartest2::test2
    upvartest2::test3
    upvartest2::test4

    {wideimpure 3.0}

    {hash::H9fast ultraantidisestablishmentarianistically}
    {hash::H9mid ultraantidisestablishmentarianistically}
    {hash::H9slow ultraantidisestablishmentarianistically}

    {toHex [poly1305 compute $key $msg]}
    {poly1305 verify $key $msg $tag}

    {wideimpure 3.0}

    {cse-caller}
    {licm1 100}
    {licm2 100}
    {redundant-purify 2}

    {inlinetwice::test 0x10000003 0x50000007}

    {hash::H9fast ultraantidisestablishmentarianistically}
    {hash::H9mid ultraantidisestablishmentarianistically}
    {hash::H9slow ultraantidisestablishmentarianistically}

    {toHex [poly1305 compute $key $msg]}
    {poly1305 verify $key $msg $tag}
}

set demos'slow' {
    {flightawarebench::test 5 5 2}
    {llength [hash::main]}
}








<
<
<
<
<
<









>






|
<







2578
2579
2580
2581
2582
2583
2584






2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601

2602
2603
2604
2605
2606
2607
2608
    upvartest1::check1
    upvartest1::check2
    upvartest2::test1
    upvartest2::test2
    upvartest2::test3
    upvartest2::test4







    {toHex [poly1305 compute $key $msg]}
    {poly1305 verify $key $msg $tag}

    {wideimpure 3.0}

    {cse-caller}
    {licm1 100}
    {licm2 100}
    {redundant-purify 2}
    {redundant-set foobar}
    {inlinetwice::test 0x10000003 0x50000007}

    {hash::H9fast ultraantidisestablishmentarianistically}
    {hash::H9mid ultraantidisestablishmentarianistically}
    {hash::H9slow ultraantidisestablishmentarianistically}

    {minfunc::b}

}

set demos'slow' {
    {flightawarebench::test 5 5 2}
    {llength [hash::main]}
}

2644
2645
2646
2647
2648
2649
2650


2651
2652
2653
2654
2655
2656
2657
2658
    regsubtest
    # Failure handling, [subst], [try]
    wideretest
    substtest
    substtest2
    switchfail
    trimtest


    magicreturn
    returntest
    errortest1
    errortest2
    errortest2-caller
    errortest3
    errortest4 errortest4a errortest4b
    errortest5 errortest6







>
>
|







2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
    regsubtest
    # Failure handling, [subst], [try]
    wideretest
    substtest
    substtest2
    switchfail
    trimtest
    # See email chain at
    # https://sourceforge.net/p/tcl/mailman/message/36579552/
    # magicreturn		  <-- BUG in refactor-callframe
    returntest
    errortest1
    errortest2
    errortest2-caller
    errortest3
    errortest4 errortest4a errortest4b
    errortest5 errortest6
2669
2670
2671
2672
2673
2674
2675
2676

2677
2678
2679


2680
2681
2682
2683
2684
2685
2686





















2687


2688
2689
2690
2691
2692
2693
2694
    rangetest
    numberitems numberitems2 numberitems3 doubleitems
    containment
    lsorttest
    lsortcmd
    # Dictionary operations (also see some [try] tests)
    dictest
    dictest2 dictest3

    dictest4 dictest5
    dictest6
    dictest7 dictest8 dictest9


    dictfor
    # Nonexistent variables
    nextest1
    nextest2
    nextest3
    nextest4
    # Array operations





















    arrayTest::*


    wordcounter1
    wordcounter2
    wordcounter3
    wordcounter4
    # Calls of uncompiled code
    calltest
    calltest2







|
>


|
>
>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>







2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
    rangetest
    numberitems numberitems2 numberitems3 doubleitems
    containment
    lsorttest
    lsortcmd
    # Dictionary operations (also see some [try] tests)
    dictest
    dictest2
    dictest3
    dictest4 dictest5
    dictest6
    dictest7
    dictest8
    dictest9
    dictfor
    # Nonexistent variables
    nextest1
    nextest2
    nextest3
    nextest4
    # Array operations
    ::arrayTest::aexists
    ::arrayTest::errors1
    ::arrayTest::errors1a
    ::arrayTest::errors1b
    ::arrayTest::errors1c
    ::arrayTest::errors1d
    ::arrayTest::errors1e
    ::arrayTest::errors1f
    ::arrayTest::errors2
    ::arrayTest::errors2a
    ::arrayTest::errors2b
    ::arrayTest::errors2c
    ::arrayTest::errors2d
    ::arrayTest::errors2e
    ::arrayTest::errors2f
    ::arrayTest::errors3
    ::arrayTest::errors4a
    ::arrayTest::errors4b
    ::arrayTest::errors4c
    ::arrayTest::errors4d
    ::arrayTest::iexists
    ::arrayTest::init
    ::arrayTest::init2
    ::arrayTest::unsetelt
    wordcounter1
    wordcounter2
    wordcounter3
    wordcounter4
    # Calls of uncompiled code
    calltest
    calltest2
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
    coscaller1
    coscaller2
    xsum xsum2
    # Namespace tests
    nstestaux::pts
    nstest::nstest0
    nstest::nstest1
    # nstest::nstest2   fails with command not found
    nstest::nstest3
    nstest::nstest4
    # nstest::nstest5   fails with invalid command name
    nstest::nstest6
    nstest::nstest7
    nstest::nstest8
    nstest9
    upvartest::*
    # Miscellaneous other tests
    bctest
    asmtest

    # List expansion tests

    expandtest::joinsp expandtest::join/ expandtest::join, expandtest::fixed
    expandtest::fixedUp
    expandtest::test1 expandtest::test2 expandtest::test3
    # expandtest::test4   Needs support for return -code continue
    # expandtest::test5   Needs support for loop exception ranges
    expandtest::test6
    expandtest::test7
    expandtest::test8
    expandtest::test9
    expandtest::test10
    expandtest::test11
    expandtest::test12







|


|














|
|







2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
    coscaller1
    coscaller2
    xsum xsum2
    # Namespace tests
    nstestaux::pts
    nstest::nstest0
    nstest::nstest1
    # nstest::nstest2   fails with command not found		BUG
    nstest::nstest3
    nstest::nstest4
    # nstest::nstest5   fails with invalid command name		BUG
    nstest::nstest6
    nstest::nstest7
    nstest::nstest8
    nstest9
    upvartest::*
    # Miscellaneous other tests
    bctest
    asmtest

    # List expansion tests

    expandtest::joinsp expandtest::join/ expandtest::join, expandtest::fixed
    expandtest::fixedUp
    expandtest::test1 expandtest::test2 expandtest::test3
    # expandtest::test4   Needs support for return -code continue   BUG
    # expandtest::test5   Needs support for loop exception ranges   BUG
    expandtest::test6
    expandtest::test7
    expandtest::test8
    expandtest::test9
    expandtest::test10
    expandtest::test11
    expandtest::test12
2747
2748
2749
2750
2751
2752
2753


2754



2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767




2768


2769

2770
2771
2772
2773
2774










2775



2776

2777
2778
2779
2780
2781
2782
2783
    bug-7c599d4029::*
    singleton::*
    linesearch::colinear
    linesearch::sameline
    linesearch::getAllLines1
    linesearch::getAllLines2
    regexptest::*


    vartest::*



    nsvartest::*
    directtest::init directtest::accum directtest::summarize
    directtest::check
    directtest::ary1
    directtest::ary2 directtest::ary3
    directtest::ary4 directtest::ary5
    directtest::alias
    upvar0
    upvar0a
    upvartest0::*
    upvartest1::*
    upvartest2::*
    flightawarebench::*




    hash::*


    redundant-purify

    inlinetwice::*
    licm1 licm2
    cse cse-caller
    wideimpure
    poly1305::*










    poly1305::tcl::mathfunc::*



}

set toCompile'slow' {
    parseBuiltinsTxt::main
}

#############################################################################
#
# Demonstration/test running code. In particular, this (effectively) calls:







>
>
|
>
>
>













>
>
>
>
|
>
>

>




|
>
>
>
>
>
>
>
>
>
>
|
>
>
>

>







2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
    bug-7c599d4029::*
    singleton::*
    linesearch::colinear
    linesearch::sameline
    linesearch::getAllLines1
    linesearch::getAllLines2
    regexptest::*
    ::vartest::accum
    ::vartest::check
    ::vartest::init
    ::vartest::summarize
    ::vartest::throw
    ::vartest::throwcheck
    nsvartest::*
    directtest::init directtest::accum directtest::summarize
    directtest::check
    directtest::ary1
    directtest::ary2 directtest::ary3
    directtest::ary4 directtest::ary5
    directtest::alias
    upvar0
    upvar0a
    upvartest0::*
    upvartest1::*
    upvartest2::*
    flightawarebench::*
    ::hash::H9fast
    ::hash::H9mid
    ::hash::H9slow
    ::hash::Hfast
    ::hash::Hmid
    ::hash::Hslow
    ::hash::main
    redundant-purify
    redundant-set
    inlinetwice::*
    licm1 licm2
    cse cse-caller
    wideimpure
    ::poly1305::carry
    ::poly1305::clamp
    # ::poly1305::compute - Don't optimize this - SEGV ensues
    # ::poly1305::debug - This gets optimized by the bytecode compiler if
    #                     quadcode doesn't take it away. Need to make sure
    #                     that quadcode does nothing gracefully, either by
    #                     inlining the null function or by detecting it up
    #                     front.
    ::poly1305::equals
    ::poly1305::load_130_le_26
    ::poly1305::verify
    ::poly1305::tcl::mathfunc::*
    fromHex toHex
    minfunc::a minfunc::b
    ::tcl::mathfunc::min
}

set toCompile'slow' {
    parseBuiltinsTxt::main
}

#############################################################################
#
# Demonstration/test running code. In particular, this (effectively) calls:

Added doc/20190216callframe/anticout.svg.































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?xml version='1.0' encoding='UTF-8'?>
<!-- This file was generated by dvisvgm 1.15.1 -->
<svg height='32.8594pt' version='1.1' viewBox='-0.239051 -0.227989 215.851 32.8594' width='215.851pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
<defs>
<path d='M3.74595 -0.860772C3.74595 -1.03611 3.61046 -1.10785 3.44309 -1.10785C3.33151 -1.10785 3.21993 -1.10785 3.14819 -0.924533C3.00473 -0.573848 2.68593 -0.486177 2.399 -0.486177C1.73748 -0.486177 1.17958 -1.02814 1.17958 -1.72154C1.17958 -2.12802 1.43462 -2.97285 2.44682 -2.97285C2.67796 -2.97285 2.81345 -2.95691 2.8533 -2.94894C2.87721 -2.94097 2.88518 -2.933 2.88518 -2.86127C2.90112 -2.63014 3.06849 -2.49465 3.26775 -2.49465C3.50685 -2.49465 3.65828 -2.66999 3.65828 -2.88518C3.65828 -3.49888 2.82939 -3.49888 2.46276 -3.49888C1.04408 -3.49888 0.573848 -2.399 0.573848 -1.72154C0.573848 -0.765131 1.33898 0.0398506 2.35915 0.0398506C3.49091 0.0398506 3.74595 -0.72528 3.74595 -0.860772Z' id='g0-99'/>
<path d='M3.45106 -3.15616C3.45106 -3.27572 3.45106 -3.49888 3.18804 -3.49888C3.00473 -3.49888 2.96488 -3.40324 2.94097 -3.35542C2.6142 -3.49888 2.29539 -3.49888 2.11208 -3.49888C0.757161 -3.49888 0.581818 -2.82939 0.581818 -2.55044C0.581818 -1.80922 1.41868 -1.68169 2.12005 -1.57011C2.55044 -1.49838 3.16413 -1.40274 3.16413 -1.0122C3.16413 -0.72528 2.86127 -0.486177 2.16787 -0.486177C1.67372 -0.486177 1.35492 -0.653549 1.18755 -1.13176C1.1477 -1.25928 1.11582 -1.35492 0.884682 -1.35492C0.581818 -1.35492 0.581818 -1.15567 0.581818 -1.0122V-0.302864C0.581818 -0.183313 0.581818 0.0398506 0.844832 0.0398506C0.924533 0.0398506 1.068 0.0159402 1.1477 -0.223163C1.55417 0.0398506 2.0005 0.0398506 2.1599 0.0398506C3.51482 0.0398506 3.69016 -0.70934 3.69016 -1.00423C3.69016 -1.19552 3.6264 -1.48244 3.32354 -1.71357C3.00473 -1.95268 2.6939 -2.0005 2.13599 -2.09614C1.59402 -2.18381 1.10785 -2.26351 1.10785 -2.55044C1.10785 -2.70984 1.29913 -2.97285 2.09614 -2.97285C2.81345 -2.97285 2.83736 -2.71781 2.84533 -2.57435C2.86127 -2.3193 3.06052 -2.3193 3.14819 -2.3193C3.45106 -2.3193 3.45106 -2.51059 3.45106 -2.66202V-3.15616Z' id='g0-115'/>
<path d='M3.467 -3.0924C3.467 -3.36339 3.3873 -3.43512 3.12428 -3.43512H2.5345C2.40697 -3.43512 2.19178 -3.43512 2.19178 -3.1721S2.40697 -2.90909 2.5345 -2.90909H2.86127V-1.23537C2.86127 -0.605729 2.27945 -0.486177 1.97659 -0.486177C1.36289 -0.486177 1.36289 -0.71731 1.36289 -0.948443V-3.0924C1.36289 -3.36339 1.28319 -3.43512 1.02017 -3.43512H0.430386C0.302864 -3.43512 0.0876712 -3.43512 0.0876712 -3.1721S0.302864 -2.90909 0.430386 -2.90909H0.757161V-0.924533C0.757161 -0.191283 1.25928 0.0398506 1.92877 0.0398506C2.35118 0.0398506 2.65405 -0.0797011 2.8533 -0.231133C2.89315 0 3.08443 0 3.20399 0H3.79377C3.9213 0 4.13649 0 4.13649 -0.263014S3.9213 -0.526027 3.79377 -0.526027H3.467V-3.0924Z' id='g0-117'/>
<path d='M11.6085 16.0797C11.6085 16.2351 11.6085 16.7372 12.0986 16.7372C12.6007 16.7372 12.6007 16.2471 12.6007 16.0797V5.70262C12.6007 2.63014 9.98257 0 6.63512 0S0.669489 2.63014 0.669489 5.70262V16.0797C0.669489 16.2351 0.669489 16.7372 1.15965 16.7372C1.66177 16.7372 1.66177 16.2471 1.66177 16.0797V5.76239C1.66177 3.02466 3.96912 0.992279 6.63512 0.992279S11.6085 3.03661 11.6085 5.76239V16.0797Z' id='g2-92'/>
<path d='M4.37559 -7.35243C4.48319 -7.79477 4.53101 -7.81868 4.99726 -7.81868H6.55143C7.90237 -7.81868 7.90237 -6.67098 7.90237 -6.56339C7.90237 -5.59502 6.934 -4.36364 5.35592 -4.36364H3.63437L4.37559 -7.35243ZM6.39601 -4.268C7.69913 -4.5071 8.88269 -5.41569 8.88269 -6.51557C8.88269 -7.44807 8.05778 -8.16538 6.70685 -8.16538H2.86924C2.64209 -8.16538 2.5345 -8.16538 2.5345 -7.93823C2.5345 -7.81868 2.64209 -7.81868 2.82142 -7.81868C3.55068 -7.81868 3.55068 -7.72304 3.55068 -7.59153C3.55068 -7.56762 3.55068 -7.49589 3.50286 -7.31656L1.88892 -0.884682C1.78132 -0.466252 1.75741 -0.3467 0.920548 -0.3467C0.6934 -0.3467 0.573848 -0.3467 0.573848 -0.131507C0.573848 0 0.645579 0 0.884682 0H4.98531C6.81445 0 8.22516 -1.3868 8.22516 -2.59427C8.22516 -3.5746 7.36438 -4.17235 6.39601 -4.268ZM4.69838 -0.3467H3.08443C2.91706 -0.3467 2.89315 -0.3467 2.82142 -0.358655C2.68991 -0.37061 2.67796 -0.394521 2.67796 -0.490162C2.67796 -0.573848 2.70187 -0.645579 2.72578 -0.753176L3.56264 -4.12453H5.81021C7.22092 -4.12453 7.22092 -2.80946 7.22092 -2.71382C7.22092 -1.56613 6.18082 -0.3467 4.69838 -0.3467Z' id='g5-66'/>
<path d='M3.53873 -3.80174H5.5472C7.19701 -3.80174 8.84682 -5.02117 8.84682 -6.38406C8.84682 -7.31656 8.05778 -8.16538 6.55143 -8.16538H2.85729C2.63014 -8.16538 2.52254 -8.16538 2.52254 -7.93823C2.52254 -7.81868 2.63014 -7.81868 2.80946 -7.81868C3.53873 -7.81868 3.53873 -7.72304 3.53873 -7.59153C3.53873 -7.56762 3.53873 -7.49589 3.49091 -7.31656L1.87696 -0.884682C1.76936 -0.466252 1.74545 -0.3467 0.908593 -0.3467C0.681445 -0.3467 0.561893 -0.3467 0.561893 -0.131507C0.561893 0 0.669489 0 0.74122 0C0.968369 0 1.20747 -0.0239103 1.43462 -0.0239103H2.83337C3.06052 -0.0239103 3.31158 0 3.53873 0C3.63437 0 3.76588 0 3.76588 -0.227148C3.76588 -0.3467 3.65828 -0.3467 3.47895 -0.3467C2.76164 -0.3467 2.74969 -0.430386 2.74969 -0.549938C2.74969 -0.609714 2.76164 -0.6934 2.7736 -0.753176L3.53873 -3.80174ZM4.3995 -7.35243C4.5071 -7.79477 4.55492 -7.81868 5.02117 -7.81868H6.20473C7.10137 -7.81868 7.84259 -7.53176 7.84259 -6.63512C7.84259 -6.32428 7.68717 -5.30809 7.13724 -4.75816C6.934 -4.54296 6.36015 -4.08867 5.27223 -4.08867H3.58655L4.3995 -7.35243Z' id='g5-80'/>
<path d='M2.1599 1.99253V1.6259H1.35492V-5.61096H2.1599V-5.97758H0.988294V1.99253H2.1599Z' id='g6-91'/>
<path d='M1.35492 -5.97758H0.183313V-5.61096H0.988294V1.6259H0.183313V1.99253H1.35492V-5.97758Z' id='g6-93'/>
<path d='M1.34695 -0.629639C1.27522 -0.326775 1.25928 -0.263014 0.669489 -0.263014C0.518057 -0.263014 0.422416 -0.263014 0.422416 -0.111582C0.422416 0 0.526027 0 0.661519 0H3.61843C4.9335 0 5.91382 -0.932503 5.91382 -1.7056C5.91382 -2.28742 5.41171 -2.75766 4.61469 -2.84533C5.53923 -3.02067 6.33624 -3.6264 6.33624 -4.32777C6.33624 -4.92553 5.75442 -5.44359 4.75019 -5.44359H1.96862C1.82516 -5.44359 1.72154 -5.44359 1.72154 -5.29215C1.72154 -5.18057 1.81719 -5.18057 1.95268 -5.18057C2.21569 -5.18057 2.44682 -5.18057 2.44682 -5.05305C2.44682 -5.02117 2.43885 -5.0132 2.41494 -4.90959L1.34695 -0.629639ZM2.59029 -2.94097L3.07646 -4.88568C3.14819 -5.15666 3.15616 -5.18057 3.48294 -5.18057H4.63064C5.41171 -5.18057 5.58705 -4.67049 5.58705 -4.34371C5.58705 -3.66625 4.86177 -2.94097 3.84159 -2.94097H2.59029ZM2.04035 -0.263014C1.96862 -0.278954 1.94471 -0.278954 1.94471 -0.334745C1.94471 -0.398506 1.96065 -0.462267 1.97659 -0.510087L2.5345 -2.71781H4.15243C4.89365 -2.71781 5.14072 -2.21569 5.14072 -1.76936C5.14072 -0.988294 4.37559 -0.263014 3.41918 -0.263014H2.04035Z' id='g4-66'/>
<path d='M2.51059 -2.48667H3.96115C5.10884 -2.48667 6.30436 -3.28369 6.30436 -4.22416C6.30436 -4.90162 5.66675 -5.44359 4.63861 -5.44359H1.95268C1.80922 -5.44359 1.7056 -5.44359 1.7056 -5.29215C1.7056 -5.18057 1.80922 -5.18057 1.93674 -5.18057C2.19975 -5.18057 2.43088 -5.18057 2.43088 -5.05305C2.43088 -5.02117 2.42291 -5.0132 2.399 -4.90959L1.33101 -0.629639C1.25928 -0.334745 1.24334 -0.263014 0.67746 -0.263014C0.494147 -0.263014 0.406476 -0.263014 0.406476 -0.111582C0.406476 -0.0797011 0.430386 0 0.533998 0C0.68543 0 0.876712 -0.0159402 1.02814 -0.0239103H1.53823C2.30336 -0.0239103 2.51059 0 2.56638 0C2.6142 0 2.72578 0 2.72578 -0.151432C2.72578 -0.263014 2.62217 -0.263014 2.48667 -0.263014C2.46276 -0.263014 2.3193 -0.263014 2.18381 -0.278954C2.01644 -0.294894 2.0005 -0.318804 2.0005 -0.390535C2.0005 -0.430386 2.01644 -0.478207 2.02441 -0.518057L2.51059 -2.48667ZM3.0924 -4.88568C3.16413 -5.15666 3.1721 -5.18057 3.49888 -5.18057H4.37559C5.02914 -5.18057 5.53126 -4.98929 5.53126 -4.3995C5.53126 -4.29589 5.49141 -3.58655 5.04508 -3.14819C4.92553 -3.02864 4.54296 -2.72578 3.76189 -2.72578H2.55044L3.0924 -4.88568Z' id='g4-80'/>
<path d='M3.68219 -7.04159C3.58655 -7.47198 3.34745 -7.47198 3.07248 -7.47198C2.70187 -7.47198 2.55841 -7.42416 2.47472 -7.04159L0.992279 -0.6934C0.597758 -0.6934 0.32279 -0.6934 0.32279 -0.3467S0.645579 0 0.812951 0H1.96065C2.12802 0 2.45081 0 2.45081 -0.3467S2.16389 -0.6934 1.79328 -0.6934L2.10411 -2.03238H4.04085L4.35168 -0.6934C3.98107 -0.6934 3.69415 -0.6934 3.69415 -0.3467S4.01694 0 4.18431 0H5.332C5.49938 0 5.82217 0 5.82217 -0.3467S5.5472 -0.6934 5.15268 -0.6934L3.68219 -7.04159ZM2.25953 -2.72578C2.34321 -3.08443 3.00075 -5.90585 3.06052 -6.4797H3.07248C3.10834 -6.20473 3.27572 -5.47547 3.27572 -5.46351L3.88543 -2.72578H2.25953Z' id='g1-65'/>
<path d='M5.66675 -6.99377C5.66675 -7.18506 5.66675 -7.44807 5.332 -7.44807C5.11681 -7.44807 5.05704 -7.31656 5.00922 -7.23288C4.97335 -7.13724 4.87771 -6.92204 4.84184 -6.83836C4.35168 -7.26874 3.80174 -7.44807 3.29963 -7.44807C1.75741 -7.44807 0.478207 -5.79826 0.478207 -3.65828C0.478207 -1.47049 1.79328 0.143462 3.29963 0.143462C4.69838 0.143462 5.66675 -0.968369 5.66675 -2.02042C5.66675 -2.39103 5.41569 -2.39103 5.27223 -2.39103C5.10486 -2.39103 4.91357 -2.33126 4.88966 -2.12802C4.79402 -0.633624 3.58655 -0.549938 3.38331 -0.549938C2.27148 -0.549938 1.25529 -1.85305 1.25529 -3.65828S2.28344 -6.75467 3.37136 -6.75467C4.01694 -6.75467 4.72229 -6.2406 4.88966 -5.14072C4.92553 -4.87771 5.03313 -4.80598 5.27223 -4.80598C5.66675 -4.80598 5.66675 -5.02117 5.66675 -5.26027V-6.99377Z' id='g1-67'/>
<path d='M3.467 -6.61121H4.68643C4.8538 -6.61121 5.16463 -6.61121 5.16463 -6.95791S4.8538 -7.30461 4.68643 -7.30461H1.47049C1.30311 -7.30461 0.992279 -7.30461 0.992279 -6.95791S1.30311 -6.61121 1.47049 -6.61121H2.68991V-0.6934H1.47049C1.30311 -0.6934 0.992279 -0.6934 0.992279 -0.3467S1.30311 0 1.47049 0H4.68643C4.8538 0 5.16463 0 5.16463 -0.3467S4.8538 -0.6934 4.68643 -0.6934H3.467V-6.61121Z' id='g1-73'/>
<path d='M2.23562 -6.89813C2.09215 -7.30461 1.85305 -7.30461 1.60199 -7.30461H0.824907C0.645579 -7.30461 0.3467 -7.30461 0.3467 -6.95791S0.657534 -6.61121 0.824907 -6.61121H1.08792V-0.6934H0.824907C0.657534 -0.6934 0.3467 -0.6934 0.3467 -0.3467S0.645579 0 0.824907 0H2.02042C2.1878 0 2.51059 0 2.51059 -0.3467S2.1878 -0.6934 2.02042 -0.6934H1.75741V-6.4797H1.76936C1.80523 -6.34819 1.91283 -6.03736 2.12802 -5.42765L3.90934 -0.406476C4.0528 0 4.29191 0 4.55492 0C4.91357 0 5.05704 -0.0358655 5.05704 -0.490162V-6.61121H5.32005C5.48742 -6.61121 5.79826 -6.61121 5.79826 -6.95791S5.49938 -7.30461 5.32005 -7.30461H4.12453C3.95716 -7.30461 3.63437 -7.30461 3.63437 -6.95791S3.95716 -6.61121 4.12453 -6.61121H4.38755V-0.824907H4.37559C4.33973 -0.956413 4.23213 -1.26725 4.01694 -1.87696L2.23562 -6.89813Z' id='g1-78'/>
<path d='M5.48742 -3.64633C5.48742 -7.12528 5.23636 -7.44807 3.07248 -7.44807S0.657534 -7.12528 0.657534 -3.65828C0.657534 -0.179328 0.908593 0.143462 3.07248 0.143462S5.48742 -0.179328 5.48742 -3.64633ZM3.07248 -0.549938C1.98456 -0.549938 1.72154 -0.836862 1.59004 -1.3868C1.43462 -1.99651 1.43462 -3.07248 1.43462 -3.75392C1.43462 -4.51905 1.43462 -5.36787 1.56613 -5.94172C1.7335 -6.59925 2.09215 -6.75467 3.07248 -6.75467C4.01694 -6.75467 4.3995 -6.61121 4.56687 -5.97758C4.71034 -5.41569 4.71034 -4.48319 4.71034 -3.75392C4.71034 -3.0127 4.71034 -2.09215 4.57883 -1.44658C4.44732 -0.836862 4.18431 -0.549938 3.07248 -0.549938Z' id='g1-79'/>
<path d='M3.467 -6.61121H5.05704V-6.0254C5.05704 -5.81021 5.05704 -5.53524 5.4396 -5.53524C5.83412 -5.53524 5.83412 -5.79826 5.83412 -6.0254V-6.81445C5.83412 -7.18506 5.76239 -7.30461 5.35592 -7.30461H0.800996C0.406476 -7.30461 0.310834 -7.20897 0.310834 -6.81445V-6.0254C0.310834 -5.81021 0.310834 -5.53524 0.6934 -5.53524C1.08792 -5.53524 1.08792 -5.79826 1.08792 -6.0254V-6.61121H2.68991V-0.6934H2.11606C1.94869 -0.6934 1.63786 -0.6934 1.63786 -0.3467S1.94869 0 2.11606 0H4.04085C4.20822 0 4.51905 0 4.51905 -0.3467S4.20822 -0.6934 4.04085 -0.6934H3.467V-6.61121Z' id='g1-84'/>
<path d='M5.24832 -6.61121H5.57111C5.73848 -6.61121 6.06127 -6.61121 6.06127 -6.95791S5.73848 -7.30461 5.57111 -7.30461H4.14844C3.98107 -7.30461 3.65828 -7.30461 3.65828 -6.95791S3.98107 -6.61121 4.14844 -6.61121H4.47123V-2.49863C4.47123 -1.19552 3.69415 -0.549938 3.07248 -0.549938C2.43885 -0.549938 1.67372 -1.20747 1.67372 -2.49863V-6.61121H1.99651C2.16389 -6.61121 2.48667 -6.61121 2.48667 -6.95791S2.16389 -7.30461 1.99651 -7.30461H0.573848C0.406476 -7.30461 0.0836862 -7.30461 0.0836862 -6.95791S0.406476 -6.61121 0.573848 -6.61121H0.896638V-2.4269C0.896638 -0.980324 1.88892 0.143462 3.07248 0.143462S5.24832 -0.980324 5.24832 -2.4269V-6.61121Z' id='g1-85'/>
<path d='M8.06974 -3.87347C8.23711 -3.87347 8.4523 -3.87347 8.4523 -4.08867C8.4523 -4.31582 8.24907 -4.31582 8.06974 -4.31582H1.02814C0.860772 -4.31582 0.645579 -4.31582 0.645579 -4.10062C0.645579 -3.87347 0.848817 -3.87347 1.02814 -3.87347H8.06974ZM8.06974 -1.64981C8.23711 -1.64981 8.4523 -1.64981 8.4523 -1.86501C8.4523 -2.09215 8.24907 -2.09215 8.06974 -2.09215H1.02814C0.860772 -2.09215 0.645579 -2.09215 0.645579 -1.87696C0.645579 -1.64981 0.848817 -1.64981 1.02814 -1.64981H8.06974Z' id='g7-61'/>
<path d='M2.98879 2.98879V2.54645H1.82914V-8.52403H2.98879V-8.96638H1.3868V2.98879H2.98879Z' id='g7-91'/>
<path d='M1.85305 -8.96638H0.251059V-8.52403H1.41071V2.54645H0.251059V2.98879H1.85305V-8.96638Z' id='g7-93'/>
<path d='M4.63064 -1.80922C4.75816 -1.80922 4.9335 -1.80922 4.9335 -1.99253S4.75816 -2.17584 4.63064 -2.17584H1.07597C1.17958 -3.28369 2.10411 -4.12852 3.31557 -4.12852H4.63064C4.75816 -4.12852 4.9335 -4.12852 4.9335 -4.31183S4.75816 -4.49514 4.63064 -4.49514H3.29166C1.85704 -4.49514 0.70137 -3.37933 0.70137 -1.99253C0.70137 -0.597758 1.86501 0.510087 3.29166 0.510087H4.63064C4.75816 0.510087 4.9335 0.510087 4.9335 0.326775S4.75816 0.143462 4.63064 0.143462H3.31557C2.10411 0.143462 1.17958 -0.70137 1.07597 -1.80922H4.63064Z' id='g3-50'/>
</defs>
<g id='page1' transform='matrix(1.13 0 0 1.13 -63.986 -61.0251)'>
<use x='56.4133' xlink:href='#g1-65' y='66.3512'/>
<use x='62.5422' xlink:href='#g1-78' y='66.3512'/>
<use x='68.6712' xlink:href='#g1-84' y='66.3512'/>
<use x='74.8001' xlink:href='#g1-73' y='66.3512'/>
<use x='80.9291' xlink:href='#g1-67' y='66.3512'/>
<rect height='0.3985' width='3.69119' x='87.7962' y='65.9528'/>
<use x='91.4874' xlink:href='#g1-79' y='66.3512'/>
<use x='97.6164' xlink:href='#g1-85' y='66.3512'/>
<use x='103.745' xlink:href='#g1-84' y='66.3512'/>
<use x='110.058' xlink:href='#g7-91' y='66.3512'/>
<use x='113.298' xlink:href='#g5-66' y='66.3512'/>
<use x='122.761' xlink:href='#g7-93' y='66.3512'/>
<use x='129.321' xlink:href='#g7-61' y='66.3512'/>
<use x='155.377' xlink:href='#g2-92' y='54.9938'/>
<use x='141.712' xlink:href='#g4-80' y='80.8968'/>
<use x='148.237' xlink:href='#g3-50' y='80.8968'/>
<use x='153.862' xlink:href='#g0-115' y='80.8968'/>
<use x='158.08' xlink:href='#g0-117' y='80.8968'/>
<use x='162.299' xlink:href='#g0-99' y='80.8968'/>
<use x='166.517' xlink:href='#g0-99' y='80.8968'/>
<use x='170.799' xlink:href='#g6-91' y='80.8968'/>
<use x='173.142' xlink:href='#g4-66' y='80.8968'/>
<use x='179.898' xlink:href='#g6-93' y='80.8968'/>
<use x='184.317' xlink:href='#g1-65' y='66.3512'/>
<use x='190.446' xlink:href='#g1-78' y='66.3512'/>
<use x='196.575' xlink:href='#g1-84' y='66.3512'/>
<use x='202.704' xlink:href='#g1-73' y='66.3512'/>
<use x='208.833' xlink:href='#g1-67' y='66.3512'/>
<rect height='0.3985' width='3.69119' x='215.7' y='65.9528'/>
<use x='219.391' xlink:href='#g1-73' y='66.3512'/>
<use x='225.52' xlink:href='#g1-78' y='66.3512'/>
<use x='231.81' xlink:href='#g7-91' y='66.3512'/>
<use x='235.05' xlink:href='#g5-80' y='66.3512'/>
<use x='244.192' xlink:href='#g7-93' y='66.3512'/>
</g>
</svg>

Added doc/20190216callframe/avail.svg.























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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
104
105
106
107
<?xml version='1.0' encoding='UTF-8'?>
<!-- This file was generated by dvisvgm 1.15.1 -->
<svg height='48.5433pt' version='1.1' viewBox='-0.239051 -0.227978 447.172 48.5433' width='447.172pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
<defs>
<path d='M3.467 -4.52702C3.467 -4.79801 3.3873 -4.86974 3.12428 -4.86974H2.5345C2.40697 -4.86974 2.19178 -4.86974 2.19178 -4.60672S2.40697 -4.34371 2.5345 -4.34371H2.86127V-3.14819C2.49465 -3.43512 2.1599 -3.47497 1.94471 -3.47497C1.06002 -3.47497 0.270984 -2.72578 0.270984 -1.71357C0.270984 -0.74122 0.996264 0.0398506 1.87298 0.0398506C2.29539 0.0398506 2.63014 -0.151432 2.86127 -0.374595C2.86127 -0.151432 2.86127 0 3.20399 0H3.79377C3.9213 0 4.13649 0 4.13649 -0.263014S3.9213 -0.526027 3.79377 -0.526027H3.467V-4.52702ZM2.86127 -1.57011C2.86127 -1.11582 2.49465 -0.486177 1.89689 -0.486177C1.36289 -0.486177 0.876712 -1.0122 0.876712 -1.71357C0.876712 -2.42291 1.40274 -2.94894 1.98456 -2.94894C2.45479 -2.94894 2.86127 -2.54247 2.86127 -2.10411V-1.57011Z' id='g0-100'/>
<path d='M3.40324 -1.49838C3.55467 -1.49838 3.74595 -1.49838 3.74595 -1.80125C3.74595 -2.75766 3.20399 -3.49888 2.17584 -3.49888C1.19552 -3.49888 0.422416 -2.70187 0.422416 -1.72951C0.422416 -0.781071 1.21943 0.0398506 2.30336 0.0398506C3.39527 0.0398506 3.74595 -0.661519 3.74595 -0.860772C3.74595 -1.03611 3.61046 -1.10785 3.44309 -1.10785C3.3076 -1.10785 3.2279 -1.09988 3.14819 -0.924533C2.98879 -0.565878 2.59826 -0.486177 2.34321 -0.486177C1.76139 -0.486177 1.17958 -0.868742 1.05205 -1.49838H3.40324ZM1.06002 -2.01644C1.17958 -2.57435 1.64981 -2.97285 2.17584 -2.97285C2.89315 -2.97285 3.07646 -2.41494 3.12428 -2.01644H1.06002Z' id='g0-101'/>
<path d='M1.68966 1.76936C1.81719 1.76936 2.03238 1.76936 2.03238 1.50635S1.81719 1.24334 1.68966 1.24334H1.36289V-0.334745C1.60996 -0.0956413 1.9208 0.0398506 2.27148 0.0398506C3.15616 0.0398506 3.95318 -0.70934 3.95318 -1.72154C3.95318 -2.68593 3.24384 -3.47497 2.35118 -3.47497C1.97659 -3.47497 1.64981 -3.33948 1.36289 -3.11631C1.36289 -3.43512 1.18755 -3.43512 1.02017 -3.43512H0.430386C0.302864 -3.43512 0.0876712 -3.43512 0.0876712 -3.1721S0.302864 -2.90909 0.430386 -2.90909H0.757161V1.24334H0.430386C0.302864 1.24334 0.0876712 1.24334 0.0876712 1.50635S0.302864 1.76936 0.430386 1.76936H1.68966ZM1.36289 -2.09614C1.36289 -2.55841 1.83313 -2.94894 2.3193 -2.94894C2.87721 -2.94894 3.34745 -2.40697 3.34745 -1.72154C3.34745 -0.996264 2.80548 -0.486177 2.24757 -0.486177C1.65778 -0.486177 1.36289 -1.1477 1.36289 -1.5462V-2.09614Z' id='g0-112'/>
<path d='M1.80125 -1.45853C1.80125 -2.32727 2.42291 -2.94894 3.19601 -2.94894C3.21196 -2.63811 3.43512 -2.57435 3.56264 -2.57435C3.76189 -2.57435 3.92927 -2.71781 3.92927 -2.94894C3.92927 -3.14819 3.7858 -3.47497 3.16413 -3.47497C2.43088 -3.47497 2.0005 -3.05255 1.80125 -2.8533V-3.0924C1.80125 -3.36339 1.72154 -3.43512 1.45853 -3.43512H0.589788C0.478207 -3.43512 0.239103 -3.43512 0.239103 -3.1721S0.478207 -2.90909 0.589788 -2.90909H1.19552V-0.526027H0.589788C0.478207 -0.526027 0.239103 -0.526027 0.239103 -0.263014S0.478207 0 0.589788 0H2.64608C2.7736 0 2.98879 0 2.98879 -0.263014S2.7736 -0.526027 2.64608 -0.526027H1.80125V-1.45853Z' id='g0-114'/>
<path d='M4.47123 21.1606C4.73425 21.1606 4.80598 21.1606 4.80598 20.9933C4.82989 12.6127 5.79826 5.65479 9.98257 -0.191283C10.0663 -0.298879 10.0663 -0.32279 10.0663 -0.3467C10.0663 -0.466252 9.98257 -0.466252 9.79128 -0.466252S9.57609 -0.466252 9.55218 -0.442341C9.50436 -0.406476 7.98605 1.33898 6.77858 3.74197C5.2005 6.89813 4.20822 10.5205 3.76588 14.8722C3.73001 15.2428 3.47895 17.7295 3.47895 20.5629V21.0291C3.49091 21.1606 3.56264 21.1606 3.8137 21.1606H4.47123Z' id='g2-48'/>
<path d='M6.96986 20.5629C6.96986 13.2583 5.66675 8.97833 5.29614 7.77086C4.48319 5.11681 3.15616 2.3193 1.15965 -0.143462C0.980324 -0.358655 0.932503 -0.418431 0.884682 -0.442341C0.860772 -0.454296 0.848817 -0.466252 0.657534 -0.466252C0.478207 -0.466252 0.382565 -0.466252 0.382565 -0.3467C0.382565 -0.32279 0.382565 -0.298879 0.537983 -0.0836862C4.69838 5.72653 5.63088 12.8996 5.64284 20.9933C5.64284 21.1606 5.71457 21.1606 5.97758 21.1606H6.63512C6.88618 21.1606 6.95791 21.1606 6.96986 21.0291V20.5629Z' id='g2-49'/>
<path d='M3.8137 -0.597758C3.56264 -0.597758 3.49091 -0.597758 3.47895 -0.466252V0C3.47895 7.30461 4.78207 11.5846 5.15268 12.792C5.96563 15.4461 7.29265 18.2436 9.28917 20.7064C9.46849 20.9215 9.51631 20.9813 9.56413 21.0052C9.58804 21.0172 9.6 21.0291 9.79128 21.0291S10.0663 21.0291 10.0663 20.9096C10.0663 20.8857 10.0663 20.8618 9.99452 20.7542C6.01345 15.2309 4.81793 8.58381 4.80598 -0.430386C4.80598 -0.597758 4.73425 -0.597758 4.47123 -0.597758H3.8137Z' id='g2-64'/>
<path d='M6.96986 -0.466252C6.95791 -0.597758 6.88618 -0.597758 6.63512 -0.597758H5.97758C5.71457 -0.597758 5.64284 -0.597758 5.64284 -0.430386C5.64284 0.800996 5.63088 3.64633 5.32005 6.62316C4.67447 12.804 3.08443 17.0839 0.466252 20.7542C0.382565 20.8618 0.382565 20.8857 0.382565 20.9096C0.382565 21.0291 0.478207 21.0291 0.657534 21.0291C0.848817 21.0291 0.872727 21.0291 0.896638 21.0052C0.944458 20.9694 2.46276 19.2239 3.67024 16.8209C5.24832 13.6648 6.2406 10.0423 6.68294 5.69066C6.7188 5.32005 6.96986 2.83337 6.96986 0V-0.466252Z' id='g2-65'/>
<path d='M11.6085 16.0797C11.6085 16.2351 11.6085 16.7372 12.0986 16.7372C12.6007 16.7372 12.6007 16.2471 12.6007 16.0797V5.70262C12.6007 2.63014 9.98257 0 6.63512 0S0.669489 2.63014 0.669489 5.70262V16.0797C0.669489 16.2351 0.669489 16.7372 1.15965 16.7372C1.66177 16.7372 1.66177 16.2471 1.66177 16.0797V5.76239C1.66177 3.02466 3.96912 0.992279 6.63512 0.992279S11.6085 3.03661 11.6085 5.76239V16.0797Z' id='g2-92'/>
<path d='M1.34695 -0.629639C1.27522 -0.326775 1.25928 -0.263014 0.669489 -0.263014C0.518057 -0.263014 0.422416 -0.263014 0.422416 -0.111582C0.422416 0 0.526027 0 0.661519 0H3.61843C4.9335 0 5.91382 -0.932503 5.91382 -1.7056C5.91382 -2.28742 5.41171 -2.75766 4.61469 -2.84533C5.53923 -3.02067 6.33624 -3.6264 6.33624 -4.32777C6.33624 -4.92553 5.75442 -5.44359 4.75019 -5.44359H1.96862C1.82516 -5.44359 1.72154 -5.44359 1.72154 -5.29215C1.72154 -5.18057 1.81719 -5.18057 1.95268 -5.18057C2.21569 -5.18057 2.44682 -5.18057 2.44682 -5.05305C2.44682 -5.02117 2.43885 -5.0132 2.41494 -4.90959L1.34695 -0.629639ZM2.59029 -2.94097L3.07646 -4.88568C3.14819 -5.15666 3.15616 -5.18057 3.48294 -5.18057H4.63064C5.41171 -5.18057 5.58705 -4.67049 5.58705 -4.34371C5.58705 -3.66625 4.86177 -2.94097 3.84159 -2.94097H2.59029ZM2.04035 -0.263014C1.96862 -0.278954 1.94471 -0.278954 1.94471 -0.334745C1.94471 -0.398506 1.96065 -0.462267 1.97659 -0.510087L2.5345 -2.71781H4.15243C4.89365 -2.71781 5.14072 -2.21569 5.14072 -1.76936C5.14072 -0.988294 4.37559 -0.263014 3.41918 -0.263014H2.04035Z' id='g5-66'/>
<path d='M2.51059 -2.48667H3.96115C5.10884 -2.48667 6.30436 -3.28369 6.30436 -4.22416C6.30436 -4.90162 5.66675 -5.44359 4.63861 -5.44359H1.95268C1.80922 -5.44359 1.7056 -5.44359 1.7056 -5.29215C1.7056 -5.18057 1.80922 -5.18057 1.93674 -5.18057C2.19975 -5.18057 2.43088 -5.18057 2.43088 -5.05305C2.43088 -5.02117 2.42291 -5.0132 2.399 -4.90959L1.33101 -0.629639C1.25928 -0.334745 1.24334 -0.263014 0.67746 -0.263014C0.494147 -0.263014 0.406476 -0.263014 0.406476 -0.111582C0.406476 -0.0797011 0.430386 0 0.533998 0C0.68543 0 0.876712 -0.0159402 1.02814 -0.0239103H1.53823C2.30336 -0.0239103 2.51059 0 2.56638 0C2.6142 0 2.72578 0 2.72578 -0.151432C2.72578 -0.263014 2.62217 -0.263014 2.48667 -0.263014C2.46276 -0.263014 2.3193 -0.263014 2.18381 -0.278954C2.01644 -0.294894 2.0005 -0.318804 2.0005 -0.390535C2.0005 -0.430386 2.01644 -0.478207 2.02441 -0.518057L2.51059 -2.48667ZM3.0924 -4.88568C3.16413 -5.15666 3.1721 -5.18057 3.49888 -5.18057H4.37559C5.02914 -5.18057 5.53126 -4.98929 5.53126 -4.3995C5.53126 -4.29589 5.49141 -3.58655 5.04508 -3.14819C4.92553 -3.02864 4.54296 -2.72578 3.76189 -2.72578H2.55044L3.0924 -4.88568Z' id='g5-80'/>
<path d='M7.30461 -6.7188C7.30461 -6.934 7.30461 -7.14919 7.0655 -7.14919S6.8264 -6.934 6.8264 -6.7188V-2.39103C6.8264 -0.597758 4.87771 -0.215193 3.98107 -0.215193C3.44309 -0.215193 2.68991 -0.32279 2.05629 -0.729265C1.13574 -1.31507 1.13574 -2.0802 1.13574 -2.40299V-6.7188C1.13574 -6.934 1.13574 -7.14919 0.896638 -7.14919S0.657534 -6.934 0.657534 -6.7188V-2.34321C0.657534 -0.526027 2.48667 0.263014 3.98107 0.263014C5.53524 0.263014 7.30461 -0.573848 7.30461 -2.33126V-6.7188Z' id='g4-91'/>
<path d='M7.30461 -4.54296C7.30461 -6.36015 5.47547 -7.14919 3.98107 -7.14919C2.4269 -7.14919 0.657534 -6.31233 0.657534 -4.55492V-0.167372C0.657534 0.0478207 0.657534 0.263014 0.896638 0.263014S1.13574 0.0478207 1.13574 -0.167372V-4.49514C1.13574 -6.28842 3.08443 -6.67098 3.98107 -6.67098C4.51905 -6.67098 5.27223 -6.56339 5.90585 -6.15691C6.8264 -5.57111 6.8264 -4.80598 6.8264 -4.48319V-0.167372C6.8264 0.0478207 6.8264 0.263014 7.0655 0.263014S7.30461 0.0478207 7.30461 -0.167372V-4.54296Z' id='g4-92'/>
<path d='M3.68219 -7.04159C3.58655 -7.47198 3.34745 -7.47198 3.07248 -7.47198C2.70187 -7.47198 2.55841 -7.42416 2.47472 -7.04159L0.992279 -0.6934C0.597758 -0.6934 0.32279 -0.6934 0.32279 -0.3467S0.645579 0 0.812951 0H1.96065C2.12802 0 2.45081 0 2.45081 -0.3467S2.16389 -0.6934 1.79328 -0.6934L2.10411 -2.03238H4.04085L4.35168 -0.6934C3.98107 -0.6934 3.69415 -0.6934 3.69415 -0.3467S4.01694 0 4.18431 0H5.332C5.49938 0 5.82217 0 5.82217 -0.3467S5.5472 -0.6934 5.15268 -0.6934L3.68219 -7.04159ZM2.25953 -2.72578C2.34321 -3.08443 3.00075 -5.90585 3.06052 -6.4797H3.07248C3.10834 -6.20473 3.27572 -5.47547 3.27572 -5.46351L3.88543 -2.72578H2.25953Z' id='g1-65'/>
<path d='M1.92478 -3.44309H3.50286C3.50286 -3.02466 3.50286 -2.79751 3.89738 -2.79751C4.27995 -2.79751 4.27995 -3.07248 4.27995 -3.28767V-4.29191C4.27995 -4.5071 4.27995 -4.78207 3.89738 -4.78207C3.50286 -4.78207 3.50286 -4.55492 3.50286 -4.13649H1.92478V-6.61121H4.8538V-6.0254C4.8538 -5.81021 4.8538 -5.53524 5.23636 -5.53524C5.63088 -5.53524 5.63088 -5.79826 5.63088 -6.0254V-6.81445C5.63088 -7.18506 5.55915 -7.30461 5.15268 -7.30461H0.824907C0.657534 -7.30461 0.334745 -7.30461 0.334745 -6.95791S0.657534 -6.61121 0.824907 -6.61121H1.1477V-0.6934H0.824907C0.657534 -0.6934 0.334745 -0.6934 0.334745 -0.3467S0.657534 0 0.824907 0H5.41569C5.81021 0 5.8939 -0.107597 5.8939 -0.490162V-1.45853C5.8939 -1.67372 5.8939 -1.94869 5.51133 -1.94869C5.11681 -1.94869 5.11681 -1.68568 5.11681 -1.45853V-0.6934H1.92478V-3.44309Z' id='g1-69'/>
<path d='M5.26027 -2.5345C5.49938 -2.5345 5.81021 -2.5345 5.81021 -2.8812S5.48742 -3.2279 5.32005 -3.2279H3.98107C3.8137 -3.2279 3.49091 -3.2279 3.49091 -2.8812S3.8137 -2.5345 3.98107 -2.5345H4.47123C4.41146 -1.80523 4.08867 -0.549938 3.10834 -0.549938C2.13998 -0.549938 1.21943 -1.85305 1.21943 -3.64633C1.21943 -5.48742 2.17584 -6.75467 3.1203 -6.75467C3.69415 -6.75467 4.32777 -6.30037 4.48319 -5.10486C4.51905 -4.80598 4.7462 -4.80598 4.86575 -4.80598C5.26027 -4.80598 5.26027 -5.02117 5.26027 -5.26027V-6.99377C5.26027 -7.18506 5.26027 -7.44807 4.92553 -7.44807C4.72229 -7.44807 4.65056 -7.31656 4.61469 -7.25679L4.45928 -6.87422C4.06476 -7.23288 3.58655 -7.44807 3.06052 -7.44807C1.64981 -7.44807 0.442341 -5.83412 0.442341 -3.65828C0.442341 -1.44658 1.66177 0.143462 3.06052 0.143462C3.5746 0.143462 4.07671 -0.071731 4.48319 -0.514072C4.48319 -0.203238 4.48319 0.0239103 4.87771 0.0239103C5.26027 0.0239103 5.26027 -0.227148 5.26027 -0.454296V-2.5345Z' id='g1-71'/>
<path d='M3.467 -6.61121H4.68643C4.8538 -6.61121 5.16463 -6.61121 5.16463 -6.95791S4.8538 -7.30461 4.68643 -7.30461H1.47049C1.30311 -7.30461 0.992279 -7.30461 0.992279 -6.95791S1.30311 -6.61121 1.47049 -6.61121H2.68991V-0.6934H1.47049C1.30311 -0.6934 0.992279 -0.6934 0.992279 -0.3467S1.30311 0 1.47049 0H4.68643C4.8538 0 5.16463 0 5.16463 -0.3467S4.8538 -0.6934 4.68643 -0.6934H3.467V-6.61121Z' id='g1-73'/>
<path d='M3.23985 -4.27995L5.06899 -6.61121C5.41569 -6.61121 5.69066 -6.61121 5.69066 -6.95791S5.37983 -7.30461 5.21245 -7.30461H4.20822C4.04085 -7.30461 3.73001 -7.30461 3.73001 -6.95791S4.04085 -6.61121 4.20822 -6.61121L1.69763 -3.40722V-6.61121H1.93674C2.10411 -6.61121 2.41494 -6.61121 2.41494 -6.95791S2.10411 -7.30461 1.93674 -7.30461H0.789041C0.621669 -7.30461 0.310834 -7.30461 0.310834 -6.95791S0.621669 -6.61121 0.789041 -6.61121H1.02814V-0.6934H0.789041C0.621669 -0.6934 0.310834 -0.6934 0.310834 -0.3467S0.621669 0 0.789041 0H1.93674C2.10411 0 2.41494 0 2.41494 -0.3467S2.10411 -0.6934 1.93674 -0.6934H1.69763V-2.3193L2.78555 -3.7061L4.44732 -0.6934C4.29191 -0.6934 3.98107 -0.6934 3.98107 -0.3467S4.29191 0 4.45928 0H5.32005C5.48742 0 5.79826 0 5.79826 -0.3467S5.51133 -0.6934 5.21245 -0.6934L3.23985 -4.27995Z' id='g1-75'/>
<path d='M2.06824 -6.61121H2.68991C2.85729 -6.61121 3.16812 -6.61121 3.16812 -6.95791S2.85729 -7.30461 2.68991 -7.30461H0.896638C0.729265 -7.30461 0.406476 -7.30461 0.406476 -6.95791S0.729265 -6.61121 0.896638 -6.61121H1.29116V-0.6934H0.896638C0.729265 -0.6934 0.406476 -0.6934 0.406476 -0.3467S0.729265 0 0.896638 0H5.24832C5.64284 0 5.72653 -0.107597 5.72653 -0.490162V-1.47049C5.72653 -1.67372 5.72653 -1.94869 5.34396 -1.94869C4.94944 -1.94869 4.94944 -1.68568 4.94944 -1.47049V-0.6934H2.06824V-6.61121Z' id='g1-76'/>
<path d='M2.23562 -6.89813C2.09215 -7.30461 1.85305 -7.30461 1.60199 -7.30461H0.824907C0.645579 -7.30461 0.3467 -7.30461 0.3467 -6.95791S0.657534 -6.61121 0.824907 -6.61121H1.08792V-0.6934H0.824907C0.657534 -0.6934 0.3467 -0.6934 0.3467 -0.3467S0.645579 0 0.824907 0H2.02042C2.1878 0 2.51059 0 2.51059 -0.3467S2.1878 -0.6934 2.02042 -0.6934H1.75741V-6.4797H1.76936C1.80523 -6.34819 1.91283 -6.03736 2.12802 -5.42765L3.90934 -0.406476C4.0528 0 4.29191 0 4.55492 0C4.91357 0 5.05704 -0.0358655 5.05704 -0.490162V-6.61121H5.32005C5.48742 -6.61121 5.79826 -6.61121 5.79826 -6.95791S5.49938 -7.30461 5.32005 -7.30461H4.12453C3.95716 -7.30461 3.63437 -7.30461 3.63437 -6.95791S3.95716 -6.61121 4.12453 -6.61121H4.38755V-0.824907H4.37559C4.33973 -0.956413 4.23213 -1.26725 4.01694 -1.87696L2.23562 -6.89813Z' id='g1-78'/>
<path d='M5.48742 -3.64633C5.48742 -7.12528 5.23636 -7.44807 3.07248 -7.44807S0.657534 -7.12528 0.657534 -3.65828C0.657534 -0.179328 0.908593 0.143462 3.07248 0.143462S5.48742 -0.179328 5.48742 -3.64633ZM3.07248 -0.549938C1.98456 -0.549938 1.72154 -0.836862 1.59004 -1.3868C1.43462 -1.99651 1.43462 -3.07248 1.43462 -3.75392C1.43462 -4.51905 1.43462 -5.36787 1.56613 -5.94172C1.7335 -6.59925 2.09215 -6.75467 3.07248 -6.75467C4.01694 -6.75467 4.3995 -6.61121 4.56687 -5.97758C4.71034 -5.41569 4.71034 -4.48319 4.71034 -3.75392C4.71034 -3.0127 4.71034 -2.09215 4.57883 -1.44658C4.44732 -0.836862 4.18431 -0.549938 3.07248 -0.549938Z' id='g1-79'/>
<path d='M3.467 -6.61121H5.05704V-6.0254C5.05704 -5.81021 5.05704 -5.53524 5.4396 -5.53524C5.83412 -5.53524 5.83412 -5.79826 5.83412 -6.0254V-6.81445C5.83412 -7.18506 5.76239 -7.30461 5.35592 -7.30461H0.800996C0.406476 -7.30461 0.310834 -7.20897 0.310834 -6.81445V-6.0254C0.310834 -5.81021 0.310834 -5.53524 0.6934 -5.53524C1.08792 -5.53524 1.08792 -5.79826 1.08792 -6.0254V-6.61121H2.68991V-0.6934H2.11606C1.94869 -0.6934 1.63786 -0.6934 1.63786 -0.3467S1.94869 0 2.11606 0H4.04085C4.20822 0 4.51905 0 4.51905 -0.3467S4.20822 -0.6934 4.04085 -0.6934H3.467V-6.61121Z' id='g1-84'/>
<path d='M5.24832 -6.61121H5.57111C5.73848 -6.61121 6.06127 -6.61121 6.06127 -6.95791S5.73848 -7.30461 5.57111 -7.30461H4.14844C3.98107 -7.30461 3.65828 -7.30461 3.65828 -6.95791S3.98107 -6.61121 4.14844 -6.61121H4.47123V-2.49863C4.47123 -1.19552 3.69415 -0.549938 3.07248 -0.549938C2.43885 -0.549938 1.67372 -1.20747 1.67372 -2.49863V-6.61121H1.99651C2.16389 -6.61121 2.48667 -6.61121 2.48667 -6.95791S2.16389 -7.30461 1.99651 -7.30461H0.573848C0.406476 -7.30461 0.0836862 -7.30461 0.0836862 -6.95791S0.406476 -6.61121 0.573848 -6.61121H0.896638V-2.4269C0.896638 -0.980324 1.88892 0.143462 3.07248 0.143462S5.24832 -0.980324 5.24832 -2.4269V-6.61121Z' id='g1-85'/>
<path d='M5.28418 -6.61121C5.65479 -6.61121 5.92976 -6.61121 5.92976 -6.95791S5.61893 -7.30461 5.45156 -7.30461H4.32777C4.1604 -7.30461 3.83761 -7.30461 3.83761 -6.95791S4.12453 -6.61121 4.48319 -6.61121L3.51482 -2.74969C3.3594 -2.13998 3.15616 -1.30311 3.08443 -0.812951H3.07248C3.00075 -1.2792 2.86924 -1.78132 2.74969 -2.27148L1.66177 -6.61121C2.02042 -6.61121 2.30735 -6.61121 2.30735 -6.95791S1.98456 -7.30461 1.81719 -7.30461H0.6934C0.526027 -7.30461 0.215193 -7.30461 0.215193 -6.95791S0.490162 -6.61121 0.848817 -6.61121H0.860772L2.45081 -0.32279C2.55841 0.107597 2.80946 0.107597 3.07248 0.107597S3.5746 0.107597 3.68219 -0.298879L5.28418 -6.61121Z' id='g1-86'/>
<path d='M4.37559 -7.35243C4.48319 -7.79477 4.53101 -7.81868 4.99726 -7.81868H6.55143C7.90237 -7.81868 7.90237 -6.67098 7.90237 -6.56339C7.90237 -5.59502 6.934 -4.36364 5.35592 -4.36364H3.63437L4.37559 -7.35243ZM6.39601 -4.268C7.69913 -4.5071 8.88269 -5.41569 8.88269 -6.51557C8.88269 -7.44807 8.05778 -8.16538 6.70685 -8.16538H2.86924C2.64209 -8.16538 2.5345 -8.16538 2.5345 -7.93823C2.5345 -7.81868 2.64209 -7.81868 2.82142 -7.81868C3.55068 -7.81868 3.55068 -7.72304 3.55068 -7.59153C3.55068 -7.56762 3.55068 -7.49589 3.50286 -7.31656L1.88892 -0.884682C1.78132 -0.466252 1.75741 -0.3467 0.920548 -0.3467C0.6934 -0.3467 0.573848 -0.3467 0.573848 -0.131507C0.573848 0 0.645579 0 0.884682 0H4.98531C6.81445 0 8.22516 -1.3868 8.22516 -2.59427C8.22516 -3.5746 7.36438 -4.17235 6.39601 -4.268ZM4.69838 -0.3467H3.08443C2.91706 -0.3467 2.89315 -0.3467 2.82142 -0.358655C2.68991 -0.37061 2.67796 -0.394521 2.67796 -0.490162C2.67796 -0.573848 2.70187 -0.645579 2.72578 -0.753176L3.56264 -4.12453H5.81021C7.22092 -4.12453 7.22092 -2.80946 7.22092 -2.71382C7.22092 -1.56613 6.18082 -0.3467 4.69838 -0.3467Z' id='g6-66'/>
<path d='M3.53873 -3.80174H5.5472C7.19701 -3.80174 8.84682 -5.02117 8.84682 -6.38406C8.84682 -7.31656 8.05778 -8.16538 6.55143 -8.16538H2.85729C2.63014 -8.16538 2.52254 -8.16538 2.52254 -7.93823C2.52254 -7.81868 2.63014 -7.81868 2.80946 -7.81868C3.53873 -7.81868 3.53873 -7.72304 3.53873 -7.59153C3.53873 -7.56762 3.53873 -7.49589 3.49091 -7.31656L1.87696 -0.884682C1.76936 -0.466252 1.74545 -0.3467 0.908593 -0.3467C0.681445 -0.3467 0.561893 -0.3467 0.561893 -0.131507C0.561893 0 0.669489 0 0.74122 0C0.968369 0 1.20747 -0.0239103 1.43462 -0.0239103H2.83337C3.06052 -0.0239103 3.31158 0 3.53873 0C3.63437 0 3.76588 0 3.76588 -0.227148C3.76588 -0.3467 3.65828 -0.3467 3.47895 -0.3467C2.76164 -0.3467 2.74969 -0.430386 2.74969 -0.549938C2.74969 -0.609714 2.76164 -0.6934 2.7736 -0.753176L3.53873 -3.80174ZM4.3995 -7.35243C4.5071 -7.79477 4.55492 -7.81868 5.02117 -7.81868H6.20473C7.10137 -7.81868 7.84259 -7.53176 7.84259 -6.63512C7.84259 -6.32428 7.68717 -5.30809 7.13724 -4.75816C6.934 -4.54296 6.36015 -4.08867 5.27223 -4.08867H3.58655L4.3995 -7.35243Z' id='g6-80'/>
<path d='M8.06974 -3.87347C8.23711 -3.87347 8.4523 -3.87347 8.4523 -4.08867C8.4523 -4.31582 8.24907 -4.31582 8.06974 -4.31582H1.02814C0.860772 -4.31582 0.645579 -4.31582 0.645579 -4.10062C0.645579 -3.87347 0.848817 -3.87347 1.02814 -3.87347H8.06974ZM8.06974 -1.64981C8.23711 -1.64981 8.4523 -1.64981 8.4523 -1.86501C8.4523 -2.09215 8.24907 -2.09215 8.06974 -2.09215H1.02814C0.860772 -2.09215 0.645579 -2.09215 0.645579 -1.87696C0.645579 -1.64981 0.848817 -1.64981 1.02814 -1.64981H8.06974Z' id='g8-61'/>
<path d='M2.98879 2.98879V2.54645H1.82914V-8.52403H2.98879V-8.96638H1.3868V2.98879H2.98879Z' id='g8-91'/>
<path d='M1.85305 -8.96638H0.251059V-8.52403H1.41071V2.54645H0.251059V2.98879H1.85305V-8.96638Z' id='g8-93'/>
<path d='M2.1599 1.99253V1.6259H1.35492V-5.61096H2.1599V-5.97758H0.988294V1.99253H2.1599Z' id='g7-91'/>
<path d='M1.35492 -5.97758H0.183313V-5.61096H0.988294V1.6259H0.183313V1.99253H1.35492V-5.97758Z' id='g7-93'/>
<path d='M4.63064 -1.80922C4.75816 -1.80922 4.9335 -1.80922 4.9335 -1.99253S4.75816 -2.17584 4.63064 -2.17584H1.07597C1.17958 -3.28369 2.10411 -4.12852 3.31557 -4.12852H4.63064C4.75816 -4.12852 4.9335 -4.12852 4.9335 -4.31183S4.75816 -4.49514 4.63064 -4.49514H3.29166C1.85704 -4.49514 0.70137 -3.37933 0.70137 -1.99253C0.70137 -0.597758 1.86501 0.510087 3.29166 0.510087H4.63064C4.75816 0.510087 4.9335 0.510087 4.9335 0.326775S4.75816 0.143462 4.63064 0.143462H3.31557C2.10411 0.143462 1.17958 -0.70137 1.07597 -1.80922H4.63064Z' id='g3-50'/>
</defs>
<g id='page1' transform='matrix(1.13 0 0 1.13 -63.986 -61.022)'>
<use x='56.4133' xlink:href='#g1-65' y='78.3066'/>
<use x='62.5422' xlink:href='#g1-86' y='78.3066'/>
<use x='68.6712' xlink:href='#g1-65' y='78.3066'/>
<use x='74.8001' xlink:href='#g1-73' y='78.3066'/>
<use x='80.9291' xlink:href='#g1-76' y='78.3066'/>
<rect height='0.3985' width='3.69119' x='87.7962' y='77.9081'/>
<use x='91.4874' xlink:href='#g1-79' y='78.3066'/>
<use x='97.6164' xlink:href='#g1-85' y='78.3066'/>
<use x='103.745' xlink:href='#g1-84' y='78.3066'/>
<use x='110.058' xlink:href='#g8-91' y='78.3066'/>
<use x='113.298' xlink:href='#g6-66' y='78.3066'/>
<use x='122.761' xlink:href='#g8-93' y='78.3066'/>
<use x='129.321' xlink:href='#g8-61' y='78.3066'/>
<use x='141.712' xlink:href='#g1-65' y='78.3066'/>
<use x='147.841' xlink:href='#g1-86' y='78.3066'/>
<use x='153.97' xlink:href='#g1-65' y='78.3066'/>
<use x='160.099' xlink:href='#g1-73' y='78.3066'/>
<use x='166.228' xlink:href='#g1-76' y='78.3066'/>
<rect height='0.3985' width='3.69119' x='173.095' y='77.9081'/>
<use x='176.787' xlink:href='#g1-71' y='78.3066'/>
<use x='182.916' xlink:href='#g1-69' y='78.3066'/>
<use x='189.045' xlink:href='#g1-78' y='78.3066'/>
<use x='195.357' xlink:href='#g8-91' y='78.3066'/>
<use x='198.597' xlink:href='#g6-66' y='78.3066'/>
<use x='208.06' xlink:href='#g8-93' y='78.3066'/>
<use x='213.901' xlink:href='#g4-91' y='78.3066'/>
<use x='226.435' xlink:href='#g2-48' y='54.2764'/>
<use x='226.435' xlink:href='#g2-64' y='75.796'/>
<rect height='0.478187' width='75.7964' x='236.896' y='67.4274'/>
<use x='236.896' xlink:href='#g1-65' y='78.3066'/>
<use x='243.025' xlink:href='#g1-86' y='78.3066'/>
<use x='249.154' xlink:href='#g1-65' y='78.3066'/>
<use x='255.283' xlink:href='#g1-73' y='78.3066'/>
<use x='261.412' xlink:href='#g1-76' y='78.3066'/>
<rect height='0.3985' width='3.69119' x='268.279' y='77.9081'/>
<use x='271.97' xlink:href='#g1-75' y='78.3066'/>
<use x='278.099' xlink:href='#g1-73' y='78.3066'/>
<use x='284.228' xlink:href='#g1-76' y='78.3066'/>
<use x='290.357' xlink:href='#g1-76' y='78.3066'/>
<use x='296.693' xlink:href='#g8-91' y='78.3066'/>
<use x='299.932' xlink:href='#g6-66' y='78.3066'/>
<use x='309.395' xlink:href='#g8-93' y='78.3066'/>
<use x='319.251' xlink:href='#g4-92' y='78.3066'/>
<use x='343.512' xlink:href='#g2-92' y='66.9491'/>
<use x='329.848' xlink:href='#g5-80' y='92.8521'/>
<use x='336.373' xlink:href='#g3-50' y='92.8521'/>
<use x='341.997' xlink:href='#g0-112' y='92.8521'/>
<use x='346.216' xlink:href='#g0-114' y='92.8521'/>
<use x='350.434' xlink:href='#g0-101' y='92.8521'/>
<use x='354.652' xlink:href='#g0-100' y='92.8521'/>
<use x='358.934' xlink:href='#g7-91' y='92.8521'/>
<use x='361.277' xlink:href='#g5-66' y='92.8521'/>
<use x='368.034' xlink:href='#g7-93' y='92.8521'/>
<use x='372.452' xlink:href='#g1-65' y='78.3066'/>
<use x='378.581' xlink:href='#g1-86' y='78.3066'/>
<use x='384.71' xlink:href='#g1-65' y='78.3066'/>
<use x='390.839' xlink:href='#g1-73' y='78.3066'/>
<use x='396.968' xlink:href='#g1-76' y='78.3066'/>
<rect height='0.3985' width='3.69119' x='403.835' y='77.9081'/>
<use x='407.527' xlink:href='#g1-79' y='78.3066'/>
<use x='413.655' xlink:href='#g1-85' y='78.3066'/>
<use x='419.784' xlink:href='#g1-84' y='78.3066'/>
<use x='426.097' xlink:href='#g8-91' y='78.3066'/>
<use x='429.337' xlink:href='#g6-80' y='78.3066'/>
<use x='438.48' xlink:href='#g8-93' y='78.3066'/>
<use x='441.719' xlink:href='#g2-49' y='54.2764'/>
<use x='441.719' xlink:href='#g2-65' y='75.796'/>
</g>
</svg>

Added doc/20190216callframe/availin.svg.



































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?xml version='1.0' encoding='UTF-8'?>
<!-- This file was generated by dvisvgm 1.15.1 -->
<svg height='32.8594pt' version='1.1' viewBox='-0.239051 -0.227989 215.851 32.8594' width='215.851pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
<defs>
<path d='M3.467 -4.52702C3.467 -4.79801 3.3873 -4.86974 3.12428 -4.86974H2.5345C2.40697 -4.86974 2.19178 -4.86974 2.19178 -4.60672S2.40697 -4.34371 2.5345 -4.34371H2.86127V-3.14819C2.49465 -3.43512 2.1599 -3.47497 1.94471 -3.47497C1.06002 -3.47497 0.270984 -2.72578 0.270984 -1.71357C0.270984 -0.74122 0.996264 0.0398506 1.87298 0.0398506C2.29539 0.0398506 2.63014 -0.151432 2.86127 -0.374595C2.86127 -0.151432 2.86127 0 3.20399 0H3.79377C3.9213 0 4.13649 0 4.13649 -0.263014S3.9213 -0.526027 3.79377 -0.526027H3.467V-4.52702ZM2.86127 -1.57011C2.86127 -1.11582 2.49465 -0.486177 1.89689 -0.486177C1.36289 -0.486177 0.876712 -1.0122 0.876712 -1.71357C0.876712 -2.42291 1.40274 -2.94894 1.98456 -2.94894C2.45479 -2.94894 2.86127 -2.54247 2.86127 -2.10411V-1.57011Z' id='g0-100'/>
<path d='M3.40324 -1.49838C3.55467 -1.49838 3.74595 -1.49838 3.74595 -1.80125C3.74595 -2.75766 3.20399 -3.49888 2.17584 -3.49888C1.19552 -3.49888 0.422416 -2.70187 0.422416 -1.72951C0.422416 -0.781071 1.21943 0.0398506 2.30336 0.0398506C3.39527 0.0398506 3.74595 -0.661519 3.74595 -0.860772C3.74595 -1.03611 3.61046 -1.10785 3.44309 -1.10785C3.3076 -1.10785 3.2279 -1.09988 3.14819 -0.924533C2.98879 -0.565878 2.59826 -0.486177 2.34321 -0.486177C1.76139 -0.486177 1.17958 -0.868742 1.05205 -1.49838H3.40324ZM1.06002 -2.01644C1.17958 -2.57435 1.64981 -2.97285 2.17584 -2.97285C2.89315 -2.97285 3.07646 -2.41494 3.12428 -2.01644H1.06002Z' id='g0-101'/>
<path d='M1.68966 1.76936C1.81719 1.76936 2.03238 1.76936 2.03238 1.50635S1.81719 1.24334 1.68966 1.24334H1.36289V-0.334745C1.60996 -0.0956413 1.9208 0.0398506 2.27148 0.0398506C3.15616 0.0398506 3.95318 -0.70934 3.95318 -1.72154C3.95318 -2.68593 3.24384 -3.47497 2.35118 -3.47497C1.97659 -3.47497 1.64981 -3.33948 1.36289 -3.11631C1.36289 -3.43512 1.18755 -3.43512 1.02017 -3.43512H0.430386C0.302864 -3.43512 0.0876712 -3.43512 0.0876712 -3.1721S0.302864 -2.90909 0.430386 -2.90909H0.757161V1.24334H0.430386C0.302864 1.24334 0.0876712 1.24334 0.0876712 1.50635S0.302864 1.76936 0.430386 1.76936H1.68966ZM1.36289 -2.09614C1.36289 -2.55841 1.83313 -2.94894 2.3193 -2.94894C2.87721 -2.94894 3.34745 -2.40697 3.34745 -1.72154C3.34745 -0.996264 2.80548 -0.486177 2.24757 -0.486177C1.65778 -0.486177 1.36289 -1.1477 1.36289 -1.5462V-2.09614Z' id='g0-112'/>
<path d='M1.80125 -1.45853C1.80125 -2.32727 2.42291 -2.94894 3.19601 -2.94894C3.21196 -2.63811 3.43512 -2.57435 3.56264 -2.57435C3.76189 -2.57435 3.92927 -2.71781 3.92927 -2.94894C3.92927 -3.14819 3.7858 -3.47497 3.16413 -3.47497C2.43088 -3.47497 2.0005 -3.05255 1.80125 -2.8533V-3.0924C1.80125 -3.36339 1.72154 -3.43512 1.45853 -3.43512H0.589788C0.478207 -3.43512 0.239103 -3.43512 0.239103 -3.1721S0.478207 -2.90909 0.589788 -2.90909H1.19552V-0.526027H0.589788C0.478207 -0.526027 0.239103 -0.526027 0.239103 -0.263014S0.478207 0 0.589788 0H2.64608C2.7736 0 2.98879 0 2.98879 -0.263014S2.7736 -0.526027 2.64608 -0.526027H1.80125V-1.45853Z' id='g0-114'/>
<path d='M4.37559 -7.35243C4.48319 -7.79477 4.53101 -7.81868 4.99726 -7.81868H6.55143C7.90237 -7.81868 7.90237 -6.67098 7.90237 -6.56339C7.90237 -5.59502 6.934 -4.36364 5.35592 -4.36364H3.63437L4.37559 -7.35243ZM6.39601 -4.268C7.69913 -4.5071 8.88269 -5.41569 8.88269 -6.51557C8.88269 -7.44807 8.05778 -8.16538 6.70685 -8.16538H2.86924C2.64209 -8.16538 2.5345 -8.16538 2.5345 -7.93823C2.5345 -7.81868 2.64209 -7.81868 2.82142 -7.81868C3.55068 -7.81868 3.55068 -7.72304 3.55068 -7.59153C3.55068 -7.56762 3.55068 -7.49589 3.50286 -7.31656L1.88892 -0.884682C1.78132 -0.466252 1.75741 -0.3467 0.920548 -0.3467C0.6934 -0.3467 0.573848 -0.3467 0.573848 -0.131507C0.573848 0 0.645579 0 0.884682 0H4.98531C6.81445 0 8.22516 -1.3868 8.22516 -2.59427C8.22516 -3.5746 7.36438 -4.17235 6.39601 -4.268ZM4.69838 -0.3467H3.08443C2.91706 -0.3467 2.89315 -0.3467 2.82142 -0.358655C2.68991 -0.37061 2.67796 -0.394521 2.67796 -0.490162C2.67796 -0.573848 2.70187 -0.645579 2.72578 -0.753176L3.56264 -4.12453H5.81021C7.22092 -4.12453 7.22092 -2.80946 7.22092 -2.71382C7.22092 -1.56613 6.18082 -0.3467 4.69838 -0.3467Z' id='g5-66'/>
<path d='M3.53873 -3.80174H5.5472C7.19701 -3.80174 8.84682 -5.02117 8.84682 -6.38406C8.84682 -7.31656 8.05778 -8.16538 6.55143 -8.16538H2.85729C2.63014 -8.16538 2.52254 -8.16538 2.52254 -7.93823C2.52254 -7.81868 2.63014 -7.81868 2.80946 -7.81868C3.53873 -7.81868 3.53873 -7.72304 3.53873 -7.59153C3.53873 -7.56762 3.53873 -7.49589 3.49091 -7.31656L1.87696 -0.884682C1.76936 -0.466252 1.74545 -0.3467 0.908593 -0.3467C0.681445 -0.3467 0.561893 -0.3467 0.561893 -0.131507C0.561893 0 0.669489 0 0.74122 0C0.968369 0 1.20747 -0.0239103 1.43462 -0.0239103H2.83337C3.06052 -0.0239103 3.31158 0 3.53873 0C3.63437 0 3.76588 0 3.76588 -0.227148C3.76588 -0.3467 3.65828 -0.3467 3.47895 -0.3467C2.76164 -0.3467 2.74969 -0.430386 2.74969 -0.549938C2.74969 -0.609714 2.76164 -0.6934 2.7736 -0.753176L3.53873 -3.80174ZM4.3995 -7.35243C4.5071 -7.79477 4.55492 -7.81868 5.02117 -7.81868H6.20473C7.10137 -7.81868 7.84259 -7.53176 7.84259 -6.63512C7.84259 -6.32428 7.68717 -5.30809 7.13724 -4.75816C6.934 -4.54296 6.36015 -4.08867 5.27223 -4.08867H3.58655L4.3995 -7.35243Z' id='g5-80'/>
<path d='M11.6085 16.0797C11.6085 16.2351 11.6085 16.7372 12.0986 16.7372C12.6007 16.7372 12.6007 16.2471 12.6007 16.0797V5.70262C12.6007 2.63014 9.98257 0 6.63512 0S0.669489 2.63014 0.669489 5.70262V16.0797C0.669489 16.2351 0.669489 16.7372 1.15965 16.7372C1.66177 16.7372 1.66177 16.2471 1.66177 16.0797V5.76239C1.66177 3.02466 3.96912 0.992279 6.63512 0.992279S11.6085 3.03661 11.6085 5.76239V16.0797Z' id='g2-92'/>
<path d='M2.1599 1.99253V1.6259H1.35492V-5.61096H2.1599V-5.97758H0.988294V1.99253H2.1599Z' id='g6-91'/>
<path d='M1.35492 -5.97758H0.183313V-5.61096H0.988294V1.6259H0.183313V1.99253H1.35492V-5.97758Z' id='g6-93'/>
<path d='M1.34695 -0.629639C1.27522 -0.326775 1.25928 -0.263014 0.669489 -0.263014C0.518057 -0.263014 0.422416 -0.263014 0.422416 -0.111582C0.422416 0 0.526027 0 0.661519 0H3.61843C4.9335 0 5.91382 -0.932503 5.91382 -1.7056C5.91382 -2.28742 5.41171 -2.75766 4.61469 -2.84533C5.53923 -3.02067 6.33624 -3.6264 6.33624 -4.32777C6.33624 -4.92553 5.75442 -5.44359 4.75019 -5.44359H1.96862C1.82516 -5.44359 1.72154 -5.44359 1.72154 -5.29215C1.72154 -5.18057 1.81719 -5.18057 1.95268 -5.18057C2.21569 -5.18057 2.44682 -5.18057 2.44682 -5.05305C2.44682 -5.02117 2.43885 -5.0132 2.41494 -4.90959L1.34695 -0.629639ZM2.59029 -2.94097L3.07646 -4.88568C3.14819 -5.15666 3.15616 -5.18057 3.48294 -5.18057H4.63064C5.41171 -5.18057 5.58705 -4.67049 5.58705 -4.34371C5.58705 -3.66625 4.86177 -2.94097 3.84159 -2.94097H2.59029ZM2.04035 -0.263014C1.96862 -0.278954 1.94471 -0.278954 1.94471 -0.334745C1.94471 -0.398506 1.96065 -0.462267 1.97659 -0.510087L2.5345 -2.71781H4.15243C4.89365 -2.71781 5.14072 -2.21569 5.14072 -1.76936C5.14072 -0.988294 4.37559 -0.263014 3.41918 -0.263014H2.04035Z' id='g4-66'/>
<path d='M2.51059 -2.48667H3.96115C5.10884 -2.48667 6.30436 -3.28369 6.30436 -4.22416C6.30436 -4.90162 5.66675 -5.44359 4.63861 -5.44359H1.95268C1.80922 -5.44359 1.7056 -5.44359 1.7056 -5.29215C1.7056 -5.18057 1.80922 -5.18057 1.93674 -5.18057C2.19975 -5.18057 2.43088 -5.18057 2.43088 -5.05305C2.43088 -5.02117 2.42291 -5.0132 2.399 -4.90959L1.33101 -0.629639C1.25928 -0.334745 1.24334 -0.263014 0.67746 -0.263014C0.494147 -0.263014 0.406476 -0.263014 0.406476 -0.111582C0.406476 -0.0797011 0.430386 0 0.533998 0C0.68543 0 0.876712 -0.0159402 1.02814 -0.0239103H1.53823C2.30336 -0.0239103 2.51059 0 2.56638 0C2.6142 0 2.72578 0 2.72578 -0.151432C2.72578 -0.263014 2.62217 -0.263014 2.48667 -0.263014C2.46276 -0.263014 2.3193 -0.263014 2.18381 -0.278954C2.01644 -0.294894 2.0005 -0.318804 2.0005 -0.390535C2.0005 -0.430386 2.01644 -0.478207 2.02441 -0.518057L2.51059 -2.48667ZM3.0924 -4.88568C3.16413 -5.15666 3.1721 -5.18057 3.49888 -5.18057H4.37559C5.02914 -5.18057 5.53126 -4.98929 5.53126 -4.3995C5.53126 -4.29589 5.49141 -3.58655 5.04508 -3.14819C4.92553 -3.02864 4.54296 -2.72578 3.76189 -2.72578H2.55044L3.0924 -4.88568Z' id='g4-80'/>
<path d='M3.68219 -7.04159C3.58655 -7.47198 3.34745 -7.47198 3.07248 -7.47198C2.70187 -7.47198 2.55841 -7.42416 2.47472 -7.04159L0.992279 -0.6934C0.597758 -0.6934 0.32279 -0.6934 0.32279 -0.3467S0.645579 0 0.812951 0H1.96065C2.12802 0 2.45081 0 2.45081 -0.3467S2.16389 -0.6934 1.79328 -0.6934L2.10411 -2.03238H4.04085L4.35168 -0.6934C3.98107 -0.6934 3.69415 -0.6934 3.69415 -0.3467S4.01694 0 4.18431 0H5.332C5.49938 0 5.82217 0 5.82217 -0.3467S5.5472 -0.6934 5.15268 -0.6934L3.68219 -7.04159ZM2.25953 -2.72578C2.34321 -3.08443 3.00075 -5.90585 3.06052 -6.4797H3.07248C3.10834 -6.20473 3.27572 -5.47547 3.27572 -5.46351L3.88543 -2.72578H2.25953Z' id='g1-65'/>
<path d='M3.467 -6.61121H4.68643C4.8538 -6.61121 5.16463 -6.61121 5.16463 -6.95791S4.8538 -7.30461 4.68643 -7.30461H1.47049C1.30311 -7.30461 0.992279 -7.30461 0.992279 -6.95791S1.30311 -6.61121 1.47049 -6.61121H2.68991V-0.6934H1.47049C1.30311 -0.6934 0.992279 -0.6934 0.992279 -0.3467S1.30311 0 1.47049 0H4.68643C4.8538 0 5.16463 0 5.16463 -0.3467S4.8538 -0.6934 4.68643 -0.6934H3.467V-6.61121Z' id='g1-73'/>
<path d='M2.06824 -6.61121H2.68991C2.85729 -6.61121 3.16812 -6.61121 3.16812 -6.95791S2.85729 -7.30461 2.68991 -7.30461H0.896638C0.729265 -7.30461 0.406476 -7.30461 0.406476 -6.95791S0.729265 -6.61121 0.896638 -6.61121H1.29116V-0.6934H0.896638C0.729265 -0.6934 0.406476 -0.6934 0.406476 -0.3467S0.729265 0 0.896638 0H5.24832C5.64284 0 5.72653 -0.107597 5.72653 -0.490162V-1.47049C5.72653 -1.67372 5.72653 -1.94869 5.34396 -1.94869C4.94944 -1.94869 4.94944 -1.68568 4.94944 -1.47049V-0.6934H2.06824V-6.61121Z' id='g1-76'/>
<path d='M2.23562 -6.89813C2.09215 -7.30461 1.85305 -7.30461 1.60199 -7.30461H0.824907C0.645579 -7.30461 0.3467 -7.30461 0.3467 -6.95791S0.657534 -6.61121 0.824907 -6.61121H1.08792V-0.6934H0.824907C0.657534 -0.6934 0.3467 -0.6934 0.3467 -0.3467S0.645579 0 0.824907 0H2.02042C2.1878 0 2.51059 0 2.51059 -0.3467S2.1878 -0.6934 2.02042 -0.6934H1.75741V-6.4797H1.76936C1.80523 -6.34819 1.91283 -6.03736 2.12802 -5.42765L3.90934 -0.406476C4.0528 0 4.29191 0 4.55492 0C4.91357 0 5.05704 -0.0358655 5.05704 -0.490162V-6.61121H5.32005C5.48742 -6.61121 5.79826 -6.61121 5.79826 -6.95791S5.49938 -7.30461 5.32005 -7.30461H4.12453C3.95716 -7.30461 3.63437 -7.30461 3.63437 -6.95791S3.95716 -6.61121 4.12453 -6.61121H4.38755V-0.824907H4.37559C4.33973 -0.956413 4.23213 -1.26725 4.01694 -1.87696L2.23562 -6.89813Z' id='g1-78'/>
<path d='M5.48742 -3.64633C5.48742 -7.12528 5.23636 -7.44807 3.07248 -7.44807S0.657534 -7.12528 0.657534 -3.65828C0.657534 -0.179328 0.908593 0.143462 3.07248 0.143462S5.48742 -0.179328 5.48742 -3.64633ZM3.07248 -0.549938C1.98456 -0.549938 1.72154 -0.836862 1.59004 -1.3868C1.43462 -1.99651 1.43462 -3.07248 1.43462 -3.75392C1.43462 -4.51905 1.43462 -5.36787 1.56613 -5.94172C1.7335 -6.59925 2.09215 -6.75467 3.07248 -6.75467C4.01694 -6.75467 4.3995 -6.61121 4.56687 -5.97758C4.71034 -5.41569 4.71034 -4.48319 4.71034 -3.75392C4.71034 -3.0127 4.71034 -2.09215 4.57883 -1.44658C4.44732 -0.836862 4.18431 -0.549938 3.07248 -0.549938Z' id='g1-79'/>
<path d='M3.467 -6.61121H5.05704V-6.0254C5.05704 -5.81021 5.05704 -5.53524 5.4396 -5.53524C5.83412 -5.53524 5.83412 -5.79826 5.83412 -6.0254V-6.81445C5.83412 -7.18506 5.76239 -7.30461 5.35592 -7.30461H0.800996C0.406476 -7.30461 0.310834 -7.20897 0.310834 -6.81445V-6.0254C0.310834 -5.81021 0.310834 -5.53524 0.6934 -5.53524C1.08792 -5.53524 1.08792 -5.79826 1.08792 -6.0254V-6.61121H2.68991V-0.6934H2.11606C1.94869 -0.6934 1.63786 -0.6934 1.63786 -0.3467S1.94869 0 2.11606 0H4.04085C4.20822 0 4.51905 0 4.51905 -0.3467S4.20822 -0.6934 4.04085 -0.6934H3.467V-6.61121Z' id='g1-84'/>
<path d='M5.24832 -6.61121H5.57111C5.73848 -6.61121 6.06127 -6.61121 6.06127 -6.95791S5.73848 -7.30461 5.57111 -7.30461H4.14844C3.98107 -7.30461 3.65828 -7.30461 3.65828 -6.95791S3.98107 -6.61121 4.14844 -6.61121H4.47123V-2.49863C4.47123 -1.19552 3.69415 -0.549938 3.07248 -0.549938C2.43885 -0.549938 1.67372 -1.20747 1.67372 -2.49863V-6.61121H1.99651C2.16389 -6.61121 2.48667 -6.61121 2.48667 -6.95791S2.16389 -7.30461 1.99651 -7.30461H0.573848C0.406476 -7.30461 0.0836862 -7.30461 0.0836862 -6.95791S0.406476 -6.61121 0.573848 -6.61121H0.896638V-2.4269C0.896638 -0.980324 1.88892 0.143462 3.07248 0.143462S5.24832 -0.980324 5.24832 -2.4269V-6.61121Z' id='g1-85'/>
<path d='M5.28418 -6.61121C5.65479 -6.61121 5.92976 -6.61121 5.92976 -6.95791S5.61893 -7.30461 5.45156 -7.30461H4.32777C4.1604 -7.30461 3.83761 -7.30461 3.83761 -6.95791S4.12453 -6.61121 4.48319 -6.61121L3.51482 -2.74969C3.3594 -2.13998 3.15616 -1.30311 3.08443 -0.812951H3.07248C3.00075 -1.2792 2.86924 -1.78132 2.74969 -2.27148L1.66177 -6.61121C2.02042 -6.61121 2.30735 -6.61121 2.30735 -6.95791S1.98456 -7.30461 1.81719 -7.30461H0.6934C0.526027 -7.30461 0.215193 -7.30461 0.215193 -6.95791S0.490162 -6.61121 0.848817 -6.61121H0.860772L2.45081 -0.32279C2.55841 0.107597 2.80946 0.107597 3.07248 0.107597S3.5746 0.107597 3.68219 -0.298879L5.28418 -6.61121Z' id='g1-86'/>
<path d='M8.06974 -3.87347C8.23711 -3.87347 8.4523 -3.87347 8.4523 -4.08867C8.4523 -4.31582 8.24907 -4.31582 8.06974 -4.31582H1.02814C0.860772 -4.31582 0.645579 -4.31582 0.645579 -4.10062C0.645579 -3.87347 0.848817 -3.87347 1.02814 -3.87347H8.06974ZM8.06974 -1.64981C8.23711 -1.64981 8.4523 -1.64981 8.4523 -1.86501C8.4523 -2.09215 8.24907 -2.09215 8.06974 -2.09215H1.02814C0.860772 -2.09215 0.645579 -2.09215 0.645579 -1.87696C0.645579 -1.64981 0.848817 -1.64981 1.02814 -1.64981H8.06974Z' id='g7-61'/>
<path d='M2.98879 2.98879V2.54645H1.82914V-8.52403H2.98879V-8.96638H1.3868V2.98879H2.98879Z' id='g7-91'/>
<path d='M1.85305 -8.96638H0.251059V-8.52403H1.41071V2.54645H0.251059V2.98879H1.85305V-8.96638Z' id='g7-93'/>
<path d='M4.63064 -1.80922C4.75816 -1.80922 4.9335 -1.80922 4.9335 -1.99253S4.75816 -2.17584 4.63064 -2.17584H1.07597C1.17958 -3.28369 2.10411 -4.12852 3.31557 -4.12852H4.63064C4.75816 -4.12852 4.9335 -4.12852 4.9335 -4.31183S4.75816 -4.49514 4.63064 -4.49514H3.29166C1.85704 -4.49514 0.70137 -3.37933 0.70137 -1.99253C0.70137 -0.597758 1.86501 0.510087 3.29166 0.510087H4.63064C4.75816 0.510087 4.9335 0.510087 4.9335 0.326775S4.75816 0.143462 4.63064 0.143462H3.31557C2.10411 0.143462 1.17958 -0.70137 1.07597 -1.80922H4.63064Z' id='g3-50'/>
</defs>
<g id='page1' transform='matrix(1.13 0 0 1.13 -63.986 -61.0251)'>
<use x='56.4133' xlink:href='#g1-65' y='66.3512'/>
<use x='62.5422' xlink:href='#g1-86' y='66.3512'/>
<use x='68.6712' xlink:href='#g1-65' y='66.3512'/>
<use x='74.8001' xlink:href='#g1-73' y='66.3512'/>
<use x='80.9291' xlink:href='#g1-76' y='66.3512'/>
<rect height='0.3985' width='3.69119' x='87.7962' y='65.9528'/>
<use x='91.4874' xlink:href='#g1-73' y='66.3512'/>
<use x='97.6164' xlink:href='#g1-78' y='66.3512'/>
<use x='103.906' xlink:href='#g7-91' y='66.3512'/>
<use x='107.146' xlink:href='#g5-66' y='66.3512'/>
<use x='116.609' xlink:href='#g7-93' y='66.3512'/>
<use x='123.169' xlink:href='#g7-61' y='66.3512'/>
<use x='149.225' xlink:href='#g2-92' y='54.9938'/>
<use x='135.561' xlink:href='#g4-80' y='80.8968'/>
<use x='142.085' xlink:href='#g3-50' y='80.8968'/>
<use x='147.71' xlink:href='#g0-112' y='80.8968'/>
<use x='151.928' xlink:href='#g0-114' y='80.8968'/>
<use x='156.147' xlink:href='#g0-101' y='80.8968'/>
<use x='160.365' xlink:href='#g0-100' y='80.8968'/>
<use x='164.647' xlink:href='#g6-91' y='80.8968'/>
<use x='166.99' xlink:href='#g4-66' y='80.8968'/>
<use x='173.747' xlink:href='#g6-93' y='80.8968'/>
<use x='178.165' xlink:href='#g1-65' y='66.3512'/>
<use x='184.294' xlink:href='#g1-86' y='66.3512'/>
<use x='190.423' xlink:href='#g1-65' y='66.3512'/>
<use x='196.552' xlink:href='#g1-73' y='66.3512'/>
<use x='202.681' xlink:href='#g1-76' y='66.3512'/>
<rect height='0.3985' width='3.69119' x='209.548' y='65.9528'/>
<use x='213.239' xlink:href='#g1-79' y='66.3512'/>
<use x='219.368' xlink:href='#g1-85' y='66.3512'/>
<use x='225.497' xlink:href='#g1-84' y='66.3512'/>
<use x='231.81' xlink:href='#g7-91' y='66.3512'/>
<use x='235.05' xlink:href='#g5-80' y='66.3512'/>
<use x='244.192' xlink:href='#g7-93' y='66.3512'/>
</g>
</svg>

Added doc/20190216callframe/callframe.md.





















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
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
271
272
273
274
275
276
277
278
279
280
281
282
283
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
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
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
408
409
410
411
412
413
414
415
416
417
418
419
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
463
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
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
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
567
568
569
570
571
572
573
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
# Optimizing data motion into and out of callframes in Tcl

Kevin B Kenny


## Introduction

As of the current version ([0718166269]), the handling of variables in
the callframe reflects some fairly fundamental oversights in the effect of
Tcl operations on variables. Essentially, what it does is to introduce
`moveToCallFrame` and `moveToCallFrame` operations around a partial
subset of operations that might change or refer to a variable in a
callframe. This subset includes command invocations that are known to
access caller variables, assignments to potentially-aliased variables,
some direct operations, and very little else. It fails to account for
all the operations, while simultaneously introducing unnecessary data
motion. It also forecloses on optimizations such as deferring writes
to non-local variables to loop exits.

This discussion is written at least partly for the benefit of its
author, to help with understanding what optimizations are safe and
profitable, and how to compute them. It will, however, hopefully aid
those who come after in understanding how the the decisions that were
made.

### Back to basics - the code generation strategy

One general strategy has been overwhelmingly successful in other areas
of quadcode manipulation. Rather than attempting to add operations
that handle the awkward cases when they are detected, it has been much
easier to generate code for the worst case always, and then optimize
it away. The code for variable accesses, for instance, is truly
horrific when initially generated:

  + test that a variable exists, and throw an error otherwise
  
  + test that the variable is not an array, and throw an error
    otherwise.
	
  + test that the value is of an admissible type for the operation
    that will use it, and throw an error otherwise.
	
  + downcast the value to an instance of the correct type.
  
  + if the value is used in an arithmetic operation, purify the value,
    that is, extract the machine-native representation.

Nevertheless, all of these tests become redundant if a second access
to the variable is dominated by the first. In that case, partial
redundancy elimination will eliminate all five of these steps and
simply use the pure value in the arithmetic operation. The partial
redundancy elimination is based largely on the value-based algorithms
developed in \[SIMP96\].

We therefore assume here that we will take the brutally simple
approach of generating code that:

  + whenever a local variable (whether potentially aliased or not) is
    loaded, generate a `moveFromCallFrame` instruction transferring a
	Tcl value into an SSA value.
	
  + whenever a local variable (whether potientially aliased or not) is
    stored, generate a `moveToCallFrame` instruction transferring an
    SSA value into a Tcl value.
	
  + whenever an operation (an invocation, a direct operation, etc.)
    may potentially refer to a local variable or an alias
    thereof. make sure that it has the callframe as one of its inputs.
	
  + whenever an operation (an invocation, a direct operation, etc.)
    may potentially modify a local variable or an alias thereof,
	make sure that it has the callframe as both an input and an
    output.
	
  + upon procedure exit (normal or abnormal) make sure that any
    potentially aliased local variables are actually returned to the
    callframe. 

The last three items in the list ensure that we can track
antidependencies correctly; they become dependencies on the callframe
value. This, in turn, will require that we modify the `directSet`,
`directGet`, `directIncr`, etc. instructions, to include callframe
references. (This change will also address a set of issues marked with
**TODO** in `quadcode/translate.tcl` where it is assumed that the
`existStk`, `loadStk`, `storeStk`, etc. bytecode instructions refer
only to qualified names.)

Simpson mentions fairly briefly how memory load operations (he uses
the example of array accesses, but our `moveFromCallFrame`
fits the scheme) can also be eliminated by his techniques. The
treatment is considerly less well developed than that for simple
values. Moreover, he calls out that memory store operations are not
amenable to his technique owing to anti-dependencies (a STORE
operation may not be hoisted above a LOAD operation that might refer
to the same memory). His technique also does not contemplate downward
code motion, where a STORE operation that does not affect a loop's
operation might be moved to after the loop exit. To address these
deficiencies, it falls to us to develop a better theory of Tcl
variable accesses.

### Trace semantics

As soon as we get into discussion of non-local variables, the question
of traces comes up. In this particular writeup, a very limited concept
of traces is admitted:

  * We assume that any traces present are 'well behaved' in the sense
    that they do not invalidate the compilation (for instance, by
    redefining or changing the resolution of compiled commands,
	creating new aliases among local variables or changing their
    values).
	
  * We assume that skipping traces is permissible to a limited
    extent. In particular, repeated writes to the same variable may
    fire only a trace for the last write, while repeated reads may
    fire only a single read trace. We do, however, respect the
    ordering among reads or writes; a procedure that reads a variable,
    changes its value, and puts it back will fire a read trace and a
    write trace in the correct sequence. We also promise that any read
    trace will fire at a time when all prior writes have been traced.
	
These constraints are weak enough that many loop-invariant reads
and writes can be optimized away. For instance, a procedure that
repeatedly reads the same global value in a loop can fire a trace only
for the first read, and one that accumulates a result through multiple
writes of the same value can defer the write until after the
loop. They nevertheless are strong enough that the common cases (the
read trace on `::env`, and the write traces on variables that appear
in Tk user interfaces) will work - and, in fact, may avoid needless
work relative to interpreted code.

### Types of optimization to be considered

The particular optimizations considered in this document all consist
of eliminating code motion to and from the callframe. There are a
number of these that we will attempt to cover:

  * Dead LOAD - An instruction moves a value from the callframe, but
    the result is not used anywhere in the program. This case should
    already be covered by the dead code analysis in quadcode.
	
  * LOAD-LOAD - An instruction moves a value from the callframe, and
    an earlier instruction has already put the Tcl value into an
    SSA value. It can be proven that the value in the callframe has
    not changed, so the second move can be eliminated.
	
  * STORE-LOAD - An instruction moves a value from the callframe, and
    an earlier instruction has moved an SSA value into the callframe.
	It can be proven that the value in the callframe has not changed.
	The move from the callframe can be eliminated.
	
  * Loop-invariant LOAD - An instruction inside a loop moves a
    value from the callframe, and it can be proven that nothing inside
	the loop alters the value. The move from the callframe can be
	hoisted to before the start of the loop. (Note that in this
	case, partial redundancy elimination actually works by creating
	a second move outside the loop, and reducing the optimization to
	the LOAD-LOAD case.)
	
  * Dead STORE - An instruction moves a value to the callframe, but
    the variable in the callframe is not aliased and is not referred
	to again before procedure exit.
	
  * LOAD-STORE - An instruction moves a value to the callframe, but
    the value came from an earlier move from the same place in the
    callframe, and it can be proven that the value has not changed.
	The move to the callframe can be eliminated.
	
  * STORE-STORE - An instruction moves a value to the callframe, and
    there is a _later_ instruction on each code path that moves a
    value to the same place in the callframe, and nothing in between
    the two instructions might read the value. It is safe to eliminate
    the first store.
	
  * Loop invariant STORE - An instruction withing a loop moves a value
    to the callframe, and nothing inside the loop loads the value.
    (This condition will commonly be introduced by STORE-LOAD
    elimination.) In this case, the STORE may be pushed to after the
    loop exit(s). It is expected that it will be simplest to introduce
	speculative move instructions at each loop exit, which will then
	cause STORE-STORE optimization to eliminate the move inside the
    loop. (It is possible that some of the speculative instructions
    can then be optimized away by other means.)

From among these, it is useful to separate those requiring
_anterograde_ analysis (proceeding from a procedure's entry to its
exits) from those requiring _retrograde_ analysis (proceeding from the
procedure exits to the entry). LOAD-LOAD, STORE-LOAD, loop-invariant
LOAD, and LOAD-STORE are all anterograde. They depend on the
availability of SSA counterparts to callframe values at a particular
point in the program and on whether the use of a value in the
callframe can be anticipated at a given point in the program.
By contrast, dead-LOAD, dead-STORE, STORE-STORE, and loop-invariant
STORE are retrograde. They depend on whether it is true that all paths
forward to the program exit will contain a move to the callframe or a
use of a callframe value, or whether some path contains a reference to
a callframe value.

The pass structure of the two types of analysis is different. While
the 'iterate to convergence' structure would allow visiting the blocks
of a program in any order, performance demands that anterograde
analysis visit dominators before the blocks that they dominate, while
retrograde analysis visits postdominators before the blocks that they
postdominate. With that ordering, a given iteration to convergence
will require only a number of passes proportional to the loop nesting
depth.

## TASK 1: Availability analysis

The first part of anterograde analysis will begin with developing the
set of callframe values that are known to be available as SSA values.
This involves looking at the instructions of a block in order, and
accumulating the mapping of name and callframe instance to SSA value.

Initially, the available set on exit from each block is empty.

We iterate through a basic block, applying the following
rules. Initially, the set of available values is the set from the
block's dominator, or Ø if the block is the entry block or unreachable.

+ `entry` - All variables listed on the instruction acquire `Nothing` as
  their values.

+ `moveFromCallFrame` - The result of the instruction becomes the
  SSA value corresponding to the given variable name in the given
  callframe.

+ `moveToCallFrame` - The name-value mapping in the result callframe
  is set up as follows:
  
  + The available values in the source callframe become available
    values in the destination callframe.
	
  + For each name specified in the instruction from left to right, the
    available value for the name becomes the corresponding value in
    the instruction, and all other names that potentially alias the
	given name lose their values.
	
+ `invoke[Expanded]` - The available values in the source callframe
  become available in the destination callframe.  Then, any names that the
  invoked command might change and any names that might alias them,
  lose their available values.
  
+ `extractCallframe` - The available values in the source callframe
  become available in the destination callframe.

+ `directSet` etc. - Any name that might be an alias of the changing
  variable loses its available value. (If the changing variable name
  cannot be determined, all names might be aliases, because in this
  case we cannot determine that the name is fully qualified.)
  
+ `variable`, `upvar`, `nsupvar` - Any existing value for the given
  name and any possible alias thereof is no longer available. Note
  that this is actually a program error, but we need to retain correct
  behaviour in the case where the error is caught.
  
+ φ - If several callframes meet at a φ, the set of names that have
  available values will be the intersection of the available sets of
  the input callframes. For each name in that intersection:
  
  + If all the incoming values are the same, that value becomes the value of
    the name in the result callframe. 
  
  + If values are different, then we find the available values for each
    name on exit from the predecessor blocks, and construct a φ
    instruction that combines them. We search for a φ that combines
    them.
  
    + If such a φ is found, its result is the new value for the given
      name. 
  
    + If no such φ is found, we insert such a φ speculatively into the
      header of the block, and give its result as the value for the
      given name.
  
At the end of the block, after applying these rules, we have the
block's new available set. The calculation of this set may in turn
change the available values on φ instructions at the start of loops,
so the calculation must be applied to convergence over all blocks in
the program.

Those who are versed in formal data flow analysis are welcome to
separate the descriptions of the operations given above into separate
sets `AVAIL\_GEN` and `AVAIL\_KILL` so that the problem can be given as
the forward analysis:

![\texttt{AVAIL\_OUT}[B] = \texttt{AVAIL\_GEN}[B] 
~ \cup ~ \left( 
\overline{\texttt{AVAIL\_KILL}[B]} 
~ \cap \bigcap_{P\in \texttt{pred}[B]} \texttt{AVAIL\_OUT}[P] 
\right) 
](./avail.svg)

This separation will be made in the code if it turns out that it
enables combining of passes with other callframe optimizations.


### Availability analysis: implications

Calculating the available values already exposes opportunities for
optimization. In particular, LOAD-LOAD and STORE-LOAD redundancies can
be eliminated by checking each `moveFromCallFrame` operation in turn
for whether it is accessing an available value. If it is, it is
eliminated and its result is replaced with the available value.

### Availability analysis: equivalence sets

LOAD-STORE pairs can also be detected, by examining `moveToCallFrame`
instructions and eliminating them if the variable being written is
available, and known to be equal to the Tcl value in the callframe.

Therefore, in the availability analysis, as well as accumulating the
sets of available Tcl values and the names in the callframe that
correspond to them, we must track the sets of names in a given
callframe that correspond correspond to each SSA value. That way, 
when we examine a `moveToCallFrame` instruction, we can detect
that the given value is already in the callframe under the given name.

## TASK 2: Live Tcl value analysis

The first part of retrograde analysis needs to compute the sets of Tcl
variables whose values are possibly needed at the entry to each block
in the program. This analysis involves examining the instructions of
the block in _reverse_ order (that is, visiting postdominators before
the blocks that they postdominate)  and accumulating the sets of needed
values.

Initially, the required set at each block is empty.

When beginning to examine a block, if the block is an exit, then the
set of required variables is the set of local variables that may be
aliased (by virtue of appearing in `[upvar]`, `[namespace
upvar]/[global]`, or `[variable]`. This assertion mirrors the
requirement that a compiled procedure must have all the nonlocal
variables in sync when it leaves. The set is marked as being relative
to the input callframe of the `return` instruction.

If a block is not an exit block, then the set of required variables is
the union of the sets of variables required at the entry to its
successors. If a successor contains a φ operation that produces the
callframe to which the variable references refer, then the callframe
reference of each variable is updated to the appropriate input to the 
φ.

Then, back to front, the sets get updated by examining individual
instructions:

+ `moveFromCallFrame` - The given variable, and all possible aliases
  are added to the set of variables whose values are required.
  
+ `moveToCallFrame` - The variables required will be relative to the 
  input callframe. Starting with the set of variables required in the
  output callframe, we examine the variables given in the instruction
  from left to right. For each of those, the given variable is removed 
  from the set of variables whose values are required. All possible
  aliases of the given variable are added to the set.
  
+ `invoke[expanded]` - The variables required will be relative to the
  input callframe. We start with the set required relative to the
  output callframe. All variables that may be read or written, and
  all possible aliases, are added to the set. (Since we do not in
  general examine whether a procedure must alter a given variable,
  but only whether it may alter it, we require in general that the
  previous value of the variable must already be in sync.)
  
+ `extractCallframe` - The variables required in the source callframe
  are precisely those anticipated in the destination callframe.

+ `directGet` etc. - The variables required will be relative to the
  input callframe. We start with the set required relative to the
  output callframe. Any variable that might alias the variable being
  retrieved or set in the instruction is added to the set.
  
+ `variable`, `upvar`, `nsupvar` - The variables required will be
  relative to the input callframe. We start with the set required
  relative to the output callframe. The target variable and any
  possible aliases are added to the set.

+ φ - Analysis stops at a φ instruction that references a callframe.
  The translation to the correct input callframe will happen when
  analyzing the predecessor block, as noted above.
  
When we arrive at a loop's entry, we may produce a greater set of
values that must be in sync at the bottom of the loop, so just as with
the availability analysis, the liveness analysis must be iterated to
convergence.

### Liveness analysis: implications

When liveness analysis is complete, it informs removal of certain
`moveToCallFrame` instructions. Any `moveToCallFrame` instruction that
designates a variable that is not live in the given callframe may be
safely removed. Either it is a dead STORE (that is, neither it nor
any potential alias will ever be accessed again), or it participates
in a STORE-STORE pair. 

## TASK 3: Anticipability analysis and loop-invariant loads

With what has been developed in Tasks 1 and 2, we can get rid of
locally redundant `moveToCallFrame` and `moveFromCallFrame`
instructions. What remains is to attack loop-invariant ones: that is,
`moveFromCallFrame` that can be safely moved above a loop or
`moveToCallFrame` that can be safely be moved below. We use a plan of
attack based loosely on \[DREC93\].

### Anticipability

We already have the concept of _availability,_ developed in
Task 1. Let us introduce some notation for available values.
`AVAIL_OUT[B]` will be notation for the set of ordered pairs
(_cf_. _name_) available in SSA registers on exit from block `B` of
the program. (In the pairs, _cf_ names an SSA variable designating a
callframe, and _name_ is the name of a variable in that frame.
Similarly, `AVAIL_IN[B]`will be the set of (_cf_, _name_) pairs
available on entry to block `B`, and we know that

![\texttt{AVAIL\_IN}[B] =  
\bigcap_{P\in \texttt{pred}[B]} \texttt{AVAIL\_OUT}[P] 
\right)](./availin.svg)

(This discussion glosses over the fact that the callframe reference
must be translated every time that it passes through a φ instruction.
The translation is straightforward - for the intersection above, the
available value will be the output of the phi; for the anticipability
analysis below, the anticipable value will be the input of the phi on
the code path being analyzed.)

Availability by itself is not sufficient for loop-invariant code
motion. In addition, we need the concept of _anticipability_. A (_cf_,
_name_) pair is _anticipable_ at a given point in the program if every
execution path forward from that point contains a `moveFromCallFrame`
retrieving that value prior to the value's being modified.

Calculating anticipability requires multiple traversals of the program
in postdominator order. Nothing is anticipable on `return`. For blocks
that do not return, we begin by taking the intersection of values
anticipable at their successors:

![\texttt{ANTIC\_OUT}[B] =  
\bigcap_{P\in \texttt{succ}[B]} \texttt{ANTIC\_IN}[P] 
\right)](./anticout.svg)

(Note that in computing this function, we translate the callframe
reference if it appears in a φ operation at the start of the block.)

and then traverse the instructions of the block in reverse order.

+ `moveFromCallFrame` - The given name and callframe reference become
  anticipable.

+ `moveToCallFrame` - The given name and callframe reference, if they
  are anticipable, are removed from the anticipable set, along with
  any names that might potentially be aliases of the given name .This
  becomes the anticipable set for the input callframe. The output
  callframe is no longer relevant and may be forgotten.
  
+ `invoke[Expanded]` - Any variables potentially modified by the
  invoked command, and any potential aliases, are removed from the
  anticipable set, and the new set becomes the anticipable set for the
  input callframe. The output callframe is no longer relevant and may
  be forgotten.

+ `extractCallFrame` - The store operations anticipated in the source
  callframe are precisely those anticipated in the destination
  callframe, and the destination callframe is no longer relevant.
  
+ `directGet` - Since (as stated above) we ignore the possibility that
  a read trace on one variable may modify another, we simply copy all
  anticipable references.
  
+ `directSet`, etc. - Any local variable that might alias the
  variable being modified is no longer anticipable, and once again
  the callframes are swapped as with `moveToCallFrame` and `invoke`.
  
+ `variable`, `upvar`, `nsupvar` - The local variable and any aliases
  are no longer anticipable.
  
+ φ - Analysis stops at a φ instruction that references a callframe.
  When analyzing a predecessor block, `ANTIC_IN` for its successors
  will be translated to refer to the callframe that is input to the φ.

If a block has no φ instruction for the callframe, the same callframe
will be used when constructing its `ANTIC_IN` when analyzing a predecessor.

### Placement of load instructions

Once the `AVAIL_OUT` and `ANTIC_IN` sets are constructed, we can
determine where to place additional `moveFromCallFrame` instructions
that will perform loop-independent code motion. 

Since the entry block of a loop is always a merge point in the control
flow, its predecessor blocks will be single-exit blocks owing to
critical edge splitting. We need consider only insertion of
`moveFromCallFrame` instructions at these points.

The general plan is sketched in Section 4.3.2 of \[VanD04\]. We
examine merge points in the program (blocks with more than one
predecessor), in dominator order. For each (_cf_, _name_) that is 
anticipable at the entry to the block, we check availability in the
predecessor blocks. If the expression is available in at least one
predecessor, but not all predecessors, we insert `moveFromCallFrame`
instructions for it in the predecessors where it is unavailable. 

This is another analysis that must be iterated to
convergence. Inserting these `moveFromCallFrame` operations produces
new available variables, which can in turn expose further
opportunities for code motion. \[VAND04\] discusses this in more
detail in chapter 4.

### Possible combination of passes

This analysis closely mirrors what happens in partial redundancy
elimination (`quadcode/pre.tcl`). It may be possible to combine the
two into a single pass. The principal change will be that availability
analysis will need some refactoring, to discipline the size of the
`AVAIL` sets. Unlike the description in \[SIMP96\], we do not need to
shrink any of these sets for safety, because every time we perform an
operation that might affect a value in the callframe, we assign a new
SSA value to the callframe. Nevertheless, the quadcode sequence is
structured so that only one callframe is in flight at any given
time. Even if procedure inlining gives rise to additional callframes,
we still have the weaker condition that if there is an instruction
like

`doSomething cfout cfin moreArgs`

the input callframe will never again be used.
  
## TASK 4: Loop-invariant stores

We have seen in Task 3 that `moveFromCallFrame` instructions can be
placed speculatively to convert partial availability of a needed
expression to full availability (and remove a `moveFromCallFrame`
later in the program on a 'busier' execution path). In a similar manner,
`moveToCallFrame` instructions can be placed speculatively at the
head of blocks in order to make partially dead assignments ("faint"
assignments in the terminology of \[KNOO94\]) fully dead and eliminate
a `moveToCallFrame` on an eariler path of the program. 

\[LO98\] demonstrates how this partial liveness analysis is precisely
dual to partial availability analysis, and introduces a dual form to
Static Single Assignment (SSA), called Static Single Use (SSU). This
latter form has similar advantages to SSA in that the dependency
chain, here from definition to use rather than from use to definition,
is factored so that there are explicit deviation points (dual to the merge
points represented by φ operations in SSA form), and all divergence
analysis can be limited to those points (just as confluence analysis
can be limited to φ operations.)

Since this analysis, and the liveness analysis on SSA values that is
used to insert `free` instructions, appear to be the only places where
factored _du_-chains are of interest in the quadcode compiler, it
appears that converting programs to SSU (or combined SSA/SSU) form
will not be profitable, compared with the additional expense of
performing the analysis on an un-factored data flow graph. For this
reason, the more computationally complex analysis of \[KNOO94\] will
be followed, but modified to operate on basic blocks rather than
individual instructions.

We begin with the liveness analysis of Task 2. We augment 'liveness'
with the concept of partial liveness. The data flow equations will look like

![\textt{LIVE\_OUT}[B] formula](liveout.svg)

![\textt{PLIVE\_OUT}[B] formula](pliveout.svg)

![\textt{LIVE\_IN}[B] = \textt{process}(B, \textt{LIVE\_OUT}[B])](livein.svg)

![\textt{PLIVE\_IN}[B] = \textt{process}(B, \textt{PLIVE\_OUT}[B])](plivein.svg)

In these equations, _process_ represents the basic-block-level upward
analysis from Task 2. The _LIVE_ and _PLIVE_ sets are sets of
(callframe, variable) pairs, and it is assumed that the arguments to
the intersection and union are translated if the callframe appears in
a φ operation.

Liveness corresponds to the 'availability' of the partial redundancy
elimination. Just as a `moveFromCallFrame` may not be hoisted over the
point where it is available, a `moveToCallFrame` may not be sunk past the
point where it is live.

Similarly, `moveToCallFrame` creates values and corresponds to
anticipability. Just as it is of no benefit to insert a
`moveFromCallFrame` for a value that is not anticipated, it is of no
benefit to insert a `moveToCallFrame` for a value that is already present.



## References

\[DREC93\] Karl-Heinz Drechsler and Manfred P. Stadel. "A variation of
Knoop, Rüthing, and Steffen's _Lazy Code Motion_". _ACM SIGPLAN
Notices_ 28:5 (May, 1993), pp. 29-38.
[<https://dl.acm.org/citation.cfm?id=152823>]

\[KNOO94\] Jens Knoop, Oliver Rüthing, and Bernhard Steffen. "Partial
dead code elimination". Proc. 1994 ACM SIGPLAN Conf. Orlando,
Fla. USA: ACM, June 1994, pp. 147-158.
[<http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.49.2470>]

\[LO98\] Raymond Lo, Fred Chow, Robert Kennedy, Shin-Ming Liu, and
Peng Tu. "Register promotion by sparse partial redundancy elimination
of loads and stores." Proc. 1998 ACM SIGPLAN Conf. Programming
Language Design and Implementation (PLDI '98). Montreal, Canada: ACM,
June, 1998, pp. 26-37.
[<http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.33.9937>]

\[SIMP96\]
Loren Taylor Simpson. 1996. "Value-Driven Redundancy
Elimination". Ph.D. Dissertation. Rice University, Houston, TX,
USA. AAI9631092. 
[<https://www.clear.rice.edu/comp512/Lectures/Papers/SimpsonThesis.pdf>]

\[VanD04\]
VanDrunen, Thomas J. "Partial redundancy elimination for global value
numbering." PhD thesis, Purdue University, West Lafayette, Indiana
(August, 2004)
[<ftp://ftp.cs.purdue.edu/pub/hosking/papers/vandrunen.pdf>]

Added doc/20190216callframe/livein.svg.





























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?xml version='1.0' encoding='UTF-8'?>
<!-- This file was generated by dvisvgm 1.15.1 -->
<svg height='13.4589pt' version='1.1' viewBox='-0.239051 -0.240777 257.398 13.4589' width='257.398pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
<defs>
<path d='M2.33126 0.0478207C2.33126 -0.645579 2.10411 -1.15965 1.61395 -1.15965C1.23138 -1.15965 1.0401 -0.848817 1.0401 -0.585803S1.21943 0 1.6259 0C1.78132 0 1.91283 -0.0478207 2.02042 -0.155417C2.04433 -0.179328 2.05629 -0.179328 2.06824 -0.179328C2.09215 -0.179328 2.09215 -0.0119552 2.09215 0.0478207C2.09215 0.442341 2.02042 1.21943 1.32702 1.99651C1.19552 2.13998 1.19552 2.16389 1.19552 2.1878C1.19552 2.24757 1.25529 2.30735 1.31507 2.30735C1.41071 2.30735 2.33126 1.42267 2.33126 0.0478207Z' id='g0-59'/>
<path d='M4.37559 -7.35243C4.48319 -7.79477 4.53101 -7.81868 4.99726 -7.81868H6.55143C7.90237 -7.81868 7.90237 -6.67098 7.90237 -6.56339C7.90237 -5.59502 6.934 -4.36364 5.35592 -4.36364H3.63437L4.37559 -7.35243ZM6.39601 -4.268C7.69913 -4.5071 8.88269 -5.41569 8.88269 -6.51557C8.88269 -7.44807 8.05778 -8.16538 6.70685 -8.16538H2.86924C2.64209 -8.16538 2.5345 -8.16538 2.5345 -7.93823C2.5345 -7.81868 2.64209 -7.81868 2.82142 -7.81868C3.55068 -7.81868 3.55068 -7.72304 3.55068 -7.59153C3.55068 -7.56762 3.55068 -7.49589 3.50286 -7.31656L1.88892 -0.884682C1.78132 -0.466252 1.75741 -0.3467 0.920548 -0.3467C0.6934 -0.3467 0.573848 -0.3467 0.573848 -0.131507C0.573848 0 0.645579 0 0.884682 0H4.98531C6.81445 0 8.22516 -1.3868 8.22516 -2.59427C8.22516 -3.5746 7.36438 -4.17235 6.39601 -4.268ZM4.69838 -0.3467H3.08443C2.91706 -0.3467 2.89315 -0.3467 2.82142 -0.358655C2.68991 -0.37061 2.67796 -0.394521 2.67796 -0.490162C2.67796 -0.573848 2.70187 -0.645579 2.72578 -0.753176L3.56264 -4.12453H5.81021C7.22092 -4.12453 7.22092 -2.80946 7.22092 -2.71382C7.22092 -1.56613 6.18082 -0.3467 4.69838 -0.3467Z' id='g0-66'/>
<path d='M8.30884 -2.7736C8.3208 -2.80946 8.35666 -2.89315 8.35666 -2.94097C8.35666 -3.00075 8.30884 -3.06052 8.23711 -3.06052C8.18929 -3.06052 8.16538 -3.04857 8.12951 -3.0127C8.1056 -3.00075 8.1056 -2.97684 7.99801 -2.73773C7.29265 -1.06401 6.77858 -0.3467 4.86575 -0.3467H3.1203C2.95293 -0.3467 2.92902 -0.3467 2.85729 -0.358655C2.72578 -0.37061 2.71382 -0.394521 2.71382 -0.490162C2.71382 -0.573848 2.73773 -0.645579 2.76164 -0.753176L3.58655 -4.0528H4.77011C5.70262 -4.0528 5.77435 -3.84956 5.77435 -3.49091C5.77435 -3.37136 5.77435 -3.26376 5.69066 -2.90511C5.66675 -2.85729 5.65479 -2.80946 5.65479 -2.7736C5.65479 -2.68991 5.71457 -2.65405 5.7863 -2.65405C5.8939 -2.65405 5.90585 -2.73773 5.95367 -2.90511L6.63512 -5.6787C6.63512 -5.73848 6.5873 -5.79826 6.51557 -5.79826C6.40797 -5.79826 6.39601 -5.75044 6.34819 -5.58306C6.10909 -4.66252 5.86999 -4.3995 4.80598 -4.3995H3.67024L4.41146 -7.34047C4.51905 -7.7589 4.54296 -7.79477 5.03313 -7.79477H6.74271C8.2132 -7.79477 8.51208 -7.40025 8.51208 -6.49166C8.51208 -6.4797 8.51208 -6.14496 8.46426 -5.75044C8.4523 -5.70262 8.44035 -5.63088 8.44035 -5.60697C8.44035 -5.51133 8.50012 -5.47547 8.57186 -5.47547C8.65554 -5.47547 8.70336 -5.52329 8.72727 -5.73848L8.97833 -7.83064C8.97833 -7.8665 9.00224 -7.98605 9.00224 -8.00996C9.00224 -8.14147 8.89465 -8.14147 8.67945 -8.14147H2.84533C2.61818 -8.14147 2.49863 -8.14147 2.49863 -7.92628C2.49863 -7.79477 2.58232 -7.79477 2.78555 -7.79477C3.52677 -7.79477 3.52677 -7.71108 3.52677 -7.57958C3.52677 -7.5198 3.51482 -7.47198 3.47895 -7.34047L1.86501 -0.884682C1.75741 -0.466252 1.7335 -0.3467 0.896638 -0.3467C0.669489 -0.3467 0.549938 -0.3467 0.549938 -0.131507C0.549938 0 0.621669 0 0.860772 0H6.86227C7.12528 0 7.13724 -0.0119552 7.22092 -0.203238L8.30884 -2.7736Z' id='g0-69'/>
<path d='M4.3995 -7.2807C4.5071 -7.69913 4.53101 -7.81868 5.40374 -7.81868C5.66675 -7.81868 5.76239 -7.81868 5.76239 -8.04583C5.76239 -8.16538 5.63088 -8.16538 5.59502 -8.16538C5.37983 -8.16538 5.11681 -8.14147 4.90162 -8.14147H3.43113C3.19203 -8.14147 2.91706 -8.16538 2.67796 -8.16538C2.58232 -8.16538 2.45081 -8.16538 2.45081 -7.93823C2.45081 -7.81868 2.54645 -7.81868 2.78555 -7.81868C3.52677 -7.81868 3.52677 -7.72304 3.52677 -7.59153C3.52677 -7.50785 3.50286 -7.43611 3.47895 -7.32852L1.86501 -0.884682C1.75741 -0.466252 1.7335 -0.3467 0.860772 -0.3467C0.597758 -0.3467 0.490162 -0.3467 0.490162 -0.119552C0.490162 0 0.609714 0 0.669489 0C0.884682 0 1.1477 -0.0239103 1.36289 -0.0239103H2.83337C3.07248 -0.0239103 3.33549 0 3.5746 0C3.67024 0 3.8137 0 3.8137 -0.215193C3.8137 -0.3467 3.74197 -0.3467 3.47895 -0.3467C2.73773 -0.3467 2.73773 -0.442341 2.73773 -0.585803C2.73773 -0.609714 2.73773 -0.669489 2.78555 -0.860772L4.3995 -7.2807Z' id='g0-73'/>
<path d='M4.38755 -7.24483C4.49514 -7.69913 4.53101 -7.81868 5.58306 -7.81868C5.90585 -7.81868 5.98954 -7.81868 5.98954 -8.04583C5.98954 -8.16538 5.85803 -8.16538 5.81021 -8.16538C5.57111 -8.16538 5.29614 -8.14147 5.05704 -8.14147H3.45504C3.2279 -8.14147 2.96488 -8.16538 2.73773 -8.16538C2.64209 -8.16538 2.51059 -8.16538 2.51059 -7.93823C2.51059 -7.81868 2.61818 -7.81868 2.79751 -7.81868C3.52677 -7.81868 3.52677 -7.72304 3.52677 -7.59153C3.52677 -7.56762 3.52677 -7.49589 3.47895 -7.31656L1.86501 -0.884682C1.75741 -0.466252 1.7335 -0.3467 0.896638 -0.3467C0.669489 -0.3467 0.549938 -0.3467 0.549938 -0.131507C0.549938 0 0.621669 0 0.860772 0H6.21669C6.4797 0 6.49166 -0.0119552 6.57534 -0.227148L7.49589 -2.7736C7.5198 -2.83337 7.54371 -2.90511 7.54371 -2.94097C7.54371 -3.0127 7.48394 -3.06052 7.42416 -3.06052C7.4122 -3.06052 7.35243 -3.06052 7.32852 -3.0127C7.30461 -3.00075 7.30461 -2.97684 7.20897 -2.74969C6.8264 -1.69763 6.28842 -0.3467 4.268 -0.3467H3.1203C2.95293 -0.3467 2.92902 -0.3467 2.85729 -0.358655C2.72578 -0.37061 2.71382 -0.394521 2.71382 -0.490162C2.71382 -0.573848 2.73773 -0.645579 2.76164 -0.753176L4.38755 -7.24483Z' id='g0-76'/>
<path d='M8.84682 -6.91009C8.97833 -7.42416 9.16961 -7.78281 10.0782 -7.81868C10.1141 -7.81868 10.2575 -7.83064 10.2575 -8.03387C10.2575 -8.16538 10.1499 -8.16538 10.1021 -8.16538C9.86301 -8.16538 9.2533 -8.14147 9.0142 -8.14147H8.44035C8.27298 -8.14147 8.05778 -8.16538 7.89041 -8.16538C7.81868 -8.16538 7.67522 -8.16538 7.67522 -7.93823C7.67522 -7.81868 7.77086 -7.81868 7.85455 -7.81868C8.57186 -7.79477 8.61968 -7.5198 8.61968 -7.30461C8.61968 -7.19701 8.60772 -7.16115 8.57186 -6.99377L7.22092 -1.60199L4.66252 -7.96214C4.57883 -8.15342 4.56687 -8.16538 4.30386 -8.16538H2.84533C2.60623 -8.16538 2.49863 -8.16538 2.49863 -7.93823C2.49863 -7.81868 2.58232 -7.81868 2.80946 -7.81868C2.86924 -7.81868 3.5746 -7.81868 3.5746 -7.71108C3.5746 -7.68717 3.55068 -7.59153 3.53873 -7.55567L1.94869 -1.21943C1.80523 -0.633624 1.51831 -0.382565 0.729265 -0.3467C0.669489 -0.3467 0.549938 -0.334745 0.549938 -0.119552C0.549938 0 0.669489 0 0.705355 0C0.944458 0 1.55417 -0.0239103 1.79328 -0.0239103H2.36712C2.5345 -0.0239103 2.73773 0 2.90511 0C2.98879 0 3.1203 0 3.1203 -0.227148C3.1203 -0.334745 3.00075 -0.3467 2.95293 -0.3467C2.55841 -0.358655 2.17584 -0.430386 2.17584 -0.860772C2.17584 -0.956413 2.19975 -1.06401 2.22366 -1.15965L3.83761 -7.55567C3.90934 -7.43611 3.90934 -7.4122 3.95716 -7.30461L6.80249 -0.215193C6.86227 -0.071731 6.88618 0 6.99377 0C7.11333 0 7.12528 -0.0358655 7.1731 -0.239103L8.84682 -6.91009Z' id='g0-78'/>
<path d='M8.67945 -5.23636C8.67945 -7.20897 7.38829 -8.41644 5.71457 -8.41644C3.15616 -8.41644 0.573848 -5.66675 0.573848 -2.90511C0.573848 -1.02814 1.81719 0.251059 3.55068 0.251059C6.06127 0.251059 8.67945 -2.36712 8.67945 -5.23636ZM3.62242 -0.0239103C2.64209 -0.0239103 1.60199 -0.74122 1.60199 -2.60623C1.60199 -3.69415 1.99651 -5.47547 2.97684 -6.67098C3.84956 -7.72304 4.8538 -8.15342 5.65479 -8.15342C6.70685 -8.15342 7.72304 -7.38829 7.72304 -5.66675C7.72304 -4.60274 7.26874 -2.94097 6.46775 -1.80523C5.59502 -0.585803 4.5071 -0.0239103 3.62242 -0.0239103Z' id='g0-79'/>
<path d='M4.98531 -7.29265C5.05704 -7.57958 5.08095 -7.68717 5.26027 -7.73499C5.35592 -7.7589 5.75044 -7.7589 6.00149 -7.7589C7.19701 -7.7589 7.7589 -7.71108 7.7589 -6.77858C7.7589 -6.59925 7.71108 -6.14496 7.63935 -5.70262L7.6274 -5.55915C7.6274 -5.51133 7.67522 -5.4396 7.74695 -5.4396C7.8665 -5.4396 7.8665 -5.49938 7.90237 -5.69066L8.24907 -7.80672C8.27298 -7.91432 8.27298 -7.93823 8.27298 -7.9741C8.27298 -8.1056 8.20125 -8.1056 7.96214 -8.1056H1.42267C1.1477 -8.1056 1.13574 -8.09365 1.06401 -7.87846L0.334745 -5.72653C0.32279 -5.70262 0.286924 -5.57111 0.286924 -5.55915C0.286924 -5.49938 0.334745 -5.4396 0.406476 -5.4396C0.502117 -5.4396 0.526027 -5.48742 0.573848 -5.64284C1.07597 -7.08941 1.32702 -7.7589 2.91706 -7.7589H3.71806C4.00498 -7.7589 4.12453 -7.7589 4.12453 -7.6274C4.12453 -7.59153 4.12453 -7.56762 4.06476 -7.35243L2.46276 -0.932503C2.34321 -0.466252 2.3193 -0.3467 1.05205 -0.3467C0.753176 -0.3467 0.669489 -0.3467 0.669489 -0.119552C0.669489 0 0.800996 0 0.860772 0C1.15965 0 1.47049 -0.0239103 1.76936 -0.0239103H3.63437C3.93325 -0.0239103 4.25604 0 4.55492 0C4.68643 0 4.80598 0 4.80598 -0.227148C4.80598 -0.3467 4.72229 -0.3467 4.41146 -0.3467C3.33549 -0.3467 3.33549 -0.454296 3.33549 -0.633624C3.33549 -0.645579 3.33549 -0.729265 3.38331 -0.920548L4.98531 -7.29265Z' id='g0-84'/>
<path d='M6.04932 -2.74969C5.63088 -1.07597 4.24408 -0.0956413 3.1203 -0.0956413C2.25953 -0.0956413 1.67372 -0.669489 1.67372 -1.66177C1.67372 -1.70959 1.67372 -2.06824 1.80523 -2.59427L2.97684 -7.29265C3.08443 -7.69913 3.10834 -7.81868 3.95716 -7.81868C4.17235 -7.81868 4.29191 -7.81868 4.29191 -8.03387C4.29191 -8.16538 4.18431 -8.16538 4.11258 -8.16538C3.89738 -8.16538 3.64633 -8.14147 3.41918 -8.14147H2.00847C1.78132 -8.14147 1.53026 -8.16538 1.30311 -8.16538C1.21943 -8.16538 1.07597 -8.16538 1.07597 -7.93823C1.07597 -7.81868 1.15965 -7.81868 1.3868 -7.81868C2.10411 -7.81868 2.10411 -7.72304 2.10411 -7.59153C2.10411 -7.5198 2.02042 -7.1731 1.96065 -6.96986L0.920548 -2.78555C0.884682 -2.65405 0.812951 -2.33126 0.812951 -2.00847C0.812951 -0.6934 1.75741 0.251059 3.06052 0.251059C4.268 0.251059 5.60697 -0.705355 6.21669 -2.22366C6.30037 -2.4269 6.40797 -2.84533 6.4797 -3.16812C6.59925 -3.59851 6.85031 -4.65056 6.934 -4.96139L7.38829 -6.75467C7.54371 -7.37634 7.63935 -7.77086 8.69141 -7.81868C8.78705 -7.83064 8.83487 -7.92628 8.83487 -8.03387C8.83487 -8.16538 8.72727 -8.16538 8.67945 -8.16538C8.51208 -8.16538 8.29689 -8.14147 8.12951 -8.14147H7.56762C6.8264 -8.14147 6.44384 -8.16538 6.43188 -8.16538C6.36015 -8.16538 6.21669 -8.16538 6.21669 -7.93823C6.21669 -7.81868 6.31233 -7.81868 6.39601 -7.81868C7.11333 -7.79477 7.16115 -7.5198 7.16115 -7.30461C7.16115 -7.19701 7.16115 -7.16115 7.11333 -6.99377L6.04932 -2.74969Z' id='g0-85'/>
<path d='M7.40025 -6.83836C7.80672 -7.48394 8.17733 -7.77086 8.78705 -7.81868C8.9066 -7.83064 9.00224 -7.83064 9.00224 -8.04583C9.00224 -8.09365 8.97833 -8.16538 8.87073 -8.16538C8.65554 -8.16538 8.14147 -8.14147 7.92628 -8.14147C7.57958 -8.14147 7.22092 -8.16538 6.88618 -8.16538C6.79054 -8.16538 6.67098 -8.16538 6.67098 -7.93823C6.67098 -7.83064 6.77858 -7.81868 6.8264 -7.81868C7.26874 -7.78281 7.31656 -7.56762 7.31656 -7.42416C7.31656 -7.24483 7.14919 -6.96986 7.13724 -6.95791L3.38331 -1.00423L2.54645 -7.44807C2.54645 -7.79477 3.16812 -7.81868 3.29963 -7.81868C3.47895 -7.81868 3.58655 -7.81868 3.58655 -8.04583C3.58655 -8.16538 3.45504 -8.16538 3.41918 -8.16538C3.21594 -8.16538 2.97684 -8.14147 2.7736 -8.14147H2.10411C1.23138 -8.14147 0.872727 -8.16538 0.860772 -8.16538C0.789041 -8.16538 0.645579 -8.16538 0.645579 -7.95019C0.645579 -7.81868 0.729265 -7.81868 0.920548 -7.81868C1.53026 -7.81868 1.56613 -7.71108 1.60199 -7.4122L2.55841 -0.0358655C2.59427 0.215193 2.59427 0.251059 2.76164 0.251059C2.90511 0.251059 2.96488 0.215193 3.08443 0.0239103L7.40025 -6.83836Z' id='g0-86'/>
<path d='M4.67447 -4.49514C4.44732 -4.49514 4.33973 -4.49514 4.17235 -4.35168C4.10062 -4.29191 3.96912 -4.11258 3.96912 -3.9213C3.96912 -3.68219 4.14844 -3.53873 4.37559 -3.53873C4.66252 -3.53873 4.98531 -3.77783 4.98531 -4.25604C4.98531 -4.82989 4.43537 -5.27223 3.61046 -5.27223C2.04433 -5.27223 0.478207 -3.56264 0.478207 -1.86501C0.478207 -0.824907 1.12379 0.119552 2.34321 0.119552C3.96912 0.119552 4.99726 -1.1477 4.99726 -1.30311C4.99726 -1.37484 4.92553 -1.43462 4.87771 -1.43462C4.84184 -1.43462 4.82989 -1.42267 4.72229 -1.31507C3.95716 -0.298879 2.82142 -0.119552 2.36712 -0.119552C1.54222 -0.119552 1.2792 -0.836862 1.2792 -1.43462C1.2792 -1.85305 1.48244 -3.0127 1.91283 -3.82565C2.22366 -4.38755 2.86924 -5.03313 3.62242 -5.03313C3.77783 -5.03313 4.43537 -5.00922 4.67447 -4.49514Z' id='g0-99'/>
<path d='M2.13998 -2.7736C2.46276 -2.7736 3.27572 -2.79751 3.84956 -3.0127C4.75816 -3.3594 4.84184 -4.0528 4.84184 -4.268C4.84184 -4.79402 4.38755 -5.27223 3.59851 -5.27223C2.34321 -5.27223 0.537983 -4.13649 0.537983 -2.00847C0.537983 -0.753176 1.25529 0.119552 2.34321 0.119552C3.96912 0.119552 4.99726 -1.1477 4.99726 -1.30311C4.99726 -1.37484 4.92553 -1.43462 4.87771 -1.43462C4.84184 -1.43462 4.82989 -1.42267 4.72229 -1.31507C3.95716 -0.298879 2.82142 -0.119552 2.36712 -0.119552C1.68568 -0.119552 1.32702 -0.657534 1.32702 -1.54222C1.32702 -1.70959 1.32702 -2.00847 1.50635 -2.7736H2.13998ZM1.56613 -3.0127C2.0802 -4.8538 3.21594 -5.03313 3.59851 -5.03313C4.12453 -5.03313 4.48319 -4.72229 4.48319 -4.268C4.48319 -3.0127 2.57036 -3.0127 2.06824 -3.0127H1.56613Z' id='g0-101'/>
<path d='M5.45156 -3.28767C5.45156 -4.42341 4.71034 -5.27223 3.62242 -5.27223C2.04433 -5.27223 0.490162 -3.55068 0.490162 -1.86501C0.490162 -0.729265 1.23138 0.119552 2.3193 0.119552C3.90934 0.119552 5.45156 -1.60199 5.45156 -3.28767ZM2.33126 -0.119552C1.7335 -0.119552 1.29116 -0.597758 1.29116 -1.43462C1.29116 -1.98456 1.57808 -3.20399 1.91283 -3.80174C2.45081 -4.72229 3.1203 -5.03313 3.61046 -5.03313C4.19626 -5.03313 4.65056 -4.55492 4.65056 -3.71806C4.65056 -3.23985 4.3995 -1.96065 3.94521 -1.23138C3.45504 -0.430386 2.79751 -0.119552 2.33126 -0.119552Z' id='g0-111'/>
<path d='M0.514072 1.51831C0.430386 1.87696 0.382565 1.9726 -0.107597 1.9726C-0.251059 1.9726 -0.37061 1.9726 -0.37061 2.19975C-0.37061 2.22366 -0.358655 2.3193 -0.227148 2.3193C-0.071731 2.3193 0.0956413 2.29539 0.251059 2.29539H0.765131C1.01619 2.29539 1.6259 2.3193 1.87696 2.3193C1.94869 2.3193 2.09215 2.3193 2.09215 2.10411C2.09215 1.9726 2.00847 1.9726 1.80523 1.9726C1.25529 1.9726 1.21943 1.88892 1.21943 1.79328C1.21943 1.64981 1.75741 -0.406476 1.82914 -0.681445C1.96065 -0.3467 2.28344 0.119552 2.90511 0.119552C4.25604 0.119552 5.71457 -1.63786 5.71457 -3.39527C5.71457 -4.49514 5.0929 -5.27223 4.19626 -5.27223C3.43113 -5.27223 2.78555 -4.53101 2.65405 -4.36364C2.55841 -4.96139 2.09215 -5.27223 1.61395 -5.27223C1.26725 -5.27223 0.992279 -5.10486 0.765131 -4.65056C0.549938 -4.22017 0.382565 -3.49091 0.382565 -3.44309S0.430386 -3.33549 0.514072 -3.33549C0.609714 -3.33549 0.621669 -3.34745 0.6934 -3.62242C0.872727 -4.32777 1.09988 -5.03313 1.57808 -5.03313C1.85305 -5.03313 1.94869 -4.84184 1.94869 -4.48319C1.94869 -4.19626 1.91283 -4.07671 1.86501 -3.86152L0.514072 1.51831ZM2.58232 -3.73001C2.666 -4.06476 3.00075 -4.41146 3.19203 -4.57883C3.32354 -4.69838 3.71806 -5.03313 4.17235 -5.03313C4.69838 -5.03313 4.93748 -4.5071 4.93748 -3.88543C4.93748 -3.31158 4.60274 -1.96065 4.30386 -1.33898C4.00498 -0.6934 3.45504 -0.119552 2.90511 -0.119552C2.09215 -0.119552 1.96065 -1.1477 1.96065 -1.19552C1.96065 -1.23138 1.98456 -1.32702 1.99651 -1.3868L2.58232 -3.73001Z' id='g0-112'/>
<path d='M4.65056 -4.88966C4.27995 -4.81793 4.08867 -4.55492 4.08867 -4.29191C4.08867 -4.00498 4.31582 -3.90934 4.48319 -3.90934C4.81793 -3.90934 5.0929 -4.19626 5.0929 -4.55492C5.0929 -4.93748 4.72229 -5.27223 4.12453 -5.27223C3.64633 -5.27223 3.09639 -5.05704 2.59427 -4.32777C2.51059 -4.96139 2.03238 -5.27223 1.55417 -5.27223C1.08792 -5.27223 0.848817 -4.91357 0.705355 -4.65056C0.502117 -4.22017 0.32279 -3.50286 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.549938 -3.33549 0.561893 -3.34745 0.633624 -3.62242C0.812951 -4.33973 1.0401 -5.03313 1.51831 -5.03313C1.80523 -5.03313 1.88892 -4.82989 1.88892 -4.48319C1.88892 -4.22017 1.76936 -3.75392 1.68568 -3.38331L1.35093 -2.09215C1.30311 -1.86501 1.17161 -1.32702 1.11183 -1.11183C1.02814 -0.800996 0.896638 -0.239103 0.896638 -0.179328C0.896638 -0.0119552 1.02814 0.119552 1.20747 0.119552C1.33898 0.119552 1.56613 0.0358655 1.63786 -0.203238C1.67372 -0.298879 2.11606 -2.10411 2.1878 -2.37908C2.24757 -2.64209 2.3193 -2.89315 2.37908 -3.15616C2.4269 -3.32354 2.47472 -3.51482 2.51059 -3.67024C2.54645 -3.77783 2.86924 -4.36364 3.16812 -4.62665C3.31158 -4.75816 3.62242 -5.03313 4.11258 -5.03313C4.30386 -5.03313 4.49514 -4.99726 4.65056 -4.88966Z' id='g0-114'/>
<path d='M2.72578 -2.39103C2.92902 -2.35517 3.25181 -2.28344 3.32354 -2.27148C3.47895 -2.22366 4.01694 -2.03238 4.01694 -1.45853C4.01694 -1.08792 3.68219 -0.119552 2.29539 -0.119552C2.04433 -0.119552 1.1477 -0.155417 0.908593 -0.812951C1.3868 -0.753176 1.6259 -1.12379 1.6259 -1.3868C1.6259 -1.63786 1.45853 -1.76936 1.21943 -1.76936C0.956413 -1.76936 0.609714 -1.56613 0.609714 -1.02814C0.609714 -0.32279 1.32702 0.119552 2.28344 0.119552C4.10062 0.119552 4.63861 -1.21943 4.63861 -1.8411C4.63861 -2.02042 4.63861 -2.35517 4.25604 -2.73773C3.95716 -3.02466 3.67024 -3.08443 3.02466 -3.21594C2.70187 -3.28767 2.1878 -3.39527 2.1878 -3.93325C2.1878 -4.17235 2.40299 -5.03313 3.53873 -5.03313C4.04085 -5.03313 4.53101 -4.84184 4.65056 -4.41146C4.12453 -4.41146 4.10062 -3.95716 4.10062 -3.94521C4.10062 -3.69415 4.32777 -3.62242 4.43537 -3.62242C4.60274 -3.62242 4.93748 -3.75392 4.93748 -4.25604S4.48319 -5.27223 3.55068 -5.27223C1.98456 -5.27223 1.56613 -4.04085 1.56613 -3.55068C1.56613 -2.64209 2.45081 -2.45081 2.72578 -2.39103Z' id='g0-115'/>
<path d='M3.88543 2.90511C3.88543 2.86924 3.88543 2.84533 3.68219 2.64209C2.48667 1.43462 1.81719 -0.537983 1.81719 -2.97684C1.81719 -5.29614 2.37908 -7.29265 3.76588 -8.70336C3.88543 -8.81096 3.88543 -8.83487 3.88543 -8.87073C3.88543 -8.94247 3.82565 -8.96638 3.77783 -8.96638C3.62242 -8.96638 2.64209 -8.1056 2.05629 -6.934C1.44658 -5.72653 1.17161 -4.44732 1.17161 -2.97684C1.17161 -1.91283 1.33898 -0.490162 1.96065 0.789041C2.666 2.22366 3.64633 3.00075 3.77783 3.00075C3.82565 3.00075 3.88543 2.97684 3.88543 2.90511Z' id='g1-40'/>
<path d='M3.37136 -2.97684C3.37136 -3.88543 3.25181 -5.36787 2.58232 -6.75467C1.87696 -8.18929 0.896638 -8.96638 0.765131 -8.96638C0.71731 -8.96638 0.657534 -8.94247 0.657534 -8.87073C0.657534 -8.83487 0.657534 -8.81096 0.860772 -8.60772C2.05629 -7.40025 2.72578 -5.42765 2.72578 -2.98879C2.72578 -0.669489 2.16389 1.32702 0.777086 2.73773C0.657534 2.84533 0.657534 2.86924 0.657534 2.90511C0.657534 2.97684 0.71731 3.00075 0.765131 3.00075C0.920548 3.00075 1.90087 2.13998 2.48667 0.968369C3.09639 -0.251059 3.37136 -1.54222 3.37136 -2.97684Z' id='g1-41'/>
<path d='M8.06974 -3.87347C8.23711 -3.87347 8.4523 -3.87347 8.4523 -4.08867C8.4523 -4.31582 8.24907 -4.31582 8.06974 -4.31582H1.02814C0.860772 -4.31582 0.645579 -4.31582 0.645579 -4.10062C0.645579 -3.87347 0.848817 -3.87347 1.02814 -3.87347H8.06974ZM8.06974 -1.64981C8.23711 -1.64981 8.4523 -1.64981 8.4523 -1.86501C8.4523 -2.09215 8.24907 -2.09215 8.06974 -2.09215H1.02814C0.860772 -2.09215 0.645579 -2.09215 0.645579 -1.87696C0.645579 -1.64981 0.848817 -1.64981 1.02814 -1.64981H8.06974Z' id='g1-61'/>
<path d='M2.98879 2.98879V2.54645H1.82914V-8.52403H2.98879V-8.96638H1.3868V2.98879H2.98879Z' id='g1-91'/>
<path d='M1.85305 -8.96638H0.251059V-8.52403H1.41071V2.54645H0.251059V2.98879H1.85305V-8.96638Z' id='g1-93'/>
</defs>
<g id='page1' transform='matrix(1.13 0 0 1.13 -63.986 -64.448)'>
<use x='56.4133' xlink:href='#g0-76' y='65.7534'/>
<use x='64.348' xlink:href='#g0-73' y='65.7534'/>
<use x='70.4315' xlink:href='#g0-86' y='65.7534'/>
<use x='79.8317' xlink:href='#g0-69' y='65.7534'/>
<rect height='0.3985' width='3.51182' x='89.8678' y='65.3549'/>
<use x='93.3797' xlink:href='#g0-73' y='65.7534'/>
<use x='99.4632' xlink:href='#g0-78' y='65.7534'/>
<use x='110.212' xlink:href='#g1-91' y='65.7534'/>
<use x='113.451' xlink:href='#g0-66' y='65.7534'/>
<use x='122.914' xlink:href='#g1-93' y='65.7534'/>
<use x='129.475' xlink:href='#g1-61' y='65.7534'/>
<use x='141.866' xlink:href='#g0-112' y='65.7534'/>
<use x='147.719' xlink:href='#g0-114' y='65.7534'/>
<use x='153.3' xlink:href='#g0-111' y='65.7534'/>
<use x='158.907' xlink:href='#g0-99' y='65.7534'/>
<use x='163.926' xlink:href='#g0-101' y='65.7534'/>
<use x='169.331' xlink:href='#g0-115' y='65.7534'/>
<use x='174.824' xlink:href='#g0-115' y='65.7534'/>
<use x='180.461' xlink:href='#g1-40' y='65.7534'/>
<use x='184.996' xlink:href='#g0-66' y='65.7534'/>
<use x='194.459' xlink:href='#g0-59' y='65.7534'/>
<use x='199.691' xlink:href='#g0-76' y='65.7534'/>
<use x='207.626' xlink:href='#g0-73' y='65.7534'/>
<use x='213.709' xlink:href='#g0-86' y='65.7534'/>
<use x='223.11' xlink:href='#g0-69' y='65.7534'/>
<rect height='0.3985' width='3.51182' x='233.146' y='65.3549'/>
<use x='236.658' xlink:href='#g0-79' y='65.7534'/>
<use x='245.895' xlink:href='#g0-85' y='65.7534'/>
<use x='255.065' xlink:href='#g0-84' y='65.7534'/>
<use x='263.722' xlink:href='#g1-91' y='65.7534'/>
<use x='266.961' xlink:href='#g0-66' y='65.7534'/>
<use x='276.424' xlink:href='#g1-93' y='65.7534'/>
<use x='279.664' xlink:href='#g1-41' y='65.7534'/>
</g>
</svg>

Added doc/20190216callframe/liveout.svg.











































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
<?xml version='1.0' encoding='UTF-8'?>
<!-- This file was generated by dvisvgm 1.15.1 -->
<svg height='49.5404pt' version='1.1' viewBox='-0.239051 -0.227989 588.106 49.5404' width='588.106pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
<defs>
<path d='M6.0254 5.41569C6.0254 4.43537 6.28842 2.15193 8.41644 0.645579C8.57186 0.526027 8.58381 0.514072 8.58381 0.298879C8.58381 0.0239103 8.57186 0.0119552 8.27298 0.0119552H8.08169C5.51133 1.39875 4.59078 3.65828 4.59078 5.41569V10.5564C4.59078 10.8672 4.60274 10.8792 4.92553 10.8792H5.69066C6.01345 10.8792 6.0254 10.8672 6.0254 10.5564V5.41569Z' id='g0-56'/>
<path d='M8.27298 10.7477C8.57186 10.7477 8.58381 10.7357 8.58381 10.4608C8.58381 10.2456 8.57186 10.2336 8.52403 10.1978C8.15342 9.92279 7.29265 9.31308 6.73076 8.2132C6.26451 7.30461 6.0254 6.38406 6.0254 5.34396V0.203238C6.0254 -0.107597 6.01345 -0.119552 5.69066 -0.119552H4.92553C4.60274 -0.119552 4.59078 -0.107597 4.59078 0.203238V5.34396C4.59078 7.11333 5.51133 9.37285 8.08169 10.7477H8.27298Z' id='g0-58'/>
<path d='M4.59078 21.3161C4.59078 21.6269 4.60274 21.6389 4.92553 21.6389H5.69066C6.01345 21.6389 6.0254 21.6269 6.0254 21.3161V16.271C6.0254 14.8244 5.41569 12.3856 2.73773 10.7597C5.4396 9.12179 6.0254 6.65903 6.0254 5.24832V0.203238C6.0254 -0.107597 6.01345 -0.119552 5.69066 -0.119552H4.92553C4.60274 -0.119552 4.59078 -0.107597 4.59078 0.203238V5.26027C4.59078 6.26451 4.37559 8.75118 2.17584 10.4249C2.04433 10.5325 2.03238 10.5445 2.03238 10.7597S2.04433 10.9868 2.17584 11.0944C2.48667 11.3335 3.31158 11.9671 3.88543 13.1746C4.35168 14.131 4.59078 15.195 4.59078 16.259V21.3161Z' id='g0-60'/>
<path d='M11.6085 16.0797C11.6085 16.2351 11.6085 16.7372 12.0986 16.7372C12.6007 16.7372 12.6007 16.2471 12.6007 16.0797V5.70262C12.6007 2.63014 9.98257 0 6.63512 0S0.669489 2.63014 0.669489 5.70262V16.0797C0.669489 16.2351 0.669489 16.7372 1.15965 16.7372C1.66177 16.7372 1.66177 16.2471 1.66177 16.0797V5.76239C1.66177 3.02466 3.96912 0.992279 6.63512 0.992279S11.6085 3.03661 11.6085 5.76239V16.0797Z' id='g0-92'/>
<path d='M8.06974 -3.87347C8.23711 -3.87347 8.4523 -3.87347 8.4523 -4.08867C8.4523 -4.31582 8.24907 -4.31582 8.06974 -4.31582H1.02814C0.860772 -4.31582 0.645579 -4.31582 0.645579 -4.10062C0.645579 -3.87347 0.848817 -3.87347 1.02814 -3.87347H8.06974ZM8.06974 -1.64981C8.23711 -1.64981 8.4523 -1.64981 8.4523 -1.86501C8.4523 -2.09215 8.24907 -2.09215 8.06974 -2.09215H1.02814C0.860772 -2.09215 0.645579 -2.09215 0.645579 -1.87696C0.645579 -1.64981 0.848817 -1.64981 1.02814 -1.64981H8.06974Z' id='g6-61'/>
<path d='M2.98879 2.98879V2.54645H1.82914V-8.52403H2.98879V-8.96638H1.3868V2.98879H2.98879Z' id='g6-91'/>
<path d='M1.85305 -8.96638H0.251059V-8.52403H1.41071V2.54645H0.251059V2.98879H1.85305V-8.96638Z' id='g6-93'/>
<path d='M4.61469 -3.19203C4.61469 -3.83761 4.61469 -4.31582 4.08867 -4.78207C3.67024 -5.16463 3.13225 -5.332 2.60623 -5.332C1.6259 -5.332 0.872727 -4.68643 0.872727 -3.90934C0.872727 -3.56264 1.09988 -3.39527 1.37484 -3.39527C1.66177 -3.39527 1.86501 -3.59851 1.86501 -3.88543C1.86501 -4.37559 1.43462 -4.37559 1.25529 -4.37559C1.53026 -4.87771 2.10411 -5.0929 2.58232 -5.0929C3.13225 -5.0929 3.83761 -4.63861 3.83761 -3.56264V-3.08443C1.43462 -3.04857 0.526027 -2.04433 0.526027 -1.12379C0.526027 -0.179328 1.6259 0.119552 2.35517 0.119552C3.14421 0.119552 3.68219 -0.358655 3.90934 -0.932503C3.95716 -0.37061 4.32777 0.0597758 4.84184 0.0597758C5.0929 0.0597758 5.7863 -0.107597 5.7863 -1.06401V-1.7335H5.52329V-1.06401C5.52329 -0.382565 5.23636 -0.286924 5.06899 -0.286924C4.61469 -0.286924 4.61469 -0.920548 4.61469 -1.09988V-3.19203ZM3.83761 -1.68568C3.83761 -0.514072 2.96488 -0.119552 2.45081 -0.119552C1.86501 -0.119552 1.37484 -0.549938 1.37484 -1.12379C1.37484 -2.70187 3.40722 -2.84533 3.83761 -2.86924V-1.68568Z' id='g6-97'/>
<path d='M1.99651 -8.29689L0.334745 -8.16538V-7.81868C1.1477 -7.81868 1.24334 -7.73499 1.24334 -7.14919V0H1.50635C1.55417 -0.0956413 1.88892 -0.6934 1.93674 -0.777086C2.21171 -0.334745 2.72578 0.119552 3.49091 0.119552C4.86575 0.119552 6.07323 -1.0401 6.07323 -2.58232C6.07323 -4.10062 4.94944 -5.27223 3.62242 -5.27223C2.96488 -5.27223 2.40299 -4.97335 1.99651 -4.47123V-8.29689ZM2.02042 -3.82565C2.02042 -4.04085 2.02042 -4.06476 2.15193 -4.25604C2.43885 -4.68643 2.96488 -5.03313 3.55068 -5.03313C3.90934 -5.03313 5.16463 -4.88966 5.16463 -2.59427C5.16463 -1.79328 5.04508 -1.29116 4.75816 -0.860772C4.51905 -0.490162 4.04085 -0.119552 3.44309 -0.119552C2.79751 -0.119552 2.37908 -0.537983 2.17584 -0.860772C2.02042 -1.11183 2.02042 -1.15965 2.02042 -1.36289V-3.82565Z' id='g6-98'/>
<path d='M4.32777 -4.42341C4.18431 -4.42341 3.74197 -4.42341 3.74197 -3.93325C3.74197 -3.64633 3.94521 -3.44309 4.23213 -3.44309C4.5071 -3.44309 4.73425 -3.61046 4.73425 -3.95716C4.73425 -4.75816 3.89738 -5.332 2.92902 -5.332C1.53026 -5.332 0.418431 -4.08867 0.418431 -2.58232C0.418431 -1.05205 1.56613 0.119552 2.91706 0.119552C4.49514 0.119552 4.8538 -1.31507 4.8538 -1.42267S4.77011 -1.53026 4.73425 -1.53026C4.62665 -1.53026 4.61469 -1.4944 4.57883 -1.35093C4.31582 -0.502117 3.67024 -0.143462 3.02466 -0.143462C2.29539 -0.143462 1.32702 -0.777086 1.32702 -2.59427C1.32702 -4.57883 2.34321 -5.06899 2.94097 -5.06899C3.39527 -5.06899 4.0528 -4.88966 4.32777 -4.42341Z' id='g6-99'/>
<path d='M4.57883 -2.7736C4.84184 -2.7736 4.86575 -2.7736 4.86575 -3.00075C4.86575 -4.20822 4.22017 -5.332 2.7736 -5.332C1.41071 -5.332 0.358655 -4.10062 0.358655 -2.61818C0.358655 -1.0401 1.57808 0.119552 2.90511 0.119552C4.32777 0.119552 4.86575 -1.17161 4.86575 -1.42267C4.86575 -1.4944 4.80598 -1.54222 4.73425 -1.54222C4.63861 -1.54222 4.61469 -1.48244 4.59078 -1.42267C4.27995 -0.418431 3.47895 -0.143462 2.97684 -0.143462S1.26725 -0.478207 1.26725 -2.54645V-2.7736H4.57883ZM1.2792 -3.00075C1.37484 -4.87771 2.4269 -5.0929 2.76164 -5.0929C4.04085 -5.0929 4.11258 -3.40722 4.12453 -3.00075H1.2792Z' id='g6-101'/>
<path d='M1.42267 -2.16389C1.98456 -1.79328 2.46276 -1.79328 2.59427 -1.79328C3.67024 -1.79328 4.47123 -2.60623 4.47123 -3.52677C4.47123 -3.84956 4.37559 -4.30386 3.99303 -4.68643C4.45928 -5.16463 5.02117 -5.16463 5.08095 -5.16463C5.12877 -5.16463 5.18854 -5.16463 5.23636 -5.14072C5.11681 -5.0929 5.05704 -4.97335 5.05704 -4.84184C5.05704 -4.67447 5.17659 -4.53101 5.36787 -4.53101C5.46351 -4.53101 5.6787 -4.59078 5.6787 -4.8538C5.6787 -5.06899 5.51133 -5.40374 5.0929 -5.40374C4.47123 -5.40374 4.00498 -5.02117 3.83761 -4.84184C3.47895 -5.11681 3.06052 -5.27223 2.60623 -5.27223C1.53026 -5.27223 0.729265 -4.45928 0.729265 -3.53873C0.729265 -2.85729 1.1477 -2.41494 1.26725 -2.30735C1.12379 -2.12802 0.908593 -1.78132 0.908593 -1.31507C0.908593 -0.621669 1.32702 -0.32279 1.42267 -0.263014C0.872727 -0.107597 0.32279 0.32279 0.32279 0.944458C0.32279 1.76936 1.44658 2.45081 2.91706 2.45081C4.33973 2.45081 5.52329 1.81719 5.52329 0.920548C5.52329 0.621669 5.4396 -0.0836862 4.72229 -0.454296C4.11258 -0.765131 3.51482 -0.765131 2.48667 -0.765131C1.75741 -0.765131 1.67372 -0.765131 1.45853 -0.992279C1.33898 -1.11183 1.23138 -1.33898 1.23138 -1.59004C1.23138 -1.79328 1.30311 -1.99651 1.42267 -2.16389ZM2.60623 -2.04433C1.55417 -2.04433 1.55417 -3.25181 1.55417 -3.52677C1.55417 -3.74197 1.55417 -4.23213 1.75741 -4.55492C1.98456 -4.90162 2.34321 -5.02117 2.59427 -5.02117C3.64633 -5.02117 3.64633 -3.8137 3.64633 -3.53873C3.64633 -3.32354 3.64633 -2.83337 3.44309 -2.51059C3.21594 -2.16389 2.85729 -2.04433 2.60623 -2.04433ZM2.92902 2.19975C1.78132 2.19975 0.908593 1.61395 0.908593 0.932503C0.908593 0.836862 0.932503 0.37061 1.3868 0.0597758C1.64981 -0.107597 1.75741 -0.107597 2.59427 -0.107597C3.58655 -0.107597 4.93748 -0.107597 4.93748 0.932503C4.93748 1.63786 4.02889 2.19975 2.92902 2.19975Z' id='g6-103'/>
<path d='M5.32005 -2.90511C5.32005 -4.01694 5.32005 -4.35168 5.04508 -4.73425C4.69838 -5.2005 4.13649 -5.27223 3.73001 -5.27223C2.70187 -5.27223 2.22366 -4.49514 2.05629 -4.12453H2.04433V-8.29689L0.382565 -8.16538V-7.81868C1.19552 -7.81868 1.29116 -7.73499 1.29116 -7.14919V-0.884682C1.29116 -0.3467 1.15965 -0.3467 0.382565 -0.3467V0C0.6934 -0.0239103 1.33898 -0.0239103 1.67372 -0.0239103C2.02042 -0.0239103 2.666 -0.0239103 2.97684 0V-0.3467C2.21171 -0.3467 2.06824 -0.3467 2.06824 -0.884682V-3.10834C2.06824 -4.36364 2.89315 -5.03313 3.63437 -5.03313S4.54296 -4.42341 4.54296 -3.69415V-0.884682C4.54296 -0.3467 4.41146 -0.3467 3.63437 -0.3467V0C3.94521 -0.0239103 4.59078 -0.0239103 4.92553 -0.0239103C5.27223 -0.0239103 5.91781 -0.0239103 6.22864 0V-0.3467C5.63088 -0.3467 5.332 -0.3467 5.32005 -0.705355V-2.90511Z' id='g6-104'/>
<path d='M2.0802 -7.36438C2.0802 -7.67522 1.82914 -7.95019 1.4944 -7.95019C1.18356 -7.95019 0.920548 -7.69913 0.920548 -7.37634C0.920548 -7.01768 1.20747 -6.79054 1.4944 -6.79054C1.86501 -6.79054 2.0802 -7.10137 2.0802 -7.36438ZM0.430386 -5.14072V-4.79402C1.19552 -4.79402 1.30311 -4.72229 1.30311 -4.13649V-0.884682C1.30311 -0.3467 1.17161 -0.3467 0.394521 -0.3467V0C0.729265 -0.0239103 1.30311 -0.0239103 1.64981 -0.0239103C1.78132 -0.0239103 2.47472 -0.0239103 2.8812 0V-0.3467C2.10411 -0.3467 2.05629 -0.406476 2.05629 -0.872727V-5.27223L0.430386 -5.14072Z' id='g6-105'/>
<path d='M3.34745 -3.16812C3.34745 -3.18007 3.26376 -3.27572 3.26376 -3.28767C3.26376 -3.32354 4.01694 -3.96912 4.11258 -4.06476C4.93748 -4.78207 5.46351 -4.79402 5.71457 -4.80598V-5.15268C5.47547 -5.12877 5.16463 -5.12877 4.80598 -5.12877C4.49514 -5.12877 3.88543 -5.12877 3.61046 -5.15268V-4.80598C3.8137 -4.79402 3.95716 -4.68643 3.95716 -4.49514C3.95716 -4.25604 3.71806 -4.04085 3.7061 -4.04085L1.99651 -2.5345V-8.29689L0.334745 -8.16538V-7.81868C1.1477 -7.81868 1.24334 -7.73499 1.24334 -7.14919V-0.884682C1.24334 -0.3467 1.11183 -0.3467 0.334745 -0.3467V0C0.669489 -0.0239103 1.24334 -0.0239103 1.60199 -0.0239103S2.5345 -0.0239103 2.86924 0V-0.3467C2.10411 -0.3467 1.96065 -0.3467 1.96065 -0.884682V-2.15193L2.72578 -2.82142L3.87347 -1.17161C4.0528 -0.920548 4.13649 -0.789041 4.13649 -0.621669C4.13649 -0.406476 3.96912 -0.3467 3.71806 -0.3467V0C4.01694 -0.0239103 4.60274 -0.0239103 4.92553 -0.0239103C5.4396 -0.0239103 5.46351 -0.0239103 5.97758 0V-0.3467C5.65479 -0.3467 5.28418 -0.3467 4.94944 -0.836862L3.34745 -3.16812Z' id='g6-107'/>
<path d='M2.05629 -8.29689L0.394521 -8.16538V-7.81868C1.20747 -7.81868 1.30311 -7.73499 1.30311 -7.14919V-0.884682C1.30311 -0.3467 1.17161 -0.3467 0.394521 -0.3467V0C0.729265 -0.0239103 1.31507 -0.0239103 1.67372 -0.0239103S2.63014 -0.0239103 2.96488 0V-0.3467C2.19975 -0.3467 2.05629 -0.3467 2.05629 -0.884682V-8.29689Z' id='g6-108'/>
<path d='M8.57186 -2.90511C8.57186 -4.01694 8.57186 -4.35168 8.29689 -4.73425C7.95019 -5.2005 7.38829 -5.27223 6.98182 -5.27223C5.98954 -5.27223 5.48742 -4.55492 5.29614 -4.08867C5.12877 -5.00922 4.48319 -5.27223 3.73001 -5.27223C2.57036 -5.27223 2.11606 -4.27995 2.02042 -4.04085H2.00847V-5.27223L0.382565 -5.14072V-4.79402C1.19552 -4.79402 1.29116 -4.71034 1.29116 -4.12453V-0.884682C1.29116 -0.3467 1.15965 -0.3467 0.382565 -0.3467V0C0.6934 -0.0239103 1.33898 -0.0239103 1.67372 -0.0239103C2.02042 -0.0239103 2.666 -0.0239103 2.97684 0V-0.3467C2.21171 -0.3467 2.06824 -0.3467 2.06824 -0.884682V-3.10834C2.06824 -4.36364 2.89315 -5.03313 3.63437 -5.03313S4.54296 -4.42341 4.54296 -3.69415V-0.884682C4.54296 -0.3467 4.41146 -0.3467 3.63437 -0.3467V0C3.94521 -0.0239103 4.59078 -0.0239103 4.92553 -0.0239103C5.27223 -0.0239103 5.91781 -0.0239103 6.22864 0V-0.3467C5.46351 -0.3467 5.32005 -0.3467 5.32005 -0.884682V-3.10834C5.32005 -4.36364 6.14496 -5.03313 6.88618 -5.03313S7.79477 -4.42341 7.79477 -3.69415V-0.884682C7.79477 -0.3467 7.66326 -0.3467 6.88618 -0.3467V0C7.19701 -0.0239103 7.84259 -0.0239103 8.17733 -0.0239103C8.52403 -0.0239103 9.16961 -0.0239103 9.48045 0V-0.3467C8.88269 -0.3467 8.58381 -0.3467 8.57186 -0.705355V-2.90511Z' id='g6-109'/>
<path d='M5.32005 -2.90511C5.32005 -4.01694 5.32005 -4.35168 5.04508 -4.73425C4.69838 -5.2005 4.13649 -5.27223 3.73001 -5.27223C2.57036 -5.27223 2.11606 -4.27995 2.02042 -4.04085H2.00847V-5.27223L0.382565 -5.14072V-4.79402C1.19552 -4.79402 1.29116 -4.71034 1.29116 -4.12453V-0.884682C1.29116 -0.3467 1.15965 -0.3467 0.382565 -0.3467V0C0.6934 -0.0239103 1.33898 -0.0239103 1.67372 -0.0239103C2.02042 -0.0239103 2.666 -0.0239103 2.97684 0V-0.3467C2.21171 -0.3467 2.06824 -0.3467 2.06824 -0.884682V-3.10834C2.06824 -4.36364 2.89315 -5.03313 3.63437 -5.03313S4.54296 -4.42341 4.54296 -3.69415V-0.884682C4.54296 -0.3467 4.41146 -0.3467 3.63437 -0.3467V0C3.94521 -0.0239103 4.59078 -0.0239103 4.92553 -0.0239103C5.27223 -0.0239103 5.91781 -0.0239103 6.22864 0V-0.3467C5.63088 -0.3467 5.332 -0.3467 5.32005 -0.705355V-2.90511Z' id='g6-110'/>
<path d='M5.48742 -2.55841C5.48742 -4.10062 4.31582 -5.332 2.92902 -5.332C1.4944 -5.332 0.358655 -4.06476 0.358655 -2.55841C0.358655 -1.02814 1.55417 0.119552 2.91706 0.119552C4.32777 0.119552 5.48742 -1.05205 5.48742 -2.55841ZM2.92902 -0.143462C2.48667 -0.143462 1.94869 -0.334745 1.60199 -0.920548C1.2792 -1.45853 1.26725 -2.16389 1.26725 -2.666C1.26725 -3.1203 1.26725 -3.84956 1.63786 -4.38755C1.9726 -4.90162 2.49863 -5.0929 2.91706 -5.0929C3.38331 -5.0929 3.88543 -4.87771 4.20822 -4.41146C4.57883 -3.86152 4.57883 -3.10834 4.57883 -2.666C4.57883 -2.24757 4.57883 -1.50635 4.268 -0.944458C3.93325 -0.37061 3.38331 -0.143462 2.92902 -0.143462Z' id='g6-111'/>
<path d='M1.99651 -2.78555C1.99651 -3.94521 2.47472 -5.03313 3.39527 -5.03313C3.49091 -5.03313 3.51482 -5.03313 3.56264 -5.02117C3.467 -4.97335 3.27572 -4.90162 3.27572 -4.57883C3.27572 -4.23213 3.55068 -4.10062 3.74197 -4.10062C3.98107 -4.10062 4.22017 -4.25604 4.22017 -4.57883C4.22017 -4.93748 3.89738 -5.27223 3.38331 -5.27223C2.36712 -5.27223 2.02042 -4.17235 1.94869 -3.94521H1.93674V-5.27223L0.334745 -5.14072V-4.79402C1.1477 -4.79402 1.24334 -4.71034 1.24334 -4.12453V-0.884682C1.24334 -0.3467 1.11183 -0.3467 0.334745 -0.3467V0C0.669489 -0.0239103 1.32702 -0.0239103 1.68568 -0.0239103C2.00847 -0.0239103 2.85729 -0.0239103 3.13225 0V-0.3467H2.89315C2.02042 -0.3467 1.99651 -0.478207 1.99651 -0.908593V-2.78555Z' id='g6-114'/>
<path d='M3.9213 -5.05704C3.9213 -5.27223 3.9213 -5.332 3.80174 -5.332C3.7061 -5.332 3.47895 -5.06899 3.39527 -4.96139C3.02466 -5.26027 2.65405 -5.332 2.27148 -5.332C0.824907 -5.332 0.394521 -4.54296 0.394521 -3.88543C0.394521 -3.75392 0.394521 -3.33549 0.848817 -2.91706C1.23138 -2.58232 1.63786 -2.49863 2.1878 -2.39103C2.84533 -2.25953 3.00075 -2.22366 3.29963 -1.98456C3.51482 -1.80523 3.67024 -1.54222 3.67024 -1.20747C3.67024 -0.6934 3.37136 -0.119552 2.3193 -0.119552C1.53026 -0.119552 0.956413 -0.573848 0.6934 -1.76936C0.645579 -1.98456 0.645579 -1.99651 0.633624 -2.00847C0.609714 -2.05629 0.561893 -2.05629 0.526027 -2.05629C0.394521 -2.05629 0.394521 -1.99651 0.394521 -1.78132V-0.155417C0.394521 0.0597758 0.394521 0.119552 0.514072 0.119552C0.573848 0.119552 0.585803 0.107597 0.789041 -0.143462C0.848817 -0.227148 0.848817 -0.251059 1.02814 -0.442341C1.48244 0.119552 2.12802 0.119552 2.33126 0.119552C3.58655 0.119552 4.20822 -0.573848 4.20822 -1.51831C4.20822 -2.16389 3.8137 -2.54645 3.7061 -2.65405C3.27572 -3.02466 2.95293 -3.09639 2.16389 -3.23985C1.80523 -3.31158 0.932503 -3.47895 0.932503 -4.19626C0.932503 -4.56687 1.18356 -5.11681 2.25953 -5.11681C3.56264 -5.11681 3.63437 -4.00498 3.65828 -3.63437C3.67024 -3.53873 3.75392 -3.53873 3.78979 -3.53873C3.9213 -3.53873 3.9213 -3.59851 3.9213 -3.8137V-5.05704Z' id='g6-115'/>
<path d='M2.00847 -4.80598H3.69415V-5.15268H2.00847V-7.35243H1.74545C1.7335 -6.22864 1.30311 -5.08095 0.215193 -5.04508V-4.80598H1.23138V-1.48244C1.23138 -0.155417 2.11606 0.119552 2.74969 0.119552C3.50286 0.119552 3.89738 -0.621669 3.89738 -1.48244V-2.16389H3.63437V-1.50635C3.63437 -0.645579 3.28767 -0.143462 2.82142 -0.143462C2.00847 -0.143462 2.00847 -1.25529 2.00847 -1.45853V-4.80598Z' id='g6-116'/>
<path d='M4.87771 -4.01694C4.98531 -4.27995 5.18854 -4.79402 5.95367 -4.80598V-5.15268C5.60697 -5.12877 5.4396 -5.12877 5.06899 -5.12877C4.81793 -5.12877 4.63861 -5.12877 4.08867 -5.15268V-4.80598C4.59078 -4.78207 4.65056 -4.42341 4.65056 -4.29191C4.65056 -4.18431 4.62665 -4.12453 4.56687 -3.98107L3.34745 -0.896638L2.00847 -4.268C1.94869 -4.43537 1.93674 -4.43537 1.93674 -4.49514C1.93674 -4.80598 2.39103 -4.80598 2.60623 -4.80598V-5.15268C2.30735 -5.12877 1.68568 -5.12877 1.36289 -5.12877C0.968369 -5.12877 0.944458 -5.12877 0.215193 -5.15268V-4.80598C0.884682 -4.80598 1.00423 -4.75816 1.1477 -4.38755L2.85729 -0.107597C2.91706 0.0597758 2.94097 0.119552 3.08443 0.119552C3.16812 0.119552 3.23985 0.0956413 3.32354 -0.107597L4.87771 -4.01694Z' id='g6-118'/>
<path d='M7.23288 -4.01694C7.49589 -4.77011 8.02192 -4.79402 8.22516 -4.80598V-5.15268C7.92628 -5.12877 7.71108 -5.12877 7.34047 -5.12877C6.99377 -5.12877 6.96986 -5.12877 6.32428 -5.15268V-4.80598C6.86227 -4.78207 7.00573 -4.45928 7.00573 -4.23213C7.00573 -4.22017 7.00573 -4.13649 6.95791 -4.01694L5.85803 -0.884682L4.66252 -4.268C4.60274 -4.41146 4.60274 -4.43537 4.60274 -4.47123C4.60274 -4.80598 5.04508 -4.80598 5.29614 -4.80598V-5.15268C4.96139 -5.12877 4.47123 -5.12877 4.12453 -5.12877C3.74197 -5.12877 3.71806 -5.12877 3.04857 -5.15268V-4.80598C3.50286 -4.80598 3.65828 -4.78207 3.78979 -4.62665C3.84956 -4.55492 3.99303 -4.1604 4.07671 -3.9213L3.06052 -1.00423L1.91283 -4.25604C1.85305 -4.41146 1.85305 -4.43537 1.85305 -4.48319C1.85305 -4.80598 2.3193 -4.80598 2.54645 -4.80598V-5.15268C2.24757 -5.12877 1.64981 -5.12877 1.32702 -5.12877C0.992279 -5.12877 0.968369 -5.12877 0.215193 -5.15268V-4.80598C0.824907 -4.80598 0.944458 -4.75816 1.07597 -4.37559L2.58232 -0.0956413C2.63014 0.0358655 2.666 0.119552 2.79751 0.119552C2.90511 0.119552 2.96488 0.0836862 3.02466 -0.107597L4.22017 -3.51482L5.41569 -0.107597C5.47547 0.0836862 5.53524 0.119552 5.64284 0.119552C5.77435 0.119552 5.81021 0.0358655 5.85803 -0.0956413L7.23288 -4.01694Z' id='g6-119'/>
<path d='M3.34745 -2.82142C3.69415 -3.27572 4.19626 -3.9213 4.42341 -4.17235C4.91357 -4.72229 5.47547 -4.80598 5.85803 -4.80598V-5.15268C5.34396 -5.12877 5.32005 -5.12877 4.8538 -5.12877C4.3995 -5.12877 4.37559 -5.12877 3.77783 -5.15268V-4.80598C3.93325 -4.78207 4.12453 -4.71034 4.12453 -4.43537C4.12453 -4.23213 4.01694 -4.10062 3.94521 -4.00498L3.18007 -3.03661L2.24757 -4.268C2.21171 -4.31582 2.13998 -4.42341 2.13998 -4.5071C2.13998 -4.57883 2.19975 -4.79402 2.55841 -4.80598V-5.15268C2.25953 -5.12877 1.64981 -5.12877 1.32702 -5.12877C0.932503 -5.12877 0.908593 -5.12877 0.179328 -5.15268V-4.80598C0.789041 -4.80598 1.01619 -4.78207 1.26725 -4.45928L2.666 -2.63014C2.68991 -2.60623 2.73773 -2.5345 2.73773 -2.49863S1.80523 -1.29116 1.68568 -1.13574C1.15965 -0.490162 0.633624 -0.358655 0.119552 -0.3467V0C0.573848 -0.0239103 0.597758 -0.0239103 1.11183 -0.0239103C1.56613 -0.0239103 1.59004 -0.0239103 2.1878 0V-0.3467C1.90087 -0.382565 1.85305 -0.561893 1.85305 -0.729265C1.85305 -0.920548 1.93674 -1.01619 2.05629 -1.17161C2.23562 -1.42267 2.63014 -1.91283 2.91706 -2.28344L3.89738 -1.00423C4.10062 -0.74122 4.10062 -0.71731 4.10062 -0.645579C4.10062 -0.549938 4.00498 -0.358655 3.68219 -0.3467V0C3.99303 -0.0239103 4.57883 -0.0239103 4.91357 -0.0239103C5.30809 -0.0239103 5.332 -0.0239103 6.04932 0V-0.3467C5.41569 -0.3467 5.2005 -0.37061 4.91357 -0.753176L3.34745 -2.82142Z' id='g6-120'/>
<path d='M2.1599 1.99253V1.6259H1.35492V-5.61096H2.1599V-5.97758H0.988294V1.99253H2.1599Z' id='g5-91'/>
<path d='M1.35492 -5.97758H0.183313V-5.61096H0.988294V1.6259H0.183313V1.99253H1.35492V-5.97758Z' id='g5-93'/>
<path d='M6.55143 -2.74969C6.75467 -2.74969 6.96986 -2.74969 6.96986 -2.98879S6.75467 -3.2279 6.55143 -3.2279H1.48244C1.6259 -4.82989 3.00075 -5.97758 4.68643 -5.97758H6.55143C6.75467 -5.97758 6.96986 -5.97758 6.96986 -6.21669S6.75467 -6.45579 6.55143 -6.45579H4.66252C2.61818 -6.45579 0.992279 -4.90162 0.992279 -2.98879S2.61818 0.478207 4.66252 0.478207H6.55143C6.75467 0.478207 6.96986 0.478207 6.96986 0.239103S6.75467 0 6.55143 0H4.68643C3.00075 0 1.6259 -1.1477 1.48244 -2.74969H6.55143Z' id='g2-50'/>
<path d='M3.38331 -7.37634C3.38331 -7.85455 3.69415 -8.61968 4.99726 -8.70336C5.05704 -8.71532 5.10486 -8.76314 5.10486 -8.83487C5.10486 -8.96638 5.00922 -8.96638 4.87771 -8.96638C3.68219 -8.96638 2.59427 -8.35666 2.58232 -7.47198V-4.7462C2.58232 -4.27995 2.58232 -3.89738 2.10411 -3.50286C1.68568 -3.15616 1.23138 -3.13225 0.968369 -3.1203C0.908593 -3.10834 0.860772 -3.06052 0.860772 -2.98879C0.860772 -2.86924 0.932503 -2.86924 1.05205 -2.85729C1.8411 -2.80946 2.41494 -2.37908 2.54645 -1.79328C2.58232 -1.66177 2.58232 -1.63786 2.58232 -1.20747V1.15965C2.58232 1.66177 2.58232 2.04433 3.15616 2.49863C3.62242 2.85729 4.41146 2.98879 4.87771 2.98879C5.00922 2.98879 5.10486 2.98879 5.10486 2.85729C5.10486 2.73773 5.03313 2.73773 4.91357 2.72578C4.1604 2.67796 3.5746 2.29539 3.41918 1.68568C3.38331 1.57808 3.38331 1.55417 3.38331 1.12379V-1.3868C3.38331 -1.93674 3.28767 -2.13998 2.90511 -2.52254C2.65405 -2.7736 2.30735 -2.89315 1.9726 -2.98879C2.95293 -3.26376 3.38331 -3.8137 3.38331 -4.5071V-7.37634Z' id='g2-102'/>
<path d='M2.58232 1.39875C2.58232 1.87696 2.27148 2.64209 0.968369 2.72578C0.908593 2.73773 0.860772 2.78555 0.860772 2.85729C0.860772 2.98879 0.992279 2.98879 1.09988 2.98879C2.25953 2.98879 3.37136 2.40299 3.38331 1.4944V-1.23138C3.38331 -1.69763 3.38331 -2.0802 3.86152 -2.47472C4.27995 -2.82142 4.73425 -2.84533 4.99726 -2.85729C5.05704 -2.86924 5.10486 -2.91706 5.10486 -2.98879C5.10486 -3.10834 5.03313 -3.10834 4.91357 -3.1203C4.12453 -3.16812 3.55068 -3.59851 3.41918 -4.18431C3.38331 -4.31582 3.38331 -4.33973 3.38331 -4.77011V-7.13724C3.38331 -7.63935 3.38331 -8.02192 2.80946 -8.47621C2.33126 -8.84682 1.50635 -8.96638 1.09988 -8.96638C0.992279 -8.96638 0.860772 -8.96638 0.860772 -8.83487C0.860772 -8.71532 0.932503 -8.71532 1.05205 -8.70336C1.80523 -8.65554 2.39103 -8.27298 2.54645 -7.66326C2.58232 -7.55567 2.58232 -7.53176 2.58232 -7.10137V-4.59078C2.58232 -4.04085 2.67796 -3.83761 3.06052 -3.45504C3.31158 -3.20399 3.65828 -3.08443 3.99303 -2.98879C3.0127 -2.71382 2.58232 -2.16389 2.58232 -1.47049V1.39875Z' id='g2-103'/>
<path d='M1.90087 -8.53599C1.90087 -8.75118 1.90087 -8.96638 1.66177 -8.96638S1.42267 -8.75118 1.42267 -8.53599V2.55841C1.42267 2.7736 1.42267 2.98879 1.66177 2.98879S1.90087 2.7736 1.90087 2.55841V-8.53599Z' id='g2-106'/>
<path d='M2.33126 0.0478207C2.33126 -0.645579 2.10411 -1.15965 1.61395 -1.15965C1.23138 -1.15965 1.0401 -0.848817 1.0401 -0.585803S1.21943 0 1.6259 0C1.78132 0 1.91283 -0.0478207 2.02042 -0.155417C2.04433 -0.179328 2.05629 -0.179328 2.06824 -0.179328C2.09215 -0.179328 2.09215 -0.0119552 2.09215 0.0478207C2.09215 0.442341 2.02042 1.21943 1.32702 1.99651C1.19552 2.13998 1.19552 2.16389 1.19552 2.1878C1.19552 2.24757 1.25529 2.30735 1.31507 2.30735C1.41071 2.30735 2.33126 1.42267 2.33126 0.0478207Z' id='g4-59'/>
<path d='M2.03238 -1.32702C1.61395 -0.621669 1.20747 -0.382565 0.633624 -0.3467C0.502117 -0.334745 0.406476 -0.334745 0.406476 -0.119552C0.406476 -0.0478207 0.466252 0 0.549938 0C0.765131 0 1.30311 -0.0239103 1.51831 -0.0239103C1.86501 -0.0239103 2.24757 0 2.58232 0C2.65405 0 2.79751 0 2.79751 -0.227148C2.79751 -0.334745 2.70187 -0.3467 2.63014 -0.3467C2.35517 -0.37061 2.12802 -0.466252 2.12802 -0.753176C2.12802 -0.920548 2.19975 -1.05205 2.35517 -1.31507L3.26376 -2.82142H6.31233C6.32428 -2.71382 6.32428 -2.61818 6.33624 -2.51059C6.3721 -2.19975 6.51557 -0.956413 6.51557 -0.729265C6.51557 -0.37061 5.90585 -0.3467 5.71457 -0.3467C5.58306 -0.3467 5.45156 -0.3467 5.45156 -0.131507C5.45156 0 5.55915 0 5.63088 0C5.83412 0 6.07323 -0.0239103 6.27646 -0.0239103H6.95791C7.68717 -0.0239103 8.2132 0 8.22516 0C8.30884 0 8.44035 0 8.44035 -0.227148C8.44035 -0.3467 8.33275 -0.3467 8.15342 -0.3467C7.49589 -0.3467 7.48394 -0.454296 7.44807 -0.812951L6.7188 -8.27298C6.69489 -8.51208 6.64707 -8.53599 6.51557 -8.53599C6.39601 -8.53599 6.32428 -8.51208 6.21669 -8.33275L2.03238 -1.32702ZM3.467 -3.16812L5.86999 -7.18506L6.27646 -3.16812H3.467Z' id='g4-65'/>
<path d='M4.37559 -7.35243C4.48319 -7.79477 4.53101 -7.81868 4.99726 -7.81868H6.55143C7.90237 -7.81868 7.90237 -6.67098 7.90237 -6.56339C7.90237 -5.59502 6.934 -4.36364 5.35592 -4.36364H3.63437L4.37559 -7.35243ZM6.39601 -4.268C7.69913 -4.5071 8.88269 -5.41569 8.88269 -6.51557C8.88269 -7.44807 8.05778 -8.16538 6.70685 -8.16538H2.86924C2.64209 -8.16538 2.5345 -8.16538 2.5345 -7.93823C2.5345 -7.81868 2.64209 -7.81868 2.82142 -7.81868C3.55068 -7.81868 3.55068 -7.72304 3.55068 -7.59153C3.55068 -7.56762 3.55068 -7.49589 3.50286 -7.31656L1.88892 -0.884682C1.78132 -0.466252 1.75741 -0.3467 0.920548 -0.3467C0.6934 -0.3467 0.573848 -0.3467 0.573848 -0.131507C0.573848 0 0.645579 0 0.884682 0H4.98531C6.81445 0 8.22516 -1.3868 8.22516 -2.59427C8.22516 -3.5746 7.36438 -4.17235 6.39601 -4.268ZM4.69838 -0.3467H3.08443C2.91706 -0.3467 2.89315 -0.3467 2.82142 -0.358655C2.68991 -0.37061 2.67796 -0.394521 2.67796 -0.490162C2.67796 -0.573848 2.70187 -0.645579 2.72578 -0.753176L3.56264 -4.12453H5.81021C7.22092 -4.12453 7.22092 -2.80946 7.22092 -2.71382C7.22092 -1.56613 6.18082 -0.3467 4.69838 -0.3467Z' id='g4-66'/>
<path d='M8.93051 -8.30884C8.93051 -8.41644 8.84682 -8.41644 8.82291 -8.41644S8.75118 -8.41644 8.65554 -8.29689L7.83064 -7.29265C7.4122 -8.00996 6.75467 -8.41644 5.85803 -8.41644C3.27572 -8.41644 0.597758 -5.79826 0.597758 -2.98879C0.597758 -0.992279 1.99651 0.251059 3.74197 0.251059C4.69838 0.251059 5.53524 -0.155417 6.22864 -0.74122C7.26874 -1.61395 7.57958 -2.7736 7.57958 -2.86924C7.57958 -2.97684 7.48394 -2.97684 7.44807 -2.97684C7.34047 -2.97684 7.32852 -2.90511 7.30461 -2.85729C6.75467 -0.992279 5.14072 -0.0956413 3.94521 -0.0956413C2.67796 -0.0956413 1.57808 -0.908593 1.57808 -2.60623C1.57808 -2.98879 1.69763 -5.06899 3.04857 -6.63512C3.7061 -7.40025 4.82989 -8.06974 5.96563 -8.06974C7.2807 -8.06974 7.8665 -6.98182 7.8665 -5.76239C7.8665 -5.45156 7.83064 -5.18854 7.83064 -5.14072C7.83064 -5.03313 7.95019 -5.03313 7.98605 -5.03313C8.11756 -5.03313 8.12951 -5.04508 8.17733 -5.26027L8.93051 -8.30884Z' id='g4-67'/>
<path d='M8.30884 -2.7736C8.3208 -2.80946 8.35666 -2.89315 8.35666 -2.94097C8.35666 -3.00075 8.30884 -3.06052 8.23711 -3.06052C8.18929 -3.06052 8.16538 -3.04857 8.12951 -3.0127C8.1056 -3.00075 8.1056 -2.97684 7.99801 -2.73773C7.29265 -1.06401 6.77858 -0.3467 4.86575 -0.3467H3.1203C2.95293 -0.3467 2.92902 -0.3467 2.85729 -0.358655C2.72578 -0.37061 2.71382 -0.394521 2.71382 -0.490162C2.71382 -0.573848 2.73773 -0.645579 2.76164 -0.753176L3.58655 -4.0528H4.77011C5.70262 -4.0528 5.77435 -3.84956 5.77435 -3.49091C5.77435 -3.37136 5.77435 -3.26376 5.69066 -2.90511C5.66675 -2.85729 5.65479 -2.80946 5.65479 -2.7736C5.65479 -2.68991 5.71457 -2.65405 5.7863 -2.65405C5.8939 -2.65405 5.90585 -2.73773 5.95367 -2.90511L6.63512 -5.6787C6.63512 -5.73848 6.5873 -5.79826 6.51557 -5.79826C6.40797 -5.79826 6.39601 -5.75044 6.34819 -5.58306C6.10909 -4.66252 5.86999 -4.3995 4.80598 -4.3995H3.67024L4.41146 -7.34047C4.51905 -7.7589 4.54296 -7.79477 5.03313 -7.79477H6.74271C8.2132 -7.79477 8.51208 -7.40025 8.51208 -6.49166C8.51208 -6.4797 8.51208 -6.14496 8.46426 -5.75044C8.4523 -5.70262 8.44035 -5.63088 8.44035 -5.60697C8.44035 -5.51133 8.50012 -5.47547 8.57186 -5.47547C8.65554 -5.47547 8.70336 -5.52329 8.72727 -5.73848L8.97833 -7.83064C8.97833 -7.8665 9.00224 -7.98605 9.00224 -8.00996C9.00224 -8.14147 8.89465 -8.14147 8.67945 -8.14147H2.84533C2.61818 -8.14147 2.49863 -8.14147 2.49863 -7.92628C2.49863 -7.79477 2.58232 -7.79477 2.78555 -7.79477C3.52677 -7.79477 3.52677 -7.71108 3.52677 -7.57958C3.52677 -7.5198 3.51482 -7.47198 3.47895 -7.34047L1.86501 -0.884682C1.75741 -0.466252 1.7335 -0.3467 0.896638 -0.3467C0.669489 -0.3467 0.549938 -0.3467 0.549938 -0.131507C0.549938 0 0.621669 0 0.860772 0H6.86227C7.12528 0 7.13724 -0.0119552 7.22092 -0.203238L8.30884 -2.7736Z' id='g4-69'/>
<path d='M4.3995 -7.2807C4.5071 -7.69913 4.53101 -7.81868 5.40374 -7.81868C5.66675 -7.81868 5.76239 -7.81868 5.76239 -8.04583C5.76239 -8.16538 5.63088 -8.16538 5.59502 -8.16538C5.37983 -8.16538 5.11681 -8.14147 4.90162 -8.14147H3.43113C3.19203 -8.14147 2.91706 -8.16538 2.67796 -8.16538C2.58232 -8.16538 2.45081 -8.16538 2.45081 -7.93823C2.45081 -7.81868 2.54645 -7.81868 2.78555 -7.81868C3.52677 -7.81868 3.52677 -7.72304 3.52677 -7.59153C3.52677 -7.50785 3.50286 -7.43611 3.47895 -7.32852L1.86501 -0.884682C1.75741 -0.466252 1.7335 -0.3467 0.860772 -0.3467C0.597758 -0.3467 0.490162 -0.3467 0.490162 -0.119552C0.490162 0 0.609714 0 0.669489 0C0.884682 0 1.1477 -0.0239103 1.36289 -0.0239103H2.83337C3.07248 -0.0239103 3.33549 0 3.5746 0C3.67024 0 3.8137 0 3.8137 -0.215193C3.8137 -0.3467 3.74197 -0.3467 3.47895 -0.3467C2.73773 -0.3467 2.73773 -0.442341 2.73773 -0.585803C2.73773 -0.609714 2.73773 -0.669489 2.78555 -0.860772L4.3995 -7.2807Z' id='g4-73'/>
<path d='M4.38755 -7.24483C4.49514 -7.69913 4.53101 -7.81868 5.58306 -7.81868C5.90585 -7.81868 5.98954 -7.81868 5.98954 -8.04583C5.98954 -8.16538 5.85803 -8.16538 5.81021 -8.16538C5.57111 -8.16538 5.29614 -8.14147 5.05704 -8.14147H3.45504C3.2279 -8.14147 2.96488 -8.16538 2.73773 -8.16538C2.64209 -8.16538 2.51059 -8.16538 2.51059 -7.93823C2.51059 -7.81868 2.61818 -7.81868 2.79751 -7.81868C3.52677 -7.81868 3.52677 -7.72304 3.52677 -7.59153C3.52677 -7.56762 3.52677 -7.49589 3.47895 -7.31656L1.86501 -0.884682C1.75741 -0.466252 1.7335 -0.3467 0.896638 -0.3467C0.669489 -0.3467 0.549938 -0.3467 0.549938 -0.131507C0.549938 0 0.621669 0 0.860772 0H6.21669C6.4797 0 6.49166 -0.0119552 6.57534 -0.227148L7.49589 -2.7736C7.5198 -2.83337 7.54371 -2.90511 7.54371 -2.94097C7.54371 -3.0127 7.48394 -3.06052 7.42416 -3.06052C7.4122 -3.06052 7.35243 -3.06052 7.32852 -3.0127C7.30461 -3.00075 7.30461 -2.97684 7.20897 -2.74969C6.8264 -1.69763 6.28842 -0.3467 4.268 -0.3467H3.1203C2.95293 -0.3467 2.92902 -0.3467 2.85729 -0.358655C2.72578 -0.37061 2.71382 -0.394521 2.71382 -0.490162C2.71382 -0.573848 2.73773 -0.645579 2.76164 -0.753176L4.38755 -7.24483Z' id='g4-76'/>
<path d='M8.84682 -6.91009C8.97833 -7.42416 9.16961 -7.78281 10.0782 -7.81868C10.1141 -7.81868 10.2575 -7.83064 10.2575 -8.03387C10.2575 -8.16538 10.1499 -8.16538 10.1021 -8.16538C9.86301 -8.16538 9.2533 -8.14147 9.0142 -8.14147H8.44035C8.27298 -8.14147 8.05778 -8.16538 7.89041 -8.16538C7.81868 -8.16538 7.67522 -8.16538 7.67522 -7.93823C7.67522 -7.81868 7.77086 -7.81868 7.85455 -7.81868C8.57186 -7.79477 8.61968 -7.5198 8.61968 -7.30461C8.61968 -7.19701 8.60772 -7.16115 8.57186 -6.99377L7.22092 -1.60199L4.66252 -7.96214C4.57883 -8.15342 4.56687 -8.16538 4.30386 -8.16538H2.84533C2.60623 -8.16538 2.49863 -8.16538 2.49863 -7.93823C2.49863 -7.81868 2.58232 -7.81868 2.80946 -7.81868C2.86924 -7.81868 3.5746 -7.81868 3.5746 -7.71108C3.5746 -7.68717 3.55068 -7.59153 3.53873 -7.55567L1.94869 -1.21943C1.80523 -0.633624 1.51831 -0.382565 0.729265 -0.3467C0.669489 -0.3467 0.549938 -0.334745 0.549938 -0.119552C0.549938 0 0.669489 0 0.705355 0C0.944458 0 1.55417 -0.0239103 1.79328 -0.0239103H2.36712C2.5345 -0.0239103 2.73773 0 2.90511 0C2.98879 0 3.1203 0 3.1203 -0.227148C3.1203 -0.334745 3.00075 -0.3467 2.95293 -0.3467C2.55841 -0.358655 2.17584 -0.430386 2.17584 -0.860772C2.17584 -0.956413 2.19975 -1.06401 2.22366 -1.15965L3.83761 -7.55567C3.90934 -7.43611 3.90934 -7.4122 3.95716 -7.30461L6.80249 -0.215193C6.86227 -0.071731 6.88618 0 6.99377 0C7.11333 0 7.12528 -0.0358655 7.1731 -0.239103L8.84682 -6.91009Z' id='g4-78'/>
<path d='M8.67945 -5.23636C8.67945 -7.20897 7.38829 -8.41644 5.71457 -8.41644C3.15616 -8.41644 0.573848 -5.66675 0.573848 -2.90511C0.573848 -1.02814 1.81719 0.251059 3.55068 0.251059C6.06127 0.251059 8.67945 -2.36712 8.67945 -5.23636ZM3.62242 -0.0239103C2.64209 -0.0239103 1.60199 -0.74122 1.60199 -2.60623C1.60199 -3.69415 1.99651 -5.47547 2.97684 -6.67098C3.84956 -7.72304 4.8538 -8.15342 5.65479 -8.15342C6.70685 -8.15342 7.72304 -7.38829 7.72304 -5.66675C7.72304 -4.60274 7.26874 -2.94097 6.46775 -1.80523C5.59502 -0.585803 4.5071 -0.0239103 3.62242 -0.0239103Z' id='g4-79'/>
<path d='M4.3995 -7.35243C4.5071 -7.79477 4.55492 -7.81868 5.02117 -7.81868H5.88194C6.91009 -7.81868 7.67522 -7.50785 7.67522 -6.57534C7.67522 -5.96563 7.36438 -4.20822 4.96139 -4.20822H3.61046L4.3995 -7.35243ZM6.06127 -4.06476C7.54371 -4.38755 8.70336 -5.34396 8.70336 -6.3721C8.70336 -7.30461 7.7589 -8.16538 6.09714 -8.16538H2.85729C2.61818 -8.16538 2.51059 -8.16538 2.51059 -7.93823C2.51059 -7.81868 2.59427 -7.81868 2.82142 -7.81868C3.53873 -7.81868 3.53873 -7.72304 3.53873 -7.59153C3.53873 -7.56762 3.53873 -7.49589 3.49091 -7.31656L1.87696 -0.884682C1.76936 -0.466252 1.74545 -0.3467 0.920548 -0.3467C0.645579 -0.3467 0.561893 -0.3467 0.561893 -0.119552C0.561893 0 0.6934 0 0.729265 0C0.944458 0 1.19552 -0.0239103 1.42267 -0.0239103H2.83337C3.04857 -0.0239103 3.29963 0 3.51482 0C3.61046 0 3.74197 0 3.74197 -0.227148C3.74197 -0.3467 3.63437 -0.3467 3.45504 -0.3467C2.72578 -0.3467 2.72578 -0.442341 2.72578 -0.561893C2.72578 -0.573848 2.72578 -0.657534 2.74969 -0.753176L3.55068 -3.96912H4.98531C6.12105 -3.96912 6.33624 -3.25181 6.33624 -2.85729C6.33624 -2.67796 6.21669 -2.21171 6.133 -1.90087C6.00149 -1.35093 5.96563 -1.21943 5.96563 -0.992279C5.96563 -0.143462 6.65903 0.251059 7.46002 0.251059C8.42839 0.251059 8.84682 -0.932503 8.84682 -1.09988C8.84682 -1.18356 8.78705 -1.21943 8.71532 -1.21943C8.61968 -1.21943 8.59577 -1.1477 8.57186 -1.05205C8.28493 -0.203238 7.79477 0.0119552 7.49589 0.0119552S7.00573 -0.119552 7.00573 -0.657534C7.00573 -0.944458 7.14919 -2.03238 7.16115 -2.09215C7.22092 -2.5345 7.22092 -2.58232 7.22092 -2.67796C7.22092 -3.55068 6.51557 -3.9213 6.06127 -4.06476Z' id='g4-82'/>
<path d='M7.59153 -8.30884C7.59153 -8.41644 7.50785 -8.41644 7.48394 -8.41644C7.43611 -8.41644 7.42416 -8.40448 7.2807 -8.22516C7.20897 -8.14147 6.7188 -7.5198 6.70685 -7.50785C6.31233 -8.28493 5.52329 -8.41644 5.02117 -8.41644C3.50286 -8.41644 2.12802 -7.02964 2.12802 -5.6787C2.12802 -4.78207 2.666 -4.25604 3.25181 -4.0528C3.38331 -4.00498 4.08867 -3.8137 4.44732 -3.73001C5.05704 -3.56264 5.21245 -3.51482 5.46351 -3.25181C5.51133 -3.19203 5.75044 -2.91706 5.75044 -2.35517C5.75044 -1.24334 4.72229 -0.0956413 3.52677 -0.0956413C2.54645 -0.0956413 1.45853 -0.514072 1.45853 -1.85305C1.45853 -2.0802 1.50635 -2.36712 1.54222 -2.48667C1.54222 -2.52254 1.55417 -2.58232 1.55417 -2.60623C1.55417 -2.65405 1.53026 -2.71382 1.43462 -2.71382C1.32702 -2.71382 1.31507 -2.68991 1.26725 -2.48667L0.657534 -0.0358655C0.657534 -0.0239103 0.609714 0.131507 0.609714 0.143462C0.609714 0.251059 0.705355 0.251059 0.729265 0.251059C0.777086 0.251059 0.789041 0.239103 0.932503 0.0597758L1.48244 -0.657534C1.76936 -0.227148 2.39103 0.251059 3.50286 0.251059C5.04508 0.251059 6.45579 -1.24334 6.45579 -2.73773C6.45579 -3.23985 6.33624 -3.68219 5.88194 -4.12453C5.63088 -4.37559 5.41569 -4.43537 4.31582 -4.72229C3.51482 -4.93748 3.40722 -4.97335 3.19203 -5.16463C2.98879 -5.36787 2.83337 -5.65479 2.83337 -6.06127C2.83337 -7.0655 3.84956 -8.09365 4.98531 -8.09365C6.15691 -8.09365 6.70685 -7.37634 6.70685 -6.2406C6.70685 -5.92976 6.64707 -5.60697 6.64707 -5.55915C6.64707 -5.45156 6.74271 -5.45156 6.77858 -5.45156C6.88618 -5.45156 6.89813 -5.48742 6.94595 -5.6787L7.59153 -8.30884Z' id='g4-83'/>
<path d='M4.98531 -7.29265C5.05704 -7.57958 5.08095 -7.68717 5.26027 -7.73499C5.35592 -7.7589 5.75044 -7.7589 6.00149 -7.7589C7.19701 -7.7589 7.7589 -7.71108 7.7589 -6.77858C7.7589 -6.59925 7.71108 -6.14496 7.63935 -5.70262L7.6274 -5.55915C7.6274 -5.51133 7.67522 -5.4396 7.74695 -5.4396C7.8665 -5.4396 7.8665 -5.49938 7.90237 -5.69066L8.24907 -7.80672C8.27298 -7.91432 8.27298 -7.93823 8.27298 -7.9741C8.27298 -8.1056 8.20125 -8.1056 7.96214 -8.1056H1.42267C1.1477 -8.1056 1.13574 -8.09365 1.06401 -7.87846L0.334745 -5.72653C0.32279 -5.70262 0.286924 -5.57111 0.286924 -5.55915C0.286924 -5.49938 0.334745 -5.4396 0.406476 -5.4396C0.502117 -5.4396 0.526027 -5.48742 0.573848 -5.64284C1.07597 -7.08941 1.32702 -7.7589 2.91706 -7.7589H3.71806C4.00498 -7.7589 4.12453 -7.7589 4.12453 -7.6274C4.12453 -7.59153 4.12453 -7.56762 4.06476 -7.35243L2.46276 -0.932503C2.34321 -0.466252 2.3193 -0.3467 1.05205 -0.3467C0.753176 -0.3467 0.669489 -0.3467 0.669489 -0.119552C0.669489 0 0.800996 0 0.860772 0C1.15965 0 1.47049 -0.0239103 1.76936 -0.0239103H3.63437C3.93325 -0.0239103 4.25604 0 4.55492 0C4.68643 0 4.80598 0 4.80598 -0.227148C4.80598 -0.3467 4.72229 -0.3467 4.41146 -0.3467C3.33549 -0.3467 3.33549 -0.454296 3.33549 -0.633624C3.33549 -0.645579 3.33549 -0.729265 3.38331 -0.920548L4.98531 -7.29265Z' id='g4-84'/>
<path d='M6.04932 -2.74969C5.63088 -1.07597 4.24408 -0.0956413 3.1203 -0.0956413C2.25953 -0.0956413 1.67372 -0.669489 1.67372 -1.66177C1.67372 -1.70959 1.67372 -2.06824 1.80523 -2.59427L2.97684 -7.29265C3.08443 -7.69913 3.10834 -7.81868 3.95716 -7.81868C4.17235 -7.81868 4.29191 -7.81868 4.29191 -8.03387C4.29191 -8.16538 4.18431 -8.16538 4.11258 -8.16538C3.89738 -8.16538 3.64633 -8.14147 3.41918 -8.14147H2.00847C1.78132 -8.14147 1.53026 -8.16538 1.30311 -8.16538C1.21943 -8.16538 1.07597 -8.16538 1.07597 -7.93823C1.07597 -7.81868 1.15965 -7.81868 1.3868 -7.81868C2.10411 -7.81868 2.10411 -7.72304 2.10411 -7.59153C2.10411 -7.5198 2.02042 -7.1731 1.96065 -6.96986L0.920548 -2.78555C0.884682 -2.65405 0.812951 -2.33126 0.812951 -2.00847C0.812951 -0.6934 1.75741 0.251059 3.06052 0.251059C4.268 0.251059 5.60697 -0.705355 6.21669 -2.22366C6.30037 -2.4269 6.40797 -2.84533 6.4797 -3.16812C6.59925 -3.59851 6.85031 -4.65056 6.934 -4.96139L7.38829 -6.75467C7.54371 -7.37634 7.63935 -7.77086 8.69141 -7.81868C8.78705 -7.83064 8.83487 -7.92628 8.83487 -8.03387C8.83487 -8.16538 8.72727 -8.16538 8.67945 -8.16538C8.51208 -8.16538 8.29689 -8.14147 8.12951 -8.14147H7.56762C6.8264 -8.14147 6.44384 -8.16538 6.43188 -8.16538C6.36015 -8.16538 6.21669 -8.16538 6.21669 -7.93823C6.21669 -7.81868 6.31233 -7.81868 6.39601 -7.81868C7.11333 -7.79477 7.16115 -7.5198 7.16115 -7.30461C7.16115 -7.19701 7.16115 -7.16115 7.11333 -6.99377L6.04932 -2.74969Z' id='g4-85'/>
<path d='M7.40025 -6.83836C7.80672 -7.48394 8.17733 -7.77086 8.78705 -7.81868C8.9066 -7.83064 9.00224 -7.83064 9.00224 -8.04583C9.00224 -8.09365 8.97833 -8.16538 8.87073 -8.16538C8.65554 -8.16538 8.14147 -8.14147 7.92628 -8.14147C7.57958 -8.14147 7.22092 -8.16538 6.88618 -8.16538C6.79054 -8.16538 6.67098 -8.16538 6.67098 -7.93823C6.67098 -7.83064 6.77858 -7.81868 6.8264 -7.81868C7.26874 -7.78281 7.31656 -7.56762 7.31656 -7.42416C7.31656 -7.24483 7.14919 -6.96986 7.13724 -6.95791L3.38331 -1.00423L2.54645 -7.44807C2.54645 -7.79477 3.16812 -7.81868 3.29963 -7.81868C3.47895 -7.81868 3.58655 -7.81868 3.58655 -8.04583C3.58655 -8.16538 3.45504 -8.16538 3.41918 -8.16538C3.21594 -8.16538 2.97684 -8.14147 2.7736 -8.14147H2.10411C1.23138 -8.14147 0.872727 -8.16538 0.860772 -8.16538C0.789041 -8.16538 0.645579 -8.16538 0.645579 -7.95019C0.645579 -7.81868 0.729265 -7.81868 0.920548 -7.81868C1.53026 -7.81868 1.56613 -7.71108 1.60199 -7.4122L2.55841 -0.0358655C2.59427 0.215193 2.59427 0.251059 2.76164 0.251059C2.90511 0.251059 2.96488 0.215193 3.08443 0.0239103L7.40025 -6.83836Z' id='g4-86'/>
<path d='M5.46351 -4.47123C5.46351 -5.22441 5.08095 -5.27223 4.98531 -5.27223C4.69838 -5.27223 4.43537 -4.98531 4.43537 -4.7462C4.43537 -4.60274 4.51905 -4.51905 4.56687 -4.47123C4.68643 -4.36364 4.99726 -4.04085 4.99726 -3.41918C4.99726 -2.91706 4.27995 -0.119552 2.84533 -0.119552C2.11606 -0.119552 1.9726 -0.729265 1.9726 -1.17161C1.9726 -1.76936 2.24757 -2.60623 2.57036 -3.467C2.76164 -3.95716 2.80946 -4.07671 2.80946 -4.31582C2.80946 -4.81793 2.45081 -5.27223 1.86501 -5.27223C0.765131 -5.27223 0.32279 -3.53873 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.561893 -3.33549 0.573848 -3.38331 0.621669 -3.55068C0.908593 -4.57883 1.37484 -5.03313 1.82914 -5.03313C1.93674 -5.03313 2.13998 -5.03313 2.13998 -4.63861C2.13998 -4.32777 2.00847 -3.98107 1.82914 -3.52677C1.25529 -1.99651 1.25529 -1.6259 1.25529 -1.33898C1.25529 -1.07597 1.29116 -0.585803 1.66177 -0.251059C2.09215 0.119552 2.68991 0.119552 2.79751 0.119552C4.78207 0.119552 5.46351 -3.78979 5.46351 -4.47123Z' id='g4-118'/>
<path d='M1.34695 -0.629639C1.27522 -0.326775 1.25928 -0.263014 0.669489 -0.263014C0.518057 -0.263014 0.422416 -0.263014 0.422416 -0.111582C0.422416 0 0.526027 0 0.661519 0H3.61843C4.9335 0 5.91382 -0.932503 5.91382 -1.7056C5.91382 -2.28742 5.41171 -2.75766 4.61469 -2.84533C5.53923 -3.02067 6.33624 -3.6264 6.33624 -4.32777C6.33624 -4.92553 5.75442 -5.44359 4.75019 -5.44359H1.96862C1.82516 -5.44359 1.72154 -5.44359 1.72154 -5.29215C1.72154 -5.18057 1.81719 -5.18057 1.95268 -5.18057C2.21569 -5.18057 2.44682 -5.18057 2.44682 -5.05305C2.44682 -5.02117 2.43885 -5.0132 2.41494 -4.90959L1.34695 -0.629639ZM2.59029 -2.94097L3.07646 -4.88568C3.14819 -5.15666 3.15616 -5.18057 3.48294 -5.18057H4.63064C5.41171 -5.18057 5.58705 -4.67049 5.58705 -4.34371C5.58705 -3.66625 4.86177 -2.94097 3.84159 -2.94097H2.59029ZM2.04035 -0.263014C1.96862 -0.278954 1.94471 -0.278954 1.94471 -0.334745C1.94471 -0.398506 1.96065 -0.462267 1.97659 -0.510087L2.5345 -2.71781H4.15243C4.89365 -2.71781 5.14072 -2.21569 5.14072 -1.76936C5.14072 -0.988294 4.37559 -0.263014 3.41918 -0.263014H2.04035Z' id='g3-66'/>
<path d='M5.34795 -5.39577C5.35592 -5.42765 5.37186 -5.47547 5.37186 -5.51532C5.37186 -5.57111 5.32403 -5.61096 5.26824 -5.61096S5.19651 -5.59502 5.10884 -5.49938C5.02117 -5.39577 4.81395 -5.14072 4.72628 -5.04508C4.41544 -5.49938 3.91333 -5.61096 3.50685 -5.61096C2.399 -5.61096 1.45056 -4.67846 1.45056 -3.76986C1.45056 -3.3076 1.69763 -3.03661 1.73748 -2.98082C2.0005 -2.70187 2.23163 -2.63811 2.80548 -2.50262C3.08443 -2.43088 3.10037 -2.43088 3.33151 -2.37509S4.07273 -2.19178 4.07273 -1.53026C4.07273 -0.836862 3.3873 -0.0956413 2.55044 -0.0956413C2.03238 -0.0956413 1.08394 -0.255044 1.08394 -1.24334C1.08394 -1.26725 1.08394 -1.43462 1.13176 -1.6259L1.13973 -1.7056C1.13973 -1.80125 1.05205 -1.80922 1.02017 -1.80922C0.916563 -1.80922 0.908593 -1.77733 0.868742 -1.59402L0.541968 -0.294894C0.510087 -0.175342 0.454296 0.0398506 0.454296 0.0637609C0.454296 0.127522 0.502117 0.167372 0.557908 0.167372S0.621669 0.159402 0.70934 0.0557908L1.09191 -0.390535C1.27522 -0.151432 1.72951 0.167372 2.5345 0.167372C3.69016 0.167372 4.63861 -0.876712 4.63861 -1.83313C4.63861 -2.19975 4.51905 -2.48667 4.30386 -2.70984C4.06476 -2.97285 3.80174 -3.03661 3.42715 -3.13225C3.19601 -3.18804 2.88518 -3.25978 2.70187 -3.3076C2.46276 -3.36339 2.01644 -3.52279 2.01644 -4.0807C2.01644 -4.70237 2.68593 -5.37186 3.49888 -5.37186C4.21619 -5.37186 4.71034 -4.99726 4.71034 -4.13649C4.71034 -3.94521 4.67846 -3.77783 4.67846 -3.74595C4.67846 -3.65031 4.75019 -3.63437 4.80598 -3.63437C4.90162 -3.63437 4.90959 -3.66625 4.94147 -3.79377L5.34795 -5.39577Z' id='g3-83'/>
<path d='M3.25978 -3.05255C2.933 -3.0127 2.82939 -2.76563 2.82939 -2.60623C2.82939 -2.37509 3.03661 -2.31133 3.14022 -2.31133C3.18007 -2.31133 3.58655 -2.34321 3.58655 -2.82939S3.06052 -3.51482 2.58232 -3.51482C1.45056 -3.51482 0.350685 -2.41494 0.350685 -1.29913C0.350685 -0.541968 0.868742 0.0797011 1.75342 0.0797011C3.0127 0.0797011 3.67422 -0.72528 3.67422 -0.828892C3.67422 -0.900623 3.59452 -0.956413 3.5467 -0.956413S3.47497 -0.932503 3.43512 -0.884682C2.80548 -0.143462 1.91283 -0.143462 1.76936 -0.143462C1.33898 -0.143462 0.996264 -0.406476 0.996264 -1.0122C0.996264 -1.36289 1.15567 -2.20772 1.53026 -2.70187C1.88095 -3.14819 2.27945 -3.29166 2.59029 -3.29166C2.68593 -3.29166 3.05255 -3.28369 3.25978 -3.05255Z' id='g3-99'/>
<path d='M3.21196 -2.99676C3.02864 -2.96488 2.86127 -2.82142 2.86127 -2.62217C2.86127 -2.4787 2.95691 -2.37509 3.13225 -2.37509C3.25181 -2.37509 3.49888 -2.46276 3.49888 -2.82142C3.49888 -3.31557 2.98082 -3.51482 2.48667 -3.51482C1.41868 -3.51482 1.08394 -2.75766 1.08394 -2.35118C1.08394 -2.27148 1.08394 -1.98456 1.37883 -1.76139C1.56214 -1.61793 1.69763 -1.59402 2.11208 -1.51432C2.39103 -1.45853 2.84533 -1.37883 2.84533 -0.964384C2.84533 -0.757161 2.6939 -0.494147 2.47073 -0.342715C2.17584 -0.151432 1.78531 -0.143462 1.65778 -0.143462C1.4665 -0.143462 0.924533 -0.175342 0.72528 -0.494147C1.13176 -0.510087 1.18755 -0.836862 1.18755 -0.932503C1.18755 -1.17161 0.972354 -1.2274 0.876712 -1.2274C0.749191 -1.2274 0.422416 -1.13176 0.422416 -0.6934C0.422416 -0.223163 0.916563 0.0797011 1.65778 0.0797011C3.04458 0.0797011 3.33948 -0.900623 3.33948 -1.23537C3.33948 -1.95268 2.55841 -2.10411 2.26351 -2.1599C1.88095 -2.23163 1.57011 -2.28742 1.57011 -2.62217C1.57011 -2.76563 1.7056 -3.29166 2.4787 -3.29166C2.78157 -3.29166 3.0924 -3.20399 3.21196 -2.99676Z' id='g3-115'/>
<path d='M2.98879 -0.868742C2.94894 -0.71731 2.57435 -0.143462 2.04035 -0.143462C1.64981 -0.143462 1.51432 -0.430386 1.51432 -0.789041C1.51432 -1.25928 1.79328 -1.97659 1.96862 -2.42291C2.04832 -2.62217 2.07223 -2.6939 2.07223 -2.83736C2.07223 -3.27572 1.72154 -3.51482 1.35492 -3.51482C0.565878 -3.51482 0.239103 -2.39103 0.239103 -2.29539C0.239103 -2.22366 0.294894 -2.19178 0.358655 -2.19178C0.462267 -2.19178 0.470237 -2.2396 0.494147 -2.3193C0.70137 -3.02864 1.05205 -3.29166 1.33101 -3.29166C1.45056 -3.29166 1.52229 -3.21196 1.52229 -3.02864S1.45056 -2.66202 1.34695 -2.38306C1.0122 -1.53823 0.940473 -1.19552 0.940473 -0.908593C0.940473 -0.127522 1.53026 0.0797011 2.0005 0.0797011C2.59826 0.0797011 2.96488 -0.398506 2.99676 -0.438356C3.12428 -0.0637609 3.48294 0.0797011 3.76986 0.0797011C4.14446 0.0797011 4.32777 -0.239103 4.38356 -0.358655C4.54296 -0.645579 4.65455 -1.10785 4.65455 -1.13973C4.65455 -1.18755 4.62267 -1.24334 4.52702 -1.24334S4.41544 -1.20349 4.36762 -0.996264C4.26401 -0.597758 4.12055 -0.143462 3.79377 -0.143462C3.61046 -0.143462 3.53873 -0.294894 3.53873 -0.518057C3.53873 -0.653549 3.61046 -0.924533 3.65828 -1.12379S3.82565 -1.80125 3.85753 -1.94471L4.01694 -2.55044C4.06476 -2.76563 4.1604 -3.14022 4.1604 -3.18804C4.1604 -3.3873 4.001 -3.43512 3.90535 -3.43512C3.79377 -3.43512 3.61843 -3.36339 3.56264 -3.1721L2.98879 -0.868742Z' id='g3-117'/>
<path d='M4.63064 -1.80922C4.75816 -1.80922 4.9335 -1.80922 4.9335 -1.99253S4.75816 -2.17584 4.63064 -2.17584H1.07597C1.17958 -3.28369 2.10411 -4.12852 3.31557 -4.12852H4.63064C4.75816 -4.12852 4.9335 -4.12852 4.9335 -4.31183S4.75816 -4.49514 4.63064 -4.49514H3.29166C1.85704 -4.49514 0.70137 -3.37933 0.70137 -1.99253C0.70137 -0.597758 1.86501 0.510087 3.29166 0.510087H4.63064C4.75816 0.510087 4.9335 0.510087 4.9335 0.326775S4.75816 0.143462 4.63064 0.143462H3.31557C2.10411 0.143462 1.17958 -0.70137 1.07597 -1.80922H4.63064Z' id='g1-50'/>
</defs>
<g id='page1' transform='matrix(1.13 0 0 1.13 -63.986 -61.0251)'>
<use x='56.4133' xlink:href='#g4-76' y='79.1532'/>
<use x='64.348' xlink:href='#g4-73' y='79.1532'/>
<use x='70.4315' xlink:href='#g4-86' y='79.1532'/>
<use x='79.8317' xlink:href='#g4-69' y='79.1532'/>
<rect height='0.3985' width='3.51182' x='89.8678' y='78.7547'/>
<use x='93.3797' xlink:href='#g4-79' y='79.1532'/>
<use x='102.617' xlink:href='#g4-85' y='79.1532'/>
<use x='111.787' xlink:href='#g4-84' y='79.1532'/>
<use x='120.444' xlink:href='#g6-91' y='79.1532'/>
<use x='123.683' xlink:href='#g4-66' y='79.1532'/>
<use x='133.146' xlink:href='#g6-93' y='79.1532'/>
<use x='139.707' xlink:href='#g6-61' y='79.1532'/>
<use x='152.098' xlink:href='#g0-56' y='54.6449'/>
<use x='152.098' xlink:href='#g0-60' y='65.4047'/>
<use x='152.098' xlink:href='#g0-58' y='86.9242'/>
<use x='266.262' xlink:href='#g0-92' y='54.9938'/>
<use x='253.463' xlink:href='#g3-83' y='80.8968'/>
<use x='259.04' xlink:href='#g1-50' y='80.8968'/>
<use x='264.664' xlink:href='#g3-115' y='80.8968'/>
<use x='268.565' xlink:href='#g3-117' y='80.8968'/>
<use x='273.45' xlink:href='#g3-99' y='80.8968'/>
<use x='277.104' xlink:href='#g3-99' y='80.8968'/>
<use x='280.818' xlink:href='#g5-91' y='80.8968'/>
<use x='283.162' xlink:href='#g3-66' y='80.8968'/>
<use x='289.918' xlink:href='#g5-93' y='80.8968'/>
<use x='294.336' xlink:href='#g4-76' y='66.3512'/>
<use x='302.271' xlink:href='#g4-73' y='66.3512'/>
<use x='308.354' xlink:href='#g4-86' y='66.3512'/>
<use x='317.755' xlink:href='#g4-69' y='66.3512'/>
<rect height='0.3985' width='3.51182' x='327.791' y='65.9528'/>
<use x='331.303' xlink:href='#g4-73' y='66.3512'/>
<use x='337.386' xlink:href='#g4-78' y='66.3512'/>
<use x='348.135' xlink:href='#g6-91' y='66.3512'/>
<use x='351.374' xlink:href='#g4-83' y='66.3512'/>
<use x='359.243' xlink:href='#g6-93' y='66.3512'/>
<use x='362.482' xlink:href='#g4-59' y='66.3512'/>
<use x='466.486' xlink:href='#g4-83' y='66.3512'/>
<use x='478.256' xlink:href='#g6-105' y='66.3512'/>
<use x='481.496' xlink:href='#g6-115' y='66.3512'/>
<use x='489.998' xlink:href='#g6-110' y='66.3512'/>
<use x='496.477' xlink:href='#g6-111' y='66.3512'/>
<use x='502.308' xlink:href='#g6-116' y='66.3512'/>
<use x='510.745' xlink:href='#g6-97' y='66.3512'/>
<use x='516.577' xlink:href='#g6-110' y='66.3512'/>
<use x='526.958' xlink:href='#g6-101' y='66.3512'/>
<use x='532.141' xlink:href='#g6-120' y='66.3512'/>
<use x='538.296' xlink:href='#g6-105' y='66.3512'/>
<use x='541.535' xlink:href='#g6-116' y='66.3512'/>
<use x='549.973' xlink:href='#g6-98' y='66.3512'/>
<use x='556.452' xlink:href='#g6-108' y='66.3512'/>
<use x='559.691' xlink:href='#g6-111' y='66.3512'/>
<use x='565.847' xlink:href='#g6-99' y='66.3512'/>
<use x='570.706' xlink:href='#g6-107' y='66.3512'/>
<use x='162.725' xlink:href='#g2-102' y='94.1969'/>
<use x='168.702' xlink:href='#g4-118' y='94.1969'/>
<use x='178.09' xlink:href='#g2-50' y='94.1969'/>
<use x='189.352' xlink:href='#g4-76' y='94.1969'/>
<use x='197.286' xlink:href='#g4-79' y='94.1969'/>
<use x='206.524' xlink:href='#g4-67' y='94.1969'/>
<use x='215.726' xlink:href='#g4-65' y='94.1969'/>
<use x='224.469' xlink:href='#g4-76' y='94.1969'/>
<use x='232.404' xlink:href='#g4-86' y='94.1969'/>
<use x='241.804' xlink:href='#g4-65' y='94.1969'/>
<use x='250.547' xlink:href='#g4-82' y='94.1969'/>
<use x='259.522' xlink:href='#g4-83' y='94.1969'/>
<use x='271.568' xlink:href='#g2-106' y='94.1969'/>
<use x='278.778' xlink:href='#g4-118' y='94.1969'/>
<use x='288.747' xlink:href='#g6-109' y='94.1969'/>
<use x='298.466' xlink:href='#g6-105' y='94.1969'/>
<use x='301.705' xlink:href='#g6-103' y='94.1969'/>
<use x='307.536' xlink:href='#g6-104' y='94.1969'/>
<use x='313.69' xlink:href='#g6-116' y='94.1969'/>
<use x='322.127' xlink:href='#g6-97' y='94.1969'/>
<use x='327.959' xlink:href='#g6-108' y='94.1969'/>
<use x='331.198' xlink:href='#g6-105' y='94.1969'/>
<use x='334.438' xlink:href='#g6-97' y='94.1969'/>
<use x='340.269' xlink:href='#g6-115' y='94.1969'/>
<use x='348.771' xlink:href='#g6-97' y='94.1969'/>
<use x='358.504' xlink:href='#g6-110' y='94.1969'/>
<use x='364.983' xlink:href='#g6-111' y='94.1969'/>
<use x='370.814' xlink:href='#g6-110' y='94.1969'/>
<use x='377.293' xlink:href='#g6-108' y='94.1969'/>
<use x='380.533' xlink:href='#g6-111' y='94.1969'/>
<use x='386.689' xlink:href='#g6-99' y='94.1969'/>
<use x='391.872' xlink:href='#g6-97' y='94.1969'/>
<use x='397.703' xlink:href='#g6-108' y='94.1969'/>
<use x='404.845' xlink:href='#g6-118' y='94.1969'/>
<use x='410.35' xlink:href='#g6-97' y='94.1969'/>
<use x='416.181' xlink:href='#g6-114' y='94.1969'/>
<use x='420.716' xlink:href='#g6-105' y='94.1969'/>
<use x='423.955' xlink:href='#g6-97' y='94.1969'/>
<use x='429.787' xlink:href='#g6-98' y='94.1969'/>
<use x='436.266' xlink:href='#g6-108' y='94.1969'/>
<use x='439.505' xlink:href='#g6-101' y='94.1969'/>
<use x='445.217' xlink:href='#g2-103' y='94.1969'/>
<use x='453.272' xlink:href='#g4-59' y='94.1969'/>
<use x='497.748' xlink:href='#g6-111' y='94.1969'/>
<use x='503.579' xlink:href='#g6-116' y='94.1969'/>
<use x='508.114' xlink:href='#g6-104' y='94.1969'/>
<use x='514.593' xlink:href='#g6-101' y='94.1969'/>
<use x='519.776' xlink:href='#g6-114' y='94.1969'/>
<use x='524.312' xlink:href='#g6-119' y='94.1969'/>
<use x='532.734' xlink:href='#g6-105' y='94.1969'/>
<use x='535.974' xlink:href='#g6-115' y='94.1969'/>
<use x='540.574' xlink:href='#g6-101' y='94.1969'/>
</g>
</svg>

Added doc/20190216callframe/plivein.svg.



































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?xml version='1.0' encoding='UTF-8'?>
<!-- This file was generated by dvisvgm 1.15.1 -->
<svg height='13.4589pt' version='1.1' viewBox='-0.239051 -0.240777 278.124 13.4589' width='278.124pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
<defs>
<path d='M2.33126 0.0478207C2.33126 -0.645579 2.10411 -1.15965 1.61395 -1.15965C1.23138 -1.15965 1.0401 -0.848817 1.0401 -0.585803S1.21943 0 1.6259 0C1.78132 0 1.91283 -0.0478207 2.02042 -0.155417C2.04433 -0.179328 2.05629 -0.179328 2.06824 -0.179328C2.09215 -0.179328 2.09215 -0.0119552 2.09215 0.0478207C2.09215 0.442341 2.02042 1.21943 1.32702 1.99651C1.19552 2.13998 1.19552 2.16389 1.19552 2.1878C1.19552 2.24757 1.25529 2.30735 1.31507 2.30735C1.41071 2.30735 2.33126 1.42267 2.33126 0.0478207Z' id='g0-59'/>
<path d='M4.37559 -7.35243C4.48319 -7.79477 4.53101 -7.81868 4.99726 -7.81868H6.55143C7.90237 -7.81868 7.90237 -6.67098 7.90237 -6.56339C7.90237 -5.59502 6.934 -4.36364 5.35592 -4.36364H3.63437L4.37559 -7.35243ZM6.39601 -4.268C7.69913 -4.5071 8.88269 -5.41569 8.88269 -6.51557C8.88269 -7.44807 8.05778 -8.16538 6.70685 -8.16538H2.86924C2.64209 -8.16538 2.5345 -8.16538 2.5345 -7.93823C2.5345 -7.81868 2.64209 -7.81868 2.82142 -7.81868C3.55068 -7.81868 3.55068 -7.72304 3.55068 -7.59153C3.55068 -7.56762 3.55068 -7.49589 3.50286 -7.31656L1.88892 -0.884682C1.78132 -0.466252 1.75741 -0.3467 0.920548 -0.3467C0.6934 -0.3467 0.573848 -0.3467 0.573848 -0.131507C0.573848 0 0.645579 0 0.884682 0H4.98531C6.81445 0 8.22516 -1.3868 8.22516 -2.59427C8.22516 -3.5746 7.36438 -4.17235 6.39601 -4.268ZM4.69838 -0.3467H3.08443C2.91706 -0.3467 2.89315 -0.3467 2.82142 -0.358655C2.68991 -0.37061 2.67796 -0.394521 2.67796 -0.490162C2.67796 -0.573848 2.70187 -0.645579 2.72578 -0.753176L3.56264 -4.12453H5.81021C7.22092 -4.12453 7.22092 -2.80946 7.22092 -2.71382C7.22092 -1.56613 6.18082 -0.3467 4.69838 -0.3467Z' id='g0-66'/>
<path d='M8.30884 -2.7736C8.3208 -2.80946 8.35666 -2.89315 8.35666 -2.94097C8.35666 -3.00075 8.30884 -3.06052 8.23711 -3.06052C8.18929 -3.06052 8.16538 -3.04857 8.12951 -3.0127C8.1056 -3.00075 8.1056 -2.97684 7.99801 -2.73773C7.29265 -1.06401 6.77858 -0.3467 4.86575 -0.3467H3.1203C2.95293 -0.3467 2.92902 -0.3467 2.85729 -0.358655C2.72578 -0.37061 2.71382 -0.394521 2.71382 -0.490162C2.71382 -0.573848 2.73773 -0.645579 2.76164 -0.753176L3.58655 -4.0528H4.77011C5.70262 -4.0528 5.77435 -3.84956 5.77435 -3.49091C5.77435 -3.37136 5.77435 -3.26376 5.69066 -2.90511C5.66675 -2.85729 5.65479 -2.80946 5.65479 -2.7736C5.65479 -2.68991 5.71457 -2.65405 5.7863 -2.65405C5.8939 -2.65405 5.90585 -2.73773 5.95367 -2.90511L6.63512 -5.6787C6.63512 -5.73848 6.5873 -5.79826 6.51557 -5.79826C6.40797 -5.79826 6.39601 -5.75044 6.34819 -5.58306C6.10909 -4.66252 5.86999 -4.3995 4.80598 -4.3995H3.67024L4.41146 -7.34047C4.51905 -7.7589 4.54296 -7.79477 5.03313 -7.79477H6.74271C8.2132 -7.79477 8.51208 -7.40025 8.51208 -6.49166C8.51208 -6.4797 8.51208 -6.14496 8.46426 -5.75044C8.4523 -5.70262 8.44035 -5.63088 8.44035 -5.60697C8.44035 -5.51133 8.50012 -5.47547 8.57186 -5.47547C8.65554 -5.47547 8.70336 -5.52329 8.72727 -5.73848L8.97833 -7.83064C8.97833 -7.8665 9.00224 -7.98605 9.00224 -8.00996C9.00224 -8.14147 8.89465 -8.14147 8.67945 -8.14147H2.84533C2.61818 -8.14147 2.49863 -8.14147 2.49863 -7.92628C2.49863 -7.79477 2.58232 -7.79477 2.78555 -7.79477C3.52677 -7.79477 3.52677 -7.71108 3.52677 -7.57958C3.52677 -7.5198 3.51482 -7.47198 3.47895 -7.34047L1.86501 -0.884682C1.75741 -0.466252 1.7335 -0.3467 0.896638 -0.3467C0.669489 -0.3467 0.549938 -0.3467 0.549938 -0.131507C0.549938 0 0.621669 0 0.860772 0H6.86227C7.12528 0 7.13724 -0.0119552 7.22092 -0.203238L8.30884 -2.7736Z' id='g0-69'/>
<path d='M4.3995 -7.2807C4.5071 -7.69913 4.53101 -7.81868 5.40374 -7.81868C5.66675 -7.81868 5.76239 -7.81868 5.76239 -8.04583C5.76239 -8.16538 5.63088 -8.16538 5.59502 -8.16538C5.37983 -8.16538 5.11681 -8.14147 4.90162 -8.14147H3.43113C3.19203 -8.14147 2.91706 -8.16538 2.67796 -8.16538C2.58232 -8.16538 2.45081 -8.16538 2.45081 -7.93823C2.45081 -7.81868 2.54645 -7.81868 2.78555 -7.81868C3.52677 -7.81868 3.52677 -7.72304 3.52677 -7.59153C3.52677 -7.50785 3.50286 -7.43611 3.47895 -7.32852L1.86501 -0.884682C1.75741 -0.466252 1.7335 -0.3467 0.860772 -0.3467C0.597758 -0.3467 0.490162 -0.3467 0.490162 -0.119552C0.490162 0 0.609714 0 0.669489 0C0.884682 0 1.1477 -0.0239103 1.36289 -0.0239103H2.83337C3.07248 -0.0239103 3.33549 0 3.5746 0C3.67024 0 3.8137 0 3.8137 -0.215193C3.8137 -0.3467 3.74197 -0.3467 3.47895 -0.3467C2.73773 -0.3467 2.73773 -0.442341 2.73773 -0.585803C2.73773 -0.609714 2.73773 -0.669489 2.78555 -0.860772L4.3995 -7.2807Z' id='g0-73'/>
<path d='M4.38755 -7.24483C4.49514 -7.69913 4.53101 -7.81868 5.58306 -7.81868C5.90585 -7.81868 5.98954 -7.81868 5.98954 -8.04583C5.98954 -8.16538 5.85803 -8.16538 5.81021 -8.16538C5.57111 -8.16538 5.29614 -8.14147 5.05704 -8.14147H3.45504C3.2279 -8.14147 2.96488 -8.16538 2.73773 -8.16538C2.64209 -8.16538 2.51059 -8.16538 2.51059 -7.93823C2.51059 -7.81868 2.61818 -7.81868 2.79751 -7.81868C3.52677 -7.81868 3.52677 -7.72304 3.52677 -7.59153C3.52677 -7.56762 3.52677 -7.49589 3.47895 -7.31656L1.86501 -0.884682C1.75741 -0.466252 1.7335 -0.3467 0.896638 -0.3467C0.669489 -0.3467 0.549938 -0.3467 0.549938 -0.131507C0.549938 0 0.621669 0 0.860772 0H6.21669C6.4797 0 6.49166 -0.0119552 6.57534 -0.227148L7.49589 -2.7736C7.5198 -2.83337 7.54371 -2.90511 7.54371 -2.94097C7.54371 -3.0127 7.48394 -3.06052 7.42416 -3.06052C7.4122 -3.06052 7.35243 -3.06052 7.32852 -3.0127C7.30461 -3.00075 7.30461 -2.97684 7.20897 -2.74969C6.8264 -1.69763 6.28842 -0.3467 4.268 -0.3467H3.1203C2.95293 -0.3467 2.92902 -0.3467 2.85729 -0.358655C2.72578 -0.37061 2.71382 -0.394521 2.71382 -0.490162C2.71382 -0.573848 2.73773 -0.645579 2.76164 -0.753176L4.38755 -7.24483Z' id='g0-76'/>
<path d='M8.84682 -6.91009C8.97833 -7.42416 9.16961 -7.78281 10.0782 -7.81868C10.1141 -7.81868 10.2575 -7.83064 10.2575 -8.03387C10.2575 -8.16538 10.1499 -8.16538 10.1021 -8.16538C9.86301 -8.16538 9.2533 -8.14147 9.0142 -8.14147H8.44035C8.27298 -8.14147 8.05778 -8.16538 7.89041 -8.16538C7.81868 -8.16538 7.67522 -8.16538 7.67522 -7.93823C7.67522 -7.81868 7.77086 -7.81868 7.85455 -7.81868C8.57186 -7.79477 8.61968 -7.5198 8.61968 -7.30461C8.61968 -7.19701 8.60772 -7.16115 8.57186 -6.99377L7.22092 -1.60199L4.66252 -7.96214C4.57883 -8.15342 4.56687 -8.16538 4.30386 -8.16538H2.84533C2.60623 -8.16538 2.49863 -8.16538 2.49863 -7.93823C2.49863 -7.81868 2.58232 -7.81868 2.80946 -7.81868C2.86924 -7.81868 3.5746 -7.81868 3.5746 -7.71108C3.5746 -7.68717 3.55068 -7.59153 3.53873 -7.55567L1.94869 -1.21943C1.80523 -0.633624 1.51831 -0.382565 0.729265 -0.3467C0.669489 -0.3467 0.549938 -0.334745 0.549938 -0.119552C0.549938 0 0.669489 0 0.705355 0C0.944458 0 1.55417 -0.0239103 1.79328 -0.0239103H2.36712C2.5345 -0.0239103 2.73773 0 2.90511 0C2.98879 0 3.1203 0 3.1203 -0.227148C3.1203 -0.334745 3.00075 -0.3467 2.95293 -0.3467C2.55841 -0.358655 2.17584 -0.430386 2.17584 -0.860772C2.17584 -0.956413 2.19975 -1.06401 2.22366 -1.15965L3.83761 -7.55567C3.90934 -7.43611 3.90934 -7.4122 3.95716 -7.30461L6.80249 -0.215193C6.86227 -0.071731 6.88618 0 6.99377 0C7.11333 0 7.12528 -0.0358655 7.1731 -0.239103L8.84682 -6.91009Z' id='g0-78'/>
<path d='M8.67945 -5.23636C8.67945 -7.20897 7.38829 -8.41644 5.71457 -8.41644C3.15616 -8.41644 0.573848 -5.66675 0.573848 -2.90511C0.573848 -1.02814 1.81719 0.251059 3.55068 0.251059C6.06127 0.251059 8.67945 -2.36712 8.67945 -5.23636ZM3.62242 -0.0239103C2.64209 -0.0239103 1.60199 -0.74122 1.60199 -2.60623C1.60199 -3.69415 1.99651 -5.47547 2.97684 -6.67098C3.84956 -7.72304 4.8538 -8.15342 5.65479 -8.15342C6.70685 -8.15342 7.72304 -7.38829 7.72304 -5.66675C7.72304 -4.60274 7.26874 -2.94097 6.46775 -1.80523C5.59502 -0.585803 4.5071 -0.0239103 3.62242 -0.0239103Z' id='g0-79'/>
<path d='M3.53873 -3.80174H5.5472C7.19701 -3.80174 8.84682 -5.02117 8.84682 -6.38406C8.84682 -7.31656 8.05778 -8.16538 6.55143 -8.16538H2.85729C2.63014 -8.16538 2.52254 -8.16538 2.52254 -7.93823C2.52254 -7.81868 2.63014 -7.81868 2.80946 -7.81868C3.53873 -7.81868 3.53873 -7.72304 3.53873 -7.59153C3.53873 -7.56762 3.53873 -7.49589 3.49091 -7.31656L1.87696 -0.884682C1.76936 -0.466252 1.74545 -0.3467 0.908593 -0.3467C0.681445 -0.3467 0.561893 -0.3467 0.561893 -0.131507C0.561893 0 0.669489 0 0.74122 0C0.968369 0 1.20747 -0.0239103 1.43462 -0.0239103H2.83337C3.06052 -0.0239103 3.31158 0 3.53873 0C3.63437 0 3.76588 0 3.76588 -0.227148C3.76588 -0.3467 3.65828 -0.3467 3.47895 -0.3467C2.76164 -0.3467 2.74969 -0.430386 2.74969 -0.549938C2.74969 -0.609714 2.76164 -0.6934 2.7736 -0.753176L3.53873 -3.80174ZM4.3995 -7.35243C4.5071 -7.79477 4.55492 -7.81868 5.02117 -7.81868H6.20473C7.10137 -7.81868 7.84259 -7.53176 7.84259 -6.63512C7.84259 -6.32428 7.68717 -5.30809 7.13724 -4.75816C6.934 -4.54296 6.36015 -4.08867 5.27223 -4.08867H3.58655L4.3995 -7.35243Z' id='g0-80'/>
<path d='M4.98531 -7.29265C5.05704 -7.57958 5.08095 -7.68717 5.26027 -7.73499C5.35592 -7.7589 5.75044 -7.7589 6.00149 -7.7589C7.19701 -7.7589 7.7589 -7.71108 7.7589 -6.77858C7.7589 -6.59925 7.71108 -6.14496 7.63935 -5.70262L7.6274 -5.55915C7.6274 -5.51133 7.67522 -5.4396 7.74695 -5.4396C7.8665 -5.4396 7.8665 -5.49938 7.90237 -5.69066L8.24907 -7.80672C8.27298 -7.91432 8.27298 -7.93823 8.27298 -7.9741C8.27298 -8.1056 8.20125 -8.1056 7.96214 -8.1056H1.42267C1.1477 -8.1056 1.13574 -8.09365 1.06401 -7.87846L0.334745 -5.72653C0.32279 -5.70262 0.286924 -5.57111 0.286924 -5.55915C0.286924 -5.49938 0.334745 -5.4396 0.406476 -5.4396C0.502117 -5.4396 0.526027 -5.48742 0.573848 -5.64284C1.07597 -7.08941 1.32702 -7.7589 2.91706 -7.7589H3.71806C4.00498 -7.7589 4.12453 -7.7589 4.12453 -7.6274C4.12453 -7.59153 4.12453 -7.56762 4.06476 -7.35243L2.46276 -0.932503C2.34321 -0.466252 2.3193 -0.3467 1.05205 -0.3467C0.753176 -0.3467 0.669489 -0.3467 0.669489 -0.119552C0.669489 0 0.800996 0 0.860772 0C1.15965 0 1.47049 -0.0239103 1.76936 -0.0239103H3.63437C3.93325 -0.0239103 4.25604 0 4.55492 0C4.68643 0 4.80598 0 4.80598 -0.227148C4.80598 -0.3467 4.72229 -0.3467 4.41146 -0.3467C3.33549 -0.3467 3.33549 -0.454296 3.33549 -0.633624C3.33549 -0.645579 3.33549 -0.729265 3.38331 -0.920548L4.98531 -7.29265Z' id='g0-84'/>
<path d='M6.04932 -2.74969C5.63088 -1.07597 4.24408 -0.0956413 3.1203 -0.0956413C2.25953 -0.0956413 1.67372 -0.669489 1.67372 -1.66177C1.67372 -1.70959 1.67372 -2.06824 1.80523 -2.59427L2.97684 -7.29265C3.08443 -7.69913 3.10834 -7.81868 3.95716 -7.81868C4.17235 -7.81868 4.29191 -7.81868 4.29191 -8.03387C4.29191 -8.16538 4.18431 -8.16538 4.11258 -8.16538C3.89738 -8.16538 3.64633 -8.14147 3.41918 -8.14147H2.00847C1.78132 -8.14147 1.53026 -8.16538 1.30311 -8.16538C1.21943 -8.16538 1.07597 -8.16538 1.07597 -7.93823C1.07597 -7.81868 1.15965 -7.81868 1.3868 -7.81868C2.10411 -7.81868 2.10411 -7.72304 2.10411 -7.59153C2.10411 -7.5198 2.02042 -7.1731 1.96065 -6.96986L0.920548 -2.78555C0.884682 -2.65405 0.812951 -2.33126 0.812951 -2.00847C0.812951 -0.6934 1.75741 0.251059 3.06052 0.251059C4.268 0.251059 5.60697 -0.705355 6.21669 -2.22366C6.30037 -2.4269 6.40797 -2.84533 6.4797 -3.16812C6.59925 -3.59851 6.85031 -4.65056 6.934 -4.96139L7.38829 -6.75467C7.54371 -7.37634 7.63935 -7.77086 8.69141 -7.81868C8.78705 -7.83064 8.83487 -7.92628 8.83487 -8.03387C8.83487 -8.16538 8.72727 -8.16538 8.67945 -8.16538C8.51208 -8.16538 8.29689 -8.14147 8.12951 -8.14147H7.56762C6.8264 -8.14147 6.44384 -8.16538 6.43188 -8.16538C6.36015 -8.16538 6.21669 -8.16538 6.21669 -7.93823C6.21669 -7.81868 6.31233 -7.81868 6.39601 -7.81868C7.11333 -7.79477 7.16115 -7.5198 7.16115 -7.30461C7.16115 -7.19701 7.16115 -7.16115 7.11333 -6.99377L6.04932 -2.74969Z' id='g0-85'/>
<path d='M7.40025 -6.83836C7.80672 -7.48394 8.17733 -7.77086 8.78705 -7.81868C8.9066 -7.83064 9.00224 -7.83064 9.00224 -8.04583C9.00224 -8.09365 8.97833 -8.16538 8.87073 -8.16538C8.65554 -8.16538 8.14147 -8.14147 7.92628 -8.14147C7.57958 -8.14147 7.22092 -8.16538 6.88618 -8.16538C6.79054 -8.16538 6.67098 -8.16538 6.67098 -7.93823C6.67098 -7.83064 6.77858 -7.81868 6.8264 -7.81868C7.26874 -7.78281 7.31656 -7.56762 7.31656 -7.42416C7.31656 -7.24483 7.14919 -6.96986 7.13724 -6.95791L3.38331 -1.00423L2.54645 -7.44807C2.54645 -7.79477 3.16812 -7.81868 3.29963 -7.81868C3.47895 -7.81868 3.58655 -7.81868 3.58655 -8.04583C3.58655 -8.16538 3.45504 -8.16538 3.41918 -8.16538C3.21594 -8.16538 2.97684 -8.14147 2.7736 -8.14147H2.10411C1.23138 -8.14147 0.872727 -8.16538 0.860772 -8.16538C0.789041 -8.16538 0.645579 -8.16538 0.645579 -7.95019C0.645579 -7.81868 0.729265 -7.81868 0.920548 -7.81868C1.53026 -7.81868 1.56613 -7.71108 1.60199 -7.4122L2.55841 -0.0358655C2.59427 0.215193 2.59427 0.251059 2.76164 0.251059C2.90511 0.251059 2.96488 0.215193 3.08443 0.0239103L7.40025 -6.83836Z' id='g0-86'/>
<path d='M4.67447 -4.49514C4.44732 -4.49514 4.33973 -4.49514 4.17235 -4.35168C4.10062 -4.29191 3.96912 -4.11258 3.96912 -3.9213C3.96912 -3.68219 4.14844 -3.53873 4.37559 -3.53873C4.66252 -3.53873 4.98531 -3.77783 4.98531 -4.25604C4.98531 -4.82989 4.43537 -5.27223 3.61046 -5.27223C2.04433 -5.27223 0.478207 -3.56264 0.478207 -1.86501C0.478207 -0.824907 1.12379 0.119552 2.34321 0.119552C3.96912 0.119552 4.99726 -1.1477 4.99726 -1.30311C4.99726 -1.37484 4.92553 -1.43462 4.87771 -1.43462C4.84184 -1.43462 4.82989 -1.42267 4.72229 -1.31507C3.95716 -0.298879 2.82142 -0.119552 2.36712 -0.119552C1.54222 -0.119552 1.2792 -0.836862 1.2792 -1.43462C1.2792 -1.85305 1.48244 -3.0127 1.91283 -3.82565C2.22366 -4.38755 2.86924 -5.03313 3.62242 -5.03313C3.77783 -5.03313 4.43537 -5.00922 4.67447 -4.49514Z' id='g0-99'/>
<path d='M2.13998 -2.7736C2.46276 -2.7736 3.27572 -2.79751 3.84956 -3.0127C4.75816 -3.3594 4.84184 -4.0528 4.84184 -4.268C4.84184 -4.79402 4.38755 -5.27223 3.59851 -5.27223C2.34321 -5.27223 0.537983 -4.13649 0.537983 -2.00847C0.537983 -0.753176 1.25529 0.119552 2.34321 0.119552C3.96912 0.119552 4.99726 -1.1477 4.99726 -1.30311C4.99726 -1.37484 4.92553 -1.43462 4.87771 -1.43462C4.84184 -1.43462 4.82989 -1.42267 4.72229 -1.31507C3.95716 -0.298879 2.82142 -0.119552 2.36712 -0.119552C1.68568 -0.119552 1.32702 -0.657534 1.32702 -1.54222C1.32702 -1.70959 1.32702 -2.00847 1.50635 -2.7736H2.13998ZM1.56613 -3.0127C2.0802 -4.8538 3.21594 -5.03313 3.59851 -5.03313C4.12453 -5.03313 4.48319 -4.72229 4.48319 -4.268C4.48319 -3.0127 2.57036 -3.0127 2.06824 -3.0127H1.56613Z' id='g0-101'/>
<path d='M5.45156 -3.28767C5.45156 -4.42341 4.71034 -5.27223 3.62242 -5.27223C2.04433 -5.27223 0.490162 -3.55068 0.490162 -1.86501C0.490162 -0.729265 1.23138 0.119552 2.3193 0.119552C3.90934 0.119552 5.45156 -1.60199 5.45156 -3.28767ZM2.33126 -0.119552C1.7335 -0.119552 1.29116 -0.597758 1.29116 -1.43462C1.29116 -1.98456 1.57808 -3.20399 1.91283 -3.80174C2.45081 -4.72229 3.1203 -5.03313 3.61046 -5.03313C4.19626 -5.03313 4.65056 -4.55492 4.65056 -3.71806C4.65056 -3.23985 4.3995 -1.96065 3.94521 -1.23138C3.45504 -0.430386 2.79751 -0.119552 2.33126 -0.119552Z' id='g0-111'/>
<path d='M0.514072 1.51831C0.430386 1.87696 0.382565 1.9726 -0.107597 1.9726C-0.251059 1.9726 -0.37061 1.9726 -0.37061 2.19975C-0.37061 2.22366 -0.358655 2.3193 -0.227148 2.3193C-0.071731 2.3193 0.0956413 2.29539 0.251059 2.29539H0.765131C1.01619 2.29539 1.6259 2.3193 1.87696 2.3193C1.94869 2.3193 2.09215 2.3193 2.09215 2.10411C2.09215 1.9726 2.00847 1.9726 1.80523 1.9726C1.25529 1.9726 1.21943 1.88892 1.21943 1.79328C1.21943 1.64981 1.75741 -0.406476 1.82914 -0.681445C1.96065 -0.3467 2.28344 0.119552 2.90511 0.119552C4.25604 0.119552 5.71457 -1.63786 5.71457 -3.39527C5.71457 -4.49514 5.0929 -5.27223 4.19626 -5.27223C3.43113 -5.27223 2.78555 -4.53101 2.65405 -4.36364C2.55841 -4.96139 2.09215 -5.27223 1.61395 -5.27223C1.26725 -5.27223 0.992279 -5.10486 0.765131 -4.65056C0.549938 -4.22017 0.382565 -3.49091 0.382565 -3.44309S0.430386 -3.33549 0.514072 -3.33549C0.609714 -3.33549 0.621669 -3.34745 0.6934 -3.62242C0.872727 -4.32777 1.09988 -5.03313 1.57808 -5.03313C1.85305 -5.03313 1.94869 -4.84184 1.94869 -4.48319C1.94869 -4.19626 1.91283 -4.07671 1.86501 -3.86152L0.514072 1.51831ZM2.58232 -3.73001C2.666 -4.06476 3.00075 -4.41146 3.19203 -4.57883C3.32354 -4.69838 3.71806 -5.03313 4.17235 -5.03313C4.69838 -5.03313 4.93748 -4.5071 4.93748 -3.88543C4.93748 -3.31158 4.60274 -1.96065 4.30386 -1.33898C4.00498 -0.6934 3.45504 -0.119552 2.90511 -0.119552C2.09215 -0.119552 1.96065 -1.1477 1.96065 -1.19552C1.96065 -1.23138 1.98456 -1.32702 1.99651 -1.3868L2.58232 -3.73001Z' id='g0-112'/>
<path d='M4.65056 -4.88966C4.27995 -4.81793 4.08867 -4.55492 4.08867 -4.29191C4.08867 -4.00498 4.31582 -3.90934 4.48319 -3.90934C4.81793 -3.90934 5.0929 -4.19626 5.0929 -4.55492C5.0929 -4.93748 4.72229 -5.27223 4.12453 -5.27223C3.64633 -5.27223 3.09639 -5.05704 2.59427 -4.32777C2.51059 -4.96139 2.03238 -5.27223 1.55417 -5.27223C1.08792 -5.27223 0.848817 -4.91357 0.705355 -4.65056C0.502117 -4.22017 0.32279 -3.50286 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.549938 -3.33549 0.561893 -3.34745 0.633624 -3.62242C0.812951 -4.33973 1.0401 -5.03313 1.51831 -5.03313C1.80523 -5.03313 1.88892 -4.82989 1.88892 -4.48319C1.88892 -4.22017 1.76936 -3.75392 1.68568 -3.38331L1.35093 -2.09215C1.30311 -1.86501 1.17161 -1.32702 1.11183 -1.11183C1.02814 -0.800996 0.896638 -0.239103 0.896638 -0.179328C0.896638 -0.0119552 1.02814 0.119552 1.20747 0.119552C1.33898 0.119552 1.56613 0.0358655 1.63786 -0.203238C1.67372 -0.298879 2.11606 -2.10411 2.1878 -2.37908C2.24757 -2.64209 2.3193 -2.89315 2.37908 -3.15616C2.4269 -3.32354 2.47472 -3.51482 2.51059 -3.67024C2.54645 -3.77783 2.86924 -4.36364 3.16812 -4.62665C3.31158 -4.75816 3.62242 -5.03313 4.11258 -5.03313C4.30386 -5.03313 4.49514 -4.99726 4.65056 -4.88966Z' id='g0-114'/>
<path d='M2.72578 -2.39103C2.92902 -2.35517 3.25181 -2.28344 3.32354 -2.27148C3.47895 -2.22366 4.01694 -2.03238 4.01694 -1.45853C4.01694 -1.08792 3.68219 -0.119552 2.29539 -0.119552C2.04433 -0.119552 1.1477 -0.155417 0.908593 -0.812951C1.3868 -0.753176 1.6259 -1.12379 1.6259 -1.3868C1.6259 -1.63786 1.45853 -1.76936 1.21943 -1.76936C0.956413 -1.76936 0.609714 -1.56613 0.609714 -1.02814C0.609714 -0.32279 1.32702 0.119552 2.28344 0.119552C4.10062 0.119552 4.63861 -1.21943 4.63861 -1.8411C4.63861 -2.02042 4.63861 -2.35517 4.25604 -2.73773C3.95716 -3.02466 3.67024 -3.08443 3.02466 -3.21594C2.70187 -3.28767 2.1878 -3.39527 2.1878 -3.93325C2.1878 -4.17235 2.40299 -5.03313 3.53873 -5.03313C4.04085 -5.03313 4.53101 -4.84184 4.65056 -4.41146C4.12453 -4.41146 4.10062 -3.95716 4.10062 -3.94521C4.10062 -3.69415 4.32777 -3.62242 4.43537 -3.62242C4.60274 -3.62242 4.93748 -3.75392 4.93748 -4.25604S4.48319 -5.27223 3.55068 -5.27223C1.98456 -5.27223 1.56613 -4.04085 1.56613 -3.55068C1.56613 -2.64209 2.45081 -2.45081 2.72578 -2.39103Z' id='g0-115'/>
<path d='M3.88543 2.90511C3.88543 2.86924 3.88543 2.84533 3.68219 2.64209C2.48667 1.43462 1.81719 -0.537983 1.81719 -2.97684C1.81719 -5.29614 2.37908 -7.29265 3.76588 -8.70336C3.88543 -8.81096 3.88543 -8.83487 3.88543 -8.87073C3.88543 -8.94247 3.82565 -8.96638 3.77783 -8.96638C3.62242 -8.96638 2.64209 -8.1056 2.05629 -6.934C1.44658 -5.72653 1.17161 -4.44732 1.17161 -2.97684C1.17161 -1.91283 1.33898 -0.490162 1.96065 0.789041C2.666 2.22366 3.64633 3.00075 3.77783 3.00075C3.82565 3.00075 3.88543 2.97684 3.88543 2.90511Z' id='g1-40'/>
<path d='M3.37136 -2.97684C3.37136 -3.88543 3.25181 -5.36787 2.58232 -6.75467C1.87696 -8.18929 0.896638 -8.96638 0.765131 -8.96638C0.71731 -8.96638 0.657534 -8.94247 0.657534 -8.87073C0.657534 -8.83487 0.657534 -8.81096 0.860772 -8.60772C2.05629 -7.40025 2.72578 -5.42765 2.72578 -2.98879C2.72578 -0.669489 2.16389 1.32702 0.777086 2.73773C0.657534 2.84533 0.657534 2.86924 0.657534 2.90511C0.657534 2.97684 0.71731 3.00075 0.765131 3.00075C0.920548 3.00075 1.90087 2.13998 2.48667 0.968369C3.09639 -0.251059 3.37136 -1.54222 3.37136 -2.97684Z' id='g1-41'/>
<path d='M8.06974 -3.87347C8.23711 -3.87347 8.4523 -3.87347 8.4523 -4.08867C8.4523 -4.31582 8.24907 -4.31582 8.06974 -4.31582H1.02814C0.860772 -4.31582 0.645579 -4.31582 0.645579 -4.10062C0.645579 -3.87347 0.848817 -3.87347 1.02814 -3.87347H8.06974ZM8.06974 -1.64981C8.23711 -1.64981 8.4523 -1.64981 8.4523 -1.86501C8.4523 -2.09215 8.24907 -2.09215 8.06974 -2.09215H1.02814C0.860772 -2.09215 0.645579 -2.09215 0.645579 -1.87696C0.645579 -1.64981 0.848817 -1.64981 1.02814 -1.64981H8.06974Z' id='g1-61'/>
<path d='M2.98879 2.98879V2.54645H1.82914V-8.52403H2.98879V-8.96638H1.3868V2.98879H2.98879Z' id='g1-91'/>
<path d='M1.85305 -8.96638H0.251059V-8.52403H1.41071V2.54645H0.251059V2.98879H1.85305V-8.96638Z' id='g1-93'/>
</defs>
<g id='page1' transform='matrix(1.13 0 0 1.13 -63.986 -64.448)'>
<use x='56.4133' xlink:href='#g0-80' y='65.7534'/>
<use x='65.5562' xlink:href='#g0-76' y='65.7534'/>
<use x='73.4909' xlink:href='#g0-73' y='65.7534'/>
<use x='79.5744' xlink:href='#g0-86' y='65.7534'/>
<use x='88.9746' xlink:href='#g0-69' y='65.7534'/>
<rect height='0.3985' width='3.51182' x='99.0107' y='65.3549'/>
<use x='102.523' xlink:href='#g0-73' y='65.7534'/>
<use x='108.606' xlink:href='#g0-78' y='65.7534'/>
<use x='119.383' xlink:href='#g1-91' y='65.7534'/>
<use x='122.623' xlink:href='#g0-66' y='65.7534'/>
<use x='132.086' xlink:href='#g1-93' y='65.7534'/>
<use x='138.646' xlink:href='#g1-61' y='65.7534'/>
<use x='151.037' xlink:href='#g0-112' y='65.7534'/>
<use x='156.891' xlink:href='#g0-114' y='65.7534'/>
<use x='162.471' xlink:href='#g0-111' y='65.7534'/>
<use x='168.078' xlink:href='#g0-99' y='65.7534'/>
<use x='173.097' xlink:href='#g0-101' y='65.7534'/>
<use x='178.502' xlink:href='#g0-115' y='65.7534'/>
<use x='183.995' xlink:href='#g0-115' y='65.7534'/>
<use x='189.632' xlink:href='#g1-40' y='65.7534'/>
<use x='194.167' xlink:href='#g0-66' y='65.7534'/>
<use x='203.63' xlink:href='#g0-59' y='65.7534'/>
<use x='208.862' xlink:href='#g0-80' y='65.7534'/>
<use x='218.005' xlink:href='#g0-76' y='65.7534'/>
<use x='225.94' xlink:href='#g0-73' y='65.7534'/>
<use x='232.023' xlink:href='#g0-86' y='65.7534'/>
<use x='241.424' xlink:href='#g0-69' y='65.7534'/>
<rect height='0.3985' width='3.51182' x='251.46' y='65.3549'/>
<use x='254.972' xlink:href='#g0-79' y='65.7534'/>
<use x='264.209' xlink:href='#g0-85' y='65.7534'/>
<use x='273.379' xlink:href='#g0-84' y='65.7534'/>
<use x='282.064' xlink:href='#g1-91' y='65.7534'/>
<use x='285.303' xlink:href='#g0-66' y='65.7534'/>
<use x='294.766' xlink:href='#g1-93' y='65.7534'/>
<use x='298.006' xlink:href='#g1-41' y='65.7534'/>
</g>
</svg>

Added doc/20190216callframe/pliveout.svg.

















































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
<?xml version='1.0' encoding='UTF-8'?>
<!-- This file was generated by dvisvgm 1.15.1 -->
<svg height='49.5404pt' version='1.1' viewBox='-0.239051 -0.227989 598.469 49.5404' width='598.469pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
<defs>
<path d='M6.0254 5.41569C6.0254 4.43537 6.28842 2.15193 8.41644 0.645579C8.57186 0.526027 8.58381 0.514072 8.58381 0.298879C8.58381 0.0239103 8.57186 0.0119552 8.27298 0.0119552H8.08169C5.51133 1.39875 4.59078 3.65828 4.59078 5.41569V10.5564C4.59078 10.8672 4.60274 10.8792 4.92553 10.8792H5.69066C6.01345 10.8792 6.0254 10.8672 6.0254 10.5564V5.41569Z' id='g0-56'/>
<path d='M8.27298 10.7477C8.57186 10.7477 8.58381 10.7357 8.58381 10.4608C8.58381 10.2456 8.57186 10.2336 8.52403 10.1978C8.15342 9.92279 7.29265 9.31308 6.73076 8.2132C6.26451 7.30461 6.0254 6.38406 6.0254 5.34396V0.203238C6.0254 -0.107597 6.01345 -0.119552 5.69066 -0.119552H4.92553C4.60274 -0.119552 4.59078 -0.107597 4.59078 0.203238V5.34396C4.59078 7.11333 5.51133 9.37285 8.08169 10.7477H8.27298Z' id='g0-58'/>
<path d='M4.59078 21.3161C4.59078 21.6269 4.60274 21.6389 4.92553 21.6389H5.69066C6.01345 21.6389 6.0254 21.6269 6.0254 21.3161V16.271C6.0254 14.8244 5.41569 12.3856 2.73773 10.7597C5.4396 9.12179 6.0254 6.65903 6.0254 5.24832V0.203238C6.0254 -0.107597 6.01345 -0.119552 5.69066 -0.119552H4.92553C4.60274 -0.119552 4.59078 -0.107597 4.59078 0.203238V5.26027C4.59078 6.26451 4.37559 8.75118 2.17584 10.4249C2.04433 10.5325 2.03238 10.5445 2.03238 10.7597S2.04433 10.9868 2.17584 11.0944C2.48667 11.3335 3.31158 11.9671 3.88543 13.1746C4.35168 14.131 4.59078 15.195 4.59078 16.259V21.3161Z' id='g0-60'/>
<path d='M11.6085 10.9748C11.6085 13.7126 9.30112 15.745 6.63512 15.745S1.66177 13.7006 1.66177 10.9748V0.657534C1.66177 0.502117 1.66177 0 1.17161 0C0.669489 0 0.669489 0.490162 0.669489 0.657534V11.0346C0.669489 14.1071 3.28767 16.7372 6.63512 16.7372S12.6007 14.1071 12.6007 11.0346V0.657534C12.6007 0.502117 12.6007 0 12.1106 0C11.6085 0 11.6085 0.490162 11.6085 0.657534V10.9748Z' id='g0-91'/>
<path d='M8.06974 -3.87347C8.23711 -3.87347 8.4523 -3.87347 8.4523 -4.08867C8.4523 -4.31582 8.24907 -4.31582 8.06974 -4.31582H1.02814C0.860772 -4.31582 0.645579 -4.31582 0.645579 -4.10062C0.645579 -3.87347 0.848817 -3.87347 1.02814 -3.87347H8.06974ZM8.06974 -1.64981C8.23711 -1.64981 8.4523 -1.64981 8.4523 -1.86501C8.4523 -2.09215 8.24907 -2.09215 8.06974 -2.09215H1.02814C0.860772 -2.09215 0.645579 -2.09215 0.645579 -1.87696C0.645579 -1.64981 0.848817 -1.64981 1.02814 -1.64981H8.06974Z' id='g6-61'/>
<path d='M2.98879 2.98879V2.54645H1.82914V-8.52403H2.98879V-8.96638H1.3868V2.98879H2.98879Z' id='g6-91'/>
<path d='M1.85305 -8.96638H0.251059V-8.52403H1.41071V2.54645H0.251059V2.98879H1.85305V-8.96638Z' id='g6-93'/>
<path d='M4.61469 -3.19203C4.61469 -3.83761 4.61469 -4.31582 4.08867 -4.78207C3.67024 -5.16463 3.13225 -5.332 2.60623 -5.332C1.6259 -5.332 0.872727 -4.68643 0.872727 -3.90934C0.872727 -3.56264 1.09988 -3.39527 1.37484 -3.39527C1.66177 -3.39527 1.86501 -3.59851 1.86501 -3.88543C1.86501 -4.37559 1.43462 -4.37559 1.25529 -4.37559C1.53026 -4.87771 2.10411 -5.0929 2.58232 -5.0929C3.13225 -5.0929 3.83761 -4.63861 3.83761 -3.56264V-3.08443C1.43462 -3.04857 0.526027 -2.04433 0.526027 -1.12379C0.526027 -0.179328 1.6259 0.119552 2.35517 0.119552C3.14421 0.119552 3.68219 -0.358655 3.90934 -0.932503C3.95716 -0.37061 4.32777 0.0597758 4.84184 0.0597758C5.0929 0.0597758 5.7863 -0.107597 5.7863 -1.06401V-1.7335H5.52329V-1.06401C5.52329 -0.382565 5.23636 -0.286924 5.06899 -0.286924C4.61469 -0.286924 4.61469 -0.920548 4.61469 -1.09988V-3.19203ZM3.83761 -1.68568C3.83761 -0.514072 2.96488 -0.119552 2.45081 -0.119552C1.86501 -0.119552 1.37484 -0.549938 1.37484 -1.12379C1.37484 -2.70187 3.40722 -2.84533 3.83761 -2.86924V-1.68568Z' id='g6-97'/>
<path d='M1.99651 -8.29689L0.334745 -8.16538V-7.81868C1.1477 -7.81868 1.24334 -7.73499 1.24334 -7.14919V0H1.50635C1.55417 -0.0956413 1.88892 -0.6934 1.93674 -0.777086C2.21171 -0.334745 2.72578 0.119552 3.49091 0.119552C4.86575 0.119552 6.07323 -1.0401 6.07323 -2.58232C6.07323 -4.10062 4.94944 -5.27223 3.62242 -5.27223C2.96488 -5.27223 2.40299 -4.97335 1.99651 -4.47123V-8.29689ZM2.02042 -3.82565C2.02042 -4.04085 2.02042 -4.06476 2.15193 -4.25604C2.43885 -4.68643 2.96488 -5.03313 3.55068 -5.03313C3.90934 -5.03313 5.16463 -4.88966 5.16463 -2.59427C5.16463 -1.79328 5.04508 -1.29116 4.75816 -0.860772C4.51905 -0.490162 4.04085 -0.119552 3.44309 -0.119552C2.79751 -0.119552 2.37908 -0.537983 2.17584 -0.860772C2.02042 -1.11183 2.02042 -1.15965 2.02042 -1.36289V-3.82565Z' id='g6-98'/>
<path d='M4.32777 -4.42341C4.18431 -4.42341 3.74197 -4.42341 3.74197 -3.93325C3.74197 -3.64633 3.94521 -3.44309 4.23213 -3.44309C4.5071 -3.44309 4.73425 -3.61046 4.73425 -3.95716C4.73425 -4.75816 3.89738 -5.332 2.92902 -5.332C1.53026 -5.332 0.418431 -4.08867 0.418431 -2.58232C0.418431 -1.05205 1.56613 0.119552 2.91706 0.119552C4.49514 0.119552 4.8538 -1.31507 4.8538 -1.42267S4.77011 -1.53026 4.73425 -1.53026C4.62665 -1.53026 4.61469 -1.4944 4.57883 -1.35093C4.31582 -0.502117 3.67024 -0.143462 3.02466 -0.143462C2.29539 -0.143462 1.32702 -0.777086 1.32702 -2.59427C1.32702 -4.57883 2.34321 -5.06899 2.94097 -5.06899C3.39527 -5.06899 4.0528 -4.88966 4.32777 -4.42341Z' id='g6-99'/>
<path d='M4.57883 -2.7736C4.84184 -2.7736 4.86575 -2.7736 4.86575 -3.00075C4.86575 -4.20822 4.22017 -5.332 2.7736 -5.332C1.41071 -5.332 0.358655 -4.10062 0.358655 -2.61818C0.358655 -1.0401 1.57808 0.119552 2.90511 0.119552C4.32777 0.119552 4.86575 -1.17161 4.86575 -1.42267C4.86575 -1.4944 4.80598 -1.54222 4.73425 -1.54222C4.63861 -1.54222 4.61469 -1.48244 4.59078 -1.42267C4.27995 -0.418431 3.47895 -0.143462 2.97684 -0.143462S1.26725 -0.478207 1.26725 -2.54645V-2.7736H4.57883ZM1.2792 -3.00075C1.37484 -4.87771 2.4269 -5.0929 2.76164 -5.0929C4.04085 -5.0929 4.11258 -3.40722 4.12453 -3.00075H1.2792Z' id='g6-101'/>
<path d='M1.42267 -2.16389C1.98456 -1.79328 2.46276 -1.79328 2.59427 -1.79328C3.67024 -1.79328 4.47123 -2.60623 4.47123 -3.52677C4.47123 -3.84956 4.37559 -4.30386 3.99303 -4.68643C4.45928 -5.16463 5.02117 -5.16463 5.08095 -5.16463C5.12877 -5.16463 5.18854 -5.16463 5.23636 -5.14072C5.11681 -5.0929 5.05704 -4.97335 5.05704 -4.84184C5.05704 -4.67447 5.17659 -4.53101 5.36787 -4.53101C5.46351 -4.53101 5.6787 -4.59078 5.6787 -4.8538C5.6787 -5.06899 5.51133 -5.40374 5.0929 -5.40374C4.47123 -5.40374 4.00498 -5.02117 3.83761 -4.84184C3.47895 -5.11681 3.06052 -5.27223 2.60623 -5.27223C1.53026 -5.27223 0.729265 -4.45928 0.729265 -3.53873C0.729265 -2.85729 1.1477 -2.41494 1.26725 -2.30735C1.12379 -2.12802 0.908593 -1.78132 0.908593 -1.31507C0.908593 -0.621669 1.32702 -0.32279 1.42267 -0.263014C0.872727 -0.107597 0.32279 0.32279 0.32279 0.944458C0.32279 1.76936 1.44658 2.45081 2.91706 2.45081C4.33973 2.45081 5.52329 1.81719 5.52329 0.920548C5.52329 0.621669 5.4396 -0.0836862 4.72229 -0.454296C4.11258 -0.765131 3.51482 -0.765131 2.48667 -0.765131C1.75741 -0.765131 1.67372 -0.765131 1.45853 -0.992279C1.33898 -1.11183 1.23138 -1.33898 1.23138 -1.59004C1.23138 -1.79328 1.30311 -1.99651 1.42267 -2.16389ZM2.60623 -2.04433C1.55417 -2.04433 1.55417 -3.25181 1.55417 -3.52677C1.55417 -3.74197 1.55417 -4.23213 1.75741 -4.55492C1.98456 -4.90162 2.34321 -5.02117 2.59427 -5.02117C3.64633 -5.02117 3.64633 -3.8137 3.64633 -3.53873C3.64633 -3.32354 3.64633 -2.83337 3.44309 -2.51059C3.21594 -2.16389 2.85729 -2.04433 2.60623 -2.04433ZM2.92902 2.19975C1.78132 2.19975 0.908593 1.61395 0.908593 0.932503C0.908593 0.836862 0.932503 0.37061 1.3868 0.0597758C1.64981 -0.107597 1.75741 -0.107597 2.59427 -0.107597C3.58655 -0.107597 4.93748 -0.107597 4.93748 0.932503C4.93748 1.63786 4.02889 2.19975 2.92902 2.19975Z' id='g6-103'/>
<path d='M5.32005 -2.90511C5.32005 -4.01694 5.32005 -4.35168 5.04508 -4.73425C4.69838 -5.2005 4.13649 -5.27223 3.73001 -5.27223C2.70187 -5.27223 2.22366 -4.49514 2.05629 -4.12453H2.04433V-8.29689L0.382565 -8.16538V-7.81868C1.19552 -7.81868 1.29116 -7.73499 1.29116 -7.14919V-0.884682C1.29116 -0.3467 1.15965 -0.3467 0.382565 -0.3467V0C0.6934 -0.0239103 1.33898 -0.0239103 1.67372 -0.0239103C2.02042 -0.0239103 2.666 -0.0239103 2.97684 0V-0.3467C2.21171 -0.3467 2.06824 -0.3467 2.06824 -0.884682V-3.10834C2.06824 -4.36364 2.89315 -5.03313 3.63437 -5.03313S4.54296 -4.42341 4.54296 -3.69415V-0.884682C4.54296 -0.3467 4.41146 -0.3467 3.63437 -0.3467V0C3.94521 -0.0239103 4.59078 -0.0239103 4.92553 -0.0239103C5.27223 -0.0239103 5.91781 -0.0239103 6.22864 0V-0.3467C5.63088 -0.3467 5.332 -0.3467 5.32005 -0.705355V-2.90511Z' id='g6-104'/>
<path d='M2.0802 -7.36438C2.0802 -7.67522 1.82914 -7.95019 1.4944 -7.95019C1.18356 -7.95019 0.920548 -7.69913 0.920548 -7.37634C0.920548 -7.01768 1.20747 -6.79054 1.4944 -6.79054C1.86501 -6.79054 2.0802 -7.10137 2.0802 -7.36438ZM0.430386 -5.14072V-4.79402C1.19552 -4.79402 1.30311 -4.72229 1.30311 -4.13649V-0.884682C1.30311 -0.3467 1.17161 -0.3467 0.394521 -0.3467V0C0.729265 -0.0239103 1.30311 -0.0239103 1.64981 -0.0239103C1.78132 -0.0239103 2.47472 -0.0239103 2.8812 0V-0.3467C2.10411 -0.3467 2.05629 -0.406476 2.05629 -0.872727V-5.27223L0.430386 -5.14072Z' id='g6-105'/>
<path d='M3.34745 -3.16812C3.34745 -3.18007 3.26376 -3.27572 3.26376 -3.28767C3.26376 -3.32354 4.01694 -3.96912 4.11258 -4.06476C4.93748 -4.78207 5.46351 -4.79402 5.71457 -4.80598V-5.15268C5.47547 -5.12877 5.16463 -5.12877 4.80598 -5.12877C4.49514 -5.12877 3.88543 -5.12877 3.61046 -5.15268V-4.80598C3.8137 -4.79402 3.95716 -4.68643 3.95716 -4.49514C3.95716 -4.25604 3.71806 -4.04085 3.7061 -4.04085L1.99651 -2.5345V-8.29689L0.334745 -8.16538V-7.81868C1.1477 -7.81868 1.24334 -7.73499 1.24334 -7.14919V-0.884682C1.24334 -0.3467 1.11183 -0.3467 0.334745 -0.3467V0C0.669489 -0.0239103 1.24334 -0.0239103 1.60199 -0.0239103S2.5345 -0.0239103 2.86924 0V-0.3467C2.10411 -0.3467 1.96065 -0.3467 1.96065 -0.884682V-2.15193L2.72578 -2.82142L3.87347 -1.17161C4.0528 -0.920548 4.13649 -0.789041 4.13649 -0.621669C4.13649 -0.406476 3.96912 -0.3467 3.71806 -0.3467V0C4.01694 -0.0239103 4.60274 -0.0239103 4.92553 -0.0239103C5.4396 -0.0239103 5.46351 -0.0239103 5.97758 0V-0.3467C5.65479 -0.3467 5.28418 -0.3467 4.94944 -0.836862L3.34745 -3.16812Z' id='g6-107'/>
<path d='M2.05629 -8.29689L0.394521 -8.16538V-7.81868C1.20747 -7.81868 1.30311 -7.73499 1.30311 -7.14919V-0.884682C1.30311 -0.3467 1.17161 -0.3467 0.394521 -0.3467V0C0.729265 -0.0239103 1.31507 -0.0239103 1.67372 -0.0239103S2.63014 -0.0239103 2.96488 0V-0.3467C2.19975 -0.3467 2.05629 -0.3467 2.05629 -0.884682V-8.29689Z' id='g6-108'/>
<path d='M8.57186 -2.90511C8.57186 -4.01694 8.57186 -4.35168 8.29689 -4.73425C7.95019 -5.2005 7.38829 -5.27223 6.98182 -5.27223C5.98954 -5.27223 5.48742 -4.55492 5.29614 -4.08867C5.12877 -5.00922 4.48319 -5.27223 3.73001 -5.27223C2.57036 -5.27223 2.11606 -4.27995 2.02042 -4.04085H2.00847V-5.27223L0.382565 -5.14072V-4.79402C1.19552 -4.79402 1.29116 -4.71034 1.29116 -4.12453V-0.884682C1.29116 -0.3467 1.15965 -0.3467 0.382565 -0.3467V0C0.6934 -0.0239103 1.33898 -0.0239103 1.67372 -0.0239103C2.02042 -0.0239103 2.666 -0.0239103 2.97684 0V-0.3467C2.21171 -0.3467 2.06824 -0.3467 2.06824 -0.884682V-3.10834C2.06824 -4.36364 2.89315 -5.03313 3.63437 -5.03313S4.54296 -4.42341 4.54296 -3.69415V-0.884682C4.54296 -0.3467 4.41146 -0.3467 3.63437 -0.3467V0C3.94521 -0.0239103 4.59078 -0.0239103 4.92553 -0.0239103C5.27223 -0.0239103 5.91781 -0.0239103 6.22864 0V-0.3467C5.46351 -0.3467 5.32005 -0.3467 5.32005 -0.884682V-3.10834C5.32005 -4.36364 6.14496 -5.03313 6.88618 -5.03313S7.79477 -4.42341 7.79477 -3.69415V-0.884682C7.79477 -0.3467 7.66326 -0.3467 6.88618 -0.3467V0C7.19701 -0.0239103 7.84259 -0.0239103 8.17733 -0.0239103C8.52403 -0.0239103 9.16961 -0.0239103 9.48045 0V-0.3467C8.88269 -0.3467 8.58381 -0.3467 8.57186 -0.705355V-2.90511Z' id='g6-109'/>
<path d='M5.32005 -2.90511C5.32005 -4.01694 5.32005 -4.35168 5.04508 -4.73425C4.69838 -5.2005 4.13649 -5.27223 3.73001 -5.27223C2.57036 -5.27223 2.11606 -4.27995 2.02042 -4.04085H2.00847V-5.27223L0.382565 -5.14072V-4.79402C1.19552 -4.79402 1.29116 -4.71034 1.29116 -4.12453V-0.884682C1.29116 -0.3467 1.15965 -0.3467 0.382565 -0.3467V0C0.6934 -0.0239103 1.33898 -0.0239103 1.67372 -0.0239103C2.02042 -0.0239103 2.666 -0.0239103 2.97684 0V-0.3467C2.21171 -0.3467 2.06824 -0.3467 2.06824 -0.884682V-3.10834C2.06824 -4.36364 2.89315 -5.03313 3.63437 -5.03313S4.54296 -4.42341 4.54296 -3.69415V-0.884682C4.54296 -0.3467 4.41146 -0.3467 3.63437 -0.3467V0C3.94521 -0.0239103 4.59078 -0.0239103 4.92553 -0.0239103C5.27223 -0.0239103 5.91781 -0.0239103 6.22864 0V-0.3467C5.63088 -0.3467 5.332 -0.3467 5.32005 -0.705355V-2.90511Z' id='g6-110'/>
<path d='M5.48742 -2.55841C5.48742 -4.10062 4.31582 -5.332 2.92902 -5.332C1.4944 -5.332 0.358655 -4.06476 0.358655 -2.55841C0.358655 -1.02814 1.55417 0.119552 2.91706 0.119552C4.32777 0.119552 5.48742 -1.05205 5.48742 -2.55841ZM2.92902 -0.143462C2.48667 -0.143462 1.94869 -0.334745 1.60199 -0.920548C1.2792 -1.45853 1.26725 -2.16389 1.26725 -2.666C1.26725 -3.1203 1.26725 -3.84956 1.63786 -4.38755C1.9726 -4.90162 2.49863 -5.0929 2.91706 -5.0929C3.38331 -5.0929 3.88543 -4.87771 4.20822 -4.41146C4.57883 -3.86152 4.57883 -3.10834 4.57883 -2.666C4.57883 -2.24757 4.57883 -1.50635 4.268 -0.944458C3.93325 -0.37061 3.38331 -0.143462 2.92902 -0.143462Z' id='g6-111'/>
<path d='M1.99651 -2.78555C1.99651 -3.94521 2.47472 -5.03313 3.39527 -5.03313C3.49091 -5.03313 3.51482 -5.03313 3.56264 -5.02117C3.467 -4.97335 3.27572 -4.90162 3.27572 -4.57883C3.27572 -4.23213 3.55068 -4.10062 3.74197 -4.10062C3.98107 -4.10062 4.22017 -4.25604 4.22017 -4.57883C4.22017 -4.93748 3.89738 -5.27223 3.38331 -5.27223C2.36712 -5.27223 2.02042 -4.17235 1.94869 -3.94521H1.93674V-5.27223L0.334745 -5.14072V-4.79402C1.1477 -4.79402 1.24334 -4.71034 1.24334 -4.12453V-0.884682C1.24334 -0.3467 1.11183 -0.3467 0.334745 -0.3467V0C0.669489 -0.0239103 1.32702 -0.0239103 1.68568 -0.0239103C2.00847 -0.0239103 2.85729 -0.0239103 3.13225 0V-0.3467H2.89315C2.02042 -0.3467 1.99651 -0.478207 1.99651 -0.908593V-2.78555Z' id='g6-114'/>
<path d='M3.9213 -5.05704C3.9213 -5.27223 3.9213 -5.332 3.80174 -5.332C3.7061 -5.332 3.47895 -5.06899 3.39527 -4.96139C3.02466 -5.26027 2.65405 -5.332 2.27148 -5.332C0.824907 -5.332 0.394521 -4.54296 0.394521 -3.88543C0.394521 -3.75392 0.394521 -3.33549 0.848817 -2.91706C1.23138 -2.58232 1.63786 -2.49863 2.1878 -2.39103C2.84533 -2.25953 3.00075 -2.22366 3.29963 -1.98456C3.51482 -1.80523 3.67024 -1.54222 3.67024 -1.20747C3.67024 -0.6934 3.37136 -0.119552 2.3193 -0.119552C1.53026 -0.119552 0.956413 -0.573848 0.6934 -1.76936C0.645579 -1.98456 0.645579 -1.99651 0.633624 -2.00847C0.609714 -2.05629 0.561893 -2.05629 0.526027 -2.05629C0.394521 -2.05629 0.394521 -1.99651 0.394521 -1.78132V-0.155417C0.394521 0.0597758 0.394521 0.119552 0.514072 0.119552C0.573848 0.119552 0.585803 0.107597 0.789041 -0.143462C0.848817 -0.227148 0.848817 -0.251059 1.02814 -0.442341C1.48244 0.119552 2.12802 0.119552 2.33126 0.119552C3.58655 0.119552 4.20822 -0.573848 4.20822 -1.51831C4.20822 -2.16389 3.8137 -2.54645 3.7061 -2.65405C3.27572 -3.02466 2.95293 -3.09639 2.16389 -3.23985C1.80523 -3.31158 0.932503 -3.47895 0.932503 -4.19626C0.932503 -4.56687 1.18356 -5.11681 2.25953 -5.11681C3.56264 -5.11681 3.63437 -4.00498 3.65828 -3.63437C3.67024 -3.53873 3.75392 -3.53873 3.78979 -3.53873C3.9213 -3.53873 3.9213 -3.59851 3.9213 -3.8137V-5.05704Z' id='g6-115'/>
<path d='M2.00847 -4.80598H3.69415V-5.15268H2.00847V-7.35243H1.74545C1.7335 -6.22864 1.30311 -5.08095 0.215193 -5.04508V-4.80598H1.23138V-1.48244C1.23138 -0.155417 2.11606 0.119552 2.74969 0.119552C3.50286 0.119552 3.89738 -0.621669 3.89738 -1.48244V-2.16389H3.63437V-1.50635C3.63437 -0.645579 3.28767 -0.143462 2.82142 -0.143462C2.00847 -0.143462 2.00847 -1.25529 2.00847 -1.45853V-4.80598Z' id='g6-116'/>
<path d='M4.87771 -4.01694C4.98531 -4.27995 5.18854 -4.79402 5.95367 -4.80598V-5.15268C5.60697 -5.12877 5.4396 -5.12877 5.06899 -5.12877C4.81793 -5.12877 4.63861 -5.12877 4.08867 -5.15268V-4.80598C4.59078 -4.78207 4.65056 -4.42341 4.65056 -4.29191C4.65056 -4.18431 4.62665 -4.12453 4.56687 -3.98107L3.34745 -0.896638L2.00847 -4.268C1.94869 -4.43537 1.93674 -4.43537 1.93674 -4.49514C1.93674 -4.80598 2.39103 -4.80598 2.60623 -4.80598V-5.15268C2.30735 -5.12877 1.68568 -5.12877 1.36289 -5.12877C0.968369 -5.12877 0.944458 -5.12877 0.215193 -5.15268V-4.80598C0.884682 -4.80598 1.00423 -4.75816 1.1477 -4.38755L2.85729 -0.107597C2.91706 0.0597758 2.94097 0.119552 3.08443 0.119552C3.16812 0.119552 3.23985 0.0956413 3.32354 -0.107597L4.87771 -4.01694Z' id='g6-118'/>
<path d='M7.23288 -4.01694C7.49589 -4.77011 8.02192 -4.79402 8.22516 -4.80598V-5.15268C7.92628 -5.12877 7.71108 -5.12877 7.34047 -5.12877C6.99377 -5.12877 6.96986 -5.12877 6.32428 -5.15268V-4.80598C6.86227 -4.78207 7.00573 -4.45928 7.00573 -4.23213C7.00573 -4.22017 7.00573 -4.13649 6.95791 -4.01694L5.85803 -0.884682L4.66252 -4.268C4.60274 -4.41146 4.60274 -4.43537 4.60274 -4.47123C4.60274 -4.80598 5.04508 -4.80598 5.29614 -4.80598V-5.15268C4.96139 -5.12877 4.47123 -5.12877 4.12453 -5.12877C3.74197 -5.12877 3.71806 -5.12877 3.04857 -5.15268V-4.80598C3.50286 -4.80598 3.65828 -4.78207 3.78979 -4.62665C3.84956 -4.55492 3.99303 -4.1604 4.07671 -3.9213L3.06052 -1.00423L1.91283 -4.25604C1.85305 -4.41146 1.85305 -4.43537 1.85305 -4.48319C1.85305 -4.80598 2.3193 -4.80598 2.54645 -4.80598V-5.15268C2.24757 -5.12877 1.64981 -5.12877 1.32702 -5.12877C0.992279 -5.12877 0.968369 -5.12877 0.215193 -5.15268V-4.80598C0.824907 -4.80598 0.944458 -4.75816 1.07597 -4.37559L2.58232 -0.0956413C2.63014 0.0358655 2.666 0.119552 2.79751 0.119552C2.90511 0.119552 2.96488 0.0836862 3.02466 -0.107597L4.22017 -3.51482L5.41569 -0.107597C5.47547 0.0836862 5.53524 0.119552 5.64284 0.119552C5.77435 0.119552 5.81021 0.0358655 5.85803 -0.0956413L7.23288 -4.01694Z' id='g6-119'/>
<path d='M3.34745 -2.82142C3.69415 -3.27572 4.19626 -3.9213 4.42341 -4.17235C4.91357 -4.72229 5.47547 -4.80598 5.85803 -4.80598V-5.15268C5.34396 -5.12877 5.32005 -5.12877 4.8538 -5.12877C4.3995 -5.12877 4.37559 -5.12877 3.77783 -5.15268V-4.80598C3.93325 -4.78207 4.12453 -4.71034 4.12453 -4.43537C4.12453 -4.23213 4.01694 -4.10062 3.94521 -4.00498L3.18007 -3.03661L2.24757 -4.268C2.21171 -4.31582 2.13998 -4.42341 2.13998 -4.5071C2.13998 -4.57883 2.19975 -4.79402 2.55841 -4.80598V-5.15268C2.25953 -5.12877 1.64981 -5.12877 1.32702 -5.12877C0.932503 -5.12877 0.908593 -5.12877 0.179328 -5.15268V-4.80598C0.789041 -4.80598 1.01619 -4.78207 1.26725 -4.45928L2.666 -2.63014C2.68991 -2.60623 2.73773 -2.5345 2.73773 -2.49863S1.80523 -1.29116 1.68568 -1.13574C1.15965 -0.490162 0.633624 -0.358655 0.119552 -0.3467V0C0.573848 -0.0239103 0.597758 -0.0239103 1.11183 -0.0239103C1.56613 -0.0239103 1.59004 -0.0239103 2.1878 0V-0.3467C1.90087 -0.382565 1.85305 -0.561893 1.85305 -0.729265C1.85305 -0.920548 1.93674 -1.01619 2.05629 -1.17161C2.23562 -1.42267 2.63014 -1.91283 2.91706 -2.28344L3.89738 -1.00423C4.10062 -0.74122 4.10062 -0.71731 4.10062 -0.645579C4.10062 -0.549938 4.00498 -0.358655 3.68219 -0.3467V0C3.99303 -0.0239103 4.57883 -0.0239103 4.91357 -0.0239103C5.30809 -0.0239103 5.332 -0.0239103 6.04932 0V-0.3467C5.41569 -0.3467 5.2005 -0.37061 4.91357 -0.753176L3.34745 -2.82142Z' id='g6-120'/>
<path d='M2.1599 1.99253V1.6259H1.35492V-5.61096H2.1599V-5.97758H0.988294V1.99253H2.1599Z' id='g5-91'/>
<path d='M1.35492 -5.97758H0.183313V-5.61096H0.988294V1.6259H0.183313V1.99253H1.35492V-5.97758Z' id='g5-93'/>
<path d='M6.55143 -2.74969C6.75467 -2.74969 6.96986 -2.74969 6.96986 -2.98879S6.75467 -3.2279 6.55143 -3.2279H1.48244C1.6259 -4.82989 3.00075 -5.97758 4.68643 -5.97758H6.55143C6.75467 -5.97758 6.96986 -5.97758 6.96986 -6.21669S6.75467 -6.45579 6.55143 -6.45579H4.66252C2.61818 -6.45579 0.992279 -4.90162 0.992279 -2.98879S2.61818 0.478207 4.66252 0.478207H6.55143C6.75467 0.478207 6.96986 0.478207 6.96986 0.239103S6.75467 0 6.55143 0H4.68643C3.00075 0 1.6259 -1.1477 1.48244 -2.74969H6.55143Z' id='g2-50'/>
<path d='M3.38331 -7.37634C3.38331 -7.85455 3.69415 -8.61968 4.99726 -8.70336C5.05704 -8.71532 5.10486 -8.76314 5.10486 -8.83487C5.10486 -8.96638 5.00922 -8.96638 4.87771 -8.96638C3.68219 -8.96638 2.59427 -8.35666 2.58232 -7.47198V-4.7462C2.58232 -4.27995 2.58232 -3.89738 2.10411 -3.50286C1.68568 -3.15616 1.23138 -3.13225 0.968369 -3.1203C0.908593 -3.10834 0.860772 -3.06052 0.860772 -2.98879C0.860772 -2.86924 0.932503 -2.86924 1.05205 -2.85729C1.8411 -2.80946 2.41494 -2.37908 2.54645 -1.79328C2.58232 -1.66177 2.58232 -1.63786 2.58232 -1.20747V1.15965C2.58232 1.66177 2.58232 2.04433 3.15616 2.49863C3.62242 2.85729 4.41146 2.98879 4.87771 2.98879C5.00922 2.98879 5.10486 2.98879 5.10486 2.85729C5.10486 2.73773 5.03313 2.73773 4.91357 2.72578C4.1604 2.67796 3.5746 2.29539 3.41918 1.68568C3.38331 1.57808 3.38331 1.55417 3.38331 1.12379V-1.3868C3.38331 -1.93674 3.28767 -2.13998 2.90511 -2.52254C2.65405 -2.7736 2.30735 -2.89315 1.9726 -2.98879C2.95293 -3.26376 3.38331 -3.8137 3.38331 -4.5071V-7.37634Z' id='g2-102'/>
<path d='M2.58232 1.39875C2.58232 1.87696 2.27148 2.64209 0.968369 2.72578C0.908593 2.73773 0.860772 2.78555 0.860772 2.85729C0.860772 2.98879 0.992279 2.98879 1.09988 2.98879C2.25953 2.98879 3.37136 2.40299 3.38331 1.4944V-1.23138C3.38331 -1.69763 3.38331 -2.0802 3.86152 -2.47472C4.27995 -2.82142 4.73425 -2.84533 4.99726 -2.85729C5.05704 -2.86924 5.10486 -2.91706 5.10486 -2.98879C5.10486 -3.10834 5.03313 -3.10834 4.91357 -3.1203C4.12453 -3.16812 3.55068 -3.59851 3.41918 -4.18431C3.38331 -4.31582 3.38331 -4.33973 3.38331 -4.77011V-7.13724C3.38331 -7.63935 3.38331 -8.02192 2.80946 -8.47621C2.33126 -8.84682 1.50635 -8.96638 1.09988 -8.96638C0.992279 -8.96638 0.860772 -8.96638 0.860772 -8.83487C0.860772 -8.71532 0.932503 -8.71532 1.05205 -8.70336C1.80523 -8.65554 2.39103 -8.27298 2.54645 -7.66326C2.58232 -7.55567 2.58232 -7.53176 2.58232 -7.10137V-4.59078C2.58232 -4.04085 2.67796 -3.83761 3.06052 -3.45504C3.31158 -3.20399 3.65828 -3.08443 3.99303 -2.98879C3.0127 -2.71382 2.58232 -2.16389 2.58232 -1.47049V1.39875Z' id='g2-103'/>
<path d='M1.90087 -8.53599C1.90087 -8.75118 1.90087 -8.96638 1.66177 -8.96638S1.42267 -8.75118 1.42267 -8.53599V2.55841C1.42267 2.7736 1.42267 2.98879 1.66177 2.98879S1.90087 2.7736 1.90087 2.55841V-8.53599Z' id='g2-106'/>
<path d='M2.33126 0.0478207C2.33126 -0.645579 2.10411 -1.15965 1.61395 -1.15965C1.23138 -1.15965 1.0401 -0.848817 1.0401 -0.585803S1.21943 0 1.6259 0C1.78132 0 1.91283 -0.0478207 2.02042 -0.155417C2.04433 -0.179328 2.05629 -0.179328 2.06824 -0.179328C2.09215 -0.179328 2.09215 -0.0119552 2.09215 0.0478207C2.09215 0.442341 2.02042 1.21943 1.32702 1.99651C1.19552 2.13998 1.19552 2.16389 1.19552 2.1878C1.19552 2.24757 1.25529 2.30735 1.31507 2.30735C1.41071 2.30735 2.33126 1.42267 2.33126 0.0478207Z' id='g4-59'/>
<path d='M2.03238 -1.32702C1.61395 -0.621669 1.20747 -0.382565 0.633624 -0.3467C0.502117 -0.334745 0.406476 -0.334745 0.406476 -0.119552C0.406476 -0.0478207 0.466252 0 0.549938 0C0.765131 0 1.30311 -0.0239103 1.51831 -0.0239103C1.86501 -0.0239103 2.24757 0 2.58232 0C2.65405 0 2.79751 0 2.79751 -0.227148C2.79751 -0.334745 2.70187 -0.3467 2.63014 -0.3467C2.35517 -0.37061 2.12802 -0.466252 2.12802 -0.753176C2.12802 -0.920548 2.19975 -1.05205 2.35517 -1.31507L3.26376 -2.82142H6.31233C6.32428 -2.71382 6.32428 -2.61818 6.33624 -2.51059C6.3721 -2.19975 6.51557 -0.956413 6.51557 -0.729265C6.51557 -0.37061 5.90585 -0.3467 5.71457 -0.3467C5.58306 -0.3467 5.45156 -0.3467 5.45156 -0.131507C5.45156 0 5.55915 0 5.63088 0C5.83412 0 6.07323 -0.0239103 6.27646 -0.0239103H6.95791C7.68717 -0.0239103 8.2132 0 8.22516 0C8.30884 0 8.44035 0 8.44035 -0.227148C8.44035 -0.3467 8.33275 -0.3467 8.15342 -0.3467C7.49589 -0.3467 7.48394 -0.454296 7.44807 -0.812951L6.7188 -8.27298C6.69489 -8.51208 6.64707 -8.53599 6.51557 -8.53599C6.39601 -8.53599 6.32428 -8.51208 6.21669 -8.33275L2.03238 -1.32702ZM3.467 -3.16812L5.86999 -7.18506L6.27646 -3.16812H3.467Z' id='g4-65'/>
<path d='M4.37559 -7.35243C4.48319 -7.79477 4.53101 -7.81868 4.99726 -7.81868H6.55143C7.90237 -7.81868 7.90237 -6.67098 7.90237 -6.56339C7.90237 -5.59502 6.934 -4.36364 5.35592 -4.36364H3.63437L4.37559 -7.35243ZM6.39601 -4.268C7.69913 -4.5071 8.88269 -5.41569 8.88269 -6.51557C8.88269 -7.44807 8.05778 -8.16538 6.70685 -8.16538H2.86924C2.64209 -8.16538 2.5345 -8.16538 2.5345 -7.93823C2.5345 -7.81868 2.64209 -7.81868 2.82142 -7.81868C3.55068 -7.81868 3.55068 -7.72304 3.55068 -7.59153C3.55068 -7.56762 3.55068 -7.49589 3.50286 -7.31656L1.88892 -0.884682C1.78132 -0.466252 1.75741 -0.3467 0.920548 -0.3467C0.6934 -0.3467 0.573848 -0.3467 0.573848 -0.131507C0.573848 0 0.645579 0 0.884682 0H4.98531C6.81445 0 8.22516 -1.3868 8.22516 -2.59427C8.22516 -3.5746 7.36438 -4.17235 6.39601 -4.268ZM4.69838 -0.3467H3.08443C2.91706 -0.3467 2.89315 -0.3467 2.82142 -0.358655C2.68991 -0.37061 2.67796 -0.394521 2.67796 -0.490162C2.67796 -0.573848 2.70187 -0.645579 2.72578 -0.753176L3.56264 -4.12453H5.81021C7.22092 -4.12453 7.22092 -2.80946 7.22092 -2.71382C7.22092 -1.56613 6.18082 -0.3467 4.69838 -0.3467Z' id='g4-66'/>
<path d='M8.93051 -8.30884C8.93051 -8.41644 8.84682 -8.41644 8.82291 -8.41644S8.75118 -8.41644 8.65554 -8.29689L7.83064 -7.29265C7.4122 -8.00996 6.75467 -8.41644 5.85803 -8.41644C3.27572 -8.41644 0.597758 -5.79826 0.597758 -2.98879C0.597758 -0.992279 1.99651 0.251059 3.74197 0.251059C4.69838 0.251059 5.53524 -0.155417 6.22864 -0.74122C7.26874 -1.61395 7.57958 -2.7736 7.57958 -2.86924C7.57958 -2.97684 7.48394 -2.97684 7.44807 -2.97684C7.34047 -2.97684 7.32852 -2.90511 7.30461 -2.85729C6.75467 -0.992279 5.14072 -0.0956413 3.94521 -0.0956413C2.67796 -0.0956413 1.57808 -0.908593 1.57808 -2.60623C1.57808 -2.98879 1.69763 -5.06899 3.04857 -6.63512C3.7061 -7.40025 4.82989 -8.06974 5.96563 -8.06974C7.2807 -8.06974 7.8665 -6.98182 7.8665 -5.76239C7.8665 -5.45156 7.83064 -5.18854 7.83064 -5.14072C7.83064 -5.03313 7.95019 -5.03313 7.98605 -5.03313C8.11756 -5.03313 8.12951 -5.04508 8.17733 -5.26027L8.93051 -8.30884Z' id='g4-67'/>
<path d='M8.30884 -2.7736C8.3208 -2.80946 8.35666 -2.89315 8.35666 -2.94097C8.35666 -3.00075 8.30884 -3.06052 8.23711 -3.06052C8.18929 -3.06052 8.16538 -3.04857 8.12951 -3.0127C8.1056 -3.00075 8.1056 -2.97684 7.99801 -2.73773C7.29265 -1.06401 6.77858 -0.3467 4.86575 -0.3467H3.1203C2.95293 -0.3467 2.92902 -0.3467 2.85729 -0.358655C2.72578 -0.37061 2.71382 -0.394521 2.71382 -0.490162C2.71382 -0.573848 2.73773 -0.645579 2.76164 -0.753176L3.58655 -4.0528H4.77011C5.70262 -4.0528 5.77435 -3.84956 5.77435 -3.49091C5.77435 -3.37136 5.77435 -3.26376 5.69066 -2.90511C5.66675 -2.85729 5.65479 -2.80946 5.65479 -2.7736C5.65479 -2.68991 5.71457 -2.65405 5.7863 -2.65405C5.8939 -2.65405 5.90585 -2.73773 5.95367 -2.90511L6.63512 -5.6787C6.63512 -5.73848 6.5873 -5.79826 6.51557 -5.79826C6.40797 -5.79826 6.39601 -5.75044 6.34819 -5.58306C6.10909 -4.66252 5.86999 -4.3995 4.80598 -4.3995H3.67024L4.41146 -7.34047C4.51905 -7.7589 4.54296 -7.79477 5.03313 -7.79477H6.74271C8.2132 -7.79477 8.51208 -7.40025 8.51208 -6.49166C8.51208 -6.4797 8.51208 -6.14496 8.46426 -5.75044C8.4523 -5.70262 8.44035 -5.63088 8.44035 -5.60697C8.44035 -5.51133 8.50012 -5.47547 8.57186 -5.47547C8.65554 -5.47547 8.70336 -5.52329 8.72727 -5.73848L8.97833 -7.83064C8.97833 -7.8665 9.00224 -7.98605 9.00224 -8.00996C9.00224 -8.14147 8.89465 -8.14147 8.67945 -8.14147H2.84533C2.61818 -8.14147 2.49863 -8.14147 2.49863 -7.92628C2.49863 -7.79477 2.58232 -7.79477 2.78555 -7.79477C3.52677 -7.79477 3.52677 -7.71108 3.52677 -7.57958C3.52677 -7.5198 3.51482 -7.47198 3.47895 -7.34047L1.86501 -0.884682C1.75741 -0.466252 1.7335 -0.3467 0.896638 -0.3467C0.669489 -0.3467 0.549938 -0.3467 0.549938 -0.131507C0.549938 0 0.621669 0 0.860772 0H6.86227C7.12528 0 7.13724 -0.0119552 7.22092 -0.203238L8.30884 -2.7736Z' id='g4-69'/>
<path d='M4.3995 -7.2807C4.5071 -7.69913 4.53101 -7.81868 5.40374 -7.81868C5.66675 -7.81868 5.76239 -7.81868 5.76239 -8.04583C5.76239 -8.16538 5.63088 -8.16538 5.59502 -8.16538C5.37983 -8.16538 5.11681 -8.14147 4.90162 -8.14147H3.43113C3.19203 -8.14147 2.91706 -8.16538 2.67796 -8.16538C2.58232 -8.16538 2.45081 -8.16538 2.45081 -7.93823C2.45081 -7.81868 2.54645 -7.81868 2.78555 -7.81868C3.52677 -7.81868 3.52677 -7.72304 3.52677 -7.59153C3.52677 -7.50785 3.50286 -7.43611 3.47895 -7.32852L1.86501 -0.884682C1.75741 -0.466252 1.7335 -0.3467 0.860772 -0.3467C0.597758 -0.3467 0.490162 -0.3467 0.490162 -0.119552C0.490162 0 0.609714 0 0.669489 0C0.884682 0 1.1477 -0.0239103 1.36289 -0.0239103H2.83337C3.07248 -0.0239103 3.33549 0 3.5746 0C3.67024 0 3.8137 0 3.8137 -0.215193C3.8137 -0.3467 3.74197 -0.3467 3.47895 -0.3467C2.73773 -0.3467 2.73773 -0.442341 2.73773 -0.585803C2.73773 -0.609714 2.73773 -0.669489 2.78555 -0.860772L4.3995 -7.2807Z' id='g4-73'/>
<path d='M4.38755 -7.24483C4.49514 -7.69913 4.53101 -7.81868 5.58306 -7.81868C5.90585 -7.81868 5.98954 -7.81868 5.98954 -8.04583C5.98954 -8.16538 5.85803 -8.16538 5.81021 -8.16538C5.57111 -8.16538 5.29614 -8.14147 5.05704 -8.14147H3.45504C3.2279 -8.14147 2.96488 -8.16538 2.73773 -8.16538C2.64209 -8.16538 2.51059 -8.16538 2.51059 -7.93823C2.51059 -7.81868 2.61818 -7.81868 2.79751 -7.81868C3.52677 -7.81868 3.52677 -7.72304 3.52677 -7.59153C3.52677 -7.56762 3.52677 -7.49589 3.47895 -7.31656L1.86501 -0.884682C1.75741 -0.466252 1.7335 -0.3467 0.896638 -0.3467C0.669489 -0.3467 0.549938 -0.3467 0.549938 -0.131507C0.549938 0 0.621669 0 0.860772 0H6.21669C6.4797 0 6.49166 -0.0119552 6.57534 -0.227148L7.49589 -2.7736C7.5198 -2.83337 7.54371 -2.90511 7.54371 -2.94097C7.54371 -3.0127 7.48394 -3.06052 7.42416 -3.06052C7.4122 -3.06052 7.35243 -3.06052 7.32852 -3.0127C7.30461 -3.00075 7.30461 -2.97684 7.20897 -2.74969C6.8264 -1.69763 6.28842 -0.3467 4.268 -0.3467H3.1203C2.95293 -0.3467 2.92902 -0.3467 2.85729 -0.358655C2.72578 -0.37061 2.71382 -0.394521 2.71382 -0.490162C2.71382 -0.573848 2.73773 -0.645579 2.76164 -0.753176L4.38755 -7.24483Z' id='g4-76'/>
<path d='M8.84682 -6.91009C8.97833 -7.42416 9.16961 -7.78281 10.0782 -7.81868C10.1141 -7.81868 10.2575 -7.83064 10.2575 -8.03387C10.2575 -8.16538 10.1499 -8.16538 10.1021 -8.16538C9.86301 -8.16538 9.2533 -8.14147 9.0142 -8.14147H8.44035C8.27298 -8.14147 8.05778 -8.16538 7.89041 -8.16538C7.81868 -8.16538 7.67522 -8.16538 7.67522 -7.93823C7.67522 -7.81868 7.77086 -7.81868 7.85455 -7.81868C8.57186 -7.79477 8.61968 -7.5198 8.61968 -7.30461C8.61968 -7.19701 8.60772 -7.16115 8.57186 -6.99377L7.22092 -1.60199L4.66252 -7.96214C4.57883 -8.15342 4.56687 -8.16538 4.30386 -8.16538H2.84533C2.60623 -8.16538 2.49863 -8.16538 2.49863 -7.93823C2.49863 -7.81868 2.58232 -7.81868 2.80946 -7.81868C2.86924 -7.81868 3.5746 -7.81868 3.5746 -7.71108C3.5746 -7.68717 3.55068 -7.59153 3.53873 -7.55567L1.94869 -1.21943C1.80523 -0.633624 1.51831 -0.382565 0.729265 -0.3467C0.669489 -0.3467 0.549938 -0.334745 0.549938 -0.119552C0.549938 0 0.669489 0 0.705355 0C0.944458 0 1.55417 -0.0239103 1.79328 -0.0239103H2.36712C2.5345 -0.0239103 2.73773 0 2.90511 0C2.98879 0 3.1203 0 3.1203 -0.227148C3.1203 -0.334745 3.00075 -0.3467 2.95293 -0.3467C2.55841 -0.358655 2.17584 -0.430386 2.17584 -0.860772C2.17584 -0.956413 2.19975 -1.06401 2.22366 -1.15965L3.83761 -7.55567C3.90934 -7.43611 3.90934 -7.4122 3.95716 -7.30461L6.80249 -0.215193C6.86227 -0.071731 6.88618 0 6.99377 0C7.11333 0 7.12528 -0.0358655 7.1731 -0.239103L8.84682 -6.91009Z' id='g4-78'/>
<path d='M8.67945 -5.23636C8.67945 -7.20897 7.38829 -8.41644 5.71457 -8.41644C3.15616 -8.41644 0.573848 -5.66675 0.573848 -2.90511C0.573848 -1.02814 1.81719 0.251059 3.55068 0.251059C6.06127 0.251059 8.67945 -2.36712 8.67945 -5.23636ZM3.62242 -0.0239103C2.64209 -0.0239103 1.60199 -0.74122 1.60199 -2.60623C1.60199 -3.69415 1.99651 -5.47547 2.97684 -6.67098C3.84956 -7.72304 4.8538 -8.15342 5.65479 -8.15342C6.70685 -8.15342 7.72304 -7.38829 7.72304 -5.66675C7.72304 -4.60274 7.26874 -2.94097 6.46775 -1.80523C5.59502 -0.585803 4.5071 -0.0239103 3.62242 -0.0239103Z' id='g4-79'/>
<path d='M3.53873 -3.80174H5.5472C7.19701 -3.80174 8.84682 -5.02117 8.84682 -6.38406C8.84682 -7.31656 8.05778 -8.16538 6.55143 -8.16538H2.85729C2.63014 -8.16538 2.52254 -8.16538 2.52254 -7.93823C2.52254 -7.81868 2.63014 -7.81868 2.80946 -7.81868C3.53873 -7.81868 3.53873 -7.72304 3.53873 -7.59153C3.53873 -7.56762 3.53873 -7.49589 3.49091 -7.31656L1.87696 -0.884682C1.76936 -0.466252 1.74545 -0.3467 0.908593 -0.3467C0.681445 -0.3467 0.561893 -0.3467 0.561893 -0.131507C0.561893 0 0.669489 0 0.74122 0C0.968369 0 1.20747 -0.0239103 1.43462 -0.0239103H2.83337C3.06052 -0.0239103 3.31158 0 3.53873 0C3.63437 0 3.76588 0 3.76588 -0.227148C3.76588 -0.3467 3.65828 -0.3467 3.47895 -0.3467C2.76164 -0.3467 2.74969 -0.430386 2.74969 -0.549938C2.74969 -0.609714 2.76164 -0.6934 2.7736 -0.753176L3.53873 -3.80174ZM4.3995 -7.35243C4.5071 -7.79477 4.55492 -7.81868 5.02117 -7.81868H6.20473C7.10137 -7.81868 7.84259 -7.53176 7.84259 -6.63512C7.84259 -6.32428 7.68717 -5.30809 7.13724 -4.75816C6.934 -4.54296 6.36015 -4.08867 5.27223 -4.08867H3.58655L4.3995 -7.35243Z' id='g4-80'/>
<path d='M4.3995 -7.35243C4.5071 -7.79477 4.55492 -7.81868 5.02117 -7.81868H5.88194C6.91009 -7.81868 7.67522 -7.50785 7.67522 -6.57534C7.67522 -5.96563 7.36438 -4.20822 4.96139 -4.20822H3.61046L4.3995 -7.35243ZM6.06127 -4.06476C7.54371 -4.38755 8.70336 -5.34396 8.70336 -6.3721C8.70336 -7.30461 7.7589 -8.16538 6.09714 -8.16538H2.85729C2.61818 -8.16538 2.51059 -8.16538 2.51059 -7.93823C2.51059 -7.81868 2.59427 -7.81868 2.82142 -7.81868C3.53873 -7.81868 3.53873 -7.72304 3.53873 -7.59153C3.53873 -7.56762 3.53873 -7.49589 3.49091 -7.31656L1.87696 -0.884682C1.76936 -0.466252 1.74545 -0.3467 0.920548 -0.3467C0.645579 -0.3467 0.561893 -0.3467 0.561893 -0.119552C0.561893 0 0.6934 0 0.729265 0C0.944458 0 1.19552 -0.0239103 1.42267 -0.0239103H2.83337C3.04857 -0.0239103 3.29963 0 3.51482 0C3.61046 0 3.74197 0 3.74197 -0.227148C3.74197 -0.3467 3.63437 -0.3467 3.45504 -0.3467C2.72578 -0.3467 2.72578 -0.442341 2.72578 -0.561893C2.72578 -0.573848 2.72578 -0.657534 2.74969 -0.753176L3.55068 -3.96912H4.98531C6.12105 -3.96912 6.33624 -3.25181 6.33624 -2.85729C6.33624 -2.67796 6.21669 -2.21171 6.133 -1.90087C6.00149 -1.35093 5.96563 -1.21943 5.96563 -0.992279C5.96563 -0.143462 6.65903 0.251059 7.46002 0.251059C8.42839 0.251059 8.84682 -0.932503 8.84682 -1.09988C8.84682 -1.18356 8.78705 -1.21943 8.71532 -1.21943C8.61968 -1.21943 8.59577 -1.1477 8.57186 -1.05205C8.28493 -0.203238 7.79477 0.0119552 7.49589 0.0119552S7.00573 -0.119552 7.00573 -0.657534C7.00573 -0.944458 7.14919 -2.03238 7.16115 -2.09215C7.22092 -2.5345 7.22092 -2.58232 7.22092 -2.67796C7.22092 -3.55068 6.51557 -3.9213 6.06127 -4.06476Z' id='g4-82'/>
<path d='M7.59153 -8.30884C7.59153 -8.41644 7.50785 -8.41644 7.48394 -8.41644C7.43611 -8.41644 7.42416 -8.40448 7.2807 -8.22516C7.20897 -8.14147 6.7188 -7.5198 6.70685 -7.50785C6.31233 -8.28493 5.52329 -8.41644 5.02117 -8.41644C3.50286 -8.41644 2.12802 -7.02964 2.12802 -5.6787C2.12802 -4.78207 2.666 -4.25604 3.25181 -4.0528C3.38331 -4.00498 4.08867 -3.8137 4.44732 -3.73001C5.05704 -3.56264 5.21245 -3.51482 5.46351 -3.25181C5.51133 -3.19203 5.75044 -2.91706 5.75044 -2.35517C5.75044 -1.24334 4.72229 -0.0956413 3.52677 -0.0956413C2.54645 -0.0956413 1.45853 -0.514072 1.45853 -1.85305C1.45853 -2.0802 1.50635 -2.36712 1.54222 -2.48667C1.54222 -2.52254 1.55417 -2.58232 1.55417 -2.60623C1.55417 -2.65405 1.53026 -2.71382 1.43462 -2.71382C1.32702 -2.71382 1.31507 -2.68991 1.26725 -2.48667L0.657534 -0.0358655C0.657534 -0.0239103 0.609714 0.131507 0.609714 0.143462C0.609714 0.251059 0.705355 0.251059 0.729265 0.251059C0.777086 0.251059 0.789041 0.239103 0.932503 0.0597758L1.48244 -0.657534C1.76936 -0.227148 2.39103 0.251059 3.50286 0.251059C5.04508 0.251059 6.45579 -1.24334 6.45579 -2.73773C6.45579 -3.23985 6.33624 -3.68219 5.88194 -4.12453C5.63088 -4.37559 5.41569 -4.43537 4.31582 -4.72229C3.51482 -4.93748 3.40722 -4.97335 3.19203 -5.16463C2.98879 -5.36787 2.83337 -5.65479 2.83337 -6.06127C2.83337 -7.0655 3.84956 -8.09365 4.98531 -8.09365C6.15691 -8.09365 6.70685 -7.37634 6.70685 -6.2406C6.70685 -5.92976 6.64707 -5.60697 6.64707 -5.55915C6.64707 -5.45156 6.74271 -5.45156 6.77858 -5.45156C6.88618 -5.45156 6.89813 -5.48742 6.94595 -5.6787L7.59153 -8.30884Z' id='g4-83'/>
<path d='M4.98531 -7.29265C5.05704 -7.57958 5.08095 -7.68717 5.26027 -7.73499C5.35592 -7.7589 5.75044 -7.7589 6.00149 -7.7589C7.19701 -7.7589 7.7589 -7.71108 7.7589 -6.77858C7.7589 -6.59925 7.71108 -6.14496 7.63935 -5.70262L7.6274 -5.55915C7.6274 -5.51133 7.67522 -5.4396 7.74695 -5.4396C7.8665 -5.4396 7.8665 -5.49938 7.90237 -5.69066L8.24907 -7.80672C8.27298 -7.91432 8.27298 -7.93823 8.27298 -7.9741C8.27298 -8.1056 8.20125 -8.1056 7.96214 -8.1056H1.42267C1.1477 -8.1056 1.13574 -8.09365 1.06401 -7.87846L0.334745 -5.72653C0.32279 -5.70262 0.286924 -5.57111 0.286924 -5.55915C0.286924 -5.49938 0.334745 -5.4396 0.406476 -5.4396C0.502117 -5.4396 0.526027 -5.48742 0.573848 -5.64284C1.07597 -7.08941 1.32702 -7.7589 2.91706 -7.7589H3.71806C4.00498 -7.7589 4.12453 -7.7589 4.12453 -7.6274C4.12453 -7.59153 4.12453 -7.56762 4.06476 -7.35243L2.46276 -0.932503C2.34321 -0.466252 2.3193 -0.3467 1.05205 -0.3467C0.753176 -0.3467 0.669489 -0.3467 0.669489 -0.119552C0.669489 0 0.800996 0 0.860772 0C1.15965 0 1.47049 -0.0239103 1.76936 -0.0239103H3.63437C3.93325 -0.0239103 4.25604 0 4.55492 0C4.68643 0 4.80598 0 4.80598 -0.227148C4.80598 -0.3467 4.72229 -0.3467 4.41146 -0.3467C3.33549 -0.3467 3.33549 -0.454296 3.33549 -0.633624C3.33549 -0.645579 3.33549 -0.729265 3.38331 -0.920548L4.98531 -7.29265Z' id='g4-84'/>
<path d='M6.04932 -2.74969C5.63088 -1.07597 4.24408 -0.0956413 3.1203 -0.0956413C2.25953 -0.0956413 1.67372 -0.669489 1.67372 -1.66177C1.67372 -1.70959 1.67372 -2.06824 1.80523 -2.59427L2.97684 -7.29265C3.08443 -7.69913 3.10834 -7.81868 3.95716 -7.81868C4.17235 -7.81868 4.29191 -7.81868 4.29191 -8.03387C4.29191 -8.16538 4.18431 -8.16538 4.11258 -8.16538C3.89738 -8.16538 3.64633 -8.14147 3.41918 -8.14147H2.00847C1.78132 -8.14147 1.53026 -8.16538 1.30311 -8.16538C1.21943 -8.16538 1.07597 -8.16538 1.07597 -7.93823C1.07597 -7.81868 1.15965 -7.81868 1.3868 -7.81868C2.10411 -7.81868 2.10411 -7.72304 2.10411 -7.59153C2.10411 -7.5198 2.02042 -7.1731 1.96065 -6.96986L0.920548 -2.78555C0.884682 -2.65405 0.812951 -2.33126 0.812951 -2.00847C0.812951 -0.6934 1.75741 0.251059 3.06052 0.251059C4.268 0.251059 5.60697 -0.705355 6.21669 -2.22366C6.30037 -2.4269 6.40797 -2.84533 6.4797 -3.16812C6.59925 -3.59851 6.85031 -4.65056 6.934 -4.96139L7.38829 -6.75467C7.54371 -7.37634 7.63935 -7.77086 8.69141 -7.81868C8.78705 -7.83064 8.83487 -7.92628 8.83487 -8.03387C8.83487 -8.16538 8.72727 -8.16538 8.67945 -8.16538C8.51208 -8.16538 8.29689 -8.14147 8.12951 -8.14147H7.56762C6.8264 -8.14147 6.44384 -8.16538 6.43188 -8.16538C6.36015 -8.16538 6.21669 -8.16538 6.21669 -7.93823C6.21669 -7.81868 6.31233 -7.81868 6.39601 -7.81868C7.11333 -7.79477 7.16115 -7.5198 7.16115 -7.30461C7.16115 -7.19701 7.16115 -7.16115 7.11333 -6.99377L6.04932 -2.74969Z' id='g4-85'/>
<path d='M7.40025 -6.83836C7.80672 -7.48394 8.17733 -7.77086 8.78705 -7.81868C8.9066 -7.83064 9.00224 -7.83064 9.00224 -8.04583C9.00224 -8.09365 8.97833 -8.16538 8.87073 -8.16538C8.65554 -8.16538 8.14147 -8.14147 7.92628 -8.14147C7.57958 -8.14147 7.22092 -8.16538 6.88618 -8.16538C6.79054 -8.16538 6.67098 -8.16538 6.67098 -7.93823C6.67098 -7.83064 6.77858 -7.81868 6.8264 -7.81868C7.26874 -7.78281 7.31656 -7.56762 7.31656 -7.42416C7.31656 -7.24483 7.14919 -6.96986 7.13724 -6.95791L3.38331 -1.00423L2.54645 -7.44807C2.54645 -7.79477 3.16812 -7.81868 3.29963 -7.81868C3.47895 -7.81868 3.58655 -7.81868 3.58655 -8.04583C3.58655 -8.16538 3.45504 -8.16538 3.41918 -8.16538C3.21594 -8.16538 2.97684 -8.14147 2.7736 -8.14147H2.10411C1.23138 -8.14147 0.872727 -8.16538 0.860772 -8.16538C0.789041 -8.16538 0.645579 -8.16538 0.645579 -7.95019C0.645579 -7.81868 0.729265 -7.81868 0.920548 -7.81868C1.53026 -7.81868 1.56613 -7.71108 1.60199 -7.4122L2.55841 -0.0358655C2.59427 0.215193 2.59427 0.251059 2.76164 0.251059C2.90511 0.251059 2.96488 0.215193 3.08443 0.0239103L7.40025 -6.83836Z' id='g4-86'/>
<path d='M5.46351 -4.47123C5.46351 -5.22441 5.08095 -5.27223 4.98531 -5.27223C4.69838 -5.27223 4.43537 -4.98531 4.43537 -4.7462C4.43537 -4.60274 4.51905 -4.51905 4.56687 -4.47123C4.68643 -4.36364 4.99726 -4.04085 4.99726 -3.41918C4.99726 -2.91706 4.27995 -0.119552 2.84533 -0.119552C2.11606 -0.119552 1.9726 -0.729265 1.9726 -1.17161C1.9726 -1.76936 2.24757 -2.60623 2.57036 -3.467C2.76164 -3.95716 2.80946 -4.07671 2.80946 -4.31582C2.80946 -4.81793 2.45081 -5.27223 1.86501 -5.27223C0.765131 -5.27223 0.32279 -3.53873 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.561893 -3.33549 0.573848 -3.38331 0.621669 -3.55068C0.908593 -4.57883 1.37484 -5.03313 1.82914 -5.03313C1.93674 -5.03313 2.13998 -5.03313 2.13998 -4.63861C2.13998 -4.32777 2.00847 -3.98107 1.82914 -3.52677C1.25529 -1.99651 1.25529 -1.6259 1.25529 -1.33898C1.25529 -1.07597 1.29116 -0.585803 1.66177 -0.251059C2.09215 0.119552 2.68991 0.119552 2.79751 0.119552C4.78207 0.119552 5.46351 -3.78979 5.46351 -4.47123Z' id='g4-118'/>
<path d='M1.34695 -0.629639C1.27522 -0.326775 1.25928 -0.263014 0.669489 -0.263014C0.518057 -0.263014 0.422416 -0.263014 0.422416 -0.111582C0.422416 0 0.526027 0 0.661519 0H3.61843C4.9335 0 5.91382 -0.932503 5.91382 -1.7056C5.91382 -2.28742 5.41171 -2.75766 4.61469 -2.84533C5.53923 -3.02067 6.33624 -3.6264 6.33624 -4.32777C6.33624 -4.92553 5.75442 -5.44359 4.75019 -5.44359H1.96862C1.82516 -5.44359 1.72154 -5.44359 1.72154 -5.29215C1.72154 -5.18057 1.81719 -5.18057 1.95268 -5.18057C2.21569 -5.18057 2.44682 -5.18057 2.44682 -5.05305C2.44682 -5.02117 2.43885 -5.0132 2.41494 -4.90959L1.34695 -0.629639ZM2.59029 -2.94097L3.07646 -4.88568C3.14819 -5.15666 3.15616 -5.18057 3.48294 -5.18057H4.63064C5.41171 -5.18057 5.58705 -4.67049 5.58705 -4.34371C5.58705 -3.66625 4.86177 -2.94097 3.84159 -2.94097H2.59029ZM2.04035 -0.263014C1.96862 -0.278954 1.94471 -0.278954 1.94471 -0.334745C1.94471 -0.398506 1.96065 -0.462267 1.97659 -0.510087L2.5345 -2.71781H4.15243C4.89365 -2.71781 5.14072 -2.21569 5.14072 -1.76936C5.14072 -0.988294 4.37559 -0.263014 3.41918 -0.263014H2.04035Z' id='g3-66'/>
<path d='M5.34795 -5.39577C5.35592 -5.42765 5.37186 -5.47547 5.37186 -5.51532C5.37186 -5.57111 5.32403 -5.61096 5.26824 -5.61096S5.19651 -5.59502 5.10884 -5.49938C5.02117 -5.39577 4.81395 -5.14072 4.72628 -5.04508C4.41544 -5.49938 3.91333 -5.61096 3.50685 -5.61096C2.399 -5.61096 1.45056 -4.67846 1.45056 -3.76986C1.45056 -3.3076 1.69763 -3.03661 1.73748 -2.98082C2.0005 -2.70187 2.23163 -2.63811 2.80548 -2.50262C3.08443 -2.43088 3.10037 -2.43088 3.33151 -2.37509S4.07273 -2.19178 4.07273 -1.53026C4.07273 -0.836862 3.3873 -0.0956413 2.55044 -0.0956413C2.03238 -0.0956413 1.08394 -0.255044 1.08394 -1.24334C1.08394 -1.26725 1.08394 -1.43462 1.13176 -1.6259L1.13973 -1.7056C1.13973 -1.80125 1.05205 -1.80922 1.02017 -1.80922C0.916563 -1.80922 0.908593 -1.77733 0.868742 -1.59402L0.541968 -0.294894C0.510087 -0.175342 0.454296 0.0398506 0.454296 0.0637609C0.454296 0.127522 0.502117 0.167372 0.557908 0.167372S0.621669 0.159402 0.70934 0.0557908L1.09191 -0.390535C1.27522 -0.151432 1.72951 0.167372 2.5345 0.167372C3.69016 0.167372 4.63861 -0.876712 4.63861 -1.83313C4.63861 -2.19975 4.51905 -2.48667 4.30386 -2.70984C4.06476 -2.97285 3.80174 -3.03661 3.42715 -3.13225C3.19601 -3.18804 2.88518 -3.25978 2.70187 -3.3076C2.46276 -3.36339 2.01644 -3.52279 2.01644 -4.0807C2.01644 -4.70237 2.68593 -5.37186 3.49888 -5.37186C4.21619 -5.37186 4.71034 -4.99726 4.71034 -4.13649C4.71034 -3.94521 4.67846 -3.77783 4.67846 -3.74595C4.67846 -3.65031 4.75019 -3.63437 4.80598 -3.63437C4.90162 -3.63437 4.90959 -3.66625 4.94147 -3.79377L5.34795 -5.39577Z' id='g3-83'/>
<path d='M3.25978 -3.05255C2.933 -3.0127 2.82939 -2.76563 2.82939 -2.60623C2.82939 -2.37509 3.03661 -2.31133 3.14022 -2.31133C3.18007 -2.31133 3.58655 -2.34321 3.58655 -2.82939S3.06052 -3.51482 2.58232 -3.51482C1.45056 -3.51482 0.350685 -2.41494 0.350685 -1.29913C0.350685 -0.541968 0.868742 0.0797011 1.75342 0.0797011C3.0127 0.0797011 3.67422 -0.72528 3.67422 -0.828892C3.67422 -0.900623 3.59452 -0.956413 3.5467 -0.956413S3.47497 -0.932503 3.43512 -0.884682C2.80548 -0.143462 1.91283 -0.143462 1.76936 -0.143462C1.33898 -0.143462 0.996264 -0.406476 0.996264 -1.0122C0.996264 -1.36289 1.15567 -2.20772 1.53026 -2.70187C1.88095 -3.14819 2.27945 -3.29166 2.59029 -3.29166C2.68593 -3.29166 3.05255 -3.28369 3.25978 -3.05255Z' id='g3-99'/>
<path d='M3.21196 -2.99676C3.02864 -2.96488 2.86127 -2.82142 2.86127 -2.62217C2.86127 -2.4787 2.95691 -2.37509 3.13225 -2.37509C3.25181 -2.37509 3.49888 -2.46276 3.49888 -2.82142C3.49888 -3.31557 2.98082 -3.51482 2.48667 -3.51482C1.41868 -3.51482 1.08394 -2.75766 1.08394 -2.35118C1.08394 -2.27148 1.08394 -1.98456 1.37883 -1.76139C1.56214 -1.61793 1.69763 -1.59402 2.11208 -1.51432C2.39103 -1.45853 2.84533 -1.37883 2.84533 -0.964384C2.84533 -0.757161 2.6939 -0.494147 2.47073 -0.342715C2.17584 -0.151432 1.78531 -0.143462 1.65778 -0.143462C1.4665 -0.143462 0.924533 -0.175342 0.72528 -0.494147C1.13176 -0.510087 1.18755 -0.836862 1.18755 -0.932503C1.18755 -1.17161 0.972354 -1.2274 0.876712 -1.2274C0.749191 -1.2274 0.422416 -1.13176 0.422416 -0.6934C0.422416 -0.223163 0.916563 0.0797011 1.65778 0.0797011C3.04458 0.0797011 3.33948 -0.900623 3.33948 -1.23537C3.33948 -1.95268 2.55841 -2.10411 2.26351 -2.1599C1.88095 -2.23163 1.57011 -2.28742 1.57011 -2.62217C1.57011 -2.76563 1.7056 -3.29166 2.4787 -3.29166C2.78157 -3.29166 3.0924 -3.20399 3.21196 -2.99676Z' id='g3-115'/>
<path d='M2.98879 -0.868742C2.94894 -0.71731 2.57435 -0.143462 2.04035 -0.143462C1.64981 -0.143462 1.51432 -0.430386 1.51432 -0.789041C1.51432 -1.25928 1.79328 -1.97659 1.96862 -2.42291C2.04832 -2.62217 2.07223 -2.6939 2.07223 -2.83736C2.07223 -3.27572 1.72154 -3.51482 1.35492 -3.51482C0.565878 -3.51482 0.239103 -2.39103 0.239103 -2.29539C0.239103 -2.22366 0.294894 -2.19178 0.358655 -2.19178C0.462267 -2.19178 0.470237 -2.2396 0.494147 -2.3193C0.70137 -3.02864 1.05205 -3.29166 1.33101 -3.29166C1.45056 -3.29166 1.52229 -3.21196 1.52229 -3.02864S1.45056 -2.66202 1.34695 -2.38306C1.0122 -1.53823 0.940473 -1.19552 0.940473 -0.908593C0.940473 -0.127522 1.53026 0.0797011 2.0005 0.0797011C2.59826 0.0797011 2.96488 -0.398506 2.99676 -0.438356C3.12428 -0.0637609 3.48294 0.0797011 3.76986 0.0797011C4.14446 0.0797011 4.32777 -0.239103 4.38356 -0.358655C4.54296 -0.645579 4.65455 -1.10785 4.65455 -1.13973C4.65455 -1.18755 4.62267 -1.24334 4.52702 -1.24334S4.41544 -1.20349 4.36762 -0.996264C4.26401 -0.597758 4.12055 -0.143462 3.79377 -0.143462C3.61046 -0.143462 3.53873 -0.294894 3.53873 -0.518057C3.53873 -0.653549 3.61046 -0.924533 3.65828 -1.12379S3.82565 -1.80125 3.85753 -1.94471L4.01694 -2.55044C4.06476 -2.76563 4.1604 -3.14022 4.1604 -3.18804C4.1604 -3.3873 4.001 -3.43512 3.90535 -3.43512C3.79377 -3.43512 3.61843 -3.36339 3.56264 -3.1721L2.98879 -0.868742Z' id='g3-117'/>
<path d='M4.63064 -1.80922C4.75816 -1.80922 4.9335 -1.80922 4.9335 -1.99253S4.75816 -2.17584 4.63064 -2.17584H1.07597C1.17958 -3.28369 2.10411 -4.12852 3.31557 -4.12852H4.63064C4.75816 -4.12852 4.9335 -4.12852 4.9335 -4.31183S4.75816 -4.49514 4.63064 -4.49514H3.29166C1.85704 -4.49514 0.70137 -3.37933 0.70137 -1.99253C0.70137 -0.597758 1.86501 0.510087 3.29166 0.510087H4.63064C4.75816 0.510087 4.9335 0.510087 4.9335 0.326775S4.75816 0.143462 4.63064 0.143462H3.31557C2.10411 0.143462 1.17958 -0.70137 1.07597 -1.80922H4.63064Z' id='g1-50'/>
</defs>
<g id='page1' transform='matrix(1.13 0 0 1.13 -63.986 -61.0251)'>
<use x='56.4133' xlink:href='#g4-80' y='79.1532'/>
<use x='65.5562' xlink:href='#g4-76' y='79.1532'/>
<use x='73.4909' xlink:href='#g4-73' y='79.1532'/>
<use x='79.5744' xlink:href='#g4-86' y='79.1532'/>
<use x='88.9746' xlink:href='#g4-69' y='79.1532'/>
<rect height='0.3985' width='3.51182' x='99.0107' y='78.7547'/>
<use x='102.523' xlink:href='#g4-79' y='79.1532'/>
<use x='111.76' xlink:href='#g4-85' y='79.1532'/>
<use x='120.93' xlink:href='#g4-84' y='79.1532'/>
<use x='129.615' xlink:href='#g6-91' y='79.1532'/>
<use x='132.854' xlink:href='#g4-66' y='79.1532'/>
<use x='142.317' xlink:href='#g6-93' y='79.1532'/>
<use x='148.878' xlink:href='#g6-61' y='79.1532'/>
<use x='161.269' xlink:href='#g0-56' y='54.6449'/>
<use x='161.269' xlink:href='#g0-60' y='65.4047'/>
<use x='161.269' xlink:href='#g0-58' y='86.9242'/>
<use x='270.847' xlink:href='#g0-91' y='54.9938'/>
<use x='258.049' xlink:href='#g3-83' y='80.8968'/>
<use x='263.625' xlink:href='#g1-50' y='80.8968'/>
<use x='269.25' xlink:href='#g3-115' y='80.8968'/>
<use x='273.151' xlink:href='#g3-117' y='80.8968'/>
<use x='278.036' xlink:href='#g3-99' y='80.8968'/>
<use x='281.69' xlink:href='#g3-99' y='80.8968'/>
<use x='285.404' xlink:href='#g5-91' y='80.8968'/>
<use x='287.748' xlink:href='#g3-66' y='80.8968'/>
<use x='294.504' xlink:href='#g5-93' y='80.8968'/>
<use x='298.922' xlink:href='#g4-80' y='66.3512'/>
<use x='308.065' xlink:href='#g4-76' y='66.3512'/>
<use x='315.999' xlink:href='#g4-73' y='66.3512'/>
<use x='322.083' xlink:href='#g4-86' y='66.3512'/>
<use x='331.483' xlink:href='#g4-69' y='66.3512'/>
<rect height='0.3985' width='3.51182' x='341.519' y='65.9528'/>
<use x='345.031' xlink:href='#g4-73' y='66.3512'/>
<use x='351.114' xlink:href='#g4-78' y='66.3512'/>
<use x='361.891' xlink:href='#g6-91' y='66.3512'/>
<use x='365.131' xlink:href='#g4-83' y='66.3512'/>
<use x='372.999' xlink:href='#g6-93' y='66.3512'/>
<use x='376.239' xlink:href='#g4-59' y='66.3512'/>
<use x='475.657' xlink:href='#g4-83' y='66.3512'/>
<use x='487.427' xlink:href='#g6-105' y='66.3512'/>
<use x='490.667' xlink:href='#g6-115' y='66.3512'/>
<use x='499.169' xlink:href='#g6-110' y='66.3512'/>
<use x='505.648' xlink:href='#g6-111' y='66.3512'/>
<use x='511.479' xlink:href='#g6-116' y='66.3512'/>
<use x='519.916' xlink:href='#g6-97' y='66.3512'/>
<use x='525.748' xlink:href='#g6-110' y='66.3512'/>
<use x='536.129' xlink:href='#g6-101' y='66.3512'/>
<use x='541.312' xlink:href='#g6-120' y='66.3512'/>
<use x='547.467' xlink:href='#g6-105' y='66.3512'/>
<use x='550.706' xlink:href='#g6-116' y='66.3512'/>
<use x='559.144' xlink:href='#g6-98' y='66.3512'/>
<use x='565.623' xlink:href='#g6-108' y='66.3512'/>
<use x='568.862' xlink:href='#g6-111' y='66.3512'/>
<use x='575.019' xlink:href='#g6-99' y='66.3512'/>
<use x='579.877' xlink:href='#g6-107' y='66.3512'/>
<use x='171.896' xlink:href='#g2-102' y='94.1969'/>
<use x='177.874' xlink:href='#g4-118' y='94.1969'/>
<use x='187.261' xlink:href='#g2-50' y='94.1969'/>
<use x='198.523' xlink:href='#g4-76' y='94.1969'/>
<use x='206.457' xlink:href='#g4-79' y='94.1969'/>
<use x='215.695' xlink:href='#g4-67' y='94.1969'/>
<use x='224.898' xlink:href='#g4-65' y='94.1969'/>
<use x='233.64' xlink:href='#g4-76' y='94.1969'/>
<use x='241.575' xlink:href='#g4-86' y='94.1969'/>
<use x='250.975' xlink:href='#g4-65' y='94.1969'/>
<use x='259.718' xlink:href='#g4-82' y='94.1969'/>
<use x='268.693' xlink:href='#g4-83' y='94.1969'/>
<use x='280.739' xlink:href='#g2-106' y='94.1969'/>
<use x='287.949' xlink:href='#g4-118' y='94.1969'/>
<use x='297.918' xlink:href='#g6-109' y='94.1969'/>
<use x='307.637' xlink:href='#g6-105' y='94.1969'/>
<use x='310.876' xlink:href='#g6-103' y='94.1969'/>
<use x='316.707' xlink:href='#g6-104' y='94.1969'/>
<use x='322.861' xlink:href='#g6-116' y='94.1969'/>
<use x='331.299' xlink:href='#g6-97' y='94.1969'/>
<use x='337.13' xlink:href='#g6-108' y='94.1969'/>
<use x='340.369' xlink:href='#g6-105' y='94.1969'/>
<use x='343.609' xlink:href='#g6-97' y='94.1969'/>
<use x='349.44' xlink:href='#g6-115' y='94.1969'/>
<use x='357.942' xlink:href='#g6-97' y='94.1969'/>
<use x='367.675' xlink:href='#g6-110' y='94.1969'/>
<use x='374.154' xlink:href='#g6-111' y='94.1969'/>
<use x='379.985' xlink:href='#g6-110' y='94.1969'/>
<use x='386.464' xlink:href='#g6-108' y='94.1969'/>
<use x='389.704' xlink:href='#g6-111' y='94.1969'/>
<use x='395.86' xlink:href='#g6-99' y='94.1969'/>
<use x='401.043' xlink:href='#g6-97' y='94.1969'/>
<use x='406.874' xlink:href='#g6-108' y='94.1969'/>
<use x='414.016' xlink:href='#g6-118' y='94.1969'/>
<use x='419.521' xlink:href='#g6-97' y='94.1969'/>
<use x='425.352' xlink:href='#g6-114' y='94.1969'/>
<use x='429.887' xlink:href='#g6-105' y='94.1969'/>
<use x='433.127' xlink:href='#g6-97' y='94.1969'/>
<use x='438.958' xlink:href='#g6-98' y='94.1969'/>
<use x='445.437' xlink:href='#g6-108' y='94.1969'/>
<use x='448.676' xlink:href='#g6-101' y='94.1969'/>
<use x='454.388' xlink:href='#g2-103' y='94.1969'/>
<use x='462.443' xlink:href='#g4-59' y='94.1969'/>
<use x='506.919' xlink:href='#g6-111' y='94.1969'/>
<use x='512.75' xlink:href='#g6-116' y='94.1969'/>
<use x='517.285' xlink:href='#g6-104' y='94.1969'/>
<use x='523.764' xlink:href='#g6-101' y='94.1969'/>
<use x='528.947' xlink:href='#g6-114' y='94.1969'/>
<use x='533.483' xlink:href='#g6-119' y='94.1969'/>
<use x='541.905' xlink:href='#g6-105' y='94.1969'/>
<use x='545.145' xlink:href='#g6-115' y='94.1969'/>
<use x='549.745' xlink:href='#g6-101' y='94.1969'/>
</g>
</svg>

Changes to doc/middle-end.md.

502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
Once all opportunities for path splitting are addressed, there are
final transformations to prepare the quadcode for code issuing.

* `removeSplitMarkers` (`quadcode/nodesplit.tcl`): Removes the `split`
  quadcodes that were introduced by `insertSplitMarkers` and used in
  `nodesplit` to track how much it had ballooned the code size.
  
* `removeCallFrameNop` (`quadcode/callframe.tcl`) Removes
  `callFrameNop` instructions that are used to keep callframe moves
  attached to assignments to linked variables. After this point, code
  reoredering transformations are forbidden.
  
* `uselessphis`: This cleanup is needed because `removeCallFrameNop`
  instructions may have made `phi` operations on the callframe
  redundant.
  
* `eliminateCallFrame` (`quadcode/callframe.tcl`): If the
  optimizations have managed to eliminate all `moveToCallFrame` and
  `moveFromCallFrame` instructions, and no invoked procedure touches







<
<
<
<
<







502
503
504
505
506
507
508





509
510
511
512
513
514
515
Once all opportunities for path splitting are addressed, there are
final transformations to prepare the quadcode for code issuing.

* `removeSplitMarkers` (`quadcode/nodesplit.tcl`): Removes the `split`
  quadcodes that were introduced by `insertSplitMarkers` and used in
  `nodesplit` to track how much it had ballooned the code size.
  





* `uselessphis`: This cleanup is needed because `removeCallFrameNop`
  instructions may have made `phi` operations on the callframe
  redundant.
  
* `eliminateCallFrame` (`quadcode/callframe.tcl`): If the
  optimizations have managed to eliminate all `moveToCallFrame` and
  `moveFromCallFrame` instructions, and no invoked procedure touches

Changes to quadcode/aliases.tcl.

26
27
28
29
30
31
32











	set l2 $links
	dict unset l2 $v
	return [dict keys $l2]
    } else {
	return {}
    }
}


















>
>
>
>
>
>
>
>
>
>
>
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
	set l2 $links
	dict unset l2 $v
	return [dict keys $l2]
    } else {
	return {}
    }
}

# quadcode::transformer method local-aliases --
#
#	Enumerates local variables that may alias a non-local variable.
#
# Results:
#	Returns a list of the variable names.

oo::define quadcode::transformer method local-aliases {} {
    return [lmap x [dict keys $links] {lindex $x 1}]
}

Changes to quadcode/bb.tcl.

337
338
339
340
341
342
343
344

345
346

347



348
349
350

351
352

353
354





























355
356
357
358
359
360
361
    #
    # Parameters:
    #	to - Successor of the new block
    #
    # Results:
    #	Returns the new block's block number

    method makeEmptyBB {to} {

	# Create the block
	set newb [llength $bbcontent]

	lappend bbcontent [list [list jump [list bb $to]]]



	lappend bbpred {}

	# Link $to to the new block

	my bblink $newb $to


	return $newb
    }






























    # bbcopy --
    #
    #	Makes a copy of a basic block
    #
    # Parameters:
    #	b - Block number to copy







|
>
|

>
|
>
>
>



>
|
|
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
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
    #
    # Parameters:
    #	to - Successor of the new block
    #
    # Results:
    #	Returns the new block's block number

    method makeEmptyBB {{to -1}} {

	# Create the block, with a jump if needed.
	set newb [llength $bbcontent]
	if {$to >= 0} {
	    lappend bbcontent [list [list jump [list bb $to]]]
	} else {
	    lappend bbcontent {}
	}
	lappend bbpred {}

	# Link $to to the new block
	if {$to >= 0} {
	    my bblink $newb $to
	}

	return $newb
    }

    # replaceBB --
    #
    #	Replaces the content of a basic block
    #
    # Parameters:
    #	b - Block number to replace
    #	bb - New content
    #
    # Results:
    #	None.

    method replaceBB {b bb} {
	lset bbcontent $b $bb
    }

    # gettBB --
    #
    #	Retrieves the content of a basic block
    #
    # Parameters:
    #	b - Block number to retrieve
    #
    # Results:
    #	Returns the basic block content

    method getBB {b} {
	return [lindex $bbcontent $b]
    }

    # bbcopy --
    #
    #	Makes a copy of a basic block
    #
    # Parameters:
    #	b - Block number to copy
411
412
413
414
415
416
417














418
419
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
    # The block has two exists if the penultimate instruction has a basic
    # block in its result field (the instruction must be a conditional jump
    # of some sort).

    method bb2exit {b} {
	expr {[lindex $bbcontent $b end-1 1 0] eq "bb"}
    }















    # bbsucc --
    #	Query a basic block for its successors.
    #
    # Parameters:
    #	b - Basic block index

    #
    # Results:
    #	Returns a list (0, 1 or 2 elements) of the successors of the block.
    #   Blocks that return have no successors.

    method bbsucc {b} {

	if {[lindex $bbcontent $b end 0] eq "return"} {


	    return {}
	} else {
	    set l {}
	    set q [lindex $bbcontent $b end-1]
	    if {[lindex $q 1 0] eq "bb"} {
		lappend l [lindex $q 1 1]
	    }
	    set q [lindex $bbcontent $b end]
	    if {[lindex $q 1 0] eq "bb"} {
		lappend l [lindex $q 1 1]
	    }
	}
    }

    # bblink --







>
>
>
>
>
>
>
>
>
>
>
>
>
>






>





|
>
|
>
>



|



|







447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
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
    # The block has two exists if the penultimate instruction has a basic
    # block in its result field (the instruction must be a conditional jump
    # of some sort).

    method bb2exit {b} {
	expr {[lindex $bbcontent $b end-1 1 0] eq "bb"}
    }

    # bbpred --
    #	Query a basic block for its predecessors
    #
    # Parameters:
    #	b - Basic block oindex
    #
    # Results:
    #	Returns a dictionary whose keys are the basic block numbers of
    #	predecessors and whose values are immaterial

    method bbpred {b} {
	return [lindex $bbpred $b]
    }

    # bbsucc --
    #	Query a basic block for its successors.
    #
    # Parameters:
    #	b - Basic block index
    #	bb - Basic block content, if the content is known or modified.
    #
    # Results:
    #	Returns a list (0, 1 or 2 elements) of the successors of the block.
    #   Blocks that return have no successors.

    method bbsucc {b {bb {}}} {
	if {$bb eq {}} {
	    set bb [lindex $bbcontent $b]
	}
	if {[lindex $bb end 0] eq "return"} {
	    return {}
	} else {
	    set l {}
	    set q [lindex $bb end-1]
	    if {[lindex $q 1 0] eq "bb"} {
		lappend l [lindex $q 1 1]
	    }
	    set q [lindex $bb end]
	    if {[lindex $q 1 0] eq "bb"} {
		lappend l [lindex $q 1 1]
	    }
	}
    }

    # bblink --

Added quadcode/builder.tcl.









































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
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
271
272
273
274
275
276
277
278
279
280
281
282
283
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
# builder.tcl --
#
#	Class that allows for building new quadcode inside a
#	quadcode::transformer.
#
# Copyright (c) 2018 by Kevin B. Kenny
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# Some passes that modify quadcode do fairly extensive code rewriting, and
# it's convenient have procedures to track these and allow access at a level
# closer to an 'assembly language'. This class contains convenience methods
# to allow automatic tracking of variable uses and defs, named temporaries,
# and named basic blocks.
#
#------------------------------------------------------------------------------

# quadcode::builder --
#
#	Class with support methods for building quadcode.
#
oo::class create quadcode::builder {

    variable xfmr;		# quadcode::transformer object containing
    ;				# the quadcode of interest.

    variable b;			# Basic block number under construction

    variable bbindex;		# Dictionary whose keys are the names of
    ;				# basic blocks and whose values are the
    ;				# basic block numbers.

    variable varindex;		# Dictionary whose keys are named variables
    ;				# and whose values are the SSA names of the
    ;				# variables.
}

# quadcode::builder constructor --
#
#	Makes a quadcode::builder to allow for assembling quadcode.
#
# Parameters:
#	xfmr - quadcode::transformer object containing the subprogram
#	b - Basic block number under construction
#	bb - Basic block content of the block under construction

oo::define quadcode::builder constructor {xfmr_ b_ bb_} {
    set xfmr $xfmr_
    set b $b_
    set bb $bb_
    set bbindex {}
    set varindex {}
    $xfmr replaceBB $b $bb
}

# quadcode::builder method curblock --
#
#	Returns the number of the current basic block.
#
# Results:
#	Basic block number

oo::define quadcode::builder method curblock {} {
    return $b
}

# quadcode::builder method makeblock --
#
#	Makes a new basic block.
#
# Parameters:
#	name - Name to give to the block
#
# Results:
#	Returns the basic block number
#
# Side effects:
#	Creates the block. Stores the block index in 'bbindex' if name is
#	supplied

oo::define quadcode::builder method makeblock {{name {}}} {

    # Create the block
    set newb [$xfmr makeEmptyBB]

    # Index the block
    if {$name ne {}} {
        dict set bbindex $name $newb
    }

    return $newb
}

# quadcode::builder method getblock --
#
#	Finds a basic block created by 'makeblock'
#
# Parameters:
#	name - Name of the block
#
# Results:
#	Returns the basic block number, or -1 if there is no such block

oo::define quadcode::builder method getblock {name} {
    if {![dict exists $bbindex $name]} {
        return -1
    } else {
        return [dict get $bbindex $name]
    }
}

# quadcode::builder method buildin --
#
#	Switch to a different basic block for building
#
# Parameters:
#	newb - Basic block to start building in.
#
# Results:
#	None.

oo::define quadcode::builder method buildin {newb} {

    # Set to build in the new basic block
    set b $newb

    return

}

# 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
#
# Results:
#	None.
#
# Side effects:
#	Appends the instruction to the basic bnlock under construction.
#	If the instruction is a jump, adds the basic block predecessor
#	relationship. If the instruction is an assignment, updates the
#	ud-chain of the assigned variable. Updates the du-chains of all
#	variables used oin the instruction.

oo::define quadcode::builder method emit {q} {

    # Split the instruction
    lassign $q opcode res argl

    # Handle the result
    switch -exact -- [lindex $res 0] {
        "bb" {
	    # Instruction is a jump, link the basic block to the jump target
            $xfmr bblink $b [lindex $res 1]
        }
        "temp" - "var" {
	    # Instrtuction is an assignment, update the ud-chain.
            $xfmr addDef $res $b
        }
    }

    # Handle the arguments
    foreach arg [lrange $q 2 end] {
        switch -exact -- [lindex $arg 0] {
            "temp" - "var" {

		# Argument is an SSA value, update the du-chain.
		$xfmr addUse $arg $b
            }
        }
    }

    # Add the instruction to the block
    set bb [$xfmr getBB $b]
    $xfmr replaceBB $b {}
    lappend bb $q
    $xfmr replaceBB $b $bb

    return
}

# quadcode::builder method updatephi --
#
#	Adds a given basic block and value as the source of a phi
#	operation in another block.
#
# Parameters:
#	to - Basic block being jumped to
#	var - Variable output from the phi
#	val - Data source for that variable.
#
# Results:
#	None.
#
# Side effects:
#	Adds to the phi the given value, indicated as coming from
#	the builder's current block.

oo::define quadcode::builder method updatephi {to var val} {

    # Get the target basic block
    set targetbb [$xfmr getBB $to]
    $xfmr replaceBB $to {}

    # Find the phi
    set pc -1
    foreach q $targetbb {
        incr pc
        if {[lindex $q 0] ne "phi"} {
            break
        }
        if {[lindex $q 1] eq $var} {
            set targetpc $pc
            break
        }
    }

    # Bail out if we can't find it
    if {![info exists targetpc]} {
        error "Cannot find variable $var in a phi in block $to"
    }

    # Update the phi
    set q [lindex $targetbb $targetpc]
    lset targetbb $targetpc {}
    lappend q [list bb $b] $val
    lset targetbb $targetpc $q
    $xfmr addUse $val $to

    # Put the target basic block back
    $xfmr replaceBB $to $targetbb
}

if 0 { # Rethink, if anything uses this...
# quadcode::builder method bb --
#
#	Returns the content of the basic block under construction.
#
# Results:
#	Returns the instructions.

oo::define quadcode::builder method bb {} {
    return $bb
}
}

# quadcode::builder method log-last --
#
#	Logs the last instruction emitted to the standard output
#
# Results:
#	None.

oo::define quadcode::builder method log-last {} {
    set bb [$xfmr getBB $b]
    set pc [expr {[llength $bb] -1}]
    puts "    $b:$pc: [lindex $bb end]"
}

# Local Variables:
# mode: tcl
# fill-column: 78
# auto-fill-function: nil
# buffer-file-coding-system: utf-8-unix
# indent-tabs-mode: nil
# End:

Changes to quadcode/callframe.tcl.

1
2
3
4
5
6
7
8
9
10
11
















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































12
13
14
15
16
17
18
# callframe.tcl --
#
#	Quadcode optimisation pass devoted to tidying data motion
#	into and out of callframes.
#
# Copyright (c) 2017 by Kevin B. Kenny
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
#------------------------------------------------------------------------------

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































# quadcode::transformer method containsUpvar --
#
#	Quick and dirty approximation for whether a given procedure needs
#	to have variables in the caller's frame in sync.
#
# Results:











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
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
271
272
273
274
275
276
277
278
279
280
281
282
283
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
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
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
408
409
410
411
412
413
414
415
416
417
418
419
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
463
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
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
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
567
568
569
570
571
572
573
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
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
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
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
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
929
930
931
932
933
934
935
936
937
938
939
940
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
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
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
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
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
1107
1108
1109
1110
1111
1112
1113
1114
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
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
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
1206
1207
1208
1209
1210
1211
1212
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
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
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
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
# callframe.tcl --
#
#	Quadcode optimisation pass devoted to tidying data motion
#	into and out of callframes.
#
# Copyright (c) 2017 by Kevin B. Kenny
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
#------------------------------------------------------------------------------

# Class: quadcode::callFrameAnalysis
#
# Purpose:
#
#	Encapsulates code that analyzes data flows among variables in
#	the callframe, and removes redundant 'moveFromCallFrame' and
#	'moveToCallFrame' instructions.
#
# This class is instantiated at any time the callframe analysis pass runs.
# It is invoked solely from the 'callframeDataFlow' method inside the
# 'quadcode::transformer' class.

oo::class create quadcode::callFrameAnalysis {

    # xf is the quadcode::transformer object compiling the procedure at
    # hand

    variable xf

    # nbb is the number of basic blocks in the program.

    variable nbb

    # Since the quadcode is structured so that only one callframe is
    # in flight at any given time, the logic here can be structured
    # so that only a single mapping among variables is in
    # flight. For a consistency check, we store in 'activeCFOut' a
    # list indexed by basic block whose values are the active
    # callframe on exit from the block.  On entry to a block, we
    # expect that either all predecessors will agree on the active
    # callframe or else that there is already a phi in the block's
    # header that merges the active callframes of the individual
    # predecessor blocks. If this assumption is violated, we assume
    # for safety that there are no quadcode values corresponding to
    # callframe variables

    variable activeCFOut

    # The 'seq' variable is used to serialize the names of temporary objects.

    variable seq

    # The 'bbdirty' variable is an array of flags indicating whether each
    # basic block is 'dirty' in the current analysis pass and must be reanalyzed

    variable bbdirty

    # The 'specPhi' variable is a dictionary whose keys are the
    # quadcode variable names of speculative phi instructions, and
    # whose values are the right-hand sides of the phis

    variable specPhi

    # The 'availOut' variable is list of dictionaries. List indices are
    # basic block numbers. Dictionary keys are the names of callframe
    # variables, and the values are the quadcode values known to hold the
    # variables' values on exit from the basic block.

    variable availOut

    # The 'availEquiv' variable is a dictionary whose keys are quadcode values
    # that are known to be copies of a value in the callframe, and whose
    # values are the copied value.

    variable availEquiv

    # The 'pointlessStore' variable is a two-level dictionary whose keys
    # are result callframes of 'moveToCallFrame' instructions, second-level
    # keys are Tcl variable names, and values are immaterial. It enumerates
    # store operations that are returning to the callframe values that are
    # known already to be there.

    variable pointlessStore

    # The 'liveIn' variable is a list of dictionaries. List indices
    # are basic block numbers. Dictionary keys are callframe variables that
    # are live on entry to the block, and values are immaterial.

    variable liveIn

    # The 'eliminableLoad' variable is a dictionary whose keys are the results
    # of 'moveFromCallFrame' instructions and whose values are values that
    # may be copied instead of loading from the callframe.

    variable eliminableLoad

    # The 'deadStore' variable is a dictionary whose keys are callframe values
    # and whose values are immaterial. Entries are present in 'deadStore' if
    # the corresponding 'moveToCallFrame' operations are storing values that
    # will never be loaded.

    variable deadStore

    # quadcode::callFrameAnalysis constructor --
    #
    #	Prepares to perform data flow analysis on variables in the callframe
    #
    # Parameters:
    #	xf_ - The quadcode::transformer object that is compiling the procedure
    #	     at hand.
    #
    # Results;
    #	None.
    #
    # Side effects:
    #	Initializes available variable sets to empty, and the active callframe
    #	on exit from each block to an unknown state.
    #	Sets the serialization number to -1

    constructor {xf_} {

	set xf $xf_

	set nbb [llength [$xf bbcontent]]
	set availOut [lrepeat $nbb {}]
	set availEquiv [dict create Nothing Nothing]
	set pointlessStore {}
	set liveIn [lrepeat $nbb {}]
	set activeCFOut [lrepeat $nbb {}]
	set specPhi {}
	set eliminableLoad {}
	set deadStore {}

	set seq -1
    }
}

# quadcode::callFrameAnalysis method analyzeForward --
#
#	Performs the initial pass of forward data flow analysis on
#	the quadcode sequence.
#
# Results:
#	Returns 1 if there are opportunities to optimize, 0 otherwise.
#
# Side effects:
#	Populates the 'availOut', 'activeCFOut' and 'eliminableLoad' arrays.
#
#	In addition, may modify the quadcode to add speculative phi
#	instructions that combine the quadcode values for available
#	callframe variables, to enable more aggressive elimination of
#	downstream 'moveFromCallFrame' operations. At the conclusion
#	of this pass, it is known which speculative phis will actually
#	be beneficial. Others will be eliminated in the 'eliminate'
#	pass, which must run even if this pass returns 0.

oo::define quadcode::callFrameAnalysis method analyzeForward {} {

    set did_something 0

    # Set up 'bbq' to be a priority queue of blocks awaiting analysis,
    # ordered by block number (which orders in depth-first numbering)
    # and set up 'bbdirty' as an array of flags, indexed by block number,
    # that contains 1 if a block is queued and 0 otherwise. Initially
    # the queue contains every block in the program.

    quadcode::numheap create [namespace current]::bbq 
    set b -1
    set bbdirty {}
    foreach bb [$xf bbcontent] {
	incr b
	lappend bbdirty 1
	bbq add $b
    }

    # Process the queue elements. If processing any basic block changes
    # the data that appears at its output, force its successors to be
    # analyzed.

    while {![bbq empty]} {
	set b [bbq removeFirst]
	lset bbdirty $b 0
	$xf editBasicBlock bb $b {
	    set changed [my analyzeForwardBB $b bb]
	}
	if {$changed} {
	    foreach s [$xf bbsucc $b] {
		if {![lindex $bbdirty $s]} {
		    lset bbdirty $s 1
		    bbq add $s
		}
	    }
	}
    }

    bbq destroy

    $xf debug-callframe {
	puts "callframe: loads that may be eliminated:"
	dict for {res source} $eliminableLoad {
	    puts "    $res = $source"
	}
	puts "callframe: speculative phis that may need to be cleaned up:"
	dict for {res inputs} $specPhi {
	    puts "    $res"
	}
    }

    return [expr {[dict size $eliminableLoad] > 0}]
}

# quadcode::callFrameAnalysis method analyzeForwardBB --
#
#	Analyzes one basic block in the forward direction for callframe effects
#
# Parameters:
#	b     - Basic block number
#	bbVar - Name of a variable in caller's scope that contains the basic
#	        block's instructions and may be modified during the analysis.
#
# Results:
#	Returns 1 if anything has changed, 0 if everything is the same
#	as on a previous attempt.
#
# This method updates the b'th entry of'activeCFOut' to the active
# callframe on exit from the block, and the b'th entry of 'availOut'
# to be a dictionary mapping variable names in the callframe to the
# corresponding quadcode variables.

oo::define quadcode::callFrameAnalysis method analyzeForwardBB {b bbVar} {

    upvar 1 $bbVar bb
    namespace upvar ::quadcode::dataType CALLFRAME CALLFRAME

    $xf debug-callframe {
	puts "callframe: [$xf full-name] forward analysis for block $b"
    }

    # Find the active callframe and initialize available variables if possible.
    # This can be done if the active callframe is the same on exit from
    # each predecessor block and the available variables have the same values
    # in every predecessor. (This will trivially be the case if the block has
    # a single predecessor.)

    set preds [$xf bbpred $b]
    set acf [my activeCallFrameIn $b]
    if {$acf ne ""} {
	set avail [my availVarsIn $b $acf]
    } else {
	set avail {}
    }
    $xf debug-callframe {
	puts "Available in $acf on input to $b: $avail"
    }

    # Walk through the quadcode, updating the active callframe and the
    # available variables as needed.

    # newbb is the rewritten content of the current basic block.
    set newbb {}

    # phisSeen will be a dictionary whose keys are the data sources of phi
    # operations and whose values are the results of the phis.
    set phisSeen {}

    # If 'cfPhi' is set, it will be the phi instruction that supplies the
    # callframe on entry to this procedure.

    set didHeader 0
    set pc -1
    foreach q $bb {
	incr pc
	$xf debug-callframe {
	    puts "$b:$pc: $q"
	}
	set opcode [lindex $q 0 0]

	# Once we've seen all the phi's, insert any speculative phi's we need
	# in order to account for callframes that meet at convergence points

	if {$opcode ne "phi" && [dict size $preds] > 1 && !$didHeader} {
	    set didHeader 1

	    # This is a convergence point. If we don't have a phi for the
	    # callframe, it must have a single source. Make a fake phi so that
	    # 'makeSpeculativePhis' can copy it for the input vars:
	    #    phi $fromcf $pred1 $fromcf $pred2 $fromcf ...
	    if {![info exists cfPhi]} {
		set cfPhi [list "phi"]
		dict for {p -} $preds {
		    set cfin [lindex $activeCFOut $p]
		    if {$cfin ne {}} {
			lappend cfPhi $cfin
			break
		    }
		}
		dict for {p -} $preds {
		    lappend cfPhi [list bb $p] $cfin
		}
		$xf debug-callframe {
		    puts "FAKE PHI: $cfPhi"
		}
	    }		

	    # Insert speculative phis for the variables in the source
	    # callframes that meet here.
	    dict for {var phiRHS} [my makeSpeculativePhis $cfPhi $phisSeen] {
		if {[llength $phiRHS] == 1} {
		    set rh [lindex $phiRHS 0]
		    dict set avail $var $rh
		    dict set availEquiv $rh $rh
		    $xf debug-callframe {
			puts "        avail($var) - $rh"
			puts "        availEquiv($rh) - $var"
		    }
		} else {
		    set newvref [$xf newVarInstance [list "var" $var]]
		    $xf addDef $newvref $b
		    set newq [list phi $newvref]
		    foreach {frombb source} $phiRHS {
			$xf addUse $source $b
			lappend newq $frombb $source
		    }
		    $xf debug-callframe {
			puts "    insert: $newq"
		    }
		    lappend newbb $newq
		    dict set avail $var $newvref
		    dict set availEquiv $newvref $newvref
		    $xf debug-callframe {
			puts "        avail($var) - $newvref"
			puts "        availEquiv($newvref) - $newvref"
		    }
		    dict set phisSeen $phiRHS $newvref
		    dict set specPhi $newvref $phiRHS
		    set changed 1
		}
	    }
	    unset cfPhi
	}

	switch -exact $opcode {

	    "copy" -
	    "extractArray" -
	    "extractExists" -
	    "extractScalar" -
	    "narrowToType" {

		# If we are copying or narrowing from a value that's known
		# to be in the callframe, the result can be treated as
		# equivalent to that value, and a store of the result can
		# be eliminated

		lassign $q opcode vout vin
		if {[dict exists $availEquiv $vin]} {
		    dict set availEquiv $vout [dict get $availEquiv $vin]
		    $xf debug-callframe {
			puts "        - availEquiv($vout) -\
                                        [dict get $availEquiv $vout]"
		    }
		}
	    }

	    "directArrayExists" -
	    "directArrayGet" -
	    "directExists" -
	    "directGet" -
	    "directIsArray" {
		lassign $q opcode cfresult cfin name
		# There really is nothing to do, unless 'name' is constant
		# and unqualified, in which case it's a local var.
		# Also, 'directGet' doesn't really need to return the
		# callframe at all, as far as I can tell.

		if {$acf ne $cfin} {
		    $xf debug-callframe {
			puts "WHAT? callframe is $cfin, active is $acf"
		    }
		    $xf diagnostic warning $b $pc \
			"invoke in other than the active callframe,\
                    	     	        should not happen"
		    set avail {}
		}
	    }

	    "directAppend" -
	    "directArrayAppend" -
	    "directArrayLappend" -
	    "directArrayLappendList" -
	    "directArraySet" -
	    "directArrayUnset" -
	    "directLappend" -
	    "directLappendList" -
	    "directMakeArray" -
	    "directSet" -
	    "directUnset" {
		lassign $q opcode cfresult cfin name value
		if {$acf ne $cfin} {
		    $xf debug-callframe {
			puts "WHAT? callframe is $cfin, active is $acf"
		    }
		    $xf diagnostic warning $b $pc \
			"invoke in other than the active callframe,\
                    	     	        should not happen"
		    set avail {}
		}
		# If name is constant and qualified, spoil the aliases
		# of globals. If name is not constant, spoil  everything.
		$xf debug-callframe {
		    puts "q = $q"
		    puts "What does setting $name do?"
		}
		if {[lindex $name 0] eq "literal"
		    && [regexp :: [lindex $name 1]]} {
		    foreach v [$xf local-aliases] {
			$xf debug-callframe {
			    puts "    $v will be unavailable\
                                      because it might alias [lindex $name 1]"
			}
			dict unset avail $v
		    }
		} else {
		    $xf debug-callframe {
			puts "    direct set of an unknown variable makes\
                                  all values unavailable"
		    }
		    set avail {}
		}
		set acf $cfresult
	    }
	    
	    "entry" {
		set acf [lindex $q 1]
		set avail {}
		foreach v [lindex $q 2 1] {
		    $xf debug-callframe {
			puts "   $v will be available but unset"
		    }
		    dict set avail $v Nothing
		}
	    }

	    "extractCallFrame" {
		# All the variables available in the callframe+result will
		# become available in the extracted callframe
		set acf [lindex $q 1]
	    }

	    "invoke" -
	    "invokeExpanded" {

		set args [lassign $q op cfout cfin command]

		if {[$xf typeOfOperand $cfout] & $CALLFRAME} {

		    # Consistency check: Make sure that the active callframe
		    # is correctly linked.
		    if {$acf ne $cfin} {
			$xf debug-callframe {
			    puts "WHAT? callframe is $cfin, active is $acf"
			}
			$xf diagnostic warning $b $pc \
			    "invoke in other than the active callframe,\
                             should not happen"
			set avail {}
		    } else {
			
			# Determine what variables in the current frame might be
			# modified by this operation.
			set atypes [lmap x $args {$xf typeOfOperand $x}]
			lassign [$xf variablesProducedBy $q $atypes] known wlist
			if {!$known} {
			    
			    # The modified set is not known, spoil all vars
			    $xf debug-callframe {
				puts "    has an unknown effect, spoil all vars"
			    }
			    set avail {}
			} else {
			    $xf debug-callframe {
				puts "    spoils $wlist and all aliases"
			    }
			    # The modified set is known. Spoil everything that
			    # may alias a modified variable. 
			    foreach v $wlist {
				dict unset avail $v
				foreach a [$xf may-alias $v] {
				    $xf debug-callframe {
					puts "        including $a"
				    }
				    dict unset avail $a
				}
			    }
			    $xf debug-callframe {
				puts "    preserves avail set\
                                          [dict keys $avail]"
			    }
			}
		    }
		    set acf $cfout
		}
	    }
	    
	    "moveFromCallFrame" {

		# If the thing we're pulling out of the callframe has a constant
		# name and if the name has no namespace qualifiers, we can
		# retain its value to do load-load and load-store optimizations.
		# If we already have a value for it, we will eventually
		# elide this load operation.
		
		lassign $q op result cfin vref
		if {$acf ne $cfin} {
		    $xf debug-callframe {
			puts "WHAT? callframe is $cfin, active is $acf"
		    }
		    $xf diagnostic warning $b $pc \
			"moveFromCallFrame other than the active callframe,\
                         should not happen"
		    set avail {}
		} elseif {[lindex $vref 0] eq "literal"} {
		    set v [lindex $vref 1]
		    if {![regexp "::" $v]} {
		        if {![dict exists $avail $v]} {
			    $xf debug-callframe {
				puts "    $v becomes available with\
                                          value $result"
			    }
			    dict set availEquiv $result $result
			    $xf debug-callframe {
				puts "        avail($v) - $result"
				puts "        availEquiv($result) - $result"
			    }
			} else {
			    set source [dict get $avail $v]
			    $xf debug-callframe {
				puts "    Eventually, replace $result with a\
                                          copy from $source"
			    }
			    dict set eliminableLoad $result $source
			    dict set availEquiv $result \
				[dict get $availEquiv $source]
			    $xf debug-callframe {
				puts "        availEquiv($result) -\
			                      [dict get $availEquiv $result]"
			    }
			}
			dict set avail $v $result

		    }
		}
		set acf $cfin
	    }

	    "moveToCallFrame" {

		set pairs [lassign $q op cfout cfin]
		if {$acf ne $cfin} {
		    $xf debug-callframe {
			puts "WHAT? callframe is $cfin, active is $acf"
		    }
		    $xf diagnostic warning $b $pc \
			"moveToCallFrame other than the active callframe,\
                         should not happen"
		    set avail {}
		} else {

		    # Walk through the values being stored. If we're storing
		    # into a slot with a literal, unqualified name, then
		    # spoil known values for all potential aliases, and
		    # make the new value of the named variable available.
		    # If the name is qualified, spoil anything that might
		    # alias a namespace variable. If the name is unknown,
		    # spoil everything, since any callframe var may have
		    # been overwritten.
		    foreach {vref val} $pairs {
			lassign $vref kind v
			if {$kind eq "literal"} {
			    # TODO: Make sure that may-alias works if $v
			    #       is qualified. It should return all
			    #       unqualified names that may alias a
			    #	    namespace var
			    foreach a [$xf may-alias $v] {
				$xf debug-callframe {
				    puts "    $a becomes unavailable because\
				    	      it aliases $v"
				}
				dict unset avail $a
			    }
			    if {![regexp "::" $v]} {

				# LOAD-STORE - if we're putting into the
				# callframe a value that's already there,
				# there's no point.

				$xf debug-callframe {
				    puts "        Is there a point to this?"
				}
				if {[dict exists $availEquiv $val]
				    && [dict exists $avail $v]
				    && ([dict get $availEquiv $val]
					eq [dict get $availEquiv \
						[dict get $avail $v]])} {
				    $xf debug-callframe {
					puts "    setting $v to $val appears\
                                                  pointless"
				    }
				    dict set pointlessStore $cfout $v {}

				} else {				    
				
				    $xf debug-callframe {
					puts "    $v becomes available with\
                                                  value $val"
				    }
				    dict set avail $v $val
				    dict set availEquiv $val $val
				    $xf debug-callframe {
					puts "        avail($v) = $val"
					puts "        availEquiv($val) = $val"
				    }
				}
			    }
			} else {
			    $xf debug-callframe {
				puts "    unknown var, spoil everything"
			    }
			    set avail {}
			}
		    } 
		}
		set acf $cfout
	    }

	    "nsupvar" - "upvar" {
		lassign $q op cfout cfin localname context remotename
		set localname [lindex $localname 1]
		dict unset avail $localname
		$xf debug-callframe {
		    puts "$localname becomes unavailable"
		}
		foreach a [$xf may-alias $localname] {
		    $xf debug-callframe {
			puts "    $a becomes unavailable because\
			     	  it aliases $localname"
		    }
		    dict unset avail $a
		}
		set acf $cfout
	    }

	    "phi" {

		# If the phi is for the callframe, we will construct
		# the available set from the sets for the preceding
		# blocks. Defer this, however, until we've seen all the
		# phi's, because we may be constructing speculative phi's
		# for callframe variables, and we don't want to do that
		# until we've seen all the phi's that we have already.

		set fromlist [lassign $q opcode result]
		if {[$xf typeOfOperand [lindex $q 1]] & $CALLFRAME} {
		    set cfPhi $q
		    set avail {}
		    set acf $result
		} else {
		    dict set phisSeen \
			[lsort -dictionary -stride 2 -index 0 $fromlist] \
			$result
		}
	    }

	    "startCatch" {

		# Entering a catch implicitly spoils errorInfo and errorCode.
		# While it's pretty insane to alias these, someone probably
		# does, so spoil the local aliases.

		foreach v [$xf local-aliases] {
		    $xf debug-callframe {
			puts "    $v becomes unavailable"
		    }
		    dict unset avail $v
		}
		set acf [lindex $q 1]
	    }

	    "variable" {
		lassign $q op cfout cfin localname remotename
		set localname [lindex $localname 1]
		dict unset avail $localname
		$xf debug-callframe {
		    puts "    $localname becomes unavailable"
		}
		foreach a [$xf may-alias $localname] {
		    $xf debug-callframe {
			puts "    $a becomes unavailable because\
			     	  it aliases $localname"
		    }
		    dict unset avail $a
		}
		set acf $cfout
	    }

	    default {
		lassign $q opcode dest
		if {$dest ne {} && [lindex $dest 0] in {"var" "temp"}} {
		    set dtype [$xf typeOfOperand $dest]
		    if {$dtype & $CALLFRAME} {
			$xf diagnostic note $b $pc "Problem op: %s" $q
			$xf diagnostic warning $b $pc \
			    "I don't know the effect of %s on the callframe!" \
			    $opcode
			set acf [lindex $q 1]
			set avail {}
		    }
		}
	    }
	}

	lappend newbb $q
    }

    set changed 0
    if {$acf ne [lindex $activeCFOut $b]} {
	set changed 1
	lset activeCFOut $b $acf
    }
    if {$avail ne [lindex $availOut $b]} {
	set changed 1
	lset availOut $b $avail
    }
    set bb $newbb
    
    if {$changed} {
	$xf debug-callframe {
	    puts "    basic block $b has a different available set; we will"
	    puts "    reschedule analysis of successors."
	}
    }

    return $changed

}

# quadcode::callFrameAnalysis method makeSpeculativePhis --
#
#	Determines the set of phi instructions to add speculatively in hopes
#	of eliminating 'moveFromCallFrame' to retrieve their values after
#	the phi.
#
# Parameters:
#	cfPhi - The phi instruction at which two or more callframes meet
#	phisSeen - A dictionary describing the other phi's in the basic block.
#	           Keys are canonicalized right-hand sides. Values are the
#	           left-hand sides. This dictionary is used to identify
#	           values that are already available.
#
# Return value:
#	Returns a dictionary whose keys are the names of variables in the
#	callframe and whose values are lists. If a value is a singleton list,
#	it is the known value of the given variable. If a value is a list of
#	two or more elements, it is the right-hand side of a phi instruction
#	that should be inserted to make the given callframe variable available.
#
# This procedure works by examining each predecessor block in turn, looking
# at the available variables. For each variable seen, there are three cases.
#
# 1. The variable is unavailable in at least one predecessor. Do nothing.
# 2. The variable is available in all predecessors, and has the same value
#    in all of them. Make that value available as the variable's value
#    in the downstream context by adding it as a singleton to the output
#    dictionary.
# 3. The variable is available in all predecessors, and has two or more
#    different values. Construct the right-hand side of a phi instruction
#    at which the predecessor values meet, and add that to the output
#    dictionary.

oo::define quadcode::callFrameAnalysis method makeSpeculativePhis {cfPhi
								   phisSeen} {

    set retval {}
    set rest [lassign $cfPhi opcode result pred1 fromcf1]
    set pred1 [lindex $pred1 1]

    # Consistency check: make sure we have the correct linkage of the
    # active callframe.

    if {[lindex $activeCFOut $pred1] ne $fromcf1} {
	return {}
    }
    foreach {pred2 fromcf2} $rest {
	set pred2 [lindex $pred2 1]
	if {[lindex $activeCFOut $pred2] ne $fromcf2} {
	    return {}
	}
    }

    # Accumulate the possible speculative phis.

    dict for {var val} [lindex $availOut $pred1] {
	set avail {}
	dict set avail [list bb $pred1] $val
	set allsame 1
	foreach {pred2 fromcf2} $rest {
	    set pred2 [lindex $pred2 1]
	    if {![dict exists [lindex $availOut $pred2] $var]} {
		unset -nocomplain avail
		break
	    } else {
		set val2 [dict get [lindex $availOut $pred2] $var]
		if {$val2 ne $val} {
		    set allsame 0
		}
		dict set avail [list bb $pred2] $val2
	    }
	}
	if {[info exists avail]} {
	    if {$allsame} {
		dict set retval $var [list $val]
	    } else {
		set avail [lsort -dictionary -stride 2 -index 0 $avail]
		if {[dict exists $phisSeen $avail]} {
		    set oldphi [dict get $phisSeen $avail]
		    dict set retval $var [list $oldphi]
		} else {
		    dict set retval $var $avail
		}
	    }
	}
    }

    return $retval
    
}

# quadcode::callFrameAnalysis method analyzeBackward --
#
#	Analyzes the callframe operations in quadcode in the retrograde
#	direction.
#
# Results:
#	Returns 1 if there are one or more opportunities to optimize, 0
#	otherwise.
#
# Side effects:
#	Populates the 'liveIn' and 'deadStore' arrays.

oo::define quadcode::callFrameAnalysis method analyzeBackward {} {

    # Find out what local variables we're managing
    set q0 [lindex [$xf bbcontent] 0 0]
    lassign $q0 op callframe varnames
    if {[lindex $q0 0 0] ne "entry"} {
	error "program does not begin with 'entry'"
    }
    set allvars [lindex $varnames 1]

    # Find out which among these variables are aliased
    set aliases [$xf local-aliases]

    # Enumerate blocks in retrograde order, and invert the enumeration to
    # give the precedence of each block.
    # bbq is a priority queue of blocks awaiting analysis, in retrograde order.
    # The queue entries are precedences, which can be then converted to block
    # numbers by [lindex $order $precedence].

    quadcode::numheap create [namespace current]::bbq
    set order [$xf bbrorder]
    set bbdirty {}
    set prec [lrepeat [llength $order] -1]
    set i -1
    foreach b $order {
	lappend bbdirty 1
	set prc [incr i]
	lset prec $b $prc
	bbq add $prc
    }

    # Analyze by processing elements from tail to head.

    while {![bbq empty]} {
	set prc [bbq removeFirst]
	set b [lindex $order $prc]
	lset bbdirty $b 0
	$xf editBasicBlock bb $b {
	    set changed [my analyzeBackwardBB $b bb $allvars $aliases]
	}
	if {$changed} {
	    dict for {pred -} [$xf bbpred $b] {
		$xf debug-callframe {
		    puts "    ...schedule predecessor $pred"
		}
		if {![lindex $bbdirty $pred]} {
		    lset bbdirty $pred 1
		    set prc [lindex $prec $pred]
		    bbq add $prc
		}
	    }
	}
    }

    bbq destroy

    dict for {k v} $deadStore {
	if {[dict size $v] == 0} {
	    dict unset deadStore $k
	}
    }

    $xf debug-callframe {
	puts "callframe: stores that may be eliminated:"
	dict for {k v} $deadStore {
	    puts "    $k: [dict keys $v]"
	}
    }

    return [expr {[dict size $deadStore] > 0}]
}

# quadcode::callFrameAnalysis method analyzeBackwardBB --
#
#	Analyzes a basic block in the retrograde direction.
#
# Parameters:
#	b - Basic block number
#	bbVar - Name of a variable in caller's scope that contains the
#	        basic block's instructions and may be modified during the
#	        analysis.
#	vars - Complete set of callframe variables that are being tracked
#	aliases - Set of callframe variables that may be aliases.
#
# Results:
#	Returns 1 if anything has changed requiring predecessor blocks
#	to be reexamined, or 0 if nothing has changed.
#
# This method updates the b'th entry of 'liveIn' to be a dictionary whose
# keys are the names of variables that are live on entry to a block, and
# adjusts 'deadLoad' for any loads in the block.

oo::define quadcode::callFrameAnalysis method analyzeBackwardBB {b bbVar vars
								 aliases} {
    upvar 1 $bbVar bb
    namespace upvar ::quadcode::dataType CALLFRAME CALLFRAME

    $xf debug-callframe {
	puts "callframe: [$xf full-name] backward analysis for block $b"
    }

    # For each successor block, find the live variables on input. The
    # live variables on output from this block will be the union of
    # those live on input to the successors.

    set live {}
    foreach s [$xf bbsucc $b $bb] {
	set live [dict merge $live [lindex $liveIn $s]]
    }
    $xf debug-callframe {
	puts "    live set on exit: [dict keys $live]"
    }

    # The analyzeForward pass has already checked the consistency
    # of callframe linkage.

    # Pass through the instructions of this block from bottom to top, and
    # update liveness. Mark any dead stores that are encountered.

    set pc [llength $bb]
    while {$pc > 0} {
	incr pc -1
	set q [lindex $bb $pc]

	$xf debug-callframe {
	    puts "$b:$pc: $q"
	}

	switch -exact -- [lindex $q 0 0] {

	    "return" {

		# On return from a procedure, the variables that are
		# to be considered live are the ones that might alias
		# variables out of scope.

		set live {}
		foreach a $aliases {
		    $xf debug-callframe {
			puts "    live on exit: $a"
		    }
		    dict set live $a {}
		}

	    }
	    
	    "moveToCallFrame" {

		# On entry to 'moveToCallFrame', any variable that will
		# be overwritten is not live.
		set rest [lassign $q opcode cfout cfin]
		foreach {var value} $rest {
		    if {[lindex $var 0] eq "literal"} {
			set vname [lindex $var 1]
			if {![dict exists $live $vname]} {
			    $xf debug-callframe {
				puts "    $vname appears to be a dead store"
			    }
			    dict set deadStore $cfout $vname {}
			} else {
			    $xf debug-callframe {
				puts "    $vname appears to be a live store"
			    }
			    if {[dict exists $deadStore $cfout]} {
				dict unset deadStore $cfout $vname
			    }
			    $xf debug-callframe {
				puts "    $vname not live above here"
			    }
			    dict unset live $vname
			}
		    }
		}
	    }
		
	    "directAppend" -
	    "directArrayAppend" -
	    "directArrayExists" -
	    "directArrayGet" -
	    "directArrayLappend" -
	    "directArrayLappendList" -
	    "directArraySet" -
	    "directArrayUnset" -
	    "directExists" -
	    "directGet" -
	    "directIsArray" -
	    "directLappend" -
	    "directLappendList" -
	    "directMakeArray" -
	    "directSet" -
	    "directUnset" -
	    "moveFromCallFrame" {

		# On entry to an instruction that inspects the callframe,
		# a variable that may be read must be live. All aliases must
		# also be live.

		lassign $q opcode result cfin name

		if {[dict exists $eliminableLoad $result]} {
		    $xf debug-callframe {
			puts "    this instruction is being deleted"
		    }
		} elseif {[lindex $name 0] ne "literal"} {
		    $xf debug-callframe {
			puts "    cannot determine variable being read, make\
                                  everything live"
		    }
		    foreach v $vars {
			$xf debug-callframe {
			    puts "    $v becomes live"
			}
			dict set live $v {}
		    }
		} else {
		    set name [lindex $name 1]
		    if {[regexp :: $name]} {
			$xf debug-callframe {
			    puts "    variable is nonlocal, make aliases live"
			}
			foreach v $aliases {
			    $xf debug-callframe {
				puts "    $v becomes live"
			    }
			    dict set live $v {}
			}
		    } else {
			$xf debug-callframe {
			    puts "    make $name live"
			}
			dict set live $name {}
			foreach v [$xf may-alias $name] {
			    $xf debug-callframe {
				puts "    make potential alias $v live"
			    }
			    dict set live $v {}
			}
		    }
		}
	    }
		
	    "invoke" -
	    "invokeExpanded" {
		
		set args [lassign $q opcode cfout cfin cmd]
		set argtypes [lmap a $args {$xf typeOfOperand $a}]
		lassign [$xf variablesUsedBy $q $argtypes] known vlist
		if {!$known} {
		    $xf debug-callframe {
			puts "    variables used are not known,\
                                  make everything live"
		    }
		    foreach v $vars {
			$xf debug-callframe {
			    puts "    mark $v live"
			}
			dict set live $v {}
		    }
		} else {
		    foreach v $vlist {
			$xf debug-callframe {
			    puts "    variable $v used by call, mark live"
			}
			dict set live $v {}
			foreach a [$xf may-alias $v] {
			    $xf debug-callframe {
				puts "    $a is a potential alias, mark live"
			    }
			    dict set live $a {}
			}
		    }
		}
	    }

	    "entry" -
	    "extractCallFrame" -
	    "nsupvar" -
	    "phi" -
	    "retrieveResult" -
	    "startCatch" -
	    "upvar" -
	    "variable" {
		# It's not relevant what might be live on entry.
		# THe rest of these instructions don't change the live set
	    }

	    default {

		lassign $q opcode dest src1
		if {$src1 ne {} && [lindex $src1 0] in {"var" "temp"}} {
		    set stype [$xf typeOfOperand $src1]
		    if {$stype & $CALLFRAME} {
			$xf diagnostic note $b $pc "Problem op: %s" $q
			$xf diagnostic warning $b $pc \
			    "I don't know the effect of %s on liveness" $opcode
			foreach v $vars {
			    dict set live $v {}
			}
		    }
		}
	    }
	}
    }

    $xf debug-callframe {
	puts "    live set on entry: [dict keys $live]"
    }

    set changed 0
    if {$live ne [lindex $liveIn $b]} {
	lset liveIn $b $live
	set changed 1
    }

    if {$changed} {
	$xf debug-callframe {
	    puts "    live set changed, reschedule analysis of predecessors"
	}
    }

    return $changed
}

# quadcode::callFrameAnalysis method eliminate --
#
#	Eliminates redundant 'moveFromCallFrame' and 'moveToCallFrame'
#	instructions by replacing them with copies. Eliminates any speculative
#	phi instructions that were inserted unnecessarily.
#
# Results:
#	None.
#
# Side effects:
#	Deletes phi instructions from the quadcode and replaces
#	unneeded loads with copies.

oo::define quadcode::callFrameAnalysis method eliminate {} {

    set nbb [llength [$xf bbcontent]]
    for {set b 0} {$b < $nbb} {incr b} {
	$xf editBasicBlock bb $b {

	    set newbb {}

	    set pc -1
	    foreach q $bb {
		incr pc

		switch -exact -- [lindex $q 0 0] {

		    "moveFromCallFrame" {
			lassign $q opcode dest cfin
			if {[dict exists $eliminableLoad $dest]} {
			    set source [dict get $eliminableLoad $dest]
			    my markSpecPhi $source
			    $xf removeUse $cfin $b
			    $xf addUse $source $b
			    set newq [list "copy" $dest $source]
			    $xf debug-callframe {
				puts "$b:$pc: replace $q"
				puts "       with $newq"
			    }
			    lappend newbb $newq
			} else {
			    $xf debug-callframe {
				puts "$b:$pc: cannot eliminate $q"
			    }
			    lappend newbb $q
			}
		    }

		    "moveToCallFrame" {
			set rhs [lassign $q opcode cfout cfin]
			set newrhs {}
			foreach {v source} $rhs {
			    
			    lassign $v kind name
			    set elim 0
			    if {$kind ne "literal"} {
				$xf debug-callframe {
				    puts "$b:$pc: cannot eliminate store,\
                                                  target unknown"
				}
			    } elseif {[dict exists $pointlessStore \
					   $cfout $name]} {
				$xf debug-callframe {
				    puts "$b:$pc: can eliminate, pointless"
				}
				set elim 1
			    } elseif {[dict exists $deadStore $cfout $name]} {
				$xf debug-callframe {
				    puts "$b:$pc: can eliminate, $name is dead"
				}
				set elim 1
			    }

			    if {$elim} {
				$xf debug-callframe {
				    puts "$b:$pc: eliminate store to $name"
				    puts "$b:$pc: remove a use of $source"
				}
				$xf removeUse $source $b
			    } else {
				lappend newrhs $v $source
			    }
			}
			if {$newrhs eq {}} {
			    set newq [list copy $cfout $cfin]
			} else {
			    set newq [list $opcode $cfout $cfin {*}$newrhs]
			}
			$xf debug-callframe {
			    puts "$b:$pc replace $q"
			    puts "        with $newq"
			}
			lappend newbb $newq
		    }

		    default {
			lappend newbb $q
		    }

		}
	    }
	    set bb $newbb
	}
    }

    for {set b 0} {$b < $nbb} {incr b} {
	$xf editBasicBlock bb $b {

	    set newbb {}

	    set pc -1
	    foreach q $bb {
		incr pc

		switch -exact -- [lindex $q 0 0] {

		    "phi" {
			set pairs [lassign $q opcode dest]
			if {[dict exists $specPhi $dest]} {
			    $xf debug-callframe {
				puts "$b:$pc: remove speculative phi $dest"
			    }
			    $xf removeDef $dest
			    foreach {from source} $pairs {
				$xf removeUse $source $b
			    }
			} else {
			    lappend newbb $q
			}
		    }

		    default {
			lappend newbb $q
		    }
		}
	    }
	    set bb $newbb
	}
    }
}

# quadcode::callFrameAnalysis method markSpecPhi --
#
#	When eliminating a load from the callframe, remove any phi
#	instructions on which it depends from the 'specPhi' array so that
#	they will be retained in the quadcode.
#
# Parameters:
#	v - Output that might come from a speculative phi.
#
# Results:
#	None.
#
# Side effects:
#	The speculative phi, and any that it depends on, are removed.

oo::define quadcode::callFrameAnalysis method markSpecPhi {v} {

    $xf debug-callframe {
	puts "Check dependencies for $v"
    }
    if {[dict exists $specPhi $v]} {
	$xf debug-callframe {
	    puts "Speculative phi $v is still required"
	}
	set deps [dict get $specPhi $v]
	dict unset specPhi $v
	dict for {frombb d} $deps {
	    my markSpecPhi $d
	}
    }
    return
}

# quadcode::callFrameAnalysis method activeCallFrameIn --
#
#	If a basic block has an active callframe on entry (that is, if the
#	active callframe is the same on exit from all predecessors), locate it.
#
# Parameters:
#	b - Basic block number
#
# Results:
#	Returns the identity of the active callframe, or "" if it cannot be
#	uniquely determined.

oo::define quadcode::callFrameAnalysis method activeCallFrameIn {b} {

    set acf "";			# Return value

    set preds [$xf bbpred $b]
    if {[dict size $preds] != 0} {
	set firstTime 1
	dict for {p -} $preds {
	    set pcf [lindex $activeCFOut $p]
	    if {$firstTime} {
		set acf $pcf
		set firstTime 0
	    } elseif {$pcf ne {}} {
		if {$acf ne {} && $acf ne $pcf} {
		    set acf {}
		    break
		}
	    }
	}
    }
    
    return $acf
}

# quadcode::callFrameAnalysis method availVarsIn ---
#
#	If a block's predecessors share a callframe, enumerate any variables
#	that are available on all paths.
#
# Parameters:
#	b - Basic block number
#	acf - Active callframe on entry to block $b
#
# Results:
#	Returns a dictionary whose keys are variable names and whose
#	values are the values of variables in the callframe that are
#	available in the same quadcode register on each path coming in.
#
# It is a precondition that each predecessor block have the same active
# callframe.
#
# If more than one predecessor has the variable available but
# the values are different, then there's a need for a speculative phi here.

oo::define quadcode::callFrameAnalysis method availVarsIn {b acf} {

    set avars {}
    
    set preds [$xf bbpred $b]
    set firstTime 1
    dict for {p -} $preds {

	if {$firstTime} {
	    set avars [lindex $availOut $p]
	    set firstTime 0
	} else {
	    set av2 [lindex $availOut $p]
	    dict for {v value} $avars {
		if {![dict exists $av2 $v]
		    || [dict get $av2 $v] ne [dict get $avars $v]} {
		    dict unset avars $v
		}
	    }
	}
    }

    return $avars
}

# quadcode::transformer method callFrameFlow --
#
#	Performs data flow analysis and optimization on operations
#	that affect the callframe.
#
# Parameters:
#	None
#
# Results:
#	Returns 1 if anything has changed, 0 otherwise
#
# Side effects:
#	Rewrites code so as to eliminate redundancies among operations
#	affecting the callframe.

oo::define quadcode::transformer method callFrameFlow {} {

    my debug-callframe {
	puts "Before callframe flow analysis for [my full-name]:"
	foreach {v type} [lsort -dictionary -stride 2 -index 0 $types] {
	    puts "$v: [nameOfType $type]"
	}
	my dump-bb
    }

    set did_something 0

    set a [quadcode::callFrameAnalysis new [self]]

    # TODO - See doc/20190216callframe/callframe.md, tasks 2, 3, 4

    # 1. Compute available values in the forward direction.
    #    (There will be other forward analysis to be done).
    
    if {[$a analyzeForward]} {
	set did_something 1
    }

    # 2. Compute live stores in the backward direction.
    #    (There will be other retrograde analysis to be done.)

    if {[$a analyzeBackward]} {
	set did_something 1
    }

    # 4. Clean up any speculative phi operations that were unneeded,
    #    replace any unneeded callframe loads and stores with copies.
    $a eliminate

    # Note that the return should be 'true' if there has been code motion,
    # if any inserted speculative phi has a use, or if any load has been
    # eliminated. (And probably other reasons as I get farther into this).
    # Inserting and removing a speculative phi doesn't count. 

    my debug-callframe {
	puts "After callframe flow analysis:"
	my dump-bb
    }

    $a destroy

    if {$did_something} {
	my debug-callframe {
	    puts "The callframe analysis did something: reschedule code tidying"
	}
    }

    return $did_something

}

# quadcode::transformer method containsUpvar --
#
#	Quick and dirty approximation for whether a given procedure needs
#	to have variables in the caller's frame in sync.
#
# Results:
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
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
271
272
273
274
275
276
277
278
279
280
281
282
283
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
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
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
408
409
410
411
412
413
414
415
416
417
418
419
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
463
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
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
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
567
568
569
570
571
572
573
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
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
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
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
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
    foreach bb $bbcontent {
	if {[lsearch -exact -index 0 $bb upvar] >= 0} {
	    return 1
	}
    }
    return 0
}

# quadcode::transformer method callframeMotion --
#
#	Adds callframe data motion for variables that may be links
#	by virtue of appearing in 'nsupvar', 'upvar' or 'variable'
#	opcodes, or that may be read or written by 'invoke'
#
# Results:
#	None.
#
# Side effects:
#	Adds the necessary instructions to keep the callframe in step
#	with linked variables and with variables that may be used or
#	set in invoked commands.
#
# This pass runs before SSA, so that it doesn't need to worry about
# variable renaming. It inserts a great many redundant data motions.
# 'cleanupCallFrameMotion' will take out some of them (at least any
# 'moveFromCallFrame' whose result is unused), but proper optmization
# will depend on global alias analysis, which we don't yet have.

oo::define quadcode::transformer method callFrameMotion {} {

    my debug-callframe {
	puts "Before callframeMotion:"
	my dump-bb
	puts "Links: $links"
    }

    set catches {};		# Dictionary enumerating the places where
    ;				# errorInfo and errorCode must be spoilt

    # Walk through the basic blocks and insert any needed instructions
    # before and after the blocks

    set b -1
    foreach bb $bbcontent {
	incr b
	set newbb {}
	set pc -1
	foreach q $bb {
	    incr pc
	    my callFrameMovesBefore $b $pc newbb $q
	    lappend newbb $q
	    my callFrameMovesAfter $b $pc newbb $q
	    if {[lindex $q 0] eq "jumpMaybe"} {
		dict set catches [lindex $q 1 1] {}
		my debug-callframe {
		    puts "   [lindex $q 1] appears to be a catch block"
		}
	    }
	}
	lset bbcontent $b $newbb
    }

    # Insert instructions to spoil ::errorCode and ::errorInfo after each
    # catch.

    my debug-callframe {
	puts "Clean up catch blocks:"
    }
    dict for {b -} $catches {
	set newbb [list {startCatch {temp @callframe} {temp @callframe}}]
	my debug-callframe {
	    puts "$b:0: [lindex $newbb 0]"
	}
	dict for {var -} $links {
	    set vname [lindex $var 1]
	    set newq [list moveFromCallFrame \
			  $var {temp @callframe} \
			  [list literal $vname]]
	    my debug-callframe {
		puts "$b:[llength $newbb]: $newq"
	    }
	    lappend newbb $newq
	}
	set bb [lindex $bbcontent $b]
	lset bbcontent $b {}
	set bb [linsert $bb[set bb {}] 0 {*}$newbb]
	lset bbcontent $b $bb
    }

    my debug-callframe {
	puts "After callframeMotion:"
	my dump-bb
    }
}

# quadcode::transformer method callFrameMovesBefore --
#
#	Inserts any data motion to and from the callframe required before
#	a given quadcode instruction.
#
# Parameters:
#	b - Basic block number
#	pc - Program counter within the block
#	newbbv - Name of a variable in caller's scope accumulating the new
#	         instruction list for the block
#	q - Instruction being analyzed.
#
# Results:
#	None.
#
# Side effects:
#	The code that is needed before $q is inserted.
#
# If an instruction is an 'invoke', then 'moveToCallFrame' is needed
# before it, with all purely local variables (those that do not appear
# in 'nsupvar', 'upvar', 'variable') listed.
#
# 'load' can be treated the same way as 'invoke'. In the worst
# case, we do not know what variables they read and write, and simply have
# to deal with whatever they do to the callframe. Once we've done copy
# propagation, we can deal with the common case where 'loadStk' and
# 'storeStk' are actually reading and writing namespace-qualified
# variables.
#
# Even though 'store' does not read variables, but only writes them, it
# still needs all the 'moveToCallFrame' operations as well. The reason
# is that if it is discovered that 'store' is storing to a predictable
# place, 'moveFromCallFrame' instructions need to be eliminated.
# In that case, we need the corresponding 'moveToCallFrame' operations
# so as to look up the reaching definition of the variable.
#
# The 'cleanupCallFrameMotion' pass will optimize away the variables
# that the 'invoke' or 'load' does not read, or that are not aliased
# to the variable that the 'store' might alter.  It can also remove
# data motion involving (some of) the variables that do not need to be
# moved to the callframe because they are already there. This
# optimization may have the effect of killing 'moveFromCallFrame'
# instructions, which will be removed by the cleanup optimizations.

oo::define quadcode::transformer method callFrameMovesBefore {b pc newbbv q} {
    if {[lindex $q 0] in {
	"directAppend" "directArrayAppend" "directArrayExists" "directArrayGet"
	"directArrayLappend" "directArrayLappendList" "directArraySet"
	"directArrayUnset" "directExists" "directGet" "directLappend"
	"directLappendList" "directSet" "directUnset" "invoke" "invokeExpanded"
    }} {

	# All variables are forced into the callframe before 'invoke',
	# 'load' and 'store'. Variables that cannot be accessed are
	# optimized away later.

	upvar 1 $newbbv newbb
	set newq {moveToCallFrame {temp @callframe} {temp @callframe}}
	foreach v $vars {
	    lappend newq [list literal [lindex $v 1]] $v
	    # TODO - Store-store optimization is needed, to detect that
	    #	     $v is already in the callframe
	}
	my debug-callframe {
	    puts "    $newq"
	    puts "inserted before"
	    puts "$b:$pc: $q"
	}
	lappend newbb $newq
    }
}

# quadcode::transformer method callFrameMovesAfter --
#
#	Inserts any data motion to and from the callframe required after
#	a given quadcode instruction.
#
# Parameters:
#	b - Basic block number
#	pc - Program counter within the block
#	newbbv - Name of a variable in caller's scope accumulating the new
#	         instruction list for the block
#	q - Instruction being analyzed.
#
# Results:
#	None.
#
# Side effects:
#	The code that is needed before $q is inserted.
#
# For an 'invoke', we need to insert moves from the callframe for all
# variables, both links and strictly local variables. (Links are included
# because we don't yet know what variables the invoked command may have
# written. and if any of them potentially have aliases, we need to move
# the aliases as well as the linked variables.)
#
# 'load' requires no postaction, since it cannot alter variables.
# 'store' may be treated similarly to 'invoke'.  We can optimize later
# the common case where the name of the variable being loaded or
# stored is constant, once we've done copy propagation and know what
# the name is.
#
# For 'nsupvar', 'upvar' and 'variable', we need to insert a single
# move from the callframe to retrieve the initial value of the variable
# after creating the link.
#
# An instruction that assigns to a variable that may be a link must move
# the result to the callframe, and then move all linked variables from the
# callframe. (Alias analysis may be able to down-select what is moved here.)
#
# Many of these moves will be dead, and we depend on cleanup optimizations
# to get rid of them.

oo::define quadcode::transformer method callFrameMovesAfter {b pc newbbv q} {

    upvar 1 $newbbv newbb

    switch -exact -- [lindex $q 0] {

	"invoke" - "invokeExpanded" - "nsupvar" - "upvar" - "variable" {

	    # 'invoke', 'nsupvar', 'upvar', 'variable' are followed by
	    # 'extractCallFrame' and will be dealt with when the
	    # 'extractCallFrame' is encountered.

	}

	"extractCallFrame" {

	    # Find the instruction that altered the callframe

	    set sourceCF [lindex $q 2]

	    set pc2 $pc
	    while {$pc2 > 0} {
		incr pc2 -1
		set q2 [lindex $bbcontent $b $pc2]
		if {[lindex $q2 1] eq $sourceCF} break
	    }
	    if {$pc2 < 0} {
		error "cannot find source of callframe in $b:$pc: $q"
	    }

	    switch -exact [lindex $q2 0] {

		"invoke" - "invokeExpanded" {

		    # After 'invoke' or 'store', all variables are
		    # retrieved from the callframe. Variables that are
		    # not changed (either because an invoked proc
		    # doesn't reference them, or because they cannot
		    # alias the target of the 'store') are removed
		    # later.

		    my debug-callframe {
			puts "insert after"
			puts "$b:$pc: $q"
			puts "   (origin: $b:$pc2: $q2)"
		    }
		    foreach v $vars {
			set newq [list moveFromCallFrame $v [lindex $q 1] \
				      [list literal [lindex $v 1]]]
			my debug-callframe {
			    puts "    $newq"
			}
			lappend newbb $newq
		    }
		}

		"nsupvar" - "upvar" - "variable" {

		    # After creating a new alias as a local variable, the
		    # value of the variable has to be retrieved from the
		    # callframe.
		    upvar 1 $newbbv newbb
		    my debug-callframe {
			puts "insert after"
			puts "$b:$pc: $q"
			puts "   (origin: $b:$pc2: $q2)"
		    }
		    set litname [lindex $q2 3]
		    set name [lindex $litname 1]
		    set newq [list moveFromCallFrame \
				  [list var $name] [lindex $q 1] $litname]
		    my debug-callframe {
			puts "    $newq"
		    }
		    lappend newbb $newq
		}
	    }
	}

	"dictAppend" - "dictGet" - "dictIncr" - "dictIterStart" -
	"dictLappend" - "dictSet" - "dictSize" - "dictUnset" -
	"dictSetOrUnset" -
	"div" - "expon" - "foreachStart" -
	"initException" -
	"listAppend" - "listConcat" -
	"listIn" - "listIndex" - "listLength" - "listRange" - "listSet" -
	"mod" - "not" - "originCmd" - "regexp" -
	"strindex" - "strrange" - "strreplace" {
	    # These operations all return FAIL, and a subsequent
	    # 'extractMaybe' will be needed. The intermediate copy
	    # of the variable will not be moved to the frame. We wait
	    # for the 'extractMaybe' to move the actual value.
	}

	default {

	    # On any assignment, we move the result to the callframe,
	    # then move anything that the result might alias back from
	    # the callframe. We put a 'no op' in between so that code that
	    # tracks the callframe content can find the correct values.

	    # On a direct assignment, we also need to recover anything
	    # that might alias the direct variable.

	    set tgt [lindex $q 1]
	    set needMovesFrom 0
	    if {[lindex $tgt 0] eq "var"
		    && [dict exists $links $tgt]} {
		upvar 1 $newbbv newbb
		my debug-callframe {
		    puts "insert after"
		    puts "$b:$pc: $q"
		}
		set vname [lindex $tgt 1]
		set newq [list moveToCallFrame \
			      {temp @callframe} {temp @callframe} \
			      [list literal $vname] $tgt]
		lappend newbb $newq
		my debug-callframe {
		    puts "    $newq"
		}
		set needMovesFrom 1
	    }
	    if {[lindex $q 0] in {
		"directAppend" "directArrayAppend" "directArrayLappend"
		"directArrayLappendList" "directArraySet" "directArrayUnset"
		"directLappend" "directLappendList" "directSet" "directUnset"
	    }} {
		unset -nocomplain vname
		set tgt Nothing
		set needMovesFrom 1
	    }

	    if {$needMovesFrom} {
		if {[info exists vname]} {
		    set nopArg [list literal $vname]
		} else {
		    set nopArg Nothing
		}
		set newq2 [list callFrameNop \
			       {temp @callframe} {temp @callframe} $nopArg]
		my debug-callframe {
		    puts "    $newq2"
		}
		lappend newbb $newq2
		dict for {var -} $links {
		    if {$tgt ne $var} {
			set vname [lindex $var 1]
			set newq [list moveFromCallFrame \
				      $var {temp @callframe} \
				      [list literal $vname]]
			my debug-callframe {
			    puts "    $newq"
			}
			lappend newbb $newq
		    }
		}
	    }
	}
    }
}

# quadcode::transformer method cleanupMoveFromCallFrame --
#
#	Removes and replaces 'moveFromCallFrame' where it is known that
#	a target procedure does not write a callframe variable
#
# Results:
#	Returns 1 if any code was changed by this method, 0 otherwise
#
# Side effects:
#	The 'moveFromCallFrame' instruction is deleted, and its
#	result is replaced with the operand on the corresponding
#       'moveToCallFrame', if the operation is known not to write
#	the variable.
#
# FIXME: This procedure needs to be updated to deal with namespace variables.
#	 'moveFromCallFrame' may have been inserted after a quad has assigned
#	 to a potentially aliased variable, rather than after an 'invoke'

oo::define quadcode::transformer method cleanupMoveFromCallFrame {} {

    my debug-callframe {
	puts "before cleanupMoveFromCallFrame:"
	my dump-bb
    }

    # $vw will hold a dictionary whose keys are quadcode instructions
    # and whose values are the lists of variables that the
    # corresponding instructions might store in the callframe.

    set vw {}

    # Walk through the quadcode looking for 'moveFromCallFrame'

    set changed 0

    for {set b 0} {$b < [llength $bbcontent]} {incr b} {
	set outpc -1
	for {set pc 0} {$pc < [llength [lindex $bbcontent $b]]} {incr pc} {
	    set q [lindex $bbcontent $b $pc]
	    if {[lindex $q 0] ne "moveFromCallFrame"} {
		lset bbcontent $b [incr outpc] $q
		continue
	    }
	    my debug-callframe {
		puts "Examine $b:$pc: $q"
	    }

	    # Found 'moveFromCallFrame'. Make sure the variable name is literal
	    lassign $q opcode tovar fromcf var
	    if {[lindex $var 0] ne "literal"} {
		my debug-callframe {
		    puts "    variable name not literal, can't optimize."
		}
		lset bbcontent $b [incr outpc] $q
		continue
	    }
	    set vname [lindex $var 1]

	    # Find the instruction that produced the callframe
	    set producer [my cfProducer [lindex $q 2]]
	    my debug-callframe {
		puts "    produced by: $producer"
	    }

	    # Find out what variables that the producer potentially changes
	    if {![dict exists $vw $producer]} {

		switch -exact [lindex $producer 0] {

		    "nsupvar" - "variable" - "upvar" {

			# The producer created a new link. The result variable
			# was 'written'

			dict set vw $producer \
			    [list 1 [list [lindex $producer 3]]]
		    }

		    callFrameNop {

			# If the producer is 'callframeNop', then the
			# potential change happened because a potentially
			# aliased variable was moved to the callframe.
			# The affected variables are its potential aliases

			if {[lindex $producer 3 0] eq "literal"} {
			    dict set vw $producer \
				[list 1 [my may-alias [lindex $producer 3]]]
			} else {
			    dict set vw $producer {0 {}}
			}
		    }

		    startCatch {

			# When catching an error, resynchronize to make sure
			# that errorCode and errorInfo are up to date.
			# Our ultraconservative alias analysis has no
			# real way of handling this, so simply spoil everything

			dict set vw $producer [list 1 [dict keys $links]]
		    }

		    "invoke" - "invokeExpanded" {

			# The variables altered by the 'invoke', plus
			# all aliases, are potentially changed.

			set aliases {}
			set atypes [lmap x [lrange $producer 4 end] {
			    typeOfOperand $types $x
			}]
			lassign [my variablesProducedBy $producer $atypes] \
			    known wlist
			if {$known} {
			    foreach v $wlist {
				dict set aliases $v {}
				foreach a [my may-alias $v] {
				    dict set aliases $a {}
				}
			    }
			    dict set vw $producer \
				[list 1 [dict keys $aliases]]
			} else {
			    dict set vw $producer {0 {}}
			}
		    }
		}
	    }

	    lassign [dict get $vw $producer] known vlist
	    my debug-callframe {
		if {$known} {
		    puts "    which writes variable(s) [list $vlist]"
		} else {
		    puts "    which potentially writes any variable"
		}
	    }

	    # Is this variable written by the operation?
	    if {!$known || $vname in $vlist} {
		my debug-callframe {
		    puts "    which might include $vname, so can't remove quad"
		}
		lset bbcontent $b [incr outpc] $q
		continue
	    }
	    my debug-callframe {
		puts "    which does not include $vname"
	    }

	    # This variable is known not to be written by the invocation.
	    # Trace its data source
	    set source [my cfPreviousDataSource $var $producer]
	    if {$source eq ""} {
		my debug-callframe {
		    puts "    $vname has an unknown source, can't optimize"
		}
		lset bbcontent $b [incr outpc] $q
		continue
	    }

	    my debug-callframe {
		puts "    replace uses of $tovar with $source, delete quad"
	    }
	    my removeUse $fromcf $b
	    my replaceUses $tovar $source
	    dict unset duchain $tovar
	    set changed 1

	}

	# Truncate the basic block to its new length

	set bb [lindex $bbcontent $b]
	if {[incr outpc] < [llength $bb]} {
	    lset bbcontent $b {}
	    set bb [lreplace $bb[set bb {}] $outpc end]
	    lset bbcontent $b $bb
	}
	set bb {}
    }

    my debug-callframe {
	puts "after cleanupMoveFromCallFrame:"
	my dump-bb
    }

    return $changed
}

# quadcode::transformer method cleanupMoveToCallFrame --
#
#	Removes and replaces 'moveToCallFrame' where it is known that
#	a target procedure does not access a callframe variable
#
# Results:
#	Returns 1 if any code was changed by this method, 0 otherwise
#
# Side effects:
#
#	If the operation is known neither to read nor to write a given
#	variable, then it is safe to remove that variable from the
#	'moveToCallFrame' instruction. It is also safe to do so if the
#	variable was just produced by a 'moveFromCallFrame' and the
#	input callframe of the 'moveFromCallFrame' and that of the
#	'moveToCallFrame' are the same frame. If these deletions cause
#	all the variables to be deleted from the instruction, then the
#	instruction itself is deleted, and references to the output
#	callframe are replaced by references to the input callframe.
#
#	TODO: Also, we can safely remove moveToCallFrame if the value that
#	we are moving was just moved from the same callframe under
#	the same name.
#
#	TODO: Can we track back further, by noting that some operations
#	      modify only specific callframe slots?

oo::define quadcode::transformer method cleanupMoveToCallFrame {} {

    my debug-callframe {
	puts "before cleanupMoveToCallFrame:"
	my dump-bb
    }

    # Walk through the quadcode looking for 'moveToCallFrame'

    set changed 0

    for {set b 0} {$b < [llength $bbcontent]} {incr b} {
	set outpc -1
	for {set pc 0} {$pc < [llength [lindex $bbcontent $b]]} {incr pc} {
	    set q [lindex $bbcontent $b $pc]
	    if {[lindex $q 0] ne "moveToCallFrame"} {
		lset bbcontent $b [incr outpc] $q
		continue
	    }
	    my debug-callframe {
		puts "Examine $b:$pc: $q"
	    }

	    set opdlist [lassign $q opcode cfout cfin]

	    # Find the instruction that consumes the callframe
	    set consumer [my cfConsumer $cfout]
	    my debug-callframe {
		puts "    consumed by: $consumer"
	    }

	    if {[lindex $consumer 0] in {"callFrameNop" "startCatch"}} {
		# The 'callFrameNop' is there because it needs explicitly to
		# consume the linked variable. Don't touch!
		my debug-callframe {
		    puts "    which is there to sync a linked variable,\
                              don't touch!"
		}
		lset bbcontent $b [incr outpc] $q
		continue
	    }

	    # Determine argument types of the consuming call, which always
	    # begins with some output and a callframe input
	    set atypes [lmap x [lrange $consumer 4 end] {
		typeOfOperand $types $x
	    }]

	    # Find out what variables that the consumer potentially reads.
	    # Because potentially changed variables may also be unchanged,
	    # list them also.

	    set known 1
	    set vdict {}
	    lassign [my variablesUsedBy $consumer $atypes] flag vlist
	    if {!$flag} {
		set known 0
	    } else {
		foreach v $vlist {
		    dict set vdict $v {}
		}
	    }
	    lassign [my variablesProducedBy $consumer $atypes] flag vlist
	    if {!$flag} {
		set known 0
	    } else {
		foreach v $vlist {
		    dict set vdict $v {}
		}
	    }

	    my debug-callframe {
		if {$known} {
		    puts "    which accesses variable(s)\
 		              [list [dict keys $vdict]]"
		} else {
		    puts "    which potentially accesses any variable"
		}
	    }

	    # Make sure that any variables that the callee is known to
	    # access, that are not otherwise listed in the callframe,
	    # get listed.
	    if {[lindex $bbcontent 0 0 0] eq "entry"} {
		set vars [lindex $bbcontent 0 0 2 1]
		dict for {v -} $vdict {
		    if {[lsearch -exact $vars $v] < 0} {
			my debug-callframe {
			    puts "    add pass-by-name variable $v to callframe"
			}
			lappend vars $v
			lset bbcontent 0 0 2 1 $vars
		    }
		}
	    }

	    set ok 1
	    set newq [list $opcode $cfout $cfin]
	    foreach {vnamelit var} $opdlist {
		lassign $vnamelit l vname
		if {$l ne "literal"} {
		    my debug-callframe {
			puts "    $vnamelit is not a literal, can't optimize"
		    }
		    set ok 0
		    break
		}
		if {[lindex $var 0] in {"temp" "var"}} {
		    lassign [my findDef $var] defb defpc defq
		    lassign $defq defopc defvar defcf defname
		} else {
		    set defopc "entry"
		}
		if {$defopc eq "moveFromCallFrame"
			&& $defvar eq $var
			&& $defcf eq $cfin
			&& [lindex $defname 1] eq $vname} {
		    my debug-callframe {
			puts "    $vname just came out of $cfin and\
                                  doesn't need to go back in."
		    }
		    my removeUse $var $b
		    set changed 1
		} elseif {$known && ![dict exists $vdict $vname]} {
		    my debug-callframe {
			puts "    consumer doesn't access $vname, so\
                                  don't put it in the callframe"
		    }
		    my removeUse $var $b
		    set changed 1
		} else {
		    my debug-callframe {
			puts "    consumer accesses $vname and it's not there"
		    }
		    lappend newq $vnamelit $var
		}
	    }

	    if {!$ok} {
		my debug-callframe {
		    puts "    optimization suppressed"
		}
		lset bbcontent $b [incr outpc] $q
	    } elseif {[llength $newq] eq 3} {
		my debug-callframe {
		    puts "    no variables to move, delete this quad\
                              and replace $cfout with $cfin"
		}
		my replaceUses $cfout $cfin
		my removeUse $cfin $b
		dict unset duchain $cfout
	    } else {
		my debug-callframe {
		    puts "    new quad: $newq"
		}
		lset bbcontent $b [incr outpc] $newq
	    }
	}

	# Truncate the basic block to its new length

	set bb [lindex $bbcontent $b]
	if {[incr outpc] < [llength $bb]} {
	    lset bbcontent $b {}
	    set bb [lreplace $bb[set bb {}] $outpc end]
	    lset bbcontent $b $bb
	}
	set bb {}
    }

    my debug-callframe {
	puts "after cleanupMoveToCallFrame:"
	my dump-bb
    }

    return $changed
}

# quadcode::transformer method cfConsumer --
#
#	Determines what 'invoke' or other operation consumes a callframe
#	that appears in a 'moveToCallframe' operation
#
# Parameters:
#	frame - Callframe variable
#
# Results:
#	Returns the quadcode operation that uses the callframe in question.
#	Allows for multiple 'moveToCallFrame' operations to accumulate
#	values before the final use. Returns the empty string if a unique
#	use cannot be determined.

oo::define quadcode::transformer method cfConsumer {frame} {
    my variable bbcontent
    set qs [my allUses $frame]
    if {[llength $qs] != 3} {
	return {}
    }
    lassign $qs b pc indx
    set q [lindex $bbcontent $b $pc]
    if {[lindex $q 0 0] eq "moveToCallFrame"} {
	tailcall my cfConsumer [lindex $q 1]
    }
    return $q
}

# quadcode::transformer method cfProducer --
#
#	Locates the basic block where a given callframe originated.
#
# Parameters:
#	frame - Callframe variable
#
# Results:
#	Returns the quadcode instruction that produced the frame.

oo::define quadcode::transformer method cfProducer {frame} {
    lassign [my findDef $frame] bb pc q
    while {[lindex $q 0] eq "extractCallFrame"} {
	set frame [lindex $q 2]
	lassign [my findDef $frame] bb pc q
    }
    return $q
}

# quadcode::transformer method cfPreviousDataSource --
#
#	Determine the previous origin of a callframe variable if we
#	have decided that a given quadcode instruction does not set it.
#
# Parameters:
#	vn - Name of a callframe variable
#	producer - Quadcode that does not write to the variable.
#
# Results:
#	Returns a quadcode reference to the value of the variable in the
#	callframe before 'producer' executes.

oo::define quadcode::transformer method cfPreviousDataSource {vn producer} {

    # What was the previous value of the callframe?
    set frame [lindex $producer 2]

    # What was the instruction that produced that frame?
    lassign [my findDef $frame] b pc q
    if {[lindex $q 0 0] ne "moveToCallFrame"} {
	# Can't find a data source
	return {}
    }

    foreach {vn2 val} [lrange $q 3 end] {
	if {$vn2 eq $vn} {
	    return $val
	}
    }

    tailcall my cfPreviousDataSource $vn $q
}

# quadcode::transformer method cfAlreadyInCallFrame --
#
#	Determines whether a given value for a callframe variable
#	is already in the frame.
#
# Parameters:
#	vn - Name of the source variable
#	val - Name of the value being stored into the frame
#	frame - Name of the callframe that's receiving the value
#
# Results:
#	Returns 1 if the value can be proven already to be in the frame
#	(generally, because we just took it out of there), 0 otherwise.

oo::define quadcode::transformer method cfAlreadyInCallFrame {vn val frame} {

    if {[lindex $val 0] ni {"temp" "var"}} {
	# TODO - Move of Nothing can be eliminated if the target frame
	#        is the entry frame.
	return 0
    } else {
	lassign [my findDef $val] defBlock defPC defQ
	if {[lindex $defQ 0] eq "moveFromCallFrame"
		&& [lindex $defQ 2] eq $frame} {
	    return 1
	} else {
	    return 0
	}
    }
}

# quadcode::transformer method cleanupCallFrameUse --
#
#	Determines what operations that produce callframes may have
#	the associated callframes eliminated entirely.
#
# Results:







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1517
1518
1519
1520
1521
1522
1523






































































































































































































































































































































































































































































































































































































































































































































































































































































































1524
1525
1526
1527
1528
1529
1530
    foreach bb $bbcontent {
	if {[lsearch -exact -index 0 $bb upvar] >= 0} {
	    return 1
	}
    }
    return 0
}







































































































































































































































































































































































































































































































































































































































































































































































































































































































# quadcode::transformer method cleanupCallFrameUse --
#
#	Determines what operations that produce callframes may have
#	the associated callframes eliminated entirely.
#
# Results:
1041
1042
1043
1044
1045
1046
1047






















































1048
1049
1050
1051
1052
1053
1054
    }
    my debug-callframe {
	puts "After cleanupCallFrameUse:"
	my dump-bb
    }
    return $changed
}























































# quadcode::transformer method eliminateCallFrame --
#
#	Eliminates callframe operations on entry and return if nothing
#	else in a quadcode sequence uses the callframe
#
# Preconditions:







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
    }
    my debug-callframe {
	puts "After cleanupCallFrameUse:"
	my dump-bb
    }
    return $changed
}

# quadcode::transformer method removeCallFrameNop --
#
#	Removes all instructions that mark callframe actions but
#	generate no code, once their use for alias analysis is complete.
#
# Results:
#	None.

oo::define quadcode::transformer method removeCallFrameNop {} {

    my debug-callframe {
	puts "Before removeCallFrameNop:"
	my dump-bb
    }

    for {set b 0} {$b < [llength $bbcontent]} {incr b} {

	set outpc 0
	set bl [llength [lindex $bbcontent $b]]
	for {set pc 0} {$pc < $bl} {incr pc} {

	    set q [lindex $bbcontent $b $pc]
	    if {[lindex $q 0] in {"startCatch"}} {
		my debug-callframe {
		    puts "Remove $b:$pc: $q"
		}
		set cfout [lindex $q 1]
		set cfin [lindex $q 2]
		my replaceUses $cfout $cfin
		dict unset udchain $cfout
		my removeUse $cfin $b
	    } else {
		lset bbcontent $b $outpc $q
		incr outpc
	    }
	}

	set bb [lindex $bbcontent $b]
	if {$outpc < [llength $bb]} {
	    lset bbcontent $b {}
	    set bb [lreplace $bb[set bb {}] $outpc end]
	    lset bbcontent $b $bb
	}
    }

    my debug-callframe {
	puts "After removeCallFrameNop:"
	my dump-bb
    }

    return
}


# quadcode::transformer method eliminateCallFrame --
#
#	Eliminates callframe operations on entry and return if nothing
#	else in a quadcode sequence uses the callframe
#
# Preconditions:
1064
1065
1066
1067
1068
1069
1070

1071
1072
1073
1074
1075
1076
1077
#	Callframe operations are removed if possible

oo::define quadcode::transformer method eliminateCallFrame {} {

    my debug-callframe {
	puts "Check whether callframe can be removed entirely from\
              ${originProc}([lmap t $ptype {nameOfType $t}])"

    }

    # The entry operation is block 0, pc 0, and its output callframe
    # is arg 1

    if {[lindex $bbcontent 0 0 0] ne {entry}} {
	return -code error "Quadcode sequence does not begin with 'entry'"







>







1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
#	Callframe operations are removed if possible

oo::define quadcode::transformer method eliminateCallFrame {} {

    my debug-callframe {
	puts "Check whether callframe can be removed entirely from\
              ${originProc}([lmap t $ptype {nameOfType $t}])"
	my dump-bb
    }

    # The entry operation is block 0, pc 0, and its output callframe
    # is arg 1

    if {[lindex $bbcontent 0 0 0] ne {entry}} {
	return -code error "Quadcode sequence does not begin with 'entry'"
1113
1114
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
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
	dict unset udchain $initCF
	lset bbcontent 0 0 1 {}
	my debug-callframe {
	    my dump-bb
	}
    }

    return
}

# quadcode::transformer method removeCallFrameNop --
#
#	Removes all callframeNop instruction once their use for
#	alias analysis is complete.
#
# Results:
#	None.

oo::define quadcode::transformer method removeCallFrameNop {} {

    my debug-callframe {
	puts "Before removeCallFrameNop:"
	my dump-bb
    }

    for {set b 0} {$b < [llength $bbcontent]} {incr b} {

	set outpc 0
	set bl [llength [lindex $bbcontent $b]]
	for {set pc 0} {$pc < $bl} {incr pc} {

	    set q [lindex $bbcontent $b $pc]
	    if {[lindex $q 0] in {"callFrameNop" "startCatch"}} {
		my debug-callframe {
		    puts "Remove $b:$pc: $q"
		}
		set cfout [lindex $q 1]
		set cfin [lindex $q 2]
		my replaceUses $cfout $cfin
		dict unset udchain $cfout
		my removeUse $cfin $b
	    } else {
		lset bbcontent $b $outpc $q
		incr outpc
	    }
	}

	set bb [lindex $bbcontent $b]
	if {$outpc < [llength $bb]} {
	    lset bbcontent $b {}
	    set bb [lreplace $bb[set bb {}] $outpc end]
	    lset bbcontent $b $bb
	}
    }

    my debug-callframe {
	puts "After removeCallFrameNop:"
	my dump-bb
    }

    return
}

# quadcode::transformer method variablesUsedBy --
#
#	Determines what variables are used by a given procedure invocation.
#







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1786
1787
1788
1789
1790
1791
1792





















































1793
1794
1795
1796
1797
1798
1799
	dict unset udchain $initCF
	lset bbcontent 0 0 1 {}
	my debug-callframe {
	    my dump-bb
	}
    }






















































    return
}

# quadcode::transformer method variablesUsedBy --
#
#	Determines what variables are used by a given procedure invocation.
#

Changes to quadcode/constfold.tcl.

89
90
91
92
93
94
95




96
97
98
99
100
101
102
			dict unset udchain $result
			my replaceUses $result $res
			set changed 1
			continue; # delete the quad
		    }

		    "arrayExists" {




			my debug-constfold {
			    puts "$b:$pc: examine $q"
			}

			# What type do I want?
			set want $quadcode::dataType::ARRAY








>
>
>
>







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
			dict unset udchain $result
			my replaceUses $result $res
			set changed 1
			continue; # delete the quad
		    }

		    "arrayExists" {

			# arrayExists tests for the actual existence of an
			# array

			my debug-constfold {
			    puts "$b:$pc: examine $q"
			}

			# What type do I want?
			set want $quadcode::dataType::ARRAY

734
735
736
737
738
739
740
741
742
743
744
745
	}
	set bb [lindex $bbcontent $b]
	lset bbcontent $b {}
	lset bbcontent $b [lrange $bb[set bb ""] 0 $newpc]
    }

    my debug-constfold {
#	puts "After constfold:"
#	my dump-bb
    }
    return $changed
}







|
|



738
739
740
741
742
743
744
745
746
747
748
749
	}
	set bb [lindex $bbcontent $b]
	lset bbcontent $b {}
	lset bbcontent $b [lrange $bb[set bb ""] 0 $newpc]
    }

    my debug-constfold {
	puts "After constfold:"
	my dump-bb
    }
    return $changed
}

Changes to quadcode/copyprop.tcl.

43
44
45
46
47
48
49









50
51
52
53
54
55
56
	    set q [lindex $bbcontent $b $pc]

	    if {[lindex $q 0] eq "copy"} {
		my debug-copyprop {
		    puts "$b:$pc: $q"
		}
		lassign $q - to from










		# Is this copy killable?
		if {[lindex $to 0] eq "temp"
		    || [lrange $from 0 1] eq [lrange $to 0 1]} {
		    # Kill a copy
		    my debug-copyprop {
			puts "Fold copy:"







>
>
>
>
>
>
>
>
>







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
	    set q [lindex $bbcontent $b $pc]

	    if {[lindex $q 0] eq "copy"} {
		my debug-copyprop {
		    puts "$b:$pc: $q"
		}
		lassign $q - to from

		# Is this copy actually an unset
		if {[lindex $from 0] eq "Nothing"} {
		    my debug-copyprop {
			puts "$b:$pc: $q - replace with unset"
		    }
		    set q [list unset $to]
		    set changed 1
		}

		# Is this copy killable?
		if {[lindex $to 0] eq "temp"
		    || [lrange $from 0 1] eq [lrange $to 0 1]} {
		    # Kill a copy
		    my debug-copyprop {
			puts "Fold copy:"

Changes to quadcode/dbginfo.tcl.

50
51
52
53
54
55
56

57
58
59
60
61
62
63
64
65



66
67
68
69
70
71
72
		set debugContext [lindex $q 2 1]
	    }

	} else {

	    # Advance to the dominating block if no debug information
	    # in the current block

	    set b [lindex $bbidom $b]
	    if {$b >= 0} {
		set pc [llength [lindex $bbcontent $b]]
	    } else {
		if {![info exists debugLines]} {
		    set debugLines {0 0}
		}
		if {![info exists debugScript]} {
		    set debugScript {}



		}
		break
	    }

	}
    }
    return [list $sourcefile $debugLines $debugScript $debugContext]







>
|
<







>
>
>







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
		set debugContext [lindex $q 2 1]
	    }

	} else {

	    # Advance to the dominating block if no debug information
	    # in the current block
	    if {$b > 0} {
		set b [lindex $bbidom $b]

		set pc [llength [lindex $bbcontent $b]]
	    } else {
		if {![info exists debugLines]} {
		    set debugLines {0 0}
		}
		if {![info exists debugScript]} {
		    set debugScript {}
		}
		if {![info exists debugContext]} {
		    set debugContext {}
		}
		break
	    }

	}
    }
    return [list $sourcefile $debugLines $debugScript $debugContext]

Changes to quadcode/duchain.tcl.

101
102
103
104
105
106
107
108



























109
110
111
112
113
114
115
			}
			my addUse $opd $b
		    }
		}
	    }
	}
    }
    



























    # addUse --
    #
    #   Updates du-chains to add a use to a variable
    #
    # Parameters:
    #	var - Variable whose use is being added. It is harmless to call
    #	      this procedure for things other than variables, but has no







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
			}
			my addUse $opd $b
		    }
		}
	    }
	}
    }

    # addDef --
    #
    #	Updates ud-chain to define a variable
    #
    # Parameters:
    #	var - Variable whose definition is being added.
    #	b - Basic block containing the added use.
    #
    # Results:
    #	None.

    method addDef {var b} {
	dict set udchain $var $b
	return
    }

    # removeDef --
    #
    #	Updates ud-chains to remove the definition of a variable
    #
    # Parameters:
    #	var - Variable to remove

    method removeDef {var} {
	dict unset udchain $var
    }

    # addUse --
    #
    #   Updates du-chains to add a use to a variable
    #
    # Parameters:
    #	var - Variable whose use is being added. It is harmless to call
    #	      this procedure for things other than variables, but has no
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
	if {[lindex $opd 0] in {"var" "temp"}} {
	    my addUse $opd $b
	}
    }

    set bb [lindex $bbcontent $b]
    lset bbcontent $b {}
    lset bbcontent $b [linsert $bb[unset -nocomplain bb] $pc $q]
    return
}

# quadcode::transformer method audit-duchain --
#
#	Makes sure that the 'duchain' dictionary matches the actual uses
#	of variables in the quadcode







|







451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
	if {[lindex $opd 0] in {"var" "temp"}} {
	    my addUse $opd $b
	}
    }

    set bb [lindex $bbcontent $b]
    lset bbcontent $b {}
    lset bbcontent $b [linsert $bb[set bb {}] $pc $q]
    return
}

# quadcode::transformer method audit-duchain --
#
#	Makes sure that the 'duchain' dictionary matches the actual uses
#	of variables in the quadcode

Deleted quadcode/exists.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
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
271
272
273
274
275
276
277
278
279
280
281
282
283
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
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# exists.tcl --
#
#	Methods that optimize checks for variable existence in quadcode.
#
# Copyright (c) 2015 by Kevin B. Kenny
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
#------------------------------------------------------------------------------

# This file contains several passes over the quadcode to optimize checks
# for variable existence. The bytecode translator emits an existence check
# for every reference to a named variable, and the methods in this file
# are responsible for removing the checks when it can be proven that the
# variable in question always exists or never exists.
#
# The first pass in this file, 'existsPeephole', is a simple peephole
# check for a conditional jump that depends on the result of an 'exists'
# test in the same basic block. 'extractExists' and 'unset' are inserted
# on the 'true' and 'false' paths of the conditional jump, so that
# downstream code will see the already-determined facts of variable existence.
#
# There are two more complex passes in this file, both of which require that
# the program be in SSA form, with the basic blocks ordered in depth
# first numbering, and with ud- and du-chains on the variables.
#
# bbVarsExist - Operates on the basic blocks and sets the 'varExists'
#               variable to a dictionary whose keys are variable names
#	        and whose values are numeric codes. The interpretation
#	        of the codes is:
#		0 - The existence of the variable has not been evaluated
#		    because its uses are unreachable.
#		1 - The variable exists
#		2 - The variable does not exist
#		3 - The variable exists on at least one code path and
#		    does not exist on another code path.
# doExists - Using the information from 'bbVarsExist', this pass simplifies
#	     the code. The following instructions are operated on:
#	     exists - If the variable is known to exist, the instruction
#		      is removed and its result replaced with the literal 1.
#		      If the variable is known not to exist, the instruction
#		      is removed and its result replaced with the literal 1.
#	     extractExists - The instruction is removed if the variable
#		             is known to exist, and its result is replaced
#			     with the literal 1. If the variable is known
#			     not to exist, a placeholder is inserted.
#			     (In this case, if there are no bugs in the
#			     earlier passes, an earlier simplification has
#			     made this code unreachable.
#	     initIfNotExists - The instruction is removed if the variable
#			       is known to exist, and its output is replaced
#			       by the value of the variable being checked.
#	                       If the variable is known not to exist, the
#			       instruction is removed and the output replaced
#			       by the default value.
#
# This optimization may leave conditional jumps that depend on literals,
# unreachable code or unused variables, which will be cleaned up in later
# passes.

oo::define quadcode::transformer {
    
    # existsPeephole --
    #
    #	Simple peephole optimization for code guarded by [info exists],
    #
    # Preconditions:
    #	This method must run after critical edges in the flow graph are split,
    #	but before conversion to SSA form. (It can't run after conversion,
    #	because in SSA form it would have to split variables.)
    #
    # Results:
    #	None.
    #
    # Side effects:
    #	Inserts 'extractExists' and 'unset' on the true and false branches
    #	of 'exists' checks.
    #
    # This pass runs before the conversion of quadcode to SSA form. It
    # inspects basic blocks to find ones ending with a conditional that depends
    # directly on 'exists' within the block. It inserts 'extractExists' and
    # 'unset' on the two exits of the block. This has the effect, once
    # the SSA representation is formed, of allowing all 'exists,'
    # 'initIfNotExists,' and so on to be optimized away in code that depends
    # on the condition.

    method existsPeephole {} {
	my debug-existsPeephole {
	    puts "before 'exists' peephole:"
	    my dump-bb
	}

	# Walk all the basic blocks looking for a 'jumpTrue' or 'jumpFalse'
	# that depends on 'exists'
	set b -1
	foreach content $bbcontent {
	    incr b

	    # This optimization applies only to two-exit blocks. Work out
	    # what are the 'true' and 'false' branches
	    if {[lindex $content end 0] ne "jump"} continue
	    switch -exact [lindex $content end-1 0] {
		"jumpTrue" {
		    set trueBranch [lindex $content end-1 1 1]
		    set resultVar [lindex $content end-1 2]
		    set falseBranch [lindex $content end 1 1]
		}
		"jumpFalse" {
		    set falseBranch [lindex $content end-1 1 1]
		    set resultVar [lindex $content end-1 2]
		    set trueBranch [lindex $content end 1 1]
		}
		default {
		    # Single-exit blocks are not suitable for this
		    # transformation
		    continue
		}
	    }

	    # Look to see if "exists" flows into the conditional branch
	    set peephole 0
	    set pc -1
	    foreach q $content {
		incr pc
		if {[lindex $q 0] eq "exists" && [lindex $q 1] eq $resultVar} {

		    # This instruction makes the jump a possible candidate
		    # for [info exists] optimization
		    set peephole 1
		    set testedVar [lindex $q 2]

		} elseif {$peephole} {

		    # Spoil the peephole optimization if either of the
		    # two variables is reassigned on the way to the
		    # conditional jump.
		    set v [lindex $q 1]
		    if {$v eq $resultVar || $v eq $testedVar} {
			set peephole 0
		    }

		}
	    }
	    if {$peephole} {
		set trueBlock [lindex $bbcontent $trueBranch]
		lset bbcontent $trueBranch \
		    [linsert $trueBlock 0 \
			 [list extractExists $testedVar $testedVar]]
		set falseBlock [lindex $bbcontent $falseBranch]
		lset bbcontent $falseBranch \
		    [linsert $falseBlock 0 [list unset $testedVar]]
	    }
	}
	my debug-existsPeephole {
	    puts "after 'exists' peephole:"
	    my dump-bb
	}
    }
    
    # bbVarsExist --
    #
    #	Determines what variables exist in the program, given a basic
    #	block representation in SSA form
    #
    # Results:
    #	None
    #
    # Side effects:
    #	Sets varExists to a dictionary whose keys are variable names and
    #	whose values are 1, 2 if it does not exist, 3 if it is unknown.

    method bbVarsExist {} {
	dict set varExists Nothing 2

	# Process the basic blocks in depth-first numbering so that
	# assignments tend to happen before uses.
	set changed 1
	while {$changed} {
	    set changed 0
	    set b -1
	    foreach content $bbcontent {
		incr b

		# Walk through all the quads and adjust what they assign

		foreach q $content {
		    switch -exact -- [lindex $q 0] {
			"phi" {

			    # A phi inherits "exists" and "does not exist"
			    # flags from all its sources
			    set val 0
			    foreach {from source} [lrange $q 2 end] {
				switch -exact -- [lindex $source 0] {
				    "var" - "temp" {
					if {[dict exists $varExists $source]} {
					    set sourceExists \
						[dict get $varExists $source]
					} else {
					    set sourceExists 0
					}
				    }
				    "literal" {
					set sourceExists 1
				    }
				    "Nothing" {
					set sourceExists 2
				    }
				    "default" {
					error "Why is there $source on a phi?"
				    }
				}
				set val [expr {$val | $sourceExists}]
			    }
			}
			"unset" {

			    # The result of an "unset" does not exist
			    # Note that the SSA transformation should have
			    # removed all 'unset' operations, but it's
			    # still safe to look for them here.
			    set val 2
			}
			default {

			    # The result of anything else does exist
			    set val 1
			}
		    }

		    # Update the destination variable
		    set v [lindex $q 1]
		    if {[lindex $v 0] in {"var" "temp"}
			&& (![dict exists $varExists $v]
			    || $val != [dict get $varExists $v])} {
			set changed 1
			dict set varExists $v $val
		    }
		}
	    }
	}

	return
    }
    
    # doExists --
    #
    #	Improves quadcode by simplifying instructions that depend on
    #	variable existence when the fact of variable existence is known
    #	statically.
    #
    # Preconditions:
    #	Quadcode must be in SSA form and free of critical edges.
    #   ud- and du-chains must exist, and 'bbVarsExist' must have been
    #   run to determine variable existence.
    #
    # Results:
    #	None.
    #
    # Side effects:
    #	Simplifies quadcode.
    #	Updates bbcontent, bbpred, udchain, and duchain to reflect the
    #	modifications.

    method doExists {} {

	my debug-doExists {
	    puts "before doExists:"
	    my dump-bb
	}

	# Walk through all the instructions. It is tempting to do this all
	# with [foreach] loops, but we need to see changes as they are made.

	for {set b 0} {$b < [llength $bbcontent]} {incr b} {
	    set j 0
	    for {set i 0} {$i < [llength [lindex $bbcontent $b]]} {incr i} {
		set q [lindex $bbcontent $b $i]

		# Identify the destination and source operands, and
		# determine whether the source exists.

		set dest [lindex $q 1]
		set source [lindex $q 2]
		switch -exact -- [lindex $source 0] {
		    "var" - "temp" {
			set ex [dict get $varExists $source]
		    }
		    "literal" {
			set ex 1; # Literals always exist
		    }
		    "Nothing" {
			set ex 2; # Nothing never exists
		    }
		    default {
			set ex 0; # Everything else is unexamined
		    }
		}
		# Other instructions that manage non-existent variables:
		# unset - Removed by the SSA processing before we get here
		switch -exact [lindex $q 0] {
		    "exists" {

			# [info exists] turns into literal 1 if the
			# variable always exists, or literal 0 if it never
			# exists.

			if {$ex == 1} {
			    my removeUse $source $b
			    my replaceUses $dest {literal 1}
			    # delete the quad
			} elseif {$ex == 2} {
			    my removeUse $source $b
			    my replaceUses $dest {literal 0}
			    # delete the quad
			} else {
			    lset bbcontent $b $j $q
			    incr j
			}
		    }
		    "extractExists" {

			# 'extractExists' can be removed if the variable
			# always exists, and is misplaced if it never exists

			if {$ex == 1} {
			    my removeUse $source $b
			    my replaceUses $dest $source
			    # delete the quad
			} else {
			    lset bbcontent $b $j $q
			    incr j
			}
		    }
		    "initIfNotExists" {

			# 'initIfNotExists' has a value equal to the
			# variable if the variable always exists, or
			# to the default if it never exists

			if {$ex == 1} {
			    my removeUse $source $b
			    my removeUse [lindex $q 3] $b
			    my replaceUses $dest $source
			    # delete the quad
			} elseif {$ex == 2} {
			    my removeUse $source $b
			    my removeUse [lindex $q 3] $b
			    my replaceUses $dest [lindex $q 3]
			    # delete the quad
			} else {
			    lset bbcontent $b $j $q
			    incr j
			}
		    }
		    default {

			# Other instructions are not changed by
			# [info exists] information

			lset bbcontent $b $j $q
			incr j
		    }
		}
	    }

	    if {$j < $i} {
		set content [lindex $bbcontent $b]
		lset bbcontent $b {}
		lset bbcontent $b [lreplace $content[set content {}] $j end]
	    }
	}

	my debug-doExists {
	    puts "After removing redundant existence checks:"
	    my dump-bb
	}

	return
    }
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























































































































































































































































































































































































































































































































































































































































































































































































Deleted quadcode/invoke.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# invoke.tcl --
#
#	Utilities for manipulating invocation sequences in quadcode.
#
# Copyright (c) 2018 by Kevin B. Kenny.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
#------------------------------------------------------------------------------

# quadcode::invocationSequence --
#
#	Class that represents the data for invoking a procedure.
#
# A quadcode::invocationSequence represents the codeburst that invokes
# a procedure, from the 'moveToCallFrame' that synchronizes the call frame
# prior to the invocation, down to the 'jumpMaybe' and 'jump' that handle
# a possible error return from the procedure. Procedure inlining and
# 'invokeExpand' repacement are two operations that need to rewrite the
# entire sequence, rather than just the 'invoke' instruction itself.
# This class abstracts the data from the codeburst.

oo::class create quadcode::invocationSequence {

    # xfmr - quadcode::transformer object holding the bytecode
    # b - Basic block number of the 'invoke' instruction
    # pc - Program counter within the basic block
    # pc0 - Program counter of the start of the invocation sequence. $pc0 <= $pc
    # q - The 'invoke' instruction itself
    # cmd - The command being invoked
    # argl - The arglist from the 'invoke' instruction
    # cfin - The callframe that flows into the invocation sequence, or Nothing
    # cfout - The callframe that flows out of the invocation sequence, or
    #         {}
    # invars - Dictionary whose keys are literal variable names and whose
    #          values are the sources of variables that need to be copied
    #          to the callframe prior to invocation
    # retval - Return value from the invocation
    # outvars - Dictionary whose keys are literal variable names and
    #           whose values are the quadcode values that need to be
    #           assigned from the callframe after the invocation
    # errexit - Basic block number to jump to on error exit
    # normexit - Basic block number to jump to on normal exit

    variable xfmr b pc q cmd argl \
	pc0 cfin invars retval cfout outvars errexit normexit

    constructor {} {
	# Defer construction to an initialization method to avoid throwing
	# constructor errors.
    }

}

# quadcode::invocationSequence method analyze --
#
#	Decompose the codeburst that invokes a command from quadcode
#
# Parameters:
#	xfmr_ - quadcode::transformer object holding the quadcode
#	b_ - Basic block number in which the invoke instruction appears
#	pc_ - PC within the basic block at which the invoke instruction appears
#
# Results:
#	None
#
# Side effects:
#	Initializes variables according to the instruction.

oo::define quadcode::invocationSequence method analyze {xfmr_ b_ pc_} {

    set xfmr $xfmr_
    set b $b_
    set pc $pc_

    set bb [$xfmr getBasicBlock $b]
    set q [lindex $bb $pc]

    # Take apart the invocation

    set argl [lassign $q op cfo_invoke cfi_invoke cmd]
    if {$op ni {"invoke" "invokeExpanded"}} {
	error "cannot analyze: not an invocation."
    }

    # Find the input callframe and relevant input variables
    
    set pc0 $pc
    set cfin Nothing
    set invars {}
    if {$cfi_invoke ne "Nothing"} {
	set qb [lindex $bb [expr {$pc-1}]]
	if {[lindex $qb 0] eq "moveToCallFrame"} {
	    if {[lindex $qb 1] ne $cfi_invoke} {
		error "cannot analyze: moveToCallFrame mislinked"
	    }
	    set varl [lassign $qb - - cfin]
	    foreach {namelit source} $varl {
		if {[lindex $namelit 0] ne "literal"} {
		    error "cannot analyze: name of input var not literal"
		}
		dict set invars [lindex $namelit 1] $source
	    }
	    set pc0 [expr {$pc-1}]
	}
    }

    # Find the result value

    set retval $cfo_invoke
    if {[lindex $bb [incr pc] 0] eq "retrieveResult"} {
	set q2 [lindex $bb $pc]
	lassign $q2 - retval cf2
	if {$cf2 ne $cfo_invoke} {
	    error "cannot analyze: retrieveResult mislinked"
	}
    } else {
	incr pc -1
    }

    # Find the output callframe

    set cfout $cfo_invoke
    if {[lindex $bb [incr pc] 0] eq "extractCallFrame"} {
	set q2 [lindex $bb $pc]
	lassign $q2 - cfout cf2
	if {$cf2 ne $cfo_invoke} {
	    error "cannot analyze: extractCallFrame mislinked"
	}
    } else {
	incr pc -1
    }

    # Find the output variables

    set outvars {}
    while {[lindex $bb [incr pc] 0] eq "moveFromCallFrame"} {
	set q2 [lindex $bb $pc]
	lassign $q2 - varout cf2 litname
	if {$cf2 ne $cfout} {
	    error "cannot analyze: moveFromCallFrame mislinked"
	}
	lassign $litname kind val
	if {$kind ne "literal"} {
	    error "cannot analyze: moveFromCallFrame with non-literal variable"
	}
	dict set outvars $val $varout
    }
    incr pc -1

    # Find the error exit

    if {[lindex $bb [incr pc] 0] eq "jumpMaybe"} {
	set q2 [lindex $bb $pc]
	lassign $q2 - target cond
	if {$cond ne $retval} {
	    error "cannot analyze: jumpMaybe mislinked"
	}
	set errexit [lindex $target 1]
    } else {
	error "cannot analyze: invocation does not end basic block."
    }

    # Find the normal exit

    if {[lindex $bb [incr pc] 0] eq "jump"} {
	set normexit [lindex $bb $pc 1 1]
    } else {
	error "cannot analyze: basic block does not end with a jump"
    }
	
    return
}

# quadcode::invocationSequence method cfin --
#
#	Returns the starting callframe for an invocation sequence

oo::define quadcode::invocationSequence method cfin {} {
    return $cfin
}

# quadcode::invocationSequence method cfout --
#
#	Returns the ending callframe for an invocation sequence

oo::define quadcode::invocationSequence method cfout {} {
    return $cfout
}

# quadcode::invocationSequence method errexit --
#
#	Returns the error exit block number for an invocation sequence

oo::define quadcode::invocationSequence method errexit {} {
    return $errexit
}

# quadcode::invocationSequence method invars --
#
#	Returns the input variables of an invocation sequence

oo::define quadcode::invocationSequence method invars {} {
    return $invars
}

# quadcode::invocationSequence method normexit --
#
#	Returns the normal exit block number for an invocation sequence

oo::define quadcode::invocationSequence method normexit {} {
    return $normexit
}

# quadcode::invocationSequence method outvars --
#
#	Returns the output variables of an invocation sequence

oo::define quadcode::invocationSequence method outvars {} {
    return $outvars
}

# quadcode::invocationSequence method pc0 --
#
#	Returns the starting program counter for an invocation sequence

oo::define quadcode::invocationSequence method pc0 {} {
    return $pc0
}

# quadcode::invocationSequence method retval --
#
#	Returns the return value for an invocation sequence

oo::define quadcode::invocationSequence method retval {} {
    return $retval
}

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























































































































































































































































































































































































































































































Changes to quadcode/narrow.tcl.

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
#	Inserts narrowing operations in the quadcode.
#
# Results:
#	None.
#
# Preconditions:
#
#	The program must be in SSA form, and the DJ graph (bbidom, bbkids,
#	bbnlevels, bblevel) must be accurate. ud- and du-chains must be
#	present.
#
# Side effects:
#
#	Wherever a conditional branch tests the data type or existence of
#	a value, narrowing instructions are inserted in the quadcode to
#	mark that the value is of the required type.
#
#	The ud- and du-chains are updated as the narrowing instructions
#	are inserted, and phi instructions for the controlled variables
#	are inserted on the iterated dominance frontier. The phi's may
#	turn out to be useless, in which case a subsequent 'uselessphis'
#	pass will clean them up.
#
# All of the operations introduced in this pass consist of introducing
# new quads of the form
#	v2 := some_narrowing_operation(v1)
# where v2 is a new variable instance, followed by fixup to the SSA diagram.


oo::define quadcode::transformer method narrow {} {
    upvar #0 quadcode::dataType::IMPURE IMPURE

    my debug-narrow {
	puts "before inserting narrowing operations:"
	my dump-bb







|
|
|







<
<
<
<
<
<


|
|
>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32






33
34
35
36
37
38
39
40
41
42
43
44
#	Inserts narrowing operations in the quadcode.
#
# Results:
#	None.
#
# Preconditions:
#
#	The program must be deconstructed from SSA form. ud- and du-chains
#	must reflect the state of the program before deconstruction. One
#	round of copy propagation must have been done.
#
# Side effects:
#
#	Wherever a conditional branch tests the data type or existence of
#	a value, narrowing instructions are inserted in the quadcode to
#	mark that the value is of the required type.
#






# All of the operations introduced in this pass consist of introducing
# new quads of the form
#	v := some_narrowing_operation(v)
# where v is the value being tested (possibly indirectly) by the conditional
# jump. 

oo::define quadcode::transformer method narrow {} {
    upvar #0 quadcode::dataType::IMPURE IMPURE

    my debug-narrow {
	puts "before inserting narrowing operations:"
	my dump-bb
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
104



105


106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122



123


124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
		    set falseBranch [lindex $bb end 1 1]
		} else {
		    set falseBranch [lindex $q 1 1]
		    set trueBranch [lindex $bb end 1 1]
		}

		# These operations may narrow if the defining instruction
		# is 'exists' or 'instanceOf'

		# The assignment appears at 'dpc' within basic block 'dbb'
		# and consists of the quadcode statement 'dquad'.





		lassign [my findDef [lindex $q 2]] dbb dpc dquad










		set dop [lindex $dquad 0 0]

		switch -exact -- $dop {

		    arrayExists {
			set dvar [lindex $dquad 2]
			if {[lindex $dvar 0] ni {var temp}} continue
			my insertQuad $trueBranch 0 \
			    [list extractArray $dvar $dvar]
			my insertQuad $falseBranch 0 \
			    [list extractScalar $dvar $dvar]



			my narrow_repairSSA $dvar $trueBranch $falseBranch


		    }
		    exists {
			set dvar [lindex $dquad 2]
			if {[lindex $dvar 0] ni {var temp}} continue
			my insertQuad $trueBranch 0 \
			    [list extractExists $dvar $dvar]
			my insertQuad $falseBranch 0 \
			    [list unset $dvar]



			my narrow_repairSSA $dvar $trueBranch $falseBranch


		    }

		    instanceOf {
			set typecode [lindex $dquad 0 1]
			set typename [lindex $dquad 0 2]
			set dvar [lindex $dquad 2]
			if {[lindex $dvar 0] ni {var temp}} continue
			set nottype [::quadcode::dataType::allbut $typecode]
			set nottype [::quadcode::dataType::typeUnion \
					 $nottype $IMPURE]
			set notname [nameOfType $nottype]
			my insertQuad $trueBranch 0 \
			    [list [list narrowToType $typecode $typename] \
				 $dvar $dvar]
			my insertQuad $falseBranch 0 \
			    [list [list narrowToType $nottype $notname] \
				 $dvar $dvar]



			my narrow_repairSSA $dvar $trueBranch $falseBranch


		    }
		}
	    }

	    jumpMaybe {
		set okBranch [lindex $bb end 1 1]
		set failBranch [lindex $q 1 1]
		set var [lindex $q 2]
		if {[lindex $var 0] ni {"var" "temp"}} continue
		my debug-narrow {
		    puts "  $bbindex:end-1: $q"
		    puts "  $okBranch:0: [list copy $var $var]"
		    puts "  $failBranch:0: [list extractFail $var $var]"
		}
		my insertQuad $okBranch 0 [list copy $var $var]
		my insertQuad $failBranch 0 [list extractFail $var $var]
		my narrow_repairSSA $var $okBranch $failBranch
	    }
	}
    }
    my debug-narrow {
	puts "after inserting narrowing operations:"
	my dump-bb
    }

}

# quadcode::transformer method narrow_repairSSA --
#
#	Repairs the SSA property after introducing a narrowing operation
#	on a variable.
#
# Parameters:
#	v - Variable that has been narrowed and now has duplicate assignments
#	b1 - First block containing a new assignment to v
#	b2 - Second block containing a new assignment to v
#
# Results:
#	None.
#
# Side effects:
#	The SSA property is restored by giving new names to the assignments to
#	$v, and updating the uses, possibly introducing new phi operations.

oo::define quadcode::transformer method narrow_repairSSA {v b1 b2} {
    set d [dict create [dict get $udchain $v] 1]
    dict incr d $b1
    dict incr d $b2

    my repairSSAVariable $v $d
}

# quadcode::transformer method cleanupNarrow --
#
#	Removes narrowing instructions that are no longer relevant
#
# Preconditions:
#	The 'narrow' pass must have run to insert narrowing instructions,







|



>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>











>
>
>
|
>
>








>
>
>
|
>
>

















>
>
>
|
>
>
















<









<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
172
173

























174
175
176
177
178
179
180
		    set falseBranch [lindex $bb end 1 1]
		} else {
		    set falseBranch [lindex $q 1 1]
		    set trueBranch [lindex $bb end 1 1]
		}

		# These operations may narrow if the defining instruction
		# is 'arrayExists', 'exists' or 'instanceOf'

		# The assignment appears at 'dpc' within basic block 'dbb'
		# and consists of the quadcode statement 'dquad'.
		if {[catch {

		    # Finding the definition will throw an error at a phi.
		    # The error can be ignored, because phi is not 'arrayExists'
		    # 'exists' or 'instanceOf'.
		    my findDef [lindex $q 2]
		} result]} {
		    my debug-narrow {
			puts "cannot find data source of [lindex $q 2]"
		    }
		    continue
		}
		lassign $result dbb dpc dquad
		my debug-narrow {
		    puts "data source is $dbb:$dpc: $dquad"
		}
		set dop [lindex $dquad 0 0]

		switch -exact -- $dop {

		    arrayExists {
			set dvar [lindex $dquad 2]
			if {[lindex $dvar 0] ni {var temp}} continue
			my insertQuad $trueBranch 0 \
			    [list extractArray $dvar $dvar]
			my insertQuad $falseBranch 0 \
			    [list extractScalar $dvar $dvar]
			my debug-narrow {
			    puts "$trueBranch:0:\
                                  [lindex $bbcontent $trueBranch 0]"
			    puts "$falseBranch:0:\
                                  [lindex $bbcontent $falseBranch 0]"
			}
		    }
		    exists {
			set dvar [lindex $dquad 2]
			if {[lindex $dvar 0] ni {var temp}} continue
			my insertQuad $trueBranch 0 \
			    [list extractExists $dvar $dvar]
			my insertQuad $falseBranch 0 \
			    [list unset $dvar]
			my debug-narrow {
			    puts "$trueBranch:0:\
                                  [lindex $bbcontent $trueBranch 0]"
			    puts "$falseBranch:0:\
                                  [lindex $bbcontent $falseBranch 0]"
			}
		    }

		    instanceOf {
			set typecode [lindex $dquad 0 1]
			set typename [lindex $dquad 0 2]
			set dvar [lindex $dquad 2]
			if {[lindex $dvar 0] ni {var temp}} continue
			set nottype [::quadcode::dataType::allbut $typecode]
			set nottype [::quadcode::dataType::typeUnion \
					 $nottype $IMPURE]
			set notname [nameOfType $nottype]
			my insertQuad $trueBranch 0 \
			    [list [list narrowToType $typecode $typename] \
				 $dvar $dvar]
			my insertQuad $falseBranch 0 \
			    [list [list narrowToType $nottype $notname] \
				 $dvar $dvar]
			my debug-narrow {
			    puts "$trueBranch:0:\
                                  [lindex $bbcontent $trueBranch 0]"
			    puts "$falseBranch:0:\
                                  [lindex $bbcontent $falseBranch 0]"
			}
		    }
		}
	    }

	    jumpMaybe {
		set okBranch [lindex $bb end 1 1]
		set failBranch [lindex $q 1 1]
		set var [lindex $q 2]
		if {[lindex $var 0] ni {"var" "temp"}} continue
		my debug-narrow {
		    puts "  $bbindex:end-1: $q"
		    puts "  $okBranch:0: [list copy $var $var]"
		    puts "  $failBranch:0: [list extractFail $var $var]"
		}
		my insertQuad $okBranch 0 [list copy $var $var]
		my insertQuad $failBranch 0 [list extractFail $var $var]

	    }
	}
    }
    my debug-narrow {
	puts "after inserting narrowing operations:"
	my dump-bb
    }

}


























# quadcode::transformer method cleanupNarrow --
#
#	Removes narrowing instructions that are no longer relevant
#
# Preconditions:
#	The 'narrow' pass must have run to insert narrowing instructions,
240
241
242
243
244
245
246


247
248

249
250
251

252
253
254
255
256
257
258
		    set flag [quadcode::dataType::existence $types $source]
		    set inputType [quadcode::typeOfOperand $types $source]
		    unset -nocomplain replacer
		    my debug-cleanupNarrow {
			puts "existence \$flag=$flag"
			puts "type = [quadcode::nameOfType $inputType]"
		    }


		    if {$flag eq "no" ||
			    ![quadcode::dataType::mightbea $inputType $ARRAY]} {

			set replacer {literal 0}
		    } elseif {$flag eq "yes" &&
			    [quadcode::dataType::isa $inputType $ARRAY]} {

			set replacer {literal 1}
		    }
		    if {[info exists replacer]} {
			my debug-cleanupNarrow {
			    puts "$b:$pc: Able to remove $q because $source is\
			          [quadcode::nameOfType $inputType]\
				  and hence result is $replacer"







>
>

|
>



>







239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
		    set flag [quadcode::dataType::existence $types $source]
		    set inputType [quadcode::typeOfOperand $types $source]
		    unset -nocomplain replacer
		    my debug-cleanupNarrow {
			puts "existence \$flag=$flag"
			puts "type = [quadcode::nameOfType $inputType]"
		    }
		    # The 'arrayExists' will return false if the value does
		    # not exist, or if the value is scalar
		    if {$flag eq "no" ||
			![quadcode::dataType::mightbea $inputType $ARRAY]} {
			# Does not exist or cannot be an array
			set replacer {literal 0}
		    } elseif {$flag eq "yes" &&
			    [quadcode::dataType::isa $inputType $ARRAY]} {
			# Exists and is an array
			set replacer {literal 1}
		    }
		    if {[info exists replacer]} {
			my debug-cleanupNarrow {
			    puts "$b:$pc: Able to remove $q because $source is\
			          [quadcode::nameOfType $inputType]\
				  and hence result is $replacer"
291
292
293
294
295
296
297







298
299
300
301
302
303
304
305
		}

		extractArray {
		    set result [lindex $q 1]
		    set source [lindex $q 2]
		    set inputType [quadcode::typeOfOperand $types $source]
		    set flag [quadcode::dataType::existence $types $source]







		    if {$flag eq "no" || (!($inputType & $NONARRAY) && ($inputType & $ARRAY))} {
			lset bbcontent $b $pc {nop {}}
			my removeUse $source $b
			my replaceUses $result $source
			dict unset udchain $result
			set changed 1
			continue; # delete the quad
		    }







>
>
>
>
>
>
>
|







294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
		}

		extractArray {
		    set result [lindex $q 1]
		    set source [lindex $q 2]
		    set inputType [quadcode::typeOfOperand $types $source]
		    set flag [quadcode::dataType::existence $types $source]
		    # The 'extractArray' operation is inserted on the 'true'
		    # branch of 'arrayExists'. It asserts specifically that
		    # the value is an array, which implies that it exists.
		    # This quad can therefore be removed only if the input
		    # value exists and is an array
		    if  {$flag eq "yes"
			 && (!($inputType & $NONARRAY)
			     && ($inputType & $ARRAY))} {
			lset bbcontent $b $pc {nop {}}
			my removeUse $source $b
			my replaceUses $result $source
			dict unset udchain $result
			set changed 1
			continue; # delete the quad
		    }
362
363
364
365
366
367
368







369






370
371
372
373
374
375
376
		}

		extractScalar {
		    set result [lindex $q 1]
		    set source [lindex $q 2]
		    set inputType [quadcode::typeOfOperand $types $source]
		    set flag [quadcode::dataType::existence $types $source]







		    if {$flag eq "no" || (!($inputType & $ARRAY) && ($inputType & $NONARRAY))} {






			lset bbcontent $b $pc {nop {}}
			my removeUse $source $b
			my replaceUses $result $source
			dict unset udchain $result
			set changed 1
			continue; # delete the quad
		    }







>
>
>
>
>
>
>
|
>
>
>
>
>
>







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
		}

		extractScalar {
		    set result [lindex $q 1]
		    set source [lindex $q 2]
		    set inputType [quadcode::typeOfOperand $types $source]
		    set flag [quadcode::dataType::existence $types $source]
		    # The 'extractScalar' operation is inserted on the
		    # 'false' branch of 'arrayExists'. It asserts that the
		    # value either is not an array or that the value does
		    # not exist.  In either case, this operation may be
		    # removed.
		    if {$flag eq "no"
			|| (!($inputType & $ARRAY)
			    && ($inputType & $NONARRAY))} {
			my debug-cleanupNarrow {
			    puts "   (flag = $flag; inputType = \
                                      [nameOfType $inputType])"
			    puts "$b:$pc: delete $q"
			    puts "$b:$pc: replace $result with $source"
			}
			lset bbcontent $b $pc {nop {}}
			my removeUse $source $b
			my replaceUses $result $source
			dict unset udchain $result
			set changed 1
			continue; # delete the quad
		    }
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
		    }
		}

		instanceOf {
		    set result [lindex $q 1]
		    set source [lindex $q 2]
		    set typecode [lindex $q 0 1]
		    set is [quadcode::dataType::isa \
				[quadcode::typeOfOperand $types $source] \
				$typecode]
		    set maybe [quadcode::dataType::mightbea \
				   [quadcode::typeOfOperand $types $source] \
				   $typecode]
		    if {$is} {






			lset bbcontent $b $pc {nop {}}
			my removeUse $source $b
			my replaceUses $result {literal 1}
			dict unset udchain $result
			set changed 1
			continue; # delete the quad
		    } elseif {!$maybe} {






			lset bbcontent $b $pc {nop {}}
			my removeUse $source $b
			my replaceUses $result {literal 0}
			dict unset udchain $result
			set changed 1
			continue; # delete the quad
		    }







<
|
|
|
<
<

>
>
>
>
>
>







>
>
>
>
>
>







447
448
449
450
451
452
453

454
455
456


457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
		    }
		}

		instanceOf {
		    set result [lindex $q 1]
		    set source [lindex $q 2]
		    set typecode [lindex $q 0 1]

		    set fromtype [quadcode::typeOfOperand $types $source]
		    set is [quadcode::dataType::isa $fromtype $typecode]
		    set maybe [quadcode::dataType::mightbea $fromtype $typecode]


		    if {$is} {
			my debug-cleanupNarrow {
			    puts "always true:"
			    puts "$b:$pc: $q"
			    puts "from type [nameOfType $fromtype]"
			    puts "is=$is, maybe=$maybe"
			}
			lset bbcontent $b $pc {nop {}}
			my removeUse $source $b
			my replaceUses $result {literal 1}
			dict unset udchain $result
			set changed 1
			continue; # delete the quad
		    } elseif {!$maybe} {
			my debug-cleanupNarrow {
			    puts "always false:"
			    puts "$b:$pc: $q"
			    puts "from type [nameOfType $fromtype]"
			    puts "is=$is, maybe=$maybe"
			}
			lset bbcontent $b $pc {nop {}}
			my removeUse $source $b
			my replaceUses $result {literal 0}
			dict unset udchain $result
			set changed 1
			continue; # delete the quad
		    }

Changes to quadcode/pre.tcl.

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
	    ge gt
	    initIfNotExists
	    instanceOf
	    le
	    listAppend listConcat listIn listIndex listLength listRange
	    listSet
	    lshift lt
	    maptoint mod moveFromCallFrame mult
	    narrowToType neq not
	    purify
	    regexp retrieveResult rshift
	    strcase strcat strclass strcmp streq strfind strindex strlen
	    strmap strmatch strrange strreplace strrfind strtrim
	    sub
	    uminus







|







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
	    ge gt
	    initIfNotExists
	    instanceOf
	    le
	    listAppend listConcat listIn listIndex listLength listRange
	    listSet
	    lshift lt
	    maptoint mod mult
	    narrowToType neq not
	    purify
	    regexp retrieveResult rshift
	    strcase strcat strclass strcmp streq strfind strindex strlen
	    strmap strmatch strrange strreplace strrfind strtrim
	    sub
	    uminus
202
203
204
205
206
207
208





209
210
211
212
213
214
215
	my pre_remove_speculative_phis
    }
    my pre_cleanup

    # 6. Now, dead code elimination and copy propagation will eliminate
    #    any messes that step 4 left behind.
    





    return $did_something

}

# quadcode::transformer method pre_init --
#
#	Initializes the tables for global value numbering and partial







>
>
>
>
>







202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
	my pre_remove_speculative_phis
    }
    my pre_cleanup

    # 6. Now, dead code elimination and copy propagation will eliminate
    #    any messes that step 4 left behind.
    
    my debug-pre {
	puts "After partial redundancy elimination:"
	my dump-bb
    }

    return $did_something

}

# quadcode::transformer method pre_init --
#
#	Initializes the tables for global value numbering and partial

Changes to quadcode/specializer.tcl.

308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324

325



















326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
		    } on error {msg opts} {
			my diagnostic $procName $argTypes \
			    "" 0 $procName \
			    fatal "Cannot analyze %s\n%s" \
			    $procName $::errorInfo
		    }
		}
		1 {
		    try {
			my TidyInstance $procName $argTypes
		    } on error {msg opts} {
			my diagnostic $procName $argTypes \
			    "" 0 $procName \
			    fatal "Cannot optimize %s\n%s" \
			    $procName $::errorInfo
		    }
		}

		2 {



















		    try {
			my NodeSplitInstance $procName $argTypes
		    } on error {msg opts} {
			my diagnostic $procName $argTypes \
			    "" 0 $procName \
			    fatal "Cannot perform path splitting on %s\n%s" \
			    $procName $::errorInfo
		    }
		}
		3 {
		    try {
			my DoneNodeSplitting $procName $argTypes
		    } on error {msg opts} {
			my diagnostic $procName $argTypes \
			    "" 0 $procName \
			    fatal "Cannot perform path splitting on %s\n%s" \
			    $procName $::errorInfo







|









>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









|







308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
		    } on error {msg opts} {
			my diagnostic $procName $argTypes \
			    "" 0 $procName \
			    fatal "Cannot analyze %s\n%s" \
			    $procName $::errorInfo
		    }
		}
		100 {
		    try {
			my TidyInstance $procName $argTypes
		    } on error {msg opts} {
			my diagnostic $procName $argTypes \
			    "" 0 $procName \
			    fatal "Cannot optimize %s\n%s" \
			    $procName $::errorInfo
		    }
		}
		125 {
		    try {
			my PartialRedundancyInstance $procName $argTypes
		    } on error {msg opts} {
			my diagnostic $procName $argTypes \
			    "" 0 $procName \
			    fatal "Cannot optimize %s\n%s" \
			    $procName $::errorInfo
		    }
		}
		150 {
		    try {
			my CallFrameFlowInstance $procName $argTypes
		    } on error {msg opts} {
			my diagnostic $procName $argTypes \
			    "" 0 $procName \
			    fatal "Cannot optimize %s\n%s" \
			    $procName $::errorInfo
		    }
		}
		200 {
		    try {
			my NodeSplitInstance $procName $argTypes
		    } on error {msg opts} {
			my diagnostic $procName $argTypes \
			    "" 0 $procName \
			    fatal "Cannot perform path splitting on %s\n%s" \
			    $procName $::errorInfo
		    }
		}
		300 {
		    try {
			my DoneNodeSplitting $procName $argTypes
		    } on error {msg opts} {
			my diagnostic $procName $argTypes \
			    "" 0 $procName \
			    fatal "Cannot perform path splitting on %s\n%s" \
			    $procName $::errorInfo
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
	if {[dict exists $dependents $instance]} {
	    dict for {d -} [dict get $dependents $instance] {
		my AddToWorklist 0 {*}$d
	    }
	}
    }

    my AddToWorklist 1 $procName $argTypes
}

# quadcode::specializer method TidyInstance --
#
#	Runs cleanup optimizations on a procedure instance
#
# Parameters:







|







1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
	if {[dict exists $dependents $instance]} {
	    dict for {d -} [dict get $dependents $instance] {
		my AddToWorklist 0 {*}$d
	    }
	}
    }

    my AddToWorklist 100 $procName $argTypes
}

# quadcode::specializer method TidyInstance --
#
#	Runs cleanup optimizations on a procedure instance
#
# Parameters:
1060
1061
1062
1063
1064
1065
1066




























1067
































































1068
1069
1070
1071
1072
1073
1074
    set argTypeNames [lmap x $argTypes {nameOfType $x}]
    my debug-specializer {
	puts "TIDY $procName ($argTypeNames):"
    }
    if {[$inf tidy]} {
	my AddToWorklist 0 $procName $argTypes
    } else {




























	my AddToWorklist 2 $procName $argTypes
































































    }
}

# quadcode::specializer method NodeSplitInstance --
#
#	Runs one round of node splitting on a procedure instance
#







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1080
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
1107
1108
1109
1110
1111
1112
1113
1114
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
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
    set argTypeNames [lmap x $argTypes {nameOfType $x}]
    my debug-specializer {
	puts "TIDY $procName ($argTypeNames):"
    }
    if {[$inf tidy]} {
	my AddToWorklist 0 $procName $argTypes
    } else {
	my AddToWorklist 125 $procName $argTypes
    }
}

# quadcode::specializer method PartialRedundancyInstance --
#
#	Runs one round of partial redundancy elimination on a procedure
#	instance.
#
# Parameters:
#	procName - Name of the procedure being optimized
#	argTypes - List of type codes for the procedure's arguments
#
# Results:
#	None.
#
# Side effects:
#
#	Partial redundancy elimination may introduce new quadcode
#	variables, resulting in the need to repeat type analysis. It
#	also introduces new opportunities for the cleanup
#	optimizations.  Therefore, if this pass makes changes, the
#	procedure gets backtracked to type analysis. If no changes are
#	made, we can continue with node splitting.

oo::define quadcode::specializer method PartialRedundancyInstance {procName
								   argTypes} {
    
    set instance [list $procName $argTypes]
    set argTypeNames [lmap x $argTypes {nameOfType $x}]

    if {[dict exists $failed $procName $argTypes]} {
	my debug-specializer {
	    puts "DON'T PRE $procName ($argTypeNames) - it's failed"
	}
	return;			# Don't reanalyze failed instances
    }

    set inf [dict get $typeInf $instance]

    my debug-specializer {
	puts "PRE $procName ($argTypeNames):"
    }
    if {[$inf partialredundancy]} {
	my AddToWorklist 0 $procName $argTypes
    } else {
	my AddToWorklist 150 $procName $argTypes
    }
}

# quadcode::specializer method CallFrameFlowInstance --
#
#	Runs one round of callframe data motion analysis on a procedure
#	instance.
#
# Parameters:
#	procName - Name of the procedure being optimized
#	argTypes - List of type codes for the procedure's arguments
#
# Results:
#	None.
#
# Side effects:
#
#	Optimizing call frame motion may introduce new quadcode variables,
#	resulting in the need to repeat type analysis. It also
#	introduces new opportunities for the cleanup optimizations.
#	Therefore, if this pass makes changes, the procedure
#	gets backtracked to type analysis. If no changes are made,
#	we can continue with node splitting.

oo::define quadcode::specializer method CallFrameFlowInstance {procName
							       argTypes} {
    
    set instance [list $procName $argTypes]
    set argTypeNames [lmap x $argTypes {nameOfType $x}]

    if {[dict exists $failed $procName $argTypes]} {
	my debug-specializer {
	    puts "DON'T CALLFRAME-FLOW $procName ($argTypeNames) - it's failed"
	}
	return;			# Don't reanalyze failed instances
    }

    set inf [dict get $typeInf $instance]

    my debug-specializer {
	puts "CALLFRAME-FLOW $procName ($argTypeNames):"
    }
    if {[$inf callFrameFlow]} {
	my AddToWorklist 0 $procName $argTypes
    } else {
	my AddToWorklist 200 $procName $argTypes
    }
}

# quadcode::specializer method NodeSplitInstance --
#
#	Runs one round of node splitting on a procedure instance
#
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117

    my debug-specializer {
	puts "SPLIT $procName ($argTypeNames):"
    }
    if {[$inf jumpthread]} {
	my AddToWorklist 0 $procName $argTypes
    } else {
	my AddToWorklist 3 $procName $argTypes
    }
}

# quadcode::specializer method DoneNodeSplitting --
#
#	Cleans up after the final round of node splitting on a procedure
#	instance.







|







1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229

    my debug-specializer {
	puts "SPLIT $procName ($argTypeNames):"
    }
    if {[$inf jumpthread]} {
	my AddToWorklist 0 $procName $argTypes
    } else {
	my AddToWorklist 300 $procName $argTypes
    }
}

# quadcode::specializer method DoneNodeSplitting --
#
#	Cleans up after the final round of node splitting on a procedure
#	instance.
1147
1148
1149
1150
1151
1152
1153
1154

1155
1156
1157
1158
1159
1160
1161
1162
1163
# quadcode::specializer method AddToWorklist --
#
#	Puts a procedure instance on the worklist of procedures to specialize.
#
# Parameters:
#	actNum - Number of the analysis being queued.
#		0 - Type inference
#		1 - Type narrowing and cleanup optimization

#		2 - Node splitting
#		3 - Final cleanup
#	procName - Name of the procedure under consideration
#	argTy - Types of the arguments
#
# Results:
#	None.
#
# The worklist is a binary heap of AnalysisAction objects. The precedence







|
>
|
|







1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
# quadcode::specializer method AddToWorklist --
#
#	Puts a procedure instance on the worklist of procedures to specialize.
#
# Parameters:
#	actNum - Number of the analysis being queued.
#		0 - Type inference
#		100 - Type narrowing and cleanup optimization
#		150 - Callframe data motion
#		200 - Node splitting
#		300 - Final cleanup
#	procName - Name of the procedure under consideration
#	argTy - Types of the arguments
#
# Results:
#	None.
#
# The worklist is a binary heap of AnalysisAction objects. The precedence

Changes to quadcode/ssa.tcl.

1245
1246
1247
1248
1249
1250
1251



1252
1253
1254
1255
1256
1257
1258
	set newb {}
	set newpc -1
	set pc -1
	set singleExit 1
	foreach q $bb {
	    incr pc
	    if {[lindex $q 0 0] eq "phi"} {



		continue
	    }
	    if {[lindex $q 0 0] eq "jump"} {
		break
	    }
	    if {[lindex $q 1 0] eq "bb"} {
		set singleExit 0







>
>
>







1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
	set newb {}
	set newpc -1
	set pc -1
	set singleExit 1
	foreach q $bb {
	    incr pc
	    if {[lindex $q 0 0] eq "phi"} {
		foreach {from val} [lrange $q 2 end] {
		    my removeUse $val $from
		}
		continue
	    }
	    if {[lindex $q 0 0] eq "jump"} {
		break
	    }
	    if {[lindex $q 1 0] eq "bb"} {
		set singleExit 0
1278
1279
1280
1281
1282
1283
1284

1285
1286
1287
1288
1289
1290
1291
		    break
		}
		set src [dict get $argl $bkey]
		if {$src eq "Nothing"} {
		    set q3 [list unset $dest]
		} else {
		    set q3 [list copy $dest $src]

		}
		my debug-deconstructSSA {
		    puts "    [incr newpc]: $q3"
		}
		lappend newb $q3
	    }
	}







>







1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
		    break
		}
		set src [dict get $argl $bkey]
		if {$src eq "Nothing"} {
		    set q3 [list unset $dest]
		} else {
		    set q3 [list copy $dest $src]
		    my addUse $src $b
		}
		my debug-deconstructSSA {
		    puts "    [incr newpc]: $q3"
		}
		lappend newb $q3
	    }
	}

Changes to quadcode/transformer.tcl.

314
315
316
317
318
319
320
321
322
323



324
325
326
327
328
329
330

331






332
333
334
335
336
337
338


339
340
341
342
343
344
345
346
347
#	    renameTemps

	foreach pass {
	    bbpartition
	    constJumpPeephole
	    sortbb
	    loopinv
	    callFrameMotion
	    ssa
	    ud_du_chain



	    copyprop
	    fqcmd
	    varargs
	    deadbb
	    bbidom
	    bblevel
	    rewriteParamChecks

	    narrow






	} {
	    lappend timings $pass [lindex [time [list my $pass]] 0]
	    my debug-audit {
		my audit-duchain $pass
		my audit-phis $pass
	    }
	}


	my debug-timings {
	    foreach {pass usec} $timings {
		puts "$pass: $usec microseconds"
	    }
	}
	my debug-transform {
	    puts "after initial transform:"
	    my dump-bb
	}







<


>
>
>







>

>
>
>
>
>
>

<
|
|
<

<
>
>
|
<







314
315
316
317
318
319
320

321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341

342
343

344

345
346
347

348
349
350
351
352
353
354
#	    renameTemps

	foreach pass {
	    bbpartition
	    constJumpPeephole
	    sortbb
	    loopinv

	    ssa
	    ud_du_chain
	    deadbb
	    deadvars
	    uselessphis
	    copyprop
	    fqcmd
	    varargs
	    deadbb
	    bbidom
	    bblevel
	    rewriteParamChecks
	    deconstructSSA
	    narrow
	    ssa
	    ud_du_chain
	    deadbb
	    deadvars
	    uselessphis
	    copyprop
	} {

	    my debug-transform {
		puts "Run: $pass"

	    }

	    set usec [lindex [time [list my $pass]] 0]
	    lappend timings $pass $usec
	    my debug-timings {

		puts "$pass: $usec microseconds"
	    }
	}
	my debug-transform {
	    puts "after initial transform:"
	    my dump-bb
	}
431
432
433
434
435
436
437






























438
439
440
441
442
443
444
    #
    # Results:
    #	Returns the desired basic block, or {} if the block does not exist.

    method getBasicBlock {b} {
	lindex $bbcontent $b
    }































    # getReturnType --
    #
    #	Retrieves the return type for a quadcode sequence.
    #
    # Preconditions:
    #	Presumes that 'inferTypes' has already run.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
    #
    # Results:
    #	Returns the desired basic block, or {} if the block does not exist.

    method getBasicBlock {b} {
	lindex $bbcontent $b
    }

    # editBasicBlock --
    #
    #	Performs a step that may edit the content of a basic block.
    #	This logic is set up so that the basic block content will be
    #	unshared while the editing step is proceeding.
    #
    # Parameters:
    #	bbVar - Variable in the caller that will be set to the basic block
    #	        content.
    #	b - Basic block number of the block that is to be modified.
    #	script - Script to evaluate in the caller with the variable set.
    #
    # Results:
    #	Returns the result of evaluating the script
    #
    # Side effects:
    #	Sets the given variable and does whatever the script does.
    #	Sets the basic block to the value of 'bbVar' after the script
    #   returns, if no error has occurred.

    method editBasicBlock {bbVar b script} {
	upvar 1 $bbVar bb
	set bb [lindex $bbcontent $b]
	lset bbcontent $b {};	# Remove the block from 'bbcontent' while
	;			# editing
	set result [uplevel 1 $script]
	lset bbcontent $b $bb;	# Replace the block content when done editing
	return $result
    }

    # getReturnType --
    #
    #	Retrieves the return type for a quadcode sequence.
    #
    # Preconditions:
    #	Presumes that 'inferTypes' has already run.
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
    while {$changed} {
	set changed 0
	my debug-tidy {
	    set debugLine {tidy:}
	}
	foreach pass {
	    copyprop
	    cleanupMoveFromCallFrame
	    cleanupMoveToCallFrame
	    cleanupCallFrameUse
	    cleanupNarrow
	    bbidom
	    bblevel
	    deadcond
	    deadjump
	    deadbb
	    deadvars
	    uselessphis
	    bbidom
	    bblevel
	    constfold
	    partialredundancy
	} {
	    set cmd [string map [list @pass $pass] {
		set result [my @pass]
	    }]
	    lappend timings $pass [lindex [time $cmd] 0]
	    if {$result} {
		set changed 1







<
<












<







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
    while {$changed} {
	set changed 0
	my debug-tidy {
	    set debugLine {tidy:}
	}
	foreach pass {
	    copyprop


	    cleanupCallFrameUse
	    cleanupNarrow
	    bbidom
	    bblevel
	    deadcond
	    deadjump
	    deadbb
	    deadvars
	    uselessphis
	    bbidom
	    bblevel
	    constfold

	} {
	    set cmd [string map [list @pass $pass] {
		set result [my @pass]
	    }]
	    lappend timings $pass [lindex [time $cmd] 0]
	    if {$result} {
		set changed 1
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
#	None.
#
# Side effects:
#	Removes the markers for which nodes have been split. Removes
#	any remaining 'callFrameNop' instructions. Cleans up useless phis,
#	and eliminates the use of the callframe entirely if possible.
#
# TODO: It is very likely that removeCallFrameNop and eliminateCallFrame
#       can appear much earlier in optimization than this. It might be
#       profitable to investigate this.

oo::define quadcode::transformer method doneWithNodeSplitting {} {

    foreach pass {
	removeCallFrameNop







|







692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
#	None.
#
# Side effects:
#	Removes the markers for which nodes have been split. Removes
#	any remaining 'callFrameNop' instructions. Cleans up useless phis,
#	and eliminates the use of the callframe entirely if possible.
#
# TODO: It is very likely that eliminateCallFrame
#       can appear much earlier in optimization than this. It might be
#       profitable to investigate this.

oo::define quadcode::transformer method doneWithNodeSplitting {} {

    foreach pass {
	removeCallFrameNop
764
765
766
767
768
769
770

771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
# types comes first - other modules' initialization can depend on it

source [file join $quadcode::libdir types.tcl]

source [file join $quadcode::libdir abbreviate.tcl]
source [file join $quadcode::libdir aliases.tcl]
source [file join $quadcode::libdir bb.tcl]

source [file join $quadcode::libdir bytecode.tcl]
source [file join $quadcode::libdir callframe.tcl]
source [file join $quadcode::libdir constfold.tcl]
source [file join $quadcode::libdir constjump.tcl]
source [file join $quadcode::libdir copyprop.tcl]
source [file join $quadcode::libdir dbginfo.tcl]
source [file join $quadcode::libdir deadcode.tcl]
source [file join $quadcode::libdir duchain.tcl]
source [file join $quadcode::libdir flatten.tcl]
source [file join $quadcode::libdir fqcmd.tcl]
source [file join $quadcode::libdir inline.tcl]
source [file join $quadcode::libdir invoke.tcl]
source [file join $quadcode::libdir jumpthread.tcl]
source [file join $quadcode::libdir liveranges.tcl]
source [file join $quadcode::libdir loopinv.tcl]
source [file join $quadcode::libdir narrow.tcl]
source [file join $quadcode::libdir pre.tcl]
source [file join $quadcode::libdir ssa.tcl]
source [file join $quadcode::libdir translate.tcl]
source [file join $quadcode::libdir typecheck.tcl]
source [file join $quadcode::libdir upvar.tcl]
source [file join $quadcode::libdir varargs.tcl]
source [file join $quadcode::libdir widen.tcl]

#source [file join $quadcode::libdir exists.tcl]
#source [file join $quadcode::libdir interval.tcl]







>











<











<
<
<
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816

817
818
819
820
821
822
823
824
825
826
827



# types comes first - other modules' initialization can depend on it

source [file join $quadcode::libdir types.tcl]

source [file join $quadcode::libdir abbreviate.tcl]
source [file join $quadcode::libdir aliases.tcl]
source [file join $quadcode::libdir bb.tcl]
source [file join $quadcode::libdir builder.tcl]
source [file join $quadcode::libdir bytecode.tcl]
source [file join $quadcode::libdir callframe.tcl]
source [file join $quadcode::libdir constfold.tcl]
source [file join $quadcode::libdir constjump.tcl]
source [file join $quadcode::libdir copyprop.tcl]
source [file join $quadcode::libdir dbginfo.tcl]
source [file join $quadcode::libdir deadcode.tcl]
source [file join $quadcode::libdir duchain.tcl]
source [file join $quadcode::libdir flatten.tcl]
source [file join $quadcode::libdir fqcmd.tcl]
source [file join $quadcode::libdir inline.tcl]

source [file join $quadcode::libdir jumpthread.tcl]
source [file join $quadcode::libdir liveranges.tcl]
source [file join $quadcode::libdir loopinv.tcl]
source [file join $quadcode::libdir narrow.tcl]
source [file join $quadcode::libdir pre.tcl]
source [file join $quadcode::libdir ssa.tcl]
source [file join $quadcode::libdir translate.tcl]
source [file join $quadcode::libdir typecheck.tcl]
source [file join $quadcode::libdir upvar.tcl]
source [file join $quadcode::libdir varargs.tcl]
source [file join $quadcode::libdir widen.tcl]



Changes to quadcode/translate.tcl.

42
43
44
45
46
47
48









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
104
105
106
107
108
    set quads {};	        # List of instructions under construction
    set quadindex {};		# Dictionary mapping bytecode PC to
    ;				# quadcode PC in the initial translation
    set fixup {};		# Dictionary whose keys are jump targets
    ;				# and the values are lists of quad program
    ;				# counters that jump to them, used to fix up
    ;				# forward jumps.










    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 [lmap x [dict get $bytecode variables] {lindex $x 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}]


    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
    }












    # 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"
	    }
	    # TODO - Should we warn of unreachable code?
	    continue
	}
	lassign [dict get $bytecode stackState $pc] state depth
	my debug-translate {
	    puts "$pc:  ($depth) [my format-bytecode $pc $insn]"
	}

	# Fix up any quads that jump to the current quad
	dict set quadindex $pc [llength $quads]
	if {[dict exists $fixup $pc]} {
	    foreach qi [dict get $fixup $pc] {
		my debug-translate {
		    puts "    fixup $qi to proceed to $pc"
		}
		lset quads $qi 1 [list pc [llength $quads]]
	    }
	    dict unset fixup $pc
	}

	# Determine if the current source line has changed







>
>
>
>
>
>
>
>
>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|
<
|













<

>
>







>
>
>
>
>
>
>
>
>
>
>




















|







42
43
44
45
46
47
48
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
    set quads {};	        # List of instructions under construction
    set quadindex {};		# Dictionary mapping bytecode PC to
    ;				# quadcode PC in the initial translation
    set fixup {};		# Dictionary whose keys are jump targets
    ;				# and the values are lists of quad program
    ;				# counters that jump to them, used to fix up
    ;				# forward jumps.
    set cf [list temp @callframe]
    ;				# Callframe is used in many places, so
    ;				# allow it to be abbreviated
    set catches {};		# Dictionary whose keys are program counters
    ;				# that are the targets of catch exception ranges
    ;				# and whose values are immaterial. Used to
    ;				# generate a 'startCatch' operation at each
    ;				# point where errorInfo and errorCode need
    ;				# to be spoilt.

    my debug-translate {
	puts "Translate bytecode: $originProc"
    }

    # vlist is a list of local variables present in the bytecode.
    set vlist {}
    foreach v [dict get $bytecode variables] {
	if {!("temp" in [lindex $v 0])} {
	    lappend vlist [lindex $v 1]
	}
    }

    # Enumerate the catch targets
    foreach row [dict get $bytecode exception] {
	if {[dict get $row type] eq "catch"} {
	    dict set catches [dict get $row catch] {}
	}
    }

    # Construct a header that sets parameters and provides a fake point
    # to which live-on-entry variables can be attached.
    

    my quads entry $cf [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 $cf $cf]
    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"
	    }
	    # TODO - Should we warn of unreachable code?
	    continue
	}
	lassign [dict get $bytecode stackState $pc] state depth
	my debug-translate {
	    puts "$pc:  ($depth) [my format-bytecode $pc $insn]"
	}

	# Fix up any quads that jump to the current quad
	dict set quadindex $pc [llength $quads]
	if {[dict exists $fixup $pc]} {
	    foreach qi [dict get $fixup $pc] {
		my debug-translate {
		    puts "    fixup $qi to proceed to [llength $quads]"
		}
		lset quads $qi 1 [list pc [llength $quads]]
	    }
	    dict unset fixup $pc
	}

	# Determine if the current source line has changed
129
130
131
132
133
134
135






136
137
138
139
140
141
142
	    }
	    # Issue the directive if there has been a change in script text
	    if {$currentscript ne [dict get $c script]} {
		set currentscript [dict get $c script]
		my quads @debug-script {} [list literal [dict get $c script]]
	    }
	}







	# Translate the current bytecode
	switch -exact -- [lindex $insn 0] {
	    add -
	    bitand -
	    bitor -
	    bitxor -







>
>
>
>
>
>







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
	    }
	    # Issue the directive if there has been a change in script text
	    if {$currentscript ne [dict get $c script]} {
		set currentscript [dict get $c script]
		my quads @debug-script {} [list literal [dict get $c script]]
	    }
	}

	# Add a startCatch to spoil errorCode if this instruction begins
	# an exception range
	if {[dict exists $catches $pc]} {
	    my quads startCatch $cf $cf
	}

	# Translate the current bytecode
	switch -exact -- [lindex $insn 0] {
	    add -
	    bitand -
	    bitor -
	    bitxor -
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
		set chars [list temp [incr depth -1]]
		set v [list temp [incr depth -1]]
		my quads strtrim $v $v $chars [list literal 1]
	    }

	    done {		# End of bytecode
		set v [list temp [incr depth -1]]
		my quads return {} {temp @callframe} $v
	    }
	    returnStk {
		# NOTE! Opposite order to 'returnImm'
		set v [list temp [incr depth -1]]
		set opt [list temp [incr depth -1]]
		set resultVar [list temp $depth]
		my error-quads $pc initException $resultVar $v $opt







|







371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
		set chars [list temp [incr depth -1]]
		set v [list temp [incr depth -1]]
		my quads strtrim $v $v $chars [list literal 1]
	    }

	    done {		# End of bytecode
		set v [list temp [incr depth -1]]
		my quads return {} $cf $v
	    }
	    returnStk {
		# NOTE! Opposite order to 'returnImm'
		set v [list temp [incr depth -1]]
		set opt [list temp [incr depth -1]]
		set resultVar [list temp $depth]
		my error-quads $pc initException $resultVar $v $opt
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
463
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
517
518
519
520
521
522
523
524

525
526
527
528
529

530
531
532
533
534
535

536

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
567
568
569
570
571
572

573
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
		set res [list temp $depth]
		my quads foreachIter $res $pair
		set n [expr {$depth - [llength $assign] - 3}]
		set lists [lmap group $assign {
		    list temp [incr n]
		}]
		set idx [list temp [expr {$depth + 1}]]

		foreach varGroup $assign list $lists {
		    if {[llength $varGroup] == 1} {
			my quads copy $idx $res
		    } else {
			my quads mult $idx $res [list literal [llength $varGroup]]
		    }
		    foreach varIndex $varGroup {
			set var [my index-to-var $varIndex]

			my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
			    "can't set \"%s\": variable is array"
			my quads listIndex $var $list $idx
			my quads extractMaybe $var $var

			my quads add $idx $idx [list literal 1]
		    }
		}

		my quads foreachMayStep $res $pair
		my quads foreachAdvance $pair $pair
		set target [expr {$pc + $jumpOffset}]
		my generate-jump $target true $res
	    }
	    foreach_end {
		# No special action needed; just a fancy pop, and that's
		# handled by the stack calculation code.
	    }
	    lmap_collect {
		set auxNum [lindex $insn 1]
		set aux [lindex [dict get $bytecode auxiliary] $auxNum]
		dict with aux {}
		set collector [list temp [expr {$depth - [llength $assign] - 4}]]
		set value [list temp [incr depth -1]]
		my quads listAppend $collector $collector $value
		my quads extractMaybe $collector $collector
	    }
	    dictFirst {
		set var [my index-to-var [lindex $insn 1]]

		set dict [list temp [incr depth -1]]
		set value [list temp $depth]
		set key [list temp [incr depth]]
		set done [list temp [incr depth]]
		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my error-quads $pc dictIterStart $var $dict
		my quads dictIterKey $key $var
		my quads dictIterValue $value $var
		my quads dictIterDone $done $var
	    }
	    dictNext {
		set var [my index-to-var [lindex $insn 1]]
		set value [list temp $depth]
		set key [list temp [incr depth]]
		set done [list temp [incr depth]]

		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my quads dictIterNext $var $var
		my quads dictIterKey $key $var
		my quads dictIterValue $value $var
		my quads dictIterDone $done $var
	    }
	    dictUpdateStart {
		set var [my index-to-var [lindex $insn 1]]

		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]
		set mid [list temp opnd3]
		set updating [list temp opnd4]
		set val [list temp [incr depth -1]]
		set idx 0

		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't write \"%s\": variable is array"
		my quads copy $updating $var
		foreach v [dict get $aux variables] {
		    set r [my index-to-var $v]

		    my error-quads $pc listIndex $key $val [list literal $idx]
		    incr idx
		    # Convert an ARRAY into a NEXIST here; ARRAY is unreadable
		    # so treat as NEXIST...
		    my quads arrayExists $isary $r
		    set n [llength $quads]

		    my quads jumpFalse [list pc [expr {$n + 3}]] $isary

		    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
		# The result will be discarded
	    }
	    incrScalar1Imm {
		set result [list temp $depth]
		set var [my index-to-var [lindex $insn 1]]
		set delta [lindex $insn 2]

		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "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}







>








>




>



>




















>
















>









>







>


>




>


>











>





>






>

>

>

>
|
>

|
>


>






>
>
>
>






>




>













>








>






>







>







>













>






>












>







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
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
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
567
568
569
570
571
572
573
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
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
		set res [list temp $depth]
		my quads foreachIter $res $pair
		set n [expr {$depth - [llength $assign] - 3}]
		set lists [lmap group $assign {
		    list temp [incr n]
		}]
		set idx [list temp [expr {$depth + 1}]]
		set toUpdate {}
		foreach varGroup $assign list $lists {
		    if {[llength $varGroup] == 1} {
			my quads copy $idx $res
		    } else {
			my quads mult $idx $res [list literal [llength $varGroup]]
		    }
		    foreach varIndex $varGroup {
			set var [my index-to-var $varIndex]
			my generate-move-from-callframe $var
			my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
			    "can't set \"%s\": variable is array"
			my quads listIndex $var $list $idx
			my quads extractMaybe $var $var
			lappend toUpdate [lreplace $var 0 0 literal] $var
			my quads add $idx $idx [list literal 1]
		    }
		}
		my update-in-callframe {*}$toUpdate
		my quads foreachMayStep $res $pair
		my quads foreachAdvance $pair $pair
		set target [expr {$pc + $jumpOffset}]
		my generate-jump $target true $res
	    }
	    foreach_end {
		# No special action needed; just a fancy pop, and that's
		# handled by the stack calculation code.
	    }
	    lmap_collect {
		set auxNum [lindex $insn 1]
		set aux [lindex [dict get $bytecode auxiliary] $auxNum]
		dict with aux {}
		set collector [list temp [expr {$depth - [llength $assign] - 4}]]
		set value [list temp [incr depth -1]]
		my quads listAppend $collector $collector $value
		my quads extractMaybe $collector $collector
	    }
	    dictFirst {
		set var [my index-to-var [lindex $insn 1]]
		my generate-move-from-callframe $var
		set dict [list temp [incr depth -1]]
		set value [list temp $depth]
		set key [list temp [incr depth]]
		set done [list temp [incr depth]]
		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my error-quads $pc dictIterStart $var $dict
		my quads dictIterKey $key $var
		my quads dictIterValue $value $var
		my quads dictIterDone $done $var
	    }
	    dictNext {
		set var [my index-to-var [lindex $insn 1]]
		set value [list temp $depth]
		set key [list temp [incr depth]]
		set done [list temp [incr depth]]
		my generate-move-from-callframe $var
		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my quads dictIterNext $var $var
		my quads dictIterKey $key $var
		my quads dictIterValue $value $var
		my quads dictIterDone $done $var
	    }
	    dictUpdateStart {
		set var [my index-to-var [lindex $insn 1]]
		my generate-move-from-callframe $var
		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-move-from-callframe $r
		    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]
		set mid [list temp opnd3]
		set updating [list temp opnd4]
		set val [list temp [incr depth -1]]
		set idx 0
		my generate-move-from-callframe $var
		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't write \"%s\": variable is array"
		my quads copy $updating $var
		foreach v [dict get $aux variables] {
		    set r [my index-to-var $v]
		    my generate-move-from-callframe $r
		    my error-quads $pc listIndex $key $val [list literal $idx]
		    incr idx
		    # Convert an ARRAY into a NEXIST here; ARRAY is unreadable
		    # so treat as NEXIST...
		    my quads arrayExists $isary $r
		    set n [llength $quads]
		    # 0
		    my quads jumpFalse [list pc [expr {$n + 3}]] $isary
		    # 1
		    my quads copy $mid Nothing
		    # 2
		    my quads jump [list pc [expr {$n + 4}]]
		    # 3
		    my quads copy $mid $r
		    # 4
		    # 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
		if {[lindex $var 0] eq "var"} {
		    my quads moveToCallFrame $cf $cf \
			[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-move-from-callframe $ary
		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
		# The result will be discarded
	    }
	    incrScalar1Imm {
		set result [list temp $depth]
		set var [my index-to-var [lindex $insn 1]]
		set delta [lindex $insn 2]
		my generate-move-from-callframe $var
		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "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-move-from-callframe $var
		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-move-from-callframe $ary
		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-move-from-callframe $ary
		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}
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
		# TODO: Typecheck: need lists in $var and $listvalue
		my generate-callframe-op $pc \
		    directArrayLappendList $var $var $elem $listvalue
	    }
	    existStk {
		set var [list temp [incr depth -1]]
		# TODO: This assumes we're dealing with qualified names!
		my quads directExists $var {temp @callframe} $var
	    }
	    existArrayStk {
		set elem [list temp [incr depth -1]]
		set var [list temp [incr depth -1]]
		# TODO: This assumes we're dealing with qualified names!
		my quads directArrayExists $var {temp @callframe} $var $elem
	    }
	    loadStk {
		set var [list temp [incr depth -1]]
		# TODO: This assumes we're dealing with qualified names!
		my generate-callframe-op $pc directGet $var $var
	    }
	    loadArrayStk {







|





|







804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
		# TODO: Typecheck: need lists in $var and $listvalue
		my generate-callframe-op $pc \
		    directArrayLappendList $var $var $elem $listvalue
	    }
	    existStk {
		set var [list temp [incr depth -1]]
		# TODO: This assumes we're dealing with qualified names!
		my quads directExists $var $cf $var
	    }
	    existArrayStk {
		set elem [list temp [incr depth -1]]
		set var [list temp [incr depth -1]]
		# TODO: This assumes we're dealing with qualified names!
		my quads directArrayExists $var $cf $var $elem
	    }
	    loadStk {
		set var [list temp [incr depth -1]]
		# TODO: This assumes we're dealing with qualified names!
		my generate-callframe-op $pc directGet $var $var
	    }
	    loadArrayStk {
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
857
858

859
860
861
862
863
864
865
		set var [my index-to-var [lindex $insn 2]]
		set val [list temp [incr depth -1]]
		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 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} {







|
>





>










>





>






>





>






>





>







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
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
		set var [my index-to-var [lindex $insn 2]]
		set val [list temp [incr depth -1]]
		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-move-from-callframe $var
		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-move-from-callframe $var
		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-move-from-callframe $var
		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-move-from-callframe $var
		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} {
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
		#	  the invoked procedure raises an error
		set qd [list [list temp [expr {$depth + $acount}]]]
		for {set i $rcount} {$i < $acount} {incr i} {
		    lappend qd [list temp [expr {$depth + $i}]]
		}
		my generate-function-param-check $pc $qd
		# generate the call itself
		my quads invoke {temp @callframe} {temp @callframe} {*}$qd
		my quads retrieveResult {temp @exception} {temp @callframe}
		my quads extractCallFrame {temp @callframe} {temp @callframe}
		my generate-jump [my exception-target $pc catch] maybe \
		    {temp @exception}
		my quads extractMaybe $result {temp @exception}
	    }
	    invokeStk1 - invokeStk4 {
		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} {
		    lappend qd [list temp [expr {$depth + $i}]]
		}
		my generate-function-param-check $pc $qd
		# generate the call itself
		my quads invoke {temp @callframe} {temp @callframe} {*}$qd
		my quads retrieveResult {temp @exception} {temp @callframe}
		my quads extractCallFrame {temp @callframe} {temp @callframe}
		my generate-jump [my exception-target $pc catch] maybe \
		    {temp @exception} 
		my quads extractMaybe $result {temp @exception}
	    }
	    jump1 - jump4 {
		switch -exact -- [lindex $insn 1 0] {
		    pc {







|
|
|














|
|
|







990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
		#	  the invoked procedure raises an error
		set qd [list [list temp [expr {$depth + $acount}]]]
		for {set i $rcount} {$i < $acount} {incr i} {
		    lappend qd [list temp [expr {$depth + $i}]]
		}
		my generate-function-param-check $pc $qd
		# generate the call itself
		my quads invoke $cf $cf {*}$qd
		my quads retrieveResult {temp @exception} $cf
		my quads extractCallFrame $cf $cf
		my generate-jump [my exception-target $pc catch] maybe \
		    {temp @exception}
		my quads extractMaybe $result {temp @exception}
	    }
	    invokeStk1 - invokeStk4 {
		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} {
		    lappend qd [list temp [expr {$depth + $i}]]
		}
		my generate-function-param-check $pc $qd
		# generate the call itself
		my quads invoke $cf $cf {*}$qd
		my quads retrieveResult {temp @exception} $cf
		my quads extractCallFrame $cf $cf
		my generate-jump [my exception-target $pc catch] maybe \
		    {temp @exception} 
		my quads extractMaybe $result {temp @exception}
	    }
	    jump1 - jump4 {
		switch -exact -- [lindex $insn 1 0] {
		    pc {
1008
1009
1010
1011
1012
1013
1014

1015
1016
1017
1018
1019
1020
1021

1022
1023
1024
1025
1026
1027
1028
1029

1030
1031
1032
1033
1034
1035
1036
1037
1038

1039
1040
1041
1042
1043
1044
1045
		    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]
		set var [my index-to-var [lindex $insn 1]]

		my generate-existence-check $pc $var
		my generate-scalar-check $pc $var {TCL READ VARNAME} \
		    "can't read \"%s\": variable is array"
		my quads copy $result $var
	    }
	    loadArray1 -
	    loadArray4 {	# Load from an array
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 1]]

		my generate-existence-check $pc $ary
		my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \
		    "can't read \"%s(%s)\": variable isn't array"
		set res $idx
		my quads arrayGet $res $ary $idx
		set name [lindex $ary 1](...)
		# FIXME: error variable name







>







>








>









>







1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
		    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 generate-move-from-callframe $var
		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 generate-move-from-callframe $ary
		my quads initArrayIfNotExists $tmp $ary
		my quads arrayElementExists $result $tmp $idx
	    }

	    loadScalar1 -
	    loadScalar4 {	# Load a variable
		set result [list temp $depth]
		set var [my index-to-var [lindex $insn 1]]
		my generate-move-from-callframe $var
		my generate-existence-check $pc $var
		my generate-scalar-check $pc $var {TCL READ VARNAME} \
		    "can't read \"%s\": variable is array"
		my quads copy $result $var
	    }
	    loadArray1 -
	    loadArray4 {	# Load from an array
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 1]]
		my generate-move-from-callframe $ary
		my generate-existence-check $pc $ary
		my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \
		    "can't read \"%s(%s)\": variable isn't array"
		set res $idx
		my quads arrayGet $res $ary $idx
		set name [lindex $ary 1](...)
		# FIXME: error variable name
1087
1088
1089
1090
1091
1092
1093

1094
1095
1096

1097
1098
1099
1100
1101
1102
1103

1104
1105
1106
1107
1108

1109
1110
1111
1112
1113
1114
1115
		# For now, startCommand does nothing
		# lappend quads startCommand
	    }
	    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 \







>



>







>





>







1174
1175
1176
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
1206
		# For now, startCommand does nothing
		# lappend quads startCommand
	    }
	    storeScalar1 -
	    storeScalar4 {	# Store a variable
		incr depth -1
		set var [my index-to-var [lindex $insn 1]]
		my generate-move-from-callframe $var
		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-move-from-callframe $ary
		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 \
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
1206
1207

1208
1209
1210
1211
1212
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
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
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
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
		set v0 [list temp [incr depth -1]]
		set r $v0
		my error-quads $pc [lindex $insn 0] $r $v0
	    }
	    appendScalar1 - appendScalar4 {
		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 {}}
		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]]
		}
		set result [list temp $depth]
		if {$op eq "concatStk"} {
		    set op "concat"
		}
		my quads $op $result {*}[lreverse $strcatvals]
	    }
	    lappendScalar1 - lappendScalar4 {
		set val [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 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 {temp @callframe} $ary
	    }
	    arrayMakeStk {
		set ary [list temp [incr depth -1]]
		set res [list temp $depth]
		my generate-callframe-op $pc directMakeArray $res $ary
	    }
	    variable {
		set var [my index-to-var [lindex $insn 1]]
		set name [list temp [incr depth -1]]
		my quads [lindex $insn 0] {temp @callframe} {temp @callframe} \
		    [list literal [lindex $var 1]] $name
		my quads retrieveResult {temp @exception} {temp @callframe}
		my quads extractCallFrame {temp @callframe} {temp @callframe}
		my generate-jump [my exception-target $pc catch] \
		    maybe {temp @exception}
	    }
	    nsupvar - upvar {
		set var [my index-to-var [lindex $insn 1]]
		set name [list temp [incr depth -1]]
		set context [list temp [incr depth -1]]
		my quads [lindex $insn 0] {temp @callframe} {temp @callframe} \
		    [list literal [lindex $var 1]] $context $name
		my quads retrieveResult {temp @exception} {temp @callframe}
		my quads extractCallFrame {temp @callframe} {temp @callframe}
		my generate-jump [my exception-target $pc catch] \
		    maybe {temp @exception}
	    }
	    currentNamespace {
		my quads copy [list temp $depth] \
		    [list literal [dict get $bytecode namespace]]
	    }
	    infoLevelArgs {
		set value [list temp [incr depth -1]]
		set r [list temp $depth]
		my generate-arith-domain-check $pc [lindex $insn 0] $value
		my quads purify {temp opd0} $value
		my error-quads $pc frameArgs $r {temp opd0} {temp @callframe}
	    }
	    infoLevelNumber {
		set r [list temp $depth]
		my quads frameDepth $r {temp @callframe}
	    }
	    expandStart {
		# do nothing
	    }
	    expandStkTop {
		set r [list temp [incr depth -1]]
		my error-quads $pc verifyList $r $r
		my quads expand $r $r
	    }
	    invokeExpanded {
		lassign [dict get $bytecode stackState $state] headWas depthWas
		set result [list temp $depthWas]
		set qd {}
		for {set i $depthWas} {$i < $depth} {incr i} {
		    lappend qd [list temp $i]
		}
		my quads \
		    invokeExpanded {temp @callframe} {temp @callframe} {*}$qd
		my quads retrieveResult {temp @exception} {temp @callframe}
		my quads extractCallFrame {temp @callframe} {temp @callframe}
		my generate-jump [my exception-target $pc catch] maybe \
		    {temp @exception}
		my quads extractMaybe $result {temp @exception}
	    }
	    default {
		# TODO - Many more instructions
		lappend errors $sourcefile $currentline $currentscript \
		    "Bytecode instruction '[lindex $insn 0]'\
                     is not implemented."
	    }
	}
    }

    if {[dict exists $fixup -1]} {
	foreach q [dict get $fixup -1] {
	    lset quads $q 1 [list pc [llength $quads]]
	}
	# let the flow analysis figure out whether this is confluent!
	# lappend quads confluence
	my quads returnCode [set code [list temp 0]] {temp @exception}
	my quads procLeave $code $code \
	    [list literal [namespace tail $originProc]]
	my quads return {} {temp @callframe} $code
	dict unset fixup -1
    }
    if {[dict size $fixup] > 0} {
	error "Failed to fix jumps at [join [dict keys $fixup] ,]"
    }
    if {[llength $errors] > 1} {
	set result {}







>






>







>








>

















>






>





>






>







>


|





>







>









>










>





>



>




|









|

|
|







|

|
|












|



|

















|
|
|

















|
|



|







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
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
		set v0 [list temp [incr depth -1]]
		set r $v0
		my error-quads $pc [lindex $insn 0] $r $v0
	    }
	    appendScalar1 - appendScalar4 {
		set val [list temp [incr depth -1]]
		set var [my index-to-var [lindex $insn 1]]
		my generate-move-from-callframe $var
		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-move-from-callframe $ary
		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]]
		}
		set result [list temp $depth]
		if {$op eq "concatStk"} {
		    set op "concat"
		}
		my quads $op $result {*}[lreverse $strcatvals]
	    }
	    lappendScalar1 - lappendScalar4 {
		set val [list temp [incr depth -1]]
		set var [my index-to-var [lindex $insn 1]]
		set res [list temp $depth]
		my generate-move-from-callframe $var
		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-move-from-callframe $var
		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-move-from-callframe $ary
		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 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-move-from-callframe $ary
		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 generate-move-from-callframe $ary
		set res [list temp $depth]
		my quads arrayExists $res $ary
	    }
	    arrayMakeImm {
		set ary [my index-to-var [lindex $insn 1]]
		my generate-move-from-callframe $ary
		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 $ary 1]] $ary
	    }
	    arrayExistsStk {
		set ary [list temp [incr depth -1]]
		set res [list temp $depth]
		my error-quads $pc directIsArray $res $cf $ary
	    }
	    arrayMakeStk {
		set ary [list temp [incr depth -1]]
		set res [list temp $depth]
		my generate-callframe-op $pc directMakeArray $res $ary
	    }
	    variable {
		set var [my index-to-var [lindex $insn 1]]
		set name [list temp [incr depth -1]]
		my quads [lindex $insn 0] $cf $cf \
		    [list literal [lindex $var 1]] $name
		my quads retrieveResult {temp @exception} $cf
		my quads extractCallFrame $cf $cf
		my generate-jump [my exception-target $pc catch] \
		    maybe {temp @exception}
	    }
	    nsupvar - upvar {
		set var [my index-to-var [lindex $insn 1]]
		set name [list temp [incr depth -1]]
		set context [list temp [incr depth -1]]
		my quads [lindex $insn 0] $cf $cf \
		    [list literal [lindex $var 1]] $context $name
		my quads retrieveResult {temp @exception} $cf
		my quads extractCallFrame $cf $cf
		my generate-jump [my exception-target $pc catch] \
		    maybe {temp @exception}
	    }
	    currentNamespace {
		my quads copy [list temp $depth] \
		    [list literal [dict get $bytecode namespace]]
	    }
	    infoLevelArgs {
		set value [list temp [incr depth -1]]
		set r [list temp $depth]
		my generate-arith-domain-check $pc [lindex $insn 0] $value
		my quads purify {temp opd0} $value
		my error-quads $pc frameArgs $r {temp opd0} $cf
	    }
	    infoLevelNumber {
		set r [list temp $depth]
		my quads frameDepth $r $cf
	    }
	    expandStart {
		# do nothing
	    }
	    expandStkTop {
		set r [list temp [incr depth -1]]
		my error-quads $pc verifyList $r $r
		my quads expand $r $r
	    }
	    invokeExpanded {
		lassign [dict get $bytecode stackState $state] headWas depthWas
		set result [list temp $depthWas]
		set qd {}
		for {set i $depthWas} {$i < $depth} {incr i} {
		    lappend qd [list temp $i]
		}
		my quads \
		    invokeExpanded $cf $cf {*}$qd
		my quads retrieveResult {temp @exception} $cf
		my quads extractCallFrame $cf $cf
		my generate-jump [my exception-target $pc catch] maybe \
		    {temp @exception}
		my quads extractMaybe $result {temp @exception}
	    }
	    default {
		# TODO - Many more instructions
		lappend errors $sourcefile $currentline $currentscript \
		    "Bytecode instruction '[lindex $insn 0]'\
                     is not implemented."
	    }
	}
    }

    if {[dict exists $fixup -1]} {
	foreach q [dict get $fixup -1] {
	    lset quads $q 1 [list pc [llength $quads]]
	}
	# spoil errorCode and errorInfo
	my quads startCatch $cf $cf
	my quads returnCode [set code [list temp 0]] {temp @exception}
	my quads procLeave $code $code \
	    [list literal [namespace tail $originProc]]
	my quads return {} $cf $code
	dict unset fixup -1
    }
    if {[dict size $fixup] > 0} {
	error "Failed to fix jumps at [join [dict keys $fixup] ,]"
    }
    if {[llength $errors] > 1} {
	set result {}
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
oo::define quadcode::transformer method index-to-var {varIndex} {
    if {[string match "%*" $varIndex]} {
	set varIndex [string range $varIndex 1 end]
    }
    lassign [lindex [dict get $bytecode variables] $varIndex] flags name
    if {"temp" in $flags} {
	# Variable name is not legal for Tcl scalar local variables
	return [list var ($varIndex)]
    }
    return [list var $name]
}

# exception-target --
#
#	Locate where an exception should go to from the current PC. Do not







|







1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
oo::define quadcode::transformer method index-to-var {varIndex} {
    if {[string match "%*" $varIndex]} {
	set varIndex [string range $varIndex 1 end]
    }
    lassign [lindex [dict get $bytecode variables] $varIndex] flags name
    if {"temp" in $flags} {
	# Variable name is not legal for Tcl scalar local variables
	return [list temp @var$varIndex]
    }
    return [list var $name]
}

# exception-target --
#
#	Locate where an exception should go to from the current PC. Do not
1542
1543
1544
1545
1546
1547
1548



















1549
1550
1551
1552
1553
1554
1555
    if {[llength $args] == 2} {
	lassign $args type var
	my quads jump[string totitle $type] $target $var
    } else {
	my quads jump $target
    }
}




















# generate-existence-check --
#
#	Generates a check to make sure that a variable exists, and
#	appends it to the list of quadcodes being built. Do not call from
#	anywhere but bytecode-to-quads!
#







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    if {[llength $args] == 2} {
	lassign $args type var
	my quads jump[string totitle $type] $target $var
    } else {
	my quads jump $target
    }
}

# generate-move-from-callframe --
#
#	Generates a 'moveFromCallFrame' instruction for a given variable.
#
# Parameters:
#	var - Variable to load
#
# Results:
#	None.
#
# Side effects:
#	Emits the quad

oo::define quadcode::transformer method generate-move-from-callframe {var} {
    if {[lindex $var 0] ne "var"} return
    my quads moveFromCallFrame $var {temp @callframe} \
	[list literal [lindex $var 1]]
}

# generate-existence-check --
#
#	Generates a check to make sure that a variable exists, and
#	appends it to the list of quadcodes being built. Do not call from
#	anywhere but bytecode-to-quads!
#
1613
1614
1615
1616
1617
1618
1619








1620
1621
1622
1623
1624
1625
1626
#
# Results:
#	None.
#
# Side effects:
#	Emits a sequence that tests the variable's type and throws the
#	requested error if it is incorrect.









oo::define quadcode::transformer method generate-array-check {pc var idx error msg} {

    set varname [lindex $var 1]
    ;				# Name of the variable being checked

    set ok [list pc [expr {[llength $quads] + 11}]]







>
>
>
>
>
>
>
>







1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
#
# Results:
#	None.
#
# Side effects:
#	Emits a sequence that tests the variable's type and throws the
#	requested error if it is incorrect.
#
# Notes:
#	A variable that does not exist will pass both the scalar check
#	and the array check.
#	When writing a variable, the check will determine
#	whether write will succeed or be rejected.
#	When reading a variable, these checks must be paired with an
#	existence check.

oo::define quadcode::transformer method generate-array-check {pc var idx error msg} {

    set varname [lindex $var 1]
    ;				# Name of the variable being checked

    set ok [list pc [expr {[llength $quads] + 11}]]
1830
1831
1832
1833
1834
1835
1836





























1837
1838
1839
1840
1841
1842
1843
	my generate-jump $target
	# 5 - ok:
        my quads [list purifyParam $i] $val $val $functionName
	# 6
	# (next instruction)
	
    }





























}

# quads --
#
#	Generate the given quadcode.
#
# Parameters:







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
	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} {
    set q {moveToCallFrame {temp @callframe} {temp @callframe}}
    set need 0
    foreach {name value} $args {
	if {[lindex $value 0] eq "var"} {
	    lappend q $name $value
	    set need 1
	}
    }
    if {$need} {
	my quads {*}$q
    }
    return
}

# quads --
#
#	Generate the given quadcode.
#
# Parameters:
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878


























1879
1880
1881
1882
1883
1884
1885
1886
# Results:
#	None.

oo::define quadcode::transformer method error-quads {pc opcode result args} {
    my quads $opcode {temp @exception} {*}$args
    set target [my exception-target $pc catch]
    my generate-jump $target maybe {temp @exception}
    my quads extractMaybe {temp @exception} {temp @exception}
    my quads copy $result {temp @exception}
    return
}



























# interp alias {} tcl::mathfunc::istype {} ::dataType::isa

# Local Variables:
# mode: tcl
# fill-column: 78
# auto-fill-function: nil
# End:







<
|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








2030
2031
2032
2033
2034
2035
2036

2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
# Results:
#	None.

oo::define quadcode::transformer method error-quads {pc opcode result args} {
    my quads $opcode {temp @exception} {*}$args
    set target [my exception-target $pc catch]
    my generate-jump $target maybe {temp @exception}

    my quads extractMaybe $result {temp @exception}
    return
}

# callframe-error-quads --
#
#	Generate the given quadcode, and the sequence that intercepts
#	its errors and unpacks its (callframe, maybe result} tuple.
#
# Parameters:
#	pc - Program counter from the original bytecode
#	opcode - Opcode being emitted
#	result - Result of the operation, which must be CALLFRAME FAIL SOMETHING
#	args - Inputs to the operation.
#
# Results:
#	None

oo::define quadcode::transformer method callframe-error-quads {pc opcode result
							       args} {

    my quads $opcode {temp @tuple} {temp @callframe} $args
    my quads extractCallFrame {temp @callframe} {temp @tuple}
    my quads retrieveResult {temp @exception} {temp @tuple}
    set target [my exception-target $pc catch]
    my generate-jump $target maybe {temp @exception}
    my quads extractMaybe $result {temp @exception}
    
}

# interp alias {} tcl::mathfunc::istype {} ::dataType::isa

# Local Variables:
# mode: tcl
# fill-column: 78
# auto-fill-function: nil
# End:

Changes to quadcode/types.tcl.

407
408
409
410
411
412
413
414
415
416
417
418
419
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
    namespace upvar ::quadcode::dataType BOTTOM BOTTOM FAIL FAIL STRING STRING

    # Initialize all types to BOTTOM
    set types {}
    dict for {v -} $udchain {
	dict set types $v $BOTTOM
    }
    dict set types return $BOTTOM

    # Put all basic blocks on the worklist for processing in depth-first
    # order
    set worklist {}
    for {set b [expr {[llength $bbcontent]-1}]} {$b >= 0} {incr b -1} {
	lappend worklist $b
    }

    # Process blocks from the worklist

    while {[llength $worklist] > 0} {
	set b [lindex $worklist end]
	set worklist [lrange $worklist[set worklist {}] 0 end-1]
	set content [lindex $bbcontent $b]

	# Process instructions in each block from top to bottom
	set pc 0
	foreach q $content {

	    my debug-inferTypes {
		puts "$b:$pc: $q"
	    }
	    switch -exact -- [lindex $q 0] {
		return {
		    dict set types return \
			[expr {[dict get $types return]
			       | [typeOfOperand $types [lindex $q 3]]}]
		    my debug-inferTypes {
			puts "    return: [nameOfType [dict get $types return]]"
		    }
		}
		default {
		    set rvar [lindex $q 1]
		    if {[lindex $rvar 0] in {"var" "temp"}} {
			set type [my typeOfResult $q]
			if {$type != [dict get $types $rvar]} {
			    my debug-inferTypes {
				puts "   $rvar: [nameOfType $type]"


			    }
			    dict set types $rvar $type
			    if {[dict exists $duchain $rvar]} {
				dict for {use -} [dict get $duchain $rvar] {
				    set idx [lsearch -sorted -integer \
						 -decreasing -bisect \
						 $worklist $use]







|
















|

>



















>
>







407
408
409
410
411
412
413
414
415
416
417
418
419
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
    namespace upvar ::quadcode::dataType BOTTOM BOTTOM FAIL FAIL STRING STRING

    # Initialize all types to BOTTOM
    set types {}
    dict for {v -} $udchain {
	dict set types $v $BOTTOM
    }
    dict set types return $FAIL

    # Put all basic blocks on the worklist for processing in depth-first
    # order
    set worklist {}
    for {set b [expr {[llength $bbcontent]-1}]} {$b >= 0} {incr b -1} {
	lappend worklist $b
    }

    # Process blocks from the worklist

    while {[llength $worklist] > 0} {
	set b [lindex $worklist end]
	set worklist [lrange $worklist[set worklist {}] 0 end-1]
	set content [lindex $bbcontent $b]

	# Process instructions in each block from top to bottom
	set pc -1
	foreach q $content {
	    incr pc
	    my debug-inferTypes {
		puts "$b:$pc: $q"
	    }
	    switch -exact -- [lindex $q 0] {
		return {
		    dict set types return \
			[expr {[dict get $types return]
			       | [typeOfOperand $types [lindex $q 3]]}]
		    my debug-inferTypes {
			puts "    return: [nameOfType [dict get $types return]]"
		    }
		}
		default {
		    set rvar [lindex $q 1]
		    if {[lindex $rvar 0] in {"var" "temp"}} {
			set type [my typeOfResult $q]
			if {$type != [dict get $types $rvar]} {
			    my debug-inferTypes {
				puts "   $rvar: [nameOfType $type]"
				puts "   was [nameOfType \
                                                  [dict get $types $rvar]]"
			    }
			    dict set types $rvar $type
			    if {[dict exists $duchain $rvar]} {
				dict for {use -} [dict get $duchain $rvar] {
				    set idx [lsearch -sorted -integer \
						 -decreasing -bisect \
						 $worklist $use]
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
	    return [lindex $q 0 1]
	}
	narrowToType {
	    set targetTypeCode [lindex $q 0 1]
	    return [quadcode::dataType::typeIntersect $targetTypeCode \
			[typeOfOperand $types [lindex $q 2]]]
	}
	entry {
	    return $CALLFRAME
	}
	param {
	    if {[lindex $q 2 1] < [llength $ptype]} {
		return [lindex $ptype [lindex $q 2 1]]
	    } else {
		return $STRING







|







513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
	    return [lindex $q 0 1]
	}
	narrowToType {
	    set targetTypeCode [lindex $q 0 1]
	    return [quadcode::dataType::typeIntersect $targetTypeCode \
			[typeOfOperand $types [lindex $q 2]]]
	}
	entry - extractCallFrame {
	    return $CALLFRAME
	}
	param {
	    if {[lindex $q 2 1] < [llength $ptype]} {
		return [lindex $ptype [lindex $q 2 1]]
	    } else {
		return $STRING
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
	strcmp -
	strfind -
	strlen -
	strrfind -
	frameDepth {
	    return $INT
	}
	copy {
	    return [typeOfOperand $types [lindex $q 2]]
	}
	purify {
	    return [expr {[typeOfOperand $types [lindex $q 2]] & ~$IMPURE}]
	}
	purifyParam {
	    # Will be replaced with 'purify' when type is known, but must







|







580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
	strcmp -
	strfind -
	strlen -
	strrfind -
	frameDepth {
	    return $INT
	}
	copy - startCatch {
	    return [typeOfOperand $types [lindex $q 2]]
	}
	purify {
	    return [expr {[typeOfOperand $types [lindex $q 2]] & ~$IMPURE}]
	}
	purifyParam {
	    # Will be replaced with 'purify' when type is known, but must
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
	}
	invokeExpanded {
	    # We can eliminate callframe in a smaller set of cases than
	    # with 'invoke' - but punt for now.
	    set inty [typeOfOperand $types [lindex $q 2]]
	    return [expr {($inty & $CALLFRAME) | $FAIL | $STRING}]
	}
	callFrameNop - startCatch {
	    return $CALLFRAME
	}
	nsupvar - upvar - variable {
	    return [expr {$CALLFRAME | $ZEROONE | $FAIL}]
	}
	retrieveResult {
	    # Pull from the callframe of the earlier 'invoke'
	    return [expr {[typeOfOperand $types [lindex $q 2]] & ~$CALLFRAME}]
	}
	extractCallFrame {
	    # Trim the non-callframe part
	    return $CALLFRAME
	}
	list - unshareList -
	result - returnOptions -
	dictIterKey - dictIterValue -
	concat - strcat - strmap - strtrim - strcase {
	    return $STRING
	}
	foreachAdvance {







<
<
<







<
<
<
<







699
700
701
702
703
704
705



706
707
708
709
710
711
712




713
714
715
716
717
718
719
	}
	invokeExpanded {
	    # We can eliminate callframe in a smaller set of cases than
	    # with 'invoke' - but punt for now.
	    set inty [typeOfOperand $types [lindex $q 2]]
	    return [expr {($inty & $CALLFRAME) | $FAIL | $STRING}]
	}



	nsupvar - upvar - variable {
	    return [expr {$CALLFRAME | $ZEROONE | $FAIL}]
	}
	retrieveResult {
	    # Pull from the callframe of the earlier 'invoke'
	    return [expr {[typeOfOperand $types [lindex $q 2]] & ~$CALLFRAME}]
	}




	list - unshareList -
	result - returnOptions -
	dictIterKey - dictIterValue -
	concat - strcat - strmap - strtrim - strcase {
	    return $STRING
	}
	foreachAdvance {
859
860
861
862
863
864
865














866
867
868
869
870
871
872
	    }
	}
	default {
	    error "What is the type of $opd in [info level -1]?"
	}
    }
}















# typeOfLiteral --
#
#	Determines whether a literal represents a number, and returns
#	its type.
#
# Parameters:







>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	    }
	}
	default {
	    error "What is the type of $opd in [info level -1]?"
	}
    }
}

# oo::transformer method typeOfOperand --
#
#	Looks up the type of an operand
#
# Parameters:
#	opd - Operand to query
#
# Results:
#	Returns the type code

oo::define quadcode::transformer method typeOfOperand {opd} {
    return [quadcode::typeOfOperand $types $opd]
}

# typeOfLiteral --
#
#	Determines whether a literal represents a number, and returns
#	its type.
#
# Parameters:

Changes to quadcode/upvar.tcl.

184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#           {global} - The variable is known to be in global or
#                      namespace scope, not in the callframe.
#           {nonlocal} - The variable may be in the callframe of an
#                        outer caller, so calling this procedure might
#                        have nonlocal effects.
#
# Operations that change the aliasing status of one or more variables:
#    callFrameNop
#    extractCallFrame
#    moveToCallFrame
#       Do noting about aliasing, simply copy the aliasing information from
#       the source callframe to the destination callframe.
#    entry -
#       On entry, no variable is an alias
#    invoke -







<







184
185
186
187
188
189
190

191
192
193
194
195
196
197
#           {global} - The variable is known to be in global or
#                      namespace scope, not in the callframe.
#           {nonlocal} - The variable may be in the callframe of an
#                        outer caller, so calling this procedure might
#                        have nonlocal effects.
#
# Operations that change the aliasing status of one or more variables:

#    extractCallFrame
#    moveToCallFrame
#       Do noting about aliasing, simply copy the aliasing information from
#       the source callframe to the destination callframe.
#    entry -
#       On entry, no variable is an alias
#    invoke -
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
	    lassign $q opcode result arg1 arg2

	    # resFrame, if set is the alias info for the new quad.
	    unset -nocomplain resFrame

	    # Analyze individual quads
	    switch -exact -- [lindex $opcode 0] {
		callFrameNop -
		extractCallFrame -
		invoke -
		startCatch {

		    # These instructions do not change aliases, so copy
		    # the input frame to the result frame.
		    if {![dict exists $aliasInfo $arg1]} {
			set resFrame {}
		    } else {
			set resFrame [dict get $aliasInfo $arg1]







<

|
<







241
242
243
244
245
246
247

248
249

250
251
252
253
254
255
256
	    lassign $q opcode result arg1 arg2

	    # resFrame, if set is the alias info for the new quad.
	    unset -nocomplain resFrame

	    # Analyze individual quads
	    switch -exact -- [lindex $opcode 0] {

		extractCallFrame -
		invoke {


		    # These instructions do not change aliases, so copy
		    # the input frame to the result frame.
		    if {![dict exists $aliasInfo $arg1]} {
			set resFrame {}
		    } else {
			set resFrame [dict get $aliasInfo $arg1]
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455

# quadcode::transformer method upvarProcEffect --
#
#	Determines the effect of a procedure on the outer callframes of
#	the stack.
#
# Parameters:
#	state - Dictionaries whose keys are the names of quadcode variables
#	        that designate callframes, and whose values are the possible
#               aliases of the variables in outer frames.
#
# Results:
#	Returns a dictionary that characterizes the code's effect.

oo::define quadcode::transformer method upvarProcEffect {aliasInfo} {

    my debug-upvar {







|
|
|







436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452

# quadcode::transformer method upvarProcEffect --
#
#	Determines the effect of a procedure on the outer callframes of
#	the stack.
#
# Parameters:
#	aliasInfo - Dictionaries whose keys are the names of quadcode variables
#	            that designate callframes, and whose values are the possible
#                   aliases of the variables in outer frames.
#
# Results:
#	Returns a dictionary that characterizes the code's effect.

oo::define quadcode::transformer method upvarProcEffect {aliasInfo} {

    my debug-upvar {
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

	    set did 0
	    switch -exact -- [lindex $q 0] {

		"directArrayExists" -
		"directArrayGet" -
		"directExists" -
		"directGet" {

		    dict set result readsGlobal {}
		    dict unset result pure
		}

		"directAppend" -
		"directArrayAppend" -
		"directArrayLappend" -
		"directArrayLappendList" -
		"directArraySet" -
		"directArrayUnset" -
		"directLappend" -
		"directLappendList" -
		"directUnset" {
		    dict set result readsGlobal {}
		    dict set result writesGlobal {}
		    dict unset result pure
		    dict unset result killable
		}


		"directSet" {
		    dict set result writesGlobal {}
		    dict unset result pure
		    dict unset result killable
		}

		"moveFromCallFrame" {







|
>



















>







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

	    set did 0
	    switch -exact -- [lindex $q 0] {

		"directArrayExists" -
		"directArrayGet" -
		"directExists" -
		"directGet" -
		"directIsArray" {
		    dict set result readsGlobal {}
		    dict unset result pure
		}

		"directAppend" -
		"directArrayAppend" -
		"directArrayLappend" -
		"directArrayLappendList" -
		"directArraySet" -
		"directArrayUnset" -
		"directLappend" -
		"directLappendList" -
		"directUnset" {
		    dict set result readsGlobal {}
		    dict set result writesGlobal {}
		    dict unset result pure
		    dict unset result killable
		}

		"directMakeArray" -
		"directSet" {
		    dict set result writesGlobal {}
		    dict unset result pure
		    dict unset result killable
		}

		"moveFromCallFrame" {
561
562
563
564
565
566
567








568
569
570
571
572
573
574
		    # so correctly.
		    if {[dict exists $attrs error]} {
			my diagnostic error $b $pc [dict get $attrs error]
			dict unset attrs error
		    }
		    my upvarInvoke result $aliasInfo $attrs $q $typeList
		}









	    }

	    my debug-upvar {
		if {$did} {
		    puts "$b:$pc: $q"
		    puts "    effect changed to $result"







>
>
>
>
>
>
>
>







560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
		    # so correctly.
		    if {[dict exists $attrs error]} {
			my diagnostic error $b $pc [dict get $attrs error]
			dict unset attrs error
		    }
		    my upvarInvoke result $aliasInfo $attrs $q $typeList
		}

		"startCatch" {
		    # Any procedure that does a [catch] implicitly writes
		    # ::errorInfo and ::errorCode. It's insane to alias these,
		    # but someone probably does, so indicate that this proc
		    # writes globals.
		    dict set result writesGlobal {}
		}

	    }

	    my debug-upvar {
		if {$did} {
		    puts "$b:$pc: $q"
		    puts "    effect changed to $result"

Changes to quadcode/varargs.tcl.

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#
# Preconditions:
#       This pass presumes that the quadcode is partitioned into basic blocks,
#       and that SSA conversion has been run (so a constant procedure name
#       will have propagated into 'invoke' instructions. It also presumes
#       that procedure names have been resolved into the fully qualified names.
#
#       This pass introduces temporaries, but only locally to basic blocks,
#       so it does not require elaborate rewriting of SSA form. It must run
#       prior to parameter type checking (including the 'rewriteParamChecks'
#       peephole).
#
#       There is a hidden assumption in this method that default args are
#       always of acceptable type - and so type checks need not be
#       emitted for default parameters. (There is major rethinking needed
#       if this ever might not be the case.)

oo::define quadcode::transformer method varargs {} {







<
<
|
|







27
28
29
30
31
32
33


34
35
36
37
38
39
40
41
42
#
# Preconditions:
#       This pass presumes that the quadcode is partitioned into basic blocks,
#       and that SSA conversion has been run (so a constant procedure name
#       will have propagated into 'invoke' instructions. It also presumes
#       that procedure names have been resolved into the fully qualified names.
#


#       This pass must run prior to parameter type checking (including the
#       'rewriteParamChecks' peephole).
#
#       There is a hidden assumption in this method that default args are
#       always of acceptable type - and so type checks need not be
#       emitted for default parameters. (There is major rethinking needed
#       if this ever might not be the case.)

oo::define quadcode::transformer method varargs {} {
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208


209



210




211
212














213















214
215


216
217
218
219
220
221

222
223
224

225
226








227

228
229

230





231





232
233
234

235




236
237

238





239










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
271
272




273
274
275
276
277
278
279
280
281
282
283
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
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334

335

336
337


338

339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
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
408
409
410
411
412
413
414
415
416
417
418
419
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
463
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
517
518
519
520
521
522
523
524
525
526
527
528






529
530






531
532
533
534
535
536
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
567
568











569
570
571
572


573
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
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
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762

763
764
765
766
767
768

769


770
771



772
773
774
775
776
777
778
779
780
781
782
783
784


785
786


787
788
789
790

791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
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
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
929
930
931
932
933

934
935
936
937
938
939
940
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
991
992
993


994
995
996
997



998

999



1000








1001











































1002
1003



1004




1005
1006
1007


1008
1009









1010

1011







1012

























1013
1014
1015
1016
1017
1018
1019
1020
1021

1022





1023


1024
1025
1026

1027


1028

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
1054
1055
1056
        set pc -1
        foreach q $bb {
            incr pc

            # At this point in optimization, all invokes are part of a
            # sequence that is followed within a few instructions by a
            # jumpMaybe, so there can never be more than one in a basic
            # block. Since rewriting invocations can peform major surgery
            # on the program, simply call out to the appropriate handling
            # routine and 'break' to the next basic block.

            switch -exact [lindex $q 0] {
                "invoke" - "invokeExpanded" {
                    my debug-varargs {
                        puts "varargs: examine $b:$pc: $q"
                    }
                    my varargsRewriteInvoke $b $pc $q
                    break
                }
            }
        }
    }

    my debug-varargs {
        puts "After variadic call replacement:"
        my dump-bb
    }




}



# quadcode::transformer method varargsRewriteInvoke --
#
#       Rewrites 'invoke' and 'invokeExpanded' instructions to accommodate
#       compiled procs that accept variable numbers of arguments without going
#       through a call thunk or losing data type information.
#
# Parameters:
#       b - Basic block number
#       pc - Program counter within the block
#       q - Quadcode instruction being compiled
#
# Results:
#	None.
#
# Side effects:
#	Rewrites the instruction and 'expand' instructions that it
#       uses. Updates ud- and du-chains.
#
# We actually have to work on a whole code burst here. What we need to
# consider is a sequence like
#
# (may be omitted) moveToCallFrame cf1 cf0 name0 var0 name1 var1 ...
#                  invokeExpanded res0 cf1 command args...
# (may be omitted) retrieveResult res1 res0
# (may be omitted) extractCallframe cf2 res0
# (zero or more)   moveFromCallFrame var cf2 name
#                  jumpMaybe catchHandler res1
#                  jump normalReturn
#
# The reason is that there is a considerable amount of logic in
# optimization and code generation that isn't prepared to have
# a moveFromCallFrame's callframe argument be the result of a phi.
# (There are places where the optimizer needs to track moveFromCallFrame
# back to a unique 'invoke' or other callframe-altering operation).
#
# What we want the result to look like:
#
#    (... code to unpack arguments. Normal exit is bbNormal. Wrong
#    number of args exit is bbWrong.)
#
# bbNormal:
#    moveToCallFrame cf3 cf0 name0 var0 name1 var1 ...
#    invoke res2 cf3 command args ...
#    retrieveResult res3 res2
#    extractCallframe cf4 res3
#    moveFromCallFrame var' cf4 name (zero or more)
#    jumpMaybe bb0 res3
#    jump bb1
#
# bbWrong:
#    (no need for moveToCallFrame)
#    invokeExpanded res4 Nothing command originalArgs...
#    (no need for callframe manipulation)
#    jumpMaybe bb0 res4
#    jump bb1 (this jump is never taken, the 'invokeExpanded' always errors
#	       out in this case).
#
# bb0:
#    cf2* = phi(cf4 [bbNormal], cf0 [bbWrong])
#    res1* = phi(res3 [bbNormal], res4 [bbWrong])
#    zero or more:
#      var* = phi(var' [bbnormal], var' reaching def [bbWrong])
#    jump catchHandler
#
# bb1:
#    cf2** = phi(cf4 [bbNormal], cf0 [bbWrong])
#    res1** = phi(res3 [bbNormal], res4 [bbWrong])
#    zero or more:
#      var** = phi(var' [bbnormal], var' reaching def [bbWrong])
#    jump normalReturn
#
# Then, cf2*/cf2**, res1*/res1** and all instances of var*/var** become and
# are treated as duplicate definitions for repairSSAVariable.
#
# Note that the reaching definition of each variable in 'moveFromCallFrame'
# is easily obtained, because it has to be in the 'moveToCallFrame' that
# precedes the 'invokeExpanded'.

oo::define quadcode::transformer method varargsRewriteInvoke {b pc q} {

    set newqds {}

    # Take apart the quad
    set argv [lassign $q opcode cfout cfin calleeLit]

    # We care only about 'invokeExpanded' operations where the procedure
    # name is known a priori, the expected args are known, and
    # the target procedure is compiled.

    # TODO: We also care about {*} expansion passed to non-variadic
    #       Core commands. That will give us information about
    #	their stack effects.

    if {[lindex $calleeLit 0] ne "literal"
        || [catch {
            set callee [lindex $calleeLit 1]
            info args $callee
        } arginfo]
        || ![$specializer compiling $callee]} {

        return
    }

    my debug-varargs {
        puts "[my full-name]: $b:$pc: $q"
    }

    # Analyze the codeburst that carries out the 'invokeExpanded'.
    # This codeburst will run from the 'moveToCallFrame' preceding
    # the invocation out to the end of the basic block.
    # We will be rewriting it.

    set call [::quadcode::invocationSequence new]
    trace add variable call unset [list $call destroy]
    $call analyze [self] $b $pc

    # We are going to be doing major surgery on the basic block.
    # Remove the 'invokeExpanded' and all following instructions
    # from the block. Unlink the block from its successors, and
    # remove ud- and du-chaining for the removed instructions.






    set bb [my varargsUnlinkTail $b [$call pc0]]





    # Create the basic blocks for the actual invocation sequences. We make














    # them in advance to avoid backpatching.















    # Blocks 'err0b', 'norm0b', 'err1b' and 'norm1b' will be empty and are
    # present in order to split critical edges.



    set norm0b [llength $bbcontent]
    lappend bbcontent {}; lappend bbpred {}
    set err0b [llength $bbcontent]
    lappend bbcontent {}; lappend bbpred {}
    set notokb [llength $bbcontent]

    lappend bbcontent {}; lappend bbpred {}
    set norm1b [llength $bbcontent]
    lappend bbcontent {}; lappend bbpred {}

    set err1b [llength $bbcontent]
    lappend bbcontent {}; lappend bbpred {}








    set normb [llength $bbcontent]

    lappend bbcontent {}; lappend bbpred {}
    set normphis {}

    set errorb [llength $bbcontent]





    lappend bbcontent {}; lappend bbpred {}





    set errorphis {}

    # Create the first part of the 'invoke' instruction

    set invokeres [my newVarInstance $cfin]




    set newq [list invoke $invokeres $cfin $calleeLit]


    # Generate code for the 'wrong # args' case





    set notokbb {}










    set invexpres [my newVarInstance [$call retval]]

    foreach qq [my varargsEmitWrongArgs $invexpres {} Nothing $calleeLit] {


        my varargsEmitAndTrack $notokb notokbb $qq


    }
    dict set normphis [$call retval] [list bb $norm1b] $invexpres
    dict set errorphis [$call retval] [list bb $err1b] $invexpres
    dict set normphis [$call cfout] [list bb $norm1b] [$call cfin]
    dict set errorphis [$call cfout] [list bb $err1b] [$call cfin]
    my varargsEmitAndTrack $notokb notokbb \

        [list jumpMaybe [list bb $err1b] $invexpres]
    my varargsEmitAndTrack $notokb notokbb [list jump [list bb $norm1b]]
    lset bbcontent $notokb $notokbb














    # Split the critical edges

    foreach {edge target} [list $norm0b $normb $err0b $errorb \





















                               $norm1b $normb $err1b $errorb] {






        set splitbb {}

        my varargsEmitAndTrack $edge splitbb [list jump [list bb $target]]

        lset bbcontent $edge $splitbb
    }


    # Now start the parameter checking logic





    set nPlainParams [llength $arginfo]
    set haveargs 0
    if {[lindex $arginfo end] eq "args"} {
        set haveargs 1
        incr nPlainParams -1
    }




    # Start by matching off non-expanded args with parameters in the callee

    set pos 0




    while {$pos < $nPlainParams} {
        if {[my varargsNonExpandedArgument newq $arginfo $pos $q]} break
        incr pos
    }

    # Concatenate the remaining args into a list. 'listLoc' will
    # be the name of the object that holds the list.
    my debug-varargs {
        puts "varargs: $b:$pc: $q:\n\
              \    Matched leading non-expanded args.\
                   $pos of $nPlainParams plain params"
    }
    set tempIndex -1

    set listLoc [my varargsExpandFixed bb tempIndex pos $b $q]

    # 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 [list temp [incr tempIndex]]]
    set lenLoc [my newVarInstance [list temp $tempIndex]]
    my varargsEmitAndTrack $b bb [list listLength $lenLoc1 $listLoc]







    my varargsEmitAndTrack $b bb [list extractMaybe $lenLoc $lenLoc1]



    # Count the mandatory args


    set firstMandatory $pos
    while {$pos < $nPlainParams} {




        if {[info default $callee [lindex $arginfo $pos] defaultVal]} {



            break
        }
        incr pos
    }

    set firstOptional $pos

    set compTemp [list temp [incr $tempIndex]]

    set nMandatory 0
    if {$firstOptional > $firstMandatory} {

        # Make code to check length of arg list, starting a
        # new basic block
        set nMandatory [expr {$firstOptional - $firstMandatory}]
        set b [my varargsCheckEnough $b $bb $lenLoc $compTemp \
                   $nMandatory $notokb]
        set bb {}

        # Make code to transfer mandatory args
        my varargsUnpackMandatory tempIndex bb newq $b $listLoc $nMandatory
    }

    # Now we have the parameters that have default values.

    set j $nMandatory
    if {$nPlainParams > $firstOptional} {

        # 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 {}
        set i $firstOptional

        while {$i < $nPlainParams} {

            info default $callee [lindex $arginfo $i] defaultVal
            lassign [my varargsUnpackOptional tempIndex b bb \


                         $finishB $compTemp $listLoc $lenLoc $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
        my varargsFinishOptional b bb newq $finishB $optInfo

    }

    # If the procedure has 'args', then fill it in with the remainder of the
    # arg list.
    if {$haveargs} {
        my varargsDoArgs tempIndex $b bb newq $listLoc $j
    } else {
        my varargsCheckTooMany b bb $lenLoc $compTemp $j $notokb
    }

    # Create the normal invocation sequence.
    # 1. Create moveToCallFrame

    set cfin [$call cfin]
    set invars [$call invars]
    if {[$call pc0] < $pc} {
        set cf2 [my newVarInstance $cfin]
        set q2 [list moveToCallFrame $cf2 $cfin]
        dict for {vname val} $invars {
            lappend q2 [list literal $vname] $val
        }
        my varargsEmitAndTrack $b bb $q2
        set cfin $cf2
        lset newq 2 $cfin
    }
    
    # 2. Emit the call as rewritten
    my varargsEmitAndTrack $b bb $newq

    # 3. Make the 'retrieveResult'
    set okresult [my newVarInstance [$call retval]]
    my varargsEmitAndTrack $b bb [list retrieveResult $okresult $invokeres]
    dict set normphis [$call retval] [list bb $norm0b] $okresult
    dict set errorphis [$call retval] [list bb $err0b] $okresult

    # 4. Make the 'extractCallFrame'
    set okcf [my newVarInstance [$call cfout]]
    my varargsEmitAndTrack $b bb [list extractCallFrame $okcf $invokeres]
    dict set normphis [$call cfout] [list bb $norm0b] $okcf
    dict set errorphis [$call cfout] [list bb $err0b] $okcf

    # 5. Make 'moveFromCallFrame' for all output values
    dict for {vname outval} [$call outvars] {
        set okval [my newVarInstance $outval]
        my varargsEmitAndTrack $b bb \
            [list moveFromCallFrame $okval $okcf [list literal $vname]]
        dict set normphis $outval [list bb $norm0b] $okval
        dict set errorphis $outval [list bb $err0b] $okval
        set notokval [dict get [$call invars] $vname]
        dict set normphis $outval [list bb $norm1b] $notokval
        dict set errorphis $outval [list bb $err1b] $notokval
    }        

    # 6. Make the terminal jumps
    my varargsEmitAndTrack $b bb [list jumpMaybe [list bb $err0b] $okresult]
    my varargsEmitAndTrack $b bb [list jump [list bb $norm0b]]

    # 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 {}

    # Make the block for the normal exit
    set normbb {}
    foreach {v sources} $normphis {
        set val 0
        if {[dict exists $toRepair $v $normb]} {
            set val [dict get $toRepair $v $normb]
        }
        incr val
        dict set toRepair $v $normb $val
        my varargsEmitAndTrack $normb normbb [list phi $v {*}$sources]
    }
    my varargsEmitAndTrack $normb normbb [list jump [list bb [$call normexit]]]
    lset bbcontent $normb $normbb

    # Make the block for the error exit
    set errorbb {}
    foreach {v sources} $errorphis {
        set val 0
        if {[dict exists $toRepair $v $errorb]} {
            set val [dict get $toRepair $v $errorb]
        }
        incr val
        dict set toRepair $v $errorb $val
        my varargsEmitAndTrack $errorb errorbb [list phi $v {*}$sources]
    }
    my varargsEmitAndTrack $errorb errorbb [list jump [list bb [$call errexit]]]
    lset bbcontent $errorb $errorbb

    # Restore dominance relationships
    my bbidom; my bblevel

    my debug-varargs {
        puts "Before repairing SSA relationships:"
        my dump-bb
    }

    # Repair variable relationships that have been damaged
    dict for {v defs} $toRepair {
        my debug-varargs {
            puts "Replace $v with reaching definitions $defs"
        }
        my repairSSAVariable $v $defs
        my debug-varargs {
            puts "Replaced $v"
        }
    }

    my debug-varargs {
        puts "After repairing SSA relationships:"
        my dump-bb
    }
    
    return
}

# quadcode::transformer method varargsUnlinkTail --
#
#	Takes the last few instructions of a basic block and removes
#	them temporarily, unlinking the block from its successors and
#	the instructions from their ud- and du-chains.
#
# Parameters:
#	b - Number of the basic block
#	pc - Program counter of the first instruction being deleted
#
# Results:
#	Returns the partial basic block that remains
#
# Side effects:
#	Linkages are destroyed.

oo::define quadcode::transformer method varargsUnlinkTail {b pc} {
    set bb [lindex $bbcontent $b]
    set head [lrange $bb 0 [expr {$pc-1}]]
    set tail [lrange $bb $pc end]
    foreach q $tail {
        if {[lindex $q 1 0] in {"temp" "var"}} {
            dict unset udchain [lindex $q 1]
        }
        foreach arg [lrange $q 2 end] {
            if {[lindex $arg 0] in {"temp" "var"}} {
                my removeUse $arg $b
            }
        }
    }
    foreach b2 [my bbsucc $b] {
        my removePred $b2 $b
    }
    
    lset bbcontent $b $head

    return $head
}

# quadcode::transformer method varargsNonExpandedArgument --
#
#	Transfer a leading non-expanded argument into a quad
#	under construction when rewriting 'invokeExpanded'
#
# Parameters:
#	newqVar - Name of a variable in caller's scope storing the
#	          plain 'invoke' operation under construction
#	arginfo - Result of [info args] against the invoked proc
#	pos - Position of the argument (0 = first) in the argument list
#	q - Quadruple under construction
#
# Results:
#	Returns 0 if the parameter was transferred, 1 if we are at the
#	end of the possible static transfers.

oo::define quadcode::transformer method \
    varargsNonExpandedArgument {newqVar arginfo pos q} {

        upvar 1 $newqVar newq







        set param [lindex $arginfo $pos]
        set arg [lindex $q [expr {4 + $pos}]]






        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 varargsExpandFixed --
#
#	Takes the non-fixed-position arguments of 'invokeExpanded'
#	and emits code to make them into a list.
#
# Parameters:
#	bbVar - Variable in caller holding the basic block under construction
#	tempIdxVar - Variable in caller holding the number of the last
#	             temporary allocated.
#	posVar - Position in the parameter list where the list construction
#	         should begin.
#	b - Basic block number of the block under construction
#	q - 'invokeExpanded' instruction being deconstructed
#
# Results:
#
#	Returns the name of a variable, temporary or literal that holds the
#	expanded list.

oo::define quadcode::transformer method \
    varargsExpandFixed {bbVar tempIdxVar posVar b q} {












        upvar 1 $bbVar bb $tempIdxVar tempIndex $posVar pos

        set listTemp [list temp [incr tempIndex]]



        # Handle the first arg. Since 'invokeExpanded' always
        # has at least one expanded arg, there has to be a first
        # arg.
        if {4 + $pos >= [llength $q]} {
            set listLoc "literal {}"
        } else {
            set arg [lindex $q [expr {4 + $pos}]]



            switch -exact -- [lindex $arg 0] {
                "literal" {
                    set listLoc [my newVarInstance $listTemp]








                    my varargsEmitAndTrack $b bb [list list $listLoc $arg]

                }
                "temp" - "var" {
                    lassign [my findDef $arg] defb defpc defstmt
                    if {[lindex $defstmt 0] eq "expand"} {
                        set listLoc [lindex $defstmt 2]




                    } else {
                        set listLoc [my newVarInstance $listTemp]


                        my varargsEmitAndTrack $b bb [list list $listLoc $arg]


                    }

                }
            }
        }


        # listLoc now is holding the location of the list under
        # construction. Concatenate the remaining params onto it.






        foreach arg [lrange $q [expr {5 + $pos}] end] {





            # Do we need to expand this arg?
            switch -exact -- [lindex $arg 0] {
                "literal" {
                    set op listAppend
                }
                "temp" - "var" {
                    lassign [my findDef $arg] defb defpc defstmt
                    if {[lindex $defstmt 0] eq "expand"} {
                        set op listConcat

                    } else {
                        set op listAppend
                    }
                }
            }

            # Make variable to hold Maybe result from the concatenation,
            # and emit the concatenation.
            # This can't fail, $listTemp is known to be a list
            set nloc [my newVarInstance $listTemp]
            my varargsEmitAndTrack $b bb [list $op $nloc $listLoc $arg]

            # extract the result from the Maybe
            set listLoc [my newVarInstance $listTemp]
            my varargsEmitAndTrack $b bb [list extractMaybe $listLoc $nloc]
        }

        return $listLoc
    }



# quadcode::transformer method varargsCheckEnough --
#
#	Emits code to check for too few args passed to invokeExpanded
#
# Parameters:
#	b - Basic block number under construction
#	bb - Instructions in the block
#	lenLoc - Location holding the length of the arg list
#	compTemp - Temporary variable name to use for comparison
#	nMandatory - Number of mandatory args still unpaired
#	errorB - Basic block to jump to if too few args
#
# Results:
#	Returns the new basic block number; this method ends the block.

oo::define quadcode::transformer method varargsCheckEnough {b bb lenLoc compTemp
                                                            nMandatory errorB} {
    # Emit {$nMandatory > $lenLoc}
    set compLoc [my newVarInstance $compTemp]
    my varargsEmitAndTrack $b bb \
        [list gt $compLoc [list literal $nMandatory] $lenLoc]

    # Emit jumpTrue to the error block. This has to go through an
    # intermediate block because it will be a critical edge otherwise.
    # Emit jump to the following block
    set intb [llength $bbcontent]
    lappend bbcontent {}

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


    lappend bbpred {}

    my varargsEmitAndTrack $b bb [list jumpTrue [list bb $intb] $compLoc]
    my varargsEmitAndTrack $b bb [list jump [list bb $newb]]

    lset bbcontent $b $bb
    set bb {}

    # Emit the intermediate jump
    my varargsEmitAndTrack $intb bb [list jump [list bb $errorB]]
    lset bbcontent $intb $bb
    set bb {}



    return $newb
}


# quadcode::transformer method varargsUnpackMandatory --
#
#	Unpacks the mandatory args to a proc from the list created
#	by argument expansion
#
# Parameters;
#	tempIdxVar - Variable in caller's scope containing the last
#	             allocated temporary
#	bbVar - Variable in caller's scope containing basic block content
#	newqVar - Variable in caller's scope containing the new 'invoke'
#	          quad being constructed.
#	b - Basic block number under construction
#	listLoc - Variable or temp holding the list being unpacked
#	nMandatory - Number of parameters to unpack
#
# Results:
#	None.
#
# Side effects:
#	Emits code to unpack the mandatory parameters

oo::define quadcode::transformer method varargsUnpackMandatory {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

        set argTemp [list temp [incr tempIdx]]
        set argLoc [my newVarInstance $argTemp]
        my varargsEmitAndTrack $b bb \
            [list listIndex $argLoc $listLoc [list literal $i]]

        # Emit the 'extractMaybe' to get the arg from the Maybe
        # result of 'listIndex'
        set argLoc2 [my newVarInstance $argTemp]
        my varargsEmitAndTrack $b bb [list extractMaybe $argLoc2 $argLoc]




        # Put the extracted arg on the 'invoke' instruction
        lappend newq $argLoc2
    }
}



# quadcode::transformer method varargsUnpackOptional --
#
#	Emits code to unpack one optional parameter in an invokeExpanded
#
# Parameters:
#	tempIdxVar - Variable holding the index of the last used temporary
#	bVar - Variable holding the current basic block number
#	bbVar - Variable holding the content of the basic block under
#	        construction
#	finishB - Basic block number of the finishing block
#	compTemp - Temporary to use for list comparisons
#	listLoc - Location where the arg list is found
#	lenLoc - Location where the list length is found
#	j - Index in the arg list of the current parameter
#
# 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 varargsUnpackOptional {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 varargsEmitAndTrack $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 varargsEmitAndTrack $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 varargsEmitAndTrack $b bb [list jump [list bb $newb]]
    lset bbcontent $b $bb

    # Make the intermediate block
    set b $intb
    set bb {}
    my varargsEmitAndTrack $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 varargsEmitAndTrack $b bb [list listIndex $argLoc1 $listLoc $pos]


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

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

}

# quadcode::transformer method varargsFinishOptional --
#
#	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 varargsFinishOptional {bVar bbVar
                                                               newqVar finishB
                                                               optInfo} {

    upvar 1 $bVar b $bbVar bb $newqVar newq

    # Finish the current block and start building into 'finishB'


    my varargsEmitAndTrack $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
            incr k
            lappend q [list bb $fromBlock]
            if {$k >= $n} {
                lappend q $tempLoc
            } else {
                lappend q $defaultLit
            }
        }
        lappend q [list bb $fromb] $tempLoc

        my varargsEmitAndTrack $b bb $q


        lappend newq $newTemp
    }
}



# quadcode::transformer method varargsDoArgs --
#
#	Emits code to extract the parameter sequence needed to fill '$args'
#	from the parameter list.
#
# Parameters:
#	tempIdxVar - Variable containing the last temporary index used
#	b - basic block number under construction
#	bbVar - Variable containing the code of the basic block
#	newqVar - Variable containing the 'invoke' instruction under
#                 construction
#	listLoc - LLVM location holding the argument list
#	i - Index in the arg 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 varargsDoArgs {tempIdxVar b bbVar

                                                       newqVar listLoc i} {




    upvar 1 $tempIdxVar tempIndex $bbVar bb $newqVar newq


    if {$i == 0} {
        lappend newq $listLoc
    } else {
        set argsTemp [list temp [incr tempIndex]]
        set argsLoc1 [my newVarInstance $argsTemp]
        my varargsEmitAndTrack $b bb [list listRange $argsLoc1 $listLoc \
                                   [list literal $i] [list literal end]]




        set argsLoc2 [my newVarInstance $argsTemp]
        my varargsEmitAndTrack $b bb [list extractMaybe $argsLoc2 $argsLoc1]
        lappend newq $argsLoc2
    }
}


# quadcode::transformer method varargsCheckTooMany --



































#
#	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 varargsCheckTooMany {bVar bbVar lenLoc
                                                             compTemp i
                                                             errorB} {

    upvar 1 $bVar b $bbVar bb


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

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

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

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

    set b $intb
    set bb {}
    my varargsEmitAndTrack $b bb [list jump [list bb $errorB]]
    lset bbcontent $b $bb

    set b $newb
    set bb {}

}

# quadcode::transformer method varargsEmitWrongArgs --
#
#	Generates code to throw the 'wrong # args' error when needed

#
# Parameters:

#	result - Quadcode value that will hold the command result
#	cfout - Quadcode value that will hold the result callframe,
#	        or {} if no callframe need be produced
#	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 varargsEmitWrongArgs {result cfout 

                                                              cfin cmd} {










    set burst {}






    if {$cfin ne "Nothing"} {


        lappend burst [list copy $cfout $cfin]
    }

























    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} {
            append sbval " ?arg ...?"
        } elseif {[info default [lindex $cmd 1] $a -]} {
            lappend sbval ?$a?
        } else {
            lappend sbval $a
        }
    }

    set msgval "wrong # args: should be \"$sbval\""
    set intres [my newVarInstance $result]


    set q [list initException $intres [list literal $msgval] \
               {literal {-errorcode {TCL WRONGARGS}}} \
               {literal 1} \
               {literal 0}]



    lappend burst $q

    set q [list extractFail $result $intres]



    lappend burst $q








    return $burst












































}








# quadcode::transformer method varargsEmitAndTrack --
#
#	Emits a quadcode instruction and tracks its effects


#
# Parameters:









#	b - Basic block number

#	bbVar - Variable containing the basic block content







#	q - Quadcode instruction to emit

























#
# Results:
#	None.
#
# Side effects:
#	Instruction is added to the basic block, and linked in ud- and du-chains
#	Basic block is linked in control flow if needed.

oo::define quadcode::transformer method varargsEmitAndTrack {b bbVar q} {







    upvar 1 $bbVar bb



    set res [lindex $q 1]
    switch -exact -- [lindex $res 0] {

        "bb" {


            my bblink $b [lindex $res 1]

        }

        "temp" - "var" {


            dict set udchain $res $b




        }
    }









    foreach arg [lrange $q 2 end] {


        switch -exact -- [lindex $arg 0] {


            "temp" - "var" {



                my addUse $arg $b

            }




        }
    }




    my debug-varargs {
        puts "--> $b:[llength $bb]: $q"

    }
    lappend bb $q



}

# Local Variables:
# mode: tcl
# fill-column: 78
# auto-fill-function: nil
# buffer-file-coding-system: utf-8-unix
# indent-tabs-mode: nil
# End:







|
<
<
<





|











>
>
>
|
|
>
>
|
















|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|

<
|
<
<
<
<
|
<
|
<
<
<
|
<
<
<
<
<
<
|
|
<
<


<
|
<
<
<
<
|
<
<
<





>
>

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

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

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

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

>
>







>
>
>
|
|

>
>
>
>

|



<
<

|
|
<

|
>
|




|
|
|
>
>
>
>
>
>
>
|
>
>
|
|

>


>
>
>
>

>
>
>




>
|
|
|




|
<

<
|
<


|









<
<
<
<

>

>

|
>
>
|
>
|







|






|

<
<
|
<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|


|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<









|





|
|

|
|
>
>
>
>
>
>
|
|
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
|
|

|





|
|
<
|
<
<
|



|
|

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

>



|
>
|
<
>
|
>
>
>
>
|

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

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

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





<
<
<
<
|
|
<



|




|
|
|
<
<


>
>
>
>




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

|

|
>
|
>
|




|
<
<
<
<
<
<
<
|


>
|
|
>
|





|
<
<
<
<

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

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

|



|





|
<
<
|
<












|
<
<

<
<
|
>

|
<
<
|
|





|
>
>
>
>
>
>
















>
|
>
>


|
>
|
>
|





|
<
|
|
<
<
|








|
>
|
>
>
>
|
<

>



<
|
|
|
>
>
>
>
|
|


|
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|
|
|
>
|
>
>
>
|
<







|
<
<

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

<
<
|


|

<
>


>
|
|
|
<
<
<





>
>
|

|
>
|
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
|
>
>
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

|




|







|
>
>
|
|
|
|
>
>
>
|
>
|
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
|
>
>
>
>
|

<
>
>


>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|
<

|
>

>
>
>
>
>
|
>
>

|
<
>
|
>
>
|
>

>
|
>
>
|
>
>
>
>

|
>
>
>
>
>
>
>
|
>
|
>
>
|
>
>
|
>
>
>
|
>
|
>
>
>
>



>
>
>
|
<
>
|
<
|
>
>









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
104
105
106




























































107
108

109




110

111



112






113
114


115
116

117




118



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

168
169
170

171
172

173
174
175
176

177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206

207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
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
271
272
273
274
275
276
277
278
279
280
281
282
283
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
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325


326
327
328

329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
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
408
409
410
411
412
413
414
415
416
417


418


419







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
463
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
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532



533
534
535
536
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
567
568
569
570
571
572
573
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
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
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789

790
791


792
793
794
795
796
797
798
799
800
801
802
803
804
805
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
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
929
930
931
932
933
934
935
936
937
938
939
940
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
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
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
1054
1055
1056
1057
1058
1059
1060
1061
1062

1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
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
1107
1108
1109
1110
1111
1112
1113
1114
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
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182

1183
1184

1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
        set pc -1
        foreach q $bb {
            incr pc

            # At this point in optimization, all invokes are part of a
            # sequence that is followed within a few instructions by a
            # jumpMaybe, so there can never be more than one in a basic
            # block.



            switch -exact [lindex $q 0] {
                "invoke" - "invokeExpanded" {
                    my debug-varargs {
                        puts "varargs: examine $b:$pc: $q"
                    }
                    my va_RewriteInvoke $b $pc $q
                    break
                }
            }
        }
    }

    my debug-varargs {
        puts "After variadic call replacement:"
        my dump-bb
    }

    my debug-audit {
        my audit-phis varargs
        my audit-duchain varargs
    }

}

# quadcode::transformer method va_RewriteInvoke --
#
#       Rewrites 'invoke' and 'invokeExpanded' instructions to accommodate
#       compiled procs that accept variable numbers of arguments without going
#       through a call thunk or losing data type information.
#
# Parameters:
#       b - Basic block number
#       pc - Program counter within the block
#       q - Quadcode instruction being compiled
#
# Results:
#	None.
#
# Side effects:
#	Rewrites the instruction and 'expand' instructions that it
#       uses. Updates ud- and du-chains.





























































oo::define quadcode::transformer method va_RewriteInvoke {b pc q} {


    # We can process only those sequences where the procedure name is known




    # a priori, the expected arguments are known, and the target procedure

    # is compiled.  BUG - We know the arguments to a great many Core commands



    # and need to work with them as well.






    lassign [my va_GetArgInfo $q] status arginfo
    if {!$status} return


    my debug-varargs {
        puts "[my full-name]: $b:$pc: $q"

        puts "    arginfo = $arginfo"




    }




    # We are going to be doing major surgery on the basic block.
    # Remove the 'invokeExpanded' and all following instructions
    # from the block. Unlink the block from its successors, and
    # remove ud- and du-chaining for the removed instructions.
    set bb [my va_UnlinkTail $b $pc]
    set B [quadcode::builder new [self] $b [lindex $bbcontent $b]]

    # Prepare parameters for the 'invoke' (or 'invokeExpanded') call, and
    # add the call to the instruction sequence under construction.
    set newq [my va_PrepareArgs $B $b $pc $q $arginfo]
 
    # Emit the call
    $B emit $newq
    my debug-varargs {
        $B log-last
    }

    # Check that the return value from the invoke is linked correctly, and
    # bring in the 'retrieveResult'
    set q1 [lindex $bb 0]
    my debug-varargs {
        puts "varargs: result retrieval: $q1"
    }
    if {[lindex $q1 0] ne "retrieveResult" || [lindex $q1 2] ne [lindex $q 1]} {
        error "mislinked invoke: should be followed with 'retrieveResult'"
    }
    set result [lindex $q1 1]
    $B emit [list retrieveResult [$B maketemp "result"] [lindex $newq 1]]
    my debug-varargs {
        $B log-last
    }

    # Check that the extractCallFrame is linked correctly, and bring in
    # the 'extractCallFrame'
    set q2 [lindex $bb 1]
    my debug-varargs {
        puts "varargs: callframe extraction: $q2"
    }
    if {[lindex $q2 0] ne "extractCallFrame"
        || [lindex $q2 2] ne [lindex $q 1]} {
        error "mislinked invoke: should be followed with 'extractCallFrame'"
    }
    set cf [lindex $q2 1]
    $B emit [list extractCallFrame [$B maketemp "callframe"] [lindex $newq 1]]
    my debug-varargs {
        $B log-last
    }


    set cfin [lindex $newq 2]
    my va_ConvergeErrorPath $B $result $cf $cfin [lreplace $bb[set bb ""] 0 1]


    $B destroy


    return
}

# quadcode::transformer method va_GetArgInfo --

#
#	Determines the target of an invocation and performs [info args] on
#	that target to get its argument list.
#
# Parameters:
#	q - Quadcode 'invoke' or 'invokeExpanded' instruction
#
# Results:
#	Returns [list 1 $arglist] if the callee is known and [info args]
#	succeeds. Returns [list 0 {}] for an unknown callee or one whose
#	expected args are unknown.

oo::define quadcode::transformer method va_GetArgInfo {q} {

    set cmd [lindex $q 3]
    my debug-varargs {
        puts "varargs: callee is $cmd"
    }
    if {[lindex $cmd 0] ne "literal"} {
        my debug-varargs {
            puts "varargs: command name is not literal, do not rewrite"
        }
        return {0 {}}
    }
    if {[catch {info args [lindex $cmd 1]} arginfo]} {
        my debug-varargs {
            puts "varargs: do not rewrite [lindex $cmd 1]: $arginfo"
        }
        return {0 {}}
    }

    if {![$specializer compiling [lindex $cmd 1]]} {
        my debug-varargs {
            puts "varargs: do not rewrite [lindex $cmd 1], it's not compiled."
        }
        return {0 {}}
    } else {
        return [list 1 $arginfo]
    }
}

# quadcode::transformer method va_UnlinkTail --
#
#	Removes the invocation sequence from a basic block in preparation
#	for rewriting it.
#
# Parameters:
#	b - Number of the basic block
#	pc - Program counter of the first instruction being deleted
#
# Results:
#	Returns the partial basic block that remains.
#
# Side effects:
#	Variable defs and uses in the invocation sequence are removed
#	from ud- and du-chains. The basic block is unlinked from its
#	successors. 

oo::define quadcode::transformer method va_UnlinkTail {b pc} {

    set bb [lindex $bbcontent $b]
    lset bbcontent $b {}
    my debug-varargs {
        puts "varargs: Split basic block $b:"
        puts "   $b:$pc: [lindex $bb $pc]"
    }





    set tail [lrange $bb $pc end]
    set bb [lreplace $bb[set bb {}] $pc end]

    lset bbcontent $b $bb
    foreach q $tail {
        if {[lindex $q 1 0] in {"temp" "var"}} {
            dict unset udchain [lindex $q 1]
        }
        foreach arg [lrange $q 2 end] {
            if {[lindex $arg 0] in {"temp" "var"}} {
                my removeUse $arg $b
            }
         }
    }
    foreach b2 [my bbsucc $b] {
        my removePred $b2 $b
    }

    return [lreplace $tail[set tail {}] 0 0]
}

# quadcode::transformer method va_PrepareArgs --
#
#	Emits code to prepare the arguments for an 'invoke' or
#	'invokeExpanded' command, up to the point where the actual
#	'invoke' is issued.
#
# Parameters:
#	B - quadcode::builder where the new invocation sequence is being built.
#	b - Basic block where the original 'invoke' instruction resided
#	pc - Program counter within the basic block
#	q - 'invoke' or 'invokeExpanded' instruction.
#	arginfo - Arguments expected by the invoked command
#
# Results:
#	Returns the rewritten 'invoke' instruction
#
# Side effects:
#	Emits code so that the args off the rewritten instruction are
#	known to be available. May emit error handling code, qin which
#	case the following locations will be known to $B:
#		block 'error' - The block to which control transfers on
#	                        an error
#		value 'error' - The FAIL value that is used to report an error
#	The callframe on error is always the callframe input to the 'invoke'
#	instruction.
#
# The command name being invoked, and the expected arguments, are always known
# at this point.

oo::define quadcode::transformer method va_PrepareArgs {B b pc q arginfo} {
    
    set argl [lassign $q opcode result cfin cmd]
    set callee [lindex $cmd 1]

    # Create the first part of the 'invoke' instruction.
    

    set iresult [my newVarInstance $result]
    set newq [list invoke $iresult $cfin $cmd]

    # Find out how many plain parameters (that is, not 'args') the
    # called command has.
    set nPlainParams [llength $arginfo]
    set haveargs 0
    if {[lindex $arginfo end] eq "args"} {
        set haveargs 1
        incr nPlainParams -1
    }

    # 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\
              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
    }
    if {$mightThrow} {
        my va_MakeErrorCheck $B $lenLoc1
        set mightThrow 0
    }
    $B emit [list extractMaybe $lenLoc $lenLoc1]
    my debug-varargs {
        $B log-last
    }


    # Count the mandatory args
    set firstMandatory $pos
    while {$pos < $nPlainParams} {
        my debug-varargs {
            puts "varargs: does arg $pos: \"[lindex $arginfo $pos]\"\
                  have a default?"
        }
        if {[info default $callee [lindex $arginfo $pos] defaultVal]} {
            my debug-varargs {
                puts "         yes: \"defaultVal\""
            }
            break
        }
        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 $callee $nMandatory


        # Make code to transfer mandatory args
        set newq [my va_UnpackMandatory $B $newq $nMandatory]
    }

    # Now we have the parameters that have default values.

    set j $nMandatory
    if {$nPlainParams > $firstOptional} {

        # Emit a code burst for each optional parameter to
        # check the list length and extract the parameter




        set i $firstOptional

        while {$i < $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 --







































#
#	Transfer a leading non-expanded argument into a quad
#	under construction when rewriting 'invokeExpanded'
#
# Parameters:
#	newqVar - Name of a variable in caller's scope storing the
#	          plain 'invoke' operation under construction
#	arginfo - Result of [info args] against the invoked proc
#	pos - Position of the argument (0 = first) in the argument list
#	argl - Argument list of the 'invoke' or 'invokeExpanded' instruction
#
# Results:
#	Returns 0 if the parameter was transferred, 1 if we are at the
#	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 emits code to make them into a list.
#
# Parameters:
#	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"
    }

    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 mightThrow 0
                }
            }
        }
    }
    my debug-varargs {
        puts "varargs: transferred first arg into [list $listLoc]."

        puts "         mightThrow = $mightThrow"
    }

    # listLoc now holds the location of the list under
    # construction. Concatenate the remaining params onto it.

    foreach arg [lrange $argl [expr {1 + $pos}] end] {

        my debug-varargs {
            puts "varargs: transfer arg $arg"
        }

        # Do we need to expand this arg?
        switch -exact -- [lindex $arg 0] {
            "literal" {
                set op "listAppend"
            }
            "temp" - "var" {
                lassign [my findDef $arg] defb defpc defstmt
                if {[lindex $defstmt 0] eq "expand"} {
                    set op "listConcat"
                    set mightThrow 1
                } else {
                    set op "listAppend"
                }
            }
        }
        
        # Make variable to hold Maybe result from the concatenation,
        # and emit the concatenation.

        set nloc [$B maketemp arglist]
        $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
        }


    }




    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
#	by argument expansion
#
# Parameters;




#	B - Builder that is emitting quadcode
#	newq - 'invoke' instruction under construction

#	nMandatory - Number of parameters to unpack
#
# Results:
#	Returns the 'invoke' instruction with the mandatory parameters added.
#
# Side effects:
#	Emits code to unpack the mandatory parameters

oo::define quadcode::transformer method va_UnpackMandatory {B newq nMandatory} {

    set arglist [$B gettemp arglist]



    for {set i 0} {$i < $nMandatory} {incr i} {

        my debug-varargs {
            puts "varargs: transfer mandatory argument $i"
        }

        # Emit the 'listIndex' instruction for one arg. It can't fail
        # because we know we have a list

        set argtemp [$B maketemp arg$i]
        $B emit [list listIndex $argtemp $arglist [list literal $i]]
        my debug-varargs {
            $B log-last
        }


        set argloc [$B maketemp arg$i]
        $B emit [list extractMaybe $argloc $argtemp]
        my debug-varargs {
            $B log-last
        }

        # Put the extracted arg on the 'invoke' instruction
        lappend newq $argloc
    }

    return $newq
}

# 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
            incr k
            lappend q [list bb $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.
#
# 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 emit [list listRange $argsLoc1 $listLoc \
                      [list literal $i] {literal end}]
        my debug-varargs {
            $B log-last
        }

        set argsLoc2 [$B maketemp \$args]
        $B emit [list extractMaybe $argsLoc2 $argsLoc1]
        lappend newq $argsLoc2
    }

}

# 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
#	callee - Name of the invoked command
#	minLength - Minumum length of the arglist
#
# Results:
#	None.
#
# Side effects:
#	Emits the check, the 'wrong # args' error if needed, and generates
#	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
#
# Parameters:
#	B - Builder that is generating quadcode
#	callee - Name of the called procedure
#
# Results:
#	Returns the basic block number of the generated block
#
# Side effects:
#	Generates a block that creates an exception and jumps to the
#	error handler.

oo::define quadcode::transformer method va_MakeWrongArgs {B callee} {

    set wrongb [$B getblock "wrongargs"]
    if {$wrongb >= 0} {
        return $wrongb
    }
    set wrongb [$B makeblock "wrongargs"]
    set currentb [$B curblock]

    set argl [info args $callee]
    set left [llength $argl]
    set sbval [list $callee]
    foreach a $argl {
        incr left -1
        if {$a eq "args" && $left == 0} {
            append sbval " ?arg ...?"
        } elseif {[info default $callee $a -]} {
            lappend sbval ?$a?
        } else {
            lappend sbval $a
        }
    }

    set msgval "wrong # args: should be \"$sbval\""
    set intres [$B maketemp wrongargs]

    $B buildin $wrongb
    $B emit [list initException $intres [list literal $msgval] \
                 {literal {-errorcode {TCL WRONGARGS}}} \
                 {literal 1} \
                 {literal 0}]
    my debug-varargs {
        $B log-last
    }
    
    set excloc [$B maketemp wrongargs]
    $B emit [list extractFail $excloc $intres]
    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
    
}

# 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} {

    # 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 {
        $B log-last
    }
    $B emit [list jump [list bb $nextb]]
    my debug-varargs {
        $B log-last
    }

    # Make an intermediate block that jumps to the error block
    $B buildin $intb
    $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 gettemp error]
    $B updatephi $errorb $errorInPhi $val

    # Now continue building in the normal exit
    $B buildin $nextb
}

# quadcode::transformer method va_MakeErrorBlock --
#

#	Makes the block to which all the error paths in an invocation
#	sequence jump.
#
# Parameters:
#	B - Builder that is emitting code
#
# Results:
#	Returns the number of the block.
#
# Side effects:
#	Creates the block, and adds a vacuous 'phi' operation to it that
#	will hold the FAIL value from the error. The block and the result
#	of the 'phi' are both named 'error' in the builder.

oo::define quadcode::transformer method va_MakeErrorBlock {B} {

    my debug-varargs {
        puts "varargs: Create a block for error exits."
    }
    set errorb [$B getblock error]
    if {$errorb >= 0} {
        return $errorb
    }
    
    set currentb [$B curblock]
    set errorb [$B makeblock error]

    $B buildin $errorb
    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:
#	B - Builder that is emitting code
#	result - Quadcode variable that will hold the result
#	cf - Quadcode variable that will hold the callframe
#	cfin - Callframe on input to the 'invoke'
#	bb - Remainder of the basic block following 'invoke', 'retrieveResult'
#	     and 'extractCallFrame'.
#
# Results:
#	None.
#
# Side effects:
#	Emits all the remaining code.


oo::define quadcode::transformer method va_ConvergeErrorPath {B result
                                                              cf cfin bb} {

    # Find where errors were routed
    set errorb [$B getblock "error"]
    set normresult [$B gettemp "result"]
    set normcf [$B gettemp "callframe"]
    if {$errorb < 0} {

        # Nothing could throw, so just emit copies of the callframe and
        # the command's result. The copies will get cleaned up later

        $B emit [list copy $cf $normcf]

        my debug-varargs {
            $B log-last
        }
        $B emit [list copy $result $normresult]
        my debug-varargs {
            $B log-last
        }
    } else {

        # There is an error path that has to join here. Emit a jump to the
        # join point.
        set normb [$B curblock]
        set finalb [$B makeblock]
        $B emit [list jump [list bb $finalb]]
        my debug-varargs {
            $B log-last
        }

        # Move to the error block, and emit a jump to the join point
        set errResult [$B gettemp "error"]
        set errFail [$B maketemp "error"]
        $B buildin $errorb
        $B emit [list extractFail $errFail $errResult]
        my debug-varargs {
            $B log-last
        }
        $B emit [list jump [list bb $finalb]]
        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 \
                     [list bb $errorb] $errFail [list bb $normb] $normresult]
        my debug-varargs {
            $B log-last
        }
    }

    # Put back the instructions that followed the 'invoke'
    foreach q $bb {
        $B emit $q
        my debug-varargs {

            $B log-last
        }

    }
    
    return
}

# Local Variables:
# mode: tcl
# fill-column: 78
# auto-fill-function: nil
# buffer-file-coding-system: utf-8-unix
# indent-tabs-mode: nil
# End:

Changes to quadcodes.txt.

156
157
158
159
160
161
162



163
164
165
166
167
168
169
dictIterKey TGT SRC
    Let TGT be the key from the current step of the interation in SRC.
dictIterValue TGT SRC
    Let TGT be the value from the current step of the interation in SRC.

Error-Related Operations List Operations
--------------------



extractMaybe TGT SRC
    Given a Maybe in SRC which contains a Just X, let TGT become the X.
initException TGT SRC1 SRC2 ?SRC3 SRC4?
    Set up an exception. TGT is a Maybe of the result value. SRC1 is the
    result value. SRC2 is the options dictionary. SRC3 is the return code
    override, and SRC4 is the return level override. Both SRC3 and SRC4 may be
    omitted.







>
>
>







156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
dictIterKey TGT SRC
    Let TGT be the key from the current step of the interation in SRC.
dictIterValue TGT SRC
    Let TGT be the value from the current step of the interation in SRC.

Error-Related Operations List Operations
--------------------
extractFail TGT SRC
    Given a Maybe in SRC which contains an exception, let TGT become the
    exception.
extractMaybe TGT SRC
    Given a Maybe in SRC which contains a Just X, let TGT become the X.
initException TGT SRC1 SRC2 ?SRC3 SRC4?
    Set up an exception. TGT is a Maybe of the result value. SRC1 is the
    result value. SRC2 is the options dictionary. SRC3 is the return code
    override, and SRC4 is the return level override. Both SRC3 and SRC4 may be
    omitted.
182
183
184
185
186
187
188





189
190
191
192
193
194
195
196
197
198
199
200
201
202
203



204
205
206




207
208
209
210




211
212
213
214
215
216
217
    for TCL_ERROR, etc.)  Note that this is only expected to be used in
    situations where the code is handling an error case.
returnOptions TGT SRC
    Let TGT contain the current interpreter return options, given that SRC
    contains the exception code, as obtained by 'returnCode'.
setReturnCode {} SRC
    Sets the current return code to SRC.






General/Structural Operations
-----------------------
allocObjvForCallees {} {literal N}
    Preallocates the 'objv' vector for commands that this command invokes.
    N is the required length of the vector.
confluence
    Comes at the start of a block that has execution flowing in from multiple
    other blocks.
copy TGT SRC
    Let TGT become SRC
entry
    Marks the entry to the function.
exists TGT SRC
    Sets TGT to 1 if SRC has a value, and 0 otherwise



extractExists TGT SRC
    Given a SRC value that is of type {NEXIST SOMETHING}, let TGT become
    just the SOMETHING.




invoke TGT SRC1 ...
    Let TGT become the invoke of the given command with the given arguments.
    The command is given by SRC1 and the arguments are given by SRC2...
    Variadic.




jump BLK
    Transfer execution to the block with address BLK.
jumpFalse BLK SRC
    Transfer execution to the block with address BLK if SRC is false, otherwise
    transfer execution to the "next" block.
jumpTrue BLK SRC
    Transfer execution to the block with address BLK if SRC is true, otherwise







>
>
>
>
>






<
<
<






>
>
>



>
>
>
>
|



>
>
>
>







185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
    for TCL_ERROR, etc.)  Note that this is only expected to be used in
    situations where the code is handling an error case.
returnOptions TGT SRC
    Let TGT contain the current interpreter return options, given that SRC
    contains the exception code, as obtained by 'returnCode'.
setReturnCode {} SRC
    Sets the current return code to SRC.
startCatch CALLFRAME CALLFRAME
    Appears shortly after anything in the program that throws an error.
    Used to do the bookkeeping needed to track that ::errorInfo and ::errorCode
    have been changed 'behind the program's back' and make sure that
    any variables that might alias them are synchronized.

General/Structural Operations
-----------------------
allocObjvForCallees {} {literal N}
    Preallocates the 'objv' vector for commands that this command invokes.
    N is the required length of the vector.



copy TGT SRC
    Let TGT become SRC
entry
    Marks the entry to the function.
exists TGT SRC
    Sets TGT to 1 if SRC has a value, and 0 otherwise
extractCallFrame TGT SRC
    Given a SRC value that is a callframe combined with something else,
    extracts the callframe from it.
extractExists TGT SRC
    Given a SRC value that is of type {NEXIST SOMETHING}, let TGT become
    just the SOMETHING.
extractResult TGT SRC
    Give a SRC value that is a callframe combined with another type X, extracts
    the X from it.  (extractExists and extractResult ordinarily follow 'invoke'
    to unpack the structure that it returns.)
invoke TGT {} SRC1 SRC2...
    Let TGT become the invoke of the given command with the given arguments.
    The command is given by SRC1 and the arguments are given by SRC2...
    Variadic.
invoke TGT+CALLFRAME CALLFRAME SRC1 ...
    This variant is used when the 'invoke' may alter variables. CALLFRAME
    is the callframe before the invocation, and TGT+CALLFRAME is the result
    combined with the callframe afterward.
jump BLK
    Transfer execution to the block with address BLK.
jumpFalse BLK SRC
    Transfer execution to the block with address BLK if SRC is false, otherwise
    transfer execution to the "next" block.
jumpTrue BLK SRC
    Transfer execution to the block with address BLK if SRC is true, otherwise
252
253
254
255
256
257
258


























































259
260
261
{{purifyParam N} TGT SRC FUNC}
   Sets TGT to SRC, with any IMPURE indication removed, if FUNC is a built-in
   math function requiring a pure value as argument #N.
   Otherwise, simply sets TGT to SRC. This operation is
   replaced with 'purify' or removed during optimization. It is there to
   purify the operands of built-in mathfuncs.



























































For these operations, the data types that must be implemented are INT32,
INT, ENTIER, DOUBLE; the same four data types unioned with EMPTY; and the
complements of these eight types, so there are sixteen variants in all. 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
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
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
{{purifyParam N} TGT SRC FUNC}
   Sets TGT to SRC, with any IMPURE indication removed, if FUNC is a built-in
   math function requiring a pure value as argument #N.
   Otherwise, simply sets TGT to SRC. This operation is
   replaced with 'purify' or removed during optimization. It is there to
   purify the operands of built-in mathfuncs.

# Direct variable manipulation instructions

directExists VAL CF VAR
    Tests whether variable VAR exists (in callframe CF, if the value is
    not fully qualified). Returns ZEROONE.
directGet VAL CF VAR
    Gets the value of VAR from callframe CF and puts the result in VAL.
    Result is of type {FAIL NEXIST STRING}.
directSet TUPLE CF VAR VAL
    Sets variable VAR in callframe CF (or in a namespace) to the value VAL.
    Returns the result of the set, or an error if the value cannot be set.
    TUPLE is of type {CALLFRAME FAIL T} where T is the type of VAL.
directAppend TUPLE CF VAR VAL
    Appends value VAL to variable VAR in callframe CF (or in a namespace).
    Returns the result of the set, or an error if the value cannot be set.
    TUPLE is of type {CALLFRAME FAIL STRING}.
directLappend TUPLE CF VAR VAL
    Appends value VAL to variable VAR in callframe CF (or in a namespace).
    Returns the result of the set, or an error if the value cannot be set.
    TUPLE is of type {CALLFRAME FAIL STRING}.
directLappendList TUPLE CF VAR LISTVAL
    Appends the list of values LISTVAL to variable VAR in callframe CF
    (or in a namespace). Returns the result of the append, or an error if
    the value could not be apppended. TUPLE is of type {CALLFRAME FAIL STRING}
directIsArray VAL CF ARY
    Tests [array exists ARY] (in callframe CF, if ARY is not fully qualified).
    Returns a Boolean indicating the existence, or an error in the event of
    an error in traces. (Note that traces are not implemented in quadcode yet!)
    Result is of type {FAIL ZEROONE}.
directMakeArray TUPLE CF ARY
    Creates an array ARY (in callframe CF if ARY is not fully qualified).
    Returns an ignored result or throws an error. Return type is {ZEROONE FAIL}.
directArrayExists VAL CF ARY ELT
    Tests whether element ELT of array ARY exists (in callframe CF, if the
    value is not fully qualified). Returns ZEROONE.
directArrayGet VAL CF ARY ELT
    Gets the value of element ELT of array ARY in callframe CF and puts
    the result in VAL. Result is of type {FAIL NEXIST STRING}.
directArraySet TUPLE CF ARY ELT VAL
    Sets element ELT of array ARY in callframe CF (or in a namespace) to the
    value VAL. Returns the result of the set, or an error if the value cannot
    be set. TUPLE is of type {CALLFRAME FAIL T} where T is the type of VAL.
directArrayAppend TUPLE CF ARY ELT VAL
    Appends value VAL to element ELT of array ARY (in callframe CF if ARY
    is not fully qualified).
    Returns the result of the set, or an error if the value cannot be set.
    TUPLE is of type {CALLFRAME FAIL STRING}.
directArrayLappend TUPLE CF ARY ELT VAL
    Appends value VAL to element ELT of array ARY (in callframe CF, if
    ARY is not fully qualified).  Returns the result of the operation,
    or an error if the value cannot be set.  TUPLE is of type
    {CALLFRAME FAIL STRING}.
directArrayLappendList TUPLE CF ARY ELT LISTVAL
    Appends the list of values LISTVAL to element ELT of array ARY
    (in callframe CF, if ARY is not fully qualified).
    Returns the result of the append, or an error if
    the value could not be apppended. TUPLE is of type {CALLFRAME FAIL STRING}

For these operations, the data types that must be implemented are INT32,
INT, ENTIER, DOUBLE; the same four data types unioned with EMPTY; and the
complements of these eight types, so there are sixteen variants in all.