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*
220 | CRetVector -- Return vector with "holes"
221 -- (Nothings) for the default
222 CLabel -- vector-table label
224 AbstractC -- (and what to put in a "hole" [when Nothing])
226 | CRetUnVector -- Direct return
227 CLabel -- unvector-table label
228 CAddrMode -- return code
230 | CFlatRetVector -- A labelled block of static data
231 CLabel -- This is the flattened version of CRetVector
234 | CCostCentreDecl -- A cost centre *declaration*
235 Bool -- True <=> local => full declaration
236 -- False <=> extern; just say so
240 | CComment -- to insert a comment into the output
245 AbstractC -- InRegs Info Table (CClosureInfoTable)
247 -- out of date -- HWL
249 | CSplitMarker -- Split into separate object modules here
252 | CNativeInfoTableAndCode
253 ClosureInfo -- Explains placement and layout of closure
254 String -- closure description
255 AbstractC -- We want to apply the trick outlined in the STG
256 -- paper of putting the info table before the normal
257 -- entry point to a function (well a very similar
258 -- trick, see nativeDap/NOTES.static). By putting the
259 -- abstractC here we stop the info table
260 -- wandering off :-) (No post mangler hacking going
262 #endif {- Data Parallel Haskell -}
265 About @CMacroStmt@, etc.: notionally, they all just call some
266 arbitrary C~macro or routine, passing the @CAddrModes@ as arguments.
267 However, we distinguish between various flavours of these things,
268 mostly just to keep things somewhat less wild and wooly.
272 Some {\em essential} bits of the STG execution model are done with C
273 macros. An example is @STK_CHK@, which checks for stack-space
274 overflow. This enumeration type lists all such macros:
277 = ARGS_CHK_A_LOAD_NODE
279 | ARGS_CHK_B_LOAD_NODE
288 | UPD_BH_SINGLE_ENTRY
291 --UNUSED: | PUSH_CON_UPD_FRAME
296 | GRAN_FETCH -- for GrAnSim only -- HWL
297 | GRAN_RESCHEDULE -- for GrAnSim only -- HWL
298 | GRAN_FETCH_AND_RESCHEDULE -- for GrAnSim only -- HWL
299 | THREAD_CONTEXT_SWITCH -- for GrAnSim only -- HWL
305 \item[@CCallProfCtrMacro@:]
306 The @String@ names a macro that, if \tr{#define}d, will bump one/some
307 of the STG-event profiling counters.
309 \item[@CCallProfCCMacro@:]
310 The @String@ names a macro that, if \tr{#define}d, will perform some
311 cost-centre-profiling-related action.
314 HERE ARE SOME OLD NOTES ABOUT HEAP-CHK ENTRY POINTS:
317 Some parts of the system, {\em notably the storage manager}, are
318 implemented by C~routines that must know something about the internals
319 of the STG world, e.g., where the heap-pointer is. (The
320 ``C-as-assembler'' documents describes this stuff in detail.)
322 This is quite a tricky business, especially with ``optimised~C,'' so
323 we keep close tabs on these fellows. This enumeration type lists all
324 such ``STG~C'' routines:
326 HERE ARE SOME *OLD* NOTES ABOUT HEAP-CHK ENTRY POINTS:
328 Heap overflow invokes the garbage collector (of your choice :-), and
329 we have different entry points, to tell the GC the exact configuration
332 \item[Branch of a boxed case:]
333 The @Node@ register points off to somewhere legitimate, the @TagReg@
334 holds the tag, and the @RetReg@ points to the code for the
335 alterative which should be resumed. (ToDo: update)
337 \item[Branch of an unboxed case:]
338 The @Node@ register points nowhere of any particular interest, a
339 kind-specific register (@IntReg@, @FloatReg@, etc.) holds the unboxed
340 value, and the @RetReg@ points to the code for the alternative
341 which should be resumed. (ToDo: update)
343 \item[Closure entry:]
344 The @Node@ register points to the closure, and the @RetReg@ points
345 to the code to be resumed. (ToDo: update)
348 %************************************************************************
350 \subsection[CAddrMode]{C addressing modes}
352 %************************************************************************
354 Addressing modes: these have @PrimitiveKinds@ pinned on them.
357 = CVal RegRelative PrimKind
358 -- On RHS of assign: Contents of Magic[n]
359 -- On LHS of assign: location Magic[n]
360 -- (ie at addr Magic+n)
363 -- On RHS of assign: Address of Magic[n]; ie Magic+n
364 -- n=0 gets the Magic location itself
365 -- (NB: n=0 case superceded by CReg)
366 -- On LHS of assign: only sensible if n=0,
367 -- which gives the magic location itself
368 -- (NB: superceded by CReg)
370 | CReg MagicId -- To replace (CAddr MagicId 0)
372 | CTableEntry -- CVal should be generalized to allow this
375 PrimKind -- For casting
377 | CTemp Unique PrimKind -- Temporary locations
378 -- ``Temporaries'' correspond to local variables in C, and registers in
380 -- OLD: The kind (that used to be there) is redundant, but it's REALLY helpful for
381 -- generating C declarations
383 | CLbl CLabel -- Labels in the runtime system, etc.
384 -- See comment under CLabelledData about (String,Name)
385 PrimKind -- the kind is so we can generate accurate C decls
387 | CUnVecLbl -- A choice of labels left up to the back end
391 | CCharLike CAddrMode -- The address of a static char-like closure for
392 -- the specified character. It is guaranteed to be in
395 | CIntLike CAddrMode -- The address of a static int-like closure for the
396 -- specified small integer. It is guaranteed to be in the
397 -- range mIN_INTLIKE..mAX_INTLIKE
399 | CString FAST_STRING -- The address of the null-terminated string
401 | CLitLit FAST_STRING -- completely literal literal: just spit this String
405 | COffset HeapOffset -- A literal constant, not an offset *from* anything!
406 -- ToDo: this should really be CLitOffset
408 | CCode AbstractC -- Some code. Used mainly for return addresses.
410 | CLabelledCode CLabel AbstractC -- Almost defunct? (ToDo?) --JSM
411 -- Some code that must have a particular label
412 -- (which is jumpable to)
414 | CJoinPoint -- This is used as the amode of a let-no-escape-bound variable
415 VirtualSpAOffset -- SpA and SpB values after any volatile free vars
416 VirtualSpBOffset -- of the rhs have been saved on stack.
417 -- Just before the code for the thing is jumped to,
418 -- SpA/B will be set to these values,
419 -- and then any stack-passed args pushed,
420 -- then the code for this thing will be entered
423 PrimKind -- the kind of the result
424 CExprMacro -- the macro to generate a value
425 [CAddrMode] -- and its arguments
427 | CCostCentre -- If Bool is True ==> it to be printed as a String,
428 CostCentre -- (*not* as a C identifier or some such).
429 Bool -- (It's not just the double-quotes on either side;
430 -- spaces and other funny characters will have been
431 -- fiddled in the non-String variant.)
434 = --ASSERT(not (currentOrSubsumedCosts cc))
435 --FALSE: We do put subsumedCC in static closures
439 Various C macros for values which are dependent on the back-end layout.
454 mkIntCLit :: Int -> CAddrMode
455 mkIntCLit i = CLit (mkMachInt (toInteger i))
458 %************************************************************************
460 \subsection[RegRelative]{@RegRelatives@: ???}
462 %************************************************************************
466 = HpRel VirtualHeapOffset -- virtual offset of Hp
467 VirtualHeapOffset -- virtual offset of The Thing
468 | SpARel VirtualSpAOffset -- virtual offset of SpA
469 VirtualSpAOffset -- virtual offset of The Thing
470 | SpBRel VirtualSpBOffset -- virtual offset of SpB
471 VirtualSpBOffset -- virtual offset of The Thing
472 | NodeRel VirtualHeapOffset
475 = DirectReturn -- Jump directly, if possible
476 | StaticVectoredReturn Int -- Fixed tag, starting at zero
477 | DynamicVectoredReturn CAddrMode -- Dynamic tag given by amode, starting at zero
481 %************************************************************************
483 \subsection[MagicId]{@MagicIds@: registers and such}
485 %************************************************************************
487 Much of what happens in Abstract-C is in terms of ``magic'' locations,
488 such as the stack pointer, heap pointer, etc. If possible, these will
489 be held in registers.
491 Here are some notes about what's active when:
493 \item[Always active:]
494 Hp, HpLim, SpA, SpB, SuA, SuB
500 Ptr regs: RetPtr1 (= Node), RetPtr2...
501 Int/char regs: RetData1 (= TagReg = IntReg), RetData2...
502 Float regs: RetFloat1, ...
503 Double regs: RetDouble1, ...
508 = BaseReg -- mentioned only in nativeGen
510 | StkOReg -- mentioned only in nativeGen
512 -- Argument and return registers
513 | VanillaReg -- pointers, unboxed ints and chars
514 PrimKind -- PtrKind, IntKind, CharKind, StablePtrKind or MallocPtrKind
515 -- (in case we need to distinguish)
516 FAST_INT -- its number (1 .. mAX_Vanilla_REG)
518 | FloatReg -- single-precision floating-point registers
519 FAST_INT -- its number (1 .. mAX_Float_REG)
521 | DoubleReg -- double-precision floating-point registers
522 FAST_INT -- its number (1 .. mAX_Double_REG)
524 | TagReg -- to return constructor tags; as almost all returns are vectored,
525 -- this is rarely used.
527 | RetReg -- topmost return address from the B stack
529 | SpA -- Stack ptr; points to last occupied stack location.
530 -- Stack grows downward.
531 | SuA -- mentioned only in nativeGen
533 | SpB -- Basic values, return addresses and update frames.
535 | SuB -- mentioned only in nativeGen
537 | Hp -- Heap ptr; points to last occupied heap location.
538 -- Free space at lower addresses.
540 | HpLim -- Heap limit register: mentioned only in nativeGen
542 | LivenessReg -- (parallel only) used when we need to record explicitly
543 -- what registers are live
545 | ActivityReg -- mentioned only in nativeGen
546 | StdUpdRetVecReg -- mentioned only in nativeGen
547 | StkStubReg -- register holding STK_STUB_closure (for stubbing dead stack slots)
549 | CurCostCentre -- current cost centre register.
551 | VoidReg -- see "VoidPrim" type; just a placeholder; no actual register
555 -- (VanillaReg X) for pointers, ints, chars floats
556 -- (DataReg X) for ints chars or floats
557 -- (DoubleReg X) first 32 bits of double in register X, second 32 in
558 -- register X+1; DoubleReg is a synonymn for
559 -- DataReg X; DataReg X+1
564 #endif {- Data Parallel Haskell -}
566 node = VanillaReg PtrKind ILIT(1) -- A convenient alias for Node
567 infoptr = VanillaReg DataPtrKind ILIT(2) -- An alias for InfoPtr
570 We need magical @Eq@ because @VanillaReg@s come in multiple flavors.
573 instance Eq MagicId where
575 (FloatReg f1) == (FloatReg f2) = f1 == f2
576 (DoubleReg d1) == (DoubleReg d2) = d1 == d2
577 (DataReg _ d1) == (DataReg _ d2) = d1 == d2
578 #endif {- Data Parallel Haskell -}
579 reg1 == reg2 = tagOf_MagicId reg1 _EQ_ tagOf_MagicId reg2
581 tagOf_MagicId BaseReg = (ILIT(0) :: FAST_INT)
582 tagOf_MagicId StkOReg = ILIT(1)
583 tagOf_MagicId TagReg = ILIT(2)
584 tagOf_MagicId RetReg = ILIT(3)
585 tagOf_MagicId SpA = ILIT(4)
586 tagOf_MagicId SuA = ILIT(5)
587 tagOf_MagicId SpB = ILIT(6)
588 tagOf_MagicId SuB = ILIT(7)
589 tagOf_MagicId Hp = ILIT(8)
590 tagOf_MagicId HpLim = ILIT(9)
591 tagOf_MagicId LivenessReg = ILIT(10)
592 tagOf_MagicId ActivityReg = ILIT(11)
593 tagOf_MagicId StdUpdRetVecReg = ILIT(12)
594 tagOf_MagicId StkStubReg = ILIT(13)
595 tagOf_MagicId CurCostCentre = ILIT(14)
596 tagOf_MagicId VoidReg = ILIT(15)
598 tagOf_MagicId (VanillaReg _ i) = ILIT(15) _ADD_ i
601 tagOf_MagicId (FloatReg i) = ILIT(15) _ADD_ maxv _ADD_ i
603 maxv = case mAX_Vanilla_REG of { IBOX(x) -> x }
605 tagOf_MagicId (DoubleReg i) = ILIT(15) _ADD_ maxv _ADD_ maxf _ADD_ i
607 maxv = case mAX_Vanilla_REG of { IBOX(x) -> x }
608 maxf = case mAX_Float_REG of { IBOX(x) -> x }
611 tagOf_MagicId (DoubleReg i) = ILIT(1066) _ADD_ i -- Hacky, but we want disjoint
612 tagOf_MagicId (DataReg _ IBOX(i)) = ILIT(1066) _ADD_ i -- range with Vanillas
613 #endif {- Data Parallel Haskell -}
616 Returns True for any register that {\em potentially} dies across
617 C calls (or anything near equivalent). We just say @True@ and
618 let the (machine-specific) registering macros sort things out...
620 isVolatileReg :: MagicId -> Bool
622 isVolatileReg any = True
623 --isVolatileReg (FloatReg _) = True
624 --isVolatileReg (DoubleReg _) = True
627 %************************************************************************
629 \subsection[AbsCSyn-printing]{Pretty-printing Abstract~C}
631 %************************************************************************
633 It's in \tr{PprAbsC.lhs}.
635 %************************************************************************
637 \subsection[EqInstances]{Eq instance for RegRelative & CAddrMode}
639 %************************************************************************
641 DPH requires CAddrMode to be in class Eq for its register allocation
642 algorithm. The code for equality is rather conservative --- it doesnt
643 matter if two things are determined to be not equal (even if they really are,
644 i.e with CVal's), we just generate less efficient code.
646 NOTE(07/04/93) It does matter, its doing really bad with the reg relative
651 instance Eq CAddrMode where
652 (CVal r _) == (CVal r' _) = r `eqRRel` r'
653 (CAddr r) == (CAddr r') = r `eqRRel` r'
654 (CReg reg) == (CReg reg') = reg == reg'
655 (CTemp u _) == (CTemp u' _) = u == u'
656 (CLbl l _) == (CLbl l' _) = l == l'
657 (CUnVecLbl d v) == (CUnVecLbl d' v') = d == d' && v == v'
658 (CCharLike c) == (CCharLike c') = c == c'
659 (CIntLike c) == (CIntLike c') = c == c'
660 (CString str) == (CString str') = str == str'
661 (CLit lit) == (CLit lit') = lit == lit'
662 (COffset off) == (COffset off') = possiblyEqualHeapOffset off off'
663 (CCode _) == (CCode _) = panic "(==) Code in CAddrMode"
664 (CLabelledCode _ _) == (CLabelledCode _ _)= panic "(==) LabCode in CAddrMode"
668 eqRRel :: RegRelative -> RegRelative -> Bool
669 eqRRel (NodeRel x) (NodeRel y)
670 = virtualHeapOffsetToInt x == virtualHeapOffsetToInt y
672 eqRRel l@(SpARel _ _) r@(SpARel _ _)
673 = spARelToInt l == spARelToInt r
675 eqRRel l@(SpBRel _ _) r@(SpBRel _ _)
676 = spBRelToInt l == spBRelToInt r
678 eqRRel (HpRel hp off) (HpRel hp' off')
679 = (virtualHeapOffsetToInt (hp `subOff` off)) ==
680 (virtualHeapOffsetToInt (hp' `subOff` off'))
684 eqRetInfo:: ReturnInfo -> ReturnInfo -> Bool
685 eqRetInfo DirectReturn DirectReturn = True
686 eqRetInfo (StaticVectoredReturn x) (StaticVectoredReturn x') = x == x'
687 eqRetInfo _ _ = False
688 #endif {- Data Parallel Haskell -}