
Is the "cml_cont" field of the CmmCall variant is really used in practice?
Seconding what Michal has already said, yes, the `cml_cont` field is used quite a bit in Cmm. Any non-tail call in the program will have this field populated with information about where control-flow continues after the call returns. This field is used for some important steps, such as Proc Point analysis ( CmmProcPoint.callProcPoints ), the result of which is used to layout the stack. Stack layout uses the information about what values are live in the continuation block of a non-tail call to determine what values need to be saved to the stack. Thus, the control-flow graph structure of a CmmProc is defined in part by the `cml_cont` field (see the Cmm specific instance of Hoopl's NonLocal class in CmmNode, where it is used to indicate successors of a block).
I traversed the output of raw Cmm produced by ghc compiling the whole base package, but the value of cml_cont is always Nothing.
Hrm, were you looking for "returns to" in that output? ~kavon
On Mar 18, 2018, at 8:52 AM, Michal Terepeta
wrote: On Sun, Mar 18, 2018 at 6:38 AM Shao, Cheng
mailto:cheng.shao@tweag.io> wrote: Hi all, Is the "cml_cont" field of the CmmCall variant is really used in practice? I traversed the output of raw Cmm produced by ghc compiling the whole base package, but the value of cml_cont is always Nothing.
Regards, Shao Cheng
Hi,
I'm not a GHC expert, so please don't trust everything I say ;)
That being said, I think `cml_cont` is used a lot. If you look at the `compiler/codeGen` directory (that's what turns STG to cmm), you'll see that `MkGraph.mkCallReturnsTo` is called a few times. That's the function that will construct a `CmmCall` with the continuation block.
When dumping cmm, you'll often see all those `returns to` notes. For instance, compiling:
``` foo :: Int -> Int foo x = case x of 42 -> 111111 _ -> 000000 ```
results in:
``` [...] c2cN: // global I64[Sp - 8] = c2cI; R1 = R2; Sp = Sp - 8; if (R1 & 7 != 0) goto c2cI; else goto c2cJ;
// Evaluate the parameter. c2cJ: // global call (I64[R1])(R1) returns to c2cI, args: 8, res: 8, upd: 8; // ^^^^^^^^^^^^^^^ // this specifies the continuation block // see also PprCmm.pprNode
// Now check if it's 42. c2cI: // global if (I64[R1 + 7] == 42) goto c2cU; else goto c2cT; c2cU: // global [...] ```
As far as I understand it, this allows the code above to jump to the `x` closure (to evalutae it), and have the closure jump back to the continuation block (note that it's address is stored before we jump to closure). AFAICS this particular code is created by `StgCmmExpr.emitEnter`.
Hope this helps!
- Michal
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs