9247568401cc764b2d199230f217e956d32be6c8
[ghc-hetmet.git] / ghc / compiler / absCSyn / PprAbsC.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
3 %
4 %************************************************************************
5 %*                                                                      *
6 \section[PprAbsC]{Pretty-printing Abstract~C}
7 %*                                                                      *
8 %************************************************************************
9
10 \begin{code}
11 #include "HsVersions.h"
12
13 module PprAbsC (
14         writeRealC,
15         dumpRealC
16 #if defined(DEBUG)
17         , pprAmode -- otherwise, not exported
18 #endif
19     ) where
20
21 import Ubiq{-uitous-}
22 import AbsCLoop         -- break its dependence on ClosureInfo
23
24 import AbsCSyn
25
26 import AbsCUtils        ( getAmodeRep, nonemptyAbsC,
27                           mixedPtrLocn, mixedTypeLocn
28                         )
29 import CgCompInfo       ( spARelToInt, spBRelToInt, mIN_UPD_SIZE )
30 import CLabel           ( externallyVisibleCLabel, mkErrorStdEntryLabel,
31                           isReadOnly, needsCDecl, pprCLabel,
32                           CLabel{-instance Ord-}
33                         )
34 import CmdLineOpts      ( opt_SccProfilingOn )
35 import CostCentre       ( uppCostCentre, uppCostCentreDecl )
36 import Costs            ( costs, addrModeCosts, CostRes(..), Side(..) )
37 import CStrings         ( stringToC )
38 import FiniteMap        ( addToFM, emptyFM, lookupFM )
39 import HeapOffs         ( isZeroOff, subOff, pprHeapOffset )
40 import Literal          ( showLiteral, Literal(..) )
41 import Maybes           ( maybeToBool, catMaybes )
42 import PprStyle         ( PprStyle(..) )
43 import Pretty           ( prettyToUn )
44 import PrimOp           ( primOpNeedsWrapper, pprPrimOp, PrimOp(..) )
45 import PrimRep          ( isFloatingRep, showPrimRep, PrimRep(..) )
46 import SMRep            ( getSMInfoStr, getSMInitHdrStr, getSMUpdInplaceHdrStr,
47                           isConstantRep, isSpecRep, isPhantomRep
48                         )
49 import Unique           ( pprUnique, Unique{-instance NamedThing-} )
50 import UniqSet          ( emptyUniqSet, elementOfUniqSet,
51                           addOneToUniqSet, UniqSet(..)
52                         )
53 import Unpretty         -- ********** NOTE **********
54 import Util             ( nOfThem, panic, assertPanic )
55
56 infixr 9 `thenTE`
57 \end{code}
58
59 For spitting out the costs of an abstract~C expression, @writeRealC@
60 now not only prints the C~code of the @absC@ arg but also adds a macro
61 call to a cost evaluation function @GRAN_EXEC@. For that,
62 @pprAbsC@ has a new ``costs'' argument.  %% HWL
63
64 \begin{code}
65 writeRealC :: _FILE -> AbstractC -> IO ()
66
67 writeRealC file absC
68   = uppAppendFile file 80 (
69       uppAbove (pprAbsC PprForC absC (costs absC)) (uppChar '\n')
70     )
71
72 dumpRealC :: AbstractC -> String
73
74 dumpRealC absC
75   = uppShow 80 (
76       uppAbove (pprAbsC PprForC absC (costs absC)) (uppChar '\n')
77     )
78 \end{code}
79
80 This emits the macro,  which is used in GrAnSim  to compute the total costs
81 from a cost 5 tuple. %%  HWL
82
83 \begin{code}
84 emitMacro :: CostRes -> Unpretty
85
86 #ifndef GRAN
87 emitMacro _ = uppNil
88 #else
89 emitMacro (Cost (i,b,l,s,f))
90   = uppBesides [ uppStr "GRAN_EXEC(",
91         uppInt i, uppComma, uppInt b, uppComma, uppInt l, uppComma,
92         uppInt s, uppComma, uppInt f, pp_paren_semi ]
93 #endif {-GRAN-}
94 \end{code}
95
96 \begin{code}
97 pp_paren_semi = uppStr ");"
98
99 -- ---------------------------------------------------------------------------
100 -- New type: Now pprAbsC also takes the costs for evaluating the Abstract C
101 -- code as an argument (that's needed when spitting out the GRAN_EXEC macro
102 -- which must be done before the return i.e. inside absC code)   HWL
103 -- ---------------------------------------------------------------------------
104
105 pprAbsC :: PprStyle -> AbstractC -> CostRes -> Unpretty
106
107 pprAbsC sty AbsCNop _ = uppNil
108 pprAbsC sty (AbsCStmts s1 s2) c = uppAbove (pprAbsC sty s1 c) (pprAbsC sty s2 c)
109
110 pprAbsC sty (CClosureUpdInfo info) c
111   = pprAbsC sty info c
112
113 pprAbsC sty (CAssign dest src) _ = pprAssign sty (getAmodeRep dest) dest src
114
115 pprAbsC sty (CJump target) c
116   = uppAbove (uppBesides [emitMacro c {-WDP:, uppStr "/* <--++  CJump */"-} ])
117              (uppBesides [ uppStr "JMP_(", pprAmode sty target, pp_paren_semi ])
118
119 pprAbsC sty (CFallThrough target) c
120   = uppAbove (uppBesides [emitMacro c {-WDP:, uppStr "/* <--++  CFallThrough */"-} ])
121              (uppBesides [ uppStr "JMP_(", pprAmode sty target, pp_paren_semi ])
122
123 -- --------------------------------------------------------------------------
124 -- Spit out GRAN_EXEC macro immediately before the return                 HWL
125
126 pprAbsC sty (CReturn am return_info)  c
127   = uppAbove (uppBesides [emitMacro c {-WDP:, uppStr "/* <----  CReturn */"-} ])
128              (uppBesides [uppStr "JMP_(", target, pp_paren_semi ])
129   where
130    target = case return_info of
131         DirectReturn -> uppBesides [uppStr "DIRECT(", pprAmode sty am, uppRparen]
132         DynamicVectoredReturn am' -> mk_vector (pprAmode sty am')
133         StaticVectoredReturn n -> mk_vector (uppInt n)  -- Always positive
134    mk_vector x = uppBesides [uppLparen, pprAmode sty am, uppStr ")[RVREL(", x, uppStr ")]"]
135
136 pprAbsC sty (CSplitMarker) _ = uppPStr SLIT("/* SPLIT */")
137
138 -- we optimise various degenerate cases of CSwitches.
139
140 -- --------------------------------------------------------------------------
141 -- Assume: CSwitch is also end of basic block
142 --         costs function yields nullCosts for whole switch
143 --         ==> inherited costs c are those of basic block up to switch
144 --         ==> inherit c + costs for the corresponding branch
145 --                                                                       HWL
146 -- --------------------------------------------------------------------------
147
148 pprAbsC sty (CSwitch discrim [] deflt) c
149   = pprAbsC sty deflt (c + costs deflt)
150     -- Empty alternative list => no costs for discrim as nothing cond. here HWL
151
152 pprAbsC sty (CSwitch discrim [(tag,alt_code)] deflt) c -- only one alt
153   = case (nonemptyAbsC deflt) of
154       Nothing ->                -- one alt and no default
155                  pprAbsC sty alt_code (c + costs alt_code)
156                  -- Nothing conditional in here either  HWL
157
158       Just dc ->                -- make it an "if"
159                  do_if_stmt sty discrim tag alt_code dc c
160
161 pprAbsC sty (CSwitch discrim [(tag1@(MachInt i1 _), alt_code1),
162                               (tag2@(MachInt i2 _), alt_code2)] deflt) c
163   | empty_deflt && ((i1 == 0 && i2 == 1) || (i1 == 1 && i2 == 0))
164   = if (i1 == 0) then
165         do_if_stmt sty discrim tag1 alt_code1 alt_code2 c
166     else
167         do_if_stmt sty discrim tag2 alt_code2 alt_code1 c
168   where
169     empty_deflt = not (maybeToBool (nonemptyAbsC deflt))
170
171 pprAbsC sty (CSwitch discrim alts deflt) c -- general case
172   | isFloatingRep (getAmodeRep discrim)
173     = pprAbsC sty (foldr ( \ a -> CSwitch discrim [a]) deflt alts) c
174   | otherwise
175     = uppAboves [
176         uppBesides [uppStr "switch (", pp_discrim, uppStr ") {"],
177         uppNest 2 (uppAboves (map (ppr_alt sty) alts)),
178         (case (nonemptyAbsC deflt) of
179            Nothing -> uppNil
180            Just dc ->
181             uppNest 2 (uppAboves [uppPStr SLIT("default:"),
182                                   pprAbsC sty dc (c + switch_head_cost
183                                                     + costs dc),
184                                   uppPStr SLIT("break;")])),
185         uppChar '}' ]
186   where
187     pp_discrim
188       = pprAmode sty discrim
189
190     ppr_alt sty (lit, absC)
191       = uppAboves [ uppBesides [uppPStr SLIT("case "), pprBasicLit sty lit, uppChar ':'],
192                    uppNest 2 (uppAbove (pprAbsC sty absC (c + switch_head_cost + costs absC))
193                                        (uppPStr SLIT("break;"))) ]
194
195     -- Costs for addressing header of switch and cond. branching        -- HWL
196     switch_head_cost = addrModeCosts discrim Rhs + (Cost (0, 1, 0, 0, 0))
197
198 pprAbsC sty stmt@(COpStmt results op@(CCallOp _ _ _ _ _) args liveness_mask vol_regs) _
199   = pprCCall sty op args results liveness_mask vol_regs
200
201 pprAbsC sty stmt@(COpStmt results op args liveness_mask vol_regs) _
202   = let
203         non_void_args = grab_non_void_amodes args
204         non_void_results = grab_non_void_amodes results
205         -- if just one result, we print in the obvious "assignment" style;
206         -- if 0 or many results, we emit a macro call, w/ the results
207         -- followed by the arguments.  The macro presumably knows which
208         -- are which :-)
209
210         the_op = ppr_op_call non_void_results non_void_args
211                 -- liveness mask is *in* the non_void_args
212     in
213     case (ppr_vol_regs sty vol_regs) of { (pp_saves, pp_restores) ->
214     if primOpNeedsWrapper op then
215         uppAboves [  pp_saves,
216                     the_op,
217                     pp_restores
218                  ]
219     else
220         the_op
221     }
222   where
223     ppr_op_call results args
224       = uppBesides [ prettyToUn (pprPrimOp sty op), uppLparen,
225         uppIntersperse uppComma (map ppr_op_result results),
226         if null results || null args then uppNil else uppComma,
227         uppIntersperse uppComma (map (pprAmode sty) args),
228         pp_paren_semi ]
229
230     ppr_op_result r = ppr_amode sty r
231       -- primop macros do their own casting of result;
232       -- hence we can toss the provided cast...
233
234 pprAbsC sty (CSimultaneous abs_c) c
235   = uppBesides [uppStr "{{", pprAbsC sty abs_c c, uppStr "}}"]
236
237 pprAbsC sty stmt@(CMacroStmt macro as) _
238   = uppBesides [uppStr (show macro), uppLparen,
239         uppIntersperse uppComma (map (ppr_amode sty) as),pp_paren_semi] -- no casting
240 pprAbsC sty stmt@(CCallProfCtrMacro op as) _
241   = uppBesides [uppPStr op, uppLparen,
242         uppIntersperse uppComma (map (ppr_amode sty) as),pp_paren_semi]
243 pprAbsC sty stmt@(CCallProfCCMacro op as) _
244   = uppBesides [uppPStr op, uppLparen,
245         uppIntersperse uppComma (map (ppr_amode sty) as),pp_paren_semi]
246
247 pprAbsC sty (CCodeBlock label abs_C) _
248   = ASSERT( maybeToBool(nonemptyAbsC abs_C) )
249     case (pprTempAndExternDecls abs_C) of { (pp_temps, pp_exts) ->
250     uppAboves [
251         uppBesides [uppStr (if (externallyVisibleCLabel label)
252                           then "FN_("   -- abbreviations to save on output
253                           else "IFN_("),
254                    pprCLabel sty label, uppStr ") {"],
255         case sty of
256           PprForC -> uppAbove pp_exts pp_temps
257           _ -> uppNil,
258         uppNest 8 (uppPStr SLIT("FB_")),
259         uppNest 8 (pprAbsC sty abs_C (costs abs_C)),
260         uppNest 8 (uppPStr SLIT("FE_")),
261         uppChar '}' ]
262     }
263
264 pprAbsC sty (CInitHdr cl_info reg_rel cost_centre inplace_upd) _
265   = uppBesides [ pp_init_hdr, uppStr "_HDR(",
266                 ppr_amode sty (CAddr reg_rel), uppComma,
267                 pprCLabel sty info_lbl, uppComma,
268                 if_profiling sty (pprAmode sty cost_centre), uppComma,
269                 pprHeapOffset sty size, uppComma, uppInt ptr_wds, pp_paren_semi ]
270   where
271     info_lbl    = infoTableLabelFromCI cl_info
272     sm_rep      = closureSMRep     cl_info
273     size        = closureSizeWithoutFixedHdr cl_info
274     ptr_wds     = closurePtrsSize  cl_info
275
276     pp_init_hdr = uppStr (if inplace_upd then
277                             getSMUpdInplaceHdrStr sm_rep
278                         else
279                             getSMInitHdrStr sm_rep)
280
281 pprAbsC sty stmt@(CStaticClosure closure_lbl cl_info cost_centre amodes) _
282   = case (pprTempAndExternDecls stmt) of { (_, pp_exts) ->
283     uppAboves [
284         case sty of
285           PprForC -> pp_exts
286           _ -> uppNil,
287         uppBesides [
288                 uppStr "SET_STATIC_HDR(",
289                 pprCLabel sty closure_lbl,                      uppComma,
290                 pprCLabel sty info_lbl,                         uppComma,
291                 if_profiling sty (pprAmode sty cost_centre),    uppComma,
292                 ppLocalness closure_lbl,                        uppComma,
293                 ppLocalnessMacro False{-for data-} info_lbl,
294                 uppChar ')'
295                 ],
296         uppNest 2 (uppBesides (map (ppr_item sty) amodes)),
297         uppNest 2 (uppBesides (map (ppr_item sty) padding_wds)),
298         uppStr "};" ]
299     }
300   where
301     info_lbl = infoTableLabelFromCI cl_info
302
303     ppr_item sty item
304       = if getAmodeRep item == VoidRep
305         then uppStr ", (W_) 0" -- might not even need this...
306         else uppBeside (uppStr ", (W_)") (ppr_amode sty item)
307
308     padding_wds =
309         if not (closureUpdReqd cl_info) then
310             []
311         else
312             case (max 0 (mIN_UPD_SIZE - length amodes)) of { still_needed ->
313             nOfThem still_needed (mkIntCLit 0) } -- a bunch of 0s
314
315 {-
316    STATIC_INIT_HDR(c,i,localness) blows into:
317         localness W_ c_closure [] = { i_info, extra_fixed_wd<1..n>
318
319    then *NO VarHdr STUFF FOR STATIC*...
320
321    then the amodes are dropped in...
322         ,a1 ,a2 ... ,aN
323    then a close brace:
324         };
325 -}
326
327 pprAbsC sty stmt@(CClosureInfoAndCode cl_info slow maybe_fast upd cl_descr liveness) _
328   = uppAboves [
329         uppBesides [
330             pp_info_rep,
331             uppStr "_ITBL(",
332             pprCLabel sty info_lbl,                     uppComma,
333
334                 -- CONST_ITBL needs an extra label for
335                 -- the static version of the object.
336             if isConstantRep sm_rep
337             then uppBeside (pprCLabel sty (closureLabelFromCI cl_info)) uppComma
338             else uppNil,
339
340             pprCLabel sty slow_lbl,     uppComma,
341             pprAmode sty upd,           uppComma,
342             uppInt liveness,            uppComma,
343
344             pp_tag,                     uppComma,
345             pp_size,                    uppComma,
346             pp_ptr_wds,                 uppComma,
347
348             ppLocalness info_lbl,                               uppComma,
349             ppLocalnessMacro True{-function-} slow_lbl,         uppComma,
350
351             if is_selector
352             then uppBeside (uppInt select_word_i) uppComma
353             else uppNil,
354
355             if_profiling sty pp_kind, uppComma,
356             if_profiling sty pp_descr, uppComma,
357             if_profiling sty pp_type,
358             uppStr ");"
359         ],
360         pp_slow,
361         case maybe_fast of
362             Nothing -> uppNil
363             Just fast -> let stuff = CCodeBlock fast_lbl fast in
364                          pprAbsC sty stuff (costs stuff)
365     ]
366   where
367     info_lbl    = infoTableLabelFromCI cl_info
368     fast_lbl    = fastLabelFromCI cl_info
369     sm_rep      = closureSMRep    cl_info
370
371     (slow_lbl, pp_slow)
372       = case (nonemptyAbsC slow) of
373           Nothing -> (mkErrorStdEntryLabel, uppNil)
374           Just xx -> (entryLabelFromCI cl_info,
375                        let stuff = CCodeBlock slow_lbl xx in
376                        pprAbsC sty stuff (costs stuff))
377
378     maybe_selector = maybeSelectorInfo cl_info
379     is_selector = maybeToBool maybe_selector
380     (Just (_, select_word_i)) = maybe_selector
381
382     pp_info_rep     -- special stuff if it's a selector; otherwise, just the SMrep
383       = uppStr (if is_selector then "SELECT" else (getSMInfoStr sm_rep))
384
385     pp_tag = uppInt (closureSemiTag cl_info)
386
387     is_phantom = isPhantomRep sm_rep
388
389     pp_size = if isSpecRep sm_rep then  -- exploiting: SPEC_VHS == 0 (always)
390                  uppInt (closureNonHdrSize cl_info)
391
392               else if is_phantom then   -- do not have sizes for these
393                  uppNil
394               else
395                  pprHeapOffset sty (closureSizeWithoutFixedHdr cl_info)
396
397     pp_ptr_wds  = if is_phantom then
398                      uppNil
399                   else
400                      uppInt (closurePtrsSize cl_info)
401
402     pp_kind  = uppStr (closureKind cl_info)
403     pp_descr = uppBesides [uppChar '"', uppStr (stringToC cl_descr), uppChar '"']
404     pp_type  = uppBesides [uppChar '"', uppStr (stringToC (closureTypeDescr cl_info)), uppChar '"']
405
406 pprAbsC sty (CRetVector lbl maybes deflt) c
407   = uppAboves [ uppStr "{ // CRetVector (lbl????)",
408                uppNest 8 (uppSep (map (ppr_maybe_amode sty) maybes)),
409                uppStr "} /*default=*/ {", pprAbsC sty deflt c,
410                uppStr "}"]
411   where
412     ppr_maybe_amode sty Nothing  = uppPStr SLIT("/*default*/")
413     ppr_maybe_amode sty (Just a) = pprAmode sty a
414
415 pprAbsC sty stmt@(CRetUnVector label amode) _
416   = uppBesides [uppStr "UNVECTBL(", pp_static, uppComma, pprCLabel sty label, uppComma,
417             pprAmode sty amode, uppRparen]
418   where
419     pp_static = if externallyVisibleCLabel label then uppNil else uppPStr SLIT("static")
420
421 pprAbsC sty stmt@(CFlatRetVector label amodes) _
422   =     case (pprTempAndExternDecls stmt) of { (_, pp_exts) ->
423         uppAboves [
424             case sty of
425               PprForC -> pp_exts
426               _ -> uppNil,
427             uppBesides [ppLocalness label, uppPStr SLIT(" W_ "),
428                        pprCLabel sty label, uppStr "[] = {"],
429             uppNest 2 (uppInterleave uppComma (map (ppr_item sty) amodes)),
430             uppStr "};" ] }
431   where
432     ppr_item sty item = uppBeside (uppStr "(W_) ") (ppr_amode sty item)
433
434 pprAbsC sty (CCostCentreDecl is_local cc) _ = uppCostCentreDecl sty is_local cc
435 \end{code}
436
437 \begin{code}
438 ppLocalness label
439   = uppBeside static const
440   where
441     static = if (externallyVisibleCLabel label) then uppNil else uppPStr SLIT("static ")
442     const  = if not (isReadOnly label)          then uppNil else uppPStr SLIT("const")
443
444 ppLocalnessMacro for_fun{-vs data-} clabel
445   = case (if externallyVisibleCLabel clabel then "E" else "I") of { prefix ->
446     case (if isReadOnly clabel then "RO_" else "")            of { suffix ->
447     if for_fun
448        then uppStr (prefix ++ "F_")
449        else uppStr (prefix ++ "D_" ++ suffix)
450     } }
451 \end{code}
452
453 \begin{code}
454 grab_non_void_amodes amodes
455   = filter non_void amodes
456
457 non_void amode
458   = case (getAmodeRep amode) of
459       VoidRep -> False
460       k -> True
461 \end{code}
462
463 \begin{code}
464 ppr_vol_regs :: PprStyle -> [MagicId] -> (Unpretty, Unpretty)
465
466 ppr_vol_regs sty [] = (uppNil, uppNil)
467 ppr_vol_regs sty (VoidReg:rs) = ppr_vol_regs sty rs
468 ppr_vol_regs sty (r:rs)
469   = let pp_reg = case r of
470                     VanillaReg pk n -> pprVanillaReg n
471                     _ -> pprMagicId sty r
472         (more_saves, more_restores) = ppr_vol_regs sty rs
473     in
474     (uppAbove (uppBeside (uppPStr SLIT("CALLER_SAVE_"))    pp_reg) more_saves,
475      uppAbove (uppBeside (uppPStr SLIT("CALLER_RESTORE_")) pp_reg) more_restores)
476
477 -- pp_basic_{saves,restores}: The BaseReg, SpA, SuA, SpB, SuB, Hp and
478 -- HpLim (see StgRegs.lh) may need to be saved/restored around CCalls,
479 -- depending on the platform.  (The "volatile regs" stuff handles all
480 -- other registers.)  Just be *sure* BaseReg is OK before trying to do
481 -- anything else.
482 pp_basic_saves
483   = uppAboves [
484         uppPStr SLIT("CALLER_SAVE_Base"),
485         uppPStr SLIT("CALLER_SAVE_SpA"),
486         uppPStr SLIT("CALLER_SAVE_SuA"),
487         uppPStr SLIT("CALLER_SAVE_SpB"),
488         uppPStr SLIT("CALLER_SAVE_SuB"),
489         uppPStr SLIT("CALLER_SAVE_Ret"),
490 --      uppPStr SLIT("CALLER_SAVE_Activity"),
491         uppPStr SLIT("CALLER_SAVE_Hp"),
492         uppPStr SLIT("CALLER_SAVE_HpLim") ]
493
494 pp_basic_restores
495   = uppAboves [
496         uppPStr SLIT("CALLER_RESTORE_Base"), -- must be first!
497         uppPStr SLIT("CALLER_RESTORE_SpA"),
498         uppPStr SLIT("CALLER_RESTORE_SuA"),
499         uppPStr SLIT("CALLER_RESTORE_SpB"),
500         uppPStr SLIT("CALLER_RESTORE_SuB"),
501         uppPStr SLIT("CALLER_RESTORE_Ret"),
502 --      uppPStr SLIT("CALLER_RESTORE_Activity"),
503         uppPStr SLIT("CALLER_RESTORE_Hp"),
504         uppPStr SLIT("CALLER_RESTORE_HpLim"),
505         uppPStr SLIT("CALLER_RESTORE_StdUpdRetVec"),
506         uppPStr SLIT("CALLER_RESTORE_StkStub") ]
507 \end{code}
508
509 \begin{code}
510 if_profiling sty pretty
511   = case sty of
512       PprForC -> if  opt_SccProfilingOn
513                  then pretty
514                  else uppChar '0' -- leave it out!
515
516       _ -> {-print it anyway-} pretty
517
518 -- ---------------------------------------------------------------------------
519 -- Changes for GrAnSim:
520 --  draw costs for computation in head of if into both branches;
521 --  as no abstractC data structure is given for the head, one is constructed
522 --  guessing unknown values and fed into the costs function
523 -- ---------------------------------------------------------------------------
524
525 do_if_stmt sty discrim tag alt_code deflt c
526   = case tag of
527       -- This special case happens when testing the result of a comparison.
528       -- We can just avoid some redundant clutter in the output.
529       MachInt n _ | n==0 -> ppr_if_stmt sty (pprAmode sty discrim)
530                                       deflt alt_code
531                                       (addrModeCosts discrim Rhs) c
532       other              -> let
533                                cond = uppBesides [ pprAmode sty discrim,
534                                           uppPStr SLIT(" == "),
535                                           pprAmode sty (CLit tag) ]
536                             in
537                             ppr_if_stmt sty cond
538                                          alt_code deflt
539                                          (addrModeCosts discrim Rhs) c
540
541 ppr_if_stmt sty pp_pred then_part else_part discrim_costs c
542   = uppAboves [
543       uppBesides [uppStr "if (", pp_pred, uppStr ") {"],
544       uppNest 8 (pprAbsC sty then_part  (c + discrim_costs +
545                                         (Cost (0, 2, 0, 0, 0)) +
546                                         costs then_part)),
547       (case nonemptyAbsC else_part of Nothing -> uppNil; Just _ -> uppStr "} else {"),
548       uppNest 8 (pprAbsC sty else_part  (c + discrim_costs +
549                                         (Cost (0, 1, 0, 0, 0)) +
550                                         costs else_part)),
551       uppChar '}' ]
552     {- Total costs = inherited costs (before if) + costs for accessing discrim
553                      + costs for cond branch ( = (0, 1, 0, 0, 0) )
554                      + costs for that alternative
555     -}
556 \end{code}
557
558 Historical note: this used to be two separate cases -- one for `ccall'
559 and one for `casm'.  To get round a potential limitation to only 10
560 arguments, the numbering of arguments in @process_casm@ was beefed up a
561 bit. ADR
562
563 Some rough notes on generating code for @CCallOp@:
564
565 1) Evaluate all arguments and stuff them into registers. (done elsewhere)
566 2) Save any essential registers (heap, stack, etc).
567
568    ToDo: If stable pointers are in use, these must be saved in a place
569    where the runtime system can get at them so that the Stg world can
570    be restarted during the call.
571
572 3) Save any temporary registers that are currently in use.
573 4) Do the call putting result into a local variable
574 5) Restore essential registers
575 6) Restore temporaries
576
577    (This happens after restoration of essential registers because we
578    might need the @Base@ register to access all the others correctly.)
579
580 7) If returning Malloc Pointer, build a closure containing the
581    appropriate value.
582
583    Otherwise, copy local variable into result register.
584
585 8) If ccall (not casm), declare the function being called as extern so
586    that C knows if it returns anything other than an int.
587
588 \begin{pseudocode}
589 { ResultType _ccall_result;
590   basic_saves;
591   saves;
592   _ccall_result = f( args );
593   basic_restores;
594   restores;
595
596   #if MallocPtr
597         constructMallocPtr(liveness, return_reg, _ccall_result);
598   #else
599         return_reg = _ccall_result;
600   #end
601 }
602 \end{pseudocode}
603
604 Amendment to the above: if we can GC, we have to:
605
606 * make sure we save all our registers away where the garbage collector
607   can get at them.
608 * be sure that there are no live registers or we're in trouble.
609   (This can cause problems if you try something foolish like passing
610    an array or mallocptr to a _ccall_GC_ thing.)
611 * increment/decrement the @inCCallGC@ counter before/after the call so
612   that the runtime check that PerformGC is being used sensibly will work.
613
614 \begin{code}
615 pprCCall sty op@(CCallOp op_str is_asm may_gc _ _) args results liveness_mask vol_regs
616   = if (may_gc && liveness_mask /= noLiveRegsMask)
617     then panic ("Live register in _casm_GC_ \"" ++ casm_str ++ "\" " ++ (uppShow 80 (uppCat pp_non_void_args)) ++ "\n")
618     else
619     uppAboves [
620       uppChar '{',
621       declare_local_vars,   -- local var for *result*
622       uppAboves local_arg_decls,
623       -- if is_asm then uppNil else declareExtern,
624       pp_save_context,
625       process_casm local_vars pp_non_void_args casm_str,
626       pp_restore_context,
627       assign_results,
628       uppChar '}'
629     ]
630   where
631     (pp_saves, pp_restores) = ppr_vol_regs sty vol_regs
632     (pp_save_context, pp_restore_context) =
633         if may_gc
634         then (  uppStr "extern StgInt inCCallGC; SaveAllStgRegs(); inCCallGC++;",
635                 uppStr "inCCallGC--; RestoreAllStgRegs();")
636         else (  pp_basic_saves `uppAbove` pp_saves,
637                 pp_basic_restores `uppAbove` pp_restores)
638
639     non_void_args =
640         let nvas = tail args
641         in ASSERT (all non_void nvas) nvas
642     -- the first argument will be the "I/O world" token (a VoidRep)
643     -- all others should be non-void
644
645     non_void_results =
646         let nvrs = grab_non_void_amodes results
647         in ASSERT (length nvrs <= 1) nvrs
648     -- there will usually be two results: a (void) state which we
649     -- should ignore and a (possibly void) result.
650
651     (local_arg_decls, pp_non_void_args)
652       = unzip [ ppr_casm_arg sty a i | (a,i) <- non_void_args `zip` [1..] ]
653
654     pp_liveness = pprAmode sty (mkIntCLit liveness_mask)
655
656     (declare_local_vars, local_vars, assign_results)
657       = ppr_casm_results sty non_void_results pp_liveness
658
659     casm_str = if is_asm then _UNPK_ op_str else ccall_str
660
661     -- Remainder only used for ccall
662
663     ccall_str = uppShow 80
664         (uppBesides [
665                 if null non_void_results
666                   then uppNil
667                   else uppPStr SLIT("%r = "),
668                 uppLparen, uppPStr op_str, uppLparen,
669                   uppIntersperse uppComma ccall_args,
670                 uppStr "));"
671         ])
672     num_args = length non_void_args
673     ccall_args = take num_args [ uppBeside (uppChar '%') (uppInt i) | i <- [0..] ]
674 \end{code}
675
676 If the argument is a heap object, we need to reach inside and pull out
677 the bit the C world wants to see.  The only heap objects which can be
678 passed are @Array@s, @ByteArray@s and @MallocPtr@s.
679
680 \begin{code}
681 ppr_casm_arg :: PprStyle -> CAddrMode -> Int -> (Unpretty, Unpretty)
682     -- (a) decl and assignment, (b) local var to be used later
683
684 ppr_casm_arg sty amode a_num
685   = let
686         a_kind   = getAmodeRep amode
687         pp_amode = pprAmode sty amode
688         pp_kind  = pprPrimKind sty a_kind
689
690         local_var  = uppBeside (uppPStr SLIT("_ccall_arg")) (uppInt a_num)
691
692         (arg_type, pp_amode2)
693           = case a_kind of
694
695               -- for array arguments, pass a pointer to the body of the array
696               -- (PTRS_ARR_CTS skips over all the header nonsense)
697               ArrayRep      -> (pp_kind,
698                                 uppBesides [uppStr "PTRS_ARR_CTS(", pp_amode, uppRparen])
699               ByteArrayRep -> (pp_kind,
700                                 uppBesides [uppStr "BYTE_ARR_CTS(", pp_amode, uppRparen])
701
702               -- for Malloc Pointers, use MALLOC_PTR_DATA to fish out the contents.
703               MallocPtrRep -> (uppPStr SLIT("StgMallocPtr"),
704                                 uppBesides [uppStr "MallocPtr_CLOSURE_DATA(", pp_amode, uppStr")"])
705               other         -> (pp_kind, pp_amode)
706
707         declare_local_var
708           = uppBesides [ arg_type, uppSP, local_var, uppEquals, pp_amode2, uppSemi ]
709     in
710     (declare_local_var, local_var)
711 \end{code}
712
713 For l-values, the critical questions are:
714
715 1) Are there any results at all?
716
717    We only allow zero or one results.
718
719 2) Is the result is a mallocptr?
720
721    The mallocptr must be encapsulated immediately in a heap object.
722
723 \begin{code}
724 ppr_casm_results ::
725         PprStyle        -- style
726         -> [CAddrMode]  -- list of results (length <= 1)
727         -> Unpretty     -- liveness mask
728         ->
729         ( Unpretty,     -- declaration of any local vars
730           [Unpretty],   -- list of result vars (same length as results)
731           Unpretty )    -- assignment (if any) of results in local var to registers
732
733 ppr_casm_results sty [] liveness
734   = (uppNil, [], uppNil)        -- no results
735
736 ppr_casm_results sty [r] liveness
737   = let
738         result_reg = ppr_amode sty r
739         r_kind     = getAmodeRep r
740
741         local_var  = uppPStr SLIT("_ccall_result")
742
743         (result_type, assign_result)
744           = case r_kind of
745               MallocPtrRep ->
746                 (uppPStr SLIT("StgMallocPtr"),
747                  uppBesides [ uppStr "constructMallocPtr(",
748                                 liveness, uppComma,
749                                 result_reg, uppComma,
750                                 local_var,
751                              pp_paren_semi ])
752               _ ->
753                 (pprPrimKind sty r_kind,
754                  uppBesides [ result_reg, uppEquals, local_var, uppSemi ])
755
756         declare_local_var = uppBesides [ result_type, uppSP, local_var, uppSemi ]
757     in
758     (declare_local_var, [local_var], assign_result)
759
760 ppr_casm_results sty rs liveness
761   = panic "ppr_casm_results: ccall/casm with many results"
762 \end{code}
763
764
765 Note the sneaky way _the_ result is represented by a list so that we
766 can complain if it's used twice.
767
768 ToDo: Any chance of giving line numbers when process-casm fails?
769       Or maybe we should do a check _much earlier_ in compiler. ADR
770
771 \begin{code}
772 process_casm ::
773         [Unpretty]              -- results (length <= 1)
774         -> [Unpretty]           -- arguments
775         -> String               -- format string (with embedded %'s)
776         ->
777         Unpretty                        -- code being generated
778
779 process_casm results args string = process results args string
780  where
781   process []    _ "" = uppNil
782   process (_:_) _ "" = error ("process_casm: non-void result not assigned while processing _casm_ \"" ++ string ++ "\"\n(Try changing result type to PrimIO ()\n")
783
784   process ress args ('%':cs)
785     = case cs of
786         [] ->
787             error ("process_casm: lonely % while processing _casm_ \"" ++ string ++ "\".\n")
788
789         ('%':css) ->
790             uppBeside (uppChar '%') (process ress args css)
791
792         ('r':css)  ->
793           case ress of
794             []  -> error ("process_casm: no result to match %r while processing _casm_ \"" ++ string ++ "\".\nTry deleting %r or changing result type from PrimIO ()\n")
795             [r] -> uppBeside r (process [] args css)
796             _   -> panic ("process_casm: casm with many results while processing _casm_ \"" ++ string ++ "\".\n")
797
798         other ->
799           case readDec other of
800             [(num,css)] ->
801                   if 0 <= num && num < length args
802                   then uppBeside (uppParens (args !! num))
803                                  (process ress args css)
804                     else error ("process_casm: no such arg #:"++(show num)++" while processing \"" ++ string ++ "\".\n")
805             _ -> error ("process_casm: not %<num> while processing _casm_ \"" ++ string ++ "\".\n")
806
807   process ress args (other_c:cs)
808     = uppBeside (uppChar other_c) (process ress args cs)
809 \end{code}
810
811 %************************************************************************
812 %*                                                                      *
813 \subsection[a2r-assignments]{Assignments}
814 %*                                                                      *
815 %************************************************************************
816
817 Printing assignments is a little tricky because of type coercion.
818
819 First of all, the kind of the thing being assigned can be gotten from
820 the destination addressing mode.  (It should be the same as the kind
821 of the source addressing mode.)  If the kind of the assignment is of
822 @VoidRep@, then don't generate any code at all.
823
824 \begin{code}
825 pprAssign :: PprStyle -> PrimRep -> CAddrMode -> CAddrMode -> Unpretty
826
827 pprAssign sty VoidRep dest src = uppNil
828
829 #if 0
830 pprAssign sty kind dest src
831  | (kind /= getAmodeRep dest) || (kind /= getAmodeRep src)
832  = uppCat [uppStr "Bad kind:", pprPrimKind sty kind,
833         pprPrimKind sty (getAmodeRep dest), pprAmode sty dest,
834         pprPrimKind sty (getAmodeRep src),  pprAmode sty src]
835 #endif
836 \end{code}
837
838 Special treatment for floats and doubles, to avoid unwanted conversions.
839
840 \begin{code}
841 pprAssign sty FloatRep dest@(CVal reg_rel _) src
842   = uppBesides [ uppStr "ASSIGN_FLT(", ppr_amode sty (CAddr reg_rel), uppComma, pprAmode sty src, pp_paren_semi ]
843
844 pprAssign sty DoubleRep dest@(CVal reg_rel _) src
845   = uppBesides [ uppStr "ASSIGN_DBL(", ppr_amode sty (CAddr reg_rel), uppComma, pprAmode sty src, pp_paren_semi ]
846 \end{code}
847
848 Lastly, the question is: will the C compiler think the types of the
849 two sides of the assignment match?
850
851         We assume that the types will match
852         if neither side is a @CVal@ addressing mode for any register
853         which can point into the heap or B stack.
854
855 Why?  Because the heap and B stack are used to store miscellaneous things,
856 whereas the A stack, temporaries, registers, etc., are only used for things
857 of fixed type.
858
859 \begin{code}
860 pprAssign sty kind (CReg (VanillaReg _ dest)) (CReg (VanillaReg _ src))
861   = uppBesides [ pprVanillaReg dest, uppEquals,
862                 pprVanillaReg src, uppSemi ]
863
864 pprAssign sty kind dest src
865   | mixedTypeLocn dest
866     -- Add in a cast to StgWord (a.k.a. W_) iff the destination is mixed
867   = uppBesides [ ppr_amode sty dest, uppEquals,
868                 uppStr "(W_)(", -- Here is the cast
869                 ppr_amode sty src, pp_paren_semi ]
870
871 pprAssign sty kind dest src
872   | mixedPtrLocn dest && getAmodeRep src /= PtrRep
873     -- Add in a cast to StgPtr (a.k.a. P_) iff the destination is mixed
874   = uppBesides [ ppr_amode sty dest, uppEquals,
875                 uppStr "(P_)(", -- Here is the cast
876                 ppr_amode sty src, pp_paren_semi ]
877
878 pprAssign sty ByteArrayRep dest src
879   | mixedPtrLocn src
880     -- Add in a cast to StgPtr (a.k.a. B_) iff the source is mixed
881   = uppBesides [ ppr_amode sty dest, uppEquals,
882                 uppStr "(B_)(", -- Here is the cast
883                 ppr_amode sty src, pp_paren_semi ]
884
885 pprAssign sty kind other_dest src
886   = uppBesides [ ppr_amode sty other_dest, uppEquals,
887                 pprAmode  sty src, uppSemi ]
888 \end{code}
889
890
891 %************************************************************************
892 %*                                                                      *
893 \subsection[a2r-CAddrModes]{Addressing modes}
894 %*                                                                      *
895 %************************************************************************
896
897 @pprAmode@ is used to print r-values (which may need casts), whereas
898 @ppr_amode@ is used for l-values {\em and} as a help function for
899 @pprAmode@.
900
901 \begin{code}
902 pprAmode, ppr_amode :: PprStyle -> CAddrMode -> Unpretty
903 \end{code}
904
905 For reasons discussed above under assignments, @CVal@ modes need
906 to be treated carefully.  First come special cases for floats and doubles,
907 similar to those in @pprAssign@:
908
909 (NB: @PK_FLT@ and @PK_DBL@ require the {\em address} of the value in
910 question.)
911
912 \begin{code}
913 pprAmode sty (CVal reg_rel FloatRep)
914   = uppBesides [ uppStr "PK_FLT(", ppr_amode sty (CAddr reg_rel), uppRparen ]
915 pprAmode sty (CVal reg_rel DoubleRep)
916   = uppBesides [ uppStr "PK_DBL(", ppr_amode sty (CAddr reg_rel), uppRparen ]
917 \end{code}
918
919 Next comes the case where there is some other cast need, and the
920 no-cast case:
921
922 \begin{code}
923 pprAmode sty amode
924   | mixedTypeLocn amode
925   = uppParens (uppBesides [ pprPrimKind sty (getAmodeRep amode), uppStr ")(",
926                 ppr_amode sty amode ])
927   | otherwise   -- No cast needed
928   = ppr_amode sty amode
929 \end{code}
930
931 Now the rest of the cases for ``workhorse'' @ppr_amode@:
932
933 \begin{code}
934 ppr_amode sty (CVal reg_rel _)
935   = case (pprRegRelative sty False{-no sign wanted-} reg_rel) of
936         (pp_reg, Nothing)     -> uppBeside  (uppChar '*') pp_reg
937         (pp_reg, Just offset) -> uppBesides [ pp_reg, uppBracket offset ]
938
939 ppr_amode sty (CAddr reg_rel)
940   = case (pprRegRelative sty True{-sign wanted-} reg_rel) of
941         (pp_reg, Nothing)     -> pp_reg
942         (pp_reg, Just offset) -> uppBeside pp_reg offset
943
944 ppr_amode sty (CReg magic_id) = pprMagicId sty magic_id
945
946 ppr_amode sty (CTemp uniq kind) = prettyToUn (pprUnique uniq)
947
948 ppr_amode sty (CLbl label kind) = pprCLabel sty label
949
950 ppr_amode sty (CUnVecLbl direct vectored)
951   = uppBesides [uppStr "(StgRetAddr) UNVEC(", pprCLabel sty direct, uppComma,
952                pprCLabel sty vectored, uppRparen]
953
954 ppr_amode sty (CCharLike char)
955   = uppBesides [uppStr "CHARLIKE_CLOSURE(", pprAmode sty char, uppRparen ]
956 ppr_amode sty (CIntLike int)
957   = uppBesides [uppStr "INTLIKE_CLOSURE(", pprAmode sty int, uppRparen ]
958
959 ppr_amode sty (CString str) = uppBesides [uppChar '"', uppStr (stringToC (_UNPK_ str)), uppChar '"']
960   -- ToDo: are these *used* for anything?
961
962 ppr_amode sty (CLit lit) = pprBasicLit sty lit
963
964 ppr_amode sty (CLitLit str _) = uppPStr str
965
966 ppr_amode sty (COffset off) = pprHeapOffset sty off
967
968 ppr_amode sty (CCode abs_C)
969   = uppAboves [ uppStr "{ -- CCode", uppNest 8 (pprAbsC sty abs_C (costs abs_C)), uppChar '}' ]
970
971 ppr_amode sty (CLabelledCode label abs_C)
972   = uppAboves [ uppBesides [pprCLabel sty label, uppStr " = { -- CLabelledCode"],
973                uppNest 8 (pprAbsC sty abs_C (costs abs_C)), uppChar '}' ]
974
975 ppr_amode sty (CJoinPoint _ _)
976   = panic "ppr_amode: CJoinPoint"
977
978 ppr_amode sty (CTableEntry base index kind)
979   = uppBesides [uppStr "((", pprPrimKind sty kind, uppStr " *)(",
980                ppr_amode sty base, uppStr "))[(I_)(", ppr_amode sty index,
981                uppStr ")]"]
982
983 ppr_amode sty (CMacroExpr pk macro as)
984   = uppBesides [uppLparen, pprPrimKind sty pk, uppStr ")(", uppStr (show macro), uppLparen,
985                uppIntersperse uppComma (map (pprAmode sty) as), uppStr "))"]
986
987 ppr_amode sty (CCostCentre cc print_as_string)
988   = uppCostCentre sty print_as_string cc
989 \end{code}
990
991 %************************************************************************
992 %*                                                                      *
993 \subsection[a2r-MagicIds]{Magic ids}
994 %*                                                                      *
995 %************************************************************************
996
997 @pprRegRelative@ returns a pair of the @Unpretty@ for the register
998 (some casting may be required), and a @Maybe Unpretty@ for the offset
999 (zero offset gives a @Nothing@).
1000
1001 \begin{code}
1002 addPlusSign :: Bool -> Unpretty -> Unpretty
1003 addPlusSign False p = p
1004 addPlusSign True  p = uppBeside (uppChar '+') p
1005
1006 pprSignedInt :: Bool -> Int -> Maybe Unpretty   -- Nothing => 0
1007 pprSignedInt sign_wanted n
1008  = if n == 0 then Nothing else
1009    if n > 0  then Just (addPlusSign sign_wanted (uppInt n))
1010    else           Just (uppInt n)
1011
1012 pprRegRelative :: PprStyle
1013                -> Bool          -- True <=> Print leading plus sign (if +ve)
1014                -> RegRelative
1015                -> (Unpretty, Maybe Unpretty)
1016
1017 pprRegRelative sty sign_wanted (SpARel spA off)
1018   = (pprMagicId sty SpA, pprSignedInt sign_wanted (spARelToInt spA off))
1019
1020 pprRegRelative sty sign_wanted (SpBRel spB off)
1021   = (pprMagicId sty SpB, pprSignedInt sign_wanted (spBRelToInt spB off))
1022
1023 pprRegRelative sty sign_wanted r@(HpRel hp off)
1024   = let to_print = hp `subOff` off
1025         pp_Hp    = pprMagicId sty Hp
1026     in
1027     if isZeroOff to_print then
1028         (pp_Hp, Nothing)
1029     else
1030         (pp_Hp, Just (uppBeside (uppChar '-') (pprHeapOffset sty to_print)))
1031                                 -- No parens needed because pprHeapOffset
1032                                 -- does them when necessary
1033
1034 pprRegRelative sty sign_wanted (NodeRel off)
1035   = let pp_Node = pprMagicId sty node
1036     in
1037     if isZeroOff off then
1038         (pp_Node, Nothing)
1039     else
1040         (pp_Node, Just (addPlusSign sign_wanted (pprHeapOffset sty off)))
1041
1042 \end{code}
1043
1044 @pprMagicId@ just prints the register name.  @VanillaReg@ registers are
1045 represented by a discriminated union (@StgUnion@), so we use the @PrimRep@
1046 to select the union tag.
1047
1048 \begin{code}
1049 pprMagicId :: PprStyle -> MagicId -> Unpretty
1050
1051 pprMagicId sty BaseReg              = uppPStr SLIT("BaseReg")
1052 pprMagicId sty StkOReg              = uppPStr SLIT("StkOReg")
1053 pprMagicId sty (VanillaReg pk n)
1054                                     = uppBesides [ pprVanillaReg n, uppChar '.',
1055                                                   pprUnionTag pk ]
1056 pprMagicId sty (FloatReg  n)        = uppBeside (uppPStr SLIT("FltReg")) (uppInt IBOX(n))
1057 pprMagicId sty (DoubleReg n)        = uppBeside (uppPStr SLIT("DblReg")) (uppInt IBOX(n))
1058 pprMagicId sty TagReg               = uppPStr SLIT("TagReg")
1059 pprMagicId sty RetReg               = uppPStr SLIT("RetReg")
1060 pprMagicId sty SpA                  = uppPStr SLIT("SpA")
1061 pprMagicId sty SuA                  = uppPStr SLIT("SuA")
1062 pprMagicId sty SpB                  = uppPStr SLIT("SpB")
1063 pprMagicId sty SuB                  = uppPStr SLIT("SuB")
1064 pprMagicId sty Hp                   = uppPStr SLIT("Hp")
1065 pprMagicId sty HpLim                = uppPStr SLIT("HpLim")
1066 pprMagicId sty LivenessReg          = uppPStr SLIT("LivenessReg")
1067 pprMagicId sty StdUpdRetVecReg      = uppPStr SLIT("StdUpdRetVecReg")
1068 pprMagicId sty StkStubReg           = uppPStr SLIT("StkStubReg")
1069 pprMagicId sty CurCostCentre        = uppPStr SLIT("CCC")
1070 pprMagicId sty VoidReg              = panic "pprMagicId:VoidReg!"
1071
1072 pprVanillaReg :: FAST_INT -> Unpretty
1073
1074 pprVanillaReg n = uppBeside (uppChar 'R') (uppInt IBOX(n))
1075
1076 pprUnionTag :: PrimRep -> Unpretty
1077
1078 pprUnionTag PtrRep              = uppChar 'p'
1079 pprUnionTag CodePtrRep          = uppPStr SLIT("fp")
1080 pprUnionTag DataPtrRep          = uppChar 'd'
1081 pprUnionTag RetRep              = uppChar 'r'
1082 pprUnionTag CostCentreRep       = panic "pprUnionTag:CostCentre?"
1083
1084 pprUnionTag CharRep             = uppChar 'c'
1085 pprUnionTag IntRep              = uppChar 'i'
1086 pprUnionTag WordRep             = uppChar 'w'
1087 pprUnionTag AddrRep             = uppChar 'v'
1088 pprUnionTag FloatRep            = uppChar 'f'
1089 pprUnionTag DoubleRep           = panic "pprUnionTag:Double?"
1090
1091 pprUnionTag StablePtrRep        = uppChar 'i'
1092 pprUnionTag MallocPtrRep        = uppChar 'p'
1093
1094 pprUnionTag ArrayRep            = uppChar 'p'
1095 pprUnionTag ByteArrayRep        = uppChar 'b'
1096
1097 pprUnionTag _                   = panic "pprUnionTag:Odd kind"
1098 \end{code}
1099
1100
1101 Find and print local and external declarations for a list of
1102 Abstract~C statements.
1103 \begin{code}
1104 pprTempAndExternDecls :: AbstractC -> (Unpretty{-temps-}, Unpretty{-externs-})
1105 pprTempAndExternDecls AbsCNop = (uppNil, uppNil)
1106
1107 pprTempAndExternDecls (AbsCStmts stmt1 stmt2)
1108   = initTE (ppr_decls_AbsC stmt1        `thenTE` \ (t_p1, e_p1) ->
1109             ppr_decls_AbsC stmt2        `thenTE` \ (t_p2, e_p2) ->
1110             case (catMaybes [t_p1, t_p2])        of { real_temps ->
1111             case (catMaybes [e_p1, e_p2])        of { real_exts ->
1112             returnTE (uppAboves real_temps, uppAboves real_exts) }}
1113            )
1114
1115 pprTempAndExternDecls other_stmt
1116   = initTE (ppr_decls_AbsC other_stmt `thenTE` \ (maybe_t, maybe_e) ->
1117             returnTE (
1118                 case maybe_t of
1119                   Nothing -> uppNil
1120                   Just pp -> pp,
1121
1122                 case maybe_e of
1123                   Nothing -> uppNil
1124                   Just pp -> pp )
1125            )
1126
1127 pprBasicLit :: PprStyle -> Literal -> Unpretty
1128 pprPrimKind :: PprStyle -> PrimRep -> Unpretty
1129
1130 pprBasicLit  sty lit = uppStr (showLiteral  sty lit)
1131 pprPrimKind  sty k   = uppStr (showPrimRep k)
1132 \end{code}
1133
1134
1135 %************************************************************************
1136 %*                                                                      *
1137 \subsection[a2r-monad]{Monadery}
1138 %*                                                                      *
1139 %************************************************************************
1140
1141 We need some monadery to keep track of temps and externs we have already
1142 printed.  This info must be threaded right through the Abstract~C, so
1143 it's most convenient to hide it in this monad.
1144
1145 WDP 95/02: Switched from \tr{([Unique], [CLabel])} to
1146 \tr{(UniqSet, CLabelSet)}.  Allegedly for efficiency.
1147
1148 \begin{code}
1149 type CLabelSet = FiniteMap CLabel (){-any type will do-}
1150 emptyCLabelSet = emptyFM
1151 x `elementOfCLabelSet` labs
1152   = case (lookupFM labs x) of { Just _ -> True; Nothing -> False }
1153 addToCLabelSet set x = addToFM set x ()
1154
1155 type TEenv = (UniqSet Unique, CLabelSet)
1156
1157 type TeM result =  TEenv -> (TEenv, result)
1158
1159 initTE :: TeM a -> a
1160 initTE sa
1161   = case sa (emptyUniqSet, emptyCLabelSet) of { (_, result) ->
1162     result }
1163
1164 {-# INLINE thenTE #-}
1165 {-# INLINE returnTE #-}
1166
1167 thenTE :: TeM a -> (a -> TeM b) -> TeM b
1168 thenTE a b u
1169   = case a u        of { (u_1, result_of_a) ->
1170     b result_of_a u_1 }
1171
1172 mapTE :: (a -> TeM b) -> [a] -> TeM [b]
1173 mapTE f []     = returnTE []
1174 mapTE f (x:xs)
1175   = f x         `thenTE` \ r  ->
1176     mapTE f xs  `thenTE` \ rs ->
1177     returnTE (r : rs)
1178
1179 returnTE :: a -> TeM a
1180 returnTE result env = (env, result)
1181
1182 -- these next two check whether the thing is already
1183 -- recorded, and THEN THEY RECORD IT
1184 -- (subsequent calls will return False for the same uniq/label)
1185
1186 tempSeenTE :: Unique -> TeM Bool
1187 tempSeenTE uniq env@(seen_uniqs, seen_labels)
1188   = if (uniq `elementOfUniqSet` seen_uniqs)
1189     then (env, True)
1190     else ((addOneToUniqSet seen_uniqs uniq,
1191           seen_labels),
1192           False)
1193
1194 labelSeenTE :: CLabel -> TeM Bool
1195 labelSeenTE label env@(seen_uniqs, seen_labels)
1196   = if (label `elementOfCLabelSet` seen_labels)
1197     then (env, True)
1198     else ((seen_uniqs,
1199           addToCLabelSet seen_labels label),
1200           False)
1201 \end{code}
1202
1203 \begin{code}
1204 pprTempDecl :: Unique -> PrimRep -> Unpretty
1205 pprTempDecl uniq kind
1206   = uppBesides [ pprPrimKind PprDebug kind, uppSP, prettyToUn (pprUnique uniq), uppSemi ]
1207
1208 pprExternDecl :: CLabel -> PrimRep -> Unpretty
1209
1210 pprExternDecl clabel kind
1211   = if not (needsCDecl clabel) then
1212         uppNil -- do not print anything for "known external" things (e.g., < PreludeCore)
1213     else
1214         case (
1215             case kind of
1216               CodePtrRep -> ppLocalnessMacro True{-function-} clabel
1217               _          -> ppLocalnessMacro False{-data-}    clabel
1218         ) of { pp_macro_str ->
1219
1220         uppBesides [ pp_macro_str, uppLparen, pprCLabel PprForC clabel, pp_paren_semi ]
1221         }
1222 \end{code}
1223
1224 \begin{code}
1225 ppr_decls_AbsC :: AbstractC -> TeM (Maybe Unpretty{-temps-}, Maybe Unpretty{-externs-})
1226
1227 ppr_decls_AbsC AbsCNop          = returnTE (Nothing, Nothing)
1228
1229 ppr_decls_AbsC (AbsCStmts stmts_1 stmts_2)
1230   = ppr_decls_AbsC stmts_1  `thenTE` \ p1 ->
1231     ppr_decls_AbsC stmts_2  `thenTE` \ p2 ->
1232     returnTE (maybe_uppAboves [p1, p2])
1233
1234 ppr_decls_AbsC (CClosureUpdInfo info)
1235   = ppr_decls_AbsC info
1236
1237 ppr_decls_AbsC (CSplitMarker) = returnTE (Nothing, Nothing)
1238
1239 ppr_decls_AbsC (CAssign dest source)
1240   = ppr_decls_Amode dest    `thenTE` \ p1 ->
1241     ppr_decls_Amode source  `thenTE` \ p2 ->
1242     returnTE (maybe_uppAboves [p1, p2])
1243
1244 ppr_decls_AbsC (CJump target) = ppr_decls_Amode target
1245
1246 ppr_decls_AbsC (CFallThrough target) = ppr_decls_Amode target
1247
1248 ppr_decls_AbsC (CReturn target _) = ppr_decls_Amode target
1249
1250 ppr_decls_AbsC (CSwitch discrim alts deflt)
1251   = ppr_decls_Amode discrim     `thenTE` \ pdisc ->
1252     mapTE ppr_alt_stuff alts    `thenTE` \ palts  ->
1253     ppr_decls_AbsC deflt        `thenTE` \ pdeflt ->
1254     returnTE (maybe_uppAboves (pdisc:pdeflt:palts))
1255   where
1256     ppr_alt_stuff (_, absC) = ppr_decls_AbsC absC
1257
1258 ppr_decls_AbsC (CCodeBlock label absC)
1259   = ppr_decls_AbsC absC
1260
1261 ppr_decls_AbsC (CInitHdr cl_info reg_rel cost_centre inplace_upd)
1262         -- ToDo: strictly speaking, should chk "cost_centre" amode
1263   = labelSeenTE info_lbl     `thenTE` \  label_seen ->
1264     returnTE (Nothing,
1265               if label_seen then
1266                   Nothing
1267               else
1268                   Just (pprExternDecl info_lbl PtrRep))
1269   where
1270     info_lbl = infoTableLabelFromCI cl_info
1271
1272 ppr_decls_AbsC (COpStmt results _ args _ _) = ppr_decls_Amodes (results ++ args)
1273 ppr_decls_AbsC (CSimultaneous abc)          = ppr_decls_AbsC abc
1274
1275 ppr_decls_AbsC (CMacroStmt          _ amodes)   = ppr_decls_Amodes amodes
1276
1277 ppr_decls_AbsC (CCallProfCtrMacro   _ amodes)   = ppr_decls_Amodes [] -- *****!!!
1278   -- you get some nasty re-decls of stdio.h if you compile
1279   -- the prelude while looking inside those amodes;
1280   -- no real reason to, anyway.
1281 ppr_decls_AbsC (CCallProfCCMacro    _ amodes)   = ppr_decls_Amodes amodes
1282
1283 ppr_decls_AbsC (CStaticClosure closure_lbl closure_info cost_centre amodes)
1284         -- ToDo: strictly speaking, should chk "cost_centre" amode
1285   = ppr_decls_Amodes amodes
1286
1287 ppr_decls_AbsC (CClosureInfoAndCode cl_info slow maybe_fast upd_lbl _ _)
1288   = ppr_decls_Amodes [entry_lbl, upd_lbl]       `thenTE` \ p1 ->
1289     ppr_decls_AbsC slow                         `thenTE` \ p2 ->
1290     (case maybe_fast of
1291         Nothing   -> returnTE (Nothing, Nothing)
1292         Just fast -> ppr_decls_AbsC fast)       `thenTE` \ p3 ->
1293     returnTE (maybe_uppAboves [p1, p2, p3])
1294   where
1295     entry_lbl = CLbl slow_lbl CodePtrRep
1296     slow_lbl    = case (nonemptyAbsC slow) of
1297                     Nothing -> mkErrorStdEntryLabel
1298                     Just _  -> entryLabelFromCI cl_info
1299
1300 ppr_decls_AbsC (CRetVector label maybe_amodes absC)
1301   = ppr_decls_Amodes (catMaybes maybe_amodes)   `thenTE` \ p1 ->
1302     ppr_decls_AbsC   absC                       `thenTE` \ p2 ->
1303     returnTE (maybe_uppAboves [p1, p2])
1304
1305 ppr_decls_AbsC (CRetUnVector   _ amode)  = ppr_decls_Amode amode
1306 ppr_decls_AbsC (CFlatRetVector _ amodes) = ppr_decls_Amodes amodes
1307 \end{code}
1308
1309 \begin{code}
1310 ppr_decls_Amode :: CAddrMode -> TeM (Maybe Unpretty, Maybe Unpretty)
1311 ppr_decls_Amode (CVal _ _)      = returnTE (Nothing, Nothing)
1312 ppr_decls_Amode (CAddr _)       = returnTE (Nothing, Nothing)
1313 ppr_decls_Amode (CReg _)        = returnTE (Nothing, Nothing)
1314 ppr_decls_Amode (CString _)     = returnTE (Nothing, Nothing)
1315 ppr_decls_Amode (CLit _)        = returnTE (Nothing, Nothing)
1316 ppr_decls_Amode (CLitLit _ _)   = returnTE (Nothing, Nothing)
1317 ppr_decls_Amode (COffset _)     = returnTE (Nothing, Nothing)
1318
1319 -- CIntLike must be a literal -- no decls
1320 ppr_decls_Amode (CIntLike int)  = returnTE (Nothing, Nothing)
1321
1322 -- CCharLike may have be arbitrary value -- may have decls
1323 ppr_decls_Amode (CCharLike char)
1324   = ppr_decls_Amode char
1325
1326 -- now, the only place where we actually print temps/externs...
1327 ppr_decls_Amode (CTemp uniq kind)
1328   = case kind of
1329       VoidRep -> returnTE (Nothing, Nothing)
1330       other ->
1331         tempSeenTE uniq `thenTE` \ temp_seen ->
1332         returnTE
1333           (if temp_seen then Nothing else Just (pprTempDecl uniq kind), Nothing)
1334
1335 ppr_decls_Amode (CLbl label VoidRep)
1336   = returnTE (Nothing, Nothing)
1337
1338 ppr_decls_Amode (CLbl label kind)
1339   = labelSeenTE label `thenTE` \ label_seen ->
1340     returnTE (Nothing,
1341               if label_seen then Nothing else Just (pprExternDecl label kind))
1342
1343 {- WRONG:
1344 ppr_decls_Amode (CUnVecLbl direct vectored)
1345   = labelSeenTE direct   `thenTE` \ dlbl_seen ->
1346     labelSeenTE vectored `thenTE` \ vlbl_seen ->
1347     let
1348         ddcl = if dlbl_seen then uppNil else pprExternDecl direct CodePtrRep
1349         vdcl = if vlbl_seen then uppNil else pprExternDecl vectored DataPtrRep
1350     in
1351     returnTE (Nothing,
1352                 if (dlbl_seen || not (needsCDecl direct)) &&
1353                    (vlbl_seen || not (needsCDecl vectored)) then Nothing
1354                 else Just (uppBesides [uppStr "UNVEC(", ddcl, uppComma, vdcl, uppRparen]))
1355 -}
1356
1357 ppr_decls_Amode (CUnVecLbl direct vectored)
1358   = -- We don't mark either label as "seen", because
1359     -- we don't know which one will be used and which one tossed
1360     -- by the C macro...
1361     --labelSeenTE direct   `thenTE` \ dlbl_seen ->
1362     --labelSeenTE vectored `thenTE` \ vlbl_seen ->
1363     let
1364         ddcl = {-if dlbl_seen then uppNil else-} pprExternDecl direct CodePtrRep
1365         vdcl = {-if vlbl_seen then uppNil else-} pprExternDecl vectored DataPtrRep
1366     in
1367     returnTE (Nothing,
1368                 if ({-dlbl_seen ||-} not (needsCDecl direct)) &&
1369                    ({-vlbl_seen ||-} not (needsCDecl vectored)) then Nothing
1370                 else Just (uppBesides [uppStr "UNVEC(", ddcl, uppComma, vdcl, uppRparen]))
1371
1372 ppr_decls_Amode (CTableEntry base index _)
1373   = ppr_decls_Amode base    `thenTE` \ p1 ->
1374     ppr_decls_Amode index   `thenTE` \ p2 ->
1375     returnTE (maybe_uppAboves [p1, p2])
1376
1377 ppr_decls_Amode (CMacroExpr _ _ amodes)
1378   = ppr_decls_Amodes amodes
1379
1380 ppr_decls_Amode other = returnTE (Nothing, Nothing)
1381
1382
1383 maybe_uppAboves :: [(Maybe Unpretty, Maybe Unpretty)] -> (Maybe Unpretty, Maybe Unpretty)
1384 maybe_uppAboves ps
1385   = case (unzip ps)     of { (ts, es) ->
1386     case (catMaybes ts) of { real_ts  ->
1387     case (catMaybes es) of { real_es  ->
1388     (if (null real_ts) then Nothing else Just (uppAboves real_ts),
1389      if (null real_es) then Nothing else Just (uppAboves real_es))
1390     } } }
1391 \end{code}
1392
1393 \begin{code}
1394 ppr_decls_Amodes :: [CAddrMode] -> TeM (Maybe Unpretty, Maybe Unpretty)
1395 ppr_decls_Amodes amodes
1396   = mapTE ppr_decls_Amode amodes `thenTE` \ ps ->
1397     returnTE ( maybe_uppAboves ps )
1398 \end{code}