2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
4 \section[CgBindery]{Utility functions related to doing @CgBindings@}
7 #include "HsVersions.h"
10 SYN_IE(CgBindings), CgIdInfo(..){-dubiously concrete-},
11 VolatileLoc, StableLoc, -- (the latter is defined in CgMonad)
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
34 import CgUsages ( getHpRelOffset, getSpARelOffset, getSpBRelOffset )
35 import CLabel ( mkStaticClosureLabel, mkClosureLabel )
36 import ClosureInfo ( mkLFImported, mkConLFInfo, mkLFArgument, LambdaFormInfo )
37 import HeapOffs ( SYN_IE(VirtualHeapOffset),
38 SYN_IE(VirtualSpAOffset), SYN_IE(VirtualSpBOffset)
40 import Id ( idPrimRep, toplevelishId,
41 mkIdEnv, rngIdEnv, SYN_IE(IdEnv),
43 GenId{-instance NamedThing-}, SYN_IE(Id)
45 import Maybes ( catMaybes )
46 import Name ( isLocallyDefined, isWiredInName,
47 Name{-instance NamedThing-}, NamedThing(..) )
49 import PprAbsC ( pprAmode )
51 import Outputable ( PprStyle(..) )
53 import PrimRep ( PrimRep )
54 import StgSyn ( SYN_IE(StgArg), SYN_IE(StgLiveVars), GenStgArg(..) )
55 import Unique ( Unique, Uniquable(..) )
56 import Util ( zipWithEqual, panic )
60 %************************************************************************
62 \subsection[Bindery-datatypes]{Data types}
64 %************************************************************************
66 @(CgBinding a b)@ is a type of finite maps from a to b.
68 The assumption used to be that @lookupCgBind@ must get exactly one
69 match. This is {\em completely wrong} in the case of compiling
70 letrecs (where knot-tying is used). An initial binding is fed in (and
71 never evaluated); eventually, a correct binding is put into the
72 environment. So there can be two bindings for a given name.
75 type CgBindings = IdEnv CgIdInfo
78 = MkCgIdInfo Id -- Id that this is the info for
87 | RegLoc MagicId -- in one of the magic registers
88 -- (probably {Int,Float,Char,etc}Reg
90 | VirHpLoc VirtualHeapOffset -- Hp+offset (address of closure)
92 | VirNodeLoc VirtualHeapOffset -- Cts of offset indirect from Node
97 %************************************************************************
99 \subsection[Bindery-idInfo]{Manipulating IdInfo}
101 %************************************************************************
104 stableAmodeIdInfo i amode lf_info = MkCgIdInfo i NoVolatileLoc (StableAmodeLoc amode) lf_info
105 heapIdInfo i offset lf_info = MkCgIdInfo i (VirHpLoc offset) NoStableLoc lf_info
106 tempIdInfo i uniq lf_info = MkCgIdInfo i (TempVarLoc uniq) NoStableLoc lf_info
108 letNoEscapeIdInfo i spa spb lf_info
109 = MkCgIdInfo i NoVolatileLoc (StableAmodeLoc (CJoinPoint spa spb)) lf_info
111 newTempAmodeAndIdInfo :: Id -> LambdaFormInfo -> (CAddrMode, CgIdInfo)
113 newTempAmodeAndIdInfo name lf_info
114 = (temp_amode, temp_idinfo)
117 temp_amode = CTemp uniq (idPrimRep name)
118 temp_idinfo = tempIdInfo name uniq lf_info
120 idInfoToAmode :: PrimRep -> CgIdInfo -> FCode CAddrMode
121 idInfoToAmode kind (MkCgIdInfo _ vol stab _) = idInfoPiecesToAmode kind vol stab
123 idInfoPiecesToAmode :: PrimRep -> VolatileLoc -> StableLoc -> FCode CAddrMode
125 idInfoPiecesToAmode kind (TempVarLoc uniq) stable_loc = returnFC (CTemp uniq kind)
126 idInfoPiecesToAmode kind (RegLoc magic_id) stable_loc = returnFC (CReg magic_id)
128 idInfoPiecesToAmode kind NoVolatileLoc (LitLoc lit) = returnFC (CLit lit)
129 idInfoPiecesToAmode kind NoVolatileLoc (StableAmodeLoc amode) = returnFC amode
131 idInfoPiecesToAmode kind (VirNodeLoc nd_off) stable_loc
132 = returnFC (CVal (NodeRel nd_off) kind)
133 -- Virtual offsets from Node increase into the closures,
134 -- and so do Node-relative offsets (which we want in the CVal),
135 -- so there is no mucking about to do to the offset.
137 idInfoPiecesToAmode kind (VirHpLoc hp_off) stable_loc
138 = getHpRelOffset hp_off `thenFC` \ rel_hp ->
139 returnFC (CAddr rel_hp)
141 idInfoPiecesToAmode kind NoVolatileLoc (VirAStkLoc i)
142 = getSpARelOffset i `thenFC` \ rel_spA ->
143 returnFC (CVal rel_spA kind)
145 idInfoPiecesToAmode kind NoVolatileLoc (VirBStkLoc i)
146 = getSpBRelOffset i `thenFC` \ rel_spB ->
147 returnFC (CVal rel_spB kind)
150 idInfoPiecesToAmode kind NoVolatileLoc NoStableLoc = panic "idInfoPiecesToAmode: no loc"
154 %************************************************************************
156 \subsection[Bindery-nuke-volatile]{Nuking volatile bindings}
158 %************************************************************************
160 We sometimes want to nuke all the volatile bindings; we must be sure
161 we don't leave any (NoVolatile, NoStable) binds around...
164 nukeVolatileBinds :: CgBindings -> CgBindings
165 nukeVolatileBinds binds
166 = mkIdEnv (foldr keep_if_stable [] (rngIdEnv binds))
168 keep_if_stable (MkCgIdInfo i _ NoStableLoc entry_info) acc = acc
169 keep_if_stable (MkCgIdInfo i _ stable_loc entry_info) acc
170 = (i, MkCgIdInfo i NoVolatileLoc stable_loc entry_info) : acc
174 %************************************************************************
176 \subsection[lookup-interface]{Interface functions to looking up bindings}
178 %************************************************************************
180 I {\em think} all looking-up is done through @getCAddrMode(s)@.
183 getCAddrModeAndInfo :: Id -> FCode (CAddrMode, LambdaFormInfo)
185 getCAddrModeAndInfo id
186 | not (isLocallyDefined name) || isWiredInName name
187 {- Why the "isWiredInName"?
188 Imagine you are compiling PrelBase.hs (a module that
189 supplies some of the wired-in values). What can
190 happen is that the compiler will inject calls to
191 (e.g.) GHCbase.unpackPS, where-ever it likes -- it
192 assumes those values are ubiquitously available.
193 The main point is: it may inject calls to them earlier
194 in GHCbase.hs than the actual definition...
196 = returnFC (global_amode, mkLFImported id)
198 | otherwise = -- *might* be a nested defn: in any case, it's something whose
199 -- definition we will know about...
200 lookupBindC id `thenFC` \ (MkCgIdInfo _ volatile_loc stable_loc lf_info) ->
201 idInfoPiecesToAmode kind volatile_loc stable_loc `thenFC` \ amode ->
202 returnFC (amode, lf_info)
205 global_amode = CLbl (mkClosureLabel id) kind
208 getCAddrMode :: Id -> FCode CAddrMode
210 = getCAddrModeAndInfo name `thenFC` \ (amode, _) ->
215 getCAddrModeIfVolatile :: Id -> FCode (Maybe CAddrMode)
216 getCAddrModeIfVolatile name
217 | toplevelishId name = returnFC Nothing
219 = lookupBindC name `thenFC` \ ~(MkCgIdInfo _ volatile_loc stable_loc lf_info) ->
221 NoStableLoc -> -- Aha! So it is volatile!
222 idInfoPiecesToAmode (idPrimRep name) volatile_loc NoStableLoc `thenFC` \ amode ->
223 returnFC (Just amode)
225 a_stable_loc -> returnFC Nothing
228 @getVolatileRegs@ gets a set of live variables, and returns a list of
229 all registers on which these variables depend. These are the regs
230 which must be saved and restored across any C calls. If a variable is
231 both in a volatile location (depending on a register) {\em and} a
232 stable one (notably, on the stack), we modify the current bindings to
233 forget the volatile one.
236 getVolatileRegs :: StgLiveVars -> FCode [MagicId]
239 = mapFCs snaffle_it (idSetToList vars) `thenFC` \ stuff ->
240 returnFC (catMaybes stuff)
243 = lookupBindC var `thenFC` \ (MkCgIdInfo _ volatile_loc stable_loc lf_info) ->
245 -- commoned-up code...
247 = if not (isVolatileReg reg) then
248 -- Potentially dies across C calls
249 -- For now, that's everything; we leave
250 -- it to the save-macros to decide which
251 -- regs *really* need to be saved.
255 NoStableLoc -> returnFC (Just reg) -- got one!
257 -- has both volatile & stable locations;
258 -- force it to rely on the stable location
259 modifyBindC var nuke_vol_bind `thenC`
263 RegLoc reg -> consider_reg reg
264 VirHpLoc _ -> consider_reg Hp
265 VirNodeLoc _ -> consider_reg node
266 non_reg_loc -> returnFC Nothing
268 nuke_vol_bind (MkCgIdInfo i _ stable_loc lf_info)
269 = MkCgIdInfo i NoVolatileLoc stable_loc lf_info
273 getArgAmodes :: [StgArg] -> FCode [CAddrMode]
274 getArgAmodes [] = returnFC []
275 getArgAmodes (atom:atoms)
276 = getArgAmode atom `thenFC` \ amode ->
277 getArgAmodes atoms `thenFC` \ amodes ->
278 returnFC ( amode : amodes )
280 getArgAmode :: StgArg -> FCode CAddrMode
282 getArgAmode (StgConArg var)
283 {- Why does this case differ from StgVarArg?
284 Because the program might look like this:
285 data Foo a = Empty | Baz a
286 f a x = let c = Empty! a
288 Now, when we go Core->Stg, we drop the type applications,
289 so we can inline c, giving
291 Now we are referring to Empty as an argument (rather than in an STGCon),
292 so we'll look it up with getCAddrMode. We want to return an amode for
293 the static closure that we make for nullary constructors. But if we blindly
294 go ahead with getCAddrMode we end up looking in the environment, and it ain't there!
296 This special case used to be in getCAddrModeAndInfo, but it doesn't work there.
299 If the constructor Baz isn't inlined we simply want to treat it like any other
300 identifier, with a top level definition. We don't want to spot that it's a constructor.
306 are treated differently; the former is a call to a bog standard function while the
307 latter uses the specially-labelled, pre-defined info tables etc for the constructor.
309 The way to think of this case in getArgAmode is that
312 App f (StgCon Empty [])
314 = returnFC (CLbl (mkStaticClosureLabel var) (idPrimRep var))
316 getArgAmode (StgVarArg var) = getCAddrMode var -- The common case
318 getArgAmode (StgLitArg lit) = returnFC (CLit lit)
321 %************************************************************************
323 \subsection[binding-and-rebinding-interface]{Interface functions for binding and re-binding names}
325 %************************************************************************
328 bindNewToAStack :: (Id, VirtualSpAOffset) -> Code
329 bindNewToAStack (name, offset)
332 info = MkCgIdInfo name NoVolatileLoc (VirAStkLoc offset) mkLFArgument
334 bindNewToBStack :: (Id, VirtualSpBOffset) -> Code
335 bindNewToBStack (name, offset)
338 info = MkCgIdInfo name NoVolatileLoc (VirBStkLoc offset) (panic "bindNewToBStack")
339 -- B-stack things shouldn't need lambda-form info!
341 bindNewToNode :: Id -> VirtualHeapOffset -> LambdaFormInfo -> Code
342 bindNewToNode name offset lf_info
345 info = MkCgIdInfo name (VirNodeLoc offset) NoStableLoc lf_info
347 -- Create a new temporary whose unique is that in the id,
348 -- bind the id to it, and return the addressing mode for the
350 bindNewToTemp :: Id -> FCode CAddrMode
352 = let (temp_amode, id_info) = newTempAmodeAndIdInfo name mkLFArgument
353 -- This is used only for things we don't know
354 -- anything about; values returned by a case statement,
357 addBindC name id_info `thenC`
360 bindNewToReg :: Id -> MagicId -> LambdaFormInfo -> Code
361 bindNewToReg name magic_id lf_info
364 info = MkCgIdInfo name (RegLoc magic_id) NoStableLoc lf_info
366 bindNewToLit name lit
369 info = MkCgIdInfo name NoVolatileLoc (LitLoc lit) (error "bindNewToLit")
371 bindArgsToRegs :: [Id] -> [MagicId] -> Code
372 bindArgsToRegs args regs
373 = listCs (zipWithEqual "bindArgsToRegs" bind args regs)
375 arg `bind` reg = bindNewToReg arg reg mkLFArgument
378 @bindNewPrimToAmode@ works only for certain addressing modes, because
379 those are the only ones we've needed so far!
382 bindNewPrimToAmode :: Id -> CAddrMode -> Code
383 bindNewPrimToAmode name (CReg reg) = bindNewToReg name reg (panic "bindNewPrimToAmode")
385 -- LFinfo is irrelevant for primitives
386 bindNewPrimToAmode name (CTemp uniq kind)
387 = addBindC name (tempIdInfo name uniq (panic "bindNewPrimToAmode"))
388 -- LFinfo is irrelevant for primitives
390 bindNewPrimToAmode name (CLit lit) = bindNewToLit name lit
392 bindNewPrimToAmode name (CVal (SpBRel _ offset) _)
393 = bindNewToBStack (name, offset)
395 bindNewPrimToAmode name (CVal (NodeRel offset) _)
396 = bindNewToNode name offset (panic "bindNewPrimToAmode node")
397 -- See comment on idInfoPiecesToAmode for VirNodeLoc
400 bindNewPrimToAmode name amode
401 = panic ("bindNew...:"++(show (pprAmode PprDebug amode)))
406 rebindToAStack :: Id -> VirtualSpAOffset -> Code
407 rebindToAStack name offset
408 = modifyBindC name replace_stable_fn
410 replace_stable_fn (MkCgIdInfo i vol stab einfo)
411 = MkCgIdInfo i vol (VirAStkLoc offset) einfo
413 rebindToBStack :: Id -> VirtualSpBOffset -> Code
414 rebindToBStack name offset
415 = modifyBindC name replace_stable_fn
417 replace_stable_fn (MkCgIdInfo i vol stab einfo)
418 = MkCgIdInfo i vol (VirBStkLoc offset) einfo