X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2FcodeGen%2FCgUtils.hs;h=02f53c24545ec7d4f8dddd96660617d74835df8b;hb=48fb2b521898998a17873ad6cf30610aa5ab6db3;hp=c48b584fda43ada42ee937ccfc5e6d9de72e7268;hpb=d31dfb32ea936c22628b508c28a36c12e631430a;p=ghc-hetmet.git diff --git a/compiler/codeGen/CgUtils.hs b/compiler/codeGen/CgUtils.hs index c48b584..02f53c2 100644 --- a/compiler/codeGen/CgUtils.hs +++ b/compiler/codeGen/CgUtils.hs @@ -19,6 +19,8 @@ module CgUtils ( emitSwitch, emitLitSwitch, tagToClosure, + callerSaveVolatileRegs, get_GlobalReg_addr, + cmmAndWord, cmmOrWord, cmmNegate, cmmEqWord, cmmNeWord, cmmOffsetExprW, cmmOffsetExprB, cmmRegOffW, cmmRegOffB, @@ -37,6 +39,7 @@ module CgUtils ( ) where #include "HsVersions.h" +#include "MachRegs.h" import CgMonad import TyCon @@ -60,12 +63,6 @@ import FastString import PackageConfig import Outputable -import MachRegs (callerSaveVolatileRegs) - -- HACK: this is part of the NCG so we shouldn't use this, but we need - -- it for now to eliminate the need for saved regs to be in CmmCall. - -- The long term solution is to factor callerSaveVolatileRegs - -- from nativeGen into codeGen - import Data.Char import Data.Bits import Data.Word @@ -302,6 +299,188 @@ emitRtsCall' res fun args vols safe = do target = CmmForeignCall fun_expr CCallConv fun_expr = mkLblExpr (mkRtsCodeLabel fun) +----------------------------------------------------------------------------- +-- +-- Caller-Save Registers +-- +----------------------------------------------------------------------------- + +-- Here we generate the sequence of saves/restores required around a +-- foreign call instruction. + +-- TODO: reconcile with includes/Regs.h +-- * Regs.h claims that BaseReg should be saved last and loaded first +-- * This might not have been tickled before since BaseReg is callee save +-- * Regs.h saves SparkHd, ParkT1, SparkBase and SparkLim +callerSaveVolatileRegs :: Maybe [GlobalReg] -> ([CmmStmt], [CmmStmt]) +callerSaveVolatileRegs vols = (caller_save, caller_load) + where + caller_save = foldr ($!) [] (map callerSaveGlobalReg regs_to_save) + caller_load = foldr ($!) [] (map callerRestoreGlobalReg regs_to_save) + + system_regs = [Sp,SpLim,Hp,HpLim,CurrentTSO,CurrentNursery, + {-SparkHd,SparkTl,SparkBase,SparkLim,-}BaseReg ] + + regs_to_save = system_regs ++ vol_list + + vol_list = case vols of Nothing -> all_of_em; Just regs -> regs + + all_of_em = [ VanillaReg n | n <- [0..mAX_Vanilla_REG] ] + ++ [ FloatReg n | n <- [0..mAX_Float_REG] ] + ++ [ DoubleReg n | n <- [0..mAX_Double_REG] ] + ++ [ LongReg n | n <- [0..mAX_Long_REG] ] + + callerSaveGlobalReg reg next + | callerSaves reg = + CmmStore (get_GlobalReg_addr reg) + (CmmReg (CmmGlobal reg)) : next + | otherwise = next + + callerRestoreGlobalReg reg next + | callerSaves reg = + CmmAssign (CmmGlobal reg) + (CmmLoad (get_GlobalReg_addr reg) (globalRegRep reg)) + : next + | otherwise = next + +-- ----------------------------------------------------------------------------- +-- Global registers + +-- We map STG registers onto appropriate CmmExprs. Either they map +-- to real machine registers or stored as offsets from BaseReg. Given +-- a GlobalReg, get_GlobalReg_addr always produces the +-- register table address for it. +-- (See also get_GlobalReg_reg_or_addr in MachRegs) + +get_GlobalReg_addr :: GlobalReg -> CmmExpr +get_GlobalReg_addr BaseReg = regTableOffset 0 +get_GlobalReg_addr mid = get_Regtable_addr_from_offset + (globalRegRep mid) (baseRegOffset mid) + +-- Calculate a literal representing an offset into the register table. +-- Used when we don't have an actual BaseReg to offset from. +regTableOffset n = + CmmLit (CmmLabelOff mkMainCapabilityLabel (oFFSET_Capability_r + n)) + +get_Regtable_addr_from_offset :: MachRep -> Int -> CmmExpr +get_Regtable_addr_from_offset rep offset = +#ifdef REG_Base + CmmRegOff (CmmGlobal BaseReg) offset +#else + regTableOffset offset +#endif + + +-- | Returns 'True' if this global register is stored in a caller-saves +-- machine register. + +callerSaves :: GlobalReg -> Bool + +#ifdef CALLER_SAVES_Base +callerSaves BaseReg = True +#endif +#ifdef CALLER_SAVES_R1 +callerSaves (VanillaReg 1) = True +#endif +#ifdef CALLER_SAVES_R2 +callerSaves (VanillaReg 2) = True +#endif +#ifdef CALLER_SAVES_R3 +callerSaves (VanillaReg 3) = True +#endif +#ifdef CALLER_SAVES_R4 +callerSaves (VanillaReg 4) = True +#endif +#ifdef CALLER_SAVES_R5 +callerSaves (VanillaReg 5) = True +#endif +#ifdef CALLER_SAVES_R6 +callerSaves (VanillaReg 6) = True +#endif +#ifdef CALLER_SAVES_R7 +callerSaves (VanillaReg 7) = True +#endif +#ifdef CALLER_SAVES_R8 +callerSaves (VanillaReg 8) = True +#endif +#ifdef CALLER_SAVES_F1 +callerSaves (FloatReg 1) = True +#endif +#ifdef CALLER_SAVES_F2 +callerSaves (FloatReg 2) = True +#endif +#ifdef CALLER_SAVES_F3 +callerSaves (FloatReg 3) = True +#endif +#ifdef CALLER_SAVES_F4 +callerSaves (FloatReg 4) = True +#endif +#ifdef CALLER_SAVES_D1 +callerSaves (DoubleReg 1) = True +#endif +#ifdef CALLER_SAVES_D2 +callerSaves (DoubleReg 2) = True +#endif +#ifdef CALLER_SAVES_L1 +callerSaves (LongReg 1) = True +#endif +#ifdef CALLER_SAVES_Sp +callerSaves Sp = True +#endif +#ifdef CALLER_SAVES_SpLim +callerSaves SpLim = True +#endif +#ifdef CALLER_SAVES_Hp +callerSaves Hp = True +#endif +#ifdef CALLER_SAVES_HpLim +callerSaves HpLim = True +#endif +#ifdef CALLER_SAVES_CurrentTSO +callerSaves CurrentTSO = True +#endif +#ifdef CALLER_SAVES_CurrentNursery +callerSaves CurrentNursery = True +#endif +callerSaves _ = False + + +-- ----------------------------------------------------------------------------- +-- Information about global registers + +baseRegOffset :: GlobalReg -> Int + +baseRegOffset (VanillaReg 1) = oFFSET_StgRegTable_rR1 +baseRegOffset (VanillaReg 2) = oFFSET_StgRegTable_rR2 +baseRegOffset (VanillaReg 3) = oFFSET_StgRegTable_rR3 +baseRegOffset (VanillaReg 4) = oFFSET_StgRegTable_rR4 +baseRegOffset (VanillaReg 5) = oFFSET_StgRegTable_rR5 +baseRegOffset (VanillaReg 6) = oFFSET_StgRegTable_rR6 +baseRegOffset (VanillaReg 7) = oFFSET_StgRegTable_rR7 +baseRegOffset (VanillaReg 8) = oFFSET_StgRegTable_rR8 +baseRegOffset (VanillaReg 9) = oFFSET_StgRegTable_rR9 +baseRegOffset (VanillaReg 10) = oFFSET_StgRegTable_rR10 +baseRegOffset (FloatReg 1) = oFFSET_StgRegTable_rF1 +baseRegOffset (FloatReg 2) = oFFSET_StgRegTable_rF2 +baseRegOffset (FloatReg 3) = oFFSET_StgRegTable_rF3 +baseRegOffset (FloatReg 4) = oFFSET_StgRegTable_rF4 +baseRegOffset (DoubleReg 1) = oFFSET_StgRegTable_rD1 +baseRegOffset (DoubleReg 2) = oFFSET_StgRegTable_rD2 +baseRegOffset Sp = oFFSET_StgRegTable_rSp +baseRegOffset SpLim = oFFSET_StgRegTable_rSpLim +baseRegOffset (LongReg 1) = oFFSET_StgRegTable_rL1 +baseRegOffset Hp = oFFSET_StgRegTable_rHp +baseRegOffset HpLim = oFFSET_StgRegTable_rHpLim +baseRegOffset CurrentTSO = oFFSET_StgRegTable_rCurrentTSO +baseRegOffset CurrentNursery = oFFSET_StgRegTable_rCurrentNursery +baseRegOffset HpAlloc = oFFSET_StgRegTable_rHpAlloc +baseRegOffset GCEnter1 = oFFSET_stgGCEnter1 +baseRegOffset GCFun = oFFSET_stgGCFun +#ifdef DEBUG +baseRegOffset BaseReg = panic "baseRegOffset:BaseReg" +baseRegOffset _ = panic "baseRegOffset:other" +#endif + ------------------------------------------------------------------------- --