# widen.tcl --
#
# Transformation that inserts type-widening operations into
# quadcode sequences
#
# 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.
#
#------------------------------------------------------------------------------
# widen --
#
# Inserts type widening operations where necessary.
#
# Results:
# None.
#
# Side effects:
# 'widen' operations are inserted in the quadcode.
#
# The only place where widening is necessary is where values of
# different types meet at a phi operation. When that happens, the
# result type of the phi has been determined (before this procedure
# executes) to be the union of the argument types. This method
# simply drops in 'widen' operations to flag to the code issuer that
# the internal representation of the values may need to change.
oo::define quadcode::transformer method widen {} {
my debug-widen {
puts "widen:"
my dump-bb
}
# Find and widen the inputs of all the phi operations in the program
set b -1
foreach content $bbcontent {
incr b
set pc -1
foreach q $content {
incr pc
if {[lindex $q 0] ne "phi"} continue
set destvar [lindex $q 1]
set desttype [dict get $types $destvar]
# Examine each input to a phi
set i 2
foreach {from source} [lrange $q 2 end] {
if {[typeOfOperand $types $source] != $desttype} {
# $source needs to be widened. Make a new temporary
# to hold the widened value, and insert a 'widen'
# operation in the basic block that got here.
set frombb [lindex $from 1]
set fromcontent [lindex $bbcontent $frombb]
lset bbcontent $frombb {}
set lastjump [lindex $fromcontent end]
set fromcontent \
[lreplace $fromcontent[set fromcontent {}] end end]
set newvar [my newVarInstance $destvar]
lappend fromcontent \
[list [list widenTo $desttype [nameOfType $desttype]] \
$newvar $source] \
$lastjump
lset bbcontent $frombb $fromcontent
lset bbcontent $b $pc [expr {$i+1}] $newvar
dict set udchain $newvar $frombb
my addUse $newvar $b
my removeUse $source $b
my addUse $source $frombb
dict set types $newvar $desttype
}
incr i 2
}
}
# Also widen the operand of any 'return' instruction
# Make sure we have the current content of the basic block
set content [lindex $bbcontent $b]
set q [lindex $content end]
if {[lindex $q 0] eq "return"} {
set source [lindex $q 3]
set desttype [dict get $types "return"]
if {[typeOfOperand $types $source] != $desttype} {
# The return value needs to be widened
set newvar [my newVarInstance {temp 0}]
lset bbcontent $b {}
set content \
[lreplace $content[set content {}] end end \
[list [list widenTo $desttype [nameOfType $desttype]] \
$newvar $source] \
[list return {} [lindex $q 2] $newvar]]
lset bbcontent $b $content
dict set udchain $newvar $b
my addUse $newvar $b
my removeUse $source $b
dict set types $newvar $desttype
}
}
}
my debug-widen {
puts "after widen:"
my dump-bb
}
}