root/compiler/codeGen/CgCallConv.hs

Revision 9ee9e518fe485107c9a21fed68a7dcc86fe08b4c, 15.2 KB (checked in by David Terei <davidterei@…>, 5 months ago)

Formatting fixes

  • Property mode set to 100644
Line 
1-----------------------------------------------------------------------------
2--
3-- (c) The University of Glasgow 2004-2006
4--
5-- CgCallConv
6--
7-- The datatypes and functions here encapsulate the
8-- calling and return conventions used by the code generator.
9--
10-----------------------------------------------------------------------------
11
12module CgCallConv (
13        -- Argument descriptors
14        mkArgDescr,
15
16        -- Liveness
17        mkRegLiveness,
18
19        -- Register assignment
20        assignCallRegs, assignReturnRegs, assignPrimOpCallRegs,
21
22        -- Calls
23        constructSlowCall, slowArgs, slowCallPattern,
24
25        -- Returns
26        dataReturnConvPrim,
27        getSequelAmode
28    ) where
29
30import CgMonad
31import CgProf
32import SMRep
33
34import OldCmm
35import CLabel
36
37import Constants
38import CgStackery
39import ClosureInfo( CgRep(..), nonVoidArg, idCgRep, cgRepSizeW, isFollowableArg )
40import OldCmmUtils
41import Maybes
42import Id
43import Name
44import Util
45import StaticFlags
46import Module
47import FastString
48import Outputable
49import Data.Bits
50
51-------------------------------------------------------------------------
52--
53--      Making argument descriptors
54--
55--  An argument descriptor describes the layout of args on the stack,
56--  both for    * GC (stack-layout) purposes, and
57--              * saving/restoring registers when a heap-check fails
58--
59-- Void arguments aren't important, therefore (contrast constructSlowCall)
60--
61-------------------------------------------------------------------------
62
63-- bring in ARG_P, ARG_N, etc.
64#include "../includes/rts/storage/FunTypes.h"
65
66-------------------------
67mkArgDescr :: Name -> [Id] -> FCode ArgDescr
68mkArgDescr _nm args
69  = case stdPattern arg_reps of
70        Just spec_id -> return (ArgSpec spec_id)
71        Nothing      -> return (ArgGen arg_bits)
72  where
73    arg_bits = argBits arg_reps
74    arg_reps = filter nonVoidArg (map idCgRep args)
75        -- Getting rid of voids eases matching of standard patterns
76
77argBits :: [CgRep] -> [Bool]    -- True for non-ptr, False for ptr
78argBits []              = []
79argBits (PtrArg : args) = False : argBits args
80argBits (arg    : args) = take (cgRepSizeW arg) (repeat True) ++ argBits args
81
82stdPattern :: [CgRep] -> Maybe StgHalfWord
83stdPattern []          = Just ARG_NONE  -- just void args, probably
84
85stdPattern [PtrArg]    = Just ARG_P
86stdPattern [FloatArg]  = Just ARG_F
87stdPattern [DoubleArg] = Just ARG_D
88stdPattern [LongArg]   = Just ARG_L
89stdPattern [NonPtrArg] = Just ARG_N
90
91stdPattern [NonPtrArg,NonPtrArg] = Just ARG_NN
92stdPattern [NonPtrArg,PtrArg]    = Just ARG_NP
93stdPattern [PtrArg,NonPtrArg]    = Just ARG_PN
94stdPattern [PtrArg,PtrArg]       = Just ARG_PP
95
96stdPattern [NonPtrArg,NonPtrArg,NonPtrArg] = Just ARG_NNN
97stdPattern [NonPtrArg,NonPtrArg,PtrArg]    = Just ARG_NNP
98stdPattern [NonPtrArg,PtrArg,NonPtrArg]    = Just ARG_NPN
99stdPattern [NonPtrArg,PtrArg,PtrArg]       = Just ARG_NPP
100stdPattern [PtrArg,NonPtrArg,NonPtrArg]    = Just ARG_PNN
101stdPattern [PtrArg,NonPtrArg,PtrArg]       = Just ARG_PNP
102stdPattern [PtrArg,PtrArg,NonPtrArg]       = Just ARG_PPN
103stdPattern [PtrArg,PtrArg,PtrArg]          = Just ARG_PPP
104
105stdPattern [PtrArg,PtrArg,PtrArg,PtrArg]               = Just ARG_PPPP
106stdPattern [PtrArg,PtrArg,PtrArg,PtrArg,PtrArg]        = Just ARG_PPPPP
107stdPattern [PtrArg,PtrArg,PtrArg,PtrArg,PtrArg,PtrArg] = Just ARG_PPPPPP
108stdPattern _ = Nothing
109
110
111-------------------------------------------------------------------------
112--
113--              Bitmap describing register liveness
114--              across GC when doing a "generic" heap check
115--              (a RET_DYN stack frame).
116--
117-- NB. Must agree with these macros (currently in StgMacros.h):
118-- GET_NON_PTRS(), GET_PTRS(), GET_LIVENESS().
119-------------------------------------------------------------------------
120
121mkRegLiveness :: [(Id, GlobalReg)] -> Int -> Int -> StgWord
122mkRegLiveness regs ptrs nptrs
123  = (fromIntegral nptrs `shiftL` 16) .|.
124    (fromIntegral ptrs  `shiftL` 24) .|.
125    all_non_ptrs `xor` reg_bits regs
126  where
127    all_non_ptrs = 0xff
128
129    reg_bits [] = 0
130    reg_bits ((id, VanillaReg i _) : regs) | isFollowableArg (idCgRep id)
131        = (1 `shiftL` (i - 1)) .|. reg_bits regs
132    reg_bits (_ : regs)
133        = reg_bits regs
134
135-------------------------------------------------------------------------
136--
137--              Pushing the arguments for a slow call
138--
139-------------------------------------------------------------------------
140
141-- For a slow call, we must take a bunch of arguments and intersperse
142-- some stg_ap_<pattern>_ret_info return addresses.
143constructSlowCall
144        :: [(CgRep,CmmExpr)]
145        -> (CLabel,             -- RTS entry point for call
146           [(CgRep,CmmExpr)],   -- args to pass to the entry point
147           [(CgRep,CmmExpr)])   -- stuff to save on the stack
148
149   -- don't forget the zero case
150constructSlowCall []
151  = (mkRtsApFastLabel (fsLit "stg_ap_0"), [], [])
152
153constructSlowCall amodes
154  = (stg_ap_pat, these, rest)
155  where
156    stg_ap_pat = mkRtsApFastLabel arg_pat
157    (arg_pat, these, rest) = matchSlowPattern amodes
158
159-- | 'slowArgs' takes a list of function arguments and prepares them for
160-- pushing on the stack for "extra" arguments to a function which requires
161-- fewer arguments than we currently have.
162slowArgs :: [(CgRep,CmmExpr)] -> [(CgRep,CmmExpr)]
163slowArgs [] = []
164slowArgs amodes
165  | opt_SccProfilingOn = save_cccs ++ this_pat ++ slowArgs rest
166  | otherwise          =              this_pat ++ slowArgs rest
167  where
168    (arg_pat, args, rest) = matchSlowPattern amodes
169    stg_ap_pat = mkCmmRetInfoLabel rtsPackageId arg_pat
170    this_pat   = (NonPtrArg, mkLblExpr stg_ap_pat) : args
171    save_cccs  = [(NonPtrArg, mkLblExpr save_cccs_lbl), (NonPtrArg, curCCS)]
172    save_cccs_lbl = mkCmmRetInfoLabel rtsPackageId (fsLit "stg_restore_cccs")
173
174matchSlowPattern :: [(CgRep,CmmExpr)]
175                 -> (FastString, [(CgRep,CmmExpr)], [(CgRep,CmmExpr)])
176matchSlowPattern amodes = (arg_pat, these, rest)
177  where (arg_pat, n)  = slowCallPattern (map fst amodes)
178        (these, rest) = splitAt n amodes
179
180-- These cases were found to cover about 99% of all slow calls:
181slowCallPattern :: [CgRep] -> (FastString, Int)
182slowCallPattern (PtrArg: PtrArg: PtrArg: PtrArg: PtrArg: PtrArg: _) = (fsLit "stg_ap_pppppp", 6)
183slowCallPattern (PtrArg: PtrArg: PtrArg: PtrArg: PtrArg: _)         = (fsLit "stg_ap_ppppp", 5)
184slowCallPattern (PtrArg: PtrArg: PtrArg: PtrArg: _)     = (fsLit "stg_ap_pppp", 4)
185slowCallPattern (PtrArg: PtrArg: PtrArg: VoidArg: _)    = (fsLit "stg_ap_pppv", 4)
186slowCallPattern (PtrArg: PtrArg: PtrArg: _)             = (fsLit "stg_ap_ppp", 3)
187slowCallPattern (PtrArg: PtrArg: VoidArg: _)            = (fsLit "stg_ap_ppv", 3)
188slowCallPattern (PtrArg: PtrArg: _)                     = (fsLit "stg_ap_pp", 2)
189slowCallPattern (PtrArg: VoidArg: _)                    = (fsLit "stg_ap_pv", 2)
190slowCallPattern (PtrArg: _)                             = (fsLit "stg_ap_p", 1)
191slowCallPattern (VoidArg: _)                            = (fsLit "stg_ap_v", 1)
192slowCallPattern (NonPtrArg: _)                          = (fsLit "stg_ap_n", 1)
193slowCallPattern (FloatArg: _)                           = (fsLit "stg_ap_f", 1)
194slowCallPattern (DoubleArg: _)                          = (fsLit "stg_ap_d", 1)
195slowCallPattern (LongArg: _)                            = (fsLit "stg_ap_l", 1)
196slowCallPattern _                                       = panic "CgStackery.slowCallPattern"
197
198-------------------------------------------------------------------------
199--
200--              Return conventions
201--
202-------------------------------------------------------------------------
203
204dataReturnConvPrim :: CgRep -> CmmReg
205dataReturnConvPrim PtrArg    = CmmGlobal (VanillaReg 1 VGcPtr)
206dataReturnConvPrim NonPtrArg = CmmGlobal (VanillaReg 1 VNonGcPtr)
207dataReturnConvPrim LongArg   = CmmGlobal (LongReg 1)
208dataReturnConvPrim FloatArg  = CmmGlobal (FloatReg 1)
209dataReturnConvPrim DoubleArg = CmmGlobal (DoubleReg 1)
210dataReturnConvPrim VoidArg   = panic "dataReturnConvPrim: void"
211
212
213-- getSequelAmode returns an amode which refers to an info table.  The info
214-- table will always be of the RET_(BIG|SMALL) kind.  We're careful
215-- not to handle real code pointers, just in case we're compiling for
216-- an unregisterised/untailcallish architecture, where info pointers and
217-- code pointers aren't the same.
218-- DIRE WARNING.
219-- The OnStack case of sequelToAmode delivers an Amode which is only
220-- valid just before the final control transfer, because it assumes
221-- that Sp is pointing to the top word of the return address.  This
222-- seems unclean but there you go.
223
224getSequelAmode :: FCode CmmExpr
225getSequelAmode
226  = do  { EndOfBlockInfo virt_sp sequel <- getEndOfBlockInfo
227        ; case sequel of
228            OnStack -> do { sp_rel <- getSpRelOffset virt_sp
229                          ; returnFC (CmmLoad sp_rel bWord) }
230
231            CaseAlts lbl _ _  -> returnFC (CmmLit (CmmLabel lbl))
232        }
233
234-------------------------------------------------------------------------
235--
236--              Register assignment
237--
238-------------------------------------------------------------------------
239
240--  How to assign registers for
241--
242--      1) Calling a fast entry point.
243--      2) Returning an unboxed tuple.
244--      3) Invoking an out-of-line PrimOp.
245--
246-- Registers are assigned in order.
247--
248-- If we run out, we don't attempt to assign any further registers (even
249-- though we might have run out of only one kind of register); we just
250-- return immediately with the left-overs specified.
251--
252-- The alternative version @assignAllRegs@ uses the complete set of
253-- registers, including those that aren't mapped to real machine
254-- registers.  This is used for calling special RTS functions and PrimOps
255-- which expect their arguments to always be in the same registers.
256
257assignCallRegs, assignPrimOpCallRegs, assignReturnRegs
258        :: [(CgRep,a)]          -- Arg or result values to assign
259        -> ([(a, GlobalReg)],   -- Register assignment in same order
260                                -- for *initial segment of* input list
261                                --   (but reversed; doesn't matter)
262                                -- VoidRep args do not appear here
263            [(CgRep,a)])        -- Leftover arg or result values
264
265assignCallRegs args
266  = assign_regs args (mkRegTbl [node])
267        -- The entry convention for a function closure
268        -- never uses Node for argument passing; instead
269        -- Node points to the function closure itself
270
271assignPrimOpCallRegs args
272 = assign_regs args (mkRegTbl_allRegs [])
273        -- For primops, *all* arguments must be passed in registers
274
275assignReturnRegs args
276 -- when we have a single non-void component to return, use the normal
277 -- unpointed return convention.  This make various things simpler: it
278 -- means we can assume a consistent convention for IO, which is useful
279 -- when writing code that relies on knowing the IO return convention in
280 -- the RTS (primops, especially exception-related primops).
281 -- Also, the bytecode compiler assumes this when compiling
282 -- case expressions and ccalls, so it only needs to know one set of
283 -- return conventions.
284 | [(rep,arg)] <- non_void_args, CmmGlobal r <- dataReturnConvPrim rep
285    = ([(arg, r)], [])
286 | otherwise
287    = assign_regs args (mkRegTbl [])
288        -- For returning unboxed tuples etc,
289        -- we use all regs
290 where
291       non_void_args = filter ((/= VoidArg).fst) args
292
293assign_regs :: [(CgRep,a)]      -- Arg or result values to assign
294            -> AvailRegs        -- Regs still avail: Vanilla, Float, Double, Longs
295            -> ([(a, GlobalReg)], [(CgRep, a)])
296assign_regs args supply
297  = go args [] supply
298  where
299    go [] acc _ = (acc, [])     -- Return the results reversed (doesn't matter)
300    go ((VoidArg,_) : args) acc supply  -- Skip void arguments; they aren't passed, and
301        = go args acc supply            -- there's nothing to bind them to
302    go ((rep,arg) : args) acc supply
303        = case assign_reg rep supply of
304                Just (reg, supply') -> go args ((arg,reg):acc) supply'
305                Nothing             -> (acc, (rep,arg):args)    -- No more regs
306
307assign_reg :: CgRep -> AvailRegs -> Maybe (GlobalReg, AvailRegs)
308assign_reg FloatArg  (vs, f:fs, ds, ls) = Just (FloatReg f,   (vs, fs, ds, ls))
309assign_reg DoubleArg (vs, fs, d:ds, ls) = Just (DoubleReg d,  (vs, fs, ds, ls))
310assign_reg LongArg   (vs, fs, ds, l:ls) = Just (LongReg l,    (vs, fs, ds, ls))
311assign_reg PtrArg    (v:vs, fs, ds, ls) = Just (VanillaReg v VGcPtr, (vs, fs, ds, ls))
312assign_reg NonPtrArg (v:vs, fs, ds, ls) = Just (VanillaReg v VNonGcPtr, (vs, fs, ds, ls))
313    -- PtrArg and NonPtrArg both go in a vanilla register
314assign_reg _         _                  = Nothing
315
316
317-------------------------------------------------------------------------
318--
319--              Register supplies
320--
321-------------------------------------------------------------------------
322
323-- Vanilla registers can contain pointers, Ints, Chars.
324-- Floats and doubles have separate register supplies.
325--
326-- We take these register supplies from the *real* registers, i.e. those
327-- that are guaranteed to map to machine registers.
328
329useVanillaRegs :: Int
330useVanillaRegs | opt_Unregisterised = 0
331               | otherwise          = mAX_Real_Vanilla_REG
332useFloatRegs :: Int
333useFloatRegs   | opt_Unregisterised = 0
334               | otherwise          = mAX_Real_Float_REG
335useDoubleRegs :: Int
336useDoubleRegs  | opt_Unregisterised = 0
337               | otherwise          = mAX_Real_Double_REG
338useLongRegs :: Int
339useLongRegs    | opt_Unregisterised = 0
340               | otherwise          = mAX_Real_Long_REG
341
342vanillaRegNos, floatRegNos, doubleRegNos, longRegNos :: [Int]
343vanillaRegNos    = regList useVanillaRegs
344floatRegNos      = regList useFloatRegs
345doubleRegNos     = regList useDoubleRegs
346longRegNos       = regList useLongRegs
347
348allVanillaRegNos, allFloatRegNos, allDoubleRegNos, allLongRegNos :: [Int]
349allVanillaRegNos = regList mAX_Vanilla_REG
350allFloatRegNos   = regList mAX_Float_REG
351allDoubleRegNos  = regList mAX_Double_REG
352allLongRegNos    = regList mAX_Long_REG
353
354regList :: Int -> [Int]
355regList n = [1 .. n]
356
357type AvailRegs = ( [Int]   -- available vanilla regs.
358                 , [Int]   -- floats
359                 , [Int]   -- doubles
360                 , [Int]   -- longs (int64 and word64)
361                 )
362
363mkRegTbl :: [GlobalReg] -> AvailRegs
364mkRegTbl regs_in_use
365  = mkRegTbl' regs_in_use vanillaRegNos floatRegNos doubleRegNos longRegNos
366
367mkRegTbl_allRegs :: [GlobalReg] -> AvailRegs
368mkRegTbl_allRegs regs_in_use
369  = mkRegTbl' regs_in_use allVanillaRegNos allFloatRegNos allDoubleRegNos allLongRegNos
370
371mkRegTbl' :: [GlobalReg] -> [Int] -> [Int] -> [Int] -> [Int]
372          -> ([Int], [Int], [Int], [Int])
373mkRegTbl' regs_in_use vanillas floats doubles longs
374  = (ok_vanilla, ok_float, ok_double, ok_long)
375  where
376    ok_vanilla = mapCatMaybes (select (\i -> VanillaReg i VNonGcPtr)) vanillas
377                    -- ptrhood isn't looked at, hence we can use any old rep.
378    ok_float   = mapCatMaybes (select FloatReg)   floats
379    ok_double  = mapCatMaybes (select DoubleReg)  doubles
380    ok_long    = mapCatMaybes (select LongReg)    longs
381
382    select :: (Int -> GlobalReg) -> Int{-cand-} -> Maybe Int
383        -- one we've unboxed the Int, we make a GlobalReg
384        -- and see if it is already in use; if not, return its number.
385
386    select mk_reg_fun cand
387      = let
388            reg = mk_reg_fun cand
389        in
390        if reg `not_elem` regs_in_use
391        then Just cand
392        else Nothing
393      where
394        not_elem = isn'tIn "mkRegTbl"
395
Note: See TracBrowser for help on using the browser.