%
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
+%
+% $Id: AbsCSyn.lhs,v 1.34 2000/10/12 13:11:46 simonmar Exp $
%
\section[AbstractC]{Abstract C: the last stop before machine code}
raw assembler/machine code.
\begin{code}
-#include "HsVersions.h"
-
module AbsCSyn {- (
-- export everything
AbstractC(..),
-- registers
MagicId(..), node, infoptr,
- isVolatileReg, noLiveRegsMask, mkLiveRegsMask,
+ isVolatileReg,
CostRes(Cost)
)-} where
-IMP_Ubiq(){-uitous-}
-
-import CgCompInfo ( mAX_Vanilla_REG, mAX_Float_REG,
- mAX_Double_REG, lIVENESS_R1, lIVENESS_R2,
- lIVENESS_R3, lIVENESS_R4, lIVENESS_R5,
- lIVENESS_R6, lIVENESS_R7, lIVENESS_R8
- )
-import HeapOffs ( VirtualSpAOffset(..), VirtualSpBOffset(..),
- VirtualHeapOffset(..)
- )
-import Literal ( mkMachInt )
-import PrimRep ( isFollowableRep, PrimRep(..) )
+#include "HsVersions.h"
+
+import {-# SOURCE #-} ClosureInfo ( ClosureInfo )
+
+import CLabel
+import Constants ( mAX_Vanilla_REG, mAX_Float_REG,
+ mAX_Double_REG, spRelToInt )
+import CostCentre ( CostCentre, CostCentreStack )
+import Literal ( mkMachInt, Literal(..) )
+import PrimRep ( PrimRep(..) )
+import PrimOp ( PrimOp, CCall )
+import Unique ( Unique )
+import StgSyn ( SRT(..) )
+import TyCon ( TyCon )
+import BitSet -- for liveness masks
+
\end{code}
@AbstractC@ is a list of Abstract~C statements, but the data structure
\begin{code}
| CAssign
- CAddrMode -- target
- CAddrMode -- source
+ !CAddrMode -- target
+ !CAddrMode -- source
| CJump
CAddrMode -- Put this in the program counter
-- (for the benefit of the native code generators)
-- Equivalent to CJump in C land
- | CReturn -- This used to be RetVecRegRel
- CAddrMode -- Any base address mode
- ReturnInfo -- How to get the return address from the base address
+ | CReturn -- Perform a return
+ CAddrMode -- Address of a RET_<blah> info table
+ ReturnInfo -- Whether it's a direct or vectored return
- | CSwitch CAddrMode
+ | CSwitch !CAddrMode
[(Literal, AbstractC)] -- alternatives
AbstractC -- default; if there is no real Abstract C in here
-- (e.g., all comments; see function "nonemptyAbsC"),
-- CSwitch m [(tag,code)] AbsCNop == code
| CCodeBlock CLabel AbstractC
- -- [amode analog: CLabelledCode]
-- A labelled block of code; this "statement" is not
-- executed; rather, the labelled code will be hoisted
-- out to the top level (out of line) & it can be
| CInitHdr -- to initialise the header of a closure (both fixed/var parts)
ClosureInfo
- RegRelative -- address of the info ptr
+ CAddrMode -- address of the info ptr
CAddrMode -- cost centre to place in closure
-- CReg CurCostCentre or CC_HDR(R1.p{-Node-})
- Bool -- inplace update or allocate
| COpStmt
[CAddrMode] -- Results
PrimOp
[CAddrMode] -- Arguments
- Int -- Live registers (may be obtainable from volatility? ADR)
[MagicId] -- Potentially volatile/live registers
-- (to save/restore around the call/op)
-- For example { a := b, b := a }
-- needs to go via (at least one) temporary
+ | CCheck -- heap or stack checks, or both.
+ CCheckMacro -- These might include some code to fill in tags
+ [CAddrMode] -- on the stack, so we can't use CMacroStmt below.
+ AbstractC
+
+ | CRetDirect -- Direct return
+ !Unique -- for making labels
+ AbstractC -- return code
+ (CLabel,SRT) -- SRT info
+ Liveness -- stack liveness at the return point
+
-- see the notes about these next few; they follow below...
| CMacroStmt CStmtMacro [CAddrMode]
| CCallProfCtrMacro FAST_STRING [CAddrMode]
| CCallProfCCMacro FAST_STRING [CAddrMode]
+ {- The presence of this constructor is a makeshift solution;
+ it being used to work around a gcc-related problem of
+ handling typedefs within statement blocks (or, rather,
+ the inability to do so.)
+
+ The AbstractC flattener takes care of lifting out these
+ typedefs if needs be (i.e., when generating .hc code and
+ compiling 'foreign import dynamic's)
+ -}
+ | CCallTypedef Bool {- True => use "typedef"; False => use "extern"-}
+ CCall [CAddrMode] [CAddrMode]
+
-- *** the next three [or so...] are DATA (those above are CODE) ***
| CStaticClosure
CLabel -- The (full, not base) label to use for labelling the closure.
ClosureInfo
- CAddrMode -- cost centre identifier to place in closure
- [CAddrMode] -- free vars; ptrs, then non-ptrs
+ CAddrMode -- cost centre identifier to place in closure
+ [CAddrMode] -- free vars; ptrs, then non-ptrs.
+ | CSRT CLabel [CLabel] -- SRT declarations: basically an array of
+ -- pointers to static closures.
+
+ | CBitmap CLabel LivenessMask -- A larger-than-32-bits bitmap.
| CClosureInfoAndCode
- ClosureInfo -- Explains placement and layout of closure
- AbstractC -- Slow entry point code
+ ClosureInfo -- Explains placement and layout of closure
+ AbstractC -- Slow entry point code
(Maybe AbstractC)
- -- Fast entry point code, if any
- CAddrMode -- Address of update code; Nothing => should never be used
- -- (which is the case for all except constructors)
- String -- Closure description; NB we can't get this from
- -- ClosureInfo, because the latter refers to the *right* hand
- -- side of a defn, whereas the "description" refers to *left*
- -- hand side
- Int -- Liveness info; this is here because it is
- -- easy to produce w/in the CgMonad; hard
- -- thereafter. (WDP 95/11)
-
- | CRetVector -- Return vector with "holes"
- -- (Nothings) for the default
- CLabel -- vector-table label
- [Maybe CAddrMode]
- AbstractC -- (and what to put in a "hole" [when Nothing])
-
- | CRetUnVector -- Direct return
- CLabel -- unvector-table label
- CAddrMode -- return code
-
- | CFlatRetVector -- A labelled block of static data
- CLabel -- This is the flattened version of CRetVector
+ -- Fast entry point code, if any
+ String -- Closure description; NB we can't get this
+ -- from ClosureInfo, because the latter refers
+ -- to the *right* hand side of a defn, whereas
+ -- the "description" refers to *left* hand side
+
+ | CRetVector -- A labelled block of static data
+ CLabel
[CAddrMode]
+ (CLabel,SRT) -- SRT info
+ Liveness -- stack liveness at the return point
- | CCostCentreDecl -- A cost centre *declaration*
- Bool -- True <=> local => full declaration
- -- False <=> extern; just say so
+ | CClosureTbl -- table of constructors for enumerated types
+ TyCon -- which TyCon this table is for
+
+ | CModuleInitBlock -- module initialisation block
+ CLabel -- label for init block
+ AbstractC -- initialisation code
+
+ | CCostCentreDecl -- A cost centre *declaration*
+ Bool -- True <=> local => full declaration
+ -- False <=> extern; just say so
CostCentre
- | CClosureUpdInfo
- AbstractC -- InRegs Info Table (CClosureInfoTable)
- -- ^^^^^^^^^^^^^^^^^
- -- out of date -- HWL
+ | CCostCentreStackDecl -- A cost centre stack *declaration*
+ CostCentreStack -- this is the declaration for a
+ -- pre-defined singleton CCS (see
+ -- CostCentre.lhs)
- | CSplitMarker -- Split into separate object modules here
+ | CSplitMarker -- Split into separate object modules here
\end{code}
About @CMacroStmt@, etc.: notionally, they all just call some
overflow. This enumeration type lists all such macros:
\begin{code}
data CStmtMacro
- = ARGS_CHK_A_LOAD_NODE
- | ARGS_CHK_A
- | ARGS_CHK_B_LOAD_NODE
- | ARGS_CHK_B
- | HEAP_CHK
- | STK_CHK
- | UPD_CAF
- | UPD_IND
- | UPD_INPLACE_NOPTRS
- | UPD_INPLACE_PTRS
- | UPD_BH_UPDATABLE
- | UPD_BH_SINGLE_ENTRY
- | PUSH_STD_UPD_FRAME
- | POP_STD_UPD_FRAME
- | SET_ARITY
- | CHK_ARITY
- | SET_TAG
+ = ARGS_CHK -- arg satisfaction check
+ | ARGS_CHK_LOAD_NODE -- arg check for top-level functions
+ | UPD_CAF -- update CAF closure with indirection
+ | UPD_BH_UPDATABLE -- eager backholing
+ | UPD_BH_SINGLE_ENTRY -- more eager blackholing
+ | PUSH_UPD_FRAME -- push update frame
+ | PUSH_SEQ_FRAME -- push seq frame
+ | UPDATE_SU_FROM_UPD_FRAME -- pull Su out of the update frame
+ | SET_TAG -- set TagReg if it exists
+
+ | REGISTER_FOREIGN_EXPORT -- register a foreign exported fun
+ | REGISTER_IMPORT -- register an imported module
+ | REGISTER_DIMPORT -- register an imported module from
+ -- another DLL
+
| GRAN_FETCH -- for GrAnSim only -- HWL
| GRAN_RESCHEDULE -- for GrAnSim only -- HWL
| GRAN_FETCH_AND_RESCHEDULE -- for GrAnSim only -- HWL
| THREAD_CONTEXT_SWITCH -- for GrAnSim only -- HWL
| GRAN_YIELD -- for GrAnSim only -- HWL
- deriving Text
+\end{code}
+
+Heap/Stack checks. There are far too many of these.
+
+\begin{code}
+data CCheckMacro
+
+ = HP_CHK_NP -- heap/stack checks when
+ | STK_CHK_NP -- node points to the closure
+ | HP_STK_CHK_NP
+ | HP_CHK_SEQ_NP -- for 'seq' style case alternatives
+
+ | HP_CHK -- heap/stack checks when
+ | STK_CHK -- node doesn't point
+ | HP_STK_CHK
+ -- case alternative heap checks:
+
+ | HP_CHK_NOREGS -- no registers live
+ | HP_CHK_UNPT_R1 -- R1 is boxed/unlifted
+ | HP_CHK_UNBX_R1 -- R1 is unboxed
+ | HP_CHK_F1 -- FloatReg1 (only) is live
+ | HP_CHK_D1 -- DblReg1 (only) is live
+ | HP_CHK_L1 -- LngReg1 (only) is live
+ | HP_CHK_UT_ALT -- unboxed tuple return.
+
+ | HP_CHK_GEN -- generic heap check
\end{code}
\item[@CCallProfCtrMacro@:]
cost-centre-profiling-related action.
\end{description}
-HERE ARE SOME OLD NOTES ABOUT HEAP-CHK ENTRY POINTS:
-
-\item[@CCallStgC@:]
-Some parts of the system, {\em notably the storage manager}, are
-implemented by C~routines that must know something about the internals
-of the STG world, e.g., where the heap-pointer is. (The
-``C-as-assembler'' documents describes this stuff in detail.)
-
-This is quite a tricky business, especially with ``optimised~C,'' so
-we keep close tabs on these fellows. This enumeration type lists all
-such ``STG~C'' routines:
-
-HERE ARE SOME *OLD* NOTES ABOUT HEAP-CHK ENTRY POINTS:
-
-Heap overflow invokes the garbage collector (of your choice :-), and
-we have different entry points, to tell the GC the exact configuration
-before it.
-\begin{description}
-\item[Branch of a boxed case:]
-The @Node@ register points off to somewhere legitimate, the @TagReg@
-holds the tag, and the @RetReg@ points to the code for the
-alterative which should be resumed. (ToDo: update)
-
-\item[Branch of an unboxed case:]
-The @Node@ register points nowhere of any particular interest, a
-kind-specific register (@IntReg@, @FloatReg@, etc.) holds the unboxed
-value, and the @RetReg@ points to the code for the alternative
-which should be resumed. (ToDo: update)
-
-\item[Closure entry:]
-The @Node@ register points to the closure, and the @RetReg@ points
-to the code to be resumed. (ToDo: update)
-\end{description}
-
%************************************************************************
%* *
\subsection[CAddrMode]{C addressing modes}
%* *
%************************************************************************
-Addressing modes: these have @PrimitiveKinds@ pinned on them.
\begin{code}
data CAddrMode
= CVal RegRelative PrimRep
| CReg MagicId -- To replace (CAddr MagicId 0)
- | CTableEntry -- CVal should be generalized to allow this
- CAddrMode -- Base
- CAddrMode -- Offset
- PrimRep -- For casting
-
- | CTemp Unique PrimRep -- Temporary locations
+ | CTemp !Unique !PrimRep -- Temporary locations
-- ``Temporaries'' correspond to local variables in C, and registers in
-- native code.
| CLbl CLabel -- Labels in the runtime system, etc.
- -- See comment under CLabelledData about (String,Name)
PrimRep -- the kind is so we can generate accurate C decls
- | CUnVecLbl -- A choice of labels left up to the back end
- CLabel -- direct
- CLabel -- vectored
-
| CCharLike CAddrMode -- The address of a static char-like closure for
-- the specified character. It is guaranteed to be in
- -- the range 0..255.
+ -- the range mIN_CHARLIKE..mAX_CHARLIKE
| CIntLike CAddrMode -- The address of a static int-like closure for the
- -- specified small integer. It is guaranteed to be in the
- -- range mIN_INTLIKE..mAX_INTLIKE
+ -- specified small integer. It is guaranteed to be in
+ -- the range mIN_INTLIKE..mAX_INTLIKE
- | CString FAST_STRING -- The address of the null-terminated string
| CLit Literal
- | CLitLit FAST_STRING -- completely literal literal: just spit this String
- -- into the C output
- PrimRep
-
- | COffset HeapOffset -- A literal constant, not an offset *from* anything!
- -- ToDo: this should really be CLitOffset
-
- | CCode AbstractC -- Some code. Used mainly for return addresses.
-
- | CLabelledCode CLabel AbstractC -- Almost defunct? (ToDo?) --JSM
- -- Some code that must have a particular label
- -- (which is jumpable to)
-
- | CJoinPoint -- This is used as the amode of a let-no-escape-bound variable
- VirtualSpAOffset -- SpA and SpB values after any volatile free vars
- VirtualSpBOffset -- of the rhs have been saved on stack.
- -- Just before the code for the thing is jumped to,
- -- SpA/B will be set to these values,
- -- and then any stack-passed args pushed,
- -- then the code for this thing will be entered
+ | CJoinPoint -- This is used as the amode of a let-no-escape-bound
+ -- variable.
+ VirtualSpOffset -- Sp value after any volatile free vars
+ -- of the rhs have been saved on stack.
+ -- Just before the code for the thing is jumped to,
+ -- Sp will be set to this value,
+ -- and then any stack-passed args pushed,
+ -- then the code for this thing will be entered
| CMacroExpr
- PrimRep -- the kind of the result
+ !PrimRep -- the kind of the result
CExprMacro -- the macro to generate a value
[CAddrMode] -- and its arguments
-
- | CCostCentre -- If Bool is True ==> it to be printed as a String,
- CostCentre -- (*not* as a C identifier or some such).
- Bool -- (It's not just the double-quotes on either side;
- -- spaces and other funny characters will have been
- -- fiddled in the non-String variant.)
-
-mkCCostCentre cc
- = --ASSERT(not (currentOrSubsumedCosts cc))
- --FALSE: We do put subsumedCC in static closures
- CCostCentre cc False
\end{code}
Various C macros for values which are dependent on the back-end layout.
\begin{code}
data CExprMacro
- = INFO_PTR
- | ENTRY_CODE
- | INFO_TAG
- | EVAL_TAG
- deriving(Text)
+ = ENTRY_CODE
+ | ARG_TAG -- stack argument tagging
+ | GET_TAG -- get current constructor tag
+ | UPD_FRAME_UPDATEE
+ | CCS_HDR
\end{code}
-A tiny convenience:
+Convenience functions:
+
\begin{code}
mkIntCLit :: Int -> CAddrMode
mkIntCLit i = CLit (mkMachInt (toInteger i))
+
+mkCString :: FAST_STRING -> CAddrMode
+mkCString s = CLit (MachStr s)
+
+mkCCostCentre :: CostCentre -> CAddrMode
+mkCCostCentre cc = CLbl (mkCC_Label cc) DataPtrRep
+
+mkCCostCentreStack :: CostCentreStack -> CAddrMode
+mkCCostCentreStack ccs = CLbl (mkCCS_Label ccs) DataPtrRep
\end{code}
%************************************************************************
\begin{code}
data RegRelative
- = HpRel VirtualHeapOffset -- virtual offset of Hp
- VirtualHeapOffset -- virtual offset of The Thing
- | SpARel VirtualSpAOffset -- virtual offset of SpA
- VirtualSpAOffset -- virtual offset of The Thing
- | SpBRel VirtualSpBOffset -- virtual offset of SpB
- VirtualSpBOffset -- virtual offset of The Thing
- | NodeRel VirtualHeapOffset
+ = HpRel FastInt -- }
+ | SpRel FastInt -- }- offsets in StgWords
+ | NodeRel FastInt -- }
+ | CIndex CAddrMode CAddrMode PrimRep -- pointer arithmetic :-)
+ -- CIndex a b k === (k*)a[b]
data ReturnInfo
= DirectReturn -- Jump directly, if possible
| StaticVectoredReturn Int -- Fixed tag, starting at zero
| DynamicVectoredReturn CAddrMode -- Dynamic tag given by amode, starting at zero
+
+hpRel :: VirtualHeapOffset -- virtual offset of Hp
+ -> VirtualHeapOffset -- virtual offset of The Thing
+ -> RegRelative -- integer offset
+hpRel _IBOX(hp) _IBOX(off) = HpRel (hp _SUB_ off)
+
+spRel :: VirtualSpOffset -- virtual offset of Sp
+ -> VirtualSpOffset -- virtual offset of The Thing
+ -> RegRelative -- integer offset
+spRel sp off = SpRel (case spRelToInt sp off of { _IBOX(i) -> i })
+
+nodeRel :: VirtualHeapOffset
+ -> RegRelative
+nodeRel _IBOX(off) = NodeRel off
+
\end{code}
%************************************************************************
%* *
-\subsection[MagicId]{@MagicIds@: registers and such}
+\subsection[Liveness]{Liveness Masks}
%* *
%************************************************************************
-Much of what happens in Abstract-C is in terms of ``magic'' locations,
-such as the stack pointer, heap pointer, etc. If possible, these will
-be held in registers.
-
-Here are some notes about what's active when:
-\begin{description}
-\item[Always active:]
- Hp, HpLim, SpA, SpB, SuA, SuB
-
-\item[Entry set:]
- ArgPtr1 (= Node)...
-
-\item[Return set:]
-Ptr regs: RetPtr1 (= Node), RetPtr2...
-Int/char regs: RetData1 (= TagReg = IntReg), RetData2...
-Float regs: RetFloat1, ...
-Double regs: RetDouble1, ...
-\end{description}
+We represent liveness bitmaps as a BitSet (whose internal
+representation really is a bitmap). These are pinned onto case return
+vectors to indicate the state of the stack for the garbage collector.
\begin{code}
-data MagicId
- = BaseReg -- mentioned only in nativeGen
-
- | StkOReg -- mentioned only in nativeGen
-
- -- Argument and return registers
- | VanillaReg -- pointers, unboxed ints and chars
- PrimRep -- PtrRep, IntRep, CharRep, StablePtrRep or ForeignObjRep
- -- (in case we need to distinguish)
- FAST_INT -- its number (1 .. mAX_Vanilla_REG)
-
- | FloatReg -- single-precision floating-point registers
- FAST_INT -- its number (1 .. mAX_Float_REG)
+type LivenessMask = [BitSet]
- | DoubleReg -- double-precision floating-point registers
- FAST_INT -- its number (1 .. mAX_Double_REG)
-
- | TagReg -- to return constructor tags; as almost all returns are vectored,
- -- this is rarely used.
+data Liveness = LvSmall BitSet
+ | LvLarge CLabel
+\end{code}
- | RetReg -- topmost return address from the B stack
+%************************************************************************
+%* *
+\subsection[HeapOffset]{@Heap Offsets@}
+%* *
+%************************************************************************
- | SpA -- Stack ptr; points to last occupied stack location.
- -- Stack grows downward.
- | SuA -- mentioned only in nativeGen
+This used to be a grotesquely complicated datatype in an attempt to
+hide the details of header sizes from the compiler itself. Now these
+constants are imported from the RTS, and we deal in real Ints.
- | SpB -- Basic values, return addresses and update frames.
- -- Grows upward.
- | SuB -- mentioned only in nativeGen
+\begin{code}
+type HeapOffset = Int -- ToDo: remove
- | Hp -- Heap ptr; points to last occupied heap location.
- -- Free space at lower addresses.
+type VirtualHeapOffset = HeapOffset
+type VirtualSpOffset = Int
- | HpLim -- Heap limit register: mentioned only in nativeGen
+type HpRelOffset = HeapOffset
+type SpRelOffset = Int
+\end{code}
- | LivenessReg -- (parallel only) used when we need to record explicitly
- -- what registers are live
+%************************************************************************
+%* *
+\subsection[MagicId]{@MagicIds@: registers and such}
+%* *
+%************************************************************************
- | StdUpdRetVecReg -- mentioned only in nativeGen
- | StkStubReg -- register holding STK_STUB_closure (for stubbing dead stack slots)
+\begin{code}
+data MagicId
+ = BaseReg -- mentioned only in nativeGen
- | CurCostCentre -- current cost centre register.
+ -- Argument and return registers
+ | VanillaReg -- pointers, unboxed ints and chars
+ PrimRep
+ FastInt -- its number (1 .. mAX_Vanilla_REG)
- | VoidReg -- see "VoidPrim" type; just a placeholder; no actual register
+ | FloatReg -- single-precision floating-point registers
+ FastInt -- its number (1 .. mAX_Float_REG)
-node = VanillaReg PtrRep ILIT(1) -- A convenient alias for Node
-infoptr = VanillaReg DataPtrRep ILIT(2) -- An alias for InfoPtr
+ | DoubleReg -- double-precision floating-point registers
+ FastInt -- its number (1 .. mAX_Double_REG)
---------------------
-noLiveRegsMask :: Int -- Mask indicating nothing live
-noLiveRegsMask = 0
+ -- STG registers
+ | Sp -- Stack ptr; points to last occupied stack location.
+ | Su -- Stack update frame pointer
+ | SpLim -- Stack limit
+ | Hp -- Heap ptr; points to last occupied heap location.
+ | HpLim -- Heap limit register
+ | CurCostCentre -- current cost centre register.
+ | VoidReg -- see "VoidPrim" type; just a placeholder;
+ -- no actual register
+ | LongReg -- long int registers (64-bit, really)
+ PrimRep -- Int64Rep or Word64Rep
+ FastInt -- its number (1 .. mAX_Long_REG)
-mkLiveRegsMask
- :: [MagicId] -- Candidate live regs; depends what they have in them
- -> Int
+ | CurrentTSO -- pointer to current thread's TSO
+ | CurrentNursery -- pointer to allocation area
-mkLiveRegsMask regs
- = foldl do_reg noLiveRegsMask regs
- where
- do_reg acc (VanillaReg kind reg_no)
- | isFollowableRep kind
- = acc + (reg_tbl !! IBOX(reg_no _SUB_ ILIT(1)))
- do_reg acc anything_else = acc
+node = VanillaReg PtrRep _ILIT(1) -- A convenient alias for Node
+tagreg = VanillaReg WordRep _ILIT(2) -- A convenient alias for TagReg
- reg_tbl -- ToDo: mk Array!
- = [lIVENESS_R1, lIVENESS_R2, lIVENESS_R3, lIVENESS_R4,
- lIVENESS_R5, lIVENESS_R6, lIVENESS_R7, lIVENESS_R8]
+nodeReg = CReg node
\end{code}
We need magical @Eq@ because @VanillaReg@s come in multiple flavors.
\begin{code}
instance Eq MagicId where
- reg1 == reg2 = tagOf_MagicId reg1 _EQ_ tagOf_MagicId reg2
-
-tagOf_MagicId BaseReg = (ILIT(0) :: FAST_INT)
-tagOf_MagicId StkOReg = ILIT(1)
-tagOf_MagicId TagReg = ILIT(2)
-tagOf_MagicId RetReg = ILIT(3)
-tagOf_MagicId SpA = ILIT(4)
-tagOf_MagicId SuA = ILIT(5)
-tagOf_MagicId SpB = ILIT(6)
-tagOf_MagicId SuB = ILIT(7)
-tagOf_MagicId Hp = ILIT(8)
-tagOf_MagicId HpLim = ILIT(9)
-tagOf_MagicId LivenessReg = ILIT(10)
-tagOf_MagicId StdUpdRetVecReg = ILIT(12)
-tagOf_MagicId StkStubReg = ILIT(13)
-tagOf_MagicId CurCostCentre = ILIT(14)
-tagOf_MagicId VoidReg = ILIT(15)
-
-tagOf_MagicId (VanillaReg _ i) = ILIT(15) _ADD_ i
-
-tagOf_MagicId (FloatReg i) = ILIT(15) _ADD_ maxv _ADD_ i
- where
- maxv = case mAX_Vanilla_REG of { IBOX(x) -> x }
-
-tagOf_MagicId (DoubleReg i) = ILIT(15) _ADD_ maxv _ADD_ maxf _ADD_ i
- where
- maxv = case mAX_Vanilla_REG of { IBOX(x) -> x }
- maxf = case mAX_Float_REG of { IBOX(x) -> x }
+ reg1 == reg2 = tag reg1 ==# tag reg2
+ where
+ tag BaseReg = (_ILIT(0) :: FastInt)
+ tag Sp = _ILIT(1)
+ tag Su = _ILIT(2)
+ tag SpLim = _ILIT(3)
+ tag Hp = _ILIT(4)
+ tag HpLim = _ILIT(5)
+ tag CurCostCentre = _ILIT(6)
+ tag VoidReg = _ILIT(7)
+
+ tag (VanillaReg _ i) = _ILIT(8) +# i
+
+ tag (FloatReg i) = _ILIT(8) +# maxv +# i
+ tag (DoubleReg i) = _ILIT(8) +# maxv +# maxf +# i
+ tag (LongReg _ i) = _ILIT(8) +# maxv +# maxf +# maxd +# i
+
+ maxv = iUnbox mAX_Vanilla_REG
+ maxf = iUnbox mAX_Float_REG
+ maxd = iUnbox mAX_Double_REG
\end{code}
Returns True for any register that {\em potentially} dies across
C calls (or anything near equivalent). We just say @True@ and
let the (machine-specific) registering macros sort things out...
+
\begin{code}
isVolatileReg :: MagicId -> Bool
-
isVolatileReg any = True
---isVolatileReg (FloatReg _) = True
---isVolatileReg (DoubleReg _) = True
\end{code}
-
-%************************************************************************
-%* *
-\subsection[AbsCSyn-printing]{Pretty-printing Abstract~C}
-%* *
-%************************************************************************
-
-It's in \tr{PprAbsC.lhs}.