2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 %************************************************************************
6 \section[PprAbsC]{Pretty-printing Abstract~C}
8 %************************************************************************
18 #include "HsVersions.h"
25 import AbsCUtils ( getAmodeRep, nonemptyAbsC,
26 mixedPtrLocn, mixedTypeLocn
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
38 import CmdLineOpts ( opt_SccProfilingOn, opt_GranMacros )
39 import CostCentre ( pprCostCentreDecl, pprCostCentreStackDecl )
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
58 import StgSyn ( StgOp(..) )
59 import BitSet ( BitSet, intBS )
62 import Util ( lengthExceeds, listLengthCmp )
64 #if __GLASGOW_HASKELL__ >= 504
74 For spitting out the costs of an abstract~C expression, @writeRealC@
75 now not only prints the C~code of the @absC@ arg but also adds a macro
76 call to a cost evaluation function @GRAN_EXEC@. For that,
77 @pprAbsC@ has a new ``costs'' argument. %% HWL
81 writeRealC :: Handle -> AbstractC -> IO ()
82 writeRealC handle absC
83 -- avoid holding on to the whole of absC in the !Gransim case.
85 then printForCFast fp (pprAbsC absC (costs absC))
86 else printForCFast fp (pprAbsC absC (panic "costs"))
87 --printForC handle (pprAbsC absC (panic "costs"))
88 dumpRealC :: AbstractC -> SDoc
89 dumpRealC absC = pprAbsC absC (costs absC)
92 writeRealC :: Handle -> AbstractC -> IO ()
93 --writeRealC handle absC =
95 -- printDoc LeftMode handle (pprAbsC absC (costs absC))
97 writeRealC handle absC
98 | opt_GranMacros = _scc_ "writeRealC" printForC handle $
99 pprCode CStyle (pprAbsC absC (costs absC))
100 | otherwise = _scc_ "writeRealC" printForC handle $
101 pprCode CStyle (pprAbsC absC (panic "costs"))
103 dumpRealC :: AbstractC -> SDoc
105 | opt_GranMacros = pprCode CStyle (pprAbsC absC (costs absC))
106 | otherwise = pprCode CStyle (pprAbsC absC (panic "costs"))
110 This emits the macro, which is used in GrAnSim to compute the total costs
111 from a cost 5 tuple. %% HWL
114 emitMacro :: CostRes -> SDoc
116 emitMacro _ | not opt_GranMacros = empty
118 emitMacro (Cost (i,b,l,s,f))
119 = hcat [ ptext SLIT("GRAN_EXEC"), char '(',
120 int i, comma, int b, comma, int l, comma,
121 int s, comma, int f, pp_paren_semi ]
123 pp_paren_semi = text ");"
126 New type: Now pprAbsC also takes the costs for evaluating the Abstract C
127 code as an argument (that's needed when spitting out the GRAN_EXEC macro
128 which must be done before the return i.e. inside absC code) HWL
131 pprAbsC :: AbstractC -> CostRes -> SDoc
132 pprAbsC AbsCNop _ = empty
133 pprAbsC (AbsCStmts s1 s2) c = ($$) (pprAbsC s1 c) (pprAbsC s2 c)
135 pprAbsC (CAssign dest src) _ = pprAssign (getAmodeRep dest) dest src
137 pprAbsC (CJump target) c
138 = ($$) (hcat [emitMacro c {-WDP:, text "/* <--++ CJump */"-} ])
139 (hcat [ text jmp_lit, pprAmode target, pp_paren_semi ])
141 pprAbsC (CFallThrough target) c
142 = ($$) (hcat [emitMacro c {-WDP:, text "/* <--++ CFallThrough */"-} ])
143 (hcat [ text jmp_lit, pprAmode target, pp_paren_semi ])
145 -- --------------------------------------------------------------------------
146 -- Spit out GRAN_EXEC macro immediately before the return HWL
148 pprAbsC (CReturn am return_info) c
149 = ($$) (hcat [emitMacro c {-WDP:, text "/* <---- CReturn */"-} ])
150 (hcat [text jmp_lit, target, pp_paren_semi ])
152 target = case return_info of
153 DirectReturn -> hcat [ptext SLIT("ENTRY_CODE"), lparen,
155 DynamicVectoredReturn am' -> mk_vector (pprAmode am')
156 StaticVectoredReturn n -> mk_vector (int n) -- Always positive
157 mk_vector x = hcat [ptext SLIT("RET_VEC"), char '(', pprAmode am, comma,
160 pprAbsC (CSplitMarker) _ = ptext SLIT("__STG_SPLIT_MARKER")
162 -- we optimise various degenerate cases of CSwitches.
164 -- --------------------------------------------------------------------------
165 -- Assume: CSwitch is also end of basic block
166 -- costs function yields nullCosts for whole switch
167 -- ==> inherited costs c are those of basic block up to switch
168 -- ==> inherit c + costs for the corresponding branch
170 -- --------------------------------------------------------------------------
172 pprAbsC (CSwitch discrim [] deflt) c
173 = pprAbsC deflt (c + costs deflt)
174 -- Empty alternative list => no costs for discrim as nothing cond. here HWL
176 pprAbsC (CSwitch discrim [(tag,alt_code)] deflt) c -- only one alt
177 = case (nonemptyAbsC deflt) of
178 Nothing -> -- one alt and no default
179 pprAbsC alt_code (c + costs alt_code)
180 -- Nothing conditional in here either HWL
182 Just dc -> -- make it an "if"
183 do_if_stmt discrim tag alt_code dc c
185 -- What problem is the re-ordering trying to solve ?
186 pprAbsC (CSwitch discrim [(tag1@(MachInt i1), alt_code1),
187 (tag2@(MachInt i2), alt_code2)] deflt) c
188 | empty_deflt && ((i1 == 0 && i2 == 1) || (i1 == 1 && i2 == 0))
190 do_if_stmt discrim tag1 alt_code1 alt_code2 c
192 do_if_stmt discrim tag2 alt_code2 alt_code1 c
194 empty_deflt = not (maybeToBool (nonemptyAbsC deflt))
196 pprAbsC (CSwitch discrim alts deflt) c -- general case
197 | isFloatingRep (getAmodeRep discrim)
198 = pprAbsC (foldr ( \ a -> CSwitch discrim [a]) deflt alts) c
201 hcat [text "switch (", pp_discrim, text ") {"],
202 nest 2 (vcat (map ppr_alt alts)),
203 (case (nonemptyAbsC deflt) of
206 nest 2 (vcat [ptext SLIT("default:"),
207 pprAbsC dc (c + switch_head_cost
209 ptext SLIT("break;")])),
216 = vcat [ hcat [ptext SLIT("case "), pprBasicLit lit, char ':'],
217 nest 2 (($$) (pprAbsC absC (c + switch_head_cost + costs absC))
218 (ptext SLIT("break;"))) ]
220 -- Costs for addressing header of switch and cond. branching -- HWL
221 switch_head_cost = addrModeCosts discrim Rhs + (Cost (0, 1, 0, 0, 0))
223 pprAbsC stmt@(COpStmt results (StgFCallOp fcall uniq) args vol_regs) _
224 = pprFCall fcall uniq args results vol_regs
226 pprAbsC stmt@(COpStmt results (StgPrimOp op) args vol_regs) _
228 non_void_args = grab_non_void_amodes args
229 non_void_results = grab_non_void_amodes results
230 -- if just one result, we print in the obvious "assignment" style;
231 -- if 0 or many results, we emit a macro call, w/ the results
232 -- followed by the arguments. The macro presumably knows which
235 the_op = ppr_op_call non_void_results non_void_args
236 -- liveness mask is *in* the non_void_args
238 if primOpNeedsWrapper op then
239 case (ppr_vol_regs vol_regs) of { (pp_saves, pp_restores) ->
248 ppr_op_call results args
249 = hcat [ ppr op, lparen,
250 hcat (punctuate comma (map ppr_op_result results)),
251 if null results || null args then empty else comma,
252 hcat (punctuate comma (map pprAmode args)),
255 ppr_op_result r = ppr_amode r
256 -- primop macros do their own casting of result;
257 -- hence we can toss the provided cast...
259 -- NEW CASES FOR EXPANDED PRIMOPS
261 pprAbsC stmt@(CMachOpStmt res mop [arg1,arg2] maybe_vols) _
262 = let prefix_fn = mop `elem` [MO_Dbl_Pwr, MO_Flt_Pwr, MO_NatS_MulMayOflo]
264 case ppr_maybe_vol_regs maybe_vols of {(saves,restores) ->
267 [ppr_amode res, equals]
269 then [pprMachOp_for_C mop, parens (pprAmode arg1 <> comma <> pprAmode arg2)]
270 else [pprAmode arg1, pprMachOp_for_C mop, pprAmode arg2])
276 pprAbsC stmt@(CMachOpStmt res mop [arg1] maybe_vols) _
277 = case ppr_maybe_vol_regs maybe_vols of {(saves,restores) ->
279 hcat [ppr_amode res, equals,
280 pprMachOp_for_C mop, parens (pprAmode arg1),
285 pprAbsC stmt@(CSequential stuff) c
286 = vcat (map (flip pprAbsC c) stuff)
288 -- end of NEW CASES FOR EXPANDED PRIMOPS
290 pprAbsC stmt@(CSRT lbl closures) c
291 = case (pprTempAndExternDecls stmt) of { (_, pp_exts) ->
293 $$ ptext SLIT("SRT") <> lparen <> pprCLabel lbl <> rparen
294 $$ nest 2 (hcat (punctuate comma (map pp_closure_lbl closures)))
298 pprAbsC stmt@(CBitmap lbl mask) c
299 = pp_bitmap_switch mask semi $
300 hcat [ ptext SLIT("BITMAP"), lparen,
301 pprCLabel lbl, comma,
302 int (length mask), comma,
303 pp_bitmap mask, rparen ]
305 pprAbsC (CSimultaneous abs_c) c
306 = hcat [ptext SLIT("{{"), pprAbsC abs_c c, ptext SLIT("}}")]
308 pprAbsC (CCheck macro as code) c
309 = hcat [ptext (cCheckMacroText macro), lparen,
310 hcat (punctuate comma (map ppr_amode as)), comma,
311 pprAbsC code c, pp_paren_semi
313 pprAbsC (CMacroStmt macro as) _
314 = hcat [ptext (cStmtMacroText macro), lparen,
315 hcat (punctuate comma (map ppr_amode as)),pp_paren_semi] -- no casting
316 pprAbsC (CCallProfCtrMacro op as) _
317 = hcat [ftext op, lparen,
318 hcat (punctuate comma (map ppr_amode as)),pp_paren_semi]
319 pprAbsC (CCallProfCCMacro op as) _
320 = hcat [ftext op, lparen,
321 hcat (punctuate comma (map ppr_amode as)),pp_paren_semi]
322 pprAbsC stmt@(CCallTypedef is_tdef (CCallSpec op_str cconv _) uniq results args) _
323 = hsep [ ptext (if is_tdef then SLIT("typedef") else SLIT("extern"))
326 , parens (hsep (punctuate comma ccall_decl_ty_args))
330 In the non-casm case, to ensure that we're entering the given external
331 entry point using the correct calling convention, we have to do the following:
333 - When entering via a function pointer (the `dynamic' case) using the specified
334 calling convention, we emit a typedefn declaration attributed with the
335 calling convention to use together with the result and parameter types we're
336 assuming. Coerce the function pointer to this type and go.
338 - to enter the function at a given code label, we emit an extern declaration
339 for the label here, stating the calling convention together with result and
340 argument types we're assuming.
342 The C compiler will hopefully use this extern declaration to good effect,
343 reporting any discrepancies between our extern decl and any other that
346 Re: calling convention, notice that gcc (2.8.1 and egcs-1.0.2) will for
347 the external function `foo' use the calling convention of the first `foo'
348 prototype it encounters (nor does it complain about conflicting attribute
349 declarations). The consequence of this is that you cannot override the
350 calling convention of `foo' using an extern declaration (you'd have to use
351 a typedef), but why you would want to do such a thing in the first place
352 is totally beyond me.
354 ToDo: petition the gcc folks to add code to warn about conflicting attribute
360 | is_tdef = parens (text (ccallConvAttribute cconv) <+> char '*' <> ccall_fun_ty)
361 | otherwise = text (ccallConvAttribute cconv) <+> ccall_fun_ty
365 DynamicTarget -> ptext SLIT("_ccall_fun_ty") <> ppr uniq
366 StaticTarget x -> pprCLabelString x
369 case non_void_results of
370 [] -> ptext SLIT("void")
371 [amode] -> ppr (getAmodeRep amode)
372 _ -> panic "pprAbsC{CCallTypedef}: ccall_res_ty"
375 | is_tdef = tail ccall_arg_tys
376 | otherwise = ccall_arg_tys
378 ccall_arg_tys = map (ppr . getAmodeRep) non_void_args
380 -- the first argument will be the "I/O world" token (a VoidRep)
381 -- all others should be non-void
384 in ASSERT (all non_void nvas) nvas
386 -- there will usually be two results: a (void) state which we
387 -- should ignore and a (possibly void) result.
389 let nvrs = grab_non_void_amodes results
390 in ASSERT (listLengthCmp nvrs 1 /= GT) nvrs
392 pprAbsC (CCodeBlock lbl abs_C) _
393 = if not (maybeToBool(nonemptyAbsC abs_C)) then
394 pprTrace "pprAbsC: curious empty code block for" (pprCLabel lbl) empty
396 case (pprTempAndExternDecls abs_C) of { (pp_temps, pp_exts) ->
400 hcat [text (if (externallyVisibleCLabel lbl)
401 then "FN_(" -- abbreviations to save on output
403 pprCLabel lbl, text ") {"],
407 nest 8 (ptext SLIT("FB_")),
408 nest 8 (pprAbsC abs_C (costs abs_C)),
409 nest 8 (ptext SLIT("FE_")),
415 pprAbsC (CInitHdr cl_info amode cost_centre size) _
416 = hcat [ ptext SLIT("SET_HDR_"), char '(',
417 ppr_amode amode, comma,
418 pprCLabelAddr info_lbl, comma,
419 if_profiling (pprAmode cost_centre), comma,
420 if_profiling (int size),
423 info_lbl = infoTableLabelFromCI cl_info
426 pprAbsC stmt@(CStaticClosure cl_info cost_centre amodes) _
427 = case (pprTempAndExternDecls stmt) of { (_, pp_exts) ->
431 ptext SLIT("SET_STATIC_HDR"), char '(',
432 pprCLabel closure_lbl, comma,
433 pprCLabel info_lbl, comma,
434 if_profiling (pprAmode cost_centre), comma,
435 ppLocalness closure_lbl, comma,
436 ppLocalnessMacro True{-include dyn-} info_lbl,
439 nest 2 (ppr_payload amodes),
443 closure_lbl = closureLabelFromCI cl_info
444 info_lbl = infoTableLabelFromCI cl_info
446 ppr_payload [] = empty
449 (braces $ hsep $ punctuate comma $
450 map (text "(L_)" <>) (foldr ppr_item [] ls))
453 | rep == VoidRep = rest
454 | rep == FloatRep = ppr_amode (floatToWord item) : rest
455 | rep == DoubleRep = map ppr_amode (doubleToWords item) ++ rest
456 | otherwise = ppr_amode item : rest
458 rep = getAmodeRep item
461 pprAbsC stmt@(CClosureInfoAndCode cl_info slow maybe_fast cl_descr) _
464 ptext SLIT("INFO_TABLE"),
465 ( if is_selector then
466 ptext SLIT("_SELECTOR")
467 else if is_constr then
468 ptext SLIT("_CONSTR")
469 else if needs_srt then
471 else empty ), char '(',
473 pprCLabel info_lbl, comma,
474 pprCLabel slow_lbl, comma,
475 pp_rest, {- ptrs,nptrs,[srt,]type,-} comma,
477 ppLocalness info_lbl, comma,
478 ppLocalnessMacro True{-include dyn-} slow_lbl, comma,
480 if_profiling pp_descr, comma,
481 if_profiling pp_type,
487 Just fast -> let stuff = CCodeBlock fast_lbl fast in
488 pprAbsC stuff (costs stuff)
491 info_lbl = infoTableLabelFromCI cl_info
492 fast_lbl = fastLabelFromCI cl_info
495 = case (nonemptyAbsC slow) of
496 Nothing -> (mkErrorStdEntryLabel, empty)
497 Just xx -> (entryLabelFromCI cl_info,
498 let stuff = CCodeBlock slow_lbl xx in
499 pprAbsC stuff (costs stuff))
501 maybe_selector = maybeSelectorInfo cl_info
502 is_selector = maybeToBool maybe_selector
503 (Just select_word_i) = maybe_selector
505 maybe_tag = closureSemiTag cl_info
506 is_constr = maybeToBool maybe_tag
507 (Just tag) = maybe_tag
509 srt = closureSRT cl_info
510 needs_srt = case srt of
515 size = closureNonHdrSize cl_info
517 ptrs = closurePtrsSize cl_info
520 pp_rest | is_selector = int select_word_i
525 hcat [ int tag, comma ]
526 else if needs_srt then
531 type_str = pprSMRep (closureSMRep cl_info)
533 pp_descr = pprStringInCStyle cl_descr
534 pp_type = pprStringInCStyle (closureTypeDescr cl_info)
536 pprAbsC stmt@(CClosureTbl tycon) _
538 ptext SLIT("CLOSURE_TBL") <>
539 lparen <> pprCLabel (mkClosureTblLabel tycon) <> rparen :
541 map (pp_closure_lbl . mkClosureLabel . getName . dataConWrapId) (tyConDataCons tycon)
543 ) $$ ptext SLIT("};")
545 pprAbsC stmt@(CRetDirect uniq code srt liveness) _
548 ptext SLIT("INFO_TABLE_SRT_BITMAP"), lparen,
549 pprCLabel info_lbl, comma,
550 pprCLabel entry_lbl, comma,
551 pp_liveness liveness, comma, -- bitmap
552 pp_srt_info srt, -- SRT
553 closure_type, comma, -- closure type
554 ppLocalness info_lbl, comma, -- info table storage class
555 ppLocalnessMacro True{-include dyn-} entry_lbl, comma, -- entry pt storage class
562 info_lbl = mkReturnInfoLabel uniq
563 entry_lbl = mkReturnPtLabel uniq
565 pp_code = let stuff = CCodeBlock entry_lbl code in
566 pprAbsC stuff (costs stuff)
568 closure_type = pp_liveness_switch liveness
569 (ptext SLIT("RET_SMALL"))
570 (ptext SLIT("RET_BIG"))
572 pprAbsC stmt@(CRetVector lbl amodes srt liveness) _
573 = case (pprTempAndExternDecls stmt) of { (_, pp_exts) ->
577 ptext SLIT("VEC_INFO_") <> int size,
579 pprCLabel lbl, comma,
580 pp_liveness liveness, comma, -- bitmap liveness mask
581 pp_srt_info srt, -- SRT
583 ppLocalness lbl, comma
585 nest 2 (sep (punctuate comma (map ppr_item amodes))),
591 ppr_item item = (<>) (text "(F_) ") (ppr_amode item)
594 closure_type = pp_liveness_switch liveness
595 (ptext SLIT("RET_VEC_SMALL"))
596 (ptext SLIT("RET_VEC_BIG"))
599 pprAbsC stmt@(CModuleInitBlock plain_lbl lbl code) _
601 ptext SLIT("START_MOD_INIT") <>
602 parens (pprCLabel plain_lbl <> comma <> pprCLabel lbl),
603 case (pprTempAndExternDecls stmt) of { (_, pp_exts) -> pp_exts },
604 pprAbsC code (costs code),
605 hcat [ptext SLIT("END_MOD_INIT"), lparen, rparen]
608 pprAbsC (CCostCentreDecl is_local cc) _ = pprCostCentreDecl is_local cc
609 pprAbsC (CCostCentreStackDecl ccs) _ = pprCostCentreStackDecl ccs
613 -- Print a CMachOp in a way suitable for emitting via C.
614 pprMachOp_for_C MO_Nat_Add = char '+'
615 pprMachOp_for_C MO_Nat_Sub = char '-'
616 pprMachOp_for_C MO_Nat_Eq = text "=="
617 pprMachOp_for_C MO_Nat_Ne = text "!="
619 pprMachOp_for_C MO_NatS_Ge = text ">="
620 pprMachOp_for_C MO_NatS_Le = text "<="
621 pprMachOp_for_C MO_NatS_Gt = text ">"
622 pprMachOp_for_C MO_NatS_Lt = text "<"
624 pprMachOp_for_C MO_NatU_Ge = text ">="
625 pprMachOp_for_C MO_NatU_Le = text "<="
626 pprMachOp_for_C MO_NatU_Gt = text ">"
627 pprMachOp_for_C MO_NatU_Lt = text "<"
629 pprMachOp_for_C MO_NatS_Mul = char '*'
630 pprMachOp_for_C MO_NatS_MulMayOflo = text "mulIntMayOflo"
631 pprMachOp_for_C MO_NatS_Quot = char '/'
632 pprMachOp_for_C MO_NatS_Rem = char '%'
633 pprMachOp_for_C MO_NatS_Neg = char '-'
635 pprMachOp_for_C MO_NatU_Mul = char '*'
636 pprMachOp_for_C MO_NatU_Quot = char '/'
637 pprMachOp_for_C MO_NatU_Rem = char '%'
639 pprMachOp_for_C MO_Nat_And = text "&"
640 pprMachOp_for_C MO_Nat_Or = text "|"
641 pprMachOp_for_C MO_Nat_Xor = text "^"
642 pprMachOp_for_C MO_Nat_Not = text "~"
643 pprMachOp_for_C MO_Nat_Shl = text "<<"
644 pprMachOp_for_C MO_Nat_Shr = text ">>"
645 pprMachOp_for_C MO_Nat_Sar = text ">>"
647 pprMachOp_for_C MO_32U_Eq = text "=="
648 pprMachOp_for_C MO_32U_Ne = text "!="
649 pprMachOp_for_C MO_32U_Ge = text ">="
650 pprMachOp_for_C MO_32U_Le = text "<="
651 pprMachOp_for_C MO_32U_Gt = text ">"
652 pprMachOp_for_C MO_32U_Lt = text "<"
654 pprMachOp_for_C MO_Dbl_Eq = text "=="
655 pprMachOp_for_C MO_Dbl_Ne = text "!="
656 pprMachOp_for_C MO_Dbl_Ge = text ">="
657 pprMachOp_for_C MO_Dbl_Le = text "<="
658 pprMachOp_for_C MO_Dbl_Gt = text ">"
659 pprMachOp_for_C MO_Dbl_Lt = text "<"
661 pprMachOp_for_C MO_Dbl_Add = text "+"
662 pprMachOp_for_C MO_Dbl_Sub = text "-"
663 pprMachOp_for_C MO_Dbl_Mul = text "*"
664 pprMachOp_for_C MO_Dbl_Div = text "/"
665 pprMachOp_for_C MO_Dbl_Pwr = text "pow"
667 pprMachOp_for_C MO_Dbl_Sin = text "sin"
668 pprMachOp_for_C MO_Dbl_Cos = text "cos"
669 pprMachOp_for_C MO_Dbl_Tan = text "tan"
670 pprMachOp_for_C MO_Dbl_Sinh = text "sinh"
671 pprMachOp_for_C MO_Dbl_Cosh = text "cosh"
672 pprMachOp_for_C MO_Dbl_Tanh = text "tanh"
673 pprMachOp_for_C MO_Dbl_Asin = text "asin"
674 pprMachOp_for_C MO_Dbl_Acos = text "acos"
675 pprMachOp_for_C MO_Dbl_Atan = text "atan"
676 pprMachOp_for_C MO_Dbl_Log = text "log"
677 pprMachOp_for_C MO_Dbl_Exp = text "exp"
678 pprMachOp_for_C MO_Dbl_Sqrt = text "sqrt"
679 pprMachOp_for_C MO_Dbl_Neg = text "-"
681 pprMachOp_for_C MO_Flt_Add = text "+"
682 pprMachOp_for_C MO_Flt_Sub = text "-"
683 pprMachOp_for_C MO_Flt_Mul = text "*"
684 pprMachOp_for_C MO_Flt_Div = text "/"
685 pprMachOp_for_C MO_Flt_Pwr = text "pow"
687 pprMachOp_for_C MO_Flt_Eq = text "=="
688 pprMachOp_for_C MO_Flt_Ne = text "!="
689 pprMachOp_for_C MO_Flt_Ge = text ">="
690 pprMachOp_for_C MO_Flt_Le = text "<="
691 pprMachOp_for_C MO_Flt_Gt = text ">"
692 pprMachOp_for_C MO_Flt_Lt = text "<"
694 pprMachOp_for_C MO_Flt_Sin = text "sin"
695 pprMachOp_for_C MO_Flt_Cos = text "cos"
696 pprMachOp_for_C MO_Flt_Tan = text "tan"
697 pprMachOp_for_C MO_Flt_Sinh = text "sinh"
698 pprMachOp_for_C MO_Flt_Cosh = text "cosh"
699 pprMachOp_for_C MO_Flt_Tanh = text "tanh"
700 pprMachOp_for_C MO_Flt_Asin = text "asin"
701 pprMachOp_for_C MO_Flt_Acos = text "acos"
702 pprMachOp_for_C MO_Flt_Atan = text "atan"
703 pprMachOp_for_C MO_Flt_Log = text "log"
704 pprMachOp_for_C MO_Flt_Exp = text "exp"
705 pprMachOp_for_C MO_Flt_Sqrt = text "sqrt"
706 pprMachOp_for_C MO_Flt_Neg = text "-"
708 pprMachOp_for_C MO_32U_to_NatS = text "(StgInt)"
709 pprMachOp_for_C MO_NatS_to_32U = text "(StgWord32)"
711 pprMachOp_for_C MO_NatS_to_Dbl = text "(StgDouble)"
712 pprMachOp_for_C MO_Dbl_to_NatS = text "(StgInt)"
714 pprMachOp_for_C MO_NatS_to_Flt = text "(StgFloat)"
715 pprMachOp_for_C MO_Flt_to_NatS = text "(StgInt)"
717 pprMachOp_for_C MO_NatS_to_NatU = text "(StgWord)"
718 pprMachOp_for_C MO_NatU_to_NatS = text "(StgInt)"
720 pprMachOp_for_C MO_NatS_to_NatP = text "(void*)"
721 pprMachOp_for_C MO_NatP_to_NatS = text "(StgInt)"
722 pprMachOp_for_C MO_NatU_to_NatP = text "(void*)"
723 pprMachOp_for_C MO_NatP_to_NatU = text "(StgWord)"
725 pprMachOp_for_C MO_Dbl_to_Flt = text "(StgFloat)"
726 pprMachOp_for_C MO_Flt_to_Dbl = text "(StgDouble)"
728 pprMachOp_for_C MO_8S_to_NatS = text "(StgInt8)(StgInt)"
729 pprMachOp_for_C MO_16S_to_NatS = text "(StgInt16)(StgInt)"
730 pprMachOp_for_C MO_32S_to_NatS = text "(StgInt32)(StgInt)"
732 pprMachOp_for_C MO_8U_to_NatU = text "(StgWord8)(StgWord)"
733 pprMachOp_for_C MO_16U_to_NatU = text "(StgWord16)(StgWord)"
734 pprMachOp_for_C MO_32U_to_NatU = text "(StgWord32)(StgWord)"
736 pprMachOp_for_C MO_8U_to_32U = text "(StgWord32)"
737 pprMachOp_for_C MO_32U_to_8U = text "(StgWord8)"
741 = if (externallyVisibleCLabel lbl)
743 else ptext SLIT("static ")
745 -- Horrible macros for declaring the types and locality of labels (see
748 ppLocalnessMacro include_dyn_prefix clabel =
753 ClosureType -> ptext SLIT("C_")
754 CodeType -> ptext SLIT("F_")
755 InfoTblType -> ptext SLIT("I_")
756 ClosureTblType -> ptext SLIT("CP_")
757 DataType -> ptext SLIT("D_")
760 is_visible = externallyVisibleCLabel clabel
761 label_type = labelType clabel
764 | is_visible = char 'E'
765 | otherwise = char 'I'
768 | include_dyn_prefix && labelDynamic clabel = char 'D'
776 grab_non_void_amodes amodes
777 = filter non_void amodes
780 = case (getAmodeRep amode) of
786 ppr_maybe_vol_regs :: Maybe [MagicId] -> (SDoc, SDoc)
787 ppr_maybe_vol_regs Nothing
789 ppr_maybe_vol_regs (Just vrs)
790 = case ppr_vol_regs vrs of
792 -> (pp_basic_saves $$ saves,
793 pp_basic_restores $$ restores)
795 ppr_vol_regs :: [MagicId] -> (SDoc, SDoc)
797 ppr_vol_regs [] = (empty, empty)
798 ppr_vol_regs (VoidReg:rs) = ppr_vol_regs rs
800 = let pp_reg = case r of
801 VanillaReg pk n -> pprVanillaReg n
803 (more_saves, more_restores) = ppr_vol_regs rs
805 (($$) ((<>) (ptext SLIT("CALLER_SAVE_")) pp_reg) more_saves,
806 ($$) ((<>) (ptext SLIT("CALLER_RESTORE_")) pp_reg) more_restores)
808 -- pp_basic_{saves,restores}: The BaseReg, Sp, Su, Hp and
809 -- HpLim (see StgRegs.lh) may need to be saved/restored around CCalls,
810 -- depending on the platform. (The "volatile regs" stuff handles all
811 -- other registers.) Just be *sure* BaseReg is OK before trying to do
812 -- anything else. The correct sequence of saves&restores are
813 -- encoded by the CALLER_*_SYSTEM macros.
814 pp_basic_saves = ptext SLIT("CALLER_SAVE_SYSTEM")
815 pp_basic_restores = ptext SLIT("CALLER_RESTORE_SYSTEM")
819 pp_srt_info NoC_SRT = hcat [ int 0, comma,
822 pp_srt_info (C_SRT lbl off len) = hcat [ pprCLabel lbl, comma,
829 | labelDynamic lbl = text "DLL_SRT_ENTRY" <> parens (pprCLabel lbl)
830 | otherwise = char '&' <> pprCLabel lbl
835 = if opt_SccProfilingOn
837 else char '0' -- leave it out!
838 -- ---------------------------------------------------------------------------
839 -- Changes for GrAnSim:
840 -- draw costs for computation in head of if into both branches;
841 -- as no abstractC data structure is given for the head, one is constructed
842 -- guessing unknown values and fed into the costs function
843 -- ---------------------------------------------------------------------------
845 do_if_stmt discrim tag alt_code deflt c
847 cond = hcat [ pprAmode discrim
850 , pprAmode (CLit tag)
852 -- to be absolutely sure that none of the
853 -- conversion rules hit, e.g.,
855 -- minInt is different to (int)minInt
857 -- in C (when minInt is a number not a constant
858 -- expression which evaluates to it.)
861 MachInt _ -> ptext SLIT("(I_)")
866 (addrModeCosts discrim Rhs) c
868 ppr_if_stmt pp_pred then_part else_part discrim_costs c
870 hcat [text "if (", pp_pred, text ") {"],
871 nest 8 (pprAbsC then_part (c + discrim_costs +
872 (Cost (0, 2, 0, 0, 0)) +
874 (case nonemptyAbsC else_part of Nothing -> empty; Just _ -> text "} else {"),
875 nest 8 (pprAbsC else_part (c + discrim_costs +
876 (Cost (0, 1, 0, 0, 0)) +
879 {- Total costs = inherited costs (before if) + costs for accessing discrim
880 + costs for cond branch ( = (0, 1, 0, 0, 0) )
881 + costs for that alternative
885 Historical note: this used to be two separate cases -- one for `ccall'
886 and one for `casm'. To get round a potential limitation to only 10
887 arguments, the numbering of arguments in @process_casm@ was beefed up a
890 Some rough notes on generating code for @CCallOp@:
892 1) Evaluate all arguments and stuff them into registers. (done elsewhere)
893 2) Save any essential registers (heap, stack, etc).
895 ToDo: If stable pointers are in use, these must be saved in a place
896 where the runtime system can get at them so that the Stg world can
897 be restarted during the call.
899 3) Save any temporary registers that are currently in use.
900 4) Do the call, putting result into a local variable
901 5) Restore essential registers
902 6) Restore temporaries
904 (This happens after restoration of essential registers because we
905 might need the @Base@ register to access all the others correctly.)
907 Otherwise, copy local variable into result register.
909 8) If ccall (not casm), declare the function being called as extern so
910 that C knows if it returns anything other than an int.
913 { ResultType _ccall_result;
916 _ccall_result = f( args );
920 return_reg = _ccall_result;
924 Amendment to the above: if we can GC, we have to:
926 * make sure we save all our registers away where the garbage collector
928 * be sure that there are no live registers or we're in trouble.
929 (This can cause problems if you try something foolish like passing
930 an array or a foreign obj to a _ccall_GC_ thing.)
931 * increment/decrement the @inCCallGC@ counter before/after the call so
932 that the runtime check that PerformGC is being used sensibly will work.
935 pprFCall call@(CCall (CCallSpec target cconv safety)) uniq args results vol_regs
938 declare_local_vars, -- local var for *result*
939 vcat local_arg_decls,
941 process_casm local_vars pp_non_void_args call_str,
947 (pp_saves, pp_restores) = ppr_vol_regs vol_regs
949 thread_macro_args = ppr_uniq_token <> comma <+>
950 text "rts" <> ppr (playThreadSafe safety)
951 ppr_uniq_token = text "tok_" <> ppr uniq
952 (pp_save_context, pp_restore_context)
953 | playSafe safety = ( text "{ I_" <+> ppr_uniq_token <>
954 text "; SUSPEND_THREAD" <> parens thread_macro_args <> semi
955 , text "RESUME_THREAD" <> parens thread_macro_args <> text ";}"
957 | otherwise = ( pp_basic_saves $$ pp_saves,
958 pp_basic_restores $$ pp_restores)
962 in ASSERT2 ( all non_void nvas, ppr call <+> hsep (map pprAmode args) )
964 -- the last argument will be the "I/O world" token (a VoidRep)
965 -- all others should be non-void
968 let nvrs = grab_non_void_amodes results
969 in ASSERT (listLengthCmp nvrs 1 /= GT) nvrs
970 -- there will usually be two results: a (void) state which we
971 -- should ignore and a (possibly void) result.
973 (local_arg_decls, pp_non_void_args)
974 = unzip [ ppr_casm_arg a i | (a,i) <- non_void_args `zip` [1..] ]
976 (declare_local_vars, local_vars, assign_results)
977 = ppr_casm_results non_void_results
979 call_str = case target of
980 CasmTarget str -> unpackFS str
981 StaticTarget fn -> mk_ccall_str (pprCLabelString fn) ccall_args
982 DynamicTarget -> mk_ccall_str dyn_fun (tail ccall_args)
984 ccall_args = zipWith (\ _ i -> char '%' <> int i) non_void_args [0..]
985 dyn_fun = parens (parens (ptext SLIT("_ccall_fun_ty") <> ppr uniq) <> text "%0")
988 -- Remainder only used for ccall
989 mk_ccall_str fun_name ccall_fun_args = showSDoc
991 if null non_void_results
994 lparen, fun_name, lparen,
995 hcat (punctuate comma ccall_fun_args),
1000 ppr_casm_arg :: CAddrMode -> Int -> (SDoc, SDoc)
1001 -- (a) decl and assignment, (b) local var to be used later
1003 ppr_casm_arg amode a_num
1005 a_kind = getAmodeRep amode
1006 pp_amode = pprAmode amode
1007 pp_kind = pprPrimKind a_kind
1009 local_var = (<>) (ptext SLIT("_ccall_arg")) (int a_num)
1012 = hcat [ pp_kind, space, local_var, equals, pp_amode, semi ]
1014 (declare_local_var, local_var)
1017 For l-values, the critical questions are:
1019 1) Are there any results at all?
1021 We only allow zero or one results.
1025 :: [CAddrMode] -- list of results (length <= 1)
1027 ( SDoc, -- declaration of any local vars
1028 [SDoc], -- list of result vars (same length as results)
1029 SDoc ) -- assignment (if any) of results in local var to registers
1032 = (empty, [], empty) -- no results
1034 ppr_casm_results [r]
1036 result_reg = ppr_amode r
1037 r_kind = getAmodeRep r
1039 local_var = ptext SLIT("_ccall_result")
1041 (result_type, assign_result)
1042 = (pprPrimKind r_kind,
1043 hcat [ result_reg, equals, local_var, semi ])
1045 declare_local_var = hcat [ result_type, space, local_var, semi ]
1047 (declare_local_var, [local_var], assign_result)
1050 = panic "ppr_casm_results: ccall/casm with many results"
1054 Note the sneaky way _the_ result is represented by a list so that we
1055 can complain if it's used twice.
1057 ToDo: Any chance of giving line numbers when process-casm fails?
1058 Or maybe we should do a check _much earlier_ in compiler. ADR
1061 process_casm :: [SDoc] -- results (length <= 1)
1062 -> [SDoc] -- arguments
1063 -> String -- format string (with embedded %'s)
1064 -> SDoc -- code being generated
1066 process_casm results args string = process results args string
1068 process [] _ "" = empty
1069 process (_:_) _ "" = error ("process_casm: non-void result not assigned while processing _casm_ \"" ++
1071 "\"\n(Try changing result type to IO ()\n")
1073 process ress args ('%':cs)
1076 error ("process_casm: lonely % while processing _casm_ \"" ++ string ++ "\".\n")
1079 char '%' <> process ress args css
1083 [] -> error ("process_casm: no result to match %r while processing _casm_ \"" ++ string ++ "\".\nTry deleting %r or changing result type from PrimIO ()\n")
1084 [r] -> r <> (process [] args css)
1085 _ -> panic ("process_casm: casm with many results while processing _casm_ \"" ++ string ++ "\".\n")
1089 read_int :: ReadS Int
1092 case (read_int other) of
1094 if num >= 0 && args `lengthExceeds` num
1095 then parens (args !! num) <> process ress args css
1096 else error ("process_casm: no such arg #:"++(show num)++" while processing \"" ++ string ++ "\".\n")
1097 _ -> error ("process_casm: not %<num> while processing _casm_ \"" ++ string ++ "\".\n")
1099 process ress args (other_c:cs)
1100 = char other_c <> process ress args cs
1103 %************************************************************************
1105 \subsection[a2r-assignments]{Assignments}
1107 %************************************************************************
1109 Printing assignments is a little tricky because of type coercion.
1111 First of all, the kind of the thing being assigned can be gotten from
1112 the destination addressing mode. (It should be the same as the kind
1113 of the source addressing mode.) If the kind of the assignment is of
1114 @VoidRep@, then don't generate any code at all.
1117 pprAssign :: PrimRep -> CAddrMode -> CAddrMode -> SDoc
1119 pprAssign VoidRep dest src = empty
1122 Special treatment for floats and doubles, to avoid unwanted conversions.
1125 pprAssign FloatRep dest@(CVal reg_rel _) src
1126 = hcat [ ptext SLIT("ASSIGN_FLT((W_*)"), parens (ppr_amode (CAddr reg_rel)), comma, pprAmode src, pp_paren_semi ]
1128 pprAssign DoubleRep dest@(CVal reg_rel _) src
1129 = hcat [ ptext SLIT("ASSIGN_DBL((W_*)"), parens (ppr_amode (CAddr reg_rel)), comma, pprAmode src, pp_paren_semi ]
1131 pprAssign Int64Rep dest@(CVal reg_rel _) src
1132 = hcat [ ptext SLIT("ASSIGN_Int64((W_*)"), parens (ppr_amode (CAddr reg_rel)), comma, pprAmode src, pp_paren_semi ]
1133 pprAssign Word64Rep dest@(CVal reg_rel _) src
1134 = hcat [ ptext SLIT("ASSIGN_Word64((W_*)"), parens (ppr_amode (CAddr reg_rel)), comma, pprAmode src, pp_paren_semi ]
1137 Lastly, the question is: will the C compiler think the types of the
1138 two sides of the assignment match?
1140 We assume that the types will match if neither side is a
1141 @CVal@ addressing mode for any register which can point into
1144 Why? Because the heap and stack are used to store miscellaneous
1145 things, whereas the temporaries, registers, etc., are only used for
1146 things of fixed type.
1149 pprAssign kind (CReg (VanillaReg _ dest)) (CReg (VanillaReg _ src))
1150 = hcat [ pprVanillaReg dest, equals,
1151 pprVanillaReg src, semi ]
1153 pprAssign kind dest src
1154 | mixedTypeLocn dest
1155 -- Add in a cast to StgWord (a.k.a. W_) iff the destination is mixed
1156 = hcat [ ppr_amode dest, equals,
1157 text "(W_)(", -- Here is the cast
1158 ppr_amode src, pp_paren_semi ]
1160 pprAssign kind dest src
1161 | mixedPtrLocn dest && getAmodeRep src /= PtrRep
1162 -- Add in a cast to StgPtr (a.k.a. P_) iff the destination is mixed
1163 = hcat [ ppr_amode dest, equals,
1164 text "(P_)(", -- Here is the cast
1165 ppr_amode src, pp_paren_semi ]
1167 pprAssign kind other_dest src
1168 = hcat [ ppr_amode other_dest, equals,
1169 pprAmode src, semi ]
1173 %************************************************************************
1175 \subsection[a2r-CAddrModes]{Addressing modes}
1177 %************************************************************************
1179 @pprAmode@ is used to print r-values (which may need casts), whereas
1180 @ppr_amode@ is used for l-values {\em and} as a help function for
1184 pprAmode, ppr_amode :: CAddrMode -> SDoc
1187 For reasons discussed above under assignments, @CVal@ modes need
1188 to be treated carefully. First come special cases for floats and doubles,
1189 similar to those in @pprAssign@:
1191 (NB: @PK_FLT@ and @PK_DBL@ require the {\em address} of the value in
1195 pprAmode (CVal reg_rel FloatRep)
1196 = hcat [ text "PK_FLT((W_*)", parens (ppr_amode (CAddr reg_rel)), rparen ]
1197 pprAmode (CVal reg_rel DoubleRep)
1198 = hcat [ text "PK_DBL((W_*)", parens (ppr_amode (CAddr reg_rel)), rparen ]
1199 pprAmode (CVal reg_rel Int64Rep)
1200 = hcat [ text "PK_Int64((W_*)", parens (ppr_amode (CAddr reg_rel)), rparen ]
1201 pprAmode (CVal reg_rel Word64Rep)
1202 = hcat [ text "PK_Word64((W_*)", parens (ppr_amode (CAddr reg_rel)), rparen ]
1205 Next comes the case where there is some other cast need, and the
1210 | mixedTypeLocn amode
1211 = parens (hcat [ pprPrimKind (getAmodeRep amode), ptext SLIT(")("),
1213 | otherwise -- No cast needed
1217 When we have an indirection through a CIndex, we have to be careful to
1218 get the type casts right.
1222 CVal (CIndex kind1 base offset) kind2
1226 *(kind2 *)((kind1 *)base + offset)
1228 That is, the indexing is done in units of kind1, but the resulting
1232 ppr_amode CBytesPerWord
1233 = text "(sizeof(void*))"
1235 ppr_amode (CVal reg_rel@(CIndex _ _ _) kind)
1236 = case (pprRegRelative False{-no sign wanted-} reg_rel) of
1237 (pp_reg, Nothing) -> panic "ppr_amode: CIndex"
1238 (pp_reg, Just offset) ->
1239 hcat [ char '*', parens (pprPrimKind kind <> char '*'),
1240 parens (pp_reg <> char '+' <> offset) ]
1243 Now the rest of the cases for ``workhorse'' @ppr_amode@:
1246 ppr_amode (CVal reg_rel _)
1247 = case (pprRegRelative False{-no sign wanted-} reg_rel) of
1248 (pp_reg, Nothing) -> (<>) (char '*') pp_reg
1249 (pp_reg, Just offset) -> hcat [ pp_reg, brackets offset ]
1251 ppr_amode (CAddr reg_rel)
1252 = case (pprRegRelative True{-sign wanted-} reg_rel) of
1253 (pp_reg, Nothing) -> pp_reg
1254 (pp_reg, Just offset) -> (<>) pp_reg offset
1256 ppr_amode (CReg magic_id) = pprMagicId magic_id
1258 ppr_amode (CTemp uniq kind) = char '_' <> pprUnique uniq <> char '_'
1260 ppr_amode (CLbl lbl kind) = pprCLabelAddr lbl
1262 ppr_amode (CCharLike ch)
1263 = hcat [ptext SLIT("CHARLIKE_CLOSURE"), char '(', pprAmode ch, rparen ]
1264 ppr_amode (CIntLike int)
1265 = hcat [ptext SLIT("INTLIKE_CLOSURE"), char '(', pprAmode int, rparen ]
1267 ppr_amode (CLit lit) = pprBasicLit lit
1269 ppr_amode (CJoinPoint _)
1270 = panic "ppr_amode: CJoinPoint"
1272 ppr_amode (CMacroExpr pk macro as)
1273 = parens (ptext (cExprMacroText macro) <>
1274 parens (hcat (punctuate comma (map pprAmode as))))
1278 cExprMacroText ENTRY_CODE = SLIT("ENTRY_CODE")
1279 cExprMacroText ARG_TAG = SLIT("ARG_TAG")
1280 cExprMacroText GET_TAG = SLIT("GET_TAG")
1281 cExprMacroText UPD_FRAME_UPDATEE = SLIT("UPD_FRAME_UPDATEE")
1282 cExprMacroText CCS_HDR = SLIT("CCS_HDR")
1283 cExprMacroText BYTE_ARR_CTS = SLIT("BYTE_ARR_CTS")
1284 cExprMacroText PTRS_ARR_CTS = SLIT("PTRS_ARR_CTS")
1285 cExprMacroText ForeignObj_CLOSURE_DATA = SLIT("ForeignObj_CLOSURE_DATA")
1287 cStmtMacroText ARGS_CHK = SLIT("ARGS_CHK")
1288 cStmtMacroText ARGS_CHK_LOAD_NODE = SLIT("ARGS_CHK_LOAD_NODE")
1289 cStmtMacroText UPD_CAF = SLIT("UPD_CAF")
1290 cStmtMacroText UPD_BH_UPDATABLE = SLIT("UPD_BH_UPDATABLE")
1291 cStmtMacroText UPD_BH_SINGLE_ENTRY = SLIT("UPD_BH_SINGLE_ENTRY")
1292 cStmtMacroText PUSH_UPD_FRAME = SLIT("PUSH_UPD_FRAME")
1293 cStmtMacroText PUSH_SEQ_FRAME = SLIT("PUSH_SEQ_FRAME")
1294 cStmtMacroText UPDATE_SU_FROM_UPD_FRAME = SLIT("UPDATE_SU_FROM_UPD_FRAME")
1295 cStmtMacroText SET_TAG = SLIT("SET_TAG")
1296 cStmtMacroText DATA_TO_TAGZH = SLIT("dataToTagzh")
1297 cStmtMacroText REGISTER_FOREIGN_EXPORT = SLIT("REGISTER_FOREIGN_EXPORT")
1298 cStmtMacroText REGISTER_IMPORT = SLIT("REGISTER_IMPORT")
1299 cStmtMacroText REGISTER_DIMPORT = SLIT("REGISTER_DIMPORT")
1300 cStmtMacroText GRAN_FETCH = SLIT("GRAN_FETCH")
1301 cStmtMacroText GRAN_RESCHEDULE = SLIT("GRAN_RESCHEDULE")
1302 cStmtMacroText GRAN_FETCH_AND_RESCHEDULE= SLIT("GRAN_FETCH_AND_RESCHEDULE")
1303 cStmtMacroText THREAD_CONTEXT_SWITCH = SLIT("THREAD_CONTEXT_SWITCH")
1304 cStmtMacroText GRAN_YIELD = SLIT("GRAN_YIELD")
1306 cCheckMacroText HP_CHK_NP = SLIT("HP_CHK_NP")
1307 cCheckMacroText STK_CHK_NP = SLIT("STK_CHK_NP")
1308 cCheckMacroText HP_STK_CHK_NP = SLIT("HP_STK_CHK_NP")
1309 cCheckMacroText HP_CHK_SEQ_NP = SLIT("HP_CHK_SEQ_NP")
1310 cCheckMacroText HP_CHK = SLIT("HP_CHK")
1311 cCheckMacroText STK_CHK = SLIT("STK_CHK")
1312 cCheckMacroText HP_STK_CHK = SLIT("HP_STK_CHK")
1313 cCheckMacroText HP_CHK_NOREGS = SLIT("HP_CHK_NOREGS")
1314 cCheckMacroText HP_CHK_UNPT_R1 = SLIT("HP_CHK_UNPT_R1")
1315 cCheckMacroText HP_CHK_UNBX_R1 = SLIT("HP_CHK_UNBX_R1")
1316 cCheckMacroText HP_CHK_F1 = SLIT("HP_CHK_F1")
1317 cCheckMacroText HP_CHK_D1 = SLIT("HP_CHK_D1")
1318 cCheckMacroText HP_CHK_L1 = SLIT("HP_CHK_L1")
1319 cCheckMacroText HP_CHK_UT_ALT = SLIT("HP_CHK_UT_ALT")
1320 cCheckMacroText HP_CHK_GEN = SLIT("HP_CHK_GEN")
1326 %************************************************************************
1328 \subsection[ppr-liveness-masks]{Liveness Masks}
1330 %************************************************************************
1333 pp_bitmap_switch :: [BitSet] -> SDoc -> SDoc -> SDoc
1334 pp_bitmap_switch ([ ]) small large = small
1335 pp_bitmap_switch ([_ ]) small large = small
1336 pp_bitmap_switch ([_,_]) small large = hcat
1337 [ptext SLIT("BITMAP_SWITCH64"), lparen, small, comma, large, rparen]
1338 pp_bitmap_switch (_ ) small large = large
1340 pp_liveness_switch :: Liveness -> SDoc -> SDoc -> SDoc
1341 pp_liveness_switch (Liveness lbl mask) = pp_bitmap_switch mask
1343 pp_bitset :: BitSet -> SDoc
1345 | i < -1 = int (i + 1) <> text "-1"
1349 pp_bitmap :: [BitSet] -> SDoc
1350 pp_bitmap [] = int 0
1351 pp_bitmap ss = hcat (punctuate delayed_comma (bundle ss)) where
1352 delayed_comma = hcat [space, ptext SLIT("COMMA"), space]
1354 bundle [s] = [hcat bitmap32]
1355 where bitmap32 = [ptext SLIT("BITMAP32"), lparen,
1356 pp_bitset s, rparen]
1357 bundle (s1:s2:ss) = hcat bitmap64 : bundle ss
1358 where bitmap64 = [ptext SLIT("BITMAP64"), lparen,
1359 pp_bitset s1, comma, pp_bitset s2, rparen]
1361 pp_liveness :: Liveness -> SDoc
1362 pp_liveness (Liveness lbl mask)
1363 = pp_bitmap_switch mask (pp_bitmap mask) (char '&' <> pprCLabel lbl)
1366 %************************************************************************
1368 \subsection[a2r-MagicIds]{Magic ids}
1370 %************************************************************************
1372 @pprRegRelative@ returns a pair of the @Doc@ for the register
1373 (some casting may be required), and a @Maybe Doc@ for the offset
1374 (zero offset gives a @Nothing@).
1377 addPlusSign :: Bool -> SDoc -> SDoc
1378 addPlusSign False p = p
1379 addPlusSign True p = (<>) (char '+') p
1381 pprSignedInt :: Bool -> Int -> Maybe SDoc -- Nothing => 0
1382 pprSignedInt sign_wanted n
1383 = if n == 0 then Nothing else
1384 if n > 0 then Just (addPlusSign sign_wanted (int n))
1387 pprRegRelative :: Bool -- True <=> Print leading plus sign (if +ve)
1389 -> (SDoc, Maybe SDoc)
1391 pprRegRelative sign_wanted (SpRel off)
1392 = (pprMagicId Sp, pprSignedInt sign_wanted (I# off))
1394 pprRegRelative sign_wanted r@(HpRel o)
1395 = let pp_Hp = pprMagicId Hp; off = I# o
1400 (pp_Hp, Just ((<>) (char '-') (int off)))
1402 pprRegRelative sign_wanted (NodeRel o)
1403 = let pp_Node = pprMagicId node; off = I# o
1408 (pp_Node, Just (addPlusSign sign_wanted (int off)))
1410 pprRegRelative sign_wanted (CIndex base offset kind)
1411 = ( hcat [text "((", pprPrimKind kind, text " *)(", ppr_amode base, text "))"]
1412 , Just (hcat [if sign_wanted then char '+' else empty,
1413 text "(I_)(", ppr_amode offset, ptext SLIT(")")])
1417 @pprMagicId@ just prints the register name. @VanillaReg@ registers are
1418 represented by a discriminated union (@StgUnion@), so we use the @PrimRep@
1419 to select the union tag.
1422 pprMagicId :: MagicId -> SDoc
1424 pprMagicId BaseReg = ptext SLIT("BaseReg")
1425 pprMagicId (VanillaReg pk n)
1426 = hcat [ pprVanillaReg n, char '.',
1428 pprMagicId (FloatReg n) = ptext SLIT("F") <> int (I# n)
1429 pprMagicId (DoubleReg n) = ptext SLIT("D") <> int (I# n)
1430 pprMagicId (LongReg _ n) = ptext SLIT("L") <> int (I# n)
1431 pprMagicId Sp = ptext SLIT("Sp")
1432 pprMagicId Su = ptext SLIT("Su")
1433 pprMagicId SpLim = ptext SLIT("SpLim")
1434 pprMagicId Hp = ptext SLIT("Hp")
1435 pprMagicId HpLim = ptext SLIT("HpLim")
1436 pprMagicId CurCostCentre = ptext SLIT("CCCS")
1437 pprMagicId VoidReg = panic "pprMagicId:VoidReg!"
1439 pprVanillaReg :: Int# -> SDoc
1440 pprVanillaReg n = char 'R' <> int (I# n)
1442 pprUnionTag :: PrimRep -> SDoc
1444 pprUnionTag PtrRep = char 'p'
1445 pprUnionTag CodePtrRep = ptext SLIT("fp")
1446 pprUnionTag DataPtrRep = char 'd'
1447 pprUnionTag RetRep = char 'p'
1448 pprUnionTag CostCentreRep = panic "pprUnionTag:CostCentre?"
1450 pprUnionTag CharRep = char 'c'
1451 pprUnionTag Int8Rep = ptext SLIT("i8")
1452 pprUnionTag IntRep = char 'i'
1453 pprUnionTag WordRep = char 'w'
1454 pprUnionTag Int32Rep = char 'i'
1455 pprUnionTag Word32Rep = char 'w'
1456 pprUnionTag AddrRep = char 'a'
1457 pprUnionTag FloatRep = char 'f'
1458 pprUnionTag DoubleRep = panic "pprUnionTag:Double?"
1460 pprUnionTag StablePtrRep = char 'p'
1462 pprUnionTag _ = panic "pprUnionTag:Odd kind"
1466 Find and print local and external declarations for a list of
1467 Abstract~C statements.
1469 pprTempAndExternDecls :: AbstractC -> (SDoc{-temps-}, SDoc{-externs-})
1470 pprTempAndExternDecls AbsCNop = (empty, empty)
1472 pprTempAndExternDecls (AbsCStmts stmt1 stmt2)
1473 = initTE (ppr_decls_AbsC stmt1 `thenTE` \ (t_p1, e_p1) ->
1474 ppr_decls_AbsC stmt2 `thenTE` \ (t_p2, e_p2) ->
1475 case (catMaybes [t_p1, t_p2]) of { real_temps ->
1476 case (catMaybes [e_p1, e_p2]) of { real_exts ->
1477 returnTE (vcat real_temps, vcat real_exts) }}
1480 pprTempAndExternDecls other_stmt
1481 = initTE (ppr_decls_AbsC other_stmt `thenTE` \ (maybe_t, maybe_e) ->
1492 pprBasicLit :: Literal -> SDoc
1493 pprPrimKind :: PrimRep -> SDoc
1495 pprBasicLit lit = ppr lit
1496 pprPrimKind k = ppr k
1500 %************************************************************************
1502 \subsection[a2r-monad]{Monadery}
1504 %************************************************************************
1506 We need some monadery to keep track of temps and externs we have already
1507 printed. This info must be threaded right through the Abstract~C, so
1508 it's most convenient to hide it in this monad.
1510 WDP 95/02: Switched from \tr{([Unique], [CLabel])} to
1511 \tr{(UniqSet, CLabelSet)}. Allegedly for efficiency.
1514 type CLabelSet = FiniteMap CLabel (){-any type will do-}
1515 emptyCLabelSet = emptyFM
1516 x `elementOfCLabelSet` labs
1517 = case (lookupFM labs x) of { Just _ -> True; Nothing -> False }
1519 addToCLabelSet set x = addToFM set x ()
1521 type TEenv = (UniqSet Unique, CLabelSet)
1523 type TeM result = TEenv -> (TEenv, result)
1525 initTE :: TeM a -> a
1527 = case sa (emptyUniqSet, emptyCLabelSet) of { (_, result) ->
1530 {-# INLINE thenTE #-}
1531 {-# INLINE returnTE #-}
1533 thenTE :: TeM a -> (a -> TeM b) -> TeM b
1535 = case a u of { (u_1, result_of_a) ->
1538 mapTE :: (a -> TeM b) -> [a] -> TeM [b]
1539 mapTE f [] = returnTE []
1541 = f x `thenTE` \ r ->
1542 mapTE f xs `thenTE` \ rs ->
1545 returnTE :: a -> TeM a
1546 returnTE result env = (env, result)
1548 -- these next two check whether the thing is already
1549 -- recorded, and THEN THEY RECORD IT
1550 -- (subsequent calls will return False for the same uniq/label)
1552 tempSeenTE :: Unique -> TeM Bool
1553 tempSeenTE uniq env@(seen_uniqs, seen_labels)
1554 = if (uniq `elementOfUniqSet` seen_uniqs)
1556 else ((addOneToUniqSet seen_uniqs uniq,
1560 labelSeenTE :: CLabel -> TeM Bool
1561 labelSeenTE lbl env@(seen_uniqs, seen_labels)
1562 = if (lbl `elementOfCLabelSet` seen_labels)
1565 addToCLabelSet seen_labels lbl),
1570 pprTempDecl :: Unique -> PrimRep -> SDoc
1571 pprTempDecl uniq kind
1572 = hcat [ pprPrimKind kind, space, char '_', pprUnique uniq, ptext SLIT("_;") ]
1574 pprExternDecl :: Bool -> CLabel -> SDoc
1575 pprExternDecl in_srt clabel
1576 | not (needsCDecl clabel) = empty -- do not print anything for "known external" things
1578 hcat [ ppLocalnessMacro (not in_srt) clabel,
1579 lparen, dyn_wrapper (pprCLabel clabel), pp_paren_semi ]
1582 | in_srt && labelDynamic clabel = text "DLL_IMPORT_DATA_VAR" <> parens d
1588 ppr_decls_AbsC :: AbstractC -> TeM (Maybe SDoc{-temps-}, Maybe SDoc{-externs-})
1590 ppr_decls_AbsC AbsCNop = returnTE (Nothing, Nothing)
1592 ppr_decls_AbsC (AbsCStmts stmts_1 stmts_2)
1593 = ppr_decls_AbsC stmts_1 `thenTE` \ p1 ->
1594 ppr_decls_AbsC stmts_2 `thenTE` \ p2 ->
1595 returnTE (maybe_vcat [p1, p2])
1597 ppr_decls_AbsC (CSplitMarker) = returnTE (Nothing, Nothing)
1599 ppr_decls_AbsC (CAssign dest source)
1600 = ppr_decls_Amode dest `thenTE` \ p1 ->
1601 ppr_decls_Amode source `thenTE` \ p2 ->
1602 returnTE (maybe_vcat [p1, p2])
1604 ppr_decls_AbsC (CJump target) = ppr_decls_Amode target
1606 ppr_decls_AbsC (CFallThrough target) = ppr_decls_Amode target
1608 ppr_decls_AbsC (CReturn target _) = ppr_decls_Amode target
1610 ppr_decls_AbsC (CSwitch discrim alts deflt)
1611 = ppr_decls_Amode discrim `thenTE` \ pdisc ->
1612 mapTE ppr_alt_stuff alts `thenTE` \ palts ->
1613 ppr_decls_AbsC deflt `thenTE` \ pdeflt ->
1614 returnTE (maybe_vcat (pdisc:pdeflt:palts))
1616 ppr_alt_stuff (_, absC) = ppr_decls_AbsC absC
1618 ppr_decls_AbsC (CCodeBlock lbl absC)
1619 = ppr_decls_AbsC absC
1621 ppr_decls_AbsC (CInitHdr cl_info reg_rel cost_centre _)
1622 -- ToDo: strictly speaking, should chk "cost_centre" amode
1623 = labelSeenTE info_lbl `thenTE` \ label_seen ->
1628 Just (pprExternDecl False{-not in an SRT decl-} info_lbl))
1630 info_lbl = infoTableLabelFromCI cl_info
1632 ppr_decls_AbsC (CMachOpStmt res _ args _) = ppr_decls_Amodes (res : args)
1633 ppr_decls_AbsC (COpStmt results _ args _) = ppr_decls_Amodes (results ++ args)
1635 ppr_decls_AbsC (CSimultaneous abc) = ppr_decls_AbsC abc
1637 ppr_decls_AbsC (CSequential abcs)
1638 = mapTE ppr_decls_AbsC abcs `thenTE` \ t_and_e_s ->
1639 returnTE (maybe_vcat t_and_e_s)
1641 ppr_decls_AbsC (CCheck _ amodes code) =
1642 ppr_decls_Amodes amodes `thenTE` \p1 ->
1643 ppr_decls_AbsC code `thenTE` \p2 ->
1644 returnTE (maybe_vcat [p1,p2])
1646 ppr_decls_AbsC (CMacroStmt _ amodes) = ppr_decls_Amodes amodes
1648 ppr_decls_AbsC (CCallProfCtrMacro _ amodes) = ppr_decls_Amodes [] -- *****!!!
1649 -- you get some nasty re-decls of stdio.h if you compile
1650 -- the prelude while looking inside those amodes;
1651 -- no real reason to, anyway.
1652 ppr_decls_AbsC (CCallProfCCMacro _ amodes) = ppr_decls_Amodes amodes
1654 ppr_decls_AbsC (CStaticClosure closure_info cost_centre amodes)
1655 -- ToDo: strictly speaking, should chk "cost_centre" amode
1656 = ppr_decls_Amodes amodes
1658 ppr_decls_AbsC (CClosureInfoAndCode cl_info slow maybe_fast _)
1659 = ppr_decls_Amodes [entry_lbl] `thenTE` \ p1 ->
1660 ppr_decls_AbsC slow `thenTE` \ p2 ->
1662 Nothing -> returnTE (Nothing, Nothing)
1663 Just fast -> ppr_decls_AbsC fast) `thenTE` \ p3 ->
1664 returnTE (maybe_vcat [p1, p2, p3])
1666 entry_lbl = CLbl slow_lbl CodePtrRep
1667 slow_lbl = case (nonemptyAbsC slow) of
1668 Nothing -> mkErrorStdEntryLabel
1669 Just _ -> entryLabelFromCI cl_info
1671 ppr_decls_AbsC (CSRT _ closure_lbls)
1672 = mapTE labelSeenTE closure_lbls `thenTE` \ seen ->
1674 if and seen then Nothing
1675 else Just (vcat [ pprExternDecl True{-in SRT decl-} l
1676 | (l,False) <- zip closure_lbls seen ]))
1678 ppr_decls_AbsC (CRetDirect _ code _ _) = ppr_decls_AbsC code
1679 ppr_decls_AbsC (CRetVector _ amodes _ _) = ppr_decls_Amodes amodes
1680 ppr_decls_AbsC (CModuleInitBlock _ _ code) = ppr_decls_AbsC code
1682 ppr_decls_AbsC (_) = returnTE (Nothing, Nothing)
1686 ppr_decls_Amode :: CAddrMode -> TeM (Maybe SDoc, Maybe SDoc)
1687 ppr_decls_Amode (CVal (CIndex base offset _) _) = ppr_decls_Amodes [base,offset]
1688 ppr_decls_Amode (CAddr (CIndex base offset _)) = ppr_decls_Amodes [base,offset]
1689 ppr_decls_Amode (CVal _ _) = returnTE (Nothing, Nothing)
1690 ppr_decls_Amode (CAddr _) = returnTE (Nothing, Nothing)
1691 ppr_decls_Amode (CReg _) = returnTE (Nothing, Nothing)
1692 ppr_decls_Amode (CLit _) = returnTE (Nothing, Nothing)
1694 -- CIntLike must be a literal -- no decls
1695 ppr_decls_Amode (CIntLike int) = returnTE (Nothing, Nothing)
1698 ppr_decls_Amode (CCharLike char) = returnTE (Nothing, Nothing)
1700 -- now, the only place where we actually print temps/externs...
1701 ppr_decls_Amode (CTemp uniq kind)
1703 VoidRep -> returnTE (Nothing, Nothing)
1705 tempSeenTE uniq `thenTE` \ temp_seen ->
1707 (if temp_seen then Nothing else Just (pprTempDecl uniq kind), Nothing)
1709 ppr_decls_Amode (CLbl lbl VoidRep)
1710 = returnTE (Nothing, Nothing)
1712 ppr_decls_Amode (CLbl lbl kind)
1713 = labelSeenTE lbl `thenTE` \ label_seen ->
1715 if label_seen then Nothing else Just (pprExternDecl False{-not in an SRT decl-} lbl))
1717 ppr_decls_Amode (CMacroExpr _ _ amodes)
1718 = ppr_decls_Amodes amodes
1720 ppr_decls_Amode other = returnTE (Nothing, Nothing)
1723 maybe_vcat :: [(Maybe SDoc, Maybe SDoc)] -> (Maybe SDoc, Maybe SDoc)
1725 = case (unzip ps) of { (ts, es) ->
1726 case (catMaybes ts) of { real_ts ->
1727 case (catMaybes es) of { real_es ->
1728 (if (null real_ts) then Nothing else Just (vcat real_ts),
1729 if (null real_es) then Nothing else Just (vcat real_es))
1734 ppr_decls_Amodes :: [CAddrMode] -> TeM (Maybe SDoc, Maybe SDoc)
1735 ppr_decls_Amodes amodes
1736 = mapTE ppr_decls_Amode amodes `thenTE` \ ps ->
1737 returnTE ( maybe_vcat ps )
1740 Print out a C Label where you want the *address* of the label, not the
1741 object it refers to. The distinction is important when the label may
1742 refer to a C structure (info tables and closures, for instance).
1744 When just generating a declaration for the label, use pprCLabel.
1747 pprCLabelAddr :: CLabel -> SDoc
1748 pprCLabelAddr clabel =
1749 case labelType clabel of
1750 InfoTblType -> addr_of_label
1751 ClosureType -> addr_of_label
1752 VecTblType -> addr_of_label
1755 addr_of_label = ptext SLIT("(P_)&") <> pp_label
1756 pp_label = pprCLabel clabel
1760 -----------------------------------------------------------------------------
1761 Initialising static objects with floating-point numbers. We can't
1762 just emit the floating point number, because C will cast it to an int
1763 by rounding it. We want the actual bit-representation of the float.
1765 This is a hack to turn the floating point numbers into ints that we
1766 can safely initialise to static locations.
1769 big_doubles = (getPrimRepSize DoubleRep) /= 1
1771 #if __GLASGOW_HASKELL__ >= 504
1772 newFloatArray :: (Int,Int) -> ST s (STUArray s Int Float)
1773 newFloatArray = newArray_
1775 newDoubleArray :: (Int,Int) -> ST s (STUArray s Int Double)
1776 newDoubleArray = newArray_
1778 castFloatToIntArray :: STUArray s Int Float -> ST s (STUArray s Int Int)
1779 castFloatToIntArray = castSTUArray
1781 castDoubleToIntArray :: STUArray s Int Double -> ST s (STUArray s Int Int)
1782 castDoubleToIntArray = castSTUArray
1784 writeFloatArray :: STUArray s Int Float -> Int -> Float -> ST s ()
1785 writeFloatArray = writeArray
1787 writeDoubleArray :: STUArray s Int Double -> Int -> Double -> ST s ()
1788 writeDoubleArray = writeArray
1790 readIntArray :: STUArray s Int Int -> Int -> ST s Int
1791 readIntArray = readArray
1795 castFloatToIntArray :: MutableByteArray s t -> ST s (MutableByteArray s t)
1796 castFloatToIntArray = return
1798 castDoubleToIntArray :: MutableByteArray s t -> ST s (MutableByteArray s t)
1799 castDoubleToIntArray = return
1803 -- floats are always 1 word
1804 floatToWord :: CAddrMode -> CAddrMode
1805 floatToWord (CLit (MachFloat r))
1807 arr <- newFloatArray ((0::Int),0)
1808 writeFloatArray arr 0 (fromRational r)
1809 arr' <- castFloatToIntArray arr
1810 i <- readIntArray arr' 0
1811 return (CLit (MachInt (toInteger i)))
1814 doubleToWords :: CAddrMode -> [CAddrMode]
1815 doubleToWords (CLit (MachDouble r))
1816 | big_doubles -- doubles are 2 words
1818 arr <- newDoubleArray ((0::Int),1)
1819 writeDoubleArray arr 0 (fromRational r)
1820 arr' <- castDoubleToIntArray arr
1821 i1 <- readIntArray arr' 0
1822 i2 <- readIntArray arr' 1
1823 return [ CLit (MachInt (toInteger i1))
1824 , CLit (MachInt (toInteger i2))
1827 | otherwise -- doubles are 1 word
1829 arr <- newDoubleArray ((0::Int),0)
1830 writeDoubleArray arr 0 (fromRational r)
1831 arr' <- castDoubleToIntArray arr
1832 i <- readIntArray arr' 0
1833 return [ CLit (MachInt (toInteger i)) ]