58cf18f1091d0c2c1b4f1875ea2c90da808b9ae8
[ghc-hetmet.git] / ghc / compiler / absCSyn / PprAbsC.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
3 %
4 %************************************************************************
5 %*                                                                      *
6 \section[PprAbsC]{Pretty-printing Abstract~C}
7 %*                                                                      *
8 %************************************************************************
9
10 \begin{code}
11 module PprAbsC (
12         writeRealC,
13         dumpRealC,
14         pprAmode,
15         pprMagicId
16     ) where
17
18 #include "HsVersions.h"
19
20 import IO       ( Handle )
21
22 import PrimRep 
23 import AbsCSyn
24 import ClosureInfo
25 import AbsCUtils        ( getAmodeRep, nonemptyAbsC,
26                           mixedPtrLocn, mixedTypeLocn
27                         )
28
29 import ForeignCall      ( CCallSpec(..), CCallTarget(..), playSafe,
30                           playThreadSafe, ccallConvAttribute )
31 import CLabel           ( externallyVisibleCLabel,
32                           needsCDecl, pprCLabel,
33                           mkReturnInfoLabel, mkReturnPtLabel, mkClosureTblLabel,
34                           mkClosureLabel, mkErrorStdEntryLabel,
35                           CLabel, CLabelType(..), labelType, labelDynamic
36                         )
37
38 import CmdLineOpts      ( opt_SccProfilingOn, opt_GranMacros )
39 import CostCentre       ( pprCostCentreDecl, pprCostCentreStackDecl )
40
41 import Costs            ( costs, addrModeCosts, CostRes(..), Side(..) )
42 import CStrings         ( pprStringInCStyle, pprCLabelString )
43 import FiniteMap        ( addToFM, emptyFM, lookupFM, FiniteMap )
44 import Literal          ( Literal(..) )
45 import TyCon            ( tyConDataCons )
46 import Name             ( NamedThing(..) )
47 import DataCon          ( dataConWrapId )
48 import Maybes           ( maybeToBool, catMaybes )
49 import PrimOp           ( primOpNeedsWrapper )
50 import MachOp           ( MachOp(..) )
51 import ForeignCall      ( ForeignCall(..) )
52 import PrimRep          ( isFloatingRep, PrimRep(..), getPrimRepSize )
53 import SMRep            ( pprSMRep )
54 import Unique           ( pprUnique, Unique{-instance NamedThing-} )
55 import UniqSet          ( emptyUniqSet, elementOfUniqSet,
56                           addOneToUniqSet, UniqSet
57                         )
58 import StgSyn           ( StgOp(..) )
59 import BitSet           ( BitSet, intBS )
60 import Outputable
61 import FastString
62 import Util             ( lengthExceeds, listLengthCmp )
63
64 #if __GLASGOW_HASKELL__ >= 504
65 import Data.Array.ST
66 #endif
67
68 import GLAEXTS
69 import MONAD_ST
70
71 infixr 9 `thenTE`
72 \end{code}
73
74 For spitting out the costs of an abstract~C expression, @writeRealC@
75 now not only prints the C~code of the @absC@ arg but also adds a macro
76 call to a cost evaluation function @GRAN_EXEC@. For that,
77 @pprAbsC@ has a new ``costs'' argument.  %% HWL
78
79 \begin{code}
80 {-
81 writeRealC :: Handle -> AbstractC -> IO ()
82 writeRealC handle absC
83      -- avoid holding on to the whole of absC in the !Gransim case.
84      if opt_GranMacros
85         then printForCFast fp (pprAbsC absC (costs absC))
86         else printForCFast fp (pprAbsC absC (panic "costs"))
87              --printForC handle (pprAbsC absC (panic "costs"))
88 dumpRealC :: AbstractC -> SDoc
89 dumpRealC absC = pprAbsC absC (costs absC)
90 -}
91
92 writeRealC :: Handle -> AbstractC -> IO ()
93 --writeRealC handle absC = 
94 -- _scc_ "writeRealC" 
95 -- printDoc LeftMode handle (pprAbsC absC (costs absC))
96
97 writeRealC handle absC
98  | opt_GranMacros = _scc_ "writeRealC" printForC handle $ 
99                                        pprCode CStyle (pprAbsC absC (costs absC))
100  | otherwise      = _scc_ "writeRealC" printForC handle $
101                                        pprCode CStyle (pprAbsC absC (panic "costs"))
102
103 dumpRealC :: AbstractC -> SDoc
104 dumpRealC absC
105  | opt_GranMacros = pprCode CStyle (pprAbsC absC (costs absC))
106  | otherwise      = pprCode CStyle (pprAbsC absC (panic "costs"))
107
108 \end{code}
109
110 This emits the macro,  which is used in GrAnSim  to compute the total costs
111 from a cost 5 tuple. %%  HWL
112
113 \begin{code}
114 emitMacro :: CostRes -> SDoc
115
116 emitMacro _ | not opt_GranMacros = empty
117
118 emitMacro (Cost (i,b,l,s,f))
119   = hcat [ ptext SLIT("GRAN_EXEC"), char '(',
120                           int i, comma, int b, comma, int l, comma,
121                           int s, comma, int f, pp_paren_semi ]
122
123 pp_paren_semi = text ");"
124 \end{code}
125
126 New type: Now pprAbsC also takes the costs for evaluating the Abstract C
127 code as an argument (that's needed when spitting out the GRAN_EXEC macro
128 which must be done before the return i.e. inside absC code)   HWL
129
130 \begin{code}
131 pprAbsC :: AbstractC -> CostRes -> SDoc
132 pprAbsC AbsCNop _ = empty
133 pprAbsC (AbsCStmts s1 s2) c = ($$) (pprAbsC s1 c) (pprAbsC s2 c)
134
135 pprAbsC (CAssign dest src) _ = pprAssign (getAmodeRep dest) dest src
136
137 pprAbsC (CJump target) c
138   = ($$) (hcat [emitMacro c {-WDP:, text "/* <--++  CJump */"-} ])
139              (hcat [ text jmp_lit, pprAmode target, pp_paren_semi ])
140
141 pprAbsC (CFallThrough target) c
142   = ($$) (hcat [emitMacro c {-WDP:, text "/* <--++  CFallThrough */"-} ])
143              (hcat [ text jmp_lit, pprAmode target, pp_paren_semi ])
144
145 -- --------------------------------------------------------------------------
146 -- Spit out GRAN_EXEC macro immediately before the return                 HWL
147
148 pprAbsC (CReturn am return_info)  c
149   = ($$) (hcat [emitMacro c {-WDP:, text "/* <----  CReturn */"-} ])
150              (hcat [text jmp_lit, target, pp_paren_semi ])
151   where
152    target = case return_info of
153         DirectReturn -> hcat [ptext SLIT("ENTRY_CODE"), lparen,
154                               pprAmode am, rparen]
155         DynamicVectoredReturn am' -> mk_vector (pprAmode am')
156         StaticVectoredReturn n -> mk_vector (int n)     -- Always positive
157    mk_vector x = hcat [ptext SLIT("RET_VEC"), char '(', pprAmode am, comma,
158                        x, rparen ]
159
160 pprAbsC (CSplitMarker) _ = ptext SLIT("__STG_SPLIT_MARKER")
161
162 -- we optimise various degenerate cases of CSwitches.
163
164 -- --------------------------------------------------------------------------
165 -- Assume: CSwitch is also end of basic block
166 --         costs function yields nullCosts for whole switch
167 --         ==> inherited costs c are those of basic block up to switch
168 --         ==> inherit c + costs for the corresponding branch
169 --                                                                       HWL
170 -- --------------------------------------------------------------------------
171
172 pprAbsC (CSwitch discrim [] deflt) c
173   = pprAbsC deflt (c + costs deflt)
174     -- Empty alternative list => no costs for discrim as nothing cond. here HWL
175
176 pprAbsC (CSwitch discrim [(tag,alt_code)] deflt) c -- only one alt
177   = case (nonemptyAbsC deflt) of
178       Nothing ->                -- one alt and no default
179                  pprAbsC alt_code (c + costs alt_code)
180                  -- Nothing conditional in here either  HWL
181
182       Just dc ->                -- make it an "if"
183                  do_if_stmt discrim tag alt_code dc c
184
185 -- What problem is the re-ordering trying to solve ?
186 pprAbsC (CSwitch discrim [(tag1@(MachInt i1), alt_code1),
187                           (tag2@(MachInt i2), alt_code2)] deflt) c
188   | empty_deflt && ((i1 == 0 && i2 == 1) || (i1 == 1 && i2 == 0))
189   = if (i1 == 0) then
190         do_if_stmt discrim tag1 alt_code1 alt_code2 c
191     else
192         do_if_stmt discrim tag2 alt_code2 alt_code1 c
193   where
194     empty_deflt = not (maybeToBool (nonemptyAbsC deflt))
195
196 pprAbsC (CSwitch discrim alts deflt) c -- general case
197   | isFloatingRep (getAmodeRep discrim)
198     = pprAbsC (foldr ( \ a -> CSwitch discrim [a]) deflt alts) c
199   | otherwise
200     = vcat [
201         hcat [text "switch (", pp_discrim, text ") {"],
202         nest 2 (vcat (map ppr_alt alts)),
203         (case (nonemptyAbsC deflt) of
204            Nothing -> empty
205            Just dc ->
206             nest 2 (vcat [ptext SLIT("default:"),
207                                   pprAbsC dc (c + switch_head_cost
208                                                     + costs dc),
209                                   ptext SLIT("break;")])),
210         char '}' ]
211   where
212     pp_discrim
213       = pprAmode discrim
214
215     ppr_alt (lit, absC)
216       = vcat [ hcat [ptext SLIT("case "), pprBasicLit lit, char ':'],
217                    nest 2 (($$) (pprAbsC absC (c + switch_head_cost + costs absC))
218                                        (ptext SLIT("break;"))) ]
219
220     -- Costs for addressing header of switch and cond. branching        -- HWL
221     switch_head_cost = addrModeCosts discrim Rhs + (Cost (0, 1, 0, 0, 0))
222
223 pprAbsC stmt@(COpStmt results (StgFCallOp fcall uniq) args vol_regs) _
224   = pprFCall fcall uniq args results vol_regs
225
226 pprAbsC stmt@(COpStmt results (StgPrimOp op) args vol_regs) _
227   = let
228         non_void_args = grab_non_void_amodes args
229         non_void_results = grab_non_void_amodes results
230         -- if just one result, we print in the obvious "assignment" style;
231         -- if 0 or many results, we emit a macro call, w/ the results
232         -- followed by the arguments.  The macro presumably knows which
233         -- are which :-)
234
235         the_op = ppr_op_call non_void_results non_void_args
236                 -- liveness mask is *in* the non_void_args
237     in
238     if primOpNeedsWrapper op then
239         case (ppr_vol_regs vol_regs) of { (pp_saves, pp_restores) ->
240         vcat [  pp_saves,
241                 the_op,
242                 pp_restores
243              ]
244         }
245     else
246         the_op
247   where
248     ppr_op_call results args
249       = hcat [ ppr op, lparen,
250         hcat (punctuate comma (map ppr_op_result results)),
251         if null results || null args then empty else comma,
252         hcat (punctuate comma (map pprAmode args)),
253         pp_paren_semi ]
254
255     ppr_op_result r = ppr_amode r
256       -- primop macros do their own casting of result;
257       -- hence we can toss the provided cast...
258
259 -- NEW CASES FOR EXPANDED PRIMOPS
260
261 pprAbsC stmt@(CMachOpStmt res mop [arg1,arg2] maybe_vols) _
262   = let prefix_fn = mop `elem` [MO_Dbl_Pwr, MO_Flt_Pwr, MO_NatS_MulMayOflo]
263     in
264     case ppr_maybe_vol_regs maybe_vols of {(saves,restores) ->
265     saves $$
266     hcat (
267        [ppr_amode res, equals]
268        ++ (if prefix_fn 
269            then [pprMachOp_for_C mop, parens (pprAmode arg1 <> comma <> pprAmode arg2)]
270            else [pprAmode arg1, pprMachOp_for_C mop, pprAmode arg2])
271        ++ [semi]
272     )
273     $$ restores
274     }
275
276 pprAbsC stmt@(CMachOpStmt res mop [arg1] maybe_vols) _
277   = case ppr_maybe_vol_regs maybe_vols of {(saves,restores) ->
278     saves $$
279     hcat [ppr_amode res, equals, 
280           pprMachOp_for_C mop, parens (pprAmode arg1),
281           semi]
282     $$ restores
283     }
284
285 pprAbsC stmt@(CSequential stuff) c
286   = vcat (map (flip pprAbsC c) stuff)
287
288 -- end of NEW CASES FOR EXPANDED PRIMOPS
289
290 pprAbsC stmt@(CSRT lbl closures) c
291   = case (pprTempAndExternDecls stmt) of { (_, pp_exts) ->
292          pp_exts
293       $$ ptext SLIT("SRT") <> lparen <> pprCLabel lbl <> rparen
294       $$ nest 2 (hcat (punctuate comma (map pp_closure_lbl closures)))
295          <> ptext SLIT("};")
296   }
297
298 pprAbsC stmt@(CBitmap lbl mask) c
299   = pp_bitmap_switch mask semi $
300     hcat [ ptext SLIT("BITMAP"), lparen,
301            pprCLabel lbl, comma,
302            int (length mask), comma,
303            pp_bitmap mask, rparen ]
304
305 pprAbsC (CSimultaneous abs_c) c
306   = hcat [ptext SLIT("{{"), pprAbsC abs_c c, ptext SLIT("}}")]
307
308 pprAbsC (CCheck macro as code) c
309   = hcat [ptext (cCheckMacroText macro), lparen,
310        hcat (punctuate comma (map ppr_amode as)), comma,
311        pprAbsC code c, pp_paren_semi
312     ]
313 pprAbsC (CMacroStmt macro as) _
314   = hcat [ptext (cStmtMacroText macro), lparen,
315         hcat (punctuate comma (map ppr_amode as)),pp_paren_semi] -- no casting
316 pprAbsC (CCallProfCtrMacro op as) _
317   = hcat [ftext op, lparen,
318         hcat (punctuate comma (map ppr_amode as)),pp_paren_semi]
319 pprAbsC (CCallProfCCMacro op as) _
320   = hcat [ftext op, lparen,
321         hcat (punctuate comma (map ppr_amode as)),pp_paren_semi]
322 pprAbsC stmt@(CCallTypedef is_tdef (CCallSpec op_str cconv _) uniq results args) _
323   =  hsep [ ptext (if is_tdef then SLIT("typedef") else SLIT("extern"))
324           , ccall_res_ty
325           , fun_nm
326           , parens (hsep (punctuate comma ccall_decl_ty_args))
327           ] <> semi
328     where
329     {-
330       In the non-casm case, to ensure that we're entering the given external
331       entry point using the correct calling convention, we have to do the following:
332
333         - When entering via a function pointer (the `dynamic' case) using the specified
334           calling convention, we emit a typedefn declaration attributed with the
335           calling convention to use together with the result and parameter types we're
336           assuming. Coerce the function pointer to this type and go.
337
338         - to enter the function at a given code label, we emit an extern declaration
339           for the label here, stating the calling convention together with result and
340           argument types we're assuming. 
341
342           The C compiler will hopefully use this extern declaration to good effect,
343           reporting any discrepancies between our extern decl and any other that
344           may be in scope.
345     
346           Re: calling convention, notice that gcc (2.8.1 and egcs-1.0.2) will for
347           the external function `foo' use the calling convention of the first `foo'
348           prototype it encounters (nor does it complain about conflicting attribute
349           declarations). The consequence of this is that you cannot override the
350           calling convention of `foo' using an extern declaration (you'd have to use
351           a typedef), but why you would want to do such a thing in the first place
352           is totally beyond me.
353           
354           ToDo: petition the gcc folks to add code to warn about conflicting attribute
355           declarations.
356
357     -}
358
359      fun_nm
360        | is_tdef   = parens (text (ccallConvAttribute cconv) <+> char '*' <> ccall_fun_ty)
361        | otherwise = text (ccallConvAttribute cconv) <+> ccall_fun_ty
362
363      ccall_fun_ty = 
364         case op_str of
365           DynamicTarget  -> ptext SLIT("_ccall_fun_ty") <> ppr uniq
366           StaticTarget x -> pprCLabelString x
367
368      ccall_res_ty = 
369        case non_void_results of
370           []       -> ptext SLIT("void")
371           [amode]  -> ppr (getAmodeRep amode)
372           _        -> panic "pprAbsC{CCallTypedef}: ccall_res_ty"
373
374      ccall_decl_ty_args 
375        | is_tdef   = tail ccall_arg_tys
376        | otherwise = ccall_arg_tys
377
378      ccall_arg_tys      = map (ppr . getAmodeRep) non_void_args
379
380       -- the first argument will be the "I/O world" token (a VoidRep)
381       -- all others should be non-void
382      non_void_args =
383         let nvas = init args
384         in ASSERT (all non_void nvas) nvas
385
386       -- there will usually be two results: a (void) state which we
387       -- should ignore and a (possibly void) result.
388      non_void_results =
389         let nvrs = grab_non_void_amodes results
390         in ASSERT (listLengthCmp nvrs 1 /= GT) nvrs
391
392 pprAbsC (CCodeBlock lbl abs_C) _
393   = if not (maybeToBool(nonemptyAbsC abs_C)) then
394         pprTrace "pprAbsC: curious empty code block for" (pprCLabel lbl) empty
395     else
396     case (pprTempAndExternDecls abs_C) of { (pp_temps, pp_exts) ->
397     vcat [
398         empty,
399         pp_exts, 
400         hcat [text (if (externallyVisibleCLabel lbl)
401                           then "FN_("   -- abbreviations to save on output
402                           else "IFN_("),
403                    pprCLabel lbl, text ") {"],
404
405         pp_temps,
406
407         nest 8 (ptext SLIT("FB_")),
408         nest 8 (pprAbsC abs_C (costs abs_C)),
409         nest 8 (ptext SLIT("FE_")),
410         char '}',
411         char ' ' ]
412     }
413
414
415 pprAbsC (CInitHdr cl_info amode cost_centre size) _
416   = hcat [ ptext SLIT("SET_HDR_"), char '(',
417                 ppr_amode amode, comma,
418                 pprCLabelAddr info_lbl, comma,
419                 if_profiling (pprAmode cost_centre), comma,
420                 if_profiling (int size),
421                 pp_paren_semi ]
422   where
423     info_lbl    = infoTableLabelFromCI cl_info
424
425
426 pprAbsC stmt@(CStaticClosure cl_info cost_centre amodes) _
427   = case (pprTempAndExternDecls stmt) of { (_, pp_exts) ->
428     vcat [
429         pp_exts,
430         hcat [
431                 ptext SLIT("SET_STATIC_HDR"), char '(',
432                 pprCLabel closure_lbl,                          comma,
433                 pprCLabel info_lbl,                             comma,
434                 if_profiling (pprAmode cost_centre),            comma,
435                 ppLocalness closure_lbl,                        comma,
436                 ppLocalnessMacro True{-include dyn-} info_lbl,
437                 char ')'
438                 ],
439         nest 2 (ppr_payload amodes),
440         ptext SLIT("};") ]
441     }
442   where
443     closure_lbl = closureLabelFromCI cl_info
444     info_lbl    = infoTableLabelFromCI cl_info
445
446     ppr_payload [] = empty
447     ppr_payload ls = 
448         comma <+> 
449           (braces $ hsep $ punctuate comma $
450            map (text "(L_)" <>) (foldr ppr_item [] ls))
451
452     ppr_item item rest
453       | rep == VoidRep   = rest
454       | rep == FloatRep  = ppr_amode (floatToWord item) : rest
455       | rep == DoubleRep = map ppr_amode (doubleToWords item) ++ rest
456       | otherwise        = ppr_amode item : rest
457       where 
458         rep  = getAmodeRep item
459
460
461 pprAbsC stmt@(CClosureInfoAndCode cl_info slow maybe_fast cl_descr) _
462   = vcat [
463         hcat [
464              ptext SLIT("INFO_TABLE"),
465              ( if is_selector then
466                  ptext SLIT("_SELECTOR")
467                else if is_constr then
468                  ptext SLIT("_CONSTR")
469                else if needs_srt then
470                  ptext SLIT("_SRT")
471                else empty ), char '(',
472
473             pprCLabel info_lbl,                         comma,
474             pprCLabel slow_lbl,                         comma,
475             pp_rest, {- ptrs,nptrs,[srt,]type,-}        comma,
476
477             ppLocalness info_lbl,                          comma,
478             ppLocalnessMacro True{-include dyn-} slow_lbl, comma,
479
480             if_profiling pp_descr, comma,
481             if_profiling pp_type,
482             text ");"
483              ],
484         pp_slow,
485         case maybe_fast of
486             Nothing -> empty
487             Just fast -> let stuff = CCodeBlock fast_lbl fast in
488                          pprAbsC stuff (costs stuff)
489     ]
490   where
491     info_lbl    = infoTableLabelFromCI cl_info
492     fast_lbl    = fastLabelFromCI cl_info
493
494     (slow_lbl, pp_slow)
495       = case (nonemptyAbsC slow) of
496           Nothing -> (mkErrorStdEntryLabel, empty)
497           Just xx -> (entryLabelFromCI cl_info,
498                        let stuff = CCodeBlock slow_lbl xx in
499                        pprAbsC stuff (costs stuff))
500
501     maybe_selector = maybeSelectorInfo cl_info
502     is_selector = maybeToBool maybe_selector
503     (Just select_word_i) = maybe_selector
504
505     maybe_tag = closureSemiTag cl_info
506     is_constr = maybeToBool maybe_tag
507     (Just tag) = maybe_tag
508
509     srt       = closureSRT cl_info
510     needs_srt = case srt of
511                    NoC_SRT -> False
512                    other   -> True
513
514
515     size = closureNonHdrSize cl_info
516
517     ptrs        = closurePtrsSize cl_info
518     nptrs       = size - ptrs
519
520     pp_rest | is_selector      = int select_word_i
521             | otherwise        = hcat [
522                   int ptrs,             comma,
523                   int nptrs,            comma,
524                   if is_constr then
525                         hcat [ int tag, comma ]
526                   else if needs_srt then
527                         pp_srt_info srt
528                   else empty,
529                   type_str ]
530
531     type_str = pprSMRep (closureSMRep cl_info)
532
533     pp_descr = pprStringInCStyle cl_descr
534     pp_type  = pprStringInCStyle (closureTypeDescr cl_info)
535
536 pprAbsC stmt@(CClosureTbl tycon) _
537   = vcat (
538         ptext SLIT("CLOSURE_TBL") <> 
539            lparen <> pprCLabel (mkClosureTblLabel tycon) <> rparen :
540         punctuate comma (
541            map (pp_closure_lbl . mkClosureLabel . getName . dataConWrapId) (tyConDataCons tycon)
542         )
543    ) $$ ptext SLIT("};")
544
545 pprAbsC stmt@(CRetDirect uniq code srt liveness) _
546   = vcat [
547       hcat [
548           ptext SLIT("INFO_TABLE_SRT_BITMAP"), lparen, 
549           pprCLabel info_lbl,           comma,
550           pprCLabel entry_lbl,          comma,
551           pp_liveness liveness,         comma,    -- bitmap
552           pp_srt_info srt,                        -- SRT
553           closure_type,                 comma,    -- closure type
554           ppLocalness info_lbl,         comma,    -- info table storage class
555           ppLocalnessMacro True{-include dyn-} entry_lbl,       comma,    -- entry pt storage class
556           int 0, comma,
557           int 0, text ");"
558       ],
559       pp_code
560     ]
561   where
562      info_lbl     = mkReturnInfoLabel uniq
563      entry_lbl    = mkReturnPtLabel uniq
564
565      pp_code      = let stuff = CCodeBlock entry_lbl code in
566                     pprAbsC stuff (costs stuff)
567
568      closure_type = pp_liveness_switch liveness
569                        (ptext SLIT("RET_SMALL"))
570                        (ptext SLIT("RET_BIG"))
571
572 pprAbsC stmt@(CRetVector lbl amodes srt liveness) _
573   = case (pprTempAndExternDecls stmt) of { (_, pp_exts) ->
574     vcat [
575         pp_exts,
576         hcat [
577           ptext SLIT("VEC_INFO_") <> int size,
578           lparen, 
579           pprCLabel lbl, comma,
580           pp_liveness liveness, comma,  -- bitmap liveness mask
581           pp_srt_info srt,              -- SRT
582           closure_type, comma,
583           ppLocalness lbl, comma
584         ],
585         nest 2 (sep (punctuate comma (map ppr_item amodes))),
586         text ");"
587     ]
588     }
589
590   where
591     ppr_item item = (<>) (text "(F_) ") (ppr_amode item)
592     size = length amodes
593
594     closure_type = pp_liveness_switch liveness
595                       (ptext SLIT("RET_VEC_SMALL"))
596                       (ptext SLIT("RET_VEC_BIG"))
597
598
599 pprAbsC stmt@(CModuleInitBlock plain_lbl lbl code) _
600   = vcat [
601         ptext SLIT("START_MOD_INIT") <> 
602             parens (pprCLabel plain_lbl <> comma <> pprCLabel lbl),
603         case (pprTempAndExternDecls stmt) of { (_, pp_exts) -> pp_exts },
604         pprAbsC code (costs code),
605         hcat [ptext SLIT("END_MOD_INIT"), lparen, rparen]
606     ]
607
608 pprAbsC (CCostCentreDecl is_local cc) _ = pprCostCentreDecl is_local cc
609 pprAbsC (CCostCentreStackDecl ccs)    _ = pprCostCentreStackDecl ccs
610 \end{code}
611
612 \begin{code}
613 -- Print a CMachOp in a way suitable for emitting via C.
614 pprMachOp_for_C MO_Nat_Add       = char '+'
615 pprMachOp_for_C MO_Nat_Sub       = char '-'
616 pprMachOp_for_C MO_Nat_Eq        = text "==" 
617 pprMachOp_for_C MO_Nat_Ne        = text "!="
618
619 pprMachOp_for_C MO_NatS_Ge       = text ">="
620 pprMachOp_for_C MO_NatS_Le       = text "<="
621 pprMachOp_for_C MO_NatS_Gt       = text ">"
622 pprMachOp_for_C MO_NatS_Lt       = text "<"
623
624 pprMachOp_for_C MO_NatU_Ge       = text ">="
625 pprMachOp_for_C MO_NatU_Le       = text "<="
626 pprMachOp_for_C MO_NatU_Gt       = text ">"
627 pprMachOp_for_C MO_NatU_Lt       = text "<"
628
629 pprMachOp_for_C MO_NatS_Mul      = char '*'
630 pprMachOp_for_C MO_NatS_MulMayOflo = text "mulIntMayOflo"
631 pprMachOp_for_C MO_NatS_Quot     = char '/'
632 pprMachOp_for_C MO_NatS_Rem      = char '%'
633 pprMachOp_for_C MO_NatS_Neg      = char '-'
634
635 pprMachOp_for_C MO_NatU_Mul      = char '*'
636 pprMachOp_for_C MO_NatU_Quot     = char '/'
637 pprMachOp_for_C MO_NatU_Rem      = char '%'
638
639 pprMachOp_for_C MO_Nat_And       = text "&"
640 pprMachOp_for_C MO_Nat_Or        = text "|"
641 pprMachOp_for_C MO_Nat_Xor       = text "^"
642 pprMachOp_for_C MO_Nat_Not       = text "~"
643 pprMachOp_for_C MO_Nat_Shl       = text "<<"
644 pprMachOp_for_C MO_Nat_Shr       = text ">>"
645 pprMachOp_for_C MO_Nat_Sar       = text ">>"
646
647 pprMachOp_for_C MO_32U_Eq        = text "=="
648 pprMachOp_for_C MO_32U_Ne        = text "!="
649 pprMachOp_for_C MO_32U_Ge        = text ">="
650 pprMachOp_for_C MO_32U_Le        = text "<="
651 pprMachOp_for_C MO_32U_Gt        = text ">"
652 pprMachOp_for_C MO_32U_Lt        = text "<"
653
654 pprMachOp_for_C MO_Dbl_Eq        = text "=="
655 pprMachOp_for_C MO_Dbl_Ne        = text "!="
656 pprMachOp_for_C MO_Dbl_Ge        = text ">="
657 pprMachOp_for_C MO_Dbl_Le        = text "<="
658 pprMachOp_for_C MO_Dbl_Gt        = text ">"
659 pprMachOp_for_C MO_Dbl_Lt        = text "<"
660
661 pprMachOp_for_C MO_Dbl_Add       = text "+"
662 pprMachOp_for_C MO_Dbl_Sub       = text "-"
663 pprMachOp_for_C MO_Dbl_Mul       = text "*"
664 pprMachOp_for_C MO_Dbl_Div       = text "/"
665 pprMachOp_for_C MO_Dbl_Pwr       = text "pow"
666
667 pprMachOp_for_C MO_Dbl_Sin       = text "sin"
668 pprMachOp_for_C MO_Dbl_Cos       = text "cos"
669 pprMachOp_for_C MO_Dbl_Tan       = text "tan"
670 pprMachOp_for_C MO_Dbl_Sinh      = text "sinh"
671 pprMachOp_for_C MO_Dbl_Cosh      = text "cosh"
672 pprMachOp_for_C MO_Dbl_Tanh      = text "tanh"
673 pprMachOp_for_C MO_Dbl_Asin      = text "asin"
674 pprMachOp_for_C MO_Dbl_Acos      = text "acos"
675 pprMachOp_for_C MO_Dbl_Atan      = text "atan"
676 pprMachOp_for_C MO_Dbl_Log       = text "log"
677 pprMachOp_for_C MO_Dbl_Exp       = text "exp"
678 pprMachOp_for_C MO_Dbl_Sqrt      = text "sqrt"
679 pprMachOp_for_C MO_Dbl_Neg       = text "-"
680
681 pprMachOp_for_C MO_Flt_Add       = text "+"
682 pprMachOp_for_C MO_Flt_Sub       = text "-"
683 pprMachOp_for_C MO_Flt_Mul       = text "*"
684 pprMachOp_for_C MO_Flt_Div       = text "/"
685 pprMachOp_for_C MO_Flt_Pwr       = text "pow"
686
687 pprMachOp_for_C MO_Flt_Eq        = text "=="
688 pprMachOp_for_C MO_Flt_Ne        = text "!="
689 pprMachOp_for_C MO_Flt_Ge        = text ">="
690 pprMachOp_for_C MO_Flt_Le        = text "<="
691 pprMachOp_for_C MO_Flt_Gt        = text ">"
692 pprMachOp_for_C MO_Flt_Lt        = text "<"
693
694 pprMachOp_for_C MO_Flt_Sin       = text "sin"
695 pprMachOp_for_C MO_Flt_Cos       = text "cos"
696 pprMachOp_for_C MO_Flt_Tan       = text "tan"
697 pprMachOp_for_C MO_Flt_Sinh      = text "sinh"
698 pprMachOp_for_C MO_Flt_Cosh      = text "cosh"
699 pprMachOp_for_C MO_Flt_Tanh      = text "tanh"
700 pprMachOp_for_C MO_Flt_Asin      = text "asin"
701 pprMachOp_for_C MO_Flt_Acos      = text "acos"
702 pprMachOp_for_C MO_Flt_Atan      = text "atan"
703 pprMachOp_for_C MO_Flt_Log       = text "log"
704 pprMachOp_for_C MO_Flt_Exp       = text "exp"
705 pprMachOp_for_C MO_Flt_Sqrt      = text "sqrt"
706 pprMachOp_for_C MO_Flt_Neg       = text "-"
707
708 pprMachOp_for_C MO_32U_to_NatS   = text "(StgInt)"
709 pprMachOp_for_C MO_NatS_to_32U   = text "(StgWord32)"
710
711 pprMachOp_for_C MO_NatS_to_Dbl   = text "(StgDouble)"
712 pprMachOp_for_C MO_Dbl_to_NatS   = text "(StgInt)"
713
714 pprMachOp_for_C MO_NatS_to_Flt   = text "(StgFloat)"
715 pprMachOp_for_C MO_Flt_to_NatS   = text "(StgInt)"
716
717 pprMachOp_for_C MO_NatS_to_NatU  = text "(StgWord)"
718 pprMachOp_for_C MO_NatU_to_NatS  = text "(StgInt)"
719
720 pprMachOp_for_C MO_NatS_to_NatP  = text "(void*)"
721 pprMachOp_for_C MO_NatP_to_NatS  = text "(StgInt)"
722 pprMachOp_for_C MO_NatU_to_NatP  = text "(void*)"
723 pprMachOp_for_C MO_NatP_to_NatU  = text "(StgWord)"
724
725 pprMachOp_for_C MO_Dbl_to_Flt    = text "(StgFloat)"
726 pprMachOp_for_C MO_Flt_to_Dbl    = text "(StgDouble)"
727
728 pprMachOp_for_C MO_8S_to_NatS    = text "(StgInt8)(StgInt)"
729 pprMachOp_for_C MO_16S_to_NatS   = text "(StgInt16)(StgInt)"
730 pprMachOp_for_C MO_32S_to_NatS   = text "(StgInt32)(StgInt)"
731
732 pprMachOp_for_C MO_8U_to_NatU    = text "(StgWord8)(StgWord)"
733 pprMachOp_for_C MO_16U_to_NatU   = text "(StgWord16)(StgWord)"
734 pprMachOp_for_C MO_32U_to_NatU   = text "(StgWord32)(StgWord)"
735
736 pprMachOp_for_C MO_8U_to_32U     = text "(StgWord32)"
737 pprMachOp_for_C MO_32U_to_8U     = text "(StgWord8)"
738
739
740 ppLocalness lbl
741   = if (externallyVisibleCLabel lbl) 
742                 then empty 
743                 else ptext SLIT("static ")
744
745 -- Horrible macros for declaring the types and locality of labels (see
746 -- StgMacros.h).
747
748 ppLocalnessMacro include_dyn_prefix clabel =
749      hcat [
750         visiblity_prefix,
751         dyn_prefix,
752         case label_type of
753           ClosureType    -> ptext SLIT("C_")
754           CodeType       -> ptext SLIT("F_")
755           InfoTblType    -> ptext SLIT("I_")
756           ClosureTblType -> ptext SLIT("CP_")
757           DataType       -> ptext SLIT("D_")
758      ]
759   where
760    is_visible = externallyVisibleCLabel clabel
761    label_type = labelType clabel
762
763    visiblity_prefix
764      | is_visible = char 'E'
765      | otherwise  = char 'I'
766
767    dyn_prefix
768      | include_dyn_prefix && labelDynamic clabel = char 'D'
769      | otherwise                                 = empty
770
771 \end{code}
772
773 \begin{code}
774 jmp_lit = "JMP_("
775
776 grab_non_void_amodes amodes
777   = filter non_void amodes
778
779 non_void amode
780   = case (getAmodeRep amode) of
781       VoidRep -> False
782       k -> True
783 \end{code}
784
785 \begin{code}
786 ppr_maybe_vol_regs :: Maybe [MagicId] -> (SDoc, SDoc)
787 ppr_maybe_vol_regs Nothing
788    = (empty, empty)
789 ppr_maybe_vol_regs (Just vrs)
790    = case ppr_vol_regs vrs of
791         (saves, restores) 
792            -> (pp_basic_saves $$ saves,
793                pp_basic_restores $$ restores)
794
795 ppr_vol_regs :: [MagicId] -> (SDoc, SDoc)
796
797 ppr_vol_regs [] = (empty, empty)
798 ppr_vol_regs (VoidReg:rs) = ppr_vol_regs rs
799 ppr_vol_regs (r:rs)
800   = let pp_reg = case r of
801                     VanillaReg pk n -> pprVanillaReg n
802                     _ -> pprMagicId r
803         (more_saves, more_restores) = ppr_vol_regs rs
804     in
805     (($$) ((<>) (ptext SLIT("CALLER_SAVE_"))    pp_reg) more_saves,
806      ($$) ((<>) (ptext SLIT("CALLER_RESTORE_")) pp_reg) more_restores)
807
808 -- pp_basic_{saves,restores}: The BaseReg, Sp, Su, Hp and
809 -- HpLim (see StgRegs.lh) may need to be saved/restored around CCalls,
810 -- depending on the platform.  (The "volatile regs" stuff handles all
811 -- other registers.)  Just be *sure* BaseReg is OK before trying to do
812 -- anything else. The correct sequence of saves&restores are
813 -- encoded by the CALLER_*_SYSTEM macros.
814 pp_basic_saves    = ptext SLIT("CALLER_SAVE_SYSTEM")
815 pp_basic_restores = ptext SLIT("CALLER_RESTORE_SYSTEM")
816 \end{code}
817
818 \begin{code}
819 pp_srt_info NoC_SRT = hcat [ int 0, comma, 
820                              int 0, comma, 
821                              int 0, comma ]
822 pp_srt_info (C_SRT lbl off len) = hcat [ pprCLabel lbl, comma,
823                                          int off, comma,
824                                          int len, comma ]
825 \end{code}
826
827 \begin{code}
828 pp_closure_lbl lbl
829       | labelDynamic lbl = text "DLL_SRT_ENTRY" <> parens (pprCLabel lbl)
830       | otherwise        = char '&' <> pprCLabel lbl
831 \end{code}
832
833 \begin{code}
834 if_profiling pretty
835   = if  opt_SccProfilingOn
836     then pretty
837     else char '0' -- leave it out!
838 -- ---------------------------------------------------------------------------
839 -- Changes for GrAnSim:
840 --  draw costs for computation in head of if into both branches;
841 --  as no abstractC data structure is given for the head, one is constructed
842 --  guessing unknown values and fed into the costs function
843 -- ---------------------------------------------------------------------------
844
845 do_if_stmt discrim tag alt_code deflt c
846    = let
847        cond = hcat [ pprAmode discrim
848                    , ptext SLIT(" == ")
849                    , tcast
850                    , pprAmode (CLit tag)
851                    ]
852         -- to be absolutely sure that none of the 
853         -- conversion rules hit, e.g.,
854         --
855         --     minInt is different to (int)minInt
856         --
857         -- in C (when minInt is a number not a constant
858         --  expression which evaluates to it.)
859         -- 
860        tcast = case tag of
861                    MachInt _  -> ptext SLIT("(I_)")
862                    _          -> empty
863      in
864      ppr_if_stmt cond
865                  alt_code deflt
866                  (addrModeCosts discrim Rhs) c
867
868 ppr_if_stmt pp_pred then_part else_part discrim_costs c
869   = vcat [
870       hcat [text "if (", pp_pred, text ") {"],
871       nest 8 (pprAbsC then_part         (c + discrim_costs +
872                                         (Cost (0, 2, 0, 0, 0)) +
873                                         costs then_part)),
874       (case nonemptyAbsC else_part of Nothing -> empty; Just _ -> text "} else {"),
875       nest 8 (pprAbsC else_part  (c + discrim_costs +
876                                         (Cost (0, 1, 0, 0, 0)) +
877                                         costs else_part)),
878       char '}' ]
879     {- Total costs = inherited costs (before if) + costs for accessing discrim
880                      + costs for cond branch ( = (0, 1, 0, 0, 0) )
881                      + costs for that alternative
882     -}
883 \end{code}
884
885 Historical note: this used to be two separate cases -- one for `ccall'
886 and one for `casm'.  To get round a potential limitation to only 10
887 arguments, the numbering of arguments in @process_casm@ was beefed up a
888 bit. ADR
889
890 Some rough notes on generating code for @CCallOp@:
891
892 1) Evaluate all arguments and stuff them into registers. (done elsewhere)
893 2) Save any essential registers (heap, stack, etc).
894
895    ToDo: If stable pointers are in use, these must be saved in a place
896    where the runtime system can get at them so that the Stg world can
897    be restarted during the call.
898
899 3) Save any temporary registers that are currently in use.
900 4) Do the call, putting result into a local variable
901 5) Restore essential registers
902 6) Restore temporaries
903
904    (This happens after restoration of essential registers because we
905    might need the @Base@ register to access all the others correctly.)
906
907    Otherwise, copy local variable into result register.
908
909 8) If ccall (not casm), declare the function being called as extern so
910    that C knows if it returns anything other than an int.
911
912 \begin{pseudocode}
913 { ResultType _ccall_result;
914   basic_saves;
915   saves;
916   _ccall_result = f( args );
917   basic_restores;
918   restores;
919
920   return_reg = _ccall_result;
921 }
922 \end{pseudocode}
923
924 Amendment to the above: if we can GC, we have to:
925
926 * make sure we save all our registers away where the garbage collector
927   can get at them.
928 * be sure that there are no live registers or we're in trouble.
929   (This can cause problems if you try something foolish like passing
930    an array or a foreign obj to a _ccall_GC_ thing.)
931 * increment/decrement the @inCCallGC@ counter before/after the call so
932   that the runtime check that PerformGC is being used sensibly will work.
933
934 \begin{code}
935 pprFCall call@(CCall (CCallSpec target cconv safety)) uniq args results vol_regs
936   = vcat [
937       char '{',
938       declare_local_vars,   -- local var for *result*
939       vcat local_arg_decls,
940       pp_save_context,
941         process_casm local_vars pp_non_void_args call_str,
942       pp_restore_context,
943       assign_results,
944       char '}'
945     ]
946   where
947     (pp_saves, pp_restores) = ppr_vol_regs vol_regs
948
949     thread_macro_args = ppr_uniq_token <> comma <+> 
950                         text "rts" <> ppr (playThreadSafe safety)
951     ppr_uniq_token = text "tok_" <> ppr uniq
952     (pp_save_context, pp_restore_context)
953         | playSafe safety = ( text "{ I_" <+> ppr_uniq_token <> 
954                                 text "; SUSPEND_THREAD" <> parens thread_macro_args <> semi
955                             , text "RESUME_THREAD" <> parens thread_macro_args <> text ";}"
956                             )
957         | otherwise = ( pp_basic_saves $$ pp_saves,
958                         pp_basic_restores $$ pp_restores)
959
960     non_void_args = 
961         let nvas = init args
962         in ASSERT2 ( all non_void nvas, ppr call <+> hsep (map pprAmode args) )
963         nvas
964     -- the last argument will be the "I/O world" token (a VoidRep)
965     -- all others should be non-void
966
967     non_void_results =
968         let nvrs = grab_non_void_amodes results
969         in ASSERT (listLengthCmp nvrs 1 /= GT) nvrs
970     -- there will usually be two results: a (void) state which we
971     -- should ignore and a (possibly void) result.
972
973     (local_arg_decls, pp_non_void_args)
974       = unzip [ ppr_casm_arg a i | (a,i) <- non_void_args `zip` [1..] ]
975
976     (declare_local_vars, local_vars, assign_results)
977       = ppr_casm_results non_void_results
978
979     call_str = case target of
980                   CasmTarget str  -> unpackFS str
981                   StaticTarget fn -> mk_ccall_str (pprCLabelString fn) ccall_args
982                   DynamicTarget   -> mk_ccall_str dyn_fun              (tail ccall_args)
983
984     ccall_args = zipWith (\ _ i -> char '%' <> int i) non_void_args [0..]
985     dyn_fun    = parens (parens (ptext SLIT("_ccall_fun_ty") <> ppr uniq) <> text "%0")
986                                                  
987
988     -- Remainder only used for ccall
989     mk_ccall_str fun_name ccall_fun_args = showSDoc
990         (hcat [
991                 if null non_void_results
992                   then empty
993                   else text "%r = ",
994                 lparen, fun_name, lparen,
995                   hcat (punctuate comma ccall_fun_args),
996                 text "));"
997         ])
998
999
1000 ppr_casm_arg :: CAddrMode -> Int -> (SDoc, SDoc)
1001     -- (a) decl and assignment, (b) local var to be used later
1002
1003 ppr_casm_arg amode a_num
1004   = let
1005         a_kind   = getAmodeRep amode
1006         pp_amode = pprAmode amode
1007         pp_kind  = pprPrimKind a_kind
1008
1009         local_var  = (<>) (ptext SLIT("_ccall_arg")) (int a_num)
1010
1011         declare_local_var
1012           = hcat [ pp_kind, space, local_var, equals, pp_amode, semi ]
1013     in
1014     (declare_local_var, local_var)
1015 \end{code}
1016
1017 For l-values, the critical questions are:
1018
1019 1) Are there any results at all?
1020
1021    We only allow zero or one results.
1022
1023 \begin{code}
1024 ppr_casm_results
1025         :: [CAddrMode]  -- list of results (length <= 1)
1026         ->
1027         ( SDoc,         -- declaration of any local vars
1028           [SDoc],       -- list of result vars (same length as results)
1029           SDoc )        -- assignment (if any) of results in local var to registers
1030
1031 ppr_casm_results []
1032   = (empty, [], empty)  -- no results
1033
1034 ppr_casm_results [r]
1035   = let
1036         result_reg = ppr_amode r
1037         r_kind     = getAmodeRep r
1038
1039         local_var  = ptext SLIT("_ccall_result")
1040
1041         (result_type, assign_result)
1042           = (pprPrimKind r_kind,
1043              hcat [ result_reg, equals, local_var, semi ])
1044
1045         declare_local_var = hcat [ result_type, space, local_var, semi ]
1046     in
1047     (declare_local_var, [local_var], assign_result)
1048
1049 ppr_casm_results rs
1050   = panic "ppr_casm_results: ccall/casm with many results"
1051 \end{code}
1052
1053
1054 Note the sneaky way _the_ result is represented by a list so that we
1055 can complain if it's used twice.
1056
1057 ToDo: Any chance of giving line numbers when process-casm fails?
1058       Or maybe we should do a check _much earlier_ in compiler. ADR
1059
1060 \begin{code}
1061 process_casm :: [SDoc]          -- results (length <= 1)
1062              -> [SDoc]          -- arguments
1063              -> String          -- format string (with embedded %'s)
1064              -> SDoc            -- code being generated
1065
1066 process_casm results args string = process results args string
1067  where
1068   process []    _ "" = empty
1069   process (_:_) _ "" = error ("process_casm: non-void result not assigned while processing _casm_ \"" ++ 
1070                               string ++ 
1071                               "\"\n(Try changing result type to IO ()\n")
1072
1073   process ress args ('%':cs)
1074     = case cs of
1075         [] ->
1076             error ("process_casm: lonely % while processing _casm_ \"" ++ string ++ "\".\n")
1077
1078         ('%':css) ->
1079             char '%' <> process ress args css
1080
1081         ('r':css)  ->
1082           case ress of
1083             []  -> error ("process_casm: no result to match %r while processing _casm_ \"" ++ string ++ "\".\nTry deleting %r or changing result type from PrimIO ()\n")
1084             [r] -> r <> (process [] args css)
1085             _   -> panic ("process_casm: casm with many results while processing _casm_ \"" ++ string ++ "\".\n")
1086
1087         other ->
1088           let
1089                 read_int :: ReadS Int
1090                 read_int = reads
1091           in
1092           case (read_int other) of
1093             [(num,css)] ->
1094                   if num >= 0 && args `lengthExceeds` num
1095                   then parens (args !! num) <> process ress args css
1096                   else error ("process_casm: no such arg #:"++(show num)++" while processing \"" ++ string ++ "\".\n")
1097             _ -> error ("process_casm: not %<num> while processing _casm_ \"" ++ string ++ "\".\n")
1098
1099   process ress args (other_c:cs)
1100     = char other_c <> process ress args cs
1101 \end{code}
1102
1103 %************************************************************************
1104 %*                                                                      *
1105 \subsection[a2r-assignments]{Assignments}
1106 %*                                                                      *
1107 %************************************************************************
1108
1109 Printing assignments is a little tricky because of type coercion.
1110
1111 First of all, the kind of the thing being assigned can be gotten from
1112 the destination addressing mode.  (It should be the same as the kind
1113 of the source addressing mode.)  If the kind of the assignment is of
1114 @VoidRep@, then don't generate any code at all.
1115
1116 \begin{code}
1117 pprAssign :: PrimRep -> CAddrMode -> CAddrMode -> SDoc
1118
1119 pprAssign VoidRep dest src = empty
1120 \end{code}
1121
1122 Special treatment for floats and doubles, to avoid unwanted conversions.
1123
1124 \begin{code}
1125 pprAssign FloatRep dest@(CVal reg_rel _) src
1126   = hcat [ ptext SLIT("ASSIGN_FLT((W_*)"), parens (ppr_amode (CAddr reg_rel)), comma, pprAmode src, pp_paren_semi ]
1127
1128 pprAssign DoubleRep dest@(CVal reg_rel _) src
1129   = hcat [ ptext SLIT("ASSIGN_DBL((W_*)"), parens (ppr_amode (CAddr reg_rel)), comma, pprAmode src, pp_paren_semi ]
1130
1131 pprAssign Int64Rep dest@(CVal reg_rel _) src
1132   = hcat [ ptext SLIT("ASSIGN_Int64((W_*)"), parens (ppr_amode (CAddr reg_rel)), comma, pprAmode src, pp_paren_semi ]
1133 pprAssign Word64Rep dest@(CVal reg_rel _) src
1134   = hcat [ ptext SLIT("ASSIGN_Word64((W_*)"), parens (ppr_amode (CAddr reg_rel)), comma, pprAmode src, pp_paren_semi ]
1135 \end{code}
1136
1137 Lastly, the question is: will the C compiler think the types of the
1138 two sides of the assignment match?
1139
1140         We assume that the types will match if neither side is a
1141         @CVal@ addressing mode for any register which can point into
1142         the heap or stack.
1143
1144 Why?  Because the heap and stack are used to store miscellaneous
1145 things, whereas the temporaries, registers, etc., are only used for
1146 things of fixed type.
1147
1148 \begin{code}
1149 pprAssign kind (CReg (VanillaReg _ dest)) (CReg (VanillaReg _ src))
1150   = hcat [ pprVanillaReg dest, equals,
1151                 pprVanillaReg src, semi ]
1152
1153 pprAssign kind dest src
1154   | mixedTypeLocn dest
1155     -- Add in a cast to StgWord (a.k.a. W_) iff the destination is mixed
1156   = hcat [ ppr_amode dest, equals,
1157                 text "(W_)(",   -- Here is the cast
1158                 ppr_amode src, pp_paren_semi ]
1159
1160 pprAssign kind dest src
1161   | mixedPtrLocn dest && getAmodeRep src /= PtrRep
1162     -- Add in a cast to StgPtr (a.k.a. P_) iff the destination is mixed
1163   = hcat [ ppr_amode dest, equals,
1164                 text "(P_)(",   -- Here is the cast
1165                 ppr_amode src, pp_paren_semi ]
1166
1167 pprAssign kind other_dest src
1168   = hcat [ ppr_amode other_dest, equals,
1169                 pprAmode  src, semi ]
1170 \end{code}
1171
1172
1173 %************************************************************************
1174 %*                                                                      *
1175 \subsection[a2r-CAddrModes]{Addressing modes}
1176 %*                                                                      *
1177 %************************************************************************
1178
1179 @pprAmode@ is used to print r-values (which may need casts), whereas
1180 @ppr_amode@ is used for l-values {\em and} as a help function for
1181 @pprAmode@.
1182
1183 \begin{code}
1184 pprAmode, ppr_amode :: CAddrMode -> SDoc
1185 \end{code}
1186
1187 For reasons discussed above under assignments, @CVal@ modes need
1188 to be treated carefully.  First come special cases for floats and doubles,
1189 similar to those in @pprAssign@:
1190
1191 (NB: @PK_FLT@ and @PK_DBL@ require the {\em address} of the value in
1192 question.)
1193
1194 \begin{code}
1195 pprAmode (CVal reg_rel FloatRep)
1196   = hcat [ text "PK_FLT((W_*)", parens (ppr_amode (CAddr reg_rel)), rparen ]
1197 pprAmode (CVal reg_rel DoubleRep)
1198   = hcat [ text "PK_DBL((W_*)", parens (ppr_amode (CAddr reg_rel)), rparen ]
1199 pprAmode (CVal reg_rel Int64Rep)
1200   = hcat [ text "PK_Int64((W_*)", parens (ppr_amode (CAddr reg_rel)), rparen ]
1201 pprAmode (CVal reg_rel Word64Rep)
1202   = hcat [ text "PK_Word64((W_*)", parens (ppr_amode (CAddr reg_rel)), rparen ]
1203 \end{code}
1204
1205 Next comes the case where there is some other cast need, and the
1206 no-cast case:
1207
1208 \begin{code}
1209 pprAmode amode
1210   | mixedTypeLocn amode
1211   = parens (hcat [ pprPrimKind (getAmodeRep amode), ptext SLIT(")("),
1212                 ppr_amode amode ])
1213   | otherwise   -- No cast needed
1214   = ppr_amode amode
1215 \end{code}
1216
1217 When we have an indirection through a CIndex, we have to be careful to
1218 get the type casts right.  
1219
1220 this amode:
1221
1222         CVal (CIndex kind1 base offset) kind2
1223
1224 means (in C speak): 
1225         
1226         *(kind2 *)((kind1 *)base + offset)
1227
1228 That is, the indexing is done in units of kind1, but the resulting
1229 amode has kind2.
1230
1231 \begin{code}
1232 ppr_amode CBytesPerWord
1233   = text "(sizeof(void*))"
1234
1235 ppr_amode (CVal reg_rel@(CIndex _ _ _) kind)
1236   = case (pprRegRelative False{-no sign wanted-} reg_rel) of
1237         (pp_reg, Nothing)     -> panic "ppr_amode: CIndex"
1238         (pp_reg, Just offset) -> 
1239            hcat [ char '*', parens (pprPrimKind kind <> char '*'),
1240                   parens (pp_reg <> char '+' <> offset) ]
1241 \end{code}
1242
1243 Now the rest of the cases for ``workhorse'' @ppr_amode@:
1244
1245 \begin{code}
1246 ppr_amode (CVal reg_rel _)
1247   = case (pprRegRelative False{-no sign wanted-} reg_rel) of
1248         (pp_reg, Nothing)     -> (<>)  (char '*') pp_reg
1249         (pp_reg, Just offset) -> hcat [ pp_reg, brackets offset ]
1250
1251 ppr_amode (CAddr reg_rel)
1252   = case (pprRegRelative True{-sign wanted-} reg_rel) of
1253         (pp_reg, Nothing)     -> pp_reg
1254         (pp_reg, Just offset) -> (<>) pp_reg offset
1255
1256 ppr_amode (CReg magic_id) = pprMagicId magic_id
1257
1258 ppr_amode (CTemp uniq kind) = char '_' <> pprUnique uniq <> char '_'
1259
1260 ppr_amode (CLbl lbl kind) = pprCLabelAddr lbl 
1261
1262 ppr_amode (CCharLike ch)
1263   = hcat [ptext SLIT("CHARLIKE_CLOSURE"), char '(', pprAmode ch, rparen ]
1264 ppr_amode (CIntLike int)
1265   = hcat [ptext SLIT("INTLIKE_CLOSURE"), char '(', pprAmode int, rparen ]
1266
1267 ppr_amode (CLit lit) = pprBasicLit lit
1268
1269 ppr_amode (CJoinPoint _)
1270   = panic "ppr_amode: CJoinPoint"
1271
1272 ppr_amode (CMacroExpr pk macro as)
1273   = parens (ptext (cExprMacroText macro) <> 
1274             parens (hcat (punctuate comma (map pprAmode as))))
1275 \end{code}
1276
1277 \begin{code}
1278 cExprMacroText ENTRY_CODE               = SLIT("ENTRY_CODE")
1279 cExprMacroText ARG_TAG                  = SLIT("ARG_TAG")
1280 cExprMacroText GET_TAG                  = SLIT("GET_TAG")
1281 cExprMacroText UPD_FRAME_UPDATEE        = SLIT("UPD_FRAME_UPDATEE")
1282 cExprMacroText CCS_HDR                  = SLIT("CCS_HDR")
1283 cExprMacroText BYTE_ARR_CTS             = SLIT("BYTE_ARR_CTS")
1284 cExprMacroText PTRS_ARR_CTS             = SLIT("PTRS_ARR_CTS")
1285 cExprMacroText ForeignObj_CLOSURE_DATA  = SLIT("ForeignObj_CLOSURE_DATA")
1286
1287 cStmtMacroText ARGS_CHK                 = SLIT("ARGS_CHK")
1288 cStmtMacroText ARGS_CHK_LOAD_NODE       = SLIT("ARGS_CHK_LOAD_NODE")
1289 cStmtMacroText UPD_CAF                  = SLIT("UPD_CAF")
1290 cStmtMacroText UPD_BH_UPDATABLE         = SLIT("UPD_BH_UPDATABLE")
1291 cStmtMacroText UPD_BH_SINGLE_ENTRY      = SLIT("UPD_BH_SINGLE_ENTRY")
1292 cStmtMacroText PUSH_UPD_FRAME           = SLIT("PUSH_UPD_FRAME")
1293 cStmtMacroText PUSH_SEQ_FRAME           = SLIT("PUSH_SEQ_FRAME")
1294 cStmtMacroText UPDATE_SU_FROM_UPD_FRAME = SLIT("UPDATE_SU_FROM_UPD_FRAME")
1295 cStmtMacroText SET_TAG                  = SLIT("SET_TAG")
1296 cStmtMacroText DATA_TO_TAGZH            = SLIT("dataToTagzh")
1297 cStmtMacroText REGISTER_FOREIGN_EXPORT  = SLIT("REGISTER_FOREIGN_EXPORT")
1298 cStmtMacroText REGISTER_IMPORT          = SLIT("REGISTER_IMPORT")
1299 cStmtMacroText REGISTER_DIMPORT         = SLIT("REGISTER_DIMPORT")
1300 cStmtMacroText GRAN_FETCH               = SLIT("GRAN_FETCH")
1301 cStmtMacroText GRAN_RESCHEDULE          = SLIT("GRAN_RESCHEDULE")
1302 cStmtMacroText GRAN_FETCH_AND_RESCHEDULE= SLIT("GRAN_FETCH_AND_RESCHEDULE")
1303 cStmtMacroText THREAD_CONTEXT_SWITCH    = SLIT("THREAD_CONTEXT_SWITCH")
1304 cStmtMacroText GRAN_YIELD               = SLIT("GRAN_YIELD")
1305
1306 cCheckMacroText HP_CHK_NP               = SLIT("HP_CHK_NP")
1307 cCheckMacroText STK_CHK_NP              = SLIT("STK_CHK_NP")
1308 cCheckMacroText HP_STK_CHK_NP           = SLIT("HP_STK_CHK_NP")
1309 cCheckMacroText HP_CHK_SEQ_NP           = SLIT("HP_CHK_SEQ_NP")
1310 cCheckMacroText HP_CHK                  = SLIT("HP_CHK")
1311 cCheckMacroText STK_CHK                 = SLIT("STK_CHK")
1312 cCheckMacroText HP_STK_CHK              = SLIT("HP_STK_CHK")
1313 cCheckMacroText HP_CHK_NOREGS           = SLIT("HP_CHK_NOREGS")
1314 cCheckMacroText HP_CHK_UNPT_R1          = SLIT("HP_CHK_UNPT_R1")
1315 cCheckMacroText HP_CHK_UNBX_R1          = SLIT("HP_CHK_UNBX_R1")
1316 cCheckMacroText HP_CHK_F1               = SLIT("HP_CHK_F1")
1317 cCheckMacroText HP_CHK_D1               = SLIT("HP_CHK_D1")
1318 cCheckMacroText HP_CHK_L1               = SLIT("HP_CHK_L1")
1319 cCheckMacroText HP_CHK_UT_ALT           = SLIT("HP_CHK_UT_ALT")
1320 cCheckMacroText HP_CHK_GEN              = SLIT("HP_CHK_GEN")
1321 \end{code}
1322
1323 \begin{code}
1324 \end{code}
1325
1326 %************************************************************************
1327 %*                                                                      *
1328 \subsection[ppr-liveness-masks]{Liveness Masks}
1329 %*                                                                      *
1330 %************************************************************************
1331
1332 \begin{code}
1333 pp_bitmap_switch :: [BitSet] -> SDoc -> SDoc -> SDoc
1334 pp_bitmap_switch ([   ]) small large = small
1335 pp_bitmap_switch ([_  ]) small large = small
1336 pp_bitmap_switch ([_,_]) small large = hcat
1337     [ptext SLIT("BITMAP_SWITCH64"), lparen, small, comma, large, rparen]
1338 pp_bitmap_switch (_    ) small large = large
1339
1340 pp_liveness_switch :: Liveness -> SDoc -> SDoc -> SDoc
1341 pp_liveness_switch (Liveness lbl mask) = pp_bitmap_switch mask
1342
1343 pp_bitset :: BitSet -> SDoc
1344 pp_bitset s
1345     | i < -1    = int (i + 1) <> text "-1"
1346     | otherwise = int i
1347     where i = intBS s
1348
1349 pp_bitmap :: [BitSet] -> SDoc
1350 pp_bitmap [] = int 0
1351 pp_bitmap ss = hcat (punctuate delayed_comma (bundle ss)) where
1352   delayed_comma         = hcat [space, ptext SLIT("COMMA"), space]
1353   bundle []         = []
1354   bundle [s]        = [hcat bitmap32]
1355      where bitmap32 = [ptext SLIT("BITMAP32"), lparen,
1356                        pp_bitset s, rparen]
1357   bundle (s1:s2:ss) = hcat bitmap64 : bundle ss
1358      where bitmap64 = [ptext SLIT("BITMAP64"), lparen,
1359                        pp_bitset s1, comma, pp_bitset s2, rparen]
1360
1361 pp_liveness :: Liveness -> SDoc
1362 pp_liveness (Liveness lbl mask)
1363  = pp_bitmap_switch mask (pp_bitmap mask) (char '&' <> pprCLabel lbl)
1364 \end{code}
1365
1366 %************************************************************************
1367 %*                                                                      *
1368 \subsection[a2r-MagicIds]{Magic ids}
1369 %*                                                                      *
1370 %************************************************************************
1371
1372 @pprRegRelative@ returns a pair of the @Doc@ for the register
1373 (some casting may be required), and a @Maybe Doc@ for the offset
1374 (zero offset gives a @Nothing@).
1375
1376 \begin{code}
1377 addPlusSign :: Bool -> SDoc -> SDoc
1378 addPlusSign False p = p
1379 addPlusSign True  p = (<>) (char '+') p
1380
1381 pprSignedInt :: Bool -> Int -> Maybe SDoc       -- Nothing => 0
1382 pprSignedInt sign_wanted n
1383  = if n == 0 then Nothing else
1384    if n > 0  then Just (addPlusSign sign_wanted (int n))
1385    else           Just (int n)
1386
1387 pprRegRelative :: Bool          -- True <=> Print leading plus sign (if +ve)
1388                -> RegRelative
1389                -> (SDoc, Maybe SDoc)
1390
1391 pprRegRelative sign_wanted (SpRel off)
1392   = (pprMagicId Sp, pprSignedInt sign_wanted (I# off))
1393
1394 pprRegRelative sign_wanted r@(HpRel o)
1395   = let pp_Hp    = pprMagicId Hp; off = I# o
1396     in
1397     if off == 0 then
1398         (pp_Hp, Nothing)
1399     else
1400         (pp_Hp, Just ((<>) (char '-') (int off)))
1401
1402 pprRegRelative sign_wanted (NodeRel o)
1403   = let pp_Node = pprMagicId node; off = I# o
1404     in
1405     if off == 0 then
1406         (pp_Node, Nothing)
1407     else
1408         (pp_Node, Just (addPlusSign sign_wanted (int off)))
1409
1410 pprRegRelative sign_wanted (CIndex base offset kind)
1411   = ( hcat [text "((", pprPrimKind kind, text " *)(", ppr_amode base, text "))"]
1412     , Just (hcat [if sign_wanted then char '+' else empty,
1413             text "(I_)(", ppr_amode offset, ptext SLIT(")")])
1414     )
1415 \end{code}
1416
1417 @pprMagicId@ just prints the register name.  @VanillaReg@ registers are
1418 represented by a discriminated union (@StgUnion@), so we use the @PrimRep@
1419 to select the union tag.
1420
1421 \begin{code}
1422 pprMagicId :: MagicId -> SDoc
1423
1424 pprMagicId BaseReg                  = ptext SLIT("BaseReg")
1425 pprMagicId (VanillaReg pk n)
1426                                     = hcat [ pprVanillaReg n, char '.',
1427                                                   pprUnionTag pk ]
1428 pprMagicId (FloatReg  n)            = ptext SLIT("F") <> int (I# n)
1429 pprMagicId (DoubleReg n)            = ptext SLIT("D") <> int (I# n)
1430 pprMagicId (LongReg _ n)            = ptext SLIT("L") <> int (I# n)
1431 pprMagicId Sp                       = ptext SLIT("Sp")
1432 pprMagicId Su                       = ptext SLIT("Su")
1433 pprMagicId SpLim                    = ptext SLIT("SpLim")
1434 pprMagicId Hp                       = ptext SLIT("Hp")
1435 pprMagicId HpLim                    = ptext SLIT("HpLim")
1436 pprMagicId CurCostCentre            = ptext SLIT("CCCS")
1437 pprMagicId VoidReg                  = panic "pprMagicId:VoidReg!"
1438
1439 pprVanillaReg :: Int# -> SDoc
1440 pprVanillaReg n = char 'R' <> int (I# n)
1441
1442 pprUnionTag :: PrimRep -> SDoc
1443
1444 pprUnionTag PtrRep              = char 'p'
1445 pprUnionTag CodePtrRep          = ptext SLIT("fp")
1446 pprUnionTag DataPtrRep          = char 'd'
1447 pprUnionTag RetRep              = char 'p'
1448 pprUnionTag CostCentreRep       = panic "pprUnionTag:CostCentre?"
1449
1450 pprUnionTag CharRep             = char 'c'
1451 pprUnionTag Int8Rep             = ptext SLIT("i8")
1452 pprUnionTag IntRep              = char 'i'
1453 pprUnionTag WordRep             = char 'w'
1454 pprUnionTag Int32Rep            = char 'i'
1455 pprUnionTag Word32Rep           = char 'w'
1456 pprUnionTag AddrRep             = char 'a'
1457 pprUnionTag FloatRep            = char 'f'
1458 pprUnionTag DoubleRep           = panic "pprUnionTag:Double?"
1459
1460 pprUnionTag StablePtrRep        = char 'p'
1461
1462 pprUnionTag _                   = panic "pprUnionTag:Odd kind"
1463 \end{code}
1464
1465
1466 Find and print local and external declarations for a list of
1467 Abstract~C statements.
1468 \begin{code}
1469 pprTempAndExternDecls :: AbstractC -> (SDoc{-temps-}, SDoc{-externs-})
1470 pprTempAndExternDecls AbsCNop = (empty, empty)
1471
1472 pprTempAndExternDecls (AbsCStmts stmt1 stmt2)
1473   = initTE (ppr_decls_AbsC stmt1        `thenTE` \ (t_p1, e_p1) ->
1474             ppr_decls_AbsC stmt2        `thenTE` \ (t_p2, e_p2) ->
1475             case (catMaybes [t_p1, t_p2])        of { real_temps ->
1476             case (catMaybes [e_p1, e_p2])        of { real_exts ->
1477             returnTE (vcat real_temps, vcat real_exts) }}
1478            )
1479
1480 pprTempAndExternDecls other_stmt
1481   = initTE (ppr_decls_AbsC other_stmt `thenTE` \ (maybe_t, maybe_e) ->
1482             returnTE (
1483                 case maybe_t of
1484                   Nothing -> empty
1485                   Just pp -> pp,
1486
1487                 case maybe_e of
1488                   Nothing -> empty
1489                   Just pp -> pp )
1490            )
1491
1492 pprBasicLit :: Literal -> SDoc
1493 pprPrimKind :: PrimRep -> SDoc
1494
1495 pprBasicLit  lit = ppr lit
1496 pprPrimKind  k   = ppr k
1497 \end{code}
1498
1499
1500 %************************************************************************
1501 %*                                                                      *
1502 \subsection[a2r-monad]{Monadery}
1503 %*                                                                      *
1504 %************************************************************************
1505
1506 We need some monadery to keep track of temps and externs we have already
1507 printed.  This info must be threaded right through the Abstract~C, so
1508 it's most convenient to hide it in this monad.
1509
1510 WDP 95/02: Switched from \tr{([Unique], [CLabel])} to
1511 \tr{(UniqSet, CLabelSet)}.  Allegedly for efficiency.
1512
1513 \begin{code}
1514 type CLabelSet = FiniteMap CLabel (){-any type will do-}
1515 emptyCLabelSet = emptyFM
1516 x `elementOfCLabelSet` labs
1517   = case (lookupFM labs x) of { Just _ -> True; Nothing -> False }
1518
1519 addToCLabelSet set x = addToFM set x ()
1520
1521 type TEenv = (UniqSet Unique, CLabelSet)
1522
1523 type TeM result =  TEenv -> (TEenv, result)
1524
1525 initTE :: TeM a -> a
1526 initTE sa
1527   = case sa (emptyUniqSet, emptyCLabelSet) of { (_, result) ->
1528     result }
1529
1530 {-# INLINE thenTE #-}
1531 {-# INLINE returnTE #-}
1532
1533 thenTE :: TeM a -> (a -> TeM b) -> TeM b
1534 thenTE a b u
1535   = case a u        of { (u_1, result_of_a) ->
1536     b result_of_a u_1 }
1537
1538 mapTE :: (a -> TeM b) -> [a] -> TeM [b]
1539 mapTE f []     = returnTE []
1540 mapTE f (x:xs)
1541   = f x         `thenTE` \ r  ->
1542     mapTE f xs  `thenTE` \ rs ->
1543     returnTE (r : rs)
1544
1545 returnTE :: a -> TeM a
1546 returnTE result env = (env, result)
1547
1548 -- these next two check whether the thing is already
1549 -- recorded, and THEN THEY RECORD IT
1550 -- (subsequent calls will return False for the same uniq/label)
1551
1552 tempSeenTE :: Unique -> TeM Bool
1553 tempSeenTE uniq env@(seen_uniqs, seen_labels)
1554   = if (uniq `elementOfUniqSet` seen_uniqs)
1555     then (env, True)
1556     else ((addOneToUniqSet seen_uniqs uniq,
1557           seen_labels),
1558           False)
1559
1560 labelSeenTE :: CLabel -> TeM Bool
1561 labelSeenTE lbl env@(seen_uniqs, seen_labels)
1562   = if (lbl `elementOfCLabelSet` seen_labels)
1563     then (env, True)
1564     else ((seen_uniqs,
1565           addToCLabelSet seen_labels lbl),
1566           False)
1567 \end{code}
1568
1569 \begin{code}
1570 pprTempDecl :: Unique -> PrimRep -> SDoc
1571 pprTempDecl uniq kind
1572   = hcat [ pprPrimKind kind, space, char '_', pprUnique uniq, ptext SLIT("_;") ]
1573
1574 pprExternDecl :: Bool -> CLabel -> SDoc
1575 pprExternDecl in_srt clabel
1576   | not (needsCDecl clabel) = empty -- do not print anything for "known external" things
1577   | otherwise               = 
1578         hcat [ ppLocalnessMacro (not in_srt) clabel, 
1579                lparen, dyn_wrapper (pprCLabel clabel), pp_paren_semi ]
1580  where
1581   dyn_wrapper d
1582     | in_srt && labelDynamic clabel = text "DLL_IMPORT_DATA_VAR" <> parens d
1583     | otherwise                     = d
1584
1585 \end{code}
1586
1587 \begin{code}
1588 ppr_decls_AbsC :: AbstractC -> TeM (Maybe SDoc{-temps-}, Maybe SDoc{-externs-})
1589
1590 ppr_decls_AbsC AbsCNop          = returnTE (Nothing, Nothing)
1591
1592 ppr_decls_AbsC (AbsCStmts stmts_1 stmts_2)
1593   = ppr_decls_AbsC stmts_1  `thenTE` \ p1 ->
1594     ppr_decls_AbsC stmts_2  `thenTE` \ p2 ->
1595     returnTE (maybe_vcat [p1, p2])
1596
1597 ppr_decls_AbsC (CSplitMarker) = returnTE (Nothing, Nothing)
1598
1599 ppr_decls_AbsC (CAssign dest source)
1600   = ppr_decls_Amode dest    `thenTE` \ p1 ->
1601     ppr_decls_Amode source  `thenTE` \ p2 ->
1602     returnTE (maybe_vcat [p1, p2])
1603
1604 ppr_decls_AbsC (CJump target) = ppr_decls_Amode target
1605
1606 ppr_decls_AbsC (CFallThrough target) = ppr_decls_Amode target
1607
1608 ppr_decls_AbsC (CReturn target _) = ppr_decls_Amode target
1609
1610 ppr_decls_AbsC (CSwitch discrim alts deflt)
1611   = ppr_decls_Amode discrim     `thenTE` \ pdisc ->
1612     mapTE ppr_alt_stuff alts    `thenTE` \ palts  ->
1613     ppr_decls_AbsC deflt        `thenTE` \ pdeflt ->
1614     returnTE (maybe_vcat (pdisc:pdeflt:palts))
1615   where
1616     ppr_alt_stuff (_, absC) = ppr_decls_AbsC absC
1617
1618 ppr_decls_AbsC (CCodeBlock lbl absC)
1619   = ppr_decls_AbsC absC
1620
1621 ppr_decls_AbsC (CInitHdr cl_info reg_rel cost_centre _)
1622         -- ToDo: strictly speaking, should chk "cost_centre" amode
1623   = labelSeenTE info_lbl     `thenTE` \  label_seen ->
1624     returnTE (Nothing,
1625               if label_seen then
1626                   Nothing
1627               else
1628                   Just (pprExternDecl False{-not in an SRT decl-} info_lbl))
1629   where
1630     info_lbl = infoTableLabelFromCI cl_info
1631
1632 ppr_decls_AbsC (CMachOpStmt res _ args _) = ppr_decls_Amodes (res : args)
1633 ppr_decls_AbsC (COpStmt results _ args _) = ppr_decls_Amodes (results ++ args)
1634
1635 ppr_decls_AbsC (CSimultaneous abc)        = ppr_decls_AbsC abc
1636
1637 ppr_decls_AbsC (CSequential abcs) 
1638   = mapTE ppr_decls_AbsC abcs   `thenTE` \ t_and_e_s ->
1639     returnTE (maybe_vcat t_and_e_s)
1640
1641 ppr_decls_AbsC (CCheck              _ amodes code) = 
1642      ppr_decls_Amodes amodes `thenTE` \p1 ->
1643      ppr_decls_AbsC code     `thenTE` \p2 ->
1644      returnTE (maybe_vcat [p1,p2])
1645
1646 ppr_decls_AbsC (CMacroStmt          _ amodes)   = ppr_decls_Amodes amodes
1647
1648 ppr_decls_AbsC (CCallProfCtrMacro   _ amodes)   = ppr_decls_Amodes [] -- *****!!!
1649   -- you get some nasty re-decls of stdio.h if you compile
1650   -- the prelude while looking inside those amodes;
1651   -- no real reason to, anyway.
1652 ppr_decls_AbsC (CCallProfCCMacro    _ amodes)   = ppr_decls_Amodes amodes
1653
1654 ppr_decls_AbsC (CStaticClosure closure_info cost_centre amodes)
1655         -- ToDo: strictly speaking, should chk "cost_centre" amode
1656   = ppr_decls_Amodes amodes
1657
1658 ppr_decls_AbsC (CClosureInfoAndCode cl_info slow maybe_fast _)
1659   = ppr_decls_Amodes [entry_lbl]                `thenTE` \ p1 ->
1660     ppr_decls_AbsC slow                         `thenTE` \ p2 ->
1661     (case maybe_fast of
1662         Nothing   -> returnTE (Nothing, Nothing)
1663         Just fast -> ppr_decls_AbsC fast)       `thenTE` \ p3 ->
1664     returnTE (maybe_vcat [p1, p2, p3])
1665   where
1666     entry_lbl = CLbl slow_lbl CodePtrRep
1667     slow_lbl    = case (nonemptyAbsC slow) of
1668                     Nothing -> mkErrorStdEntryLabel
1669                     Just _  -> entryLabelFromCI cl_info
1670
1671 ppr_decls_AbsC (CSRT _ closure_lbls)
1672   = mapTE labelSeenTE closure_lbls              `thenTE` \ seen ->
1673     returnTE (Nothing, 
1674               if and seen then Nothing
1675                 else Just (vcat [ pprExternDecl True{-in SRT decl-} l
1676                                 | (l,False) <- zip closure_lbls seen ]))
1677
1678 ppr_decls_AbsC (CRetDirect     _ code _ _)   = ppr_decls_AbsC code
1679 ppr_decls_AbsC (CRetVector _ amodes _ _)     = ppr_decls_Amodes amodes
1680 ppr_decls_AbsC (CModuleInitBlock _ _ code)   = ppr_decls_AbsC code
1681
1682 ppr_decls_AbsC (_) = returnTE (Nothing, Nothing)
1683 \end{code}
1684
1685 \begin{code}
1686 ppr_decls_Amode :: CAddrMode -> TeM (Maybe SDoc, Maybe SDoc)
1687 ppr_decls_Amode (CVal  (CIndex base offset _) _) = ppr_decls_Amodes [base,offset]
1688 ppr_decls_Amode (CAddr (CIndex base offset _))   = ppr_decls_Amodes [base,offset]
1689 ppr_decls_Amode (CVal _ _)      = returnTE (Nothing, Nothing)
1690 ppr_decls_Amode (CAddr _)       = returnTE (Nothing, Nothing)
1691 ppr_decls_Amode (CReg _)        = returnTE (Nothing, Nothing)
1692 ppr_decls_Amode (CLit _)        = returnTE (Nothing, Nothing)
1693
1694 -- CIntLike must be a literal -- no decls
1695 ppr_decls_Amode (CIntLike int)  = returnTE (Nothing, Nothing)
1696
1697 -- CCharLike too
1698 ppr_decls_Amode (CCharLike char) = returnTE (Nothing, Nothing)
1699
1700 -- now, the only place where we actually print temps/externs...
1701 ppr_decls_Amode (CTemp uniq kind)
1702   = case kind of
1703       VoidRep -> returnTE (Nothing, Nothing)
1704       other ->
1705         tempSeenTE uniq `thenTE` \ temp_seen ->
1706         returnTE
1707           (if temp_seen then Nothing else Just (pprTempDecl uniq kind), Nothing)
1708
1709 ppr_decls_Amode (CLbl lbl VoidRep)
1710   = returnTE (Nothing, Nothing)
1711
1712 ppr_decls_Amode (CLbl lbl kind)
1713   = labelSeenTE lbl `thenTE` \ label_seen ->
1714     returnTE (Nothing,
1715               if label_seen then Nothing else Just (pprExternDecl False{-not in an SRT decl-} lbl))
1716
1717 ppr_decls_Amode (CMacroExpr _ _ amodes)
1718   = ppr_decls_Amodes amodes
1719
1720 ppr_decls_Amode other = returnTE (Nothing, Nothing)
1721
1722
1723 maybe_vcat :: [(Maybe SDoc, Maybe SDoc)] -> (Maybe SDoc, Maybe SDoc)
1724 maybe_vcat ps
1725   = case (unzip ps)     of { (ts, es) ->
1726     case (catMaybes ts) of { real_ts  ->
1727     case (catMaybes es) of { real_es  ->
1728     (if (null real_ts) then Nothing else Just (vcat real_ts),
1729      if (null real_es) then Nothing else Just (vcat real_es))
1730     } } }
1731 \end{code}
1732
1733 \begin{code}
1734 ppr_decls_Amodes :: [CAddrMode] -> TeM (Maybe SDoc, Maybe SDoc)
1735 ppr_decls_Amodes amodes
1736   = mapTE ppr_decls_Amode amodes `thenTE` \ ps ->
1737     returnTE ( maybe_vcat ps )
1738 \end{code}
1739
1740 Print out a C Label where you want the *address* of the label, not the
1741 object it refers to.  The distinction is important when the label may
1742 refer to a C structure (info tables and closures, for instance).
1743
1744 When just generating a declaration for the label, use pprCLabel.
1745
1746 \begin{code}
1747 pprCLabelAddr :: CLabel -> SDoc
1748 pprCLabelAddr clabel =
1749   case labelType clabel of
1750      InfoTblType -> addr_of_label
1751      ClosureType -> addr_of_label
1752      VecTblType  -> addr_of_label
1753      _           -> pp_label
1754   where
1755     addr_of_label = ptext SLIT("(P_)&") <> pp_label
1756     pp_label = pprCLabel clabel
1757
1758 \end{code}
1759
1760 -----------------------------------------------------------------------------
1761 Initialising static objects with floating-point numbers.  We can't
1762 just emit the floating point number, because C will cast it to an int
1763 by rounding it.  We want the actual bit-representation of the float.
1764
1765 This is a hack to turn the floating point numbers into ints that we
1766 can safely initialise to static locations.
1767
1768 \begin{code}
1769 big_doubles = (getPrimRepSize DoubleRep) /= 1
1770
1771 #if __GLASGOW_HASKELL__ >= 504
1772 newFloatArray :: (Int,Int) -> ST s (STUArray s Int Float)
1773 newFloatArray = newArray_
1774
1775 newDoubleArray :: (Int,Int) -> ST s (STUArray s Int Double)
1776 newDoubleArray = newArray_
1777
1778 castFloatToIntArray :: STUArray s Int Float -> ST s (STUArray s Int Int)
1779 castFloatToIntArray = castSTUArray
1780
1781 castDoubleToIntArray :: STUArray s Int Double -> ST s (STUArray s Int Int)
1782 castDoubleToIntArray = castSTUArray
1783
1784 writeFloatArray :: STUArray s Int Float -> Int -> Float -> ST s ()
1785 writeFloatArray = writeArray
1786
1787 writeDoubleArray :: STUArray s Int Double -> Int -> Double -> ST s ()
1788 writeDoubleArray = writeArray
1789
1790 readIntArray :: STUArray s Int Int -> Int -> ST s Int
1791 readIntArray = readArray
1792
1793 #else
1794
1795 castFloatToIntArray :: MutableByteArray s t -> ST s (MutableByteArray s t)
1796 castFloatToIntArray = return
1797
1798 castDoubleToIntArray :: MutableByteArray s t -> ST s (MutableByteArray s t)
1799 castDoubleToIntArray = return
1800
1801 #endif
1802
1803 -- floats are always 1 word
1804 floatToWord :: CAddrMode -> CAddrMode
1805 floatToWord (CLit (MachFloat r))
1806   = runST (do
1807         arr <- newFloatArray ((0::Int),0)
1808         writeFloatArray arr 0 (fromRational r)
1809         arr' <- castFloatToIntArray arr
1810         i <- readIntArray arr' 0
1811         return (CLit (MachInt (toInteger i)))
1812     )
1813
1814 doubleToWords :: CAddrMode -> [CAddrMode]
1815 doubleToWords (CLit (MachDouble r))
1816   | big_doubles                         -- doubles are 2 words
1817   = runST (do
1818         arr <- newDoubleArray ((0::Int),1)
1819         writeDoubleArray arr 0 (fromRational r)
1820         arr' <- castDoubleToIntArray arr
1821         i1 <- readIntArray arr' 0
1822         i2 <- readIntArray arr' 1
1823         return [ CLit (MachInt (toInteger i1))
1824                , CLit (MachInt (toInteger i2))
1825                ]
1826     )
1827   | otherwise                           -- doubles are 1 word
1828   = runST (do
1829         arr <- newDoubleArray ((0::Int),0)
1830         writeDoubleArray arr 0 (fromRational r)
1831         arr' <- castDoubleToIntArray arr
1832         i <- readIntArray arr' 0
1833         return [ CLit (MachInt (toInteger i)) ]
1834     )
1835 \end{code}