Merge branch 'newcg' of /home/simonmar/code-all/work/ghc-newcg into newcg
[ghc.git] / compiler / cmm / cmm-notes
1 More notes (Aug 11)\r
2 ~~~~~~~~~~~~~~~~~~\r
3 * CmmInfo.cmmToRawCmm expands info tables to their representations\r
4   (needed for .cmm files as well as the code generators)\r
5 \r
6 * Why is FCode a lazy monad?  That makes it inefficient.\r
7   We want laziness to get code out one procedure at a time,\r
8   but not at the instruction level.\r
9 \r
10 Things we did\r
11   * Remove CmmCvt.graphToZgraph (Conversion from old to new Cmm reps)\r
12   * Remove HscMain.optionallyConvertAndOrCPS (converted old Cmm to\r
13     new, ran pipeline, and converted back)\r
14   * Remove CmmDecl. Put its types in Cmm.  Import Cmm into OldCmm\r
15     so it can get those types.\r
16 \r
17 \r
18 More notes (June 11)\r
19 ~~~~~~~~~~~~~~~~~~~~\r
20 \r
21 * In CmmContFlowOpts.branchChainElim, can a single block be the\r
22   successor of two calls?\r
23 \r
24 * Check in ClosureInfo:\r
25      -- NB: Results here should line up with the results of SMRep.rtsClosureType\r
26 \r
27 * "Remove redundant reloads" in CmmSpillReload should be redundant; since\r
28   insertLateReloads is now gone, every reload is reloading a live variable.\r
29   Test and nuke.\r
30 \r
31 * When stubbing dead slots be careful not to write into an area that\r
32   overlaps with an area that's in use.  So stubbing needs to *follow* \r
33   stack layout.\r
34 \r
35 \r
36 More notes (May 11)\r
37 ~~~~~~~~~~~~~~~~~~~\r
38 In CmmNode, consider spliting CmmCall into two: call and jump\r
39 \r
40 Notes on new codegen (Aug 10)\r
41 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
42 \r
43 Things to do:\r
44  - We insert spills for variables before the stack check! This is the reason for\r
45    some fishy code in StgCmmHeap.entryHeapCheck where we are doing some strange\r
46         things to fix up the stack pointer before GC calls/jumps.\r
47 \r
48         The reason spills are inserted before the sp check is that at the entry to a\r
49         function we always store the parameters passed in registers to local variables.\r
50         The spill pass simply inserts spills at variable definitions. We instead should\r
51         sink the spills so that we can avoid spilling them on branches that never\r
52         reload them.\r
53 \r
54         This will fix the spill before stack check problem but only really as a side\r
55         effect. A 'real fix' probably requires making the spiller know about sp checks.\r
56 \r
57    EZY: I don't understand this comment. David Terei, can you clarify?\r
58 \r
59  - Proc points pass all arguments on the stack, adding more code and\r
60    slowing down things a lot. We either need to fix this or even better\r
61    would be to get rid of proc points.\r
62 \r
63  - CmmInfo.cmmToRawCmm uses Old.Cmm, so it is called after converting Cmm.Cmm to\r
64    Old.Cmm. We should abstract it to work on both representations, it needs only to\r
65    convert a CmmInfoTable to [CmmStatic].\r
66 \r
67  - Improve performance of Hoopl.\r
68 \r
69    A nofib comparison of -fasm vs -fnewcodegen nofib compilation parameters\r
70    (using the same ghc-cmm branch +libraries compiled by the old codegenerator)\r
71    is at http://fox.auryn.cz/msrc/0517_hoopl/32bit.oldghcoldgen.oldghchoopl.txt\r
72    - the code produced is 10.9% slower, the compilation is +118% slower!\r
73 \r
74    The same comparison with ghc-head with zip representation is at\r
75    http://fox.auryn.cz/msrc/0517_hoopl/32bit.oldghcoldgen.oldghczip.txt\r
76    - the code produced is 11.7% slower, the compilation is +78% slower.\r
77 \r
78    When compiling nofib, ghc-cmm + libraries compiled with -fnew-codegen\r
79    is 23.7% slower (http://fox.auryn.cz/msrc/0517_hoopl/32bit.oldghcoldgen.hooplghcoldgen.txt).\r
80    When compiling nofib, ghc-head + libraries compiled with -fnew-codegen\r
81    is 31.4% slower (http://fox.auryn.cz/msrc/0517_hoopl/32bit.oldghcoldgen.zipghcoldgen.txt).\r
82 \r
83    EZY: Also importantly, Hoopl uses dramatically more memory than the\r
84    old code generator.\r
85 \r
86  - Are all blockToNodeList and blockOfNodeList really needed? Maybe we could\r
87    splice blocks instead?\r
88 \r
89  - lowerSafeForeignCall seems too lowlevel. Just use Dataflow. After that\r
90    delete splitEntrySeq from HooplUtils.\r
91 \r
92  - manifestSP seems to touch a lot of the graph representation. It is\r
93    also slow for CmmSwitch nodes O(block_nodes * switch_statements).\r
94    Maybe rewrite manifestSP to use Dataflow?\r
95 \r
96  - Sort out Label, LabelMap, LabelSet versus BlockId, BlockEnv, BlockSet\r
97    dichotomy. Mostly this means global replace, but we also need to make\r
98    Label an instance of Outputable (probably in the Outputable module).\r
99 \r
100    EZY: We should use Label, since that's the terminology Hoopl uses.\r
101 \r
102  - NB that CmmProcPoint line 283 has a hack that works around a GADT-related\r
103    bug in 6.10.\r
104 \r
105  - AsmCodeGen has a generic Cmm optimiser; move this into new pipeline\r
106    EZY (2011-04-16): The mini-inliner has been generalized and ported,\r
107    but the constant folding and other optimizations need to still be\r
108    ported.\r
109 \r
110  - AsmCodeGen has post-native-cg branch eliminator (shortCutBranches);\r
111    we ultimately want to share this with the Cmm branch eliminator.\r
112 \r
113  - At the moment, references to global registers like Hp are "lowered" \r
114    late (in CgUtils.fixStgRegisters). We should do this early, in the\r
115         new native codegen, much in the way that we lower calling conventions.\r
116         Might need to be a bit sophisticated about aliasing.\r
117 \r
118  - Question: currently we lift procpoints to become separate\r
119    CmmProcs.  Do we still want to do this?\r
120     \r
121    NB: and advantage of continuing to do this is that\r
122    we can do common-proc elimination!\r
123 \r
124  - Move to new Cmm rep:\r
125      * Make native CG consume New Cmm; \r
126      * Convert Old Cmm->New Cmm to keep old path alive\r
127      * Produce New Cmm when reading in .cmm files\r
128 \r
129  - Consider module names\r
130 \r
131  - Top-level SRT threading is a bit ugly\r
132 \r
133  - See "CAFs" below; we want to totally refactor the way SRTs are calculated\r
134 \r
135  - Pull out Areas into its own module\r
136    Parameterise AreaMap (note there are type synonyms in CmmStackLayout!)\r
137    Add ByteWidth = Int\r
138    type SubArea    = (Area, ByteOff, ByteWidth) \r
139    ByteOff should not be defined in SMRep -- that is too high up the hierarchy\r
140    \r
141  - SMRep should not be imported by any module in cmm/!  Make it so.\r
142         -- ByteOff etc   ==>  CmmExpr\r
143         -- rET_SMALL etc ==> CmmInfo\r
144    Check that there are no other imports from codeGen in cmm/\r
145 \r
146  - If you eliminate a label by branch chain elimination,\r
147    what happens if there's an Area associated with that label?\r
148 \r
149  - Think about a non-flattened representation?\r
150 \r
151  - LastCall: \r
152     * Use record fields for LastCall!\r
153     * cml_ret_off should be a ByteOff\r
154     * Split into \r
155          LastCall (which has a successor) and\r
156          LastJump (which does not, includes return?)\r
157            - does not have cml_cont, cml_ret_args, cml_ret_off\r
158          LastForeignCall \r
159            - safe! \r
160            - expands into save/MidForeignCall/restore/goto\r
161            - like any LastCall, target of the call gets an info table\r
162 \r
163  - JD: remind self of what goes wrong if you turn off the \r
164    liveness of the update frame\r
165 \r
166  - Garbage-collect http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/CPS\r
167    moving good stuff into \r
168    http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/NewCodeGenPipeline\r
169 \r
170 \r
171  - We believe that all of CmmProcPoint.addProcPointProtocols is dead.  What\r
172    goes wrong if we simply never call it?\r
173 \r
174  - Something fishy in CmmStackLayout.hs\r
175    * In particular, 'getAreaSize' returns an AreaMap, but we *know* the width of\r
176         LocalRegs, so it'd be better to return FiniteMap AreaId ByteWidth\r
177    * setSuccSPs looks fishy.  Rather than lookin in procPoints, it could\r
178         just lookup the block in areaSize which, after all, has a binding\r
179         for precisely successors of calls.  All other blocks (including proc\r
180         points that are not successors of a call, we think) can be treated\r
181         uniformly: zero-size Area, and use inSP.\r
182 \r
183 \r
184  - Currently AsmCodeGen top level calls AsmCodeGen.cmmToCmm, which is a small\r
185    C-- optimiser.  It has quite a lot of boilerplate folding code in AsmCodeGen\r
186    (cmmBlockConFold, cmmStmtConFold, cmmExprConFold), before calling out to\r
187    CmmOpt.  ToDo: see what optimisations are being done; and do them before\r
188    AsmCodeGen.\r
189 \r
190  - Modularise the CPS pipeline; instead of ...; A;B;C; ...\r
191                                 use  ..; ABC; ....\r
192 \r
193  - Most of HscMain.tryNewCodeGen does not belong in HscMain.  Instead\r
194         if new_cg then\r
195              StgCmm.codeGen\r
196              processCmm  [including generating "raw" cmm]\r
197         else\r
198              CodeGen.codeGen\r
199              cmmToRawCmm\r
200 \r
201 \r
202  - If we stick CAF and stack liveness info on a LastCall node (not LastRet/Jump)\r
203    then all CAF and stack liveness stuff be completed before we split\r
204    into separate C procedures.\r
205 \r
206    Short term:\r
207      compute and attach liveness into to LastCall\r
208      right at end, split, cvt to old rep\r
209      [must split before cvt, because old rep is not expressive enough]\r
210 \r
211    Longer term: \r
212      when old rep disappears, \r
213      move the whole splitting game into the C back end *only*\r
214          (guided by the procpoint set)\r
215 \r
216 ----------------------------------------------------\r
217         Modules in codeGen/\r
218 ----------------------------------------------------\r
219 \r
220 \r
221 ------- Shared ---------\r
222 Bitmap.hs\r
223 SMRep.lhs\r
224 \r
225 CmmParse.y\r
226 CgExtCode.hs   used in CmmParse.y\r
227 \r
228 ------- New codegen ---------\r
229 \r
230 StgCmm.hs\r
231 StgCmmBind.hs\r
232 StgCmmClosure.hs     (corresponds to old ClosureInfo)\r
233 StgCmmCon.hs\r
234 StgCmmEnv.hs\r
235 StgCmmExpr.hs\r
236 StgCmmForeign.hs\r
237 StgCmmGran.hs\r
238 StgCmmHeap.hs\r
239 StgCmmHpc.hs\r
240 StgCmmLayout.hs\r
241 StgCmmMonad.hs\r
242 StgCmmPrim.hs\r
243 StgCmmProf.hs\r
244 StgCmmTicky.hs\r
245 StgCmmUtils.hs\r
246 \r
247 ------- Old codegen (moribund) ---------\r
248 CodeGen.lhs\r
249 CgBindery.lhs\r
250 CgCallConv.hs\r
251 CgCase.lhs\r
252 CgClosure.lhs\r
253 CgCon.lhs\r
254 CgExpr.lhs\r
255 CgLetNoEscape.lhs\r
256 CgForeignCall.hs\r
257 CgHeapery.lhs\r
258 CgHpc.hs\r
259 CgInfoTbls.hs\r
260 CgMonad.lhs\r
261 CgParallel.hs\r
262 CgPrimOp.hs\r
263 CgProf.hs\r
264 CgStackery.lhs\r
265 CgTailCall.lhs\r
266 CgTicky.hs\r
267 CgUtils.hs\r
268 ClosureInfo.lhs\r
269 \r
270 ----------------------------------------------------\r
271         Modules in cmm/\r
272 ----------------------------------------------------\r
273 \r
274 -------- Testing stuff ------------\r
275 DynFlags: -frun-cpsz\r
276 \r
277 -------- Moribund stuff ------------\r
278 OldCmm.hs      Definition of flowgraph of old representation\r
279                Imports some data types from (new) Cmm\r
280 OldCmmUtil.hs  Utilites that operates mostly on on CmmStmt\r
281 OldPprCmm.hs   Pretty print for CmmStmt, GenBasicBlock and ListGraph\r
282 CmmOpt.hs      Hopefully-redundant optimiser\r
283 \r
284 -------- Stuff to keep ------------\r
285 CmmPipeline.hs            Driver for new pipeline\r
286 \r
287 CmmLive.hs                Liveness analysis, dead code elim\r
288 CmmProcPoint.hs           Identifying and splitting out proc-points\r
289 \r
290 CmmSpillReload.hs         Save and restore across calls\r
291 \r
292 CmmCommonBlockElim.hs     Common block elim\r
293 CmmContFlowOpt.hs         Other optimisations (branch-chain, merging)\r
294 \r
295 CmmBuildInfoTables.hs     New info-table \r
296 CmmStackLayout.hs         and stack layout \r
297 CmmCallConv.hs\r
298 CmmInfo.hs                Defn of InfoTables, and conversion to exact byte layout\r
299 \r
300 ---------- Cmm data types --------------\r
301 Cmm.hs              Cmm instantiations of dataflow graph framework\r
302   CmmExpr.hs        Type of Cmm expression\r
303   CmmType.hs        Type of Cmm types and their widths\r
304   CmmMachOp.hs      MachOp type and accompanying utilities\r
305 \r
306 PprCmm.hs           Pretty printer for Cmm\r
307   PprCmmExpr.hs     Pretty printer for CmmExpr\r
308 \r
309 MkGraph.hs          Interface for building Cmm for codeGen/Stg*.hs modules\r
310 \r
311 CmmUtils.hs\r
312 CmmLint.hs\r
313 \r
314 PprC.hs             Pretty print Cmm in C syntax\r
315 \r
316 CLabel.hs           CLabel\r
317 BlockId.hs          BlockId, BlockEnv, BlockSet\r
318 \r
319 ----------------------------------------------------\r
320       Top-level structure\r
321 ----------------------------------------------------\r
322 \r
323 * New codgen called in HscMain.hscGenHardCode, by calling HscMain.tryNewCodeGen, \r
324   enabled by -fnew-codegen (Opt_TryNewCodeGen)\r
325 \r
326   THEN it calls CmmInfo.cmmToRawCmm to lay out the details of info tables\r
327       type Cmm    = GenCmm CmmStatic CmmInfo     (ListGraph CmmStmt)\r
328       type RawCmm = GenCmm CmmStatic [CmmStatic] (ListGraph CmmStmt)\r
329 \r
330 * HscMain.tryNewCodeGen\r
331     - STG->Cmm:         StgCmm.codeGen (new codegen)\r
332     - Optimize and CPS: CmmPipeline.cmmPipeline\r
333     - Convert:          CmmCvt.cmmOfZgraph (convert to old rep) very self contained\r
334 \r
335 * StgCmm.hs  The new STG -> Cmm conversion code generator\r
336   Lots of modules StgCmmXXX\r
337 \r
338 \r
339 ----------------------------------------------------\r
340       CmmPipeline.cmmPipeline   The new pipeline\r
341 ----------------------------------------------------\r
342 \r
343 CmmPipeline.cmmPipeline:\r
344    1. Do control flow optimization\r
345    2. Do cpsTop for each procedures separately\r
346    3. Build SRT representation; this spans multiple procedures\r
347         (unless split-objs)\r
348    4. Do control flow optimization on all resulting procedures\r
349 \r
350 cpsTop:\r
351   * CmmCommonBlockElim.elimCommonBlocks:\r
352         eliminate common blocks \r
353 \r
354   * CmmProcPoint.minimalProcPointSet\r
355         identify proc-points\r
356         no change to graph\r
357 \r
358   * CmmProcPoint.addProcPointProtocols\r
359         something to do with the MA optimisation\r
360         probably entirely unnecessary\r
361 \r
362   * Spill and reload:\r
363      - CmmSpillReload.dualLivenessWithInsertion\r
364        insert spills/reloads across \r
365            LastCalls, and \r
366            Branches to proc-points\r
367      Now sink those reloads (and other instructions):\r
368      - CmmSpillReload.rewriteAssignments\r
369      - CmmSpillReload.removeDeadAssignmentsAndReloads\r
370 \r
371   * CmmStackLayout.stubSlotsOnDeath\r
372         debug only: zero out dead slots when they die\r
373 \r
374   * Stack layout\r
375      - CmmStackLayout.lifeSlotAnal: \r
376        find which sub-areas are live on entry to each block\r
377 \r
378      - CmmStackLayout.layout\r
379        Lay out the stack, returning an AreaMap\r
380          type AreaMap = FiniteMap Area ByteOff\r
381           -- Byte offset of the oldest byte of the Area, \r
382           -- relative to the oldest byte of the Old Area\r
383 \r
384      - CmmStackLayout.manifestSP\r
385        Manifest the stack pointer\r
386 \r
387    * Split into separate procedures\r
388 \r
389       - CmmProcPoint.procPointAnalysis\r
390         Given set of proc points (computed earlier by\r
391            CmmProcPoint.minimalProcPointSet) find which blocks \r
392            are reachable from each\r
393         Each block should be reachable from *one* proc point, so \r
394           the blocks reachable from P are the internal nodes of \r
395           the final procedure P\r
396         NB: if we the earlier analysis had produced too few proc-points \r
397             we should nevertheless be fine by code duplication; but\r
398             that is not implemented\r
399 \r
400       - CmmProcPoint.splitAtProcPoints\r
401         Using this info, split into separate procedures\r
402 \r
403       - CmmBuildInfoTables.setInfoTableStackMap\r
404         Attach stack maps to each info table\r
405 \r
406 \r
407 ----------------------------------------------------\r
408         Proc-points\r
409 ----------------------------------------------------\r
410 \r
411 Consider this program, which has a diamond control flow, \r
412 with a call on one branch\r
413  fn(p,x) {\r
414         h()\r
415         if b then { ... f(x) ...; q=5; goto J }\r
416              else { ...; q=7; goto J }\r
417      J: ..p...q...\r
418   }\r
419 then the join point J is a "proc-point".  So, is 'p' passed to J\r
420 as a parameter?  Or, if 'p' was saved on the stack anyway, perhaps\r
421 to keep it alive across the call to h(), maybe 'p' gets communicated\r
422 to J that way. This is an awkward choice.  (We think that we currently\r
423 never pass variables to join points via arguments.)\r
424 \r
425 Furthermore, there is *no way* to pass q to J in a register (other\r
426 than a parameter register).\r
427 \r
428 What we want is to do register allocation across the whole caboodle.\r
429 Then we could drop all the code that deals with the above awkward\r
430 decisions about spilling variables across proc-points.\r
431 \r
432 Note that J doesn't need an info table.\r
433 \r
434 What we really want is for each LastCall (not LastJump/Ret) \r
435 to have an info table.   Note that ProcPoints that are not successors\r
436 of calls don't need an info table.\r
437 \r
438 Figuring out proc-points\r
439 ~~~~~~~~~~~~~~~~~~~~~~~~\r
440 Proc-points are identified by\r
441 CmmProcPoint.minimalProcPointSet/extendPPSet Although there isn't\r
442 that much code, JD thinks that it could be done much more nicely using\r
443 a dominator analysis, using the Dataflow Engine.\r
444 \r
445 ----------------------------------------------------\r
446                 CAFs\r
447 ----------------------------------------------------\r
448 \r
449 * The code for a procedure f may refer to either the *closure* \r
450   or the *entry point* of another top-level procedure g.  \r
451   If f is live, then so is g.  f's SRT must include g's closure.\r
452 \r
453 * The CLabel for the entry-point/closure reveals whether g is \r
454   a CAF (or refers to CAFs).  See the IdLabel constructor of CLabel.\r
455 \r
456 * The CAF-ness of the original top-level defininions is figured out\r
457   (by TidyPgm) before we generate C--.  This CafInfo is only set for\r
458   top-level Ids; nested bindings stay with MayHaveCafRefs.\r
459 \r
460 * Currently an SRT contains (only) pointers to (top-level) closures.\r
461 \r
462 * Consider this Core code\r
463         f = \x -> let g = \y -> ...x...y...h1...\r
464                   in ...h2...g...\r
465   and suppose that h1, h2 have IdInfo of MayHaveCafRefs.\r
466   Therefore, so will f,  But g will not (since it's nested).\r
467 \r
468   This generates C-- roughly like this:\r
469      f_closure: .word f_entry\r
470      f_entry() [info-tbl-for-f] { ...jump g_entry...jump h2... }\r
471      g_entry() [info-tbl-for-g] { ...jump h1... }\r
472 \r
473   Note that there is no top-level closure for g (only an info table).\r
474   This fact (whether or not there is a top-level closure) is recorded\r
475   in the InfoTable attached to the CmmProc for f, g\r
476   INVARIANT: \r
477      Any out-of-Group references to an IdLabel goes to\r
478      a Proc whose InfoTable says "I have a top-level closure".\r
479   Equivalently: \r
480      A CmmProc whose InfoTable says "I do not have a top-level\r
481      closure" is referred to only from its own Group.\r
482 \r
483 * So:   info-tbl-for-f must have an SRT that keeps h1,h2 alive\r
484         info-tbl-for-g must have an SRT that keeps h1 (only) alive\r
485 \r
486   But if we just look for the free CAF refs, we get:\r
487         f   h2 (only)\r
488         g   h1\r
489 \r
490   So we need to do a transitive closure thing to flesh out \r
491   f's keep-alive refs to include h1.\r
492 \r
493 * The SRT info is the C_SRT field of Cmm.ClosureTypeInfo in a\r
494   CmmInfoTable attached to each CmmProc.  CmmPipeline.toTops actually does\r
495   the attaching, right at the end of the pipeline.  The C_SRT part\r
496   gives offsets within a single, shared table of closure pointers.\r
497 \r
498 * DECIDED: we can generate SRTs based on the final Cmm program\r
499   without knowledge of how it is generated.\r
500 \r
501 ----------------------------------------------------\r
502                 Foreign calls\r
503 ----------------------------------------------------\r
504 \r
505 See Note [Foreign calls] in CmmNode!  This explains that a safe\r
506 foreign call must do this:\r
507   save thread state\r
508   push info table (on thread stack) to describe frame\r
509   make call (via C stack)\r
510   pop info table\r
511   restore thread state\r
512 and explains why this expansion must be done late in the day.\r
513 \r
514 Hence, \r
515   - Every foreign call is represented as a middle node\r
516 \r
517   - *Unsafe* foreign calls are simply "fat machine instructions"\r
518       and are passed along to the native code generator\r
519 \r
520   - *Safe* foreign calls are "lowered" to unsafe calls by wrapping\r
521       them in the above save/restore sequence. This step is done\r
522       very late in the pipeline, just before handing to the native\r
523       code gen.   \r
524   \r
525       This lowering is done by BuildInfoTables.lowerSafeForeignCalls\r
526 \r
527 \r
528 NEW PLAN for foreign calls:\r
529   - Unsafe foreign calls remain as a middle node (fat machine instruction)\r
530     Even the parameter passing is not lowered (just as machine instrs\r
531     get arguments).\r
532 \r
533   - Initially, safe foreign calls appear as LastCalls with \r
534         \r
535 \r
536 ----------------------------------------------------\r
537                 Cmm representations\r
538 ----------------------------------------------------\r
539 \r
540 * CmmDecl.hs\r
541      The type [GenCmm d h g] represents a whole module, \r
542         ** one list element per .o file **\r
543         Without SplitObjs, the list has exactly one element\r
544 \r
545      newtype GenCmm d h g = Cmm [GenCmmTop d h g]  -- A whole .o file\r
546      data GenCmmTop d h g\r
547          = CmmProc h g           -- One procedure, graph d\r
548          | CmmData <stuff> [d]   -- Initialised data, items d\r
549 \r
550   Old and new piplines use different representations\r
551         (CmmCvt.hs converts between the two)\r
552 \r
553 \r
554 -------------\r
555 OLD BACK END representations (OldCmm.hs):  \r
556       type Cmm = GenCmm CmmStatic CmmInfo (ListGraph CmmStmt)\r
557                                 -- A whole module\r
558       newtype ListGraph i = ListGraph [GenBasicBlock i]\r
559 \r
560       data CmmStmt = Assign | Store | Return etc -- OLD BACK END ONLY\r
561 \r
562 \r
563    Once the info tables are laid out, we replace CmmInfo with [CmmStatic]\r
564       type RawCmm    = GenCmm CmmStatic [CmmStatic] (ListGraph CmmStmt)\r
565    which represents the info tables as data, that should \r
566    immediately precede the code\r
567   \r
568 -------------\r
569 NEW BACK END representations \r
570 * Uses Hoopl library, a zero-boot package\r
571 * CmmNode defines a node of a flow graph.\r
572 * Cmm defines CmmGraph, CmmTop, Cmm\r
573    - CmmGraph is a closed/closed graph + an entry node.\r
574 \r
575        data CmmGraph = CmmGraph { g_entry :: BlockId\r
576                                 , g_graph :: Graph CmmNode C C }\r
577 \r
578    - CmmTop is a top level chunk, specialization of GenCmmTop from CmmDecl.hs\r
579        with CmmGraph as a flow graph.\r
580    - Cmm is a collection of CmmTops.\r
581 \r
582        type Cmm          = GenCmm    CmmStatic CmmTopInfo CmmGraph\r
583        type CmmTop       = GenCmmTop CmmStatic CmmTopInfo CmmGraph\r
584 \r
585    - CmmTop uses CmmTopInfo, which is a CmmInfoTable and CmmStackInfo\r
586 \r
587        data CmmTopInfo   = TopInfo {info_tbl :: CmmInfoTable, stack_info :: CmmStackInfo}\r
588 \r
589    - CmmStackInfo\r
590 \r
591        data CmmStackInfo = StackInfo {arg_space :: ByteOff, updfr_space :: Maybe ByteOff}\r
592 \r
593          * arg_space = SP offset on entry\r
594          * updfr_space space = SP offset on exit\r
595        Once the staci is manifested, we could drom CmmStackInfo, ie. get\r
596          GenCmm CmmStatic CmmInfoTable CmmGraph, but we do not do that currently.\r
597 \r
598 \r
599 * MkGraph.hs: smart constructors for Cmm.hs\r
600   Beware, the CmmAGraph defined here does not use AGraph from Hoopl,\r
601   as CmmAGraph can be opened or closed at exit, See the notes in that module.\r
602 \r
603 -------------\r
604 * SHARED stuff\r
605   CmmDecl.hs - GenCmm and GenCmmTop types\r
606   CmmExpr.hs - defines the Cmm expression types\r
607              - CmmExpr, CmmReg, CmmLit, LocalReg, GlobalReg\r
608              - Area, AreaId etc     (separate module?)\r
609   CmmType.hs - CmmType, Width etc   (saparate module?)\r
610   CmmMachOp.hs - MachOp and CallishMachOp types\r
611 \r
612   BlockId.hs defines  BlockId, BlockEnv, BlockSet\r
613 -------------\r