2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
4 \section[CLabel]{@CLabel@: Information to make C Labels}
7 #include "HsVersions.h"
10 CLabel, -- abstract type
17 mkStaticConEntryLabel,
19 mkPhantomInfoTableLabel,
20 mkStaticInfoTableLabel,
24 mkConUpdCodePtrVecLabel,
25 mkStdUpdCodePtrVecLabel,
27 mkInfoTableVecTblLabel,
38 mkBlackHoleInfoTableLabel,
40 needsCDecl, isReadOnly, isAsmTemp, externallyVisibleCLabel,
43 #if ! OMIT_NATIVE_CODEGEN
49 import AbsCLoop ( CtrlReturnConvention(..),
52 #if ! OMIT_NATIVE_CODEGEN
53 import NcgLoop ( underscorePrefix, fmtAsmLbl )
56 import CStrings ( pp_cSEP )
57 import Id ( externallyVisibleId, cmpId_withSpecDataCon,
58 isDataCon, isDictFunId,
59 isConstMethodId_maybe,
60 isDefaultMethodId_maybe,
61 isSuperDictSelId_maybe, fIRST_TAG,
62 ConTag(..), GenId{-instance Outputable-}
64 import Maybes ( maybeToBool )
65 import PprStyle ( PprStyle(..) )
66 import PprType ( showTyCon, GenType{-instance Outputable-} )
67 import Pretty ( prettyToUn )
68 import TyCon ( TyCon{-instance Eq-} )
69 import Unique ( showUnique, pprUnique, Unique{-instance Eq-} )
70 import Unpretty -- NOTE!! ********************
71 import Util ( assertPanic )
74 things we want to find out:
76 * should the labelled things be declared "static" (visible only in this file)?
78 * should it be declared "const" (read-only text space)?
80 * does it need declarations at all? (v common Prelude things are pre-declared)
84 = IdLabel -- A family of labels related to the
85 CLabelId -- definition of a particular Id
86 IdLabelInfo -- Includes DataCon
88 | TyConLabel -- A family of labels related to the
89 TyCon -- definition of a data type
92 | CaseLabel -- A family of labels related to a particular case expression
93 Unique -- Unique says which case expression
98 | RtsLabel RtsLabelInfo
103 The CLabelId is simply so we can declare alternative Eq and Ord
104 instances which use cmpId_SpecDataCon (instead of cmpId). This avoids
105 comparing the Uniques of two specialised data constructors (which have
106 the same as the uniques their respective unspecialised data
107 constructors). Instead, the specialising types and the uniques of the
108 unspecialised constructors are compared.
111 data CLabelId = CLabelId Id
113 instance Eq CLabelId where
114 CLabelId a == CLabelId b = case cmpId_withSpecDataCon a b of { EQ_ -> True; _ -> False }
115 CLabelId a /= CLabelId b = case cmpId_withSpecDataCon a b of { EQ_ -> False; _ -> True }
117 instance Ord CLabelId where
118 CLabelId a <= CLabelId b = case cmpId_withSpecDataCon a b
119 of { LT_ -> True; EQ_ -> True; GT__ -> False }
120 CLabelId a < CLabelId b = case cmpId_withSpecDataCon a b
121 of { LT_ -> True; EQ_ -> False; GT__ -> False }
122 CLabelId a >= CLabelId b = case cmpId_withSpecDataCon a b
123 of { LT_ -> False; EQ_ -> True; GT__ -> True }
124 CLabelId a > CLabelId b = case cmpId_withSpecDataCon a b
125 of { LT_ -> False; EQ_ -> False; GT__ -> True }
126 _tagCmp (CLabelId a) (CLabelId b) = case cmpId_withSpecDataCon a b
127 of { LT_ -> _LT; EQ_ -> _EQ; GT__ -> _GT }
132 = Closure -- Label for (static???) closure
134 | InfoTbl -- Info table for a closure; always read-only
136 | EntryStd -- Thunk, or "slow", code entry point (requires arg satis check)
137 | EntryFast Int -- entry pt when no arg satisfaction chk needed;
138 -- Int is the arity of the function (to be
139 -- encoded into the name)
141 | ConEntry -- the only kind of entry pt for constructors
142 | StaticConEntry -- static constructor entry point
144 | StaticInfoTbl -- corresponding info table
146 | PhantomInfoTbl -- for phantom constructors that only exist in regs
148 | VapInfoTbl Bool -- True <=> the update-reqd version; False <=> the no-update-reqd version
151 -- Ticky-ticky counting
152 | RednCounts -- Label of place to keep reduction-count info for this Id
157 = UnvecConUpdCode -- Update code for the data type if it's unvectored
159 | VecConUpdCode ConTag -- One for each constructor which returns in
160 -- regs; this code actually performs an update
162 | StdUpdCode ConTag -- Update code for all constructors which return
163 -- in heap. There are a small number of variants,
164 -- so that the update code returns (vectored/n or
165 -- unvectored) in the right way.
166 -- ToDo: maybe replace TyCon/Int with return conv.
168 | InfoTblVecTbl -- For tables of info tables
170 | StdUpdVecTbl -- Labels the update code, or table of update codes,
171 -- for a particular type.
182 = RtsShouldNeverHappenCode
184 | RtsBlackHoleInfoTbl
186 | RtsSelectorInfoTbl -- Selectors
187 Bool -- True <=> the update-reqd version;
188 -- False <=> the no-update-reqd version
189 Int -- 0-indexed Offset from the "goods"
191 | RtsSelectorEntry -- Ditto entry code
198 mkClosureLabel id = IdLabel (CLabelId id) Closure
199 mkInfoTableLabel id = IdLabel (CLabelId id) InfoTbl
200 mkStdEntryLabel id = IdLabel (CLabelId id) EntryStd
201 mkFastEntryLabel id arity = ASSERT(arity > 0)
202 IdLabel (CLabelId id) (EntryFast arity)
203 mkConEntryLabel id = IdLabel (CLabelId id) ConEntry
204 mkStaticConEntryLabel id = IdLabel (CLabelId id) StaticConEntry
205 mkRednCountsLabel id = IdLabel (CLabelId id) RednCounts
206 mkPhantomInfoTableLabel id = IdLabel (CLabelId id) PhantomInfoTbl
207 mkStaticInfoTableLabel id = IdLabel (CLabelId id) StaticInfoTbl
208 mkVapEntryLabel id upd_flag = IdLabel (CLabelId id) (VapEntry upd_flag)
209 mkVapInfoTableLabel id upd_flag = IdLabel (CLabelId id) (VapInfoTbl upd_flag)
211 mkConUpdCodePtrVecLabel tycon tag = TyConLabel tycon (VecConUpdCode tag)
212 mkStdUpdCodePtrVecLabel tycon tag = TyConLabel tycon (StdUpdCode tag)
214 mkInfoTableVecTblLabel tycon = TyConLabel tycon InfoTblVecTbl
215 mkStdUpdVecTblLabel tycon = TyConLabel tycon StdUpdVecTbl
217 mkReturnPtLabel uniq = CaseLabel uniq CaseReturnPt
218 mkVecTblLabel uniq = CaseLabel uniq CaseVecTbl
219 mkAltLabel uniq tag = CaseLabel uniq (CaseAlt tag)
220 mkDefaultLabel uniq = CaseLabel uniq CaseDefault
222 mkAsmTempLabel = AsmTempLabel
224 -- Some fixed runtime system labels
226 mkErrorStdEntryLabel = RtsLabel RtsShouldNeverHappenCode
227 mkBlackHoleInfoTableLabel = RtsLabel RtsBlackHoleInfoTbl
231 needsCDecl :: CLabel -> Bool -- False <=> it's pre-declared; don't bother
232 isReadOnly :: CLabel -> Bool -- lives in C "text space"
233 isAsmTemp :: CLabel -> Bool -- is a local temporary for native code generation
234 externallyVisibleCLabel :: CLabel -> Bool -- not C "static"
237 @needsCDecl@ is @True@ unless the thing is a deeply-@PreludeCore@-ish
238 object. {\em Also:} No need to spit out labels for things generated
239 by the flattener (in @AbsCUtils@)---it is careful to ensure references
240 to them are always backwards. These are return-point and vector-table
243 Declarations for (non-prelude) @Id@-based things are needed because of
246 needsCDecl (IdLabel _ _) = True
247 needsCDecl (CaseLabel _ _) = False
249 needsCDecl (TyConLabel _ (StdUpdCode _)) = False
250 needsCDecl (TyConLabel _ InfoTblVecTbl) = False
251 needsCDecl (TyConLabel _ other) = True
253 needsCDecl (AsmTempLabel _) = False
254 needsCDecl (RtsLabel _) = False
256 needsCDecl other = True
259 Whether the labelled thing can be put in C "text space":
261 isReadOnly (IdLabel _ InfoTbl) = True -- info-tables: yes
262 isReadOnly (IdLabel _ StaticInfoTbl) = True -- and so on, for other
263 isReadOnly (IdLabel _ PhantomInfoTbl) = True
264 isReadOnly (IdLabel _ (VapInfoTbl _)) = True
265 isReadOnly (IdLabel _ other) = False -- others: pessimistically, no
267 isReadOnly (TyConLabel _ _) = True
268 isReadOnly (CaseLabel _ _) = True
269 isReadOnly (AsmTempLabel _) = True
270 isReadOnly (RtsLabel _) = True
273 Whether the label is an assembler temporary:
275 isAsmTemp (AsmTempLabel _) = True
279 C ``static'' or not...
281 externallyVisibleCLabel (TyConLabel tc _) = True
282 externallyVisibleCLabel (CaseLabel _ _) = False
283 externallyVisibleCLabel (AsmTempLabel _) = False
284 externallyVisibleCLabel (RtsLabel _) = True
285 externallyVisibleCLabel (IdLabel (CLabelId id) _)
286 | isDataCon id = True
287 | is_ConstMethodId id = True -- These are here to ensure splitting works
288 | isDictFunId id = True -- when these values have not been exported
289 | is_DefaultMethodId id = True
290 | is_SuperDictSelId id = True
291 | otherwise = externallyVisibleId id
293 is_ConstMethodId id = maybeToBool (isConstMethodId_maybe id)
294 is_DefaultMethodId id = maybeToBool (isDefaultMethodId_maybe id)
295 is_SuperDictSelId id = maybeToBool (isSuperDictSelId_maybe id)
298 OLD?: These GRAN functions are needed for spitting out GRAN_FETCH() at the
299 right places. It is used to detect when the abstractC statement of an
300 CCodeBlock actually contains the code for a slow entry point. -- HWL
302 We need at least @Eq@ for @CLabels@, because we want to avoid
303 duplicate declarations in generating C (see @labelSeenTE@ in
307 -- specialised for PprAsm: saves lots of arg passing in NCG
308 #if ! OMIT_NATIVE_CODEGEN
309 pprCLabel_asm = pprCLabel (PprForAsm underscorePrefix fmtAsmLbl)
312 pprCLabel :: PprStyle -> CLabel -> Unpretty
314 pprCLabel (PprForAsm _ fmtAsmLbl) (AsmTempLabel u)
315 = uppStr (fmtAsmLbl (_UNPK_ (showUnique u)))
317 pprCLabel (PprForAsm prepend_cSEP _) lbl
319 then uppBeside pp_cSEP prLbl
322 prLbl = pprCLabel PprForC lbl
324 pprCLabel sty (TyConLabel tc UnvecConUpdCode)
325 = uppBesides [uppPStr SLIT("ret"), pp_cSEP, uppStr (showTyCon sty tc),
326 pp_cSEP, uppPStr SLIT("upd")]
328 pprCLabel sty (TyConLabel tc (VecConUpdCode tag))
329 = uppBesides [uppPStr SLIT("ret"), pp_cSEP, uppStr (showTyCon sty tc), pp_cSEP,
330 uppInt tag, pp_cSEP, uppPStr SLIT("upd")]
332 pprCLabel sty (TyConLabel tc (StdUpdCode tag))
333 = case (ctrlReturnConvAlg tc) of
334 UnvectoredReturn _ -> uppPStr SLIT("IndUpdRetDir")
335 VectoredReturn _ -> uppBeside (uppPStr SLIT("IndUpdRetV")) (uppInt (tag - fIRST_TAG))
337 pprCLabel sty (TyConLabel tc InfoTblVecTbl)
338 = uppBesides [uppStr (showTyCon sty tc), pp_cSEP, uppPStr SLIT("itblvtbl")]
340 pprCLabel sty (TyConLabel tc StdUpdVecTbl)
341 = uppBesides [uppPStr SLIT("vtbl"), pp_cSEP, uppStr (showTyCon sty tc),
342 pp_cSEP, uppPStr SLIT("upd")]
344 pprCLabel sty (CaseLabel u CaseReturnPt)
345 = uppBesides [uppPStr SLIT("ret"), pp_cSEP, ppr_u u]
346 pprCLabel sty (CaseLabel u CaseVecTbl)
347 = uppBesides [uppPStr SLIT("vtbl"), pp_cSEP, ppr_u u]
348 pprCLabel sty (CaseLabel u (CaseAlt tag))
349 = uppBesides [uppPStr SLIT("djn"), pp_cSEP, ppr_u u, pp_cSEP, uppInt tag]
350 pprCLabel sty (CaseLabel u CaseDefault)
351 = uppBesides [uppPStr SLIT("djn"), pp_cSEP, ppr_u u]
353 pprCLabel sty (RtsLabel RtsShouldNeverHappenCode) = uppPStr SLIT("StdErrorCode")
355 pprCLabel sty (RtsLabel RtsBlackHoleInfoTbl) = uppPStr SLIT("BH_UPD_info")
357 pprCLabel sty (RtsLabel (RtsSelectorInfoTbl upd_reqd offset))
358 = uppBesides [uppPStr SLIT("__sel_info_"), uppStr (show offset),
359 uppStr (if upd_reqd then "upd" else "noupd"),
362 pprCLabel sty (RtsLabel (RtsSelectorEntry upd_reqd offset))
363 = uppBesides [uppPStr SLIT("__sel_entry_"), uppStr (show offset),
364 uppStr (if upd_reqd then "upd" else "noupd"),
367 pprCLabel sty (IdLabel (CLabelId id) flavor)
368 = uppBeside (prettyToUn (ppr sty id)) (ppFlavor flavor)
370 ppr_u u = prettyToUn (pprUnique u)
372 ppFlavor :: IdLabelInfo -> Unpretty
374 ppFlavor x = uppBeside pp_cSEP
376 Closure -> uppPStr SLIT("closure")
377 InfoTbl -> uppPStr SLIT("info")
378 EntryStd -> uppPStr SLIT("entry")
379 EntryFast arity -> --false:ASSERT (arity > 0)
380 uppBeside (uppPStr SLIT("fast")) (uppInt arity)
381 ConEntry -> uppPStr SLIT("entry")
382 StaticConEntry -> uppPStr SLIT("static_entry")
383 StaticInfoTbl -> uppPStr SLIT("static_info")
384 PhantomInfoTbl -> uppPStr SLIT("inregs_info")
385 VapInfoTbl True -> uppPStr SLIT("vap_info")
386 VapInfoTbl False -> uppPStr SLIT("vap_noupd_info")
387 VapEntry True -> uppPStr SLIT("vap_entry")
388 VapEntry False -> uppPStr SLIT("vap_noupd_entry")
389 RednCounts -> uppPStr SLIT("ct")