diff options
-rw-r--r-- | compiler/GHC/CmmToAsm/PPC/CodeGen.hs | 12 | ||||
-rw-r--r-- | compiler/GHC/CmmToAsm/SPARC/CodeGen.hs | 12 | ||||
-rw-r--r-- | compiler/GHC/CmmToAsm/X86/CodeGen.hs | 11 | ||||
-rw-r--r-- | compiler/GHC/CmmToC.hs | 6 | ||||
-rw-r--r-- | testsuite/tests/numeric/should_run/T19931.hs | 35 | ||||
-rw-r--r-- | testsuite/tests/numeric/should_run/T19931.stdout | 1 | ||||
-rw-r--r-- | testsuite/tests/numeric/should_run/all.T | 1 |
7 files changed, 69 insertions, 9 deletions
diff --git a/compiler/GHC/CmmToAsm/PPC/CodeGen.hs b/compiler/GHC/CmmToAsm/PPC/CodeGen.hs index 8ee20e06f5..67bc3d9bdb 100644 --- a/compiler/GHC/CmmToAsm/PPC/CodeGen.hs +++ b/compiler/GHC/CmmToAsm/PPC/CodeGen.hs @@ -2086,7 +2086,7 @@ genSwitch :: NCGConfig -> CmmExpr -> SwitchTargets -> NatM InstrBlock genSwitch config expr targets | OSAIX <- platformOS platform = do - (reg,e_code) <- getSomeReg (cmmOffset platform expr offset) + (reg,e_code) <- getSomeReg indexExpr let fmt = archWordFormat $ target32Bit platform sha = if target32Bit platform then 2 else 3 tmp <- getNewRegNat fmt @@ -2103,7 +2103,7 @@ genSwitch config expr targets | (ncgPIC config) || (not $ target32Bit platform) = do - (reg,e_code) <- getSomeReg (cmmOffset platform expr offset) + (reg,e_code) <- getSomeReg indexExpr let fmt = archWordFormat $ target32Bit platform sha = if target32Bit platform then 2 else 3 tmp <- getNewRegNat fmt @@ -2120,7 +2120,7 @@ genSwitch config expr targets return code | otherwise = do - (reg,e_code) <- getSomeReg (cmmOffset platform expr offset) + (reg,e_code) <- getSomeReg indexExpr let fmt = archWordFormat $ target32Bit platform sha = if target32Bit platform then 2 else 3 tmp <- getNewRegNat fmt @@ -2134,6 +2134,12 @@ genSwitch config expr targets ] return code where + indexExpr = cmmOffset platform exprWidened offset + -- We widen to a native-width register to santize the high bits + exprWidened = CmmMachOp + (MO_UU_Conv (cmmExprWidth platform expr) + (platformWordWidth platform)) + [expr] (offset, ids) = switchTargetsToTable targets platform = ncgPlatform config diff --git a/compiler/GHC/CmmToAsm/SPARC/CodeGen.hs b/compiler/GHC/CmmToAsm/SPARC/CodeGen.hs index 56f764560c..aeaaf1c9d3 100644 --- a/compiler/GHC/CmmToAsm/SPARC/CodeGen.hs +++ b/compiler/GHC/CmmToAsm/SPARC/CodeGen.hs @@ -313,7 +313,7 @@ genSwitch config expr targets = error "MachCodeGen: sparc genSwitch PIC not finished\n" | otherwise - = do (e_reg, e_code) <- getSomeReg (cmmOffset (ncgPlatform config) expr offset) + = do (e_reg, e_code) <- getSomeReg indexExpr base_reg <- getNewRegNat II32 offset_reg <- getNewRegNat II32 @@ -334,7 +334,15 @@ genSwitch config expr targets , LD II32 (AddrRegReg base_reg offset_reg) dst , JMP_TBL (AddrRegImm dst (ImmInt 0)) ids label , NOP ] - where (offset, ids) = switchTargetsToTable targets + where + indexExpr = cmmOffset platform exprWidened offset + -- We widen to a native-width register to santize the high bits + exprWidened = CmmMachOp + (MO_UU_Conv (cmmExprWidth platform expr) + (platformWordWidth platform)) + [expr] + (offset, ids) = switchTargetsToTable targets + platform = ncgPlatform config generateJumpTableForInstr :: Platform -> Instr -> Maybe (NatCmmDecl RawCmmStatics Instr) diff --git a/compiler/GHC/CmmToAsm/X86/CodeGen.hs b/compiler/GHC/CmmToAsm/X86/CodeGen.hs index ff25a2e53f..5e7c261cbb 100644 --- a/compiler/GHC/CmmToAsm/X86/CodeGen.hs +++ b/compiler/GHC/CmmToAsm/X86/CodeGen.hs @@ -3476,9 +3476,16 @@ genSwitch :: CmmExpr -> SwitchTargets -> NatM InstrBlock genSwitch expr targets = do config <- getConfig let platform = ncgPlatform config + -- We widen to a native-width register because we cannot use arbitry sizes + -- in x86 addressing modes. + exprWidened = CmmMachOp + (MO_UU_Conv (cmmExprWidth platform expr) + (platformWordWidth platform)) + [expr] + indexExpr = cmmOffset platform exprWidened offset if ncgPIC config then do - (reg,e_code) <- getNonClobberedReg (cmmOffset platform expr offset) + (reg,e_code) <- getNonClobberedReg indexExpr -- getNonClobberedReg because it needs to survive across t_code lbl <- getNewLabelNat let is32bit = target32Bit platform @@ -3519,7 +3526,7 @@ genSwitch expr targets = do JMP_TBL (OpReg tableReg) ids rosection lbl ] else do - (reg,e_code) <- getSomeReg (cmmOffset platform expr offset) + (reg,e_code) <- getSomeReg indexExpr lbl <- getNewLabelNat let op = OpAddr (AddrBaseIndex EABaseNone (EAIndex reg (platformWordSizeInBytes platform)) (ImmCLbl lbl)) code = e_code `appOL` toOL [ diff --git a/compiler/GHC/CmmToC.hs b/compiler/GHC/CmmToC.hs index 8349393f0d..f662f7d996 100644 --- a/compiler/GHC/CmmToC.hs +++ b/compiler/GHC/CmmToC.hs @@ -341,15 +341,17 @@ pprSwitch platform e ids where (pairs, mbdef) = switchTargetsFallThrough ids + rep = typeWidth (cmmExprType platform e) + -- fall through case caseify (ix:ixs, ident) = vcat (map do_fallthrough ixs) $$ final_branch ix where do_fallthrough ix = - hsep [ text "case" , pprHexVal platform ix (wordWidth platform) <> colon , + hsep [ text "case" , pprHexVal platform ix rep <> colon , text "/* fall through */" ] final_branch ix = - hsep [ text "case" , pprHexVal platform ix (wordWidth platform) <> colon , + hsep [ text "case" , pprHexVal platform ix rep <> colon , text "goto" , (pprBlockId ident) <> semi ] caseify (_ , _ ) = panic "pprSwitch: switch with no cases!" diff --git a/testsuite/tests/numeric/should_run/T19931.hs b/testsuite/tests/numeric/should_run/T19931.hs new file mode 100644 index 0000000000..1ab9002d2e --- /dev/null +++ b/testsuite/tests/numeric/should_run/T19931.hs @@ -0,0 +1,35 @@ +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE UnboxedTuples #-} + +module Main where + +import GHC.Exts +import GHC.Types +import GHC.Num + +data T = T Word8# + +instance Num T where + fromInteger i = T (wordToWord8# (integerToWord# i)) + +instance Eq T where + (==) (T a) (T b) = isTrue# (a `eqWord8#` b) + (/=) (T a) (T b) = isTrue# (a `neWord8#` b) + +main :: IO () +main = do + let !addr = "\0\1\2\3\4\5\6\7\8"# + + w8 <- IO (\s -> case readWord8OffAddr# (plusAddr# addr 5#) 0# s of + (# s', w8 #) -> (# s', T w8 #)) + -- w8 must be small enough for one of the branch to be taken. + -- we need several alternatives for a jump table to be used + print $ case w8 of + 0 -> 1000 + 1 -> 1001 + 2 -> 1002 + 3 -> 1003 + 4 -> 1004 + 5 -> 1005 + 6 -> 1006 + _ -> 1010 diff --git a/testsuite/tests/numeric/should_run/T19931.stdout b/testsuite/tests/numeric/should_run/T19931.stdout new file mode 100644 index 0000000000..49bc2728c7 --- /dev/null +++ b/testsuite/tests/numeric/should_run/T19931.stdout @@ -0,0 +1 @@ +1005 diff --git a/testsuite/tests/numeric/should_run/all.T b/testsuite/tests/numeric/should_run/all.T index 028677e52d..1123984bdd 100644 --- a/testsuite/tests/numeric/should_run/all.T +++ b/testsuite/tests/numeric/should_run/all.T @@ -74,5 +74,6 @@ test('T18499', normal, compile_and_run, ['']) test('T18509', normal, compile_and_run, ['']) test('T18515', normal, compile_and_run, ['']) test('T18604', normal, compile_and_run, ['']) +test('T19931', normal, compile_and_run, ['-O2']) test('IntegerToFloat', normal, compile_and_run, ['']) |