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