diff options
author | Ben Gamari <ben@smart-cactus.org> | 2021-11-06 12:55:36 -0400 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2021-12-02 18:13:30 -0500 |
commit | 1724ac37633b2796e2410296e8a34bc8e1fa4934 (patch) | |
tree | 8cca01710cbfe505a42df6817d5354a427af0d02 /compiler/GHC/CmmToAsm | |
parent | d3c7f9be47ac99637ac0ede0759f77da320afaad (diff) | |
download | haskell-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)
Diffstat (limited to 'compiler/GHC/CmmToAsm')
-rw-r--r-- | compiler/GHC/CmmToAsm/X86/CodeGen.hs | 11 |
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 |