Semantics of Cmm `switch` statement?

Andreas Klebinger klebinger.andreas at gmx.at
Wed Jan 12 02:10:06 UTC 2022


Hi Norman,

I vaguely remember that we "finish" such unterminated code blocks by
jumping to the block again.

That is for code like this:

     myswitch2 (bits32 n) {
       foreign "C" D();
     }

We produce code like this:

     {
       cg: call "ccall" arg hints:  []  result hints:  [] D();
           goto cg;
     }

Instead of blowing up the compiler at compile time or the program at
runtime.

For switch statements I think blocks are just syntactic sugar. E.g. if
you write

case n: { <code> }

it's treated as if you wrote

case n: jmp codeBlock;
...

codeBlock:
     <code>

And since your blocks don't terminate we get the behaviour you are seeing.
But I haven't looked at any of the code related to this so it's possible
I got it wrong.

Cheers
Andreas


Am 12/01/2022 um 01:02 schrieb Norman Ramsey:
> For testing purposes, I created the following Cmm program:
>
>      myswitch (bits32 n) {
>        switch [0 .. 4] n {
>          case 0, 1: { foreign "C" A(); }
>          case 2: { foreign "C" B(); }
>          case 4: { foreign "C" C(); }
>          default: { foreign "C" D(); }
>        }
>        return (666);
>      }
>
> In the original C-- specification, it's pretty clear that when, say,
> the call to foreign function `A` terminates, the switch statement is
> supposed to finish and function `myswitch` is supposed to return 666.
> What actually happens in GHC is that this source code is parsed into a
> control-flow graph in which execution loops forever, repeating the
> call.  The relevant fragment of the prettyprinted CFG looks like this:
>
>     {offset
>       ca: // global
>           _c1::I32 = %MO_XX_Conv_W64_W32(R1);
>           //tick src<programs/panic.cmm:(1,21)-(9,1)>
>           switch [0 .. 4] _c1::I32 {
>               case 0, 1 : goto c5;
>               case 2 : goto c7;
>               case 4 : goto c9;
>               default: {goto c3;}
>           }
>       ...
>       c5: // global
>           //tick src<programs/panic.cmm:3:16-35>
>           _c4::I64 = A;
>           call "ccall" arg hints:  []  result hints:  [] (_c4::I64)();
>           goto c5;
>       ...
>     }
>
> Surprising, at least to me.
>
> Is this behavior a bug or a feature?  And if it is a feature, can
> anyone explain it to me?
>
>
> Norman
> _______________________________________________
> ghc-devs mailing list
> ghc-devs at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs


More information about the ghc-devs mailing list