cmm-notes 22 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
More notes (June 11)
~~~~~~~~~~~~~~~~~~~~
* Possible refactoring: Nuke AGraph in favour of 
      mkIfThenElse :: Expr -> Graph -> Graph -> FCode Graph
  or even
      mkIfThenElse :: HasUniques m => Expr -> Graph -> Graph -> m Graph
  (Remmber that the .cmm file parser must use this function)

  or parameterise FCode over its envt; the CgState part seem useful for both

* Move top and tail calls to runCmmContFlowOpts from HscMain to CmmCps.cpsTop
  (and rename the latter!)

* "Remove redundant reloads" in CmmSpillReload should be redundant; since
  insertLateReloads is now gone, every reload is reloading a live variable.
  Test and nuke.

* Sink and inline S(RegSlot(x)) = e in precisely the same way that we
  sink and inline x = e

* Stack layout is very like register assignment: find non-conflicting assigments.
  In particular we can use colouring or linear scan (etc).

  We'd fine-grain interference (on a word by word basis) to get maximum overlap.
  But that may make very big interference graphs.  So linear scan might be
  more attactive.

  NB: linear scan does on-the-fly live range splitting.

* When stubbing dead slots be careful not to write into an area that
  overlaps with an area that's in use.  So stubbing needs to *follow* 
  stack layout.


Simon Peyton Jones's avatar
Simon Peyton Jones committed
35 36 37 38
More notes (May 11)
~~~~~~~~~~~~~~~~~~~
In CmmNode, consider spliting CmmCall into two: call and jump

39
Notes on new codegen (Aug 10)
40 41 42
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Things to do:
43 44 45
 - We insert spills for variables before the stack check! This is the reason for
   some fishy code in StgCmmHeap.entryHeapCheck where we are doing some strange
	things to fix up the stack pointer before GC calls/jumps.
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
46

47 48 49 50 51 52 53 54 55
	The reason spills are inserted before the sp check is that at the entry to a
	function we always store the parameters passed in registers to local variables.
	The spill pass simply inserts spills at variable definitions. We instead should
	sink the spills so that we can avoid spilling them on branches that never
	reload them.

	This will fix the spill before stack check problem but only really as a side
	effect. A 'real fix' probably requires making the spiller know about sp checks.

Edward Z. Yang's avatar
Edward Z. Yang committed
56
   EZY: I don't understand this comment. David Terei, can you clarify?
57

Edward Z. Yang's avatar
Edward Z. Yang committed
58 59 60
 - Proc points pass all arguments on the stack, adding more code and
   slowing down things a lot. We either need to fix this or even better
   would be to get rid of proc points.
61 62 63 64 65 66 67 68 69

 - CmmInfo.cmmToRawCmm uses Old.Cmm, so it is called after converting Cmm.Cmm to
   Old.Cmm. We should abstract it to work on both representations, it needs only to
   convert a CmmInfoTable to [CmmStatic].

 - The MkGraph currenty uses a different semantics for <*> than Hoopl. Maybe
   we could convert codeGen/StgCmm* clients to the Hoopl's semantics?
   It's all deeply unsatisfactory.

Edward Z. Yang's avatar
Edward Z. Yang committed
70
 - Improve performance of Hoopl.
71 72 73 74 75

   A nofib comparison of -fasm vs -fnewcodegen nofib compilation parameters
   (using the same ghc-cmm branch +libraries compiled by the old codegenerator)
   is at http://fox.auryn.cz/msrc/0517_hoopl/32bit.oldghcoldgen.oldghchoopl.txt
   - the code produced is 10.9% slower, the compilation is +118% slower!
76

77 78 79
   The same comparison with ghc-head with zip representation is at
   http://fox.auryn.cz/msrc/0517_hoopl/32bit.oldghcoldgen.oldghczip.txt
   - the code produced is 11.7% slower, the compilation is +78% slower.
80

