diff options
-rw-r--r-- | compiler/GHC/Cmm/CallConv.hs | 16 | ||||
-rw-r--r-- | compiler/GHC/Cmm/Parser.y | 3 | ||||
-rw-r--r-- | compiler/GHC/StgToCmm/Foreign.hs | 29 | ||||
-rw-r--r-- | compiler/GHC/StgToCmm/Utils.hs | 17 | ||||
-rw-r--r-- | includes/Cmm.h | 69 | ||||
-rw-r--r-- | rts/StgMiscClosures.cmm | 4 |
6 files changed, 54 insertions, 84 deletions
diff --git a/compiler/GHC/Cmm/CallConv.hs b/compiler/GHC/Cmm/CallConv.hs index 35f63661fa..b1133896a7 100644 --- a/compiler/GHC/Cmm/CallConv.hs +++ b/compiler/GHC/Cmm/CallConv.hs @@ -206,9 +206,13 @@ realArgRegsCover dflags | passFloatArgsInXmm (targetPlatform dflags) = map ($VGcPtr) (realVanillaRegs dflags) ++ realLongRegs dflags ++ - map XmmReg (realXmmRegNos dflags) - | otherwise = map ($VGcPtr) (realVanillaRegs dflags) ++ - realFloatRegs dflags ++ - realDoubleRegs dflags ++ - realLongRegs dflags ++ - map XmmReg (realXmmRegNos dflags) + realDoubleRegs dflags -- we only need to save the low Double part of XMM registers. + -- Moreover, the NCG can't load/store full XMM + -- registers for now... + + | otherwise + = map ($VGcPtr) (realVanillaRegs dflags) ++ + realFloatRegs dflags ++ + realDoubleRegs dflags ++ + realLongRegs dflags + -- we don't save XMM registers if they are not used for parameter passing diff --git a/compiler/GHC/Cmm/Parser.y b/compiler/GHC/Cmm/Parser.y index 1c9f0ad041..e3d7e93486 100644 --- a/compiler/GHC/Cmm/Parser.y +++ b/compiler/GHC/Cmm/Parser.y @@ -1115,6 +1115,9 @@ stmtMacros = listToUFM [ ( fsLit "LOAD_THREAD_STATE", \[] -> emitLoadThreadState ), ( fsLit "SAVE_THREAD_STATE", \[] -> emitSaveThreadState ), + ( fsLit "SAVE_REGS", \[] -> emitSaveRegs ), + ( fsLit "RESTORE_REGS", \[] -> emitRestoreRegs ), + ( fsLit "LDV_ENTER", \[e] -> ldvEnter e ), ( fsLit "LDV_RECORD_CREATE", \[e] -> ldvRecordCreate e ), diff --git a/compiler/GHC/StgToCmm/Foreign.hs b/compiler/GHC/StgToCmm/Foreign.hs index 0681d41f96..87e4ae6ccb 100644 --- a/compiler/GHC/StgToCmm/Foreign.hs +++ b/compiler/GHC/StgToCmm/Foreign.hs @@ -13,6 +13,8 @@ module GHC.StgToCmm.Foreign ( emitSaveThreadState, saveThreadState, emitLoadThreadState, + emitSaveRegs, + emitRestoreRegs, loadThreadState, emitOpenNursery, emitCloseNursery, @@ -32,6 +34,7 @@ import GHC.Cmm.BlockId (newBlockId) import GHC.Cmm import GHC.Cmm.Utils import GHC.Cmm.Graph +import GHC.Cmm.CallConv import GHC.Core.Type import GHC.Types.RepType import GHC.Cmm.CLabel @@ -308,6 +311,32 @@ saveThreadState dflags = do else mkNop ] + + +-- | Save STG registers +-- +-- STG registers must be saved around a C call, just in case the STG +-- register is mapped to a caller-saves machine register. Normally we +-- don't need to worry about this the code generator has already +-- loaded any live STG registers into variables for us, but in +-- hand-written low-level Cmm code where we don't know which registers +-- are live, we might have to save them all. +emitSaveRegs :: FCode () +emitSaveRegs = do + dflags <- getDynFlags + let regs = realArgRegsCover dflags + save = catAGraphs (map (callerSaveGlobalReg dflags) regs) + emit save + +-- | Restore STG registers (see 'emitSaveRegs') +emitRestoreRegs :: FCode () +emitRestoreRegs = do + dflags <- getDynFlags + let regs = realArgRegsCover dflags + save = catAGraphs (map (callerRestoreGlobalReg dflags) regs) + emit save + + emitCloseNursery :: FCode () emitCloseNursery = do dflags <- getDynFlags diff --git a/compiler/GHC/StgToCmm/Utils.hs b/compiler/GHC/StgToCmm/Utils.hs index 2814948189..27c79a8e62 100644 --- a/compiler/GHC/StgToCmm/Utils.hs +++ b/compiler/GHC/StgToCmm/Utils.hs @@ -23,6 +23,7 @@ module GHC.StgToCmm.Utils ( tagToClosure, mkTaggedObjectLoad, callerSaves, callerSaveVolatileRegs, get_GlobalReg_addr, + callerSaveGlobalReg, callerRestoreGlobalReg, cmmAndWord, cmmOrWord, cmmNegate, cmmEqWord, cmmNeWord, cmmUGtWord, cmmSubWord, cmmMulWord, cmmAddWord, cmmUShrWord, @@ -249,8 +250,8 @@ callerSaveVolatileRegs dflags = (caller_save, caller_load) where platform = targetPlatform dflags - caller_save = catAGraphs (map callerSaveGlobalReg regs_to_save) - caller_load = catAGraphs (map callerRestoreGlobalReg regs_to_save) + caller_save = catAGraphs (map (callerSaveGlobalReg dflags) regs_to_save) + caller_load = catAGraphs (map (callerRestoreGlobalReg dflags) regs_to_save) system_regs = [ Sp,SpLim,Hp,HpLim,CCCS,CurrentTSO,CurrentNursery {- ,SparkHd,SparkTl,SparkBase,SparkLim -} @@ -258,12 +259,14 @@ callerSaveVolatileRegs dflags = (caller_save, caller_load) regs_to_save = filter (callerSaves platform) system_regs - callerSaveGlobalReg reg - = mkStore (get_GlobalReg_addr dflags reg) (CmmReg (CmmGlobal reg)) +callerSaveGlobalReg :: DynFlags -> GlobalReg -> CmmAGraph +callerSaveGlobalReg dflags reg + = mkStore (get_GlobalReg_addr dflags reg) (CmmReg (CmmGlobal reg)) - callerRestoreGlobalReg reg - = mkAssign (CmmGlobal reg) - (CmmLoad (get_GlobalReg_addr dflags reg) (globalRegType platform reg)) +callerRestoreGlobalReg :: DynFlags -> GlobalReg -> CmmAGraph +callerRestoreGlobalReg dflags reg + = mkAssign (CmmGlobal reg) + (CmmLoad (get_GlobalReg_addr dflags reg) (globalRegType (targetPlatform dflags) reg)) ------------------------------------------------------------------------- diff --git a/includes/Cmm.h b/includes/Cmm.h index 349d6985f8..fc80ff76aa 100644 --- a/includes/Cmm.h +++ b/includes/Cmm.h @@ -740,75 +740,6 @@ TICK_BUMP_BY(ALLOC_RTS_tot,bytes) /* ----------------------------------------------------------------------------- - Saving and restoring STG registers - - STG registers must be saved around a C call, just in case the STG - register is mapped to a caller-saves machine register. Normally we - don't need to worry about this the code generator has already - loaded any live STG registers into variables for us, but in - hand-written low-level Cmm code where we don't know which registers - are live, we might have to save them all. - -------------------------------------------------------------------------- */ - -#define SAVE_STGREGS \ - W_ r1, r2, r3, r4, r5, r6, r7, r8; \ - F_ f1, f2, f3, f4, f5, f6; \ - D_ d1, d2, d3, d4, d5, d6; \ - L_ l1; \ - \ - r1 = R1; \ - r2 = R2; \ - r3 = R3; \ - r4 = R4; \ - r5 = R5; \ - r6 = R6; \ - r7 = R7; \ - r8 = R8; \ - \ - f1 = F1; \ - f2 = F2; \ - f3 = F3; \ - f4 = F4; \ - f5 = F5; \ - f6 = F6; \ - \ - d1 = D1; \ - d2 = D2; \ - d3 = D3; \ - d4 = D4; \ - d5 = D5; \ - d6 = D6; \ - \ - l1 = L1; - - -#define RESTORE_STGREGS \ - R1 = r1; \ - R2 = r2; \ - R3 = r3; \ - R4 = r4; \ - R5 = r5; \ - R6 = r6; \ - R7 = r7; \ - R8 = r8; \ - \ - F1 = f1; \ - F2 = f2; \ - F3 = f3; \ - F4 = f4; \ - F5 = f5; \ - F6 = f6; \ - \ - D1 = d1; \ - D2 = d2; \ - D3 = d3; \ - D4 = d4; \ - D5 = d5; \ - D6 = d6; \ - \ - L1 = l1; - -/* ----------------------------------------------------------------------------- Misc junk -------------------------------------------------------------------------- */ diff --git a/rts/StgMiscClosures.cmm b/rts/StgMiscClosures.cmm index 85c1ad398e..4293dfb787 100644 --- a/rts/StgMiscClosures.cmm +++ b/rts/StgMiscClosures.cmm @@ -31,14 +31,14 @@ INFO_TABLE_RET (stg_stack_underflow_frame, UNDERFLOW_FRAME, W_ new_tso; W_ ret_off; - SAVE_STGREGS + SAVE_REGS(); SAVE_THREAD_STATE(); (ret_off) = foreign "C" threadStackUnderflow(MyCapability() "ptr", CurrentTSO); LOAD_THREAD_STATE(); - RESTORE_STGREGS + RESTORE_REGS(); jump %ENTRY_CODE(Sp(ret_off)) [*]; // NB. all registers live! } |