root/compiler/codeGen/CgUtils.hs

Revision 2304a36272531fd20f163b6f378e417dc351aa25, 37.5 KB (checked in by Ian Lynagh <igloo@…>, 3 months ago)

Fix the unregisterised build; fixes #5901

  • Property mode set to 100644
Line 
1-----------------------------------------------------------------------------
2--
3-- Code generator utilities; mostly monadic
4--
5-- (c) The University of Glasgow 2004-2006
6--
7-----------------------------------------------------------------------------
8
9module CgUtils (
10        addIdReps,
11        cgLit,
12        emitDataLits, mkDataLits,
13        emitRODataLits, mkRODataLits,
14        emitIf, emitIfThenElse,
15        emitRtsCall, emitRtsCallWithVols, emitRtsCallWithResult,
16        emitRtsCallGen,
17        assignTemp, assignTemp_, newTemp,
18        emitSimultaneously,
19        emitSwitch, emitLitSwitch,
20        tagToClosure,
21
22        callerSaves, callerSaveVolatileRegs, get_GlobalReg_addr,
23        activeStgRegs, fixStgRegisters,
24
25        cmmAndWord, cmmOrWord, cmmNegate, cmmEqWord, cmmNeWord,
26        cmmUGtWord, cmmSubWord, cmmMulWord, cmmAddWord, cmmUShrWord,
27        cmmOffsetExprW, cmmOffsetExprB,
28        cmmRegOffW, cmmRegOffB,
29        cmmLabelOffW, cmmLabelOffB,
30        cmmOffsetW, cmmOffsetB,
31        cmmOffsetLitW, cmmOffsetLitB,
32        cmmLoadIndexW,
33        cmmConstrTag, cmmConstrTag1,
34
35        tagForCon, tagCons, isSmallFamily,
36        cmmUntag, cmmIsTagged, cmmGetTag,
37
38        addToMem, addToMemE,
39        mkWordCLit,
40        newStringCLit, newByteStringCLit,
41        packHalfWordsCLit,
42        blankWord,
43
44        getSRTInfo
45  ) where
46
47#include "HsVersions.h"
48#include "../includes/stg/MachRegs.h"
49
50import BlockId
51import CgMonad
52import TyCon
53import DataCon
54import Id
55import IdInfo
56import Constants
57import SMRep
58import OldCmm
59import OldCmmUtils
60import CLabel
61import ForeignCall
62import ClosureInfo
63import StgSyn (SRT(..))
64import Module
65import Literal
66import Digraph
67import ListSetOps
68import Util
69import DynFlags
70import FastString
71import Outputable
72
73import Data.Char
74import Data.Word
75import Data.Maybe
76
77-------------------------------------------------------------------------
78--
79--      Random small functions
80--
81-------------------------------------------------------------------------
82
83addIdReps :: [Id] -> [(CgRep, Id)]
84addIdReps ids = [(idCgRep id, id) | id <- ids]
85
86-------------------------------------------------------------------------
87--
88--      Literals
89--
90-------------------------------------------------------------------------
91
92cgLit :: Literal -> FCode CmmLit
93cgLit (MachStr s) = newByteStringCLit (bytesFS s)
94 -- not unpackFS; we want the UTF-8 byte stream.
95cgLit other_lit   = return (mkSimpleLit other_lit)
96
97mkSimpleLit :: Literal -> CmmLit
98mkSimpleLit (MachChar   c)    = CmmInt (fromIntegral (ord c)) wordWidth
99mkSimpleLit MachNullAddr      = zeroCLit
100mkSimpleLit (MachInt i)       = CmmInt i wordWidth
101mkSimpleLit (MachInt64 i)     = CmmInt i W64
102mkSimpleLit (MachWord i)      = CmmInt i wordWidth
103mkSimpleLit (MachWord64 i)    = CmmInt i W64
104mkSimpleLit (MachFloat r)     = CmmFloat r W32
105mkSimpleLit (MachDouble r)    = CmmFloat r W64
106mkSimpleLit (MachLabel fs ms fod)
107        = CmmLabel (mkForeignLabel fs ms labelSrc fod)
108        where
109                -- TODO: Literal labels might not actually be in the current package...
110                labelSrc = ForeignLabelInThisPackage
111mkSimpleLit (MachStr _) = panic "mkSimpleLit: MachStr"
112-- No LitInteger's should be left by the time this is called. CorePrep
113-- should have converted them all to a real core representation.
114mkSimpleLit (LitInteger {}) = panic "mkSimpleLit: LitInteger"
115
116mkLtOp :: Literal -> MachOp
117-- On signed literals we must do a signed comparison
118mkLtOp (MachInt _)    = MO_S_Lt wordWidth
119mkLtOp (MachFloat _)  = MO_F_Lt W32
120mkLtOp (MachDouble _) = MO_F_Lt W64
121mkLtOp lit            = MO_U_Lt (typeWidth (cmmLitType (mkSimpleLit lit)))
122
123
124---------------------------------------------------
125--
126--      Cmm data type functions
127--
128---------------------------------------------------
129
130
131
132{-
133   The family size of a data type (the number of constructors)
134   can be either:
135    * small, if the family size < 2**tag_bits
136    * big, otherwise.
137
138   Small families can have the constructor tag in the tag
139   bits.
140   Big families only use the tag value 1 to represent
141   evaluatedness.
142-}
143isSmallFamily :: Int -> Bool
144isSmallFamily fam_size = fam_size <= mAX_PTR_TAG
145
146tagForCon :: DataCon -> ConTagZ
147tagForCon con = tag
148    where
149    con_tag           = dataConTagZ con
150    fam_size   = tyConFamilySize (dataConTyCon con)
151    tag | isSmallFamily fam_size = con_tag + 1
152        | otherwise              = 1
153
154--Tag an expression, to do: refactor, this appears in some other module.
155tagCons :: DataCon -> CmmExpr -> CmmExpr
156tagCons con expr = cmmOffsetB expr (tagForCon con)
157
158--------------------------------------------------------------------------
159--
160-- Incrementing a memory location
161--
162--------------------------------------------------------------------------
163
164addToMem :: Width       -- rep of the counter
165         -> CmmExpr     -- Address
166         -> Int         -- What to add (a word)
167         -> CmmStmt
168addToMem width ptr n = addToMemE width ptr (CmmLit (CmmInt (toInteger n) width))
169
170addToMemE :: Width      -- rep of the counter
171          -> CmmExpr    -- Address
172          -> CmmExpr    -- What to add (a word-typed expression)
173          -> CmmStmt
174addToMemE width ptr n
175  = CmmStore ptr (CmmMachOp (MO_Add width) [CmmLoad ptr (cmmBits width), n])
176
177-------------------------------------------------------------------------
178--
179--      Converting a closure tag to a closure for enumeration types
180--      (this is the implementation of tagToEnum#).
181--
182-------------------------------------------------------------------------
183
184tagToClosure :: TyCon -> CmmExpr -> CmmExpr
185tagToClosure tycon tag
186  = CmmLoad (cmmOffsetExprW closure_tbl tag) gcWord
187  where closure_tbl = CmmLit (CmmLabel lbl)
188        lbl = mkClosureTableLabel (tyConName tycon) NoCafRefs
189
190-------------------------------------------------------------------------
191--
192--      Conditionals and rts calls
193--
194-------------------------------------------------------------------------
195
196emitIf :: CmmExpr       -- Boolean
197       -> Code          -- Then part
198       -> Code
199-- Emit (if e then x)
200-- ToDo: reverse the condition to avoid the extra branch instruction if possible
201-- (some conditionals aren't reversible. eg. floating point comparisons cannot
202-- be inverted because there exist some values for which both comparisons
203-- return False, such as NaN.)
204emitIf cond then_part
205  = do { then_id <- newLabelC
206       ; join_id <- newLabelC
207       ; stmtC (CmmCondBranch cond then_id)
208       ; stmtC (CmmBranch join_id)
209       ; labelC then_id
210       ; then_part
211       ; labelC join_id
212       }
213
214emitIfThenElse :: CmmExpr       -- Boolean
215                -> Code         -- Then part
216                -> Code         -- Else part
217                -> Code
218-- Emit (if e then x else y)
219emitIfThenElse cond then_part else_part
220  = do { then_id <- newLabelC
221       ; join_id <- newLabelC
222       ; stmtC (CmmCondBranch cond then_id)
223       ; else_part
224       ; stmtC (CmmBranch join_id)
225       ; labelC then_id
226       ; then_part
227       ; labelC join_id
228       }
229
230
231-- | Emit code to call a Cmm function.
232emitRtsCall
233   :: PackageId                 -- ^ package the function is in
234   -> FastString                -- ^ name of function
235   -> [CmmHinted CmmExpr]       -- ^ function args
236   -> Code                      -- ^ cmm code
237
238emitRtsCall pkg fun args = emitRtsCallGen [] pkg fun args Nothing
239   -- The 'Nothing' says "save all global registers"
240
241emitRtsCallWithVols :: PackageId -> FastString -> [CmmHinted CmmExpr] -> [GlobalReg] -> Code
242emitRtsCallWithVols pkg fun args vols
243   = emitRtsCallGen [] pkg fun args (Just vols)
244
245emitRtsCallWithResult
246   :: LocalReg -> ForeignHint
247   -> PackageId -> FastString
248   -> [CmmHinted CmmExpr] -> Code
249
250emitRtsCallWithResult res hint pkg fun args
251   = emitRtsCallGen [CmmHinted res hint] pkg fun args Nothing
252
253-- Make a call to an RTS C procedure
254emitRtsCallGen
255   :: [CmmHinted LocalReg]
256   -> PackageId
257   -> FastString
258   -> [CmmHinted CmmExpr]
259   -> Maybe [GlobalReg]
260   -> Code
261emitRtsCallGen res pkg fun args vols = do
262  stmtsC caller_save
263  stmtC (CmmCall target res args CmmMayReturn)
264  stmtsC caller_load
265  where
266    (caller_save, caller_load) = callerSaveVolatileRegs vols
267    target   = CmmCallee fun_expr CCallConv
268    fun_expr = mkLblExpr (mkCmmCodeLabel pkg fun)
269
270-----------------------------------------------------------------------------
271--
272--      Caller-Save Registers
273--
274-----------------------------------------------------------------------------
275
276-- Here we generate the sequence of saves/restores required around a
277-- foreign call instruction.
278
279-- TODO: reconcile with includes/Regs.h
280--  * Regs.h claims that BaseReg should be saved last and loaded first
281--    * This might not have been tickled before since BaseReg is callee save
282--  * Regs.h saves SparkHd, ParkT1, SparkBase and SparkLim
283callerSaveVolatileRegs :: Maybe [GlobalReg] -> ([CmmStmt], [CmmStmt])
284callerSaveVolatileRegs vols = (caller_save, caller_load)
285  where
286    caller_save = foldr ($!) [] (map callerSaveGlobalReg    regs_to_save)
287    caller_load = foldr ($!) [] (map callerRestoreGlobalReg regs_to_save)
288
289    system_regs = [Sp,SpLim,Hp,HpLim,CCCS,CurrentTSO,CurrentNursery,
290                   {-SparkHd,SparkTl,SparkBase,SparkLim,-}BaseReg ]
291
292    regs_to_save = system_regs ++ vol_list
293
294    vol_list = case vols of Nothing -> all_of_em; Just regs -> regs
295
296    all_of_em = [ VanillaReg n VNonGcPtr | n <- [0..mAX_Vanilla_REG] ]
297                        -- The VNonGcPtr is a lie, but I don't think it matters
298             ++ [ FloatReg   n | n <- [0..mAX_Float_REG] ]
299             ++ [ DoubleReg  n | n <- [0..mAX_Double_REG] ]
300             ++ [ LongReg    n | n <- [0..mAX_Long_REG] ]
301
302    callerSaveGlobalReg reg next
303        | callerSaves reg =
304                CmmStore (get_GlobalReg_addr reg)
305                         (CmmReg (CmmGlobal reg)) : next
306        | otherwise = next
307
308    callerRestoreGlobalReg reg next
309        | callerSaves reg =
310                CmmAssign (CmmGlobal reg)
311                          (CmmLoad (get_GlobalReg_addr reg) (globalRegType reg))
312                        : next
313        | otherwise = next
314
315
316-- | Returns @True@ if this global register is stored in a caller-saves
317-- machine register.
318
319callerSaves :: GlobalReg -> Bool
320
321#ifdef CALLER_SAVES_Base
322callerSaves BaseReg             = True
323#endif
324#ifdef CALLER_SAVES_R1
325callerSaves (VanillaReg 1 _)    = True
326#endif
327#ifdef CALLER_SAVES_R2
328callerSaves (VanillaReg 2 _)    = True
329#endif
330#ifdef CALLER_SAVES_R3
331callerSaves (VanillaReg 3 _)    = True
332#endif
333#ifdef CALLER_SAVES_R4
334callerSaves (VanillaReg 4 _)    = True
335#endif
336#ifdef CALLER_SAVES_R5
337callerSaves (VanillaReg 5 _)    = True
338#endif
339#ifdef CALLER_SAVES_R6
340callerSaves (VanillaReg 6 _)    = True
341#endif
342#ifdef CALLER_SAVES_R7
343callerSaves (VanillaReg 7 _)    = True
344#endif
345#ifdef CALLER_SAVES_R8
346callerSaves (VanillaReg 8 _)    = True
347#endif
348#ifdef CALLER_SAVES_R9
349callerSaves (VanillaReg 9 _)    = True
350#endif
351#ifdef CALLER_SAVES_R10
352callerSaves (VanillaReg 10 _)   = True
353#endif
354#ifdef CALLER_SAVES_F1
355callerSaves (FloatReg 1)        = True
356#endif
357#ifdef CALLER_SAVES_F2
358callerSaves (FloatReg 2)        = True
359#endif
360#ifdef CALLER_SAVES_F3
361callerSaves (FloatReg 3)        = True
362#endif
363#ifdef CALLER_SAVES_F4
364callerSaves (FloatReg 4)        = True
365#endif
366#ifdef CALLER_SAVES_D1
367callerSaves (DoubleReg 1)       = True
368#endif
369#ifdef CALLER_SAVES_D2
370callerSaves (DoubleReg 2)       = True
371#endif
372#ifdef CALLER_SAVES_L1
373callerSaves (LongReg 1)         = True
374#endif
375#ifdef CALLER_SAVES_Sp
376callerSaves Sp                  = True
377#endif
378#ifdef CALLER_SAVES_SpLim
379callerSaves SpLim               = True
380#endif
381#ifdef CALLER_SAVES_Hp
382callerSaves Hp                  = True
383#endif
384#ifdef CALLER_SAVES_HpLim
385callerSaves HpLim               = True
386#endif
387#ifdef CALLER_SAVES_CCCS
388callerSaves CCCS                = True
389#endif
390#ifdef CALLER_SAVES_CurrentTSO
391callerSaves CurrentTSO          = True
392#endif
393#ifdef CALLER_SAVES_CurrentNursery
394callerSaves CurrentNursery      = True
395#endif
396callerSaves _                   = False
397
398
399-- -----------------------------------------------------------------------------
400-- Information about global registers
401
402baseRegOffset :: GlobalReg -> Int
403
404baseRegOffset (VanillaReg 1 _)    = oFFSET_StgRegTable_rR1
405baseRegOffset (VanillaReg 2 _)    = oFFSET_StgRegTable_rR2
406baseRegOffset (VanillaReg 3 _)    = oFFSET_StgRegTable_rR3
407baseRegOffset (VanillaReg 4 _)    = oFFSET_StgRegTable_rR4
408baseRegOffset (VanillaReg 5 _)    = oFFSET_StgRegTable_rR5
409baseRegOffset (VanillaReg 6 _)    = oFFSET_StgRegTable_rR6
410baseRegOffset (VanillaReg 7 _)    = oFFSET_StgRegTable_rR7
411baseRegOffset (VanillaReg 8 _)    = oFFSET_StgRegTable_rR8
412baseRegOffset (VanillaReg 9 _)    = oFFSET_StgRegTable_rR9
413baseRegOffset (VanillaReg 10 _)   = oFFSET_StgRegTable_rR10
414baseRegOffset (VanillaReg n _)    = panic ("Registers above R10 are not supported (tried to use R" ++ show n ++ ")")
415baseRegOffset (FloatReg  1)       = oFFSET_StgRegTable_rF1
416baseRegOffset (FloatReg  2)       = oFFSET_StgRegTable_rF2
417baseRegOffset (FloatReg  3)       = oFFSET_StgRegTable_rF3
418baseRegOffset (FloatReg  4)       = oFFSET_StgRegTable_rF4
419baseRegOffset (FloatReg  n)       = panic ("Registers above F4 are not supported (tried to use F" ++ show n ++ ")")
420baseRegOffset (DoubleReg 1)       = oFFSET_StgRegTable_rD1
421baseRegOffset (DoubleReg 2)       = oFFSET_StgRegTable_rD2
422baseRegOffset (DoubleReg n)       = panic ("Registers above D2 are not supported (tried to use D" ++ show n ++ ")")
423baseRegOffset Sp                  = oFFSET_StgRegTable_rSp
424baseRegOffset SpLim               = oFFSET_StgRegTable_rSpLim
425baseRegOffset (LongReg 1)         = oFFSET_StgRegTable_rL1
426baseRegOffset (LongReg n)         = panic ("Registers above L1 are not supported (tried to use L" ++ show n ++ ")")
427baseRegOffset Hp                  = oFFSET_StgRegTable_rHp
428baseRegOffset HpLim               = oFFSET_StgRegTable_rHpLim
429baseRegOffset CCCS                = oFFSET_StgRegTable_rCCCS
430baseRegOffset CurrentTSO          = oFFSET_StgRegTable_rCurrentTSO
431baseRegOffset CurrentNursery      = oFFSET_StgRegTable_rCurrentNursery
432baseRegOffset HpAlloc             = oFFSET_StgRegTable_rHpAlloc
433baseRegOffset EagerBlackholeInfo  = oFFSET_stgEagerBlackholeInfo
434baseRegOffset GCEnter1            = oFFSET_stgGCEnter1
435baseRegOffset GCFun               = oFFSET_stgGCFun
436baseRegOffset BaseReg             = panic "baseRegOffset:BaseReg"
437baseRegOffset PicBaseReg          = panic "baseRegOffset:PicBaseReg"
438
439
440-------------------------------------------------------------------------
441--
442--      Strings generate a top-level data block
443--
444-------------------------------------------------------------------------
445
446emitDataLits :: CLabel -> [CmmLit] -> Code
447-- Emit a data-segment data block
448emitDataLits lbl lits = emitDecl (mkDataLits Data lbl lits)
449
450emitRODataLits :: String -> CLabel -> [CmmLit] -> Code
451-- Emit a read-only data block
452emitRODataLits _caller lbl lits
453  = emitDecl (mkRODataLits lbl lits)
454
455newStringCLit :: String -> FCode CmmLit
456-- Make a global definition for the string,
457-- and return its label
458newStringCLit str = newByteStringCLit (map (fromIntegral.ord) str)
459
460newByteStringCLit :: [Word8] -> FCode CmmLit
461newByteStringCLit bytes
462  = do  { uniq <- newUnique
463        ; let (lit, decl) = mkByteStringCLit uniq bytes
464        ; emitDecl decl
465        ; return lit }
466
467-------------------------------------------------------------------------
468--
469--      Assigning expressions to temporaries
470--
471-------------------------------------------------------------------------
472
473-- | If the expression is trivial, return it.  Otherwise, assign the
474-- expression to a temporary register and return an expression
475-- referring to this register.
476assignTemp :: CmmExpr -> FCode CmmExpr
477-- For a non-trivial expression, e, create a local
478-- variable and assign the expression to it
479assignTemp e
480  | isTrivialCmmExpr e = return e
481  | otherwise          = do { reg <- newTemp (cmmExprType e)
482                            ; stmtC (CmmAssign (CmmLocal reg) e)
483                            ; return (CmmReg (CmmLocal reg)) }
484
485-- | If the expression is trivial and doesn't refer to a global
486-- register, return it.  Otherwise, assign the expression to a
487-- temporary register and return an expression referring to this
488-- register.
489assignTemp_ :: CmmExpr -> FCode CmmExpr
490assignTemp_ e
491    | isTrivialCmmExpr e && hasNoGlobalRegs e = return e
492    | otherwise = do
493        reg <- newTemp (cmmExprType e)
494        stmtC (CmmAssign (CmmLocal reg) e)
495        return (CmmReg (CmmLocal reg))
496
497newTemp :: CmmType -> FCode LocalReg
498newTemp rep = do { uniq <- newUnique; return (LocalReg uniq rep) }
499
500-------------------------------------------------------------------------
501--
502--      Building case analysis
503--
504-------------------------------------------------------------------------
505
506emitSwitch
507        :: CmmExpr                -- Tag to switch on
508        -> [(ConTagZ, CgStmts)]   -- Tagged branches
509        -> Maybe CgStmts          -- Default branch (if any)
510        -> ConTagZ -> ConTagZ     -- Min and Max possible values; behaviour
511                                  --    outside this range is undefined
512        -> Code
513
514-- ONLY A DEFAULT BRANCH: no case analysis to do
515emitSwitch _ [] (Just stmts) _ _
516  = emitCgStmts stmts
517
518-- Right, off we go
519emitSwitch tag_expr branches mb_deflt lo_tag hi_tag
520  =     -- Just sort the branches before calling mk_sritch
521    do  { mb_deflt_id <-
522                case mb_deflt of
523                  Nothing    -> return Nothing
524                  Just stmts -> do id <- forkCgStmts stmts; return (Just id)
525
526        ; dflags <- getDynFlags
527        ; let via_C | HscC <- hscTarget dflags = True
528                    | otherwise                = False
529
530        ; stmts <- mk_switch tag_expr (sortLe le branches)
531                        mb_deflt_id lo_tag hi_tag via_C
532        ; emitCgStmts stmts
533        }
534  where
535    (t1,_) `le` (t2,_) = t1 <= t2
536
537
538mk_switch :: CmmExpr -> [(ConTagZ, CgStmts)]
539          -> Maybe BlockId -> ConTagZ -> ConTagZ -> Bool
540          -> FCode CgStmts
541
542-- SINGLETON TAG RANGE: no case analysis to do
543mk_switch _tag_expr [(tag,stmts)] _ lo_tag hi_tag _via_C
544  | lo_tag == hi_tag
545  = ASSERT( tag == lo_tag )
546    return stmts
547
548-- SINGLETON BRANCH, NO DEFAULT: no case analysis to do
549mk_switch _tag_expr [(_tag,stmts)] Nothing _lo_tag _hi_tag _via_C
550  = return stmts
551        -- The simplifier might have eliminated a case
552        --       so we may have e.g. case xs of
553        --                               [] -> e
554        -- In that situation we can be sure the (:) case
555        -- can't happen, so no need to test
556
557-- SINGLETON BRANCH: one equality check to do
558mk_switch tag_expr [(tag,stmts)] (Just deflt) _lo_tag _hi_tag _via_C
559  = return (CmmCondBranch cond deflt `consCgStmt` stmts)
560  where
561    cond  =  cmmNeWord tag_expr (CmmLit (mkIntCLit tag))
562        -- We have lo_tag < hi_tag, but there's only one branch,
563        -- so there must be a default
564
565-- ToDo: we might want to check for the two branch case, where one of
566-- the branches is the tag 0, because comparing '== 0' is likely to be
567-- more efficient than other kinds of comparison.
568
569-- DENSE TAG RANGE: use a switch statment.
570--
571-- We also use a switch uncoditionally when compiling via C, because
572-- this will get emitted as a C switch statement and the C compiler
573-- should do a good job of optimising it.  Also, older GCC versions
574-- (2.95 in particular) have problems compiling the complicated
575-- if-trees generated by this code, so compiling to a switch every
576-- time works around that problem.
577--
578mk_switch tag_expr branches mb_deflt lo_tag hi_tag via_C
579  | use_switch  -- Use a switch
580  = do  { branch_ids <- mapM forkCgStmts (map snd branches)
581        ; let
582                tagged_blk_ids = zip (map fst branches) (map Just branch_ids)
583
584                find_branch :: ConTagZ -> Maybe BlockId
585                find_branch i = assocDefault mb_deflt tagged_blk_ids i
586
587                -- NB. we have eliminated impossible branches at
588                -- either end of the range (see below), so the first
589                -- tag of a real branch is real_lo_tag (not lo_tag).
590                arms = [ find_branch i | i <- [real_lo_tag..real_hi_tag]]
591
592                switch_stmt = CmmSwitch (cmmOffset tag_expr (- real_lo_tag)) arms
593
594        ; ASSERT(not (all isNothing arms))
595          return (oneCgStmt switch_stmt)
596        }
597
598  -- if we can knock off a bunch of default cases with one if, then do so
599  | Just deflt <- mb_deflt, (lowest_branch - lo_tag) >= n_branches
600  = do { (assign_tag, tag_expr') <- assignTemp' tag_expr
601       ; let cond = cmmULtWord tag_expr' (CmmLit (mkIntCLit lowest_branch))
602             branch = CmmCondBranch cond deflt
603       ; stmts <- mk_switch tag_expr' branches mb_deflt
604                        lowest_branch hi_tag via_C
605       ; return (assign_tag `consCgStmt` (branch `consCgStmt` stmts))
606       }
607
608  | Just deflt <- mb_deflt, (hi_tag - highest_branch) >= n_branches
609  = do { (assign_tag, tag_expr') <- assignTemp' tag_expr
610       ; let cond = cmmUGtWord tag_expr' (CmmLit (mkIntCLit highest_branch))
611             branch = CmmCondBranch cond deflt
612       ; stmts <- mk_switch tag_expr' branches mb_deflt
613                        lo_tag highest_branch via_C
614       ; return (assign_tag `consCgStmt` (branch `consCgStmt` stmts))
615       }
616
617  | otherwise   -- Use an if-tree
618  = do  { (assign_tag, tag_expr') <- assignTemp' tag_expr
619                -- To avoid duplication
620        ; lo_stmts <- mk_switch tag_expr' lo_branches mb_deflt
621                                lo_tag (mid_tag-1) via_C
622        ; hi_stmts <- mk_switch tag_expr' hi_branches mb_deflt
623                                mid_tag hi_tag via_C
624        ; hi_id <- forkCgStmts hi_stmts
625        ; let cond = cmmUGeWord tag_expr' (CmmLit (mkIntCLit mid_tag))
626              branch_stmt = CmmCondBranch cond hi_id
627        ; return (assign_tag `consCgStmt` (branch_stmt `consCgStmt` lo_stmts))
628        }
629        -- we test (e >= mid_tag) rather than (e < mid_tag), because
630        -- the former works better when e is a comparison, and there
631        -- are two tags 0 & 1 (mid_tag == 1).  In this case, the code
632        -- generator can reduce the condition to e itself without
633        -- having to reverse the sense of the comparison: comparisons
634        -- can't always be easily reversed (eg. floating
635        -- pt. comparisons).
636  where
637    use_switch   = {- pprTrace "mk_switch" (
638                        ppr tag_expr <+> text "n_tags:" <+> int n_tags <+>
639                        text "branches:" <+> ppr (map fst branches) <+>
640                        text "n_branches:" <+> int n_branches <+>
641                        text "lo_tag:" <+> int lo_tag <+>
642                        text "hi_tag:" <+> int hi_tag <+>
643                        text "real_lo_tag:" <+> int real_lo_tag <+>
644                        text "real_hi_tag:" <+> int real_hi_tag) $ -}
645                   ASSERT( n_branches > 1 && n_tags > 1 )
646                   n_tags > 2 && (via_C || (dense && big_enough))
647                 -- up to 4 branches we use a decision tree, otherwise
648                 -- a switch (== jump table in the NCG).  This seems to be
649                 -- optimal, and corresponds with what gcc does.
650    big_enough   = n_branches > 4
651    dense        = n_branches > (n_tags `div` 2)
652    n_branches   = length branches
653
654    -- ignore default slots at each end of the range if there's
655    -- no default branch defined.
656    lowest_branch  = fst (head branches)
657    highest_branch = fst (last branches)
658
659    real_lo_tag
660        | isNothing mb_deflt = lowest_branch
661        | otherwise          = lo_tag
662
663    real_hi_tag
664        | isNothing mb_deflt = highest_branch
665        | otherwise          = hi_tag
666
667    n_tags = real_hi_tag - real_lo_tag + 1
668
669        -- INVARIANT: Provided hi_tag > lo_tag (which is true)
670        --      lo_tag <= mid_tag < hi_tag
671        --      lo_branches have tags <  mid_tag
672        --      hi_branches have tags >= mid_tag
673
674    (mid_tag,_) = branches !! (n_branches `div` 2)
675        -- 2 branches => n_branches `div` 2 = 1
676        --            => branches !! 1 give the *second* tag
677        -- There are always at least 2 branches here
678
679    (lo_branches, hi_branches) = span is_lo branches
680    is_lo (t,_) = t < mid_tag
681
682assignTemp' :: CmmExpr -> FCode (CmmStmt, CmmExpr)
683assignTemp' e
684  | isTrivialCmmExpr e = return (CmmNop, e)
685  | otherwise          = do { reg <- newTemp (cmmExprType e)
686                            ; return (CmmAssign (CmmLocal reg) e, CmmReg (CmmLocal reg)) }
687
688emitLitSwitch :: CmmExpr                        -- Tag to switch on
689              -> [(Literal, CgStmts)]           -- Tagged branches
690              -> CgStmts                        -- Default branch (always)
691              -> Code                           -- Emit the code
692-- Used for general literals, whose size might not be a word,
693-- where there is always a default case, and where we don't know
694-- the range of values for certain.  For simplicity we always generate a tree.
695--
696-- ToDo: for integers we could do better here, perhaps by generalising
697-- mk_switch and using that.  --SDM 15/09/2004
698emitLitSwitch _     []       deflt = emitCgStmts deflt
699emitLitSwitch scrut branches deflt_blk
700  = do  { scrut' <- assignTemp scrut
701        ; deflt_blk_id <- forkCgStmts deflt_blk
702        ; blk <- mk_lit_switch scrut' deflt_blk_id (sortLe le branches)
703        ; emitCgStmts blk }
704  where
705    le (t1,_) (t2,_) = t1 <= t2
706
707mk_lit_switch :: CmmExpr -> BlockId
708              -> [(Literal,CgStmts)]
709              -> FCode CgStmts
710mk_lit_switch scrut deflt_blk_id [(lit,blk)]
711  = return (consCgStmt if_stmt blk)
712  where
713    cmm_lit = mkSimpleLit lit
714    rep     = cmmLitType cmm_lit
715    ne      = if isFloatType rep then MO_F_Ne else MO_Ne
716    cond    = CmmMachOp (ne (typeWidth rep)) [scrut, CmmLit cmm_lit]
717    if_stmt = CmmCondBranch cond deflt_blk_id
718
719mk_lit_switch scrut deflt_blk_id branches
720  = do  { hi_blk <- mk_lit_switch scrut deflt_blk_id hi_branches
721        ; lo_blk <- mk_lit_switch scrut deflt_blk_id lo_branches
722        ; lo_blk_id <- forkCgStmts lo_blk
723        ; let if_stmt = CmmCondBranch cond lo_blk_id
724        ; return (if_stmt `consCgStmt` hi_blk) }
725  where
726    n_branches = length branches
727    (mid_lit,_) = branches !! (n_branches `div` 2)
728        -- See notes above re mid_tag
729
730    (lo_branches, hi_branches) = span is_lo branches
731    is_lo (t,_) = t < mid_lit
732
733    cond    = CmmMachOp (mkLtOp mid_lit)
734                        [scrut, CmmLit (mkSimpleLit mid_lit)]
735
736-------------------------------------------------------------------------
737--
738--      Simultaneous assignment
739--
740-------------------------------------------------------------------------
741
742
743emitSimultaneously :: CmmStmts -> Code
744-- Emit code to perform the assignments in the
745-- input simultaneously, using temporary variables when necessary.
746--
747-- The Stmts must be:
748--      CmmNop, CmmComment, CmmAssign, CmmStore
749-- and nothing else
750
751
752-- We use the strongly-connected component algorithm, in which
753--      * the vertices are the statements
754--      * an edge goes from s1 to s2 iff
755--              s1 assigns to something s2 uses
756--        that is, if s1 should *follow* s2 in the final order
757
758type CVertex = (Int, CmmStmt)   -- Give each vertex a unique number,
759                                -- for fast comparison
760
761emitSimultaneously stmts
762  = codeOnly $
763    case filterOut isNopStmt (stmtList stmts) of
764        -- Remove no-ops
765      []        -> nopC
766      [stmt]    -> stmtC stmt   -- It's often just one stmt
767      stmt_list -> doSimultaneously1 (zip [(1::Int)..] stmt_list)
768
769doSimultaneously1 :: [CVertex] -> Code
770doSimultaneously1 vertices
771  = let
772        edges = [ (vertex, key1, edges_from stmt1)
773                | vertex@(key1, stmt1) <- vertices
774                ]
775        edges_from stmt1 = [ key2 | (key2, stmt2) <- vertices,
776                                    stmt1 `mustFollow` stmt2
777                           ]
778        components = stronglyConnCompFromEdgedVertices edges
779
780        -- do_components deal with one strongly-connected component
781        -- Not cyclic, or singleton?  Just do it
782        do_component (AcyclicSCC (_n, stmt))  = stmtC stmt
783        do_component (CyclicSCC [])
784            = panic "doSimultaneously1: do_component (CyclicSCC [])"
785        do_component (CyclicSCC [(_n, stmt)]) = stmtC stmt
786
787                -- Cyclic?  Then go via temporaries.  Pick one to
788                -- break the loop and try again with the rest.
789        do_component (CyclicSCC ((_n, first_stmt) : rest))
790          = do  { from_temp <- go_via_temp first_stmt
791                ; doSimultaneously1 rest
792                ; stmtC from_temp }
793
794        go_via_temp (CmmAssign dest src)
795          = do  { tmp <- newTemp (cmmRegType dest) -- TODO FIXME NOW if the pair of assignments move across a call this will be wrong
796                ; stmtC (CmmAssign (CmmLocal tmp) src)
797                ; return (CmmAssign dest (CmmReg (CmmLocal tmp))) }
798        go_via_temp (CmmStore dest src)
799          = do  { tmp <- newTemp (cmmExprType src) -- TODO FIXME NOW if the pair of assignments move across a call this will be wrong
800                ; stmtC (CmmAssign (CmmLocal tmp) src)
801                ; return (CmmStore dest (CmmReg (CmmLocal tmp))) }
802        go_via_temp _ = panic "doSimultaneously1: go_via_temp"
803    in
804    mapCs do_component components
805
806mustFollow :: CmmStmt -> CmmStmt -> Bool
807CmmAssign reg _  `mustFollow` stmt = anySrc (reg `regUsedIn`) stmt
808CmmStore loc e   `mustFollow` stmt = anySrc (locUsedIn loc (cmmExprType e)) stmt
809CmmNop           `mustFollow` _    = False
810CmmComment _     `mustFollow` _    = False
811_                `mustFollow` _    = panic "mustFollow"
812
813
814anySrc :: (CmmExpr -> Bool) -> CmmStmt -> Bool
815-- True if the fn is true of any input of the stmt
816anySrc p (CmmAssign _ e)    = p e
817anySrc p (CmmStore e1 e2)   = p e1 || p e2      -- Might be used in either side
818anySrc _ (CmmComment _)     = False
819anySrc _ CmmNop             = False
820anySrc _ _                  = True              -- Conservative
821
822locUsedIn :: CmmExpr -> CmmType -> CmmExpr -> Bool
823-- (locUsedIn a r e) checks whether writing to r[a] could affect the value of
824-- 'e'.  Returns True if it's not sure.
825locUsedIn _   _   (CmmLit _)         = False
826locUsedIn loc rep (CmmLoad e ld_rep) = possiblySameLoc loc rep e ld_rep
827locUsedIn _   _   (CmmReg _)         = False
828locUsedIn _   _   (CmmRegOff _ _)    = False
829locUsedIn loc rep (CmmMachOp _ es)   = any (locUsedIn loc rep) es
830locUsedIn _   _   (CmmStackSlot _ _) = panic "locUsedIn: CmmStackSlot"
831
832possiblySameLoc :: CmmExpr -> CmmType -> CmmExpr -> CmmType -> Bool
833-- Assumes that distinct registers (eg Hp, Sp) do not
834-- point to the same location, nor any offset thereof.
835possiblySameLoc (CmmReg r1)           _    (CmmReg r2)           _ = r1 == r2
836possiblySameLoc (CmmReg r1)           _    (CmmRegOff r2 0)      _ = r1 == r2
837possiblySameLoc (CmmRegOff r1 0)      _    (CmmReg r2)           _ = r1 == r2
838possiblySameLoc (CmmRegOff r1 start1) rep1 (CmmRegOff r2 start2) rep2
839  = r1==r2 && end1 > start2 && end2 > start1
840  where
841    end1 = start1 + widthInBytes (typeWidth rep1)
842    end2 = start2 + widthInBytes (typeWidth rep2)
843
844possiblySameLoc _  _    (CmmLit _) _    = False
845possiblySameLoc _  _    _          _    = True  -- Conservative
846
847-------------------------------------------------------------------------
848--
849--      Static Reference Tables
850--
851-------------------------------------------------------------------------
852
853-- There is just one SRT for each top level binding; all the nested
854-- bindings use sub-sections of this SRT.  The label is passed down to
855-- the nested bindings via the monad.
856
857getSRTInfo :: FCode C_SRT
858getSRTInfo = do
859  srt_lbl <- getSRTLabel
860  srt <- getSRT
861  case srt of
862    -- TODO: Should we panic in this case?
863    -- Someone obviously thinks there should be an SRT
864    NoSRT -> return NoC_SRT
865    SRTEntries {} -> panic "getSRTInfo: SRTEntries.  Perhaps you forgot to run SimplStg?"
866    SRT off len bmp
867      | len > hALF_WORD_SIZE_IN_BITS || bmp == [fromIntegral srt_escape]
868      -> do id <- newUnique
869            let srt_desc_lbl = mkLargeSRTLabel id
870            emitRODataLits "getSRTInfo" srt_desc_lbl
871             ( cmmLabelOffW srt_lbl off
872               : mkWordCLit (fromIntegral len)
873               : map mkWordCLit bmp)
874            return (C_SRT srt_desc_lbl 0 srt_escape)
875
876      | otherwise
877      -> return (C_SRT srt_lbl off (fromIntegral (head bmp)))
878                -- The fromIntegral converts to StgHalfWord
879
880srt_escape :: StgHalfWord
881srt_escape = -1
882
883-- -----------------------------------------------------------------------------
884--
885-- STG/Cmm GlobalReg
886--
887-- -----------------------------------------------------------------------------
888
889-- | Here is where the STG register map is defined for each target arch.
890-- The order matters (for the llvm backend anyway)! We must make sure to
891-- maintain the order here with the order used in the LLVM calling conventions.
892-- Note that also, this isn't all registers, just the ones that are currently
893-- possbily mapped to real registers.
894activeStgRegs :: [GlobalReg]
895activeStgRegs = [
896#ifdef REG_Base
897    BaseReg
898#endif
899#ifdef REG_Sp
900    ,Sp
901#endif
902#ifdef REG_Hp
903    ,Hp
904#endif
905#ifdef REG_R1
906    ,VanillaReg 1 VGcPtr
907#endif
908#ifdef REG_R2
909    ,VanillaReg 2 VGcPtr
910#endif
911#ifdef REG_R3
912    ,VanillaReg 3 VGcPtr
913#endif
914#ifdef REG_R4
915    ,VanillaReg 4 VGcPtr
916#endif
917#ifdef REG_R5
918    ,VanillaReg 5 VGcPtr
919#endif
920#ifdef REG_R6
921    ,VanillaReg 6 VGcPtr
922#endif
923#ifdef REG_R7
924    ,VanillaReg 7 VGcPtr
925#endif
926#ifdef REG_R8
927    ,VanillaReg 8 VGcPtr
928#endif
929#ifdef REG_R9
930    ,VanillaReg 9 VGcPtr
931#endif
932#ifdef REG_R10
933    ,VanillaReg 10 VGcPtr
934#endif
935#ifdef REG_SpLim
936    ,SpLim
937#endif
938#ifdef REG_F1
939    ,FloatReg 1
940#endif
941#ifdef REG_F2
942    ,FloatReg 2
943#endif
944#ifdef REG_F3
945    ,FloatReg 3
946#endif
947#ifdef REG_F4
948    ,FloatReg 4
949#endif
950#ifdef REG_D1
951    ,DoubleReg 1
952#endif
953#ifdef REG_D2
954    ,DoubleReg 2
955#endif
956    ]
957
958-- | We map STG registers onto appropriate CmmExprs.  Either they map
959-- to real machine registers or stored as offsets from BaseReg.  Given
960-- a GlobalReg, get_GlobalReg_addr always produces the
961-- register table address for it.
962get_GlobalReg_addr :: GlobalReg -> CmmExpr
963get_GlobalReg_addr BaseReg = regTableOffset 0
964get_GlobalReg_addr mid     = get_Regtable_addr_from_offset
965                                (globalRegType mid) (baseRegOffset mid)
966
967-- Calculate a literal representing an offset into the register table.
968-- Used when we don't have an actual BaseReg to offset from.
969regTableOffset :: Int -> CmmExpr
970regTableOffset n =
971  CmmLit (CmmLabelOff mkMainCapabilityLabel (oFFSET_Capability_r + n))
972
973get_Regtable_addr_from_offset   :: CmmType -> Int -> CmmExpr
974get_Regtable_addr_from_offset _ offset =
975#ifdef REG_Base
976  CmmRegOff (CmmGlobal BaseReg) offset
977#else
978  regTableOffset offset
979#endif
980
981-- | Fixup global registers so that they assign to locations within the
982-- RegTable if they aren't pinned for the current target.
983fixStgRegisters :: RawCmmDecl -> RawCmmDecl
984fixStgRegisters top@(CmmData _ _) = top
985
986fixStgRegisters (CmmProc info lbl (ListGraph blocks)) =
987  let blocks' = map fixStgRegBlock blocks
988  in CmmProc info lbl $ ListGraph blocks'
989
990fixStgRegBlock :: CmmBasicBlock -> CmmBasicBlock
991fixStgRegBlock (BasicBlock id stmts) =
992  let stmts' = map fixStgRegStmt stmts
993  in BasicBlock id stmts'
994
995fixStgRegStmt :: CmmStmt -> CmmStmt
996fixStgRegStmt stmt
997  = case stmt of
998        CmmAssign (CmmGlobal reg) src ->
999            let src' = fixStgRegExpr src
1000                baseAddr = get_GlobalReg_addr reg
1001            in case reg `elem` activeStgRegs of
1002                True  -> CmmAssign (CmmGlobal reg) src'
1003                False -> CmmStore baseAddr src'
1004
1005        CmmAssign reg src ->
1006            let src' = fixStgRegExpr src
1007            in CmmAssign reg src'
1008
1009        CmmStore addr src -> CmmStore (fixStgRegExpr addr) (fixStgRegExpr src)
1010
1011        CmmCall target regs args returns ->
1012            let target' = case target of
1013                    CmmCallee e conv -> CmmCallee (fixStgRegExpr e) conv
1014                    CmmPrim op mStmts ->
1015                        CmmPrim op (fmap (map fixStgRegStmt) mStmts)
1016                args' = map (\(CmmHinted arg hint) ->
1017                                (CmmHinted (fixStgRegExpr arg) hint)) args
1018            in CmmCall target' regs args' returns
1019
1020        CmmCondBranch test dest -> CmmCondBranch (fixStgRegExpr test) dest
1021
1022        CmmSwitch expr ids -> CmmSwitch (fixStgRegExpr expr) ids
1023
1024        CmmJump addr live -> CmmJump (fixStgRegExpr addr) live
1025
1026        -- CmmNop, CmmComment, CmmBranch, CmmReturn
1027        _other -> stmt
1028
1029
1030fixStgRegExpr :: CmmExpr ->  CmmExpr
1031fixStgRegExpr expr
1032  = case expr of
1033        CmmLoad addr ty -> CmmLoad (fixStgRegExpr addr) ty
1034
1035        CmmMachOp mop args -> CmmMachOp mop args'
1036            where args' = map fixStgRegExpr args
1037
1038        CmmReg (CmmGlobal reg) ->
1039            -- Replace register leaves with appropriate StixTrees for
1040            -- the given target.  MagicIds which map to a reg on this
1041            -- arch are left unchanged.  For the rest, BaseReg is taken
1042            -- to mean the address of the reg table in MainCapability,
1043            -- and for all others we generate an indirection to its
1044            -- location in the register table.
1045            case reg `elem` activeStgRegs of
1046                True  -> expr
1047                False ->
1048                    let baseAddr = get_GlobalReg_addr reg
1049                    in case reg of
1050                        BaseReg -> fixStgRegExpr baseAddr
1051                        _other  -> fixStgRegExpr
1052                                    (CmmLoad baseAddr (globalRegType reg))
1053
1054        CmmRegOff (CmmGlobal reg) offset ->
1055            -- RegOf leaves are just a shorthand form. If the reg maps
1056            -- to a real reg, we keep the shorthand, otherwise, we just
1057            -- expand it and defer to the above code.
1058            case reg `elem` activeStgRegs of
1059                True  -> expr
1060                False -> fixStgRegExpr (CmmMachOp (MO_Add wordWidth) [
1061                                    CmmReg (CmmGlobal reg),
1062                                    CmmLit (CmmInt (fromIntegral offset)
1063                                                wordWidth)])
1064
1065        -- CmmLit, CmmReg (CmmLocal), CmmStackSlot
1066        _other -> expr
Note: See TracBrowser for help on using the browser.