2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
4 \section[CgBindery]{Utility functions related to doing @CgBindings@}
7 #include "HsVersions.h"
10 CgBindings(..), CgIdInfo(..){-dubiously concrete-},
11 StableLoc, VolatileLoc,
13 maybeAStkLoc, maybeBStkLoc,
15 stableAmodeIdInfo, heapIdInfo, newTempAmodeAndIdInfo,
16 letNoEscapeIdInfo, idInfoToAmode,
20 bindNewToAStack, bindNewToBStack,
21 bindNewToNode, bindNewToReg, bindArgsToRegs,
22 bindNewToTemp, bindNewPrimToAmode,
23 getArgAmode, getArgAmodes,
24 getCAddrModeAndInfo, getCAddrMode,
25 getCAddrModeIfVolatile, getVolatileRegs,
26 rebindToAStack, rebindToBStack
30 import CgLoop1 -- here for paranoia-checking
35 import CgUsages ( getHpRelOffset, getSpARelOffset, getSpBRelOffset )
36 import CLabel ( mkClosureLabel )
37 import ClosureInfo ( mkLFImported, mkConLFInfo, mkLFArgument )
38 import HeapOffs ( VirtualHeapOffset(..),
39 VirtualSpAOffset(..), VirtualSpBOffset(..)
41 import Id ( idPrimRep, toplevelishId, isDataCon,
42 mkIdEnv, rngIdEnv, IdEnv(..),
44 GenId{-instance NamedThing-}
46 import Maybes ( catMaybes )
47 import Outputable ( isLocallyDefined )
48 import PprAbsC ( pprAmode )
49 import PprStyle ( PprStyle(..) )
50 import StgSyn ( StgArg(..), StgLiveVars(..), GenStgArg(..) )
51 import Unpretty ( uppShow )
52 import Util ( zipWithEqual, panic )
56 %************************************************************************
58 \subsection[Bindery-datatypes]{Data types}
60 %************************************************************************
62 @(CgBinding a b)@ is a type of finite maps from a to b.
64 The assumption used to be that @lookupCgBind@ must get exactly one
65 match. This is {\em completely wrong} in the case of compiling
66 letrecs (where knot-tying is used). An initial binding is fed in (and
67 never evaluated); eventually, a correct binding is put into the
68 environment. So there can be two bindings for a given name.
71 type CgBindings = IdEnv CgIdInfo
74 = MkCgIdInfo Id -- Id that this is the info for
83 | RegLoc MagicId -- in one of the magic registers
84 -- (probably {Int,Float,Char,etc}Reg
86 | VirHpLoc VirtualHeapOffset -- Hp+offset (address of closure)
88 | VirNodeLoc VirtualHeapOffset -- Cts of offset indirect from Node
93 | VirAStkLoc VirtualSpAOffset
94 | VirBStkLoc VirtualSpBOffset
96 | StableAmodeLoc CAddrMode
98 -- these are so StableLoc can be abstract:
100 maybeAStkLoc (VirAStkLoc offset) = Just offset
101 maybeAStkLoc _ = Nothing
103 maybeBStkLoc (VirBStkLoc offset) = Just offset
104 maybeBStkLoc _ = Nothing
107 %************************************************************************
109 \subsection[Bindery-idInfo]{Manipulating IdInfo}
111 %************************************************************************
114 stableAmodeIdInfo i amode lf_info = MkCgIdInfo i NoVolatileLoc (StableAmodeLoc amode) lf_info
115 heapIdInfo i offset lf_info = MkCgIdInfo i (VirHpLoc offset) NoStableLoc lf_info
116 tempIdInfo i uniq lf_info = MkCgIdInfo i (TempVarLoc uniq) NoStableLoc lf_info
118 letNoEscapeIdInfo i spa spb lf_info
119 = MkCgIdInfo i NoVolatileLoc (StableAmodeLoc (CJoinPoint spa spb)) lf_info
121 newTempAmodeAndIdInfo :: Id -> LambdaFormInfo -> (CAddrMode, CgIdInfo)
123 newTempAmodeAndIdInfo name lf_info
124 = (temp_amode, temp_idinfo)
127 temp_amode = CTemp uniq (idPrimRep name)
128 temp_idinfo = tempIdInfo name uniq lf_info
130 idInfoToAmode :: PrimRep -> CgIdInfo -> FCode CAddrMode
131 idInfoToAmode kind (MkCgIdInfo _ vol stab _) = idInfoPiecesToAmode kind vol stab
133 idInfoPiecesToAmode :: PrimRep -> VolatileLoc -> StableLoc -> FCode CAddrMode
135 idInfoPiecesToAmode kind (TempVarLoc uniq) stable_loc = returnFC (CTemp uniq kind)
136 idInfoPiecesToAmode kind (RegLoc magic_id) stable_loc = returnFC (CReg magic_id)
138 idInfoPiecesToAmode kind NoVolatileLoc (LitLoc lit) = returnFC (CLit lit)
139 idInfoPiecesToAmode kind NoVolatileLoc (StableAmodeLoc amode) = returnFC amode
141 idInfoPiecesToAmode kind (VirNodeLoc nd_off) stable_loc
142 = returnFC (CVal (NodeRel nd_off) kind)
143 -- Virtual offsets from Node increase into the closures,
144 -- and so do Node-relative offsets (which we want in the CVal),
145 -- so there is no mucking about to do to the offset.
147 idInfoPiecesToAmode kind (VirHpLoc hp_off) stable_loc
148 = getHpRelOffset hp_off `thenFC` \ rel_hp ->
149 returnFC (CAddr rel_hp)
151 idInfoPiecesToAmode kind NoVolatileLoc (VirAStkLoc i)
152 = getSpARelOffset i `thenFC` \ rel_spA ->
153 returnFC (CVal rel_spA kind)
155 idInfoPiecesToAmode kind NoVolatileLoc (VirBStkLoc i)
156 = getSpBRelOffset i `thenFC` \ rel_spB ->
157 returnFC (CVal rel_spB kind)
160 idInfoPiecesToAmode kind NoVolatileLoc NoStableLoc = panic "idInfoPiecesToAmode: no loc"
164 %************************************************************************
166 \subsection[Bindery-nuke-volatile]{Nuking volatile bindings}
168 %************************************************************************
170 We sometimes want to nuke all the volatile bindings; we must be sure
171 we don't leave any (NoVolatile, NoStable) binds around...
174 nukeVolatileBinds :: CgBindings -> CgBindings
175 nukeVolatileBinds binds
176 = mkIdEnv (foldr keep_if_stable [] (rngIdEnv binds))
178 keep_if_stable (MkCgIdInfo i _ NoStableLoc entry_info) acc = acc
179 keep_if_stable (MkCgIdInfo i _ stable_loc entry_info) acc
180 = (i, MkCgIdInfo i NoVolatileLoc stable_loc entry_info) : acc
184 %************************************************************************
186 \subsection[lookup-interface]{Interface functions to looking up bindings}
188 %************************************************************************
190 I {\em think} all looking-up is done through @getCAddrMode(s)@.
193 getCAddrModeAndInfo :: Id -> FCode (CAddrMode, LambdaFormInfo)
195 getCAddrModeAndInfo name
196 | not (isLocallyDefined name)
197 = returnFC (global_amode, mkLFImported name)
200 = returnFC (global_amode, mkConLFInfo name)
202 | otherwise = -- *might* be a nested defn: in any case, it's something whose
203 -- definition we will know about...
204 lookupBindC name `thenFC` \ (MkCgIdInfo _ volatile_loc stable_loc lf_info) ->
205 idInfoPiecesToAmode kind volatile_loc stable_loc `thenFC` \ amode ->
206 returnFC (amode, lf_info)
208 global_amode = CLbl (mkClosureLabel name) kind
209 kind = idPrimRep name
211 getCAddrMode :: Id -> FCode CAddrMode
213 = getCAddrModeAndInfo name `thenFC` \ (amode, _) ->
218 getCAddrModeIfVolatile :: Id -> FCode (Maybe CAddrMode)
219 getCAddrModeIfVolatile name
220 | toplevelishId name = returnFC Nothing
222 = lookupBindC name `thenFC` \ ~(MkCgIdInfo _ volatile_loc stable_loc lf_info) ->
224 NoStableLoc -> -- Aha! So it is volatile!
225 idInfoPiecesToAmode (idPrimRep name) volatile_loc NoStableLoc `thenFC` \ amode ->
226 returnFC (Just amode)
228 a_stable_loc -> returnFC Nothing
231 @getVolatileRegs@ gets a set of live variables, and returns a list of
232 all registers on which these variables depend. These are the regs
233 which must be saved and restored across any C calls. If a variable is
234 both in a volatile location (depending on a register) {\em and} a
235 stable one (notably, on the stack), we modify the current bindings to
236 forget the volatile one.
239 getVolatileRegs :: StgLiveVars -> FCode [MagicId]
242 = mapFCs snaffle_it (idSetToList vars) `thenFC` \ stuff ->
243 returnFC (catMaybes stuff)
246 = lookupBindC var `thenFC` \ (MkCgIdInfo _ volatile_loc stable_loc lf_info) ->
248 -- commoned-up code...
250 = if not (isVolatileReg reg) then
251 -- Potentially dies across C calls
252 -- For now, that's everything; we leave
253 -- it to the save-macros to decide which
254 -- regs *really* need to be saved.
258 NoStableLoc -> returnFC (Just reg) -- got one!
260 -- has both volatile & stable locations;
261 -- force it to rely on the stable location
262 modifyBindC var nuke_vol_bind `thenC`
266 RegLoc reg -> consider_reg reg
267 VirHpLoc _ -> consider_reg Hp
268 VirNodeLoc _ -> consider_reg node
269 non_reg_loc -> returnFC Nothing
271 nuke_vol_bind (MkCgIdInfo i _ stable_loc lf_info)
272 = MkCgIdInfo i NoVolatileLoc stable_loc lf_info
276 getArgAmodes :: [StgArg] -> FCode [CAddrMode]
277 getArgAmodes [] = returnFC []
278 getArgAmodes (atom:atoms)
279 = getArgAmode atom `thenFC` \ amode ->
280 getArgAmodes atoms `thenFC` \ amodes ->
281 returnFC ( amode : amodes )
283 getArgAmode :: StgArg -> FCode CAddrMode
285 getArgAmode (StgVarArg var) = getCAddrMode var
286 getArgAmode (StgLitArg lit) = returnFC (CLit lit)
289 %************************************************************************
291 \subsection[binding-and-rebinding-interface]{Interface functions for binding and re-binding names}
293 %************************************************************************
296 bindNewToAStack :: (Id, VirtualSpAOffset) -> Code
297 bindNewToAStack (name, offset)
300 info = MkCgIdInfo name NoVolatileLoc (VirAStkLoc offset) mkLFArgument
302 bindNewToBStack :: (Id, VirtualSpBOffset) -> Code
303 bindNewToBStack (name, offset)
306 info = MkCgIdInfo name NoVolatileLoc (VirBStkLoc offset) (panic "bindNewToBStack")
307 -- B-stack things shouldn't need lambda-form info!
309 bindNewToNode :: Id -> VirtualHeapOffset -> LambdaFormInfo -> Code
310 bindNewToNode name offset lf_info
313 info = MkCgIdInfo name (VirNodeLoc offset) NoStableLoc lf_info
315 -- Create a new temporary whose unique is that in the id,
316 -- bind the id to it, and return the addressing mode for the
318 bindNewToTemp :: Id -> FCode CAddrMode
320 = let (temp_amode, id_info) = newTempAmodeAndIdInfo name mkLFArgument
321 -- This is used only for things we don't know
322 -- anything about; values returned by a case statement,
325 addBindC name id_info `thenC`
328 bindNewToReg :: Id -> MagicId -> LambdaFormInfo -> Code
329 bindNewToReg name magic_id lf_info
332 info = MkCgIdInfo name (RegLoc magic_id) NoStableLoc lf_info
334 bindNewToLit name lit
337 info = MkCgIdInfo name NoVolatileLoc (LitLoc lit) (error "bindNewToLit")
339 bindArgsToRegs :: [Id] -> [MagicId] -> Code
340 bindArgsToRegs args regs
341 = listCs (zipWithEqual bind args regs)
343 arg `bind` reg = bindNewToReg arg reg mkLFArgument
346 @bindNewPrimToAmode@ works only for certain addressing modes, because
347 those are the only ones we've needed so far!
350 bindNewPrimToAmode :: Id -> CAddrMode -> Code
351 bindNewPrimToAmode name (CReg reg) = bindNewToReg name reg (panic "bindNewPrimToAmode")
353 -- LFinfo is irrelevant for primitives
354 bindNewPrimToAmode name (CTemp uniq kind)
355 = addBindC name (tempIdInfo name uniq (panic "bindNewPrimToAmode"))
356 -- LFinfo is irrelevant for primitives
358 bindNewPrimToAmode name (CLit lit) = bindNewToLit name lit
360 bindNewPrimToAmode name (CVal (SpBRel _ offset) _)
361 = bindNewToBStack (name, offset)
363 bindNewPrimToAmode name (CVal (NodeRel offset) _)
364 = bindNewToNode name offset (panic "bindNewPrimToAmode node")
365 -- See comment on idInfoPiecesToAmode for VirNodeLoc
368 bindNewPrimToAmode name amode
369 = panic ("bindNew...:"++(uppShow 80 (pprAmode PprDebug amode)))
374 rebindToAStack :: Id -> VirtualSpAOffset -> Code
375 rebindToAStack name offset
376 = modifyBindC name replace_stable_fn
378 replace_stable_fn (MkCgIdInfo i vol stab einfo)
379 = MkCgIdInfo i vol (VirAStkLoc offset) einfo
381 rebindToBStack :: Id -> VirtualSpBOffset -> Code
382 rebindToBStack name offset
383 = modifyBindC name replace_stable_fn
385 replace_stable_fn (MkCgIdInfo i vol stab einfo)
386 = MkCgIdInfo i vol (VirBStkLoc offset) einfo