switches with a single case reuse temporary names
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
Mars |
Fix Released
|
Critical
|
Matt Giuca |
Bug Description
Normal switches end the current block by generating the result of the switch expression, then executing a 'switch' instruction to branch to another block where the temporaries are bound for the matched variables, finally branching to another block to bind the variables. A switch with a single case will be optimised by ast_cfg into a single block where a) the switch expression result is generated, and b) temporaries are bound for the matched variables.
However, the temporaries in (b) re-use the same names as the temporaries from (a). This is very bad -- we should not be re-using names in SSA code, especially since the second assignments usually have a different type (so the localtable is incorrect).
For example:
type Pair(a, b):
Pair(a, b)
def switchpair() :: Int:
switch Pair(1, 2):
case Pair(x, y):
pass
return x
This generates the assembly code:
def switchpair() :: Int:
var $T:0 :: Int # Also used as Pair(Int, Int)
var $T:0:1 :: Int # Also used as (Int, Int) -> Pair(Int, Int)
var $T:0:2 :: Int
var $T:0:3 :: Int
Block 0:
# Preds: []
$T:0:1 = Pair
$T:0:2 = 1
$T:0:3 = 2
$T:0 = $T:0:1($T:0:2, $T:0:3)
$T:0 = $T:0.[Pair: 0]
$T:0:1 = $T:0.[Pair: 1]
....
This produces a run-time error: "Interpreter Error: Field reference to something not an ADT."
1. The ast_cfg should terminate with an internal error if it attempts to set a variable in the localtable which already exists.
2. It needs to generate fresh temporary names for the second part of that block.
Related branches
Changed in mars: | |
status: | Fix Committed → Fix Released |
Added test case in trunk r1146 (switch: switch_ onecase) . Oddly, this case actually doesn't run at all, due to this bug (it is simply omitted from the test output). Fix #1 (making an internal error) should turn this into a firm failing case.