Fix codegen bug in PIC version of genSwitch (#12433)
authorSimon Marlow <marlowsd@gmail.com>
Thu, 15 Sep 2016 09:11:34 +0000 (10:11 +0100)
committerSimon Marlow <marlowsd@gmail.com>
Thu, 15 Sep 2016 12:23:36 +0000 (13:23 +0100)
Summary:
* getNonClobberedReg instead of getSomeReg, because the reg needs to
  survive across t_code
* Use a new reg for the table offset calculation instead of clobbering
  the reg returned by expr (this was the bug affecting #12433)

Test Plan: New unit test; validate

Reviewers: rwbarton, bgamari, austin, erikd

Subscribers: thomie

Differential Revision: https://phabricator.haskell.org/D2529

GHC Trac Issues: #12433

compiler/nativeGen/X86/CodeGen.hs
testsuite/tests/codeGen/should_run/T12433.stdout [new file with mode: 0644]
testsuite/tests/codeGen/should_run/all.T

index cd45d92..4401f38 100644 (file)
@@ -2603,7 +2603,8 @@ genSwitch :: DynFlags -> CmmExpr -> SwitchTargets -> NatM InstrBlock
 genSwitch dflags expr targets
   | gopt Opt_PIC dflags
   = do
-        (reg,e_code) <- getSomeReg (cmmOffset dflags expr offset)
+        (reg,e_code) <- getNonClobberedReg (cmmOffset dflags expr offset)
+           -- getNonClobberedReg because it needs to survive across t_code
         lbl <- getNewLabelNat
         dflags <- getDynFlags
         let is32bit = target32Bit (targetPlatform dflags)
@@ -2624,6 +2625,7 @@ genSwitch dflags expr targets
         let op = OpAddr (AddrBaseIndex (EABaseReg tableReg)
                                        (EAIndex reg (wORD_SIZE dflags)) (ImmInt 0))
 
+        offsetReg <- getNewRegNat (intFormat (wordWidth dflags))
         return $ if is32bit || os == OSDarwin
                  then e_code `appOL` t_code `appOL` toOL [
                                 ADD (intFormat (wordWidth dflags)) op (OpReg tableReg),
@@ -2636,8 +2638,9 @@ genSwitch dflags expr targets
                       -- hack should be removed in conjunction with the hack in
                       -- PprMach.hs/pprDataItem once binutils 2.17 is standard.
                       e_code `appOL` t_code `appOL` toOL [
-                               MOVSxL II32 op (OpReg reg),
-                               ADD (intFormat (wordWidth dflags)) (OpReg reg)
+                               MOVSxL II32 op (OpReg offsetReg),
+                               ADD (intFormat (wordWidth dflags))
+                                   (OpReg offsetReg)
                                    (OpReg tableReg),
                                JMP_TBL (OpReg tableReg) ids rosection lbl
                        ]
diff --git a/testsuite/tests/codeGen/should_run/T12433.stdout b/testsuite/tests/codeGen/should_run/T12433.stdout
new file mode 100644 (file)
index 0000000..45a4fb7
--- /dev/null
@@ -0,0 +1 @@
+8
index ee8772b..65e3dc0 100644 (file)
@@ -143,4 +143,4 @@ test('T10870', when(wordsize(32), skip), compile_and_run, [''])
 test('PopCnt', omit_ways(['ghci']), multi_compile_and_run,
                  ['PopCnt', [('PopCnt_cmm.cmm', '')], ''])
 test('T12059', normal, compile_and_run, [''])
-test('T12433', expect_broken(12433), compile_and_run, [''])
+test('T12433', normal, compile_and_run, [''])