2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
4 \section[AbstractC]{Abstract C: the last stop before machine code}
6 This ``Abstract C'' data type describes the raw Spineless Tagless
7 machine model at a C-ish level; it is ``abstract'' in that it only
8 includes C-like structures that we happen to need. The conversion of
9 programs from @StgSyntax@ (basically a functional language) to
10 @AbstractC@ (basically imperative C) is the heart of code generation.
11 From @AbstractC@, one may convert to real C (for portability) or to
12 raw assembler/machine code.
15 #include "HsVersions.h"
24 mkAbstractCs, mkAbsCStmts, mkAlgAltsCSwitch,
29 -- HeapOffsets, plus some convenient synonyms...
31 zeroOff, intOff, fixedHdrSize, totHdrSize, varHdrSize,
32 maxOff, addOff, subOff, intOffsetIntoGoods,
33 isZeroOff, possiblyEqualHeapOffset,
35 VirtualHeapOffset(..), HpRelOffset(..),
36 VirtualSpAOffset(..), VirtualSpBOffset(..),
37 SpARelOffset(..), SpBRelOffset(..),
43 MagicId(..), node, infoptr,
47 ClosureInfo, LambdaFormInfo, UpdateFlag, SMRep,
49 -- stuff from AbsCFuns and PprAbsC...
50 nonemptyAbsC, flattenAbsC, getAmodeKind,
51 mixedTypeLocn, mixedPtrLocn,
52 #ifdef __GLASGOW_HASKELL__
56 kindFromMagicId, -- UNUSED: getDestinationRegs,
63 -- and stuff to make the interface self-sufficient
64 Outputable(..), NamedThing(..),
65 PrettyRep, ExportFlag, SrcLoc, Unique,
66 CSeq, PprStyle, Pretty(..), Unpretty(..),
70 PrimKind(..), -- re-exported NON-ABSTRACTLY
71 BasicLit(..), mkMachInt, mkMachWord, -- re-exported NON-ABSTRACTLY
72 Id, ConTag(..), Maybe, PrimOp, SplitUniqSupply, TyCon,
73 CLabel, GlobalSwitch, CostCentre,
74 SimplifierSwitch, UniqSet(..), UniqFM, StgExpr, StgAtom
77 import AbsCFuns -- used, and re-exported
78 import ClosureInfo -- ditto
80 import PprAbsC -- ditto
81 import HeapOffs hiding ( hpRelToInt )
83 import AbsPrel ( PrimOp
84 IF_ATTACK_PRAGMAS(COMMA tagOf_PrimOp)
85 IF_ATTACK_PRAGMAS(COMMA pprPrimOp)
88 import CmdLineOpts ( GlobalSwitch(..), SimplifierSwitch )
89 import BasicLit ( mkMachInt, mkMachWord, BasicLit(..) )
90 import Id ( Id, ConTag(..), DataCon(..) )
91 import Maybes ( Maybe )
93 import Unpretty -- ********** NOTE **********
94 import PrimKind ( PrimKind(..) )
95 import CostCentre -- for CostCentre type
96 import StgSyn ( StgExpr, StgAtom, StgBinderInfo )
97 import UniqSet ( UniqSet(..), UniqFM )
98 import Unique ( Unique )
102 import CgCompInfo ( mAX_Vanilla_REG, mAX_Float_REG, mAX_Double_REG )
104 import CgCompInfo ( spARelToInt, spBRelToInt )
105 import DapInfo ( virtualHeapOffsetToInt )
106 #endif {- Data Parallel Haskell -}
109 @AbstractC@ is a list of Abstract~C statements, but the data structure
110 is tree-ish, for easier and more efficient putting-together.
114 | AbsCStmts AbstractC AbstractC
116 -- and the individual stmts...
119 A note on @CAssign@: In general, the type associated with an assignment
120 is the type of the lhs. However, when the lhs is a pointer to mixed
121 types (e.g. SpB relative), the type of the assignment is the type of
122 the rhs for float types, or the generic StgWord for all other types.
123 (In particular, a CharKind on the rhs is promoted to IntKind when
124 stored in a mixed type location.)
132 CAddrMode -- Put this in the program counter
133 -- eg `CJump (CReg (VanillaReg PtrKind 1))' puts Ret1 in PC
134 -- Enter can be done by:
135 -- CJump (CVal NodeRel zeroOff)
138 CAddrMode -- Fall through into this routine
139 -- (for the benefit of the native code generators)
140 -- Equivalent to CJump in C land
142 | CReturn -- This used to be RetVecRegRel
143 CAddrMode -- Any base address mode
144 ReturnInfo -- How to get the return address from the base address
147 [(BasicLit, AbstractC)] -- alternatives
148 AbstractC -- default; if there is no real Abstract C in here
149 -- (e.g., all comments; see function "nonemptyAbsC"),
150 -- then that means the default _cannot_ occur.
151 -- If there is only one alternative & no default code,
152 -- then there is no need to check the tag.
154 -- CSwitch m [(tag,code)] AbsCNop == code
156 | CCodeBlock CLabel AbstractC
157 -- [amode analog: CLabelledCode]
158 -- A labelled block of code; this "statement" is not
159 -- executed; rather, the labelled code will be hoisted
160 -- out to the top level (out of line) & it can be
163 | CInitHdr -- to initialise the header of a closure (both fixed/var parts)
165 RegRelative -- address of the info ptr
166 CAddrMode -- cost centre to place in closure
167 -- CReg CurCostCentre or CC_HDR(R1.p{-Node-})
168 Bool -- inplace update or allocate
171 [CAddrMode] -- Results
173 [CAddrMode] -- Arguments
174 Int -- Live registers (may be obtainable from volatility? ADR)
175 [MagicId] -- Potentially volatile/live registers
176 -- (to save/restore around the call/op)
178 -- INVARIANT: When a PrimOp which can cause GC is used, the
179 -- only live data is tidily on the STG stacks or in the STG
180 -- registers (the code generator ensures this).
182 -- Why this? Because if the arguments were arbitrary
183 -- addressing modes, they might be things like (Hp+6) which
184 -- will get utterly spongled by GC.
186 | CSimultaneous -- Perform simultaneously all the statements
187 AbstractC -- in the nested AbstractC. They are only
188 -- allowed to be CAssigns, COpStmts and AbsCNops, so the
189 -- "simultaneous" part just concerns making
190 -- sure that permutations work.
191 -- For example { a := b, b := a }
192 -- needs to go via (at least one) temporary
194 -- see the notes about these next few; they follow below...
195 | CMacroStmt CStmtMacro [CAddrMode]
196 | CCallProfCtrMacro FAST_STRING [CAddrMode]
197 | CCallProfCCMacro FAST_STRING [CAddrMode]
199 -- *** the next three [or so...] are DATA (those above are CODE) ***
202 CLabel -- The (full, not base) label to use for labelling the closure.
204 CAddrMode -- cost centre identifier to place in closure
205 [CAddrMode] -- free vars; ptrs, then non-ptrs
208 | CClosureInfoAndCode
209 ClosureInfo -- Explains placement and layout of closure
210 AbstractC -- Slow entry point code
212 -- Fast entry point code, if any
213 CAddrMode -- Address of update code; Nothing => should never be used
214 -- (which is the case for all except constructors)
215 String -- Closure description; NB we can't get this from
216 -- ClosureInfo, because the latter refers to the *right* hand
217 -- side of a defn, whereas the "description" refers to *left*
219 Int -- Liveness info; this is here because it is
220 -- easy to produce w/in the CgMonad; hard
221 -- thereafter. (WDP 95/11)
223 | CRetVector -- Return vector with "holes"
224 -- (Nothings) for the default
225 CLabel -- vector-table label
227 AbstractC -- (and what to put in a "hole" [when Nothing])
229 | CRetUnVector -- Direct return
230 CLabel -- unvector-table label
231 CAddrMode -- return code
233 | CFlatRetVector -- A labelled block of static data
234 CLabel -- This is the flattened version of CRetVector
237 | CCostCentreDecl -- A cost centre *declaration*
238 Bool -- True <=> local => full declaration
239 -- False <=> extern; just say so
243 | CComment -- to insert a comment into the output
248 AbstractC -- InRegs Info Table (CClosureInfoTable)
250 -- out of date -- HWL
252 | CSplitMarker -- Split into separate object modules here
255 | CNativeInfoTableAndCode
256 ClosureInfo -- Explains placement and layout of closure
257 String -- closure description
258 AbstractC -- We want to apply the trick outlined in the STG
259 -- paper of putting the info table before the normal
260 -- entry point to a function (well a very similar
261 -- trick, see nativeDap/NOTES.static). By putting the
262 -- abstractC here we stop the info table
263 -- wandering off :-) (No post mangler hacking going
265 #endif {- Data Parallel Haskell -}
268 About @CMacroStmt@, etc.: notionally, they all just call some
269 arbitrary C~macro or routine, passing the @CAddrModes@ as arguments.
270 However, we distinguish between various flavours of these things,
271 mostly just to keep things somewhat less wild and wooly.
275 Some {\em essential} bits of the STG execution model are done with C
276 macros. An example is @STK_CHK@, which checks for stack-space
277 overflow. This enumeration type lists all such macros:
280 = ARGS_CHK_A_LOAD_NODE
282 | ARGS_CHK_B_LOAD_NODE
291 | UPD_BH_SINGLE_ENTRY
294 --UNUSED: | PUSH_CON_UPD_FRAME
299 | GRAN_FETCH -- for GrAnSim only -- HWL
300 | GRAN_RESCHEDULE -- for GrAnSim only -- HWL
301 | GRAN_FETCH_AND_RESCHEDULE -- for GrAnSim only -- HWL
302 | THREAD_CONTEXT_SWITCH -- for GrAnSim only -- HWL
308 \item[@CCallProfCtrMacro@:]
309 The @String@ names a macro that, if \tr{#define}d, will bump one/some
310 of the STG-event profiling counters.
312 \item[@CCallProfCCMacro@:]
313 The @String@ names a macro that, if \tr{#define}d, will perform some
314 cost-centre-profiling-related action.
317 HERE ARE SOME OLD NOTES ABOUT HEAP-CHK ENTRY POINTS:
320 Some parts of the system, {\em notably the storage manager}, are
321 implemented by C~routines that must know something about the internals
322 of the STG world, e.g., where the heap-pointer is. (The
323 ``C-as-assembler'' documents describes this stuff in detail.)
325 This is quite a tricky business, especially with ``optimised~C,'' so
326 we keep close tabs on these fellows. This enumeration type lists all
327 such ``STG~C'' routines:
329 HERE ARE SOME *OLD* NOTES ABOUT HEAP-CHK ENTRY POINTS:
331 Heap overflow invokes the garbage collector (of your choice :-), and
332 we have different entry points, to tell the GC the exact configuration
335 \item[Branch of a boxed case:]
336 The @Node@ register points off to somewhere legitimate, the @TagReg@
337 holds the tag, and the @RetReg@ points to the code for the
338 alterative which should be resumed. (ToDo: update)
340 \item[Branch of an unboxed case:]
341 The @Node@ register points nowhere of any particular interest, a
342 kind-specific register (@IntReg@, @FloatReg@, etc.) holds the unboxed
343 value, and the @RetReg@ points to the code for the alternative
344 which should be resumed. (ToDo: update)
346 \item[Closure entry:]
347 The @Node@ register points to the closure, and the @RetReg@ points
348 to the code to be resumed. (ToDo: update)
351 %************************************************************************
353 \subsection[CAddrMode]{C addressing modes}
355 %************************************************************************
357 Addressing modes: these have @PrimitiveKinds@ pinned on them.
360 = CVal RegRelative PrimKind
361 -- On RHS of assign: Contents of Magic[n]
362 -- On LHS of assign: location Magic[n]
363 -- (ie at addr Magic+n)
366 -- On RHS of assign: Address of Magic[n]; ie Magic+n
367 -- n=0 gets the Magic location itself
368 -- (NB: n=0 case superceded by CReg)
369 -- On LHS of assign: only sensible if n=0,
370 -- which gives the magic location itself
371 -- (NB: superceded by CReg)
373 | CReg MagicId -- To replace (CAddr MagicId 0)
375 | CTableEntry -- CVal should be generalized to allow this
378 PrimKind -- For casting
380 | CTemp Unique PrimKind -- Temporary locations
381 -- ``Temporaries'' correspond to local variables in C, and registers in
383 -- OLD: The kind (that used to be there) is redundant, but it's REALLY helpful for
384 -- generating C declarations
386 | CLbl CLabel -- Labels in the runtime system, etc.
387 -- See comment under CLabelledData about (String,Name)
388 PrimKind -- the kind is so we can generate accurate C decls
390 | CUnVecLbl -- A choice of labels left up to the back end
394 | CCharLike CAddrMode -- The address of a static char-like closure for
395 -- the specified character. It is guaranteed to be in
398 | CIntLike CAddrMode -- The address of a static int-like closure for the
399 -- specified small integer. It is guaranteed to be in the
400 -- range mIN_INTLIKE..mAX_INTLIKE
402 | CString FAST_STRING -- The address of the null-terminated string
404 | CLitLit FAST_STRING -- completely literal literal: just spit this String
408 | COffset HeapOffset -- A literal constant, not an offset *from* anything!
409 -- ToDo: this should really be CLitOffset
411 | CCode AbstractC -- Some code. Used mainly for return addresses.
413 | CLabelledCode CLabel AbstractC -- Almost defunct? (ToDo?) --JSM
414 -- Some code that must have a particular label
415 -- (which is jumpable to)
417 | CJoinPoint -- This is used as the amode of a let-no-escape-bound variable
418 VirtualSpAOffset -- SpA and SpB values after any volatile free vars
419 VirtualSpBOffset -- of the rhs have been saved on stack.
420 -- Just before the code for the thing is jumped to,
421 -- SpA/B will be set to these values,
422 -- and then any stack-passed args pushed,
423 -- then the code for this thing will be entered
426 PrimKind -- the kind of the result
427 CExprMacro -- the macro to generate a value
428 [CAddrMode] -- and its arguments
430 | CCostCentre -- If Bool is True ==> it to be printed as a String,
431 CostCentre -- (*not* as a C identifier or some such).
432 Bool -- (It's not just the double-quotes on either side;
433 -- spaces and other funny characters will have been
434 -- fiddled in the non-String variant.)
437 = --ASSERT(not (currentOrSubsumedCosts cc))
438 --FALSE: We do put subsumedCC in static closures
442 Various C macros for values which are dependent on the back-end layout.
457 mkIntCLit :: Int -> CAddrMode
458 mkIntCLit i = CLit (mkMachInt (toInteger i))
461 %************************************************************************
463 \subsection[RegRelative]{@RegRelatives@: ???}
465 %************************************************************************
469 = HpRel VirtualHeapOffset -- virtual offset of Hp
470 VirtualHeapOffset -- virtual offset of The Thing
471 | SpARel VirtualSpAOffset -- virtual offset of SpA
472 VirtualSpAOffset -- virtual offset of The Thing
473 | SpBRel VirtualSpBOffset -- virtual offset of SpB
474 VirtualSpBOffset -- virtual offset of The Thing
475 | NodeRel VirtualHeapOffset
478 = DirectReturn -- Jump directly, if possible
479 | StaticVectoredReturn Int -- Fixed tag, starting at zero
480 | DynamicVectoredReturn CAddrMode -- Dynamic tag given by amode, starting at zero
484 %************************************************************************
486 \subsection[MagicId]{@MagicIds@: registers and such}
488 %************************************************************************
490 Much of what happens in Abstract-C is in terms of ``magic'' locations,
491 such as the stack pointer, heap pointer, etc. If possible, these will
492 be held in registers.
494 Here are some notes about what's active when:
496 \item[Always active:]
497 Hp, HpLim, SpA, SpB, SuA, SuB
503 Ptr regs: RetPtr1 (= Node), RetPtr2...
504 Int/char regs: RetData1 (= TagReg = IntReg), RetData2...
505 Float regs: RetFloat1, ...
506 Double regs: RetDouble1, ...
511 = BaseReg -- mentioned only in nativeGen
513 | StkOReg -- mentioned only in nativeGen
515 -- Argument and return registers
516 | VanillaReg -- pointers, unboxed ints and chars
517 PrimKind -- PtrKind, IntKind, CharKind, StablePtrKind or MallocPtrKind
518 -- (in case we need to distinguish)
519 FAST_INT -- its number (1 .. mAX_Vanilla_REG)
521 | FloatReg -- single-precision floating-point registers
522 FAST_INT -- its number (1 .. mAX_Float_REG)
524 | DoubleReg -- double-precision floating-point registers
525 FAST_INT -- its number (1 .. mAX_Double_REG)
527 | TagReg -- to return constructor tags; as almost all returns are vectored,
528 -- this is rarely used.
530 | RetReg -- topmost return address from the B stack
532 | SpA -- Stack ptr; points to last occupied stack location.
533 -- Stack grows downward.
534 | SuA -- mentioned only in nativeGen
536 | SpB -- Basic values, return addresses and update frames.
538 | SuB -- mentioned only in nativeGen
540 | Hp -- Heap ptr; points to last occupied heap location.
541 -- Free space at lower addresses.
543 | HpLim -- Heap limit register: mentioned only in nativeGen
545 | LivenessReg -- (parallel only) used when we need to record explicitly
546 -- what registers are live
548 | ActivityReg -- mentioned only in nativeGen (UNUSED)
549 | StdUpdRetVecReg -- mentioned only in nativeGen
550 | StkStubReg -- register holding STK_STUB_closure (for stubbing dead stack slots)
552 | CurCostCentre -- current cost centre register.
554 | VoidReg -- see "VoidPrim" type; just a placeholder; no actual register
558 -- (VanillaReg X) for pointers, ints, chars floats
559 -- (DataReg X) for ints chars or floats
560 -- (DoubleReg X) first 32 bits of double in register X, second 32 in
561 -- register X+1; DoubleReg is a synonymn for
562 -- DataReg X; DataReg X+1
567 #endif {- Data Parallel Haskell -}
569 node = VanillaReg PtrKind ILIT(1) -- A convenient alias for Node
570 infoptr = VanillaReg DataPtrKind ILIT(2) -- An alias for InfoPtr
573 We need magical @Eq@ because @VanillaReg@s come in multiple flavors.
576 instance Eq MagicId where
578 (FloatReg f1) == (FloatReg f2) = f1 == f2
579 (DoubleReg d1) == (DoubleReg d2) = d1 == d2
580 (DataReg _ d1) == (DataReg _ d2) = d1 == d2
581 #endif {- Data Parallel Haskell -}
582 reg1 == reg2 = tagOf_MagicId reg1 _EQ_ tagOf_MagicId reg2
584 tagOf_MagicId BaseReg = (ILIT(0) :: FAST_INT)
585 tagOf_MagicId StkOReg = ILIT(1)
586 tagOf_MagicId TagReg = ILIT(2)
587 tagOf_MagicId RetReg = ILIT(3)
588 tagOf_MagicId SpA = ILIT(4)
589 tagOf_MagicId SuA = ILIT(5)
590 tagOf_MagicId SpB = ILIT(6)
591 tagOf_MagicId SuB = ILIT(7)
592 tagOf_MagicId Hp = ILIT(8)
593 tagOf_MagicId HpLim = ILIT(9)
594 tagOf_MagicId LivenessReg = ILIT(10)
595 --tagOf_MagicId ActivityReg = ILIT(11) -- UNUSED
596 tagOf_MagicId StdUpdRetVecReg = ILIT(12)
597 tagOf_MagicId StkStubReg = ILIT(13)
598 tagOf_MagicId CurCostCentre = ILIT(14)
599 tagOf_MagicId VoidReg = ILIT(15)
601 tagOf_MagicId (VanillaReg _ i) = ILIT(15) _ADD_ i
604 tagOf_MagicId (FloatReg i) = ILIT(15) _ADD_ maxv _ADD_ i
606 maxv = case mAX_Vanilla_REG of { IBOX(x) -> x }
608 tagOf_MagicId (DoubleReg i) = ILIT(15) _ADD_ maxv _ADD_ maxf _ADD_ i
610 maxv = case mAX_Vanilla_REG of { IBOX(x) -> x }
611 maxf = case mAX_Float_REG of { IBOX(x) -> x }
614 tagOf_MagicId (DoubleReg i) = ILIT(1066) _ADD_ i -- Hacky, but we want disjoint
615 tagOf_MagicId (DataReg _ IBOX(i)) = ILIT(1066) _ADD_ i -- range with Vanillas
616 #endif {- Data Parallel Haskell -}
619 Returns True for any register that {\em potentially} dies across
620 C calls (or anything near equivalent). We just say @True@ and
621 let the (machine-specific) registering macros sort things out...
623 isVolatileReg :: MagicId -> Bool
625 isVolatileReg any = True
626 --isVolatileReg (FloatReg _) = True
627 --isVolatileReg (DoubleReg _) = True
630 %************************************************************************
632 \subsection[AbsCSyn-printing]{Pretty-printing Abstract~C}
634 %************************************************************************
636 It's in \tr{PprAbsC.lhs}.
638 %************************************************************************
640 \subsection[EqInstances]{Eq instance for RegRelative & CAddrMode}
642 %************************************************************************
644 DPH requires CAddrMode to be in class Eq for its register allocation
645 algorithm. The code for equality is rather conservative --- it doesnt
646 matter if two things are determined to be not equal (even if they really are,
647 i.e with CVal's), we just generate less efficient code.
649 NOTE(07/04/93) It does matter, its doing really bad with the reg relative
654 instance Eq CAddrMode where
655 (CVal r _) == (CVal r' _) = r `eqRRel` r'
656 (CAddr r) == (CAddr r') = r `eqRRel` r'
657 (CReg reg) == (CReg reg') = reg == reg'
658 (CTemp u _) == (CTemp u' _) = u == u'
659 (CLbl l _) == (CLbl l' _) = l == l'
660 (CUnVecLbl d v) == (CUnVecLbl d' v') = d == d' && v == v'
661 (CCharLike c) == (CCharLike c') = c == c'
662 (CIntLike c) == (CIntLike c') = c == c'
663 (CString str) == (CString str') = str == str'
664 (CLit lit) == (CLit lit') = lit == lit'
665 (COffset off) == (COffset off') = possiblyEqualHeapOffset off off'
666 (CCode _) == (CCode _) = panic "(==) Code in CAddrMode"
667 (CLabelledCode _ _) == (CLabelledCode _ _)= panic "(==) LabCode in CAddrMode"
671 eqRRel :: RegRelative -> RegRelative -> Bool
672 eqRRel (NodeRel x) (NodeRel y)
673 = virtualHeapOffsetToInt x == virtualHeapOffsetToInt y
675 eqRRel l@(SpARel _ _) r@(SpARel _ _)
676 = spARelToInt l == spARelToInt r
678 eqRRel l@(SpBRel _ _) r@(SpBRel _ _)
679 = spBRelToInt l == spBRelToInt r
681 eqRRel (HpRel hp off) (HpRel hp' off')
682 = (virtualHeapOffsetToInt (hp `subOff` off)) ==
683 (virtualHeapOffsetToInt (hp' `subOff` off'))
687 eqRetInfo:: ReturnInfo -> ReturnInfo -> Bool
688 eqRetInfo DirectReturn DirectReturn = True
689 eqRetInfo (StaticVectoredReturn x) (StaticVectoredReturn x') = x == x'
690 eqRetInfo _ _ = False
691 #endif {- Data Parallel Haskell -}