summaryrefslogtreecommitdiff
path: root/compiler/GHC/Wasm/ControlFlow/FromCmm.hs
diff options
context:
space:
mode:
authorCheng Shao <terrorjack@type.dance>2023-01-31 17:07:17 +0000
committerMarge Bot <ben+marge-bot@smart-cactus.org>2023-01-31 20:47:03 -0500
commitf0eefa3cf058879246991747dcd18c811402f9e5 (patch)
treeec85c5fc686c158b329bb9db53ffb367a4046a66 /compiler/GHC/Wasm/ControlFlow/FromCmm.hs
parent22089f693cf6e662a58a7011adb94d7f768ad2d7 (diff)
downloadhaskell-wip/T21776.tar.gz
compiler: properly handle non-word-sized CmmSwitch scrutinees in the wasm NCGwip/T21776
Currently, the wasm NCG has an implicit assumption: all CmmSwitch scrutinees are 32-bit integers. This is not always true; #22864 is one counter-example with a 64-bit scrutinee. This patch fixes the logic by explicitly converting the scrutinee to a word that can be used as a br_table operand. Fixes #22871. Also includes a regression test.
Diffstat (limited to 'compiler/GHC/Wasm/ControlFlow/FromCmm.hs')
-rw-r--r--compiler/GHC/Wasm/ControlFlow/FromCmm.hs10
1 files changed, 9 insertions, 1 deletions
diff --git a/compiler/GHC/Wasm/ControlFlow/FromCmm.hs b/compiler/GHC/Wasm/ControlFlow/FromCmm.hs
index 0667345162..85eb8e534b 100644
--- a/compiler/GHC/Wasm/ControlFlow/FromCmm.hs
+++ b/compiler/GHC/Wasm/ControlFlow/FromCmm.hs
@@ -75,7 +75,7 @@ flowLeaving platform b =
let (offset, target_labels) = switchTargetsToTable targets
(lo, hi) = switchTargetsRange targets
default_label = switchTargetsDefault targets
- scrutinee = smartPlus platform e offset
+ scrutinee = smartExtend platform $ smartPlus platform e offset
range = inclusiveInterval (lo+toInteger offset) (hi+toInteger offset)
in Switch scrutinee range target_labels default_label
CmmCall { cml_cont = Nothing, cml_target = e } -> TailCall e
@@ -314,6 +314,14 @@ structuredControl platform txExpr txBlock g =
nodeBody :: CmmBlock -> CmmActions
nodeBody (BlockCC _first middle _last) = middle
+-- | A CmmSwitch scrutinee may have any width, but a br_table operand
+-- must be exactly word sized, hence the extension here. (#22871)
+smartExtend :: Platform -> CmmExpr -> CmmExpr
+smartExtend p e | w0 == w1 = e
+ | otherwise = CmmMachOp (MO_UU_Conv w0 w1) [e]
+ where
+ w0 = cmmExprWidth p e
+ w1 = wordWidth p
smartPlus :: Platform -> CmmExpr -> Int -> CmmExpr
smartPlus _ e 0 = e