diff options
author | Ian Lynagh <igloo@earth.li> | 2011-09-09 00:02:04 +0100 |
---|---|---|
committer | Ian Lynagh <igloo@earth.li> | 2011-09-11 13:50:43 +0100 |
commit | 2818cfd7f2b953035ce00178c8d5f2be073af0b7 (patch) | |
tree | a733d6599993a2be85c4b038fc2950fd09e02cff /compiler/codeGen | |
parent | f5084f66d37d22b41e0ed9681a399ff3a3de1e6a (diff) | |
download | haskell-2818cfd7f2b953035ce00178c8d5f2be073af0b7.tar.gz |
Whitespace only in codeGen/CgUtils.hs
Diffstat (limited to 'compiler/codeGen')
-rw-r--r-- | compiler/codeGen/CgUtils.hs | 592 |
1 files changed, 296 insertions, 296 deletions
diff --git a/compiler/codeGen/CgUtils.hs b/compiler/codeGen/CgUtils.hs index 2fed13e452..1e7f0fc7ea 100644 --- a/compiler/codeGen/CgUtils.hs +++ b/compiler/codeGen/CgUtils.hs @@ -14,40 +14,40 @@ ----------------------------------------------------------------------------- module CgUtils ( - addIdReps, - cgLit, - emitDataLits, mkDataLits, + addIdReps, + cgLit, + emitDataLits, mkDataLits, emitRODataLits, mkRODataLits, emitIf, emitIfThenElse, - emitRtsCall, emitRtsCallWithVols, emitRtsCallWithResult, - assignTemp, assignTemp_, newTemp, - emitSimultaneously, - emitSwitch, emitLitSwitch, - tagToClosure, + emitRtsCall, emitRtsCallWithVols, emitRtsCallWithResult, + assignTemp, assignTemp_, newTemp, + emitSimultaneously, + emitSwitch, emitLitSwitch, + tagToClosure, callerSaves, callerSaveVolatileRegs, get_GlobalReg_addr, - activeStgRegs, fixStgRegisters, + activeStgRegs, fixStgRegisters, - cmmAndWord, cmmOrWord, cmmNegate, cmmEqWord, cmmNeWord, + cmmAndWord, cmmOrWord, cmmNegate, cmmEqWord, cmmNeWord, cmmUGtWord, cmmSubWord, cmmMulWord, cmmAddWord, cmmUShrWord, - cmmOffsetExprW, cmmOffsetExprB, - cmmRegOffW, cmmRegOffB, - cmmLabelOffW, cmmLabelOffB, - cmmOffsetW, cmmOffsetB, - cmmOffsetLitW, cmmOffsetLitB, - cmmLoadIndexW, + cmmOffsetExprW, cmmOffsetExprB, + cmmRegOffW, cmmRegOffB, + cmmLabelOffW, cmmLabelOffB, + cmmOffsetW, cmmOffsetB, + cmmOffsetLitW, cmmOffsetLitB, + cmmLoadIndexW, cmmConstrTag, cmmConstrTag1, tagForCon, tagCons, isSmallFamily, cmmUntag, cmmIsTagged, cmmGetTag, - addToMem, addToMemE, - mkWordCLit, - newStringCLit, newByteStringCLit, - packHalfWordsCLit, - blankWord, + addToMem, addToMemE, + mkWordCLit, + newStringCLit, newByteStringCLit, + packHalfWordsCLit, + blankWord, - getSRTInfo + getSRTInfo ) where #include "HsVersions.h" @@ -84,7 +84,7 @@ import Data.Maybe ------------------------------------------------------------------------- -- --- Random small functions +-- Random small functions -- ------------------------------------------------------------------------- @@ -93,7 +93,7 @@ addIdReps ids = [(idCgRep id, id) | id <- ids] ------------------------------------------------------------------------- -- --- Literals +-- Literals -- ------------------------------------------------------------------------- @@ -103,7 +103,7 @@ cgLit (MachStr s) = newByteStringCLit (bytesFS s) cgLit other_lit = return (mkSimpleLit other_lit) mkSimpleLit :: Literal -> CmmLit -mkSimpleLit (MachChar c) = CmmInt (fromIntegral (ord c)) wordWidth +mkSimpleLit (MachChar c) = CmmInt (fromIntegral (ord c)) wordWidth mkSimpleLit MachNullAddr = zeroCLit mkSimpleLit (MachInt i) = CmmInt i wordWidth mkSimpleLit (MachInt64 i) = CmmInt i W64 @@ -111,23 +111,23 @@ mkSimpleLit (MachWord i) = CmmInt i wordWidth mkSimpleLit (MachWord64 i) = CmmInt i W64 mkSimpleLit (MachFloat r) = CmmFloat r W32 mkSimpleLit (MachDouble r) = CmmFloat r W64 -mkSimpleLit (MachLabel fs ms fod) - = CmmLabel (mkForeignLabel fs ms labelSrc fod) - where - -- TODO: Literal labels might not actually be in the current package... - labelSrc = ForeignLabelInThisPackage - +mkSimpleLit (MachLabel fs ms fod) + = CmmLabel (mkForeignLabel fs ms labelSrc fod) + where + -- TODO: Literal labels might not actually be in the current package... + labelSrc = ForeignLabelInThisPackage + mkLtOp :: Literal -> MachOp -- On signed literals we must do a signed comparison mkLtOp (MachInt _) = MO_S_Lt wordWidth mkLtOp (MachFloat _) = MO_F_Lt W32 mkLtOp (MachDouble _) = MO_F_Lt W64 -mkLtOp lit = MO_U_Lt (typeWidth (cmmLitType (mkSimpleLit lit))) +mkLtOp lit = MO_U_Lt (typeWidth (cmmLitType (mkSimpleLit lit))) --------------------------------------------------- -- --- Cmm data type functions +-- Cmm data type functions -- --------------------------------------------------- @@ -162,22 +162,22 @@ tagCons con expr = cmmOffsetB expr (tagForCon con) -- -------------------------------------------------------------------------- -addToMem :: Width -- rep of the counter - -> CmmExpr -- Address - -> Int -- What to add (a word) - -> CmmStmt +addToMem :: Width -- rep of the counter + -> CmmExpr -- Address + -> Int -- What to add (a word) + -> CmmStmt addToMem width ptr n = addToMemE width ptr (CmmLit (CmmInt (toInteger n) width)) -addToMemE :: Width -- rep of the counter - -> CmmExpr -- Address - -> CmmExpr -- What to add (a word-typed expression) - -> CmmStmt +addToMemE :: Width -- rep of the counter + -> CmmExpr -- Address + -> CmmExpr -- What to add (a word-typed expression) + -> CmmStmt addToMemE width ptr n = CmmStore ptr (CmmMachOp (MO_Add width) [CmmLoad ptr (cmmBits width), n]) ------------------------------------------------------------------------- -- --- Converting a closure tag to a closure for enumeration types +-- Converting a closure tag to a closure for enumeration types -- (this is the implementation of tagToEnum#). -- ------------------------------------------------------------------------- @@ -186,17 +186,17 @@ tagToClosure :: TyCon -> CmmExpr -> CmmExpr tagToClosure tycon tag = CmmLoad (cmmOffsetExprW closure_tbl tag) gcWord where closure_tbl = CmmLit (CmmLabel lbl) - lbl = mkClosureTableLabel (tyConName tycon) NoCafRefs + lbl = mkClosureTableLabel (tyConName tycon) NoCafRefs ------------------------------------------------------------------------- -- --- Conditionals and rts calls +-- Conditionals and rts calls -- ------------------------------------------------------------------------- -emitIf :: CmmExpr -- Boolean - -> Code -- Then part - -> Code +emitIf :: CmmExpr -- Boolean + -> Code -- Then part + -> Code -- Emit (if e then x) -- ToDo: reverse the condition to avoid the extra branch instruction if possible -- (some conditionals aren't reversible. eg. floating point comparisons cannot @@ -212,10 +212,10 @@ emitIf cond then_part ; labelC join_id } -emitIfThenElse :: CmmExpr -- Boolean - -> Code -- Then part - -> Code -- Else part - -> Code +emitIfThenElse :: CmmExpr -- Boolean + -> Code -- Then part + -> Code -- Else part + -> Code -- Emit (if e then x else y) emitIfThenElse cond then_part else_part = do { then_id <- newLabelC @@ -230,12 +230,12 @@ emitIfThenElse cond then_part else_part -- | Emit code to call a Cmm function. -emitRtsCall - :: PackageId -- ^ package the function is in - -> FastString -- ^ name of function - -> [CmmHinted CmmExpr] -- ^ function args - -> Bool -- ^ whether this is a safe call - -> Code -- ^ cmm code +emitRtsCall + :: PackageId -- ^ package the function is in + -> FastString -- ^ name of function + -> [CmmHinted CmmExpr] -- ^ function args + -> Bool -- ^ whether this is a safe call + -> Code -- ^ cmm code emitRtsCall pkg fun args safe = emitRtsCall' [] pkg fun args Nothing safe -- The 'Nothing' says "save all global registers" @@ -244,8 +244,8 @@ emitRtsCallWithVols :: PackageId -> FastString -> [CmmHinted CmmExpr] -> [Global emitRtsCallWithVols pkg fun args vols safe = emitRtsCall' [] pkg fun args (Just vols) safe -emitRtsCallWithResult - :: LocalReg -> ForeignHint +emitRtsCallWithResult + :: LocalReg -> ForeignHint -> PackageId -> FastString -> [CmmHinted CmmExpr] -> Bool -> Code emitRtsCallWithResult res hint pkg fun args safe @@ -274,7 +274,7 @@ emitRtsCall' res pkg fun args vols safe = do ----------------------------------------------------------------------------- -- --- Caller-Save Registers +-- Caller-Save Registers -- ----------------------------------------------------------------------------- @@ -292,30 +292,30 @@ callerSaveVolatileRegs vols = (caller_save, caller_load) caller_load = foldr ($!) [] (map callerRestoreGlobalReg regs_to_save) system_regs = [Sp,SpLim,Hp,HpLim,CurrentTSO,CurrentNursery, - {-SparkHd,SparkTl,SparkBase,SparkLim,-}BaseReg ] + {-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 VNonGcPtr | n <- [0..mAX_Vanilla_REG] ] - -- The VNonGcPtr is a lie, but I don't think it matters - ++ [ FloatReg n | n <- [0..mAX_Float_REG] ] - ++ [ DoubleReg n | n <- [0..mAX_Double_REG] ] - ++ [ LongReg n | n <- [0..mAX_Long_REG] ] + -- The VNonGcPtr is a lie, but I don't think it matters + ++ [ 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 + | 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) (globalRegType reg)) - : next - | otherwise = next + | callerSaves reg = + CmmAssign (CmmGlobal reg) + (CmmLoad (get_GlobalReg_addr reg) (globalRegType reg)) + : next + | otherwise = next -- | Returns @True@ if this global register is stored in a caller-saves @@ -324,72 +324,72 @@ callerSaveVolatileRegs vols = (caller_save, caller_load) callerSaves :: GlobalReg -> Bool #ifdef CALLER_SAVES_Base -callerSaves BaseReg = True +callerSaves BaseReg = True #endif #ifdef CALLER_SAVES_R1 -callerSaves (VanillaReg 1 _) = True +callerSaves (VanillaReg 1 _) = True #endif #ifdef CALLER_SAVES_R2 -callerSaves (VanillaReg 2 _) = True +callerSaves (VanillaReg 2 _) = True #endif #ifdef CALLER_SAVES_R3 -callerSaves (VanillaReg 3 _) = True +callerSaves (VanillaReg 3 _) = True #endif #ifdef CALLER_SAVES_R4 -callerSaves (VanillaReg 4 _) = True +callerSaves (VanillaReg 4 _) = True #endif #ifdef CALLER_SAVES_R5 -callerSaves (VanillaReg 5 _) = True +callerSaves (VanillaReg 5 _) = True #endif #ifdef CALLER_SAVES_R6 -callerSaves (VanillaReg 6 _) = True +callerSaves (VanillaReg 6 _) = True #endif #ifdef CALLER_SAVES_R7 -callerSaves (VanillaReg 7 _) = True +callerSaves (VanillaReg 7 _) = True #endif #ifdef CALLER_SAVES_R8 -callerSaves (VanillaReg 8 _) = True +callerSaves (VanillaReg 8 _) = True #endif #ifdef CALLER_SAVES_F1 -callerSaves (FloatReg 1) = True +callerSaves (FloatReg 1) = True #endif #ifdef CALLER_SAVES_F2 -callerSaves (FloatReg 2) = True +callerSaves (FloatReg 2) = True #endif #ifdef CALLER_SAVES_F3 -callerSaves (FloatReg 3) = True +callerSaves (FloatReg 3) = True #endif #ifdef CALLER_SAVES_F4 -callerSaves (FloatReg 4) = True +callerSaves (FloatReg 4) = True #endif #ifdef CALLER_SAVES_D1 -callerSaves (DoubleReg 1) = True +callerSaves (DoubleReg 1) = True #endif #ifdef CALLER_SAVES_D2 -callerSaves (DoubleReg 2) = True +callerSaves (DoubleReg 2) = True #endif #ifdef CALLER_SAVES_L1 -callerSaves (LongReg 1) = True +callerSaves (LongReg 1) = True #endif #ifdef CALLER_SAVES_Sp -callerSaves Sp = True +callerSaves Sp = True #endif #ifdef CALLER_SAVES_SpLim -callerSaves SpLim = True +callerSaves SpLim = True #endif #ifdef CALLER_SAVES_Hp -callerSaves Hp = True +callerSaves Hp = True #endif #ifdef CALLER_SAVES_HpLim -callerSaves HpLim = True +callerSaves HpLim = True #endif #ifdef CALLER_SAVES_CurrentTSO -callerSaves CurrentTSO = True +callerSaves CurrentTSO = True #endif #ifdef CALLER_SAVES_CurrentNursery -callerSaves CurrentNursery = True +callerSaves CurrentNursery = True #endif -callerSaves _ = False +callerSaves _ = False -- ----------------------------------------------------------------------------- @@ -413,24 +413,24 @@ 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 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 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 EagerBlackholeInfo = oFFSET_stgEagerBlackholeInfo -baseRegOffset GCEnter1 = oFFSET_stgGCEnter1 -baseRegOffset GCFun = oFFSET_stgGCFun -baseRegOffset BaseReg = panic "baseRegOffset:BaseReg" -baseRegOffset _ = panic "baseRegOffset:other" +baseRegOffset GCEnter1 = oFFSET_stgGCEnter1 +baseRegOffset GCFun = oFFSET_stgGCFun +baseRegOffset BaseReg = panic "baseRegOffset:BaseReg" +baseRegOffset _ = panic "baseRegOffset:other" ------------------------------------------------------------------------- -- --- Strings generate a top-level data block +-- Strings generate a top-level data block -- ------------------------------------------------------------------------- @@ -450,14 +450,14 @@ newStringCLit str = newByteStringCLit (map (fromIntegral.ord) str) newByteStringCLit :: [Word8] -> FCode CmmLit newByteStringCLit bytes - = do { uniq <- newUnique - ; let (lit, decl) = mkByteStringCLit uniq bytes - ; emitDecl decl - ; return lit } + = do { uniq <- newUnique + ; let (lit, decl) = mkByteStringCLit uniq bytes + ; emitDecl decl + ; return lit } ------------------------------------------------------------------------- -- --- Assigning expressions to temporaries +-- Assigning expressions to temporaries -- ------------------------------------------------------------------------- @@ -467,11 +467,11 @@ newByteStringCLit bytes assignTemp :: CmmExpr -> FCode CmmExpr -- For a non-trivial expression, e, create a local -- variable and assign the expression to it -assignTemp e +assignTemp e | isTrivialCmmExpr e = return e - | otherwise = do { reg <- newTemp (cmmExprType e) - ; stmtC (CmmAssign (CmmLocal reg) e) - ; return (CmmReg (CmmLocal reg)) } + | otherwise = do { reg <- newTemp (cmmExprType e) + ; stmtC (CmmAssign (CmmLocal reg) e) + ; return (CmmReg (CmmLocal reg)) } -- | If the expression is trivial and doesn't refer to a global -- register, return it. Otherwise, assign the expression to a @@ -490,17 +490,17 @@ newTemp rep = do { uniq <- newUnique; return (LocalReg uniq rep) } ------------------------------------------------------------------------- -- --- Building case analysis +-- Building case analysis -- ------------------------------------------------------------------------- emitSwitch - :: CmmExpr -- Tag to switch on - -> [(ConTagZ, CgStmts)] -- Tagged branches - -> Maybe CgStmts -- Default branch (if any) - -> ConTagZ -> ConTagZ -- Min and Max possible values; behaviour - -- outside this range is undefined - -> Code + :: CmmExpr -- Tag to switch on + -> [(ConTagZ, CgStmts)] -- Tagged branches + -> Maybe CgStmts -- Default branch (if any) + -> ConTagZ -> ConTagZ -- Min and Max possible values; behaviour + -- outside this range is undefined + -> Code -- ONLY A DEFAULT BRANCH: no case analysis to do emitSwitch tag_expr [] (Just stmts) _ _ @@ -508,27 +508,27 @@ emitSwitch tag_expr [] (Just stmts) _ _ -- Right, off we go emitSwitch tag_expr branches mb_deflt lo_tag hi_tag - = -- Just sort the branches before calling mk_sritch - do { mb_deflt_id <- - case mb_deflt of - Nothing -> return Nothing - Just stmts -> do id <- forkCgStmts stmts; return (Just id) - - ; dflags <- getDynFlags - ; let via_C | HscC <- hscTarget dflags = True - | otherwise = False - - ; stmts <- mk_switch tag_expr (sortLe le branches) - mb_deflt_id lo_tag hi_tag via_C - ; emitCgStmts stmts - } + = -- Just sort the branches before calling mk_sritch + do { mb_deflt_id <- + case mb_deflt of + Nothing -> return Nothing + Just stmts -> do id <- forkCgStmts stmts; return (Just id) + + ; dflags <- getDynFlags + ; let via_C | HscC <- hscTarget dflags = True + | otherwise = False + + ; stmts <- mk_switch tag_expr (sortLe le branches) + mb_deflt_id lo_tag hi_tag via_C + ; emitCgStmts stmts + } where (t1,_) `le` (t2,_) = t1 <= t2 mk_switch :: CmmExpr -> [(ConTagZ, CgStmts)] - -> Maybe BlockId -> ConTagZ -> ConTagZ -> Bool - -> FCode CgStmts + -> Maybe BlockId -> ConTagZ -> ConTagZ -> Bool + -> FCode CgStmts -- SINGLETON TAG RANGE: no case analysis to do mk_switch tag_expr [(tag,stmts)] _ lo_tag hi_tag via_C @@ -539,19 +539,19 @@ mk_switch tag_expr [(tag,stmts)] _ lo_tag hi_tag via_C -- SINGLETON BRANCH, NO DEFUALT: no case analysis to do mk_switch tag_expr [(tag,stmts)] Nothing lo_tag hi_tag via_C = return stmts - -- The simplifier might have eliminated a case - -- so we may have e.g. case xs of - -- [] -> e - -- In that situation we can be sure the (:) case - -- can't happen, so no need to test + -- The simplifier might have eliminated a case + -- so we may have e.g. case xs of + -- [] -> e + -- In that situation we can be sure the (:) case + -- can't happen, so no need to test -- SINGLETON BRANCH: one equality check to do mk_switch tag_expr [(tag,stmts)] (Just deflt) lo_tag hi_tag via_C = return (CmmCondBranch cond deflt `consCgStmt` stmts) where cond = cmmNeWord tag_expr (CmmLit (mkIntCLit tag)) - -- We have lo_tag < hi_tag, but there's only one branch, - -- so there must be a default + -- We have lo_tag < hi_tag, but there's only one branch, + -- so there must be a default -- ToDo: we might want to check for the two branch case, where one of -- the branches is the tag 0, because comparing '== 0' is likely to be @@ -567,105 +567,105 @@ mk_switch tag_expr [(tag,stmts)] (Just deflt) lo_tag hi_tag via_C -- time works around that problem. -- mk_switch tag_expr branches mb_deflt lo_tag hi_tag via_C - | use_switch -- Use a switch - = do { branch_ids <- mapM forkCgStmts (map snd branches) - ; let - tagged_blk_ids = zip (map fst branches) (map Just branch_ids) + | use_switch -- Use a switch + = do { branch_ids <- mapM forkCgStmts (map snd branches) + ; let + tagged_blk_ids = zip (map fst branches) (map Just branch_ids) - find_branch :: ConTagZ -> Maybe BlockId - find_branch i = assocDefault mb_deflt tagged_blk_ids i + find_branch :: ConTagZ -> Maybe BlockId + find_branch i = assocDefault mb_deflt tagged_blk_ids i - -- NB. we have eliminated impossible branches at - -- either end of the range (see below), so the first - -- tag of a real branch is real_lo_tag (not lo_tag). - arms = [ find_branch i | i <- [real_lo_tag..real_hi_tag]] + -- NB. we have eliminated impossible branches at + -- either end of the range (see below), so the first + -- tag of a real branch is real_lo_tag (not lo_tag). + arms = [ find_branch i | i <- [real_lo_tag..real_hi_tag]] - switch_stmt = CmmSwitch (cmmOffset tag_expr (- real_lo_tag)) arms + switch_stmt = CmmSwitch (cmmOffset tag_expr (- real_lo_tag)) arms - ; ASSERT(not (all isNothing arms)) - return (oneCgStmt switch_stmt) - } + ; ASSERT(not (all isNothing arms)) + return (oneCgStmt switch_stmt) + } -- if we can knock off a bunch of default cases with one if, then do so | Just deflt <- mb_deflt, (lowest_branch - lo_tag) >= n_branches = do { (assign_tag, tag_expr') <- assignTemp' tag_expr ; let cond = cmmULtWord tag_expr' (CmmLit (mkIntCLit lowest_branch)) - branch = CmmCondBranch cond deflt - ; stmts <- mk_switch tag_expr' branches mb_deflt - lowest_branch hi_tag via_C + branch = CmmCondBranch cond deflt + ; stmts <- mk_switch tag_expr' branches mb_deflt + lowest_branch hi_tag via_C ; return (assign_tag `consCgStmt` (branch `consCgStmt` stmts)) } | Just deflt <- mb_deflt, (hi_tag - highest_branch) >= n_branches = do { (assign_tag, tag_expr') <- assignTemp' tag_expr ; let cond = cmmUGtWord tag_expr' (CmmLit (mkIntCLit highest_branch)) - branch = CmmCondBranch cond deflt - ; stmts <- mk_switch tag_expr' branches mb_deflt - lo_tag highest_branch via_C + branch = CmmCondBranch cond deflt + ; stmts <- mk_switch tag_expr' branches mb_deflt + lo_tag highest_branch via_C ; return (assign_tag `consCgStmt` (branch `consCgStmt` stmts)) } - | otherwise -- Use an if-tree - = do { (assign_tag, tag_expr') <- assignTemp' tag_expr - -- To avoid duplication - ; lo_stmts <- mk_switch tag_expr' lo_branches mb_deflt - lo_tag (mid_tag-1) via_C - ; hi_stmts <- mk_switch tag_expr' hi_branches mb_deflt - mid_tag hi_tag via_C - ; hi_id <- forkCgStmts hi_stmts - ; let cond = cmmUGeWord tag_expr' (CmmLit (mkIntCLit mid_tag)) - branch_stmt = CmmCondBranch cond hi_id - ; return (assign_tag `consCgStmt` (branch_stmt `consCgStmt` lo_stmts)) - } - -- we test (e >= mid_tag) rather than (e < mid_tag), because - -- the former works better when e is a comparison, and there - -- are two tags 0 & 1 (mid_tag == 1). In this case, the code - -- generator can reduce the condition to e itself without - -- having to reverse the sense of the comparison: comparisons - -- can't always be easily reversed (eg. floating - -- pt. comparisons). + | otherwise -- Use an if-tree + = do { (assign_tag, tag_expr') <- assignTemp' tag_expr + -- To avoid duplication + ; lo_stmts <- mk_switch tag_expr' lo_branches mb_deflt + lo_tag (mid_tag-1) via_C + ; hi_stmts <- mk_switch tag_expr' hi_branches mb_deflt + mid_tag hi_tag via_C + ; hi_id <- forkCgStmts hi_stmts + ; let cond = cmmUGeWord tag_expr' (CmmLit (mkIntCLit mid_tag)) + branch_stmt = CmmCondBranch cond hi_id + ; return (assign_tag `consCgStmt` (branch_stmt `consCgStmt` lo_stmts)) + } + -- we test (e >= mid_tag) rather than (e < mid_tag), because + -- the former works better when e is a comparison, and there + -- are two tags 0 & 1 (mid_tag == 1). In this case, the code + -- generator can reduce the condition to e itself without + -- having to reverse the sense of the comparison: comparisons + -- can't always be easily reversed (eg. floating + -- pt. comparisons). where - use_switch = {- pprTrace "mk_switch" ( - ppr tag_expr <+> text "n_tags:" <+> int n_tags <+> + use_switch = {- pprTrace "mk_switch" ( + ppr tag_expr <+> text "n_tags:" <+> int n_tags <+> text "branches:" <+> ppr (map fst branches) <+> - text "n_branches:" <+> int n_branches <+> - text "lo_tag:" <+> int lo_tag <+> - text "hi_tag:" <+> int hi_tag <+> - text "real_lo_tag:" <+> int real_lo_tag <+> - text "real_hi_tag:" <+> int real_hi_tag) $ -} - ASSERT( n_branches > 1 && n_tags > 1 ) - n_tags > 2 && (via_C || (dense && big_enough)) - -- up to 4 branches we use a decision tree, otherwise + text "n_branches:" <+> int n_branches <+> + text "lo_tag:" <+> int lo_tag <+> + text "hi_tag:" <+> int hi_tag <+> + text "real_lo_tag:" <+> int real_lo_tag <+> + text "real_hi_tag:" <+> int real_hi_tag) $ -} + ASSERT( n_branches > 1 && n_tags > 1 ) + n_tags > 2 && (via_C || (dense && big_enough)) + -- up to 4 branches we use a decision tree, otherwise -- a switch (== jump table in the NCG). This seems to be -- optimal, and corresponds with what gcc does. - big_enough = n_branches > 4 - dense = n_branches > (n_tags `div` 2) + big_enough = n_branches > 4 + dense = n_branches > (n_tags `div` 2) n_branches = length branches - - -- ignore default slots at each end of the range if there's + + -- ignore default slots at each end of the range if there's -- no default branch defined. lowest_branch = fst (head branches) highest_branch = fst (last branches) real_lo_tag - | isNothing mb_deflt = lowest_branch - | otherwise = lo_tag + | isNothing mb_deflt = lowest_branch + | otherwise = lo_tag real_hi_tag - | isNothing mb_deflt = highest_branch - | otherwise = hi_tag + | isNothing mb_deflt = highest_branch + | otherwise = hi_tag n_tags = real_hi_tag - real_lo_tag + 1 - -- INVARIANT: Provided hi_tag > lo_tag (which is true) - -- lo_tag <= mid_tag < hi_tag - -- lo_branches have tags < mid_tag - -- hi_branches have tags >= mid_tag + -- INVARIANT: Provided hi_tag > lo_tag (which is true) + -- lo_tag <= mid_tag < hi_tag + -- lo_branches have tags < mid_tag + -- hi_branches have tags >= mid_tag (mid_tag,_) = branches !! (n_branches `div` 2) - -- 2 branches => n_branches `div` 2 = 1 - -- => branches !! 1 give the *second* tag - -- There are always at least 2 branches here + -- 2 branches => n_branches `div` 2 = 1 + -- => branches !! 1 give the *second* tag + -- There are always at least 2 branches here (lo_branches, hi_branches) = span is_lo branches is_lo (t,_) = t < mid_tag @@ -676,30 +676,30 @@ assignTemp' e | otherwise = do { reg <- newTemp (cmmExprType e) ; return (CmmAssign (CmmLocal reg) e, CmmReg (CmmLocal reg)) } -emitLitSwitch :: CmmExpr -- Tag to switch on - -> [(Literal, CgStmts)] -- Tagged branches - -> CgStmts -- Default branch (always) - -> Code -- Emit the code --- Used for general literals, whose size might not be a word, +emitLitSwitch :: CmmExpr -- Tag to switch on + -> [(Literal, CgStmts)] -- Tagged branches + -> CgStmts -- Default branch (always) + -> Code -- Emit the code +-- Used for general literals, whose size might not be a word, -- where there is always a default case, and where we don't know -- the range of values for certain. For simplicity we always generate a tree. -- -- ToDo: for integers we could do better here, perhaps by generalising -- mk_switch and using that. --SDM 15/09/2004 -emitLitSwitch scrut [] deflt +emitLitSwitch scrut [] deflt = emitCgStmts deflt emitLitSwitch scrut branches deflt_blk - = do { scrut' <- assignTemp scrut - ; deflt_blk_id <- forkCgStmts deflt_blk - ; blk <- mk_lit_switch scrut' deflt_blk_id (sortLe le branches) - ; emitCgStmts blk } + = do { scrut' <- assignTemp scrut + ; deflt_blk_id <- forkCgStmts deflt_blk + ; blk <- mk_lit_switch scrut' deflt_blk_id (sortLe le branches) + ; emitCgStmts blk } where le (t1,_) (t2,_) = t1 <= t2 -mk_lit_switch :: CmmExpr -> BlockId - -> [(Literal,CgStmts)] - -> FCode CgStmts -mk_lit_switch scrut deflt_blk_id [(lit,blk)] +mk_lit_switch :: CmmExpr -> BlockId + -> [(Literal,CgStmts)] + -> FCode CgStmts +mk_lit_switch scrut deflt_blk_id [(lit,blk)] = return (consCgStmt if_stmt blk) where cmm_lit = mkSimpleLit lit @@ -709,25 +709,25 @@ mk_lit_switch scrut deflt_blk_id [(lit,blk)] if_stmt = CmmCondBranch cond deflt_blk_id mk_lit_switch scrut deflt_blk_id branches - = do { hi_blk <- mk_lit_switch scrut deflt_blk_id hi_branches - ; lo_blk <- mk_lit_switch scrut deflt_blk_id lo_branches - ; lo_blk_id <- forkCgStmts lo_blk - ; let if_stmt = CmmCondBranch cond lo_blk_id - ; return (if_stmt `consCgStmt` hi_blk) } + = do { hi_blk <- mk_lit_switch scrut deflt_blk_id hi_branches + ; lo_blk <- mk_lit_switch scrut deflt_blk_id lo_branches + ; lo_blk_id <- forkCgStmts lo_blk + ; let if_stmt = CmmCondBranch cond lo_blk_id + ; return (if_stmt `consCgStmt` hi_blk) } where n_branches = length branches (mid_lit,_) = branches !! (n_branches `div` 2) - -- See notes above re mid_tag + -- See notes above re mid_tag (lo_branches, hi_branches) = span is_lo branches is_lo (t,_) = t < mid_lit - cond = CmmMachOp (mkLtOp mid_lit) - [scrut, CmmLit (mkSimpleLit mid_lit)] + cond = CmmMachOp (mkLtOp mid_lit) + [scrut, CmmLit (mkSimpleLit mid_lit)] ------------------------------------------------------------------------- -- --- Simultaneous assignment +-- Simultaneous assignment -- ------------------------------------------------------------------------- @@ -737,58 +737,58 @@ emitSimultaneously :: CmmStmts -> Code -- input simultaneously, using temporary variables when necessary. -- -- The Stmts must be: --- CmmNop, CmmComment, CmmAssign, CmmStore +-- CmmNop, CmmComment, CmmAssign, CmmStore -- and nothing else -- We use the strongly-connected component algorithm, in which --- * the vertices are the statements --- * an edge goes from s1 to s2 iff --- s1 assigns to something s2 uses --- that is, if s1 should *follow* s2 in the final order +-- * the vertices are the statements +-- * an edge goes from s1 to s2 iff +-- s1 assigns to something s2 uses +-- that is, if s1 should *follow* s2 in the final order -type CVertex = (Int, CmmStmt) -- Give each vertex a unique number, - -- for fast comparison +type CVertex = (Int, CmmStmt) -- Give each vertex a unique number, + -- for fast comparison emitSimultaneously stmts = codeOnly $ - case filterOut isNopStmt (stmtList stmts) of - -- Remove no-ops - [] -> nopC - [stmt] -> stmtC stmt -- It's often just one stmt + case filterOut isNopStmt (stmtList stmts) of + -- Remove no-ops + [] -> nopC + [stmt] -> stmtC stmt -- It's often just one stmt stmt_list -> doSimultaneously1 (zip [(1::Int)..] stmt_list) doSimultaneously1 :: [CVertex] -> Code doSimultaneously1 vertices = let - edges = [ (vertex, key1, edges_from stmt1) - | vertex@(key1, stmt1) <- vertices - ] - edges_from stmt1 = [ key2 | (key2, stmt2) <- vertices, - stmt1 `mustFollow` stmt2 - ] - components = stronglyConnCompFromEdgedVertices edges - - -- do_components deal with one strongly-connected component - -- Not cyclic, or singleton? Just do it - do_component (AcyclicSCC (n,stmt)) = stmtC stmt - do_component (CyclicSCC [(n,stmt)]) = stmtC stmt - - -- Cyclic? Then go via temporaries. Pick one to - -- break the loop and try again with the rest. - do_component (CyclicSCC ((n,first_stmt) : rest)) - = do { from_temp <- go_via_temp first_stmt - ; doSimultaneously1 rest - ; stmtC from_temp } - - go_via_temp (CmmAssign dest src) - = do { tmp <- newTemp (cmmRegType dest) -- TODO FIXME NOW if the pair of assignments move across a call this will be wrong - ; stmtC (CmmAssign (CmmLocal tmp) src) - ; return (CmmAssign dest (CmmReg (CmmLocal tmp))) } - go_via_temp (CmmStore dest src) - = do { tmp <- newTemp (cmmExprType src) -- TODO FIXME NOW if the pair of assignemnts move across a call this will be wrong - ; stmtC (CmmAssign (CmmLocal tmp) src) - ; return (CmmStore dest (CmmReg (CmmLocal tmp))) } + edges = [ (vertex, key1, edges_from stmt1) + | vertex@(key1, stmt1) <- vertices + ] + edges_from stmt1 = [ key2 | (key2, stmt2) <- vertices, + stmt1 `mustFollow` stmt2 + ] + components = stronglyConnCompFromEdgedVertices edges + + -- do_components deal with one strongly-connected component + -- Not cyclic, or singleton? Just do it + do_component (AcyclicSCC (n,stmt)) = stmtC stmt + do_component (CyclicSCC [(n,stmt)]) = stmtC stmt + + -- Cyclic? Then go via temporaries. Pick one to + -- break the loop and try again with the rest. + do_component (CyclicSCC ((n,first_stmt) : rest)) + = do { from_temp <- go_via_temp first_stmt + ; doSimultaneously1 rest + ; stmtC from_temp } + + go_via_temp (CmmAssign dest src) + = do { tmp <- newTemp (cmmRegType dest) -- TODO FIXME NOW if the pair of assignments move across a call this will be wrong + ; stmtC (CmmAssign (CmmLocal tmp) src) + ; return (CmmAssign dest (CmmReg (CmmLocal tmp))) } + go_via_temp (CmmStore dest src) + = do { tmp <- newTemp (cmmExprType src) -- TODO FIXME NOW if the pair of assignemnts move across a call this will be wrong + ; stmtC (CmmAssign (CmmLocal tmp) src) + ; return (CmmStore dest (CmmReg (CmmLocal tmp))) } in mapCs do_component components @@ -802,38 +802,38 @@ CmmComment _ `mustFollow` stmt = False anySrc :: (CmmExpr -> Bool) -> CmmStmt -> Bool -- True if the fn is true of any input of the stmt anySrc p (CmmAssign _ e) = p e -anySrc p (CmmStore e1 e2) = p e1 || p e2 -- Might be used in either side -anySrc p (CmmComment _) = False -anySrc p CmmNop = False -anySrc p other = True -- Conservative +anySrc p (CmmStore e1 e2) = p e1 || p e2 -- Might be used in either side +anySrc p (CmmComment _) = False +anySrc p CmmNop = False +anySrc p other = True -- Conservative locUsedIn :: CmmExpr -> CmmType -> CmmExpr -> Bool -- (locUsedIn a r e) checks whether writing to r[a] could affect the value of -- 'e'. Returns True if it's not sure. -locUsedIn loc rep (CmmLit _) = False +locUsedIn loc rep (CmmLit _) = False locUsedIn loc rep (CmmLoad e ld_rep) = possiblySameLoc loc rep e ld_rep locUsedIn loc rep (CmmReg reg') = False locUsedIn loc rep (CmmRegOff reg' _) = False locUsedIn loc rep (CmmMachOp _ es) = any (locUsedIn loc rep) es possiblySameLoc :: CmmExpr -> CmmType -> CmmExpr -> CmmType -> Bool --- Assumes that distinct registers (eg Hp, Sp) do not +-- Assumes that distinct registers (eg Hp, Sp) do not -- point to the same location, nor any offset thereof. possiblySameLoc (CmmReg r1) rep1 (CmmReg r2) rep2 = r1==r2 possiblySameLoc (CmmReg r1) rep1 (CmmRegOff r2 0) rep2 = r1==r2 possiblySameLoc (CmmRegOff r1 0) rep1 (CmmReg r2) rep2 = r1==r2 -possiblySameLoc (CmmRegOff r1 start1) rep1 (CmmRegOff r2 start2) rep2 +possiblySameLoc (CmmRegOff r1 start1) rep1 (CmmRegOff r2 start2) rep2 = r1==r2 && end1 > start2 && end2 > start1 where end1 = start1 + widthInBytes (typeWidth rep1) end2 = start2 + widthInBytes (typeWidth rep2) possiblySameLoc l1 rep1 (CmmLit _) rep2 = False -possiblySameLoc l1 rep1 l2 rep2 = True -- Conservative +possiblySameLoc l1 rep1 l2 rep2 = True -- Conservative ------------------------------------------------------------------------- -- --- Static Reference Tables +-- Static Reference Tables -- ------------------------------------------------------------------------- @@ -854,16 +854,16 @@ getSRTInfo = do | len > hALF_WORD_SIZE_IN_BITS || bmp == [fromIntegral srt_escape] -> do id <- newUnique let srt_desc_lbl = mkLargeSRTLabel id - emitRODataLits "getSRTInfo" srt_desc_lbl + emitRODataLits "getSRTInfo" srt_desc_lbl ( cmmLabelOffW srt_lbl off - : mkWordCLit (fromIntegral len) - : map mkWordCLit bmp) - return (C_SRT srt_desc_lbl 0 srt_escape) + : mkWordCLit (fromIntegral len) + : map mkWordCLit bmp) + return (C_SRT srt_desc_lbl 0 srt_escape) SRT off len bmp - | otherwise + | otherwise -> return (C_SRT srt_lbl off (fromIntegral (head bmp))) - -- The fromIntegral converts to StgHalfWord + -- The fromIntegral converts to StgHalfWord srt_escape = (-1) :: StgHalfWord @@ -935,19 +935,19 @@ activeStgRegs = [ ,DoubleReg 2 #endif ] - + -- | 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 +-- a GlobalReg, get_GlobalReg_addr always produces the -- register table address for it. get_GlobalReg_addr :: GlobalReg -> CmmExpr get_GlobalReg_addr BaseReg = regTableOffset 0 -get_GlobalReg_addr mid = get_Regtable_addr_from_offset - (globalRegType mid) (baseRegOffset mid) +get_GlobalReg_addr mid = get_Regtable_addr_from_offset + (globalRegType 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 = +regTableOffset n = CmmLit (CmmLabelOff mkMainCapabilityLabel (oFFSET_Capability_r + n)) get_Regtable_addr_from_offset :: CmmType -> Int -> CmmExpr @@ -980,8 +980,8 @@ fixStgRegStmt stmt baseAddr = get_GlobalReg_addr reg in case reg `elem` activeStgRegs of True -> CmmAssign (CmmGlobal reg) src' - False -> CmmStore baseAddr src' - + False -> CmmStore baseAddr src' + CmmAssign reg src -> let src' = fixStgRegExpr src in CmmAssign reg src' |