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