summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2021-11-06 12:55:36 -0400
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-12-02 18:13:30 -0500
commit1724ac37633b2796e2410296e8a34bc8e1fa4934 (patch)
tree8cca01710cbfe505a42df6817d5354a427af0d02
parentd3c7f9be47ac99637ac0ede0759f77da320afaad (diff)
downloadhaskell-1724ac37633b2796e2410296e8a34bc8e1fa4934.tar.gz
nativeGen/x86: Don't encode large shift offsets
Handle the case of a shift larger than the width of the shifted value. This is necessary since x86 applies a mask of 0x1f to the shift amount, meaning that, e.g., `shr 47, $eax` will actually shift by 47 & 0x1f == 15. See #20626. (cherry picked from commit 31370f1afe1e2f071b3569fb5ed4a115096127ca)
-rw-r--r--compiler/GHC/CmmToAsm/X86/CodeGen.hs11
1 files changed, 10 insertions, 1 deletions
diff --git a/compiler/GHC/CmmToAsm/X86/CodeGen.hs b/compiler/GHC/CmmToAsm/X86/CodeGen.hs
index dccff1ef9d..52f2a52123 100644
--- a/compiler/GHC/CmmToAsm/X86/CodeGen.hs
+++ b/compiler/GHC/CmmToAsm/X86/CodeGen.hs
@@ -1003,7 +1003,16 @@ getRegister' _ is32Bit (CmmMachOp mop [x, y]) = -- dyadic MachOps
-> NatM Register
{- Case1: shift length as immediate -}
- shift_code width instr x (CmmLit lit) = do
+ shift_code width instr x (CmmLit lit)
+ -- Handle the case of a shift larger than the width of the shifted value.
+ -- This is necessary since x86 applies a mask of 0x1f to the shift
+ -- amount, meaning that, e.g., `shr 47, $eax` will actually shift by
+ -- `47 & 0x1f == 15`. See #20626.
+ | CmmInt n _ <- lit
+ , n >= fromIntegral (widthInBits width)
+ = getRegister $ CmmLit $ CmmInt 0 width
+
+ | otherwise = do
x_code <- getAnyReg x
let
format = intFormat width