81 82 83 84
   When compiling nofib, ghc-cmm + libraries compiled with -fnew-codegen
   is 23.7% slower (http://fox.auryn.cz/msrc/0517_hoopl/32bit.oldghcoldgen.hooplghcoldgen.txt).
   When compiling nofib, ghc-head + libraries compiled with -fnew-codegen
   is 31.4% slower (http://fox.auryn.cz/msrc/0517_hoopl/32bit.oldghcoldgen.zipghcoldgen.txt).
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
85

86 87
   So we generate a bit better code, but it takes us longer!

Edward Z. Yang's avatar
Edward Z. Yang committed
88 89 90
   EZY: Also importantly, Hoopl uses dramatically more memory than the
   old code generator.

91 92 93 94 95 96 97
 - Are all blockToNodeList and blockOfNodeList really needed? Maybe we could
   splice blocks instead?

   In the CmmContFlowOpt.blockConcat, using Dataflow seems too clumsy. Still,
   a block catenation function would be probably nicer than blockToNodeList
   / blockOfNodeList combo.

Edward Z. Yang's avatar
Edward Z. Yang committed
98
 - lowerSafeForeignCall seems too lowlevel. Just use Dataflow. After that
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
   delete splitEntrySeq from HooplUtils.

 - manifestSP seems to touch a lot of the graph representation. It is
   also slow for CmmSwitch nodes O(block_nodes * switch_statements).
   Maybe rewrite manifestSP to use Dataflow?

 - Sort out Label, LabelMap, LabelSet versus BlockId, BlockEnv, BlockSet
   dichotomy. Mostly this means global replace, but we also need to make
   Label an instance of Outputable (probably in the Outputable module).

 - NB that CmmProcPoint line 283 has a hack that works around a GADT-related
   bug in 6.10.

 - SDM (2010-02-26) can we remove the Foreign constructor from Convention?
   Reason: we never generate code for a function with the Foreign
   calling convention, and the code for calling foreign calls is generated
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
115 116

 - AsmCodeGen has a generic Cmm optimiser; move this into new pipeline
Edward Z. Yang's avatar
Edward Z. Yang committed
117 118 119
   EZY (2011-04-16): The mini-inliner has been generalized and ported,
   but the constant folding and other optimizations need to still be
   ported.
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
120

121
 - AsmCodeGen has post-native-cg branch eliminator (shortCutBranches);
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
122 123 124
   we ultimately want to share this with the Cmm branch eliminator.

 - At the moment, references to global registers like Hp are "lowered" 
125 126 127
   late (in CgUtils.fixStgRegisters). We should do this early, in the
	new native codegen, much in the way that we lower calling conventions.
	Might need to be a bit sophisticated about aliasing.
128 129 130 131 132 133 134 135 136 137 138 139

 - Question: currently we lift procpoints to become separate
   CmmProcs.  Do we still want to do this?
    
   NB: and advantage of continuing to do this is that
   we can do common-proc elimination!

 - Move to new Cmm rep:
     * Make native CG consume New Cmm; 
     * Convert Old Cmm->New Cmm to keep old path alive
     * Produce New Cmm when reading in .cmm files

simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
140 141
 - Consider module names

142 143 144 145 146 147 148 149 150 151
 - Top-level SRT threading is a bit ugly

 - Add type/newtype for CmmModule = [CmmGroup]    -- A module
                        CmmGroup  = [CmmTop]      -- A .o file
                        CmmTop    = Proc | Data   -- A procedure or data

 - This is a *change*: currently a CmmGroup is one function's-worth of code
   regardless of SplitObjs.   Question: can we *always* generate M.o if there
   is just one element in the list (rather than M/M1.o, M/M2.o etc)

simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
152 153 154 155
   One SRT per group.

 - See "CAFs" below; we want to totally refactor the way SRTs are calculated

156
 - Pull out Areas into its own module
Edward Z. Yang's avatar
Edward Z. Yang committed
157
   Parameterise AreaMap (note there are type synonyms in CmmStackLayout!)
158 159 160 161
   Add ByteWidth = Int
   type SubArea    = (Area, ByteOff, ByteWidth) 
   ByteOff should not be defined in SMRep -- that is too high up the hierarchy
   
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
162 163 164 165 166
 - SMRep should not be imported by any module in cmm/!  Make it so.
	-- ByteOff etc   ==>  CmmExpr
        -- rET_SMALL etc ==> CmmInfo
   Check that there are no other imports from codeGen in cmm/

167 168 169
 - If you eliminate a label by branch chain elimination,
   what happens if there's an Area associated with that label?

170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
 - Think about a non-flattened representation?

 - LastCall: 
    * Use record fields for LastCall!
    * cml_ret_off should be a ByteOff
    * Split into 
         LastCall (which has a successor) and
         LastJump (which does not, includes return?)
	   - does not have cml_cont, cml_ret_args, cml_ret_off
	 LastForeignCall 
           - safe! 
           - expands into save/MidForeignCall/restore/goto
	   - like any LastCall, target of the call gets an info table

 - JD: remind self of what goes wrong if you turn off the 
   liveness of the update frame

 - Garbage-collect http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/CPS
   moving good stuff into 
   http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/NewCodeGenPipeline


192
 - We believe that all of CmmProcPoint.addProcPointProtocols is dead.  What
193 194 195 196 197 198 199 200 201 202 203
   goes wrong if we simply never call it?

 - Something fishy in CmmStackLayout.hs
   * In particular, 'getAreaSize' returns an AreaMap, but we *know* the width of
	LocalRegs, so it'd be better to return FiniteMap AreaId ByteWidth
   * setSuccSPs looks fishy.  Rather than lookin in procPoints, it could
	just lookup the block in areaSize which, after all, has a binding
	for precisely successors of calls.  All other blocks (including proc
        points that are not successors of a call, we think) can be treated
        uniformly: zero-size Area, and use inSP.

simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240

 - Currently AsmCodeGen top level calls AsmCodeGen.cmmToCmm, which is a small
   C-- optimiser.  It has quite a lot of boilerplate folding code in AsmCodeGen
   (cmmBlockConFold, cmmStmtConFold, cmmExprConFold), before calling out to
   CmmOpt.  ToDo: see what optimisations are being done; and do them before
   AsmCodeGen.

 - Modularise the CPS pipeline; instead of ...; A;B;C; ...
                                use  ..; ABC; ....

 - Most of HscMain.tryNewCodeGen does not belong in HscMain.  Instead
	if new_cg then
             StgCmm.codeGen
             processCmm  [including generating "raw" cmm]
        else
             CodeGen.codeGen
             cmmToRawCmm


 - If we stick CAF and stack liveness info on a LastCall node (not LastRet/Jump)
   then all CAF and stack liveness stuff be completed before we split
   into separate C procedures.

   Short term:
     compute and attach liveness into to LastCall
     right at end, split, cvt to old rep
     [must split before cvt, because old rep is not expressive enough]

   Longer term: 
     when old rep disappears, 
     move the whole splitting game into the C back end *only*
	 (guided by the procpoint set)

----------------------------------------------------
	Modules in cmm/
----------------------------------------------------

241
-------- Testing stuff ------------
242 243
HscMain.optionallyConvertAndOrCPS
        testCmmConversion
244
DynFlags:  -fconvert-to-zipper-and-back, -frun-cpsz
245

simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
246
-------- Moribund stuff ------------
247 248 249
OldCmm.hs      Definition of flowgraph of old representation
OldCmmUtil.hs  Utilites that operates mostly on on CmmStmt
OldPprCmm.hs   Pretty print for CmmStmt, GenBasicBlock and ListGraph
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
250 251
CmmCvt.hs      Conversion between old and new Cmm reps
CmmOpt.hs      Hopefully-redundant optimiser
252

simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
253
-------- Stuff to keep ------------
254
CmmCPS.hs                 Driver for new pipeline
255

256 257
CmmLive.hs                Liveness analysis, dead code elim
CmmProcPoint.hs           Identifying and splitting out proc-points
258

simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
259
CmmSpillReload.hs         Save and restore across calls
260

261
CmmCommonBlockElim.hs     Common block elim
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
262 263 264 265 266
CmmContFlowOpt.hs         Other optimisations (branch-chain, merging)

CmmBuildInfoTables.hs     New info-table 
CmmStackLayout.hs         and stack layout 
CmmCallConv.hs
267
CmmInfo.hs                Defn of InfoTables, and conversion to exact byte layout
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
268 269

---------- Cmm data types --------------
270 271 272 273 274 275 276
Cmm.hs              Cmm instantiations of dataflow graph framework
MkGraph.hs          Interface for building Cmm for codeGen/Stg*.hs modules

CmmDecl.hs          Shared Cmm types of both representations
CmmExpr.hs          Type of Cmm expression
CmmType.hs          Type of Cmm types and their widths
CmmMachOp.hs        MachOp type and accompanying utilities
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
277 278 279 280 281

CmmUtils.hs
CmmLint.hs

PprC.hs	            Pretty print Cmm in C syntax
282 283 284
PprCmm.hs	    Pretty printer for CmmGraph.
PprCmmDecl.hs       Pretty printer for common Cmm types.
PprCmmExpr.hs       Pretty printer for Cmm expressions.
285

286 287
CLabel.hs           CLabel
BlockId.hs          BlockId, BlockEnv, BlockSet
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302

----------------------------------------------------
      Top-level structure
----------------------------------------------------

* New codgen called in HscMain.hscGenHardCode, by calling HscMain.tryNewCodeGen, 
  enabled by -fnew-codegen (Opt_TryNewCodeGen)

  THEN it calls CmmInfo.cmmToRawCmm to lay out the details of info tables
      type Cmm    = GenCmm CmmStatic CmmInfo     (ListGraph CmmStmt)
      type RawCmm = GenCmm CmmStatic [CmmStatic] (ListGraph CmmStmt)

* HscMain.tryNewCodeGen
    - STG->Cmm:    StgCmm.codeGen (new codegen)
    - Optimise:    CmmContFlowOpt (simple optimisations, very self contained)
303
    - Cps convert: CmmCPS.protoCmmCPS 
304 305 306 307 308 309 310 311
    - Optimise:    CmmContFlowOpt again
    - Convert:     CmmCvt.cmmOfZgraph (convert to old rep) very self contained

* StgCmm.hs  The new STG -> Cmm conversion code generator
  Lots of modules StgCmmXXX


----------------------------------------------------
312
      CmmCPS.protoCmmCPS   The new pipeline
313 314
----------------------------------------------------

315
CmmCPS.protoCmmCPS:
316 317 318 319 320
   1. Do cpsTop for each procedures separately
   2. Build SRT representation; this spans multiple procedures
	(unless split-objs)

cpsTop:
321
  * CmmCommonBlockElim.elimCommonBlocks:
322 323
	eliminate common blocks 

324
  * CmmProcPoint.minimalProcPointSet
325
	identify proc-points
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
326
        no change to graph
327

328
  * CmmProcPoint.addProcPointProtocols
329 330 331 332 333 334 335 336
	something to do with the MA optimisation
        probably entirely unnecessary

  * Spill and reload:
     - CmmSpillReload.dualLivenessWithInsertion
       insert spills/reloads across 
	   LastCalls, and 
	   Branches to proc-points
Edward Z. Yang's avatar
Edward Z. Yang committed
337 338
     Now sink those reloads (and other instructions):
     - CmmSpillReload.rewriteAssignments
339 340 341 342 343 344 345 346 347 348 349
     - CmmSpillReload.removeDeadAssignmentsAndReloads

  * CmmStackLayout.stubSlotsOnDeath
	debug only: zero out dead slots when they die

  * Stack layout
     - CmmStackLayout.lifeSlotAnal: 
       find which sub-areas are live on entry to each block

     - CmmStackLayout.layout
       Lay out the stack, returning an AreaMap
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
350
         type AreaMap = FiniteMap Area ByteOff
351 352 353 354 355 356 357
          -- Byte offset of the oldest byte of the Area, 
          -- relative to the oldest byte of the Old Area

     - CmmStackLayout.manifestSP
       Manifest the stack pointer

   * Split into separate procedures
358
      - CmmProcPoint.procPointAnalysis
359
        Given set of proc points, which blocks are reachable from each
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
360
        Claim: too few proc-points => code duplication, but program still works??
361

362
      - CmmProcPoint.splitAtProcPoints
363 364
	Using this info, split into separate procedures

simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
      - CmmBuildInfoTables.setInfoTableStackMap
	Attach stack maps to each info table


----------------------------------------------------
	Proc-points
----------------------------------------------------

Consider this program, which has a diamond control flow, 
with a call on one branch
 fn(p,x) {
        h()
	if b then { ... f(x) ...; q=5; goto J }
             else { ...; q=7; goto J }
     J: ..p...q...
  }
then the join point J is a "proc-point".  So, is 'p' passed to J
as a parameter?  Or, if 'p' was saved on the stack anyway, perhaps
to keep it alive across the call to h(), maybe 'p' gets communicated
to J that way. This is an awkward choice.  (We think that we currently
never pass variables to join points via arguments.)

Furthermore, there is *no way* to pass q to J in a register (other
Edward Z. Yang's avatar
Edward Z. Yang committed
388
than a parameter register).
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
389 390 391 392 393 394 395 396 397 398 399 400 401 402

What we want is to do register allocation across the whole caboodle.
Then we could drop all the code that deals with the above awkward
decisions about spilling variables across proc-points.

Note that J doesn't need an info table.

What we really want is for each LastCall (not LastJump/Ret) 
to have an info table.   Note that ProcPoints that are not successors
of calls don't need an info table.

Figuring out proc-points
~~~~~~~~~~~~~~~~~~~~~~~~
Proc-points are identified by
403
CmmProcPoint.minimalProcPointSet/extendPPSet Although there isn't
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
404 405 406
that much code, JD thinks that it could be done much more nicely using
a dominator analysis, using the Dataflow Engine.

407 408 409 410 411 412 413 414 415
----------------------------------------------------
		CAFs
----------------------------------------------------

* The code for a procedure f may refer to either the *closure* 
  or the *entry point* of another top-level procedure g.  
  If f is live, then so is g.  f's SRT must include g's closure.

* The CLabel for the entry-point/closure reveals whether g is 
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
416
  a CAF (or refers to CAFs).  See the IdLabel constructor of CLabel.
417 418 419

* The CAF-ness of the original top-level defininions is figured out
  (by TidyPgm) before we generate C--.  This CafInfo is only set for
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
420
  top-level Ids; nested bindings stay with MayHaveCafRefs.
421 422 423 424 425 426 427 428 429 430 431 432

* Currently an SRT contains (only) pointers to (top-level) closures.

* Consider this Core code
	f = \x -> let g = \y -> ...x...y...h1...
                  in ...h2...g...
  and suppose that h1, h2 have IdInfo of MayHaveCafRefs.
  Therefore, so will f,  But g will not (since it's nested).

  This generates C-- roughly like this:
     f_closure: .word f_entry
     f_entry() [info-tbl-for-f] { ...jump g_entry...jump h2... }
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
433
     g_entry() [info-tbl-for-g] { ...jump h1... }
434 435

  Note that there is no top-level closure for g (only an info table).
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
436 437 438 439 440 441 442 443 444 445
  This fact (whether or not there is a top-level closure) is recorded
  in the InfoTable attached to the CmmProc for f, g
  INVARIANT: 
     Any out-of-Group references to an IdLabel goes to
     a Proc whose InfoTable says "I have a top-level closure".
  Equivalently: 
     A CmmProc whose InfoTable says "I do not have a top-level
     closure" is referred to only from its own Group.

* So:   info-tbl-for-f must have an SRT that keeps h1,h2 alive
446 447 448 449 450 451 452 453 454 455
        info-tbl-for-g must have an SRT that keeps h1 (only) alive

  But if we just look for the free CAF refs, we get:
	f   h2 (only)
        g   h1

  So we need to do a transitive closure thing to flesh out 
  f's keep-alive refs to include h1.

* The SRT info is the C_SRT field of Cmm.ClosureTypeInfo in a
456
  CmmInfoTable attached to each CmmProc.  CmmCPS.toTops actually does
457 458 459
  the attaching, right at the end of the pipeline.  The C_SRT part
  gives offsets within a single, shared table of closure pointers.

simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
460 461 462
* DECIDED: we can generate SRTs based on the final Cmm program
  without knowledge of how it is generated.

463 464 465 466
----------------------------------------------------
		Foreign calls
----------------------------------------------------

467
See Note [Foreign calls] in CmmNode!  This explains that a safe
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
foreign call must do this:
  save thread state
  push info table (on thread stack) to describe frame
  make call (via C stack)
  pop info table
  restore thread state
and explains why this expansion must be done late in the day.

Hence, 
  - Every foreign call is represented as a middle node

  - *Unsafe* foreign calls are simply "fat machine instructions"
      and are passed along to the native code generator

  - *Safe* foreign calls are "lowered" to unsafe calls by wrapping
      them in the above save/restore sequence. This step is done
      very late in the pipeline, just before handing to the native
      code gen.   
  
      This lowering is done by BuildInfoTables.lowerSafeForeignCalls


NEW PLAN for foreign calls:
  - Unsafe foreign calls remain as a middle node (fat machine instruction)
    Even the parameter passing is not lowered (just as machine instrs
    get arguments).

  - Initially, safe foreign calls appear as LastCalls with 
	

----------------------------------------------------
		Cmm representations
----------------------------------------------------

502
* CmmDecl.hs
503 504 505 506 507 508 509 510 511 512 513 514 515 516
     The type [GenCmm d h g] represents a whole module, 
	** one list element per .o file **
	Without SplitObjs, the list has exactly one element

     newtype GenCmm d h g = Cmm [GenCmmTop d h g]  -- A whole .o file
     data GenCmmTop d h g
         = CmmProc h g           -- One procedure, graph d
         | CmmData <stuff> [d]   -- Initialised data, items d

  Old and new piplines use different representations
  	(CmmCvt.hs converts between the two)


-------------
517
OLD BACK END representations (OldCmm.hs):  
518 519 520 521 522 523 524 525 526 527 528 529 530 531
      type Cmm = GenCmm CmmStatic CmmInfo (ListGraph CmmStmt)
				-- A whole module
      newtype ListGraph i = ListGraph [GenBasicBlock i]

      data CmmStmt = Assign | Store | Return etc -- OLD BACK END ONLY


   Once the info tables are laid out, we replace CmmInfo with [CmmStatic]
      type RawCmm    = GenCmm CmmStatic [CmmStatic] (ListGraph CmmStmt)
   which represents the info tables as data, that should 
   immediately precede the code
  
-------------
NEW BACK END representations 
532 533 534 535
* Uses Hoopl library, a zero-boot package
* CmmNode defines a node of a flow graph.
* Cmm defines CmmGraph, CmmTop, Cmm
   - CmmGraph is a closed/closed graph + an entry node.
536

537 538
       data CmmGraph = CmmGraph { g_entry :: BlockId
                                , g_graph :: Graph CmmNode C C }
539

540 541 542
   - CmmTop is a top level chunk, specialization of GenCmmTop from CmmDecl.hs
       with CmmGraph as a flow graph.
   - Cmm is a collection of CmmTops.
543

544 545
       type Cmm          = GenCmm    CmmStatic CmmTopInfo CmmGraph
       type CmmTop       = GenCmmTop CmmStatic CmmTopInfo CmmGraph
546

547
   - CmmTop uses CmmTopInfo, which is a CmmInfoTable and CmmStackInfo
548

549
       data CmmTopInfo   = TopInfo {info_tbl :: CmmInfoTable, stack_info :: CmmStackInfo}
550

551
   - CmmStackInfo
552

553
       data CmmStackInfo = StackInfo {arg_space :: ByteOff, updfr_space :: Maybe ByteOff}
554

555 556 557 558
         * arg_space = SP offset on entry
         * updfr_space space = SP offset on exit
       Once the staci is manifested, we could drom CmmStackInfo, ie. get
         GenCmm CmmStatic CmmInfoTable CmmGraph, but we do not do that currently.
559 560


561 562 563
* MkGraph.hs: smart constructors for Cmm.hs
  Beware, the CmmAGraph defined here does not use AGraph from Hoopl,
  as CmmAGraph can be opened or closed at exit, See the notes in that module.
564 565

-------------
566 567 568 569 570 571 572 573 574 575
* SHARED stuff
  CmmDecl.hs - GenCmm and GenCmmTop types
  CmmExpr.hs - defines the Cmm expression types
             - CmmExpr, CmmReg, CmmLit, LocalReg, GlobalReg
             - Area, AreaId etc     (separate module?)
  CmmType.hs - CmmType, Width etc   (saparate module?)
  CmmMachOp.hs - MachOp and CallishMachOp types

  BlockId.hs defines  BlockId, BlockEnv, BlockSet
-------